\r
;------------------------------------------------------------------------------\r
; portSAVE_CONTEXT MACRO\r
-; Saves the context of the remaining general purpose registers, CS and ES\r
-; (only in far memory mode) registers\r
-; the usCriticalNesting Value and the Stack Pointer\r
+; Saves the context of the general purpose registers, CS and ES (only in far \r
+; memory mode) registers the usCriticalNesting Value and the Stack Pointer\r
; of the active Task onto the task stack\r
;------------------------------------------------------------------------------\r
portSAVE_CONTEXT MACRO\r
\r
- PUSH AX ; save AX Register to stack\r
+ PUSH AX ; Save AX Register to stack.\r
PUSH HL\r
#if configMEMORY_MODE == 1\r
- MOV A, CS ; save CS register\r
+ MOV A, CS ; Save CS register.\r
XCH A, X\r
- MOV A, ES ; save ES register\r
+ MOV A, ES ; Save ES register.\r
PUSH AX\r
#else\r
- MOV A, CS ; save CS register\r
+ MOV A, CS ; Save CS register.\r
PUSH AX\r
#endif\r
- PUSH DE ; save the remaining general purpose registers\r
+ PUSH DE ; Save the remaining general purpose registers.\r
PUSH BC\r
- MOVW AX, usCriticalNesting ; save the usCriticalNesting value \r
+ MOVW AX, usCriticalNesting ; Save the usCriticalNesting value.\r
PUSH AX \r
- MOVW AX, pxCurrentTCB ; save the Stack pointer \r
+ MOVW AX, pxCurrentTCB ; Save the Stack pointer.\r
MOVW HL, AX \r
MOVW AX, SP \r
MOVW [HL], AX \r
\r
;------------------------------------------------------------------------------\r
; portRESTORE_CONTEXT MACRO\r
-; Restores the context of the Stack Pointer, usCriticalNesting\r
-; value, general purpose registers and the CS and ES (only in far memory mode)\r
+; Restores the task Stack Pointer then use this to restore usCriticalNesting,\r
+; general purpose registers and the CS and ES (only in far memory mode)\r
; of the selected task from the task stack\r
;------------------------------------------------------------------------------\r
-\r
portRESTORE_CONTEXT MACRO\r
- MOVW AX, pxCurrentTCB ; restore the Stack pointer\r
+ MOVW AX, pxCurrentTCB ; Restore the Stack pointer.\r
MOVW HL, AX\r
MOVW AX, [HL]\r
MOVW SP, AX\r
- POP AX ; restore usCriticalNesting value\r
+ POP AX ; Restore usCriticalNesting value.\r
MOVW usCriticalNesting, AX\r
- POP BC ; restore the necessary general purpose registers\r
+ POP BC ; Restore the necessary general purpose registers.\r
POP DE\r
#if configMEMORY_MODE == 1\r
- POP AX ; restore the ES register\r
+ POP AX ; Restore the ES register.\r
MOV ES, A\r
- XCH A, X ; restore the CS register\r
+ XCH A, X ; Restore the CS register.\r
MOV CS, A\r
#else\r
POP AX\r
- MOV CS, A ; restore CS register\r
+ MOV CS, A ; Restore CS register.\r
#endif\r
- POP HL ; restore general purpose register HL\r
- POP AX ; restore AX \r
+ POP HL ; Restore general purpose register HL.\r
+ POP AX ; Restore AX.\r
ENDM\r
;------------------------------------------------------------------------------\r
#include "FreeRTOS.h"\r
#include "task.h"\r
\r
+/* The critical nesting value is initialised to a non zero value to ensure\r
+interrupts don't accidentally become enabled before the scheduler is started. */\r
#define portINITIAL_CRITICAL_NESTING (( unsigned portSHORT ) 10)\r
\r
-/* default Initialization of the PSW for the task:\r
+/* Initial PSW value allocated to a newly created task.\r
* 1100011000000000\r
* ||||||||-------------- Fill byte\r
- * |||||||--------------- Cary Flag cleared\r
+ * |||||||--------------- Carry Flag cleared\r
* |||||----------------- In-service priority Flags set to low level\r
* ||||------------------ Register bank Select 0 Flag cleared\r
- * |||------------------- Auxiliary Cary Flag cleared\r
+ * |||------------------- Auxiliary Carry Flag cleared\r
* ||-------------------- Register bank Select 1 Flag cleared\r
* |--------------------- Zero Flag set\r
* ---------------------- Global Interrupt Flag set (enabled)\r
*/\r
-#define portPSW (0xc6000000UL)\r
+#define portPSW (0xc6UL)\r
\r
/* We require the address of the pxCurrentTCB variable, but don't want to know\r
any details of its type. */\r
\r
#if configMEMORY_MODE == 1\r
{\r
- /* Parameters are passed in on the stack. */\r
+ /* Parameters are passed in on the stack, and written using a 32bit value\r
+ hence a space is left for the second two bytes. */\r
pxTopOfStack--;\r
+\r
+ /* Write in the parameter value. */\r
pulLocal = ( unsigned long * ) pxTopOfStack;\r
*pulLocal = ( unsigned long ) pvParameters;\r
pxTopOfStack--;\r
\r
- /* Dummy values on the stack because there normaly the return address\r
- of the funtion is written. */\r
+ /* These values are just spacers. The return address of the function\r
+ would normally be written here. */\r
*pxTopOfStack = ( portSTACK_TYPE ) 0xcdcd;\r
pxTopOfStack--;\r
*pxTopOfStack = ( portSTACK_TYPE ) 0xcdcd;\r
pxTopOfStack--;\r
\r
- /* Initial PSW value. */\r
-// *pxTopOfStack = portPSW;\r
- \r
+ /* The start address / PSW value is also written in as a 32bit value,\r
+ so leave a space for the second two bytes. */\r
pxTopOfStack--;\r
-\r
\r
- /* Task function start address. */\r
+ /* Task function start address combined with the PSW. */\r
pulLocal = ( unsigned long * ) pxTopOfStack;\r
- *pulLocal = ( ( ( unsigned long ) pxCode ) | portPSW );\r
+ *pulLocal = ( ( ( unsigned long ) pxCode ) | ( portPSW << 24UL ) );\r
pxTopOfStack--;\r
\r
- /* Next general purpose register AX. */\r
+ /* An initial value for the AX register. */\r
*pxTopOfStack = ( portSTACK_TYPE ) 0x1111;\r
pxTopOfStack--;\r
}\r
#else\r
{\r
+ TBD\r
+\r
pxTopOfStack--;\r
\r
/* Task function start address. */\r
}\r
#endif\r
\r
- /* HL. */\r
+ /* An initial value for the HL register. */\r
*pxTopOfStack = ( portSTACK_TYPE ) 0x2222;\r
pxTopOfStack--;\r
\r
pxTopOfStack--;\r
*pxTopOfStack = ( portSTACK_TYPE ) 0xBCBC;\r
pxTopOfStack--;\r
+\r
+ /* Finally the critical section nesting count is set to zero when the task\r
+ first starts. */\r
*pxTopOfStack = ( portSTACK_TYPE ) portNO_CRITICAL_SECTION_NESTING; \r
\r
- /*\r
- * Return a pointer to the top of the stack we have generated so this can\r
- * be stored in the task control block for the task.\r
- */\r
+ /* Return a pointer to the top of the stack we have generated so this can\r
+ be stored in the task control block for the task. */\r
return pxTopOfStack;\r
}\r
/*-----------------------------------------------------------*/\r
\r
void vPortEndScheduler( void )\r
{\r
- /* It is unlikely that the 78K0R/Kx3 port will get stopped. If required simply\r
+ /* It is unlikely that the 78K0R port will get stopped. If required simply\r
disable the tick interrupt here. */\r
}\r
/*-----------------------------------------------------------*/\r
\r
-/*\r
- * Hardware initialisation to generate the RTOS tick. This uses Channel 5 of\r
- * the Timer Array Unit (TAU). Any other Channel could also be used.\r
- */\r
static void prvSetupTimerInterrupt( void )\r
{\r
+ /* Setup channel 5 of the TAU to generate the tick interrupt. */\r
+\r
/* First the Timer Array Unit has to be enabled. */\r
TAU0EN = 1;\r
\r
\r
; Functions implemented in this file\r
;------------------------------------------------------------------------------\r
-\r
PUBLIC vPortYield\r
PUBLIC vPortStart\r
\r
\r
\r
;------------------------------------------------------------------------------\r
-; Port Yield function to check for a Task switch in the cooperative mode\r
+; Yield to another task. Implemented as a software interrupt. The return\r
+; address and PSW will have been saved to the stack automatically before\r
+; this code runs.\r
;\r
; Input: NONE\r
;\r
RSEG CODE:CODE\r
vPortYield:\r
portSAVE_CONTEXT ; Save the context of the current task.\r
- call vTaskSwitchContext ; Call the scheduler.\r
- portRESTORE_CONTEXT ; Restore the context of whichever task the ...\r
- RETB\r
+ call vTaskSwitchContext ; Call the scheduler to select the next task.\r
+ portRESTORE_CONTEXT ; Restore the context of the next task to run.\r
+ retb\r
\r
\r
;------------------------------------------------------------------------------\r
RSEG CODE:CODE\r
vPortStart:\r
portRESTORE_CONTEXT ; Restore the context of whichever task the ...\r
-; POP PSW ; restore active task PSW\r
- reti ; ... scheduler decided should run.\r
+ reti ; An interrupt stack frame is used so the task\r
+ ; is started using a RETI instruction.\r
\r
;------------------------------------------------------------------------------\r
; Perform the necessary steps of the Tick Count Increment and Task Switch\r
; Output: NONE\r
;\r
;------------------------------------------------------------------------------ \r
-#if configUSE_PREEMPTION == 1\r
\r
MD_INTTM05:\r
\r
portSAVE_CONTEXT ; Save the context of the current task.\r
call vTaskIncrementTick ; Call the timer tick function.\r
- call vTaskSwitchContext ; Call the scheduler.\r
- portRESTORE_CONTEXT ; Restore the context of whichever task the ...\r
- RETI\r
-#else\r
-\r
-MD_INTTM05:\r
- PUSH AX ; save necessary general purpose register...\r
- PUSH HL ; ...used by the ISR\r
- MOVW AX, CS ; save CS register\r
- PUSH AX\r
- CALL vTaskIncrementTick ; Call the timer tick function.\r
- POP AX\r
- MOVW CS, AX ; restore CS register\r
- POP HL ; restore used general purpose registers\r
- POP AX\r
- RETI\r
+#if configUSE_PREEMPTION == 1\r
+ call vTaskSwitchContext ; Call the scheduler to select the next task.\r
#endif\r
+ portRESTORE_CONTEXT ; Restore the context of the next task to run.\r
+ reti\r
+\r
+\r
\r
REQUIRE ?CL78K0R_V2_L00\r
- COMMON INTVEC:CODE:ROOT(1) ; set ISR location to the Interrupt vector table\r
+ COMMON INTVEC:CODE:ROOT(1) ; Set ISR location to the Interrupt vector table.\r
ORG 68\r
`??MD_INTTM05??INTVEC 68`:\r
DW MD_INTTM05\r
\r
- COMMON INTVEC:CODE:ROOT(1) ; set ISR location to the Interrupt vector table\r
+ COMMON INTVEC:CODE:ROOT(1) ; Set ISR location to the Interrupt vector table.\r
ORG 126\r
`??vPortYield??INTVEC 126`:\r
DW vPortYield\r
\r
- ; set value for the usCriticalNesting\r
+ ; Set value for the usCriticalNesting.\r
RSEG NEAR_ID:CONST:SORT:NOROOT(1)\r
`?<Initializer for usCriticalNesting>`:\r
DW 10\r