FreeRTOS Support Archive

The FreeRTOS support forum can be used for active support both from Amazon Web Services
and the community. In return for using our software for
free, we request you play fair and do your bit to help others! Sign up
to receive notifications of new support topics then help where you can.

This is a read only archive of threads posted to the FreeRTOS support forum.
The archive is updated every week, so will not always contain the very latest posts.
Use these archive pages to search previous posts. Use the Live FreeRTOS Forum
link to reply to a post, or start a new support thread.

RE: LPC2129-GCC port.

is it OK to modify the function 'pxPortInitialiseStack()' in 'port.c' as below while porting FreeRTOS to LPC2129 with GCC tool.because without this modification, the scheduler will not start the task due to improper information on stack when it is restored.------------------------- ORIGINAL FUNCTION --------------------------------------------portSTACK_TYPE pxPortInitialiseStack( portSTACK_TYPE pxTopOfStack, pdTASK_CODE pxCode, void pvParameters ) { portSTACK_TYPE pxOriginalTOS;pxOriginalTOS = pxTopOfStack;

/* To ensure asserts in tasks.c don't fail, although in this case the assertis not really required. */pxTopOfStack--;

/* Setup the initial stack of the task. The stack is set exactly as expected by the portRESTORE_CONTEXT() macro. */

/* First on the stack is the return address - which in this case is thestart of the task. The offset is added to make the return address appearas it would within an IRQ ISR. */*pxTopOfStack = ( portSTACK_TYPE ) pxCode + portINSTRUCTION_SIZE; pxTopOfStack--;

/* Some optimisation levels use the stack differently to others. This means the interrupt flags cannot always be stored on the stack and willinstead be stored in a variable, which is then saved as part of thetasks context. */*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;

/* To ensure asserts in tasks.c don't fail, although in this case the assertis not really required. */pxTopOfStack--;

/* Setup the initial stack of the task. The stack is set exactly as expected by the portRESTORE_CONTEXT() macro. */

/* First on the stack is the return address - which in this case is thestart of the task. The offset is added to make the return address appearas it would within an IRQ ISR. */*pxTopOfStack = ( portSTACK_TYPE ) pxCode + portINSTRUCTION_SIZE; pxTopOfStack--;

/* Some optimisation levels use the stack differently to others. This means the interrupt flags cannot always be stored on the stack and willinstead be stored in a variable, which is then saved as part of thetasks context. */*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;

return pxTopOfStack;}Thanks,GCD

ReplyLinkEditDeleteAttach

Richard 23 hours agoCan you please tell me what it is you changed so I don't have to go through the two functions line by line.I'm not sure why any change would be necessary as the code that starts the first task is written in assembler and expects to find things on the stack exactly as placed on the stack with this code.Regards.

ReplyLinkEditDeleteAttach

GCD 3 minutes agoHi Richard,Thanks for the response. Modification is as belowStatement below Just before storing the data supposed to be in 'R14' on the stackpxTempTOS = pxTopOfStack;below statement before storing the dummy contents of 'R0'pxTempTOS = (unsigned int )pxTopOfStack;I encountered this issue while debugging for not getting the first task started. unfortunately don't remember what value was getting corrupted. But got the tasks running after this modification even with FREERTOS version, 7.2.0. I'll recheck the whole procedure I did to use FREERTOS on LPC2129 with GCC. I apologise if this topic is misleading.Thanks

3) Writes over 0xaaaaaaaa (the value never gets used) with the address that R0 will be popped from. R0 holds the parameters passed into the function.

So the net effect is, the stack frame is unchanged *other than*, when the task starts, R14 holds the address that R0 was popped from.

I don't understand why this would make a difference. If you compiler conforms to the ARM EABI standard, then the value in R14 should not be used unless you try to return from the task function (which is not allowed).

Which compiler are you using? (I know you said GCC, but which build?)

Regards.

RE: LPC2129-GCC port.

Initially I'll explain the issue why I did the modification. Later i'll give the compiler details I am using.

a. Issue because of which I had to do the above modificationactually in function 'portRESTORE_CONTEXT()' in portmacro.h, after restoring the whole stack into system registers (R0 through R14), there are two more instructions to calculate PC values as below,

while trying to restore the return address using first instruction, adding 60 to the content of LR will be erroneous hence I added the address in the stack from where R0 will be popped. So with the modification, along with the address correction using next instruction gets PC value to the proper TOP OF STACK to get the return address.

b. GCC Compiler details. As u said, it looks as L14 is being used to get the right address, may be the compiler is not EABI compliant. but I have no idea how to check whether the compiler conforms to EABI. following are the details of the compiler I am using

RE: LPC2129-GCC port.

instead of "adding 60 to the content of LR will be erroneous hence I added the address in the stack from where R0 will be popped" it has to be "adding 60 to the content of LR will be erroneous hence I copied the address of the stack location from where R0 will be popped to the location from where R14 is popped."

RE: LPC2129-GCC port.

The microcontroller should be in Supervisor mode when the first task is started. The code pops the registers from the initial stack frame into the System mode registers. So, while the CPU is using the Supervisor mode registers, it restores the System mode registers, then switches into System mode when the task starts.

If you are seeing R14 being altered during the start first task execution then my best guest (actually, almost certainly) you are starting the scheduler from the wrong CPU mode.

The easiest way to ensure the CPU is in the right mode is to have your start up code set the mode to Supervisor before main() is called. Then it will be in Supervisor when it starts the first task, and System mode when the task actually executes.