refactor mpu.h some more and rename RT_MPU_ENABLE to RT_MPU_TASK_REGIONS_ENABLE
This commit is contained in:
parent
e823dc524b
commit
3cbea40dbd
|
@ -88,15 +88,17 @@ Extensions_.
|
|||
## Memory Protection
|
||||
|
||||
The memory protection unit available in many Cortex-M and Cortex-R devices is
|
||||
supported and can be enabled by compiling with `-DRT_MPU_ENABLE=1`. By default,
|
||||
`rt` assumes the MPU has 8 regions, but this can be overridden with
|
||||
`-DRT_MPU_NUM_REGIONS=<number>` for processors with more. By default, `rt`
|
||||
reserves the 4 highest-priority regions to be reconfigured for every task, with
|
||||
one of those regions reserved for the task's stack that is automatically
|
||||
initialized along with the task itself. To change the number of per-task MPU
|
||||
regions, use `-DRT_MPU_NUM_TASK_REGIONS=<number>`. The remaining lower-priority
|
||||
regions can be configured at startup time and will not be modified by `rt`. The
|
||||
MPU is never disabled at run-time, even during context switches and interrupts.
|
||||
The background MPU region is enabled, so privileged tasks and exceptions will
|
||||
have access to memory with the default permissions and attributes unless there
|
||||
is a region specifically configured for a given address.
|
||||
supported and can be used with the interface provided in
|
||||
[`<rt/arch/mpu.h>`](include/rt/arch/mpu.h). By default, `rt` assumes the MPU
|
||||
has 8 regions, but this can be overridden with `-DRT_MPU_NUM_REGIONS=<number>`
|
||||
for processors with more. To enable per-task MPU regions, compile with
|
||||
`-DRT_MPU_TASK_REGIONS_ENABLE=1`. By default, `rt` reserves the 4
|
||||
highest-priority regions to be reconfigured for every task, with one of those
|
||||
regions reserved for the task's stack that is automatically initialized along
|
||||
with the task itself. To change the number of per-task MPU regions, use
|
||||
`-DRT_MPU_NUM_TASK_REGIONS=<number>`. The remaining lower-priority regions can
|
||||
be configured at startup time and will not be modified by `rt`. The MPU is
|
||||
never disabled at run-time, even during context switches and interrupts. The
|
||||
background MPU region is enabled, so privileged tasks and exceptions will have
|
||||
access to memory with the default permissions and attributes unless there is a
|
||||
region specifically configured for a given address.
|
||||
|
|
|
@ -43,9 +43,10 @@
|
|||
#endif // RT_ARM_FP
|
||||
|
||||
.macro mpuconfigure
|
||||
#if RT_MPU_ENABLE
|
||||
ldr r1, =rt_mpu_config
|
||||
#if RT_MPU_TASK_REGIONS_ENABLE
|
||||
ldr r1, =rt_active_task
|
||||
ldr r1, [r1]
|
||||
adds r1, RT_MPU_TASK_CONFIG_OFFSET
|
||||
movs r2, RT_MPU_TASK_REGION_START_ID
|
||||
adds r5, r2, RT_MPU_NUM_TASK_REGIONS
|
||||
|
||||
|
|
|
@ -59,6 +59,12 @@ __attribute__((noreturn, weak)) void rt_trap(void)
|
|||
}
|
||||
}
|
||||
|
||||
#if RT_MPU_TASK_REGIONS_ENABLE
|
||||
rt_static_assert(offsetof(struct rt_task, mpu_config) ==
|
||||
RT_MPU_TASK_CONFIG_OFFSET,
|
||||
"RT_MPU_TASK_CONFIG_OFFSET is incorrect");
|
||||
#endif // RT_MPU_TASK_REGIONS_ENABLE
|
||||
|
||||
#if RT_ARM_V6M
|
||||
#include "m/atomic-v6.c"
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,10 @@ extern "C" {
|
|||
#define RT_MPU_TASK_REGION_START_ID \
|
||||
(RT_MPU_NUM_REGIONS - RT_MPU_NUM_TASK_REGIONS)
|
||||
|
||||
/* This value is derived from the layout of struct rt_task and checked in
|
||||
* arm.c. It's provided here so it can be used in assembly. */
|
||||
#define RT_MPU_TASK_CONFIG_OFFSET 32
|
||||
|
||||
#if !defined(__ASSEMBLER__)
|
||||
|
||||
#include <stddef.h>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if RT_MPU_ENABLE
|
||||
#if RT_MPU_TASK_REGIONS_ENABLE
|
||||
|
||||
#define RT_STACK_ALIGN(n) RT_MPU_ALIGN(n)
|
||||
|
||||
|
@ -16,7 +16,7 @@ extern "C" {
|
|||
#define RT_STACK_SIZE(n) RT_MPU_SIZE(n)
|
||||
#endif
|
||||
|
||||
#endif // RT_MPU_ENABLE
|
||||
#endif // RT_MPU_TASK_REGIONS_ENABLE
|
||||
|
||||
// The Arm ABI specifies a minimum stack alignment of 8 bytes.
|
||||
#ifndef RT_STACK_ALIGN
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
|
||||
struct context
|
||||
{
|
||||
#if !RT_ARM_V6M && RT_MPU_ENABLE
|
||||
/* Only track per-task privilege if the MPU is enabled and the architecture
|
||||
* version is 7 or greater. Dropping privilege prevents masking interrupts,
|
||||
* which is required for atomic operations on v6-m. */
|
||||
#if !RT_ARM_V6M && RT_MPU_TASK_REGIONS_ENABLE
|
||||
/* Only track per-task privilege if per-task MPU regions are enabled and
|
||||
* the architecture version is 7 or greater. Dropping privilege prevents
|
||||
* masking interrupts, which is required for atomic operations on v6-m. */
|
||||
uint32_t control;
|
||||
#endif // (__ARM_ARCH >= 7) && RT_MPU_ENABLE
|
||||
#endif // (__ARM_ARCH >= 7) && RT_MPU_TASK_REGIONS_ENABLE
|
||||
|
||||
#if RT_ARM_V8M
|
||||
uint32_t psplim;
|
||||
|
@ -52,12 +52,12 @@ static struct context *context_init(void *stack, size_t stack_size,
|
|||
struct context *ctx = sp;
|
||||
--ctx;
|
||||
|
||||
#if !RT_ARM_V6M && RT_MPU_ENABLE
|
||||
#if !RT_ARM_V6M && RT_MPU_TASK_REGIONS_ENABLE
|
||||
/* Tasks start privileged. The SPSEL bit is RAZ/WI in handler mode where
|
||||
* context switches occur. The exception return value specifies which stack
|
||||
* pointer is used when returning to thread mode. */
|
||||
ctx->control = 0;
|
||||
#endif // !RT_ARM_V6M && RT_MPU_ENABLE
|
||||
#endif // !RT_ARM_V6M && RT_MPU_TASK_REGIONS_ENABLE
|
||||
|
||||
#if RT_ARM_V8M
|
||||
ctx->psplim = (uint32_t)stack;
|
||||
|
@ -74,14 +74,14 @@ static struct context *context_init(void *stack, size_t stack_size,
|
|||
|
||||
void rt_task_drop_privilege(void)
|
||||
{
|
||||
#if !RT_ARM_V6M && RT_MPU_ENABLE
|
||||
#if !RT_ARM_V6M && RT_MPU_TASK_REGIONS_ENABLE
|
||||
uint32_t control;
|
||||
__asm__ __volatile__("mrs %0, control" : "=r"(control));
|
||||
__asm__("dsb; msr control, %0; isb"
|
||||
:
|
||||
: "r"(control | CONTROL_NPRIV)
|
||||
: "memory");
|
||||
#endif // !RT_ARM_V6M && RT_MPU_ENABLE
|
||||
#endif // !RT_ARM_V6M && RT_MPU_TASK_REGIONS_ENABLE
|
||||
}
|
||||
|
||||
void rt_cycle_init(void)
|
||||
|
|
|
@ -12,10 +12,11 @@
|
|||
|
||||
.syntax unified
|
||||
|
||||
#if RT_MPU_ENABLE
|
||||
#if RT_MPU_TASK_REGIONS_ENABLE
|
||||
.macro mpuconfigure
|
||||
ldr r1, =rt_mpu_config
|
||||
ldr r1, =rt_active_task
|
||||
ldr r1, [r1]
|
||||
adds r1, RT_MPU_TASK_CONFIG_OFFSET
|
||||
ldr r2, =0xE000ED98
|
||||
mpuset RT_MPU_TASK_REGION_START_ID, RT_MPU_NUM_TASK_REGIONS
|
||||
dsb
|
||||
|
@ -36,22 +37,22 @@
|
|||
str r5, [r2, 8]
|
||||
mpuset (\r + 1), (\n - 1)
|
||||
.endm
|
||||
#else // !RT_MPU_ENABLE
|
||||
#else // !RT_MPU_TASK_REGIONS_ENABLE
|
||||
.macro mpuconfigure
|
||||
.endm
|
||||
#endif // RT_MPU_ENABLE
|
||||
#endif // RT_MPU_TASK_REGIONS_ENABLE
|
||||
|
||||
#if (__ARM_ARCH >= 7) && RT_MPU_ENABLE
|
||||
#if (__ARM_ARCH >= 7) && RT_MPU_TASK_REGIONS_ENABLE
|
||||
#define CONTROL_SIZE 4
|
||||
#define controltemp r2,
|
||||
#define getcontrol mrs r2, control
|
||||
#define setcontrol msr control, r2
|
||||
#else // __ARM_ARCH <= 6 || !RT_MPU_ENABLE
|
||||
#else // __ARM_ARCH <= 6 || !RT_MPU_TASK_REGIONS_ENABLE
|
||||
#define CONTROL_SIZE 0
|
||||
#define controltemp
|
||||
#define getcontrol
|
||||
#define setcontrol
|
||||
#endif // (__ARM_ARCH >= 7) && RT_MPU_ENABLE
|
||||
#endif // (__ARM_ARCH >= 7) && RT_MPU_TASK_REGIONS_ENABLE
|
||||
|
||||
#if __ARM_ARCH == 8
|
||||
#define PSPLIM_SIZE 4
|
||||
|
|
|
@ -31,14 +31,15 @@
|
|||
#define return mov r0, TASK_INITIAL_EXC_RETURN; bx r0
|
||||
#endif // RT_ARM_FP
|
||||
|
||||
#if RT_MPU_ENABLE
|
||||
#if RT_MPU_TASK_REGIONS_ENABLE
|
||||
#define controltemp r2,
|
||||
#define getcontrol mrs r2, control
|
||||
#define setcontrol msr control, r2
|
||||
|
||||
.macro mpuconfigure
|
||||
ldr r1, =rt_mpu_config
|
||||
ldr r1, =rt_active_task
|
||||
ldr r1, [r1]
|
||||
adds r1, RT_MPU_TASK_CONFIG_OFFSET
|
||||
ldr r2, =0xE000ED9C
|
||||
mpuset RT_MPU_TASK_REGION_START_ID, RT_MPU_NUM_TASK_REGIONS
|
||||
dsb
|
||||
|
@ -89,12 +90,12 @@
|
|||
.endif
|
||||
.endm
|
||||
|
||||
#else // !RT_MPU_ENABLE
|
||||
#else // !RT_MPU_TASK_REGIONS_ENABLE
|
||||
#define controltemp
|
||||
#define getcontrol
|
||||
#define setcontrol
|
||||
#define mpuconfigure
|
||||
#endif // RT_MPU_ENABLE
|
||||
#endif // RT_MPU_TASK_REGIONS_ENABLE
|
||||
|
||||
#if __ARM_ARCH == 8
|
||||
#define psplimtemp r3,
|
||||
|
|
|
@ -4,17 +4,17 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef RT_MPU_ENABLE
|
||||
#define RT_MPU_ENABLE 0
|
||||
#ifndef RT_MPU_TASK_REGIONS_ENABLE
|
||||
#define RT_MPU_TASK_REGIONS_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if RT_MPU_ENABLE
|
||||
#if RT_MPU_TASK_REGIONS_ENABLE
|
||||
#include <rt/arch/mpu.h>
|
||||
#endif
|
||||
|
||||
// This can be defined by rt/arch/mpu.h.
|
||||
#ifndef RT_MPU_PRIV_SECTIONS_ENABLE
|
||||
#define RT_MPU_PRIV_SECTIONS_ENABLE RT_MPU_ENABLE
|
||||
#define RT_MPU_PRIV_SECTIONS_ENABLE RT_MPU_TASK_REGIONS_ENABLE
|
||||
#endif
|
||||
|
||||
#if RT_MPU_PRIV_SECTIONS_ENABLE
|
||||
|
|
|
@ -10,16 +10,14 @@
|
|||
#include <limits.h>
|
||||
|
||||
#ifndef RT_TASK_READY_CTZ_ENABLE
|
||||
|
||||
#if ((defined(__arm__) || defined(__aarch64__)) && \
|
||||
defined(__ARM_FEATURE_CLZ)) || \
|
||||
defined(__x86_64__)
|
||||
#define RT_TASK_READY_CTZ_ENABLE 1
|
||||
#else
|
||||
#else // architecture detection
|
||||
#define RT_TASK_READY_CTZ_ENABLE 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif // !defined(RT_TASK_READY_CTZ_ENABLE)
|
||||
|
||||
#define RT_TASK_PRIORITY_MIN UINT32_C(0)
|
||||
#define RT_TASK_PRIORITY_MAX UINT32_C(31)
|
||||
|
@ -80,11 +78,11 @@ struct rt_task
|
|||
void *ctx;
|
||||
uint32_t priority;
|
||||
uint32_t base_priority;
|
||||
enum rt_task_state state;
|
||||
unsigned long wake_tick;
|
||||
#if RT_MPU_ENABLE
|
||||
#if RT_MPU_TASK_REGIONS_ENABLE
|
||||
struct rt_mpu_config mpu_config;
|
||||
#endif
|
||||
enum rt_task_state state;
|
||||
union
|
||||
{
|
||||
struct rt_sem *sem;
|
||||
|
@ -130,15 +128,15 @@ void rt_task_ready(struct rt_task *task);
|
|||
RT_TASK_COMMON_(fn, stack_size, priority, name, ctx_init, __COUNTER__, \
|
||||
__VA_ARGS__)
|
||||
|
||||
#if RT_MPU_ENABLE
|
||||
#if RT_MPU_TASK_REGIONS_ENABLE
|
||||
#define RT_TASK_MPU_CONFIG_INIT(fn, ...) \
|
||||
RT_MPU_CONFIG_INIT(&fn##_task.mpu_config, \
|
||||
RT_MPU_REGION(fn##_task_stack, sizeof fn##_task_stack, \
|
||||
RT_MPU_ATTR_STACK), \
|
||||
__VA_ARGS__);
|
||||
#else
|
||||
#else // !RT_MPU_TASK_REGIONS_ENABLE
|
||||
#define RT_TASK_MPU_CONFIG_INIT(fn, ...)
|
||||
#endif
|
||||
#endif // RT_MPU_TASK_REGIONS_ENABLE
|
||||
|
||||
#define RT_TASK_COMMON_(fn, stack_size, priority, name, ctx_init, counter, \
|
||||
...) \
|
||||
|
@ -172,6 +170,8 @@ void rt_task_ready(struct rt_task *task);
|
|||
sizeof fn##_task_stack), \
|
||||
__VA_ARGS__)
|
||||
|
||||
extern struct rt_task *rt_active_task;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
15
src/rt.c
15
src/rt.c
|
@ -83,7 +83,7 @@ RT_TASK(rt_idle, RT_STACK_MIN, RT_TASK_PRIORITY_IDLE);
|
|||
|
||||
/* rt_active_task must be readable from user code.
|
||||
* Task structures themselves are privileged. */
|
||||
static struct rt_task *rt_active_task = NULL;
|
||||
struct rt_task *rt_active_task = NULL;
|
||||
|
||||
void rt_task_yield(void)
|
||||
{
|
||||
|
@ -148,16 +148,12 @@ static void task_wait(struct rt_task *task, struct rt_list *list)
|
|||
|
||||
RT_MPU_PRIV_BSS(rt_context_prev)
|
||||
void **rt_context_prev;
|
||||
#if RT_MPU_ENABLE
|
||||
RT_MPU_PRIV_BSS(rt_mpu_config)
|
||||
struct rt_mpu_config *rt_mpu_config;
|
||||
#endif
|
||||
|
||||
void *rt_start_context(void)
|
||||
{
|
||||
#if RT_CYCLE_ENABLE
|
||||
rt_cycle_init();
|
||||
#endif
|
||||
#endif // !RT_CYCLE_ENABLE
|
||||
rt_task_cycle_resume();
|
||||
|
||||
// Initially all tasks are ready, including the idle task.
|
||||
|
@ -166,10 +162,6 @@ void *rt_start_context(void)
|
|||
first_task->state = RT_TASK_STATE_RUNNING;
|
||||
rt_active_task = first_task;
|
||||
|
||||
#if RT_MPU_ENABLE
|
||||
rt_mpu_config = &first_task->mpu_config;
|
||||
#endif
|
||||
|
||||
rt_logf("rt_start_context: %s with priority %u\n", first_task->name,
|
||||
first_task->priority);
|
||||
|
||||
|
@ -189,9 +181,6 @@ static void *sched(void)
|
|||
|
||||
rt_context_prev = &rt_active_task->ctx;
|
||||
rt_active_task = next_task;
|
||||
#if RT_MPU_ENABLE
|
||||
rt_mpu_config = &next_task->mpu_config;
|
||||
#endif
|
||||
|
||||
rt_logf("sched: switching to %s with priority %u\n", rt_task_name(),
|
||||
next_task->priority);
|
||||
|
|
Loading…
Reference in New Issue