NIOS port_asm.S can use pxCurrentTCB when NULL

FreeRTOS version: 202212.00
Port: NIOS for Intel/Altera
Running on Cyclone V
Port files copied from: Source/portable/GCC/NiosII

I inserted test code in my project’s main.c that simply writes 0x55 to external DDR and verifies the contents. My DDR starts at address 0x0000000000000000. My test fails because the first four bytes are being mysteriously written by something else.

When I remove the FreeRTOS files from the build, the memory corruption does not occur. So I started adding back the FreeRTOS files. It turns out that the memory corruption occurs when port_asm.S is included in the build. That file does require that pxCurrentTCB be defined, so I copied the tskTCB typedef, TCB_t typedef, and “TCB_t * volatile pxCurrentTCB = NULL;” into my main.c. No other FreeRTOS files are included in the compile and no FreeRTOS functions are called.

As I learned from another posting, port_asm.S inserts exception handling code ahead of the normal exception code and includes branches to bypass the normal exception code. Reference " FreeRTOS with Altera / Intel NIOS II, exception handling clash".

The issue I see is that pxCurrentTCB is set to NULL, which is the same as address 0x0000000000000000 (the same as the start of my external RAM). Therefore, if the exception code runs for whatever reason, the code in port_asm.S writes to my external RAM, causing the memory corruption.

It seems like the code in port_asm.S needs to have protection when pxCurrentTCB is NULL.

Perhaps the root question is, why is the code in port_asm executing in the first place since I am not calling any FreeRTOS functions.

What do you think is the best way to approach this? In my “real code” (rather than this test code) I will have various init and hardware test functions that happen before creating FreeRTOS tasks and get the scheduler going (at which time it would init pxCurrentTCB with something other than NULL). I don’t want my external RAM being corrupted during my RAM integrity check).

port_asm.S appears to insert exception entry/exit code. So that code runs for interrupt handler entry/exit. Thus it runs even if you’re not making FreeRTOS calls.

Are you using interrupts in your init functions and hardware tests prior to starting FreeRTOS? If so, changing that code not to use interrupts would be one solution. It seems the NIOS port assumes interrupts will be disabled from reset until FreeRTOS starts.

An alternate solution might be to modify port_asm.S to check for a NULL pxCurrentTCB and skip the save/restore of the stack pointer. That functionality is needed only when FreeRTOS is running.

Hey @ssea000, I wanted to check if the answer that @jefftenney gave you explains why you were seeing this behaviour? If you still have any questions or need some clarification please feel free to ask!