Cortex M33 - MPU Region Support

hofan-de-bosh wrote on Tuesday, July 16, 2019:

Hello Everyone,

We are currently working on a Project incolving the STM32L562 with a Cortex M33 CPU.
The Project was thought to use the integrated MPU and a couple of their regions. At the moment it stands that the port to CM33 only supports 8 regions, from which 5 are already in use.
Now we thought to change some of those. Especially the ones regarding Peripheral access.

But we are concerned to break our combatibility with future updates so i wanted to ask three questions:

  1. Is there going to be an update for the Rtos managed MPU to support all Regions?
  2. Is it meant for us to simply modify the port*.* files to our needs?
  3. If we made those changes in the related port files, are we obligated to merge them back to the community master?

BR Andy

rtel wrote on Tuesday, July 16, 2019:

We are currently working on a Project incolving the STM32L562 with a
Cortex M33 CPU.
The Project was thought to use the integrated MPU and a couple of their
regions. At the moment it stands that the port to CM33 only supports 8
regions, from which 5 are already in use.

Can you elaborate on this. Our port should support all the regions,
some of which are used by the kernel itself (to protect its own data,
etc.), and some are available to be used on a task by task basis.

Now we thought to change some of those. Especially the ones regarding
Peripheral access.

But we are concerned to break our combatibility with future updates so i
wanted to ask three questions:

  1. Is there going to be an update for the Rtos managed MPU to support
    all Regions?

None planned at the moment but feedback from users is what drives our
roadmap so if there is something that needs to change it would be
considered - although we always strive to ensure backward compatibility.

  1. Is it meant for us to simply modify the port/./ files to our needs?

You could do that, but then you would have to maintain those changes as
we update the main code, and without knowing more detail I’m not sure
what the consequences of that would be (as the regions the kernel is
using for itself it needs to use, and the other regions are available
anyway). It would be preferable if you were to give more information on
what you were trying to do so we could make suggestions, if possible.

  1. If we made those changes in the related port files, are we obligated
    to merge them back to the community master?

It would be nice if you made them available some how, but you are not
obliged to.

hofan-de-bosh wrote on Tuesday, July 16, 2019:

Dear Richard!

Thanks for the fast answer, i will try to explain what we are doing.

Can you elaborate on this. Our port should support all the regions,
some of which are used by the kernel itself (to protect its own data,
etc.), and some are available to be used on a task by task basis.

Following the portmacro.h file of the secure part of the CM33 Port i find this code:

/* MPU regions. */
#define portPRIVILEGED_FLASH_REGION							( 0UL )
#define portUNPRIVILEGED_FLASH_REGION						( 1UL )
#define portPRIVILEGED_RAM_REGION							( 2UL )
#define portUNPRIVILEGED_DEVICE_REGION						( 3UL )
#define portSTACK_REGION									( 4UL )
#define portFIRST_CONFIGURABLE_REGION						( 5UL )
#define portLAST_CONFIGURABLE_REGION						( 7UL )
#define portNUM_CONFIGURABLE_REGIONS						( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
#define portTOTAL_NUM_REGIONS								( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */

i might be totally wrong, but in my eyes it seems like the regions 0 to 7 are supported, but not the regions 8 through 15.
What is espicially interessting for us is to use more of the regions since we are trying to protect access to certain peripherals AND also protet kernel, flash, ram etc.

What i am trying to say is, it seems like we can “only” use 3 custom memory regions to be protected by the mpu, since the first 5 are flash, ram, peripheral and stack (why stack, is something i was wondering too, since the m33 has built in stack protection the rtos uses)

Thanks for your kind reply, i hope we can find a solution together.

BR Andy

rtel wrote on Tuesday, July 16, 2019:

Here you are looking at the secure side code. Does that chip have 16
regions available on the secure side and 16 on the non-secure side - or
8 available on the secure and 8 available on the non secure to make up
the 16?

aggarg-aws wrote on Tuesday, July 16, 2019:

You are probably not looking at the latest FreeRTOS version 10.2.1 as we have the following MPU region definitions:

/* MPU regions. */
#define portPRIVILEGED_FLASH_REGION							( 0UL )
#define portUNPRIVILEGED_FLASH_REGION						( 1UL )
#define portUNPRIVILEGED_SYSCALLS_REGION					( 2UL )
#define portPRIVILEGED_RAM_REGION							( 3UL )
#define portSTACK_REGION									( 4UL )
#define portFIRST_CONFIGURABLE_REGION						( 5UL )
#define portLAST_CONFIGURABLE_REGION						( 7UL )
#define portNUM_CONFIGURABLE_REGIONS						( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
#define portTOTAL_NUM_REGIONS								( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */

