Problems Using FreeRTOS-MPU on NXP K66

Hello, I have some problems getting the FreeRTOS-MPU port for Cortex-M4 to work. I am using NXP’s Kinetis Design Studio with SDK v2 for a Kinetis K66 (FRDM-K66F Platform) under GCC. I first created a new SDK Project from FreeRTOS Hello World Example. Then replaced the FreeRTOS port (port.c, port.h), added mpu_wrappers.c and added some entries in Linker Script (see below). I set up the parameters for hello_task (User-Mode, MPU region which allows read/write access to UART peripheral) and created the task with xTaskCreateRestricted. Unfortunately there comes a HardFault when the task is trying to access the UART registers (read or write) so it seems my MPU setting is wrong. Starting the task as privileged task everything works fine. Could someone provide help? Below an excerpt of the linker script: ~~~ /* Variables used by FreeRTOS-MPU. */ _Privileged_Functions_Region_Size = 32K; _Privileged_Data_Region_Size = 512; FLASHsegmentstart = ORIGIN( minterrupts ); FLASH_segment_end = FLASH_segment_start + LENGTH( minterrupts ) + LENGTH( mflashconfig ) + LENGTH ( m_text ); privilegedfunctionsstart = ORIGIN( mtext ); privileged_functions_end = privileged_functions_start + _PrivilegedFunctionsRegionSize; SRAMsegmentstart = ORIGIN( mdata ); SRAM_segment_end = SRAM_segment_start + LENGTH( mdata ) + LENGTH( mdata2 ); privilegeddatastart = ORIGIN( mdata ); privileged_data_end = privileged_data_start + _PrivilegedDataRegionSize; /* Define output sections / SECTIONS { / The startup code goes first into internal flash */ .interrupts : { __VECTOR_TABLE = .; . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4);
} > m_interrupts .flashconfig : { . = ALIGN(4); KEEP(*(.FlashConfig)) /* Flash Configuration Field (FCF) */ . = ALIGN(4); } > mflash_config privilegedfunctions : { . = ALIGN(4); *(privilegedfunctions) . = ALIGN(4);
    /* Non privileged code is after _Privileged_Functions_Region_Size. */
    __privileged_functions_actual_end__ = .;
    . = _Privileged_Functions_Region_Size;
} > m_text

.interruptsram : { . = ALIGN(4); VECTOR_RAM = .; interrupts_ram_start = .; /* Create a global symbol at data start */ *(.minterruptsram) /* This is a user defined section */ . += MVECTORRAMSIZE; . = ALIGN(4); interruptsramend = .; /* Define a global symbol at data end */ } > m_data VECTOR_RAM = DEFINED(ramvectortable) ? __VECTOR_RAM : ORIGIN(minterrupts); RAM_VECTOR_TABLE_SIZE_BYTES = DEFINED(ramvectortable) ? (interruptsram_end__ – interrupts_ram_start) : 0x0; privilegeddata : { *(privilegeddata) /* Non kernel data is kept out of the first PrivilegedDataRegionSize bytes of SRAM. */ privileged_data_actual_end = .; . = _Privileged_Data_Region_Size; } > m_data .data : AT(__DATA_ROM) { … ~~~ And here the task set up in freertos_hello.c: ~~~ static void hello_task(void *pvParameters); … /* GCC specifics. */

define mainALIGN_TO( x ) attribute((aligned(x)))

/* Task priorities. */

define hellotaskPRIORITY ((configMAX_PRIORITIES – 1))



define mainMPUDEBUGUART_SIZE (0x80)


static portSTACKTYPE xHelloTaskStack[ mainHELLOTASKSTACKSIZEWORDS ] mainALIGNTO( mainHELLOTASKSTACK_ALIGNMENT ); static const TaskParameterst xHelloTaskParameters = { hellotask, “Hello”, mainHELLOTASKSTACKSIZEWORDS, NULL, hellotaskPRIORITY, xHelloTaskStack, { { mainMPUDEBUGUARTBASEADDR, mainMPUDEBUGUARTSIZE, portMPUREGIONREADWRITE}, { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00 }
}; … int main(void) { /* Init board hardware. */ BOARD_InitPins(); BOARD_BootClockRUN(); BOARD_InitDebugConsole(); xTaskCreateRestricted( &xHelloTaskParameters, NULL); vTaskStartScheduler(); for (;;) ; } /*! * @brief Task responsible for printing of “Hello world.” message. */ static void hello_task(void *pvParameters) { for (;;) { GETCHAR(); PRINTF(“Hello world.rn”); vTaskSuspend(NULL); } } ~~~

Problems Using FreeRTOS-MPU on NXP K66

Can you confirm the task starts, and the fault only occurs when you attempt to access the UART? If so, what is the address of the data access that causes the fault? What is BOARDDEBUGUARTBASEADDR set to? The Cortex-M hardware restricts MPU region start addresses to power of 2 boundaries. Likewise the length (mainMPUDEBUGUARTSIZE) must be a power of 2 (from memory).

Problems Using FreeRTOS-MPU on NXP K66

Problems Using FreeRTOS-MPU on NXP K66

BOARDDEBUGUART_BASEADDR is set to the address of UART0 which is (0x4006A000u). The size of the region is set to 0x80. If I understood the reference manual right, these settings should be correct for the MPU? The task starts correctly and by stepping through the debugger I found out the following line in function UART_ReadBlocking leads to the HardFault: ~~~


    while (!base->RCFIFO)


~~~ With base pointing to address 0x4006a000 (which is UART0) and RCFIFO at Offset 0x0016.

Problems Using FreeRTOS-MPU on NXP K66

Anybody there who could give some hints? I am still not able to get the MPU port run 🙁

Problems Using FreeRTOS-MPU on NXP K66

The base address and region size look to conform with the requirements (region size is binary power of 2 and base address is a multiple of the region size). Are there any additional configuration items required to allow access to the peripherals?

Problems Using FreeRTOS-MPU on NXP K66

After some more debugging I found out the HardFault Exception was not caused by the MPU. The exact fault was a BusFault and not a MemManage Fault as I expected it to be. The reference manual says, the peripherals connected to eiter AIPS-Lite0 or AIPS-Lite1 Peripheral Bridge are not protected by the MPU but have their own protection included. So the solution was to make the peripheral accessible from user mode by clearing the corresponding Supervisor Protect Bit in AIPSx_PACRn Register: ~~~ AIPS0->PACRN &= ~(AIPSPACRNSP2_MASK); /* clear Supervisor Protect Bit */ ~~~ The MPU setting for this region is not used. Thanks for your help.

Problems Using FreeRTOS-MPU on NXP K66

Thanks for taking the time to report the solution.