NIOS2: Add MPU support functions

This commit is contained in:
Sebastian Huber
2012-03-30 15:03:26 +02:00
parent 64d2c8adf9
commit 40b8f63a10
4 changed files with 165 additions and 21 deletions
+1
View File
@@ -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
@@ -0,0 +1,106 @@
/*
* Copyright (c) 2011 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Obere Lagerstr. 30
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
*
* 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 <rtems/score/nios2-utility.h>
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;
}
+1 -14
View File
@@ -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);
@@ -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();
}