IAR EWARM version 5 stack alignment

jorick23 wrote on Tuesday, September 29, 2009:

2009-09-29 10:53:24 EST
I’ve been having an issue with IAR’s EWARM version 5 where functions that take 8 byte arguments (double, long long) would have the argument misaligned on the stack. This was most noticeable in the printf and sprintf functions where a buffer overflow would occur as the misaligned double would try to format a number of over 200 digits.

After numerous tech support emails to IAR and an accidental discovery in one of their manuals, I discovered that the version 5 compiler requires the stack pointer to be 8 byte aligned when a function call is made.

Now as far as I know, FreeRTOS may already align the task stacks to 8 bytes. But I made modifications to the TCB where the registers would be stored there instead of on the task stack when a task switch was made. Apparently these modifications caused the stack to misalign and wreak havoc when I tried to upgrade to version 5.

I’ve noticed occasional emails to this forum describing a similar problem, so this post may be a solution.

I added the following line to tasks.c in the xTaskCreate function, between where pxTopOfStack is defined and pxPortInitialiseStack is called:

pxTopOfStack = (portSTACK_TYPE *) ((unsigned portLONG) pxTopOfStack & (~(8 - 1)));

The line insures that the stack will be 8-byte aligned when the task starts.

rtel wrote on Tuesday, September 29, 2009:

Thanks for taking the time to report that here.

As far as I know the only time this makes a difference (now, also with Keil) is when using 8 byte types, as you say.  Also as you say the time people tend to notice this is in sprintf() type calls.

The Virtex5 port was added recently and supports a double precision floating point unit.  For that reason I had to release that port with 8 byte alignment, and in turn to get that working correctly actually had to update xTaskCreate() slightly which now contains the line:

pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ) - ( ( usStackDepth - 1 ) % portBYTE_ALIGNMENT );

Not the most elegant solution, but the one that produces the fewest compiler warnings on the most number of compilers!

Version 6 of FreeRTOS actually moves the portBYTE_ALIGNMENT_MASK macros into the common portable.h header file instead of the individual portmacro.h files.  I suppose I should really change all the ARM7 and ARM9 configurations to use 8 byte alignment by default.  For now, this can be done simply by changing portBYTE_ALGINMENT, provided you are using the latest release version.