STM32 (Cortex M3) MPU with IAR EWARM

Hi, I’d like to enable the MPU (memory protection unit) on a Cortex-M3 project which is being developed in IAR EWARM. My main goal is to improve the stack overflow protection in FreeRTOS and catch these as they occur, not when FreeRTOS decides to check the stack (on a context switch?). However, it appears that MPU support is only present in FreeRTOS 7.5.2 for the LPC17xx microcontrollers using GCC-derived toolchains. Has anyone managed to get the MPU port working on an STM32 with IAR EWARM? Failing that, is there any way I can configure FreeRTOS to set up the MPU to provide some limited stack overflow protection, even if the full MPU protections don’t apply? Thanks,
Phil.

STM32 (Cortex M3) MPU with IAR EWARM

An MPU port is only provided for GCC – but can be used on any Cortex-M3 chip, there is nothing special about the LPC17xx. It would be relatively easy to create an IAR version by simply copying the GCC version, but updating the portions that require assembly code to use the IAR assembler instead of the inline GCC assembler.  In fact, if you are using a newish version of IAR then it understands the GCC style inline assembly syntax anyway, but I’m not sure if you can create naked functions like you can in GCC.  You can see the differences between the IAR and GCC versions by diffing the base (non-MPU) ports. You would also need to work out how to use constants provided by the linker in the source code.  In the GCC version the linker script is used to set up different memory regions, and the beginning and end of the regions are read in the C code from constants provided by the linker.  That may or may not be simple – I’ve never tried it. The alternative of just configuring the MPU after a context switch to protect just the task stack would be tricky because the task will presumably need to access RAM outside of its own stack area, so you cannot restrict its access purely to the stack.  The MPU version uses statically allocated buffers for the stack, then the CreateRestricted version of the TaskCreate function to pass the buffer in – along with its start and end addresses. Hope this helps. Regards.

STM32 (Cortex M3) MPU with IAR EWARM

Richard,
Thanks for your reply – I’ve spent the day looking into this, and have managed to get something resembling working code on my ARM board with IAR. I made copies of the Red Suite MPU porting layer, moved the naked functions (which IAR doesn’t support) out into an assembly source file and fixed a few issues with the ASM code (IAR doesn’t like short-form ARM instructions, e.g. BIC r0, #1 had to be replaced with BIC r0,r0,#1). Now I’m at the point where my tasks start up, but the first time I try to access a queue, I land here: signed portBASE_TYPE MPU_xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
{
portBASE_TYPE xRunningPrivileged = prvPortRaisePrivilege();
signed portBASE_TYPE xReturn;                 xReturn = xQueueGenericReceive( pxQueue, pvBuffer, xTicksToWait, xJustPeeking );
                portRESET_PRIVILEGE( xRunningPrivileged );
                return xReturn;
} If I step onto prvPortRaisePrivilege(), the ST-Link reports a loss of target connection and the debugger crashes. I don’t get any exceptions that I can tell, it just keels over and dies. I’m suspecting stack problems at this stage especially as my test code is using xTaskCreate() to create the first task. Thanks,
Phil.

STM32 (Cortex M3) MPU with IAR EWARM

I’m not sure why any of the tools should crash. From your post I see you have implemented the functions, and are calling the queue receive function through the macro – but are you actually using the MPU yet or just running all the tasks as privileged tasks? Does your code include dummy handlers for the Cortex-M3 fault exceptions so you can catch MPU faults without going into the weeds? Regards.

STM32 (Cortex M3) MPU with IAR EWARM

I’ve had a closer look at the code – some of the fault handlers were calling
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);
… which was stopping the CPU core (according to the comments, it was to force a watchdog reset). After stopping that, the crashing has ceased. It turns out the CPU was raising a MemManage fault – if I halt the debugger after the crash, the debugger lands in MemManage_Handler() with the following CFSR bits set: The task is created like this:
xTaskCreate(prvSTATUSTask, “Status”,
(configMINIMAL_STACK_SIZE*2)+50, NULL,
tskIDLE_PRIORITY + 1, NULL); I single stepped into the prvPortRaisePrivilege function: prvPortRaisePrivilege
mrs r0, control
/* Is the task running privileged? */
tst r0, #1
itte ne
/* CONTROL!=0, return false. */
movne r0, #0
/* Switch to privileged. */
svcne #portSVC_RAISE_PRIVILEGE
/* CONTROL==0, return true. */
moveq r0, #1
bx lr The memory management exception occurs on the first line – the MRS instruction. This appears to work fine early in the RTOS startup, but not from tasks.

STM32 (Cortex M3) MPU with IAR EWARM

Woops –
Just before the MemManage fault, I have CONTROL.UNPRIV and CONTROL.PROC set.
After I land in the MemManage fault handler:
  CONTROL.UNPRIV=1
  CONTROL.PROC=0
  CFSR.IACCVIOL=1
  CFSR.MMARVALID=0
  MMFAR = 0xE000EDF8
  BFAR = 0xE000EDF8

STM32 (Cortex M3) MPU with IAR EWARM

OK, more info – the problem in this case was that I’d moved prvPortRaisePrivilege into privileged flash. After moving it into normal flash memory, the code gets a little further but eventually throws a forced “invalid state” (INVSTATE=1) hardfault…

STM32 (Cortex M3) MPU with IAR EWARM

I think I’m finally getting somewhere! I found a copy-paste bug in the PendSV handler which was causing registers to be popped twice. That and disabling another hidden power management command (this time in the idle task and used to save power) got me into the idle task. I pushed the “User” button on the dev board (which is tied to an EXTI which pushes a byte onto the queue for my “status” task), then the status task woke up as expected… … Until I got another Forced Hard Fault. This time it was a bus fault (a “precise data bus error”) caused by IAR’s SWO printf function trying to access a debug register (specifically 0xE000EDFC)… To fix this, I made the Status task a privileged task (OR the task priority with portPRIVILEGE_BIT) and the status handler started working! I’m going to see if there’s a way to make the prvPortRaisePrivilege function private to the port handler (IAR doesn’t seem to support naked functions but perhaps the function preamble won’t be too critical?) Is there a procedure for contributing this code back to the FreeRTOS project? Obviously it’ll have to go through internal code review first, but it would be nice to see this made available for others to use.

STM32 (Cortex M3) MPU with IAR EWARM

caused by IAR’s SWO printf function trying to access a debug register (specifically 0xE000EDFC)
I had a similar problem with Rowleys print function.  To get around this I made the print function a privileged function as follows:
/* The Rowley library function debug_printf() uses data that is out of the
control of the kernel, so run the function in a privileged mode. */
int MPU_debug_printf( const char *pcMessage )
{
portBASE_TYPE xRunningPrivileged = prvRaisePrivilege();
    debug_printf( pcMessage );
    portRESET_PRIVILEGE( xRunningPrivileged );
    return 0;
}
This appears in a file called application_defined_privileged_functions.h, which is included from port.c if configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS is defined to 1 in FreeRTOSConfig.h (this is new to FreeRTOS V7.5.x).
Is there a procedure for contributing this code back to the FreeRTOS project? Obviously it’ll have to go through internal code review first, but it would be nice to see this made available for others to use.
It would be great if you could upload it to an appropriate forum in the FreeRTOS interactive site:
http://interactive.freertos.org Thanks, and regards.