Memset causes undefined instruction interrupt in SAMA5D27

Hi,

I am relatively new to FreeRTOS and embedded devices in general but I have been attempting to get ethernet communication with a SAMA5D27 dev board. I have been using MPLab libraries to set up FreeRTOS and it seems to be building correctly. Everything is initiating and I can create tasks but when vTaskStartScheduler() is called it causes it to jump to the undefined instructions interrupt handler and nothing ever actually runs. I traced through it with the debugger and it seems to always get stuck on this line in FreeRTOS_tasks.c:

memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );

Any advice on what could be causing this and what I can look into to figure out the cause?

Thanks

Do you have configASSERT defined (properly) ? This helps a lot during development.
(Along with that you should also enable stack checking.)

1 Like

I defined it for a debugger (as recommended here). When I run and pause it with the debugger it is always in the interrupt handler infinite loop:

void __attribute((weak, noreturn)) undefined_instruction_irq_handler (void)
{
    while(true)
    {
        /* Spin forever */
    }
}

Stack checking is also enabled (method 2)

apparently pxNewTCB points to an invalid memory location, for example 0 which may point to a previous allocation failure. As Hartmut points out, most of those cases can be found with configASSERT resolving to something meaningful.

Step through the memset() assembly code in the debugger to see if it is using floating point registers. Some memory set and move functions use the wide floating point registers as an optimisation. If it does use them, are you building FreeRTOS to include floating point support? If not, the floating point registers won’t be saved and restored with the task’s context, and can get corrupted.

Thank you for the advice!

I stepped through memset and found that all values looked reasonable so I went back again and found that the debugger was getting hung up on that spot but the code actually does execute past it.

configAssert() is actually being called with vPortRestoreTaskContext(); in xPortStartScheduler();

vPortRestoreTaskContext:

    // Switch to system mode
    CPS     #SYS_MODE
    portRESTORE_CONTEXT
.macro portRESTORE_CONTEXT

    // Set the SP to point to the stack of the task being restored.
    LDR     R0, =pxCurrentTCB
    LDR     R1, [R0]
    LDR     SP, [R1]

    // Is there a floating point context to restore?  If the restored
    // ulPortTaskHasFPUContext is zero then no.
    LDR     R0, =ulPortTaskHasFPUContext
    POP     {R1}
    STR     R1, [R0]
    CMP     R1, #0

    // Restore the floating point context, if any
    POPNE   {R0}
#if configFPU_D32 == 1
    VPOPNE  {D16-D31}
#endif
    VPOPNE  {D0-D15}
    VMSRNE  FPSCR, R0

    // Restore the critical section nesting depth
    LDR     R0, =ulCriticalNesting
    POP     {R1}
    STR     R1, [R0]

    // Restore all system mode registers other than the SP (which is already
    // being used)
    POP     {R0-R12, R14}

    // Return to the task code, loading CPSR on the way.  CPSR has the interrupt
    // enable bit set appropriately for the task about to execute.
    RFEIA   sp!

    .endm

I also found another post with this exact problem so I’m guessing its an issue with the example provided: https://forum.microchip.com/s/topic/a5C3l000000MdijEAC/t382740

This is the implementation I am using:

Any ideas on what could be causing this?

Thanks!

share your assert output. It normally contains a source code line to look up.

Where should it be outputting to? The debugger doesn’t have a console it can print to

Can you step through the assembly and try to find the instruction causing the fault?

It always throws the fault immediately when I try to step through it but for some reason if I ‘run to cursor’ line by line it lets me pass the ‘switch to system mode’ instruction and then errors on the second line:

    LDR     R0, = pxCurrentTCB

Are you stepping in the assembly mode? In other words, are you able to step over one assembly instruction at a time?

In other assembly code I can but in this specific case it sends it to assert when I try to do that.

It is hard to make a guess any further. If you’d like to have a debug session to debug this together, please drop me a DM with your email.

1 Like