Porting FreeRTOSV10.0.0 to Atmel SAMD51

oshkosh wrote on Friday, November 15, 2019:

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 ?

rtel wrote on Friday, November 15, 2019:

This is curious - the code is popping the context of the first task it
has selected to run - which will be the highest priority task in the
system.

If configUSE_TIMERS
https://www.freertos.org/a00110.html#configUSE_TIMERS is set to 1 then
the highest priority task could be the timer task, which is created by
FreeRTOS at the priority defined by
https://www.freertos.org/a00110.html#configTIMER_TASK_PRIORITY. If that
is the highest priority task, then its stack size is set by
https://www.freertos.org/a00110.html#configTIMER_TASK_STACK_DEPTH - what
is that value set to?

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?

oshkosh wrote on Friday, November 15, 2019:

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.

oshkosh wrote on Monday, November 18, 2019:

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.

Would you advise on the possible causes ?

oshkosh wrote on Monday, November 18, 2019:

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.

Would you advise on the possible causes ?

rtel wrote on Monday, November 18, 2019:

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?

oshkosh wrote on Monday, November 18, 2019:

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.

rtel wrote on Monday, November 18, 2019:

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.

oshkosh wrote on Monday, November 18, 2019:

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 ?

rtel wrote on Monday, November 18, 2019:

Are you still using printf()? If so, then yes definitely re-visit.

The stack overflow hook should tell you which is the offending task -
which is it?

rtel wrote on Monday, November 18, 2019:

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.

oshkosh wrote on Tuesday, November 19, 2019:

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.

oshkosh wrote on Tuesday, November 19, 2019:

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.