Still the number of per task configurable regions remain three as we use others to protect, kernel code, kernel data, system calls and task stack.

We need an MPU region for stack to grant access to the running unprivileged task to be able to access its stack. After the task is granted access to its stack using an MPU region, the stack limit registers in Cortex-M33 (MSPLIM and PSPLIM) are used to detect stack overflow. Stack overflow detection using stack limit registers and control of access rights using MPU are two different things and can be done independently (We do both of them in v8M ports).

Thanks.

hofan-de-bosh wrote on Wednesday, July 17, 2019:

Hello Richard, Hello Gaurav,

Thank you for the replies.

It seems like i was looking at the problem the wrong way, espicially with the secure and non secure split in the many regions.
Still, I am not completly grasping the whole thing in the implementation.
The code i cut out was definitly from the non-secure port files. I could not find any implementation of the MPU regions for the secure side?
I was using the MPU_M33F_Simulator_Keil_GCC example.

But back to my starting topic. So we have 3 Regions we can user define for each thread, and these are handled seperatly by the MPU for secure and non-secure side of things, right?

So if we wanted to like change access rights to peripherals via MPU or something aloing those lines i must adapt the port files and am limited to the 8 ones, take or give the ones used ones i have to use like stack, rtos kernel region etc?

BR Andy

aggarg-aws wrote on Wednesday, July 17, 2019:

The secure and non-secure side in Cortex-M33 are two separate partitions with nothing shard among them. The processor boots as secure and it then configures SAU (Security Attribution Unit) to mark the memory regions which the non-secure software can access. After which it jumps to the non-secure code.

There are two MPUs:

  • Secure MPU – Controls access rights to the secure memory.
  • Non-Secure MPU – Controls access rights to the non-secure memory.

FreeRTOS runs on the non-secure side and we only program the non-secure MPU. Each FreeRTOS task by default has access to only its stack and can be configured to have access to up to 3 additional memory regions.

For your specific use case, you can configure SAU such that you peripherals accessible from the non-secure software. Then you can use per task configurable MPU regions to grant different tasks access to different peripherals. For example:

  • Task 1 can access UART for logging purpose.
  • Task 2 can access SPI to talk to a sensor connected on the SPI bus.

Hope that helps.

Thanks.

hofan-de-bosh wrote on Thursday, July 18, 2019:

Hello Gaurav,

Thanks for the answer! That was actually kinda enlighting, i also did some digging and now know how stupid my questions where at some point.
To use the SAU might be a good idea. but therefore TZEN = 1 must be enabled, right?

One last thing though…
You said the FreeRTOS is configuring the non-secure MPU, correct?
I am kinda wondering because if find this in your port files: (GSS/CM33_NTZ/non-secure

#define portMPU_RBAR_REG					( * ( ( volatile uint32_t * ) 0xe000ed9c ) )
#define portMPU_RLAR_REG					( * ( ( volatile uint32_t * ) 0xe000eda0 ) )

#define portMPU_RBAR_A1_REG					( * ( ( volatile uint32_t * ) 0xe000eda4 ) )
#define portMPU_RLAR_A1_REG					( * ( ( volatile uint32_t * ) 0xe000eda8 ) )

#define portMPU_RBAR_A2_REG					( * ( ( volatile uint32_t * ) 0xe000edac ) )
#define portMPU_RLAR_A2_REG					( * ( ( volatile uint32_t * ) 0xe000edb0 ) )

#define portMPU_RBAR_A3_REG					( * ( ( volatile uint32_t * ) 0xe000edb4 ) )
#define portMPU_RLAR_A3_REG					( * ( ( volatile uint32_t * ) 0xe000edb8 ) )

#define portMPU_MAIR0_REG					( * ( ( volatile uint32_t * ) 0xe000edc0 ) )
#define portMPU_MAIR1_REG					( * ( ( volatile uint32_t * ) 0xe000edc4 ) )

This kinda strikes me as odd, because referring to the CortexM33 Ref Manual, those are the registers for the secure MPU? (Page B3-55)
The non securcure would be the ones with 0xe002xxxx:

https://imgur.com/Vvxc6jl

Or am i right in assuming that if TZEN = 0 the non-secure mpu is automatically accessed?
And if yes, how is it if i now enable the TZEN? Is there a different port file?
I am sorry if i sound stupid but i am not really grasping it atm.

BR Andy

hofan-de-bosh wrote on Thursday, July 18, 2019:

EDIT:
Nevermind, i figured it out i think…
Its just banked between the states i see…

aggarg-aws wrote on Thursday, July 18, 2019:

Yes, you are right. Those aliases are used when you want to access non-secure MPU from the secure software.

Thanks.