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
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(ghsbeginsdabase),zero,gp
movea lo(__ghsbegin_sdabase),gp,gp
-- Initialisation of the text pointer
movhi hi(ghsbeginrobase),zero,tp
movea lo(ghsbeginrobase),tp,tp
-- Initialisation of the stack pointer
movhi hi(ghsendstack-4),zero,sp
movea lo(ghsendstack-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 _unusedisr
_unusedisr:
br _unusedisr
-- 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 portSAVECONTEXT
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 portRESTORECONTEXT
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:
portRESTORECONTEXT -- 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 FREERTOSCONFIGH
define FREERTOSCONFIGH
/* only include in C files /
//#ifdef IARSYSTEMSICC
// #pragma language=extended
// #pragma system_include
// #include
//#endif / IARSYSTEMSICC */
/* 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 configUSEPORTOPTIMISEDTASKSELECTION 0
define configUSETICKLESSIDLE 0
define configCPUCLOCKHZ 20000000
define configTICKRATEHZ 1000
define configMAX_PRIORITIES 9
define configMINIMALSTACKSIZE 75
define configTOTALHEAPSIZE 10240
define configMAXTASKNAME_LEN 22
define configUSE16BIT_TICKS 0
define configIDLESHOULDYIELD 0
define configUSE_MUTEXES 0
define configUSERECURSIVEMUTEXES 0
define configUSECOUNTINGSEMAPHORES 0
define configUSEALTERNATIVEAPI 0 /* Deprecated! */
define configQUEUEREGISTRYSIZE 0
define configUSEQUEUESETS 0
define configUSETIMESLICING 0
define configUSENEWLIBREENTRANT 0
/* Hook function related definitions. */
define configUSEIDLEHOOK 0
define configUSETICKHOOK 0
define configCHECKFORSTACK_OVERFLOW 2
define configUSEMALLOCFAILED_HOOK 0
/* Run time and task stats gathering related definitions. */
define configGENERATERUNTIME_STATS 0
define configUSETRACEFACILITY 0
define configUSESTATSFORMATTING_FUNCTIONS 0
/* Co-routine related definitions. */
define configUSECOROUTINES 0
define configMAXCOROUTINE_PRIORITIES 0
/* Software timer related definitions. /
/#define configUSE_TIMERS 1
define configTIMERTASKPRIORITY 3
define configTIMERQUEUELENGTH 10
define configTIMERTASKSTACKDEPTH configMINIMALSTACK_SIZE
/
/ Interrupt nesting behaviour configuration. */
//#define configKERNELINTERRUPTPRIORITY 1
//#define configMAXSYSCALLINTERRUPTPRIORITY 3
//#define configMAXAPICALLINTERRUPT_PRIORITY 7
/* Define to trap errors during development. */
//#define configASSERT (( x )) if(( x )== 0) vAssertCalled( FILE, LINE )
/* FreeRTOS MPU specific definitions. */
define configINCLUDEAPPLICATIONDEFINEDPRIVILEGEDFUNCTIONS 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 /* FREERTOSCONFIGH */
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 vTaskSYSEEPROM(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 "portYIELDWITHINAPI()", 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