huzhiping wrote on Monday, May 05, 2014:
I think my porting code has issue. When I change the OS tasks to preemptive (by setting “#define configUSE_PREEMPTION 1” in FreeRTOSConfig.h), all the tasks works fine, if changed back to non-preemptive, then the issue occurred.
the following is my porting code for v850 and using GHS compiler.
/********************************************************************************
#include <df3580_IRQ.h>
#include “FreeRTOSConfig.h”
– Functions used by scheduler
.extern _vTaskSwitchContex
.extern _xTaskIncrementTick
– Variables used by scheduler
.extern _pxCurrentTCB
.extern _usCriticalNesting
– Functions implemented in this file
.global _vPortYield
.global _vPortStart
------------- Basic Initialisation of the controller
------------- User modifiable section
.weak ___lowinit
.text
_RESET:
– Initialisation of the global pointer
movhi hi(___ghsbegin_sdabase),zero,gp
movea lo(___ghsbegin_sdabase),gp,gp
– Initialisation of the text pointer
movhi hi(___ghsbegin_robase),zero,tp
movea lo(___ghsbegin_robase),tp,tp
– Initialisation of the stack pointer
movhi hi(___ghsend_stack-4),zero,sp
movea lo(___ghsend_stack-4),sp,sp
mov -4,r1
and r1,sp
– Jump to the HW Initialisation function
jarl ___lowinit, lp
– Jump to the Initialisation functions of the library,
– from there to main()
jr __start
------------- Interrupt service routine of unused interrupts
.global __unused_isr
__unused_isr:
br __unused_isr
– portSAVE_CONTEXT MACRO
– Saves the context of the remaining general purpose registers
– and the usCriticalNesting Value of the active Task onto the task stack
– saves stack pointer to the TCB
.macro portSAVE_CONTEXT
prepare {r20,r21,r22,r23,r24,r25,r26,r27,r28,r29,r30},19,sp – save general purpose registers
st.w r19,72[ep]
st.w r18,68[ep]
st.w r17,64[ep]
st.w r16,60[ep]
st.w r15,56[ep]
st.w r14,52[ep]
st.w r13,48[ep]
st.w r12,44[ep]
st.w r11,40[ep]
st.w r10,36[ep]
st.w r9,32[ep]
st.w r8,28[ep]
st.w r7,24[ep]
st.w r6,20[ep]
st.w r5,16[ep]
st.w r4,12[ep]
st.w r2,8[ep]
st.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
– portRESTORE_CONTEXT MACRO
– Gets stack pointer from the current TCB
– Restores the context of the usCriticalNesting value and general purpose
– registers of the selected task from the task stack
.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]
ld.w 4[ep],r1 – restore general purpose registers
ld.w 8[ep],r2
ld.w 12[ep],r4
ld.w 16[ep],r5
ld.w 20[ep],r6
ld.w 24[ep],r7
ld.w 28[ep],r8
ld.w 32[ep],r9
ld.w 36[ep],r10
ld.w 40[ep],r11
ld.w 44[ep],r12
ld.w 48[ep],r13
ld.w 52[ep],r14
ld.w 56[ep],r15
ld.w 60[ep],r16
ld.w 64[ep],r17
ld.w 68[ep],r18
ld.w 72[ep],r19
dispose 19,{r20,r21,r22,r23,r24,r25,r26,r27,r28,r29,r30}
.endm
– Restore the context of the first task that is going to run.
– Input: NONE
– Call: CALL vPortStart
– Output: NONE
_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]
– Port Yield function to check for a Task switch in the cooperative and
– preemptive mode
– Input: NONE
– Call: CALL vPortYield
– Output: NONE
_vPortYield:
add -0x0C,sp -- prepare stack to save necessary values
st.w lp,8[sp] -- store LP to stack
stsr 0,r31
st.w lp,4[sp] -- store EIPC to stack
stsr 1,lp
st.w lp,0[sp] -- store EIPSW to stack
portSAVE_CONTEXT -- Save the context of the current task.
jarl _vTaskSwitchContext,lp -- Call the scheduler.
portRESTORE_CONTEXT -- Restore the context of whichever task the ...
-- ... scheduler decided should run.
ld.w 0[sp],lp -- restore EIPSW from stack
ldsr lp,1
ld.w 4[sp],lp -- restore EIPC from stack
ldsr lp,0
ld.w 8[sp],lp -- restore LP from stack
add 0x0C,sp -- set SP to right position
reti
– Perform the necessary steps of the Tick Count Increment and Task Switch
– depending on the chosen kernel configuration
– Input: NONE
– Call: ISR
– Output: NONE
#if configUSE_PREEMPTION == 1 /* use preemptive kernel mode*/
_INTOSTM0:
add -0x0C,sp -- prepare stack to save necessary values
st.w lp,8[sp] -- store LP to stack
stsr 0,r31
st.w lp,4[sp] -- store EIPC to stack
stsr 1,lp
st.w lp,0[sp] -- store EIPSW to stack
portSAVE_CONTEXT -- Save the context of the current task.
jarl _xTaskIncrementTick,lp -- Call the timer tick function.
jarl _vTaskSwitchContext,lp -- Call the scheduler.
portRESTORE_CONTEXT -- Restore the context of whichever task the ...
-- ... scheduler decided should run.
ld.w 0[sp],lp -- restore EIPSW from stack
ldsr lp,1
ld.w 4[sp],lp -- restore EIPC from stack
ldsr lp,0
ld.w 8[sp],lp -- restore LP from stack
add 0x0C,sp -- set SP to right position
reti
#else /* use cooperative kernel mode*/
_INTOSTM0:
prepare {lp,ep},8,sp
sst.w r1,4[ep]
sst.w r5,0[ep]
jarl _xTaskIncrementTick,lp -- Call the timer tick function.
sld.w 0[ep],r5
sld.w 4[ep],r1
dispose 8,{lp,ep}
reti
#endif /* configUSE_PREEMPTION */
/*****************************************************************************
my FreeRTOSConfig.h as follows:
/*****************************************************************************
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/* only include in C files /
//#ifdef IAR_SYSTEMS_ICC
// #pragma language=extended
// #pragma system_include
// #include <intrinsics.h>
//#endif / IAR_SYSTEMS_ICC */
/* V850ES/Fx3 Memory Model
- 1 = Tiny data model
- 0 = Small/Large data model
*/
#define configDATA_MODE 0
/*
- Application specific definitions.
-
- These definitions should be adjusted for your particular hardware and
- application requirements.
-
- THESE PARAMETERS ARE DESCRIBED WITHIN THE ‘CONFIGURATION’ SECTION OF THE
- FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*/
#define configUSE_PREEMPTION 0
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configUSE_TICKLESS_IDLE 0
#define configCPU_CLOCK_HZ 20000000
#define configTICK_RATE_HZ 1000
#define configMAX_PRIORITIES 9
#define configMINIMAL_STACK_SIZE 75
#define configTOTAL_HEAP_SIZE 10240
#define configMAX_TASK_NAME_LEN 22
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 0
#define configUSE_MUTEXES 0
#define configUSE_RECURSIVE_MUTEXES 0
#define configUSE_COUNTING_SEMAPHORES 0
#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */
#define configQUEUE_REGISTRY_SIZE 0
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_MALLOC_FAILED_HOOK 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 0
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine related definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 0
/* Software timer related definitions. /
/#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY 3
#define configTIMER_QUEUE_LENGTH 10
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/
/ Interrupt nesting behaviour configuration. */
//#define configKERNEL_INTERRUPT_PRIORITY 1
//#define configMAX_SYSCALL_INTERRUPT_PRIORITY 3
//#define configMAX_API_CALL_INTERRUPT_PRIORITY 7
/* Define to trap errors during development. */
//#define configASSERT (( x )) if(( x )== 0) vAssertCalled( FILE, LINE )
/* FreeRTOS MPU specific definitions. */
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskSuspend 0
#define INCLUDE_xResumeFromISR 0
#define INCLUDE_vTaskDelayUntil 0
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xTaskGetCurrentTaskHandle 0
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#define INCLUDE_pcTaskGetTaskName 0
#define INCLUDE_eTaskGetState 0
/* A header file that defines trace macro can be included here. */
#endif /* FREERTOS_CONFIG_H */
The difference between preemptive and non-preemptive is that in preemptive, each os tick, it call the OS scheduler, but non-preemptive not.
in my task application code as follows:
/**************************************************************************
void vTask_SYS_EEPROM(void *pvParameters)
{
for(;
{
EE_WriteManager();
#ifndef RELEASE
/* Get the not used stack size of this task */
EEPROMFreeStack = (unsigned portSHORT)uxTaskGetStackHighWaterMark( NULL );
EEPROMFreeStackPercent = StackPercentage(EEPROMSTACK, EEPROMFreeStack);
#endif
/* relative 10 ms cycle time of this task */
vTaskDelay(TASKTIME_10MS / portTICK_RATE_MS);
}
}
/**********************************************************************************
I doubt the function “vTaskDelay(10ms)” do something make the task lost.
I have to use all my tasks to be non-preemptive.
In function “vTaskDelay(xx)” has the following code:
…
…
xAlreadyYielded = xTaskResumeAll();
}
/* Force a reschedule if xTaskResumeAll has not already done so, we may
have put ourselves to sleep. */
if( xAlreadyYielded == pdFALSE )
{
portYIELD_WITHIN_API();
}
Theoretically when calling “portYIELD_WITHIN_API()”, it will call “_vPortYield()” in the upper porting code and do OS reschedule (“trap0” is link to “_vPortYield”), but it looks like not always occurred, or maybe “xAlreadyYielded != pdFALSE” in non-preemptive kernel mode.
Any suggestions?
Thanks a lot!
Albert