FreeRTOS MPU: privileged access to bss?

I am using FreeRTOS 10.5.1 with MPU support on a Cortex M4 microcontroller (STM32F4).

I created some tasks (all privileged → portPRIVILEGE_BIT set) and my system is running fine.

Now I tested again with one task not having the portPRIVILEGE_BIT set (= User Mode). When entering the task right up in the first function (HAL_TIM_Base_Start()) I am getting a memory management exception. The mem manage address register shows an address in the bss (where the timer is located).

Why does the MPU trigger when accessing the bss? (I checked the privileged_data_end ends before) How does a User Mode task behave when accessing an area (like bss) that is not explicitly configured as e.g. portMPU_REGION_READ_WRITE in xRegions[]?

Access to bss with portPRIVILEGE_BIT set → no problem. Access to bss with portPRIVILEGE_BIT reset → mem management fault.

configured addresses:
0x20000000 privileged_data_start
0x20006000 privileged_data_end

0x2000AF65 Mem manage address register ← fault location

Edit: I did another test and created a MPU region definition for 0x2000A000 to 0x2000F000 to be portMPU_REGION_READ_WRITE. Now the program is running fine for function no.1 in my task, but it’s failing in function no.2 → fault location is now 0x20006498.

Is it really neccessary for an User mode task to explicitly define all areas that it is allowed to access? Is leaving a memory area undefined not sufficient?

Yes, it is necessary to grant an unprivileged task all the accesses explicitly. By default, an unprivileged task has only access to its stack. The application writer is expected to grant access to required memory regions explicitly.

1 Like

Hey, thanks again for precise reply.

Unfortunately I am still facing the issue to run into the Mem manage handler.

What I did:
I set up the Task parameters structure:

#define EXECUTION_TASK_STACK_SIZE_WORDS   512
#define EXECUTION_TASK_STACK_ALIGNMENT    ( EXECUTION_TASK_STACK_SIZE_WORDS * sizeof( portSTACK_TYPE ) )

static portSTACK_TYPE xInitTaskStack[ EXECUTION_TASK_STACK_SIZE_WORDS ] mainALIGN_TO( EXECUTION_TASK_STACK_ALIGNMENT );
static StaticTask_t   xInitTaskTcb;

/* Fill in a TaskParameters_t structure per test task to define the tasks. */
static const TaskParameters_t xInitTaskParameters =
{
  StartInitTask,
  "InitTask",
  EXECUTION_TASK_STACK_SIZE_WORDS,
  ( void * ) NULL,
  (PRIO_INIT_TASK) ,
  xInitTaskStack,
  {
    /* Base address                                  Length      Parameters */
    { (void*)__RAM_DATA_BSS_AREA_START__ , /*(u32)__RAM_DATA_BSS_AREA_SIZE__*/0x20000 , portMPU_REGION_READ_WRITE },
    { 0,           0,                        0                       },
    { 0,           0,                        0                       }
  },
  &xInitTaskTcb
};
static TaskHandle_t InitTaskHandle;

I created the task using xTaskCreateRestrictedStatic to have a look inside the TCB

   xTaskCreateRestrictedStatic( &xInitTaskParameters,               &InitTaskHandle               );

When executing the task it again runs into the mem manage fault handler at address 0x20006498 which should be released in my understanding.

I checked the MPU parameters in the TCB:
image
From what I see here the xRegion[1] is configured as expected.

I appreciate any further help!

Is it really failing at that address?
Is there anything else to consider when allowing an unprivileged task to access .data and .bss?

What is the value of __RAM_DATA_BSS_AREA_START__ and where do you define that? Possible for you to share complete project showing the problem?

I think I found the problem: in the alignment of base address to protected/released size parameter. Thanks for that question^^.

Unfortunately I have to restructure the complete memory layout before I can do a test. I will give an update once this is done.

Great - let me know whatever you find.

It was exactly the requirement that a protected (or released) areas start address needs to be aligned with the size of protection. After fixing that, it works as expected.

One last question regarding that answer above: A privilged task always has access to all memory areas (particulary other tasks stacks as well) unless explicitly forbidden by MPU area configuration. Is that correct?

My understanding is that “unrestricted” task are just that, unrestricted, and the MPU is configured to give them full access. There is just one set of MPU settings for ALL unrestricted tasks and the kernel running with elevated privileges so this is needed.