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.
IAR EWARM version 5 stack alignment
IAR EWARM version 5 stack alignment
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.
Regards.