/*-----------------------------------------------------------*/\r
\r
/* System register Definitions. */\r
-#define portSYSTEM_PROGRAM_STATUS_WORD ( (unsigned portBASE_TYPE) 0x000008FF ) /* Supervisor Mode, MPU Register Set 0 and Call Depth Counting disabled. */\r
-#define portINITIAL_PRIVILEGED_PROGRAM_STATUS_WORD ( (unsigned portBASE_TYPE) 0x000014FF ) /* IO Level 1, MPU Register Set 1 and Call Depth Counting disabled. */\r
-#define portINITIAL_UNPRIVILEGED_PROGRAM_STATUS_WORD ( (unsigned portBASE_TYPE) 0x000010FF ) /* IO Level 0, MPU Register Set 1 and Call Depth Counting disabled. */\r
-#define portINITIAL_PCXI_UPPER_CONTEXT_WORD ( (unsigned portBASE_TYPE) 0x00C00000 ) /* The lower 20 bits identify the CSA address. */\r
-#define portINITIAL_SYSCON ( (unsigned portBASE_TYPE) 0x00000000 ) /* MPU Disable. */\r
+#define portSYSTEM_PROGRAM_STATUS_WORD ( 0x000008FFUL ) /* Supervisor Mode, MPU Register Set 0 and Call Depth Counting disabled. */\r
+#define portINITIAL_PRIVILEGED_PROGRAM_STATUS_WORD ( 0x000014FFUL ) /* IO Level 1, MPU Register Set 1 and Call Depth Counting disabled. */\r
+#define portINITIAL_UNPRIVILEGED_PROGRAM_STATUS_WORD ( 0x000010FFUL ) /* IO Level 0, MPU Register Set 1 and Call Depth Counting disabled. */\r
+#define portINITIAL_PCXI_UPPER_CONTEXT_WORD ( 0x00C00000UL ) /* The lower 20 bits identify the CSA address. */\r
+#define portINITIAL_SYSCON ( 0x00000000UL ) /* MPU Disable. */\r
\r
/* CSA manipulation macros. */\r
#define portCSA_FCX_MASK ( 0x000FFFFFUL )\r
\r
/* Each CSA contains 16 words of data. */\r
#define portNUM_WORDS_IN_CSA ( 16 )\r
+\r
+/* The interrupt enable bit in the PCP_SRC register. */\r
+#define portENABLE_CPU_INTERRUPT ( 1U << 12U )\r
/*-----------------------------------------------------------*/\r
\r
/*\r
/*\r
* Trap handler for yields.\r
*/\r
-static void prvPortYield( int iTrapIdentification );\r
+static void prvTrapYield( int iTrapIdentification );\r
+\r
+/*\r
+ * Priority 1 interrupt handler for yields pended from an interrupt.\r
+ */\r
+static void prvInterruptYield( int iTrapIdentification );\r
+\r
/*-----------------------------------------------------------*/\r
\r
/* This reference is required by the save/restore context macros. */\r
if( ( NULL != pulLowerCSA ) && ( NULL != pulUpperCSA ) )\r
{\r
/* Remove the two consumed CSAs from the free CSA list. */\r
+ _disable();\r
+ _dsync();\r
_mtcr( $FCX, pulUpperCSA[ 0 ] );\r
-\r
- /* ISync to commit the change to the FCX. */\r
_isync();\r
+ _enable();\r
}\r
else\r
{\r
portEXIT_CRITICAL();\r
\r
/* Clear the upper CSA. */\r
- memset( pulUpperCSA, 0, portNUM_WORDS_IN_CSA * sizeof( unsigned portBASE_TYPE ) );\r
+ memset( pulUpperCSA, 0, portNUM_WORDS_IN_CSA * sizeof( unsigned long ) );\r
\r
/* Upper Context. */\r
pulUpperCSA[ 2 ] = ( unsigned long )pxTopOfStack; /* A10; Stack Return aka Stack Pointer */\r
pulUpperCSA[ 1 ] = portSYSTEM_PROGRAM_STATUS_WORD; /* PSW */\r
\r
/* Clear the lower CSA. */\r
- memset( pulLowerCSA, 0, portNUM_WORDS_IN_CSA * sizeof( unsigned portBASE_TYPE ) );\r
+ memset( pulLowerCSA, 0, portNUM_WORDS_IN_CSA * sizeof( unsigned long ) );\r
\r
/* Lower Context. */\r
pulLowerCSA[ 8 ] = ( unsigned long ) pvParameters; /* A4; Address Type Parameter Register */\r
}\r
/*-----------------------------------------------------------*/\r
\r
-portBASE_TYPE xPortStartScheduler( void )\r
+long xPortStartScheduler( void )\r
{\r
extern void vTrapInstallHandlers( void );\r
unsigned long ulMFCR = 0UL;\r
unsigned long *pulUpperCSA = NULL;\r
unsigned long *pulLowerCSA = NULL;\r
\r
+ /* Interrupts at or below configMAX_SYSCALL_INTERRUPT_PRIORITY are disable\r
+ when this function is called. */\r
+\r
/* Set-up the timer interrupt. */\r
prvSetupTimerInterrupt();\r
\r
/* Install the Trap Handlers. */\r
vTrapInstallHandlers();\r
\r
- /* Install the Syscall Handler. */\r
- if( 0 == _install_trap_handler( portSYSCALL_TRAP, prvPortYield ) )\r
+ /* Install the Syscall Handler for yield calls. */\r
+ if( 0 == _install_trap_handler( portSYSCALL_TRAP, prvTrapYield ) )\r
+ {\r
+ /* Failed to install the yield handler, force an assert. */\r
+ configASSERT( ( ( volatile void * ) NULL ) );\r
+ }\r
+\r
+ /* Enable then install the priority 1 interrupt for pending context\r
+ switches from an ISR. See mod_SRC in the TriCore manual. */\r
+ CPU_SRC0.reg = ( portENABLE_CPU_INTERRUPT ) | ( configKERNEL_YIELD_PRIORITY );\r
+ if( 0 == _install_int_handler( configKERNEL_YIELD_PRIORITY, prvInterruptYield, 0 ) )\r
{\r
/* Failed to install the yield handler, force an assert. */\r
configASSERT( ( ( volatile void * ) NULL ) );\r
}\r
\r
+ _disable();\r
+\r
/* Load the initial SYSCON. */\r
- _dsync();\r
_mtcr( $SYSCON, portINITIAL_SYSCON );\r
+ _isync();\r
\r
/* ENDINIT has already been applied in the 'cstart.c' code. */\r
\r
exception because this code is not genuinely in an exception. */\r
ulMFCR = _mfcr( $PSW );\r
ulMFCR &= portRESTORE_PSW_MASK;\r
+ _dsync();\r
_mtcr( $PSW, ulMFCR );\r
+ _isync();\r
\r
/* Finally, perform the equivalent of a portRESTORE_CONTEXT() */\r
pulLowerCSA = portCSA_TO_ADDRESS( ( *pxCurrentTCB ) );\r
pulUpperCSA = portCSA_TO_ADDRESS( pulLowerCSA[0] );\r
- _mtcr( $PCXI, *pxCurrentTCB );\r
-\r
_dsync();\r
+ _mtcr( $PCXI, *pxCurrentTCB );\r
+ _isync();\r
_nop();\r
_rslcx();\r
_nop();\r
static void prvSystemTickHandler( int iArg )\r
{\r
unsigned long ulSavedInterruptMask;\r
+unsigned long *pxUpperCSA = NULL;\r
+unsigned long xUpperCSA = 0UL;\r
+extern volatile unsigned long *pxCurrentTCB;\r
+\r
+COUNT_NEST();\r
\r
/* Just to avoid compiler warnings about unused parameters. */\r
( void ) iArg;\r
\r
#if configUSE_PREEMPTION == 1\r
{\r
- portYIELD_FROM_ISR( pdTRUE );\r
+ /* Save the context of a task.\r
+ The upper context is automatically saved when entering a trap or interrupt.\r
+ Need to save the lower context as well and copy the PCXI CSA ID into\r
+ pxCurrentTCB->pxTopOfStack. Only Lower Context CSA IDs may be saved to the\r
+ TCB of a task.\r
+\r
+ Call vTaskSwitchContext to select the next task, note that this changes the\r
+ value of pxCurrentTCB so that it needs to be reloaded.\r
+\r
+ Call vPortSetMPURegisterSetOne to change the MPU mapping for the task\r
+ that has just been switched in.\r
+\r
+ Load the context of the task.\r
+ Need to restore the lower context by loading the CSA from\r
+ pxCurrentTCB->pxTopOfStack into PCXI (effectively changing the call stack).\r
+ In the Interrupt handler post-amble, RSLCX will restore the lower context\r
+ of the task. RFE will restore the upper context of the task, jump to the\r
+ return address and restore the previous state of interrupts being\r
+ enabled/disabled. */\r
+ _disable();\r
+ _dsync();\r
+ xUpperCSA = _mfcr( $PCXI );\r
+ pxUpperCSA = portCSA_TO_ADDRESS( xUpperCSA );\r
+ *pxCurrentTCB = pxUpperCSA[ 0 ];\r
+ vTaskSwitchContext();\r
+ pxUpperCSA[ 0 ] = *pxCurrentTCB;\r
+ CPU_SRC0.bits.SETR = 0;\r
+ _isync();\r
}\r
+ulNest--;\r
#endif\r
}\r
/*-----------------------------------------------------------*/\r
* than they can be freed assuming that tasks are being spawned and\r
* deleted frequently.\r
*/\r
-void vPortReclaimCSA( unsigned portBASE_TYPE *pxTCB )\r
+void vPortReclaimCSA( unsigned long *pxTCB )\r
{\r
-unsigned portBASE_TYPE pxHeadCSA, pxTailCSA, pxFreeCSA;\r
-unsigned portBASE_TYPE *pulNextCSA;\r
+unsigned long pxHeadCSA, pxTailCSA, pxFreeCSA;\r
+unsigned long *pulNextCSA;\r
\r
/* A pointer to the first CSA in the list of CSAs consumed by the task is\r
stored in the first element of the tasks TCB structure (where the stack\r
pulNextCSA = portCSA_TO_ADDRESS( pxTailCSA );\r
}\r
\r
- taskENTER_CRITICAL();\r
+ _disable();\r
{\r
/* Look up the current free CSA head. */\r
_dsync();\r
/* Move the head of the reclaimed into the Free. */\r
_dsync();\r
_mtcr( $FCX, pxHeadCSA );\r
-\r
- /* ISync to commit the change to the FCX. */\r
_isync();\r
}\r
- taskEXIT_CRITICAL();\r
+ _enable();\r
}\r
/*-----------------------------------------------------------*/\r
\r
}\r
/*-----------------------------------------------------------*/\r
\r
-static void prvPortYield( int iTrapIdentification )\r
+static void prvTrapYield( int iTrapIdentification )\r
{\r
+unsigned long *pxUpperCSA = NULL;\r
+unsigned long xUpperCSA = 0UL;\r
+extern volatile unsigned long *pxCurrentTCB;\r
+\r
switch( iTrapIdentification )\r
{\r
case portSYSCALL_TASK_YIELD:\r
- /* Select another task to run. */\r
- portYIELD_FROM_ISR( pdTRUE );\r
+ /* Save the context of a task.\r
+ The upper context is automatically saved when entering a trap or interrupt.\r
+ Need to save the lower context as well and copy the PCXI CSA ID into\r
+ pxCurrentTCB->pxTopOfStack. Only Lower Context CSA IDs may be saved to the\r
+ TCB of a task.\r
+\r
+ Call vTaskSwitchContext to select the next task, note that this changes the\r
+ value of pxCurrentTCB so that it needs to be reloaded.\r
+\r
+ Call vPortSetMPURegisterSetOne to change the MPU mapping for the task\r
+ that has just been switched in.\r
+\r
+ Load the context of the task.\r
+ Need to restore the lower context by loading the CSA from\r
+ pxCurrentTCB->pxTopOfStack into PCXI (effectively changing the call stack).\r
+ In the Interrupt handler post-amble, RSLCX will restore the lower context\r
+ of the task. RFE will restore the upper context of the task, jump to the\r
+ return address and restore the previous state of interrupts being\r
+ enabled/disabled. */\r
+ _disable();\r
+ _dsync();\r
+ xUpperCSA = _mfcr( $PCXI );\r
+ pxUpperCSA = portCSA_TO_ADDRESS( xUpperCSA );\r
+ *pxCurrentTCB = pxUpperCSA[ 0 ];\r
+ vTaskSwitchContext();\r
+ pxUpperCSA[ 0 ] = *pxCurrentTCB;\r
+ CPU_SRC0.bits.SETR = 0;\r
+ _isync();\r
break;\r
\r
default:\r
}\r
/*-----------------------------------------------------------*/\r
\r
-unsigned portBASE_TYPE uxPortSetInterruptMaskFromISR( void )\r
+static void prvInterruptYield( int iId )\r
{\r
-unsigned portBASE_TYPE uxReturn = 0UL;\r
+unsigned long *pxUpperCSA = NULL;\r
+unsigned long xUpperCSA = 0UL;\r
+extern volatile unsigned long *pxCurrentTCB;\r
+COUNT_NEST();\r
+ /* Just to remove compiler warnings. */\r
+ ( void ) iId;\r
+\r
+ /* Save the context of a task.\r
+ The upper context is automatically saved when entering a trap or interrupt.\r
+ Need to save the lower context as well and copy the PCXI CSA ID into\r
+ pxCurrentTCB->pxTopOfStack. Only Lower Context CSA IDs may be saved to the\r
+ TCB of a task.\r
+\r
+ Call vTaskSwitchContext to select the next task, note that this changes the\r
+ value of pxCurrentTCB so that it needs to be reloaded.\r
+\r
+ Call vPortSetMPURegisterSetOne to change the MPU mapping for the task\r
+ that has just been switched in.\r
+\r
+ Load the context of the task.\r
+ Need to restore the lower context by loading the CSA from\r
+ pxCurrentTCB->pxTopOfStack into PCXI (effectively changing the call stack).\r
+ In the Interrupt handler post-amble, RSLCX will restore the lower context\r
+ of the task. RFE will restore the upper context of the task, jump to the\r
+ return address and restore the previous state of interrupts being\r
+ enabled/disabled. */\r
+ _disable();\r
+ _dsync();\r
+ xUpperCSA = _mfcr( $PCXI );\r
+ pxUpperCSA = portCSA_TO_ADDRESS( xUpperCSA );\r
+ *pxCurrentTCB = pxUpperCSA[ 0 ];\r
+ vTaskSwitchContext();\r
+ pxUpperCSA[ 0 ] = *pxCurrentTCB;\r
+ CPU_SRC0.bits.SETR = 0;\r
+ _isync();\r
+ulNest--;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+unsigned long uxPortSetInterruptMaskFromISR( void )\r
+{\r
+unsigned long uxReturn = 0UL;\r
\r
+ _disable();\r
uxReturn = _mfcr( $ICR );\r
_mtcr( $ICR, ( ( uxReturn & ~portCCPN_MASK ) | configMAX_SYSCALL_INTERRUPT_PRIORITY ) );\r
+ _isync();\r
+ _enable();\r
\r
+ /* Return just the interrupt mask bits. */\r
return ( uxReturn & portCCPN_MASK );\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vPortClearInterruptMaskFromISR( unsigned portBASE_TYPE uxSavedStatusValue )\r
-{\r
- _mtcr( $ICR, ( uxSavedStatusValue & portCCPN_MASK ) );\r
-}\r
-/*-----------------------------------------------------------*/\r
\r
#define portEXIT_CRITICAL() vTaskExitCritical()\r
/*---------------------------------------------------------------------------*/\r
\r
-/* Task utilities. */\r
-\r
-extern void vPortReclaimCSA( unsigned portBASE_TYPE *pxTCB );\r
-\r
/* CSA Manipulation. */\r
-#define portCSA_TO_ADDRESS( pCSA ) ( ( unsigned portBASE_TYPE * )( ( ( ( pCSA ) & 0x000F0000 ) << 12 ) | ( ( ( pCSA ) & 0x0000FFFF ) << 6 ) ) )\r
-#define portADDRESS_TO_CSA( pAddress ) ( ( unsigned portBASE_TYPE )( ( ( ( (unsigned portBASE_TYPE)( pAddress ) ) & 0xF0000000 ) >> 12 ) | ( ( (unsigned portBASE_TYPE)( pAddress ) & 0x003FFFC0 ) >> 6 ) ) )\r
+#define portCSA_TO_ADDRESS( pCSA ) ( ( unsigned long * )( ( ( ( pCSA ) & 0x000F0000 ) << 12 ) | ( ( ( pCSA ) & 0x0000FFFF ) << 6 ) ) )\r
+#define portADDRESS_TO_CSA( pAddress ) ( ( unsigned long )( ( ( ( (unsigned long)( pAddress ) ) & 0xF0000000 ) >> 12 ) | ( ( ( unsigned long )( pAddress ) & 0x003FFFC0 ) >> 6 ) ) )\r
/*---------------------------------------------------------------------------*/\r
\r
-#define portYIELD() _syscall(0)\r
+#define portYIELD() _syscall( 0 )\r
/* Port Restore is implicit in the platform when the function is returned from the original PSW is automatically replaced. */\r
#define portSYSCALL_TASK_YIELD 0\r
#define portSYSCALL_RAISE_PRIORITY 1\r
\r
/* Critical section management. */\r
\r
-/* Clear the ICR.IE bit. */\r
-#define portDISABLE_INTERRUPTS() _mtcr( $ICR, ( ( _mfcr( $ICR ) & ~portCCPN_MASK ) | configMAX_SYSCALL_INTERRUPT_PRIORITY ) )\r
-\r
-/* Set the ICR.IE bit. */\r
-#define portENABLE_INTERRUPTS() { unsigned long ulCurrentICR = _mfcr( $ICR ); _mtcr( $ICR, ( ulCurrentICR & ~portCCPN_MASK ) ) }\r
+/* Set ICR.CCPN to configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
+#define portDISABLE_INTERRUPTS() { \\r
+ unsigned long ulICR; \\r
+ _disable(); \\r
+ ulICR = _mfcr( $ICR ); /* Get current ICR value. */ \\r
+ ulICR &= ~portCCPN_MASK; /* Clear down mask bits. */ \\r
+ ulICR |= configMAX_SYSCALL_INTERRUPT_PRIORITY; /* Set mask bits to required priority mask. */ \\r
+ _mtcr( $ICR, ulICR ); /* Write back updated ICR. */ \\r
+ _isync(); \\r
+ _enable(); \\r
+ }\r
+\r
+/* Clear ICR.CCPN to allow all interrupt priorities. */\r
+#define portENABLE_INTERRUPTS() { \\r
+ unsigned long ulICR; \\r
+ _disable(); \\r
+ ulICR = _mfcr( $ICR ); /* Get current ICR value. */ \\r
+ ulICR &= ~portCCPN_MASK; /* Clear down mask bits. */ \\r
+ _mtcr( $ICR, ulICR ); /* Write back updated ICR. */ \\r
+ _isync(); \\r
+ _enable(); \\r
+ }\r
+\r
+/* Set ICR.CCPN to uxSavedMaskValue. */\r
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedMaskValue ) { \\r
+ unsigned long ulICR; \\r
+ _disable(); \\r
+ ulICR = _mfcr( $ICR ); /* Get current ICR value. */ \\r
+ ulICR &= ~portCCPN_MASK; /* Clear down mask bits. */ \\r
+ ulICR |= uxSavedMaskValue; /* Set mask bits to previously saved mask value. */ \\r
+ _mtcr( $ICR, ulICR ); /* Write back updated ICR. */ \\r
+ _isync(); \\r
+ _enable(); \\r
+ }\r
\r
-extern unsigned portBASE_TYPE uxPortSetInterruptMaskFromISR( void );\r
-extern void vPortClearInterruptMaskFromISR( unsigned portBASE_TYPE uxSavedStatusValue );\r
\r
/* Set ICR.CCPN to configMAX_SYSCALL_INTERRUPT_PRIORITY */\r
+extern unsigned long uxPortSetInterruptMaskFromISR( void );\r
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMaskFromISR()\r
\r
-/* Set ICR.CCPN to uxSavedInterruptStatus */\r
-#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) vPortClearInterruptMaskFromISR( uxSavedStatusValue )\r
-\r
/* As this port holds a CSA address in pxTopOfStack, the assert that checks the\r
pxTopOfStack alignment is removed. */\r
#define portALIGNMENT_ASSERT_pxCurrentTCB ( void )\r
\r
-/*---------------------------------------------------------------------------*/\r
+/* Pend a priority 1 interrupt, which will take care of the context switch. */\r
+#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken != pdFALSE ) { CPU_SRC0.bits.SETR = 1; _isync(); }\r
\r
-/*\r
- * Save the context of a task.\r
- * The upper context is automatically saved when entering a trap or interrupt.\r
- * Need to save the lower context as well and copy the PCXI CSA ID into\r
- * pxCurrentTCB->pxTopOfStack. Only Lower Context CSA IDs may be saved to the\r
- * TCB of a task.\r
- *\r
- * Call vTaskSwitchContext to select the next task, note that this changes the\r
- * value of pxCurrentTCB so that it needs to be reloaded.\r
- *\r
- * Call vPortSetMPURegisterSetOne to change the MPU mapping for the task\r
- * that has just been switched in.\r
- *\r
- * Load the context of the task.\r
- * Need to restore the lower context by loading the CSA from\r
- * pxCurrentTCB->pxTopOfStack into PCXI (effectively changing the call stack).\r
- * In the Interrupt handler post-amble, RSLCX will restore the lower context\r
- * of the task. RFE will restore the upper context of the task, jump to the\r
- * return address and restore the previous state of interrupts being\r
- * enabled/disabled.\r
- */\r
-#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) \\r
-{ \\r
-unsigned portBASE_TYPE *pxUpperCSA = NULL; \\r
-unsigned portBASE_TYPE xUpperCSA = 0UL; \\r
-extern volatile unsigned long *pxCurrentTCB; \\r
- if ( pdTRUE == xHigherPriorityTaskWoken ) \\r
- { \\r
- _disable(); \\r
- _isync(); \\r
- xUpperCSA = _mfcr( $PCXI ); \\r
- pxUpperCSA = portCSA_TO_ADDRESS( xUpperCSA ); \\r
- *pxCurrentTCB = pxUpperCSA[0]; \\r
- vTaskSwitchContext(); \\r
- pxUpperCSA[0] = *pxCurrentTCB; \\r
- _dsync(); \\r
- _isync(); \\r
- _nop(); \\r
- _nop(); \\r
- } \\r
-}\r
/*---------------------------------------------------------------------------*/\r
\r
/* Task function macros as described on the FreeRTOS.org WEB site. */\r
* Port specific clean up macro required to free the CSAs that were consumed by\r
* a task that has since been deleted.\r
*/\r
-void vPortReclaimCSA( unsigned portBASE_TYPE *pxTCB );\r
-#define portCLEAN_UP_TCB( pxTCB ) vPortReclaimCSA( ( unsigned portBASE_TYPE *) ( pxTCB ) )\r
+void vPortReclaimCSA( unsigned long *pxTCB );\r
+#define portCLEAN_UP_TCB( pxTCB ) vPortReclaimCSA( ( unsigned long * ) ( pxTCB ) )\r
\r
#ifdef __cplusplus\r
}\r