marcbe wrote on Thursday, March 23, 2017:
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;
__FLASH_segment_start__ = ORIGIN( m_interrupts );
__FLASH_segment_end__ = __FLASH_segment_start__ + LENGTH( m_interrupts ) + LENGTH( m_flash_config ) + LENGTH ( m_text );
__privileged_functions_start__ = ORIGIN( m_text );
__privileged_functions_end__ = __privileged_functions_start__ + _Privileged_Functions_Region_Size;
__SRAM_segment_start__ = ORIGIN( m_data );
__SRAM_segment_end__ = __SRAM_segment_start__ + LENGTH( m_data ) + LENGTH( m_data_2 );
__privileged_data_start__ = ORIGIN( m_data );
__privileged_data_end__ = __privileged_data_start__ + _Privileged_Data_Region_Size;
/* 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
.flash_config :
{
. = ALIGN(4);
KEEP(*(.FlashConfig)) /* Flash Configuration Field (FCF) */
. = ALIGN(4);
} > m_flash_config
privileged_functions :
{
. = ALIGN(4);
*(privileged_functions)
. = ALIGN(4);
/* Non privileged code is after _Privileged_Functions_Region_Size. */
__privileged_functions_actual_end__ = .;
. = _Privileged_Functions_Region_Size;
} > m_text
...
.interrupts_ram :
{
. = ALIGN(4);
__VECTOR_RAM__ = .;
__interrupts_ram_start__ = .; /* Create a global symbol at data start */
*(.m_interrupts_ram) /* This is a user defined section */
. += M_VECTOR_RAM_SIZE;
. = ALIGN(4);
__interrupts_ram_end__ = .; /* Define a global symbol at data end */
} > m_data
__VECTOR_RAM = DEFINED(__ram_vector_table__) ? __VECTOR_RAM__ : ORIGIN(m_interrupts);
__RAM_VECTOR_TABLE_SIZE_BYTES = DEFINED(__ram_vector_table__) ? (__interrupts_ram_end__ - __interrupts_ram_start__) : 0x0;
privileged_data :
{
*(privileged_data)
/* Non kernel data is kept out of the first _Privileged_Data_Region_Size
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 hello_task_PRIORITY ((configMAX_PRIORITIES - 1))
#define mainHELLO_TASK_STACK_SIZE_WORDS 128
#define mainHELLO_TASK_STACK_ALIGNMENT ( mainHELLO_TASK_STACK_SIZE_WORDS * sizeof( portSTACK_TYPE ) )
#define mainMPU_DEBUG_UART_SIZE (0x80)
#define mainMPU_DEBUG_UART_BASE_ADDR ((uint32_t *) BOARD_DEBUG_UART_BASEADDR)
static portSTACK_TYPE xHelloTaskStack[ mainHELLO_TASK_STACK_SIZE_WORDS ] mainALIGN_TO( mainHELLO_TASK_STACK_ALIGNMENT );
static const TaskParameters_t xHelloTaskParameters =
{
hello_task,
"Hello",
mainHELLO_TASK_STACK_SIZE_WORDS,
NULL,
hello_task_PRIORITY,
xHelloTaskStack,
{
{ mainMPU_DEBUG_UART_BASE_ADDR, mainMPU_DEBUG_UART_SIZE, portMPU_REGION_READ_WRITE},
{ 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.\r\n");
vTaskSuspend(NULL);
}
}