ARM problem with ISR local automatic variable

rtel wrote on Saturday, December 03, 2005:

There does indeed appear to be a problem when using GCC V4.0.1 as follows:

Consider the following function fragment of a naked ISR function.

void vUART_ISR( void )
{
____portENTER_SWITCHING_ISR();
____short  needSwitch, level;
____needSwitch = false;

portENTER_SWITCHING_ISR() saves the context, and sets the frame pointer to point to the last context item to be saved.

The line needSwitch = false is then translated into the following code:

mov r3, #0
strh r3, [r11, #-14]

from which it can be seen that the needSwitch variable has an offset of 14 from the frame pointer.  However, the same code compiled with GCC V4.0.1 generates the following code

mov r3, #0
strh r3 [r11]

and in so doing writes the variable directly onto the memory pointed to by the frame pointer - clobbering the last stacked item.

It seems the FreeRTOS code is taking advantage of inefficiencies within the V3.4.3 version of GCC, that are no longer present in V4.0.1.

As the OP suggests, this can be fixed by a small modification to the portENTER_SWITCHING_ISR() macro.  Within portENTER_SWITCH_ISR() the line:

asm volatile ( "MOV R11, LR" );

should be changed to

asm volatile ( "SUB R11, LR, #4" );

Many thanks to the OP for pointing this out.  A fix will be released following further investigations.

Regards.