nobody wrote on Thursday, August 24, 2006:
Different ports use two methods for entering and exiting critical sections.
The first pushes the interrupt status onto the stack, then disables interrupts to enter, and simply pops the status off the stack to exit. It sounds like this is what your port is doing. This will only work if you have the compiler options set in a particular way. Otherwise, if you are using stack frame based addressing, changing the stack will cause the sort of problem you are seeing.
The way around this is to use the other method, which defines functions to enter and exit critical sections rather than modifying the stack. This is less efficient but guaranteed to work with all compiler options.
Take a look at some of the ARM ports to see what to do. Basically:
Define a variable in port.c, say ucCriticalNesting, and initialise it to a high value, say 0xf0.
Redefine portENTER_CRITICAL and portEXIT_CRITICAL (in portmacro.h) to call functions vPortEnterCritical() and vPortExitCritical(). These functions take the following form:
void vPortEnterCritical( void )
void vPortExitCritical( void )
if( ucCriticalNesting == 0 )
This is the easy part. Then you have to save and restore the variable ucCriticalNesting on the stack of each task:
In pxPortInitialiseStack() add another byte to the initial stack setup for the task. Set this byte to 0 so the task does not start within a critical section.
In portSAVE_CONTEXT save the value of ucCriticalNesting in the same location on the stack.
In portRESTORE_CONTEXT restore the value from the stack into ucCriticalNesting.
This is an overview. For details I suggest you look at one of the ARM IAR ports and just copy that. I think the variable is called uxCriticalNesting or ulCriticalNesting in that port.