From 40b8f63a10b8106da5a7beb38124896a22c4d661 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 30 Mar 2012 14:59:18 +0200 Subject: NIOS2: Add MPU support functions --- cpukit/score/cpu/nios2/Makefile.am | 1 + cpukit/score/cpu/nios2/nios2-mpu-add-region.c | 106 +++++++++++++++++++++ cpukit/score/cpu/nios2/nios2-mpu-descriptor.c | 15 +-- cpukit/score/cpu/nios2/rtems/score/nios2-utility.h | 64 +++++++++++-- 4 files changed, 165 insertions(+), 21 deletions(-) create mode 100644 cpukit/score/cpu/nios2/nios2-mpu-add-region.c (limited to 'cpukit') diff --git a/cpukit/score/cpu/nios2/Makefile.am b/cpukit/score/cpu/nios2/Makefile.am index 11bf3bdcb0..606a512400 100644 --- a/cpukit/score/cpu/nios2/Makefile.am +++ b/cpukit/score/cpu/nios2/Makefile.am @@ -37,6 +37,7 @@ libscorecpu_a_SOURCES += nios2-isr-install-raw-handler.c libscorecpu_a_SOURCES += nios2-isr-install-vector.c libscorecpu_a_SOURCES += nios2-isr-is-in-progress.c libscorecpu_a_SOURCES += nios2-isr-set-level.c +libscorecpu_a_SOURCES += nios2-mpu-add-region.c libscorecpu_a_SOURCES += nios2-mpu-configuration.c libscorecpu_a_SOURCES += nios2-mpu-descriptor.c libscorecpu_a_SOURCES += nios2-mpu-disable-protected.c diff --git a/cpukit/score/cpu/nios2/nios2-mpu-add-region.c b/cpukit/score/cpu/nios2/nios2-mpu-add-region.c new file mode 100644 index 0000000000..d23769c48b --- /dev/null +++ b/cpukit/score/cpu/nios2/nios2-mpu-add-region.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include + +static bool _Nios2_MPU_Is_region_disabled( + const Nios2_MPU_Configuration *config, + uint32_t mpubase, + uint32_t mpuacc +) +{ + bool disabled = false; + + if ( config->region_uses_limit ) { + disabled = (mpubase & NIOS2_MPUBASE_BASE_MASK) + > (mpuacc & NIOS2_MPUACC_LIMIT_MASK); + } else { + disabled = (mpuacc & NIOS2_MPUACC_MASK_MASK) == 0; + } + + return disabled; +} + +int _Nios2_MPU_Get_disabled_region_index( + const Nios2_MPU_Configuration *config, + bool data, + int begin, + int end +) +{ + int index = -1; + int count = _Nios2_MPU_Get_region_count( config, data ); + + if ( end < 0 || count < end ) { + end = count; + } + + if ( begin >= 0 ) { + int i = 0; + + for ( i = begin; i < end && index < 0; ++i ) { + uint32_t mpubase = 0; + uint32_t mpuacc = 0; + + _Nios2_MPU_Get_region_registers( i, data, &mpubase, &mpuacc ); + + if ( _Nios2_MPU_Is_region_disabled( config, mpubase, mpuacc ) ) { + index = i; + } + } + } + + return index; +} + +bool _Nios2_MPU_Add_region( + const Nios2_MPU_Configuration *config, + const Nios2_MPU_Region_descriptor *desc, + bool force +) +{ + bool ok = true; + int index = desc->index; + bool data = desc->data; + uint32_t mpubase = 0; + uint32_t mpuacc = 0; + + if ( _Nios2_MPU_Is_valid_index( config, data, index ) ) { + if ( !force ) { + _Nios2_MPU_Get_region_registers( index, data, &mpubase, &mpuacc ); + ok = _Nios2_MPU_Is_region_disabled( config, mpubase, mpuacc ); + } + + if ( ok ) { + ok = _Nios2_MPU_Setup_region_registers( + config, + desc, + &mpubase, + &mpuacc + ); + if ( ok ) { + _Nios2_Set_ctlreg_mpubase(mpubase); + _Nios2_Set_ctlreg_mpuacc(mpuacc); + } + } + } else { + ok = false; + } + + return ok; +} diff --git a/cpukit/score/cpu/nios2/nios2-mpu-descriptor.c b/cpukit/score/cpu/nios2/nios2-mpu-descriptor.c index 2b3cc41564..1aee1c40ea 100644 --- a/cpukit/score/cpu/nios2/nios2-mpu-descriptor.c +++ b/cpukit/score/cpu/nios2/nios2-mpu-descriptor.c @@ -60,19 +60,6 @@ static bool _Nios2_Is_valid_base_and_end( return ok; } -static bool _Nios2_Is_valid_index( - const Nios2_MPU_Configuration *config, - bool data, - int index -) -{ - int count = data ? - config->data_region_count - : config->instruction_region_count; - - return 0 <= index && index < count; -} - static bool _Nios2_Is_valid_permission( bool data, int perm @@ -101,7 +88,7 @@ bool _Nios2_MPU_Setup_region_registers( &mask_or_limit ); bool ok = is_valid_base_and_end - && _Nios2_Is_valid_index( config, desc->data, desc->index ) + && _Nios2_MPU_Is_valid_index( config, desc->data, desc->index ) && _Nios2_Is_valid_permission( desc->data, desc->perm ) && !(!desc->data && desc->cacheable) && !(desc->read && desc->write); diff --git a/cpukit/score/cpu/nios2/rtems/score/nios2-utility.h b/cpukit/score/cpu/nios2/rtems/score/nios2-utility.h index 83909c3305..7327e8c7e8 100644 --- a/cpukit/score/cpu/nios2/rtems/score/nios2-utility.h +++ b/cpukit/score/cpu/nios2/rtems/score/nios2-utility.h @@ -169,13 +169,10 @@ extern char _Nios2_ISR_Status_mask []; */ extern char _Nios2_ISR_Status_bits []; -/** - * @brief This global variable indicates that the Nios2 MPU is active - * - * This global variable is set to 1 when the board support package - * initializes the MPU during startup. - */ -extern uint32_t _Nios2_Mpu_active; +static inline void _Nios2_Flush_pipeline( void ) +{ + __asm__ volatile ("flushp"); +} static inline uint32_t _Nios2_Get_ctlreg_status( void ) { @@ -377,6 +374,26 @@ typedef struct { true, false, false, true \ } +static inline int _Nios2_MPU_Get_region_count( + const Nios2_MPU_Configuration *config, + bool data +) +{ + return data ? + config->data_region_count + : config->instruction_region_count; +} + +static inline bool _Nios2_MPU_Is_valid_index( + const Nios2_MPU_Configuration *config, + bool data, + int index +) +{ + return 0 <= index + && index < _Nios2_MPU_Get_region_count( config, data ); +} + bool _Nios2_MPU_Setup_region_registers( const Nios2_MPU_Configuration *config, const Nios2_MPU_Region_descriptor *desc, @@ -384,6 +401,38 @@ bool _Nios2_MPU_Setup_region_registers( uint32_t *mpuacc ); +/** + * @brief Seaches the region table part for a disabled region. + * + * The table will be searched between indices @a begin and @a end. The @a end + * index is not part of the search range. If @a end is negative, then the + * region count will be used. Thus a @a begin of 0 and a @a end of -1 will + * specifiy the complete table. + * + * @retval -1 No disabled region is available. + * @retval other Index of disabled region. + */ +int _Nios2_MPU_Get_disabled_region_index( + const Nios2_MPU_Configuration *config, + bool data, + int begin, + int end +); + +/** + * @brief Adds a region according to region descriptor @a desc. + * + * If @a force is true, then an enabled region will be overwritten. + * + * @retval true Successful operation. + * @retval false Invalid region descriptor or region already in use. + */ +bool _Nios2_MPU_Add_region( + const Nios2_MPU_Configuration *config, + const Nios2_MPU_Region_descriptor *desc, + bool force +); + static inline void _Nios2_MPU_Get_region_registers( int index, bool data, @@ -397,6 +446,7 @@ static inline void _Nios2_MPU_Get_region_registers( _Nios2_Set_ctlreg_mpubase( base ); _Nios2_Set_ctlreg_mpuacc( NIOS2_MPUACC_RD ); + _Nios2_Flush_pipeline(); *mpubase = _Nios2_Get_ctlreg_mpubase() | base; *mpuacc = _Nios2_Get_ctlreg_mpuacc(); } -- cgit v1.2.3