I am trying to port FreeRTOSV10.0.0 on to Atmel SAMD51 (Cortex-M4 processor). OS is added as middleware from AtmelStart .
My main() function creates a task and calls
vTaskStartScheduler();
This seems to end up in an SVC call and SVC handler in port.c file is invoked.
But it runs into HardFault.
void vPortSVCHandler(void)
{
__asm volatile(" ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. /
" ldr r1, [r3] \n" / Use pxCurrentTCBConst to get the pxCurrentTCB address. /
" ldr r0, [r1] \n" / The first item in pxCurrentTCB is the task top of stack /
" ldmia r0!, {r4-r11, r14} \n" / Pop the registers that are not automatically saved on
exception entry and the critical nesting count. /
" msr psp, r0 \n" / Restore the task stack pointer. */
" isb \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" bx r14 \n"
" \n"
" .align 4 \n"
“pxCurrentTCBConst2: .word pxCurrentTCB \n”);
}
Specifically i have problem at the instruction " ldmia r0!, {r4-r11, r14} \n"
Has any one seen this issue ?
Alternatively if you create a higher priority task, how big is the stack
you are allocating to the task?
Also on the line you highlight, take a look at the R0 and R1 values - R1
should be the address of the TCB associated with the task being
restored, and R0 should point to that task’s stack. You can view the
TCB in the debugger by adding ( (tskTCB*) [address_from_r1] ) - does it
show something sensible?
Are you sure you are using the correct linker script?
Wow… task stack size was the culprit.
By default task size was set to 32 words , which seems to be not enough. It works well when i change it to 100.
Thank you.
Looks like i need some or help on the stack size.
I have had 6 functions running in a loop in the main proior to moving to FreeRTOS.
All the memory was statically allocated and never used heap.
Now on FreeRTOS, i created 6 tasks of same priority (3) and called my functions in these tasks.
FreeRTOSConfig.h has heap configured to 48k and use Heap2 implementation.
But one of my tasks is running into a hard fault. Which is more like the case earlier and happens during context switch in PendSV_Handler().
If i create my tasks with stack size of 100 words , i get see them scheduled 3 times each before the fault. If the task size is 1000 , they are running 13 times.
configCHECK_FOR_STACK_OVERFLOW is enabled but the hook function doesn’t seem to get called.
Looks like i need some or help on the stack size.
I have had 6 functions running in a loop in the main proior to moving to FreeRTOS.
All the memory was statically allocated and never used heap.
Now on FreeRTOS, i created 6 tasks of same priority (3) and called my functions in these tasks.
FreeRTOSConfig.h has heap configured to 48k and use Heap2 implementation.
But one of my tasks is running into a hard fault. Which is more like the case earlier and happens during context switch in PendSV_Handler().
If i create my tasks with stack size of 100 words , i get see them scheduled 3 times each before the fault. If the task size is 1000 , they are running 13 times.
configCHECK_FOR_STACK_OVERFLOW is enabled but the hook function doesn’t seem to get called.
What is configMINIMAL_STACK_SIZE set to? That is used to dimension the
stack used by the idle task.
What is configTIMER_TASK_STACK_DEPTH set to? That is used to dimension
the stack used by the timer task, if configUSE_TIMERS is set to 1.
Is configCHECK_FOR_STACK_OVERFLOW set to 2? Or just 1? 2 is much more
likely to catch a stack overflow. Do you have the overflow hook defined
in a way that ensure it won’t return?
How are you seeing the tasks run ‘n’ number of times? Are they printing
something out? If so, is the print function stack and thread friendly?
configMINIMAL_STACK_SIZE (uint16_t)64
configTIMER_TASK_STACK_DEPTH 64
configCHECK_FOR_STACK_OVERFLOW is set to 1 , overflow hook currently just prints a warning.
The tasks currently prints its name, i am counting it.
Prints are routed through custom log util , so they are easily made thread safe by a semaphore.
I am not sure about the stack safety though.
64 is too small for both tasks created from by the scheduler (idle and
timer) - for not just set them up to 200 - they probably don’t need to
be that big but it will at lease just prove the point for now. 70 is
generally the absolute minimum for the idle task on a Cortex-M without
floating point and no idle task hook function.
Set configCHECK_FOR_STACK_OVERFLOW to 2.
Then see what happens. You can also use the utility functions
uxTaskGetSystemState(), vTaskGetInfo() and
uxTaskGetStackHighWaterMark2() to see how close a task has got to
overflowing its stack.
Observed the same behaviour even with timer and min task stack sizes set to 200.
But this with configCHECK_FOR_STACK_OVERFLOW set to 2 vApplicationStackOverflowHook() gets invoked before the Hard Fault So we can confirm its a stack thing.
Thanks for your help and patience. Do you think i should revisit the printf() s. Or any other angle being missed ?
By the way - this could also be a memory corruption whereby the stack of
a task is just being written over, making the kernel think the stack has
overflowed when it hasn’t.
I have been trying to port an old project with lot of projects by wrapping then into FreeRTOS tasks.
Currently have lot of prints all over. Will create a project with minimal logging and see how it goes.
Appreciate your help and support. Thank you.
I have been trying to port an old project with lot of code by wrapping then into FreeRTOS tasks.
Currently have lot of prints all over. Will create a project with minimal logging and see how it goes.
Appreciate your help and support. Thank you.