Porting FreeRTOS to v850 Fx4

huzhiping wrote on Friday, December 13, 2013:

I am trying to port FreeRTOS to v850 Fx4 based on Fx3, but using GreenHills compiler.
Sereval issues found:

  1. From FreeRTOS offical website, it is said “6.If the stack on the microcontroller being ported to grows downward from high memory to low memory then set portSTACK_GROWTH in portmacro.h to -1, otherwise set portSTACK_GROWTH to 0.” --> in here, http://www.freertos.org/FreeRTOS-porting-guide.html…, if you set “portSTACK_GROWTH to 0”, then you got a compiler error, “pxEndOfStack” is undefined, you have to set “portSTACK_GROWTH to be greater than 0”, which in Tasks.c, the condition is “portSTACK_GROWTH > 0”.

  2. I created 2 simple tasks with function by setting a different LED ON in each task, When I using debugger, 2 tasks (priority is different, task 2 is 2, task1 is 1) and the idle task all created successfully, but in function "xPortStartScheduler()–>vPortStart() -> portRESTORE_CONTEXT (assembly macro), it can NOT get the right address of “_pxCurrentTCB” that is for task2. my vPortStart() function is:

_vPortStart:
portRESTORE_CONTEXT – Restore the context of whichever task the …
ld.w 0[sp],lp
ldsr lp,5 – restore PSW
DI
ld.w 4[sp],lp – restore LP
ld.w 8[sp],lp – restore LP
ADD 0x0C,sp – set SP to right position
EI
jmp [lp]

  1. I tried different heap_x.c, I found each time after call vPortStat()->portRESTORE_CONTEXT
    the stack pointer of “_pxCurrentTCB” is different. I double checked the “portRESTORE_CONTEXT” and “portSAVE_CONTEXT”, it looks like correct.
    I attched these assembly macro below:

.macro portSAVE_CONTEXT
prepare {r20,r21,r22,r23,r24,r26,r27,r28,r29,r30},18,sp – save general purpose registers
sst.w r19,68[ep]
sst.w r18,64[ep]
sst.w r17,60[ep]
sst.w r16,56[ep]
sst.w r15,52[ep]
sst.w r14,48[ep]
sst.w r13,44[ep]
sst.w r12,40[ep]
sst.w r11,36[ep]
sst.w r10,32[ep]
sst.w r9,28[ep]
sst.w r8,24[ep]
sst.w r7,20[ep]
sst.w r6,16[ep]
sst.w r5,12[ep]
sst.w r2,8[ep]
sst.w r1,4[ep]
MOVHI hi(_usCriticalNesting),r0,r1 – save usCriticalNesting value to stack
ld.w lo(_usCriticalNesting)[r1],r2
sst.w r2,0[ep]
MOVHI hi(_pxCurrentTCB),r0,r1 – save SP to top of current TCB
ld.w lo(_pxCurrentTCB)[r1],r2
st.w sp,0[r2]
.endm

.macro portRESTORE_CONTEXT
MOVHI hi(_pxCurrentTCB),r0,r1 – get Stackpointer address
ld.w lo(_pxCurrentTCB)[r1],sp
MOV sp,r1
ld.w 0[r1],sp – load stackpointer
MOV sp,ep – set stack pointer to element pointer
sld.w 0[ep],r1 – load usCriticalNesting value from stack
MOVHI hi(_usCriticalNesting),r0,r2
st.w r1,lo(_usCriticalNesting)[r2]
sld.w 4[ep],r1 – restore general purpose registers
sld.w 8[ep],r2
sld.w 12[ep],r5
sld.w 16[ep],r6
sld.w 20[ep],r7
sld.w 24[ep],r8
sld.w 28[ep],r9
sld.w 32[ep],r10
sld.w 36[ep],r11
sld.w 40[ep],r12
sld.w 44[ep],r13
sld.w 48[ep],r14
sld.w 52[ep],r15
sld.w 56[ep],r16
sld.w 60[ep],r17
sld.w 64[ep],r18
sld.w 68[ep],r19
dispose 18,{r20,r21,r22,r23,r24,r26,r27,r28,r29,r30}
.endm

I don’t know how to do it next, hopefully I can get help from you.

Thanks in advance!

Albert

rtel wrote on Saturday, December 14, 2013:

There is already a V850ES port for IAR. You can use that as a base, and basically just copy it but using the GreenHills compiler. I’m afraid I don’t have GreenHills tools so don’t know anything about them.

portSTACK_GROWTH in portmacro.h to -1, otherwise set portSTACK_GROWTH to 0

That was incorrect, portSTACK_GROWTH should be -1 or 1, not 0. I have updated the documentation. In your case I think it should be -1 anyway but would have to check.

Regards.

huzhiping wrote on Monday, December 16, 2013:

Question about the function of _vPortStart below:

_vPortStart:
portRESTORE_CONTEXT – Restore the context of whichever task the …
ld.w 0[sp],lp
ldsr lp,5 – restore PSW
DI
ld.w 4[sp],lp – restore LP
ld.w 8[sp],lp – restore LP
ADD 0x0C,sp – set SP to right position
EI
jmp [lp]

In this function, the first line is “portRESTORE_CONTEXT” to get the “_pxCurrentTCB” task context. But after you create all the tasks, the highest priority task is the “_pxCurrentTCB” and all the tasks never use “portSave_CONTEXT” to save all the r0~r30 registers, if you use “portRESTORE_CONTEXT”, it will get the wrong context registers value.

In my case, I have task1 and task2, and task2 has the highest priority, after they are created, pxCurrentTCB is task2, but after call “vPortStart” and “portRESTORE_CONTEXT”, it got the different register values, so it never call task2 to run.

Is this correct? and how do I fix it?

Thanks for you help!

Albert

rtel wrote on Monday, December 16, 2013:

Gosh, its a long time since I’ve looked at that port, but i’m not sure if I follow your post.

As you say, the first thing vPortStart() calls is portRESTORE_CONTEXT(), and the first thing portRESTORE_CONTEXT() does is load the stack pointer from the pxCurrentTCB variable. Therefore the first task to execute will be that pointed to by pxCurrentTCB.

portRESTORE_CONTEXT() then pops that task’s context from its stack, which was pre-loaded with values by the pxPortInitialiseStack() function, which was called (internally by the RTOS) when the task was created. After portRESTORE_CONTEXT() is called vPortStart() obtains the address of the tasks entry point from the tasks stack, and jumps to it to kick the task off.

Which bit am I missing?

Regards.

huzhiping wrote on Monday, December 16, 2013:

Yes. Right. My question is that after you created all the tasks, the highest priority task is the pxCurrentTCB task, when you create these tasks, the highest priority may not the last task to be created, and we didn’t use portSAVE_CONTEXT, Although we can get the right pxCurrentTCB stack address, but rest of the rigsters in r0~31 may have different values, therefore, when you call portRESTORE_CONTEXT of vPORTSTART, it will not get the right task context, I am right?

My portRESTORE/SAVE_CONTEXT functions are in my first post.

Thanks.

Albert

edwards3 wrote on Monday, December 16, 2013:

When the scheduler is started pxCurrentTCB will already be pointing to the highest priority task that was created before that point.

richard_damon wrote on Tuesday, December 17, 2013:

When tasks are created, they are created “As if” a portSAVE_CONTEXT was called, this is a requirement of the routine that sets up the initial stack of a task.

huzhiping wrote on Thursday, December 19, 2013:

Thanks for the help!

Albert