Latest TriCore port files - these still contain some debug code, and are not yet fully documented.

pull/4/head
Richard Barry 13 years ago
parent 93c4c48f78
commit b89f1a729a

@ -75,11 +75,11 @@
/*-----------------------------------------------------------*/
/* System register Definitions. */
#define portSYSTEM_PROGRAM_STATUS_WORD ( (unsigned portBASE_TYPE) 0x000008FF ) /* Supervisor Mode, MPU Register Set 0 and Call Depth Counting disabled. */
#define portINITIAL_PRIVILEGED_PROGRAM_STATUS_WORD ( (unsigned portBASE_TYPE) 0x000014FF ) /* IO Level 1, MPU Register Set 1 and Call Depth Counting disabled. */
#define portINITIAL_UNPRIVILEGED_PROGRAM_STATUS_WORD ( (unsigned portBASE_TYPE) 0x000010FF ) /* IO Level 0, MPU Register Set 1 and Call Depth Counting disabled. */
#define portINITIAL_PCXI_UPPER_CONTEXT_WORD ( (unsigned portBASE_TYPE) 0x00C00000 ) /* The lower 20 bits identify the CSA address. */
#define portINITIAL_SYSCON ( (unsigned portBASE_TYPE) 0x00000000 ) /* MPU Disable. */
#define portSYSTEM_PROGRAM_STATUS_WORD ( 0x000008FFUL ) /* Supervisor Mode, MPU Register Set 0 and Call Depth Counting disabled. */
#define portINITIAL_PRIVILEGED_PROGRAM_STATUS_WORD ( 0x000014FFUL ) /* IO Level 1, MPU Register Set 1 and Call Depth Counting disabled. */
#define portINITIAL_UNPRIVILEGED_PROGRAM_STATUS_WORD ( 0x000010FFUL ) /* IO Level 0, MPU Register Set 1 and Call Depth Counting disabled. */
#define portINITIAL_PCXI_UPPER_CONTEXT_WORD ( 0x00C00000UL ) /* The lower 20 bits identify the CSA address. */
#define portINITIAL_SYSCON ( 0x00000000UL ) /* MPU Disable. */
/* CSA manipulation macros. */
#define portCSA_FCX_MASK ( 0x000FFFFFUL )
@ -90,6 +90,9 @@
/* Each CSA contains 16 words of data. */
#define portNUM_WORDS_IN_CSA ( 16 )
/* The interrupt enable bit in the PCP_SRC register. */
#define portENABLE_CPU_INTERRUPT ( 1U << 12U )
/*-----------------------------------------------------------*/
/*
@ -101,7 +104,13 @@ static void prvSetupTimerInterrupt( void );
/*
* Trap handler for yields.
*/
static void prvPortYield( int iTrapIdentification );
static void prvTrapYield( int iTrapIdentification );
/*
* Priority 1 interrupt handler for yields pended from an interrupt.
*/
static void prvInterruptYield( int iTrapIdentification );
/*-----------------------------------------------------------*/
/* This reference is required by the save/restore context macros. */
@ -153,10 +162,11 @@ unsigned long *pulLowerCSA = NULL;
if( ( NULL != pulLowerCSA ) && ( NULL != pulUpperCSA ) )
{
/* Remove the two consumed CSAs from the free CSA list. */
_disable();
_dsync();
_mtcr( $FCX, pulUpperCSA[ 0 ] );
/* ISync to commit the change to the FCX. */
_isync();
_enable();
}
else
{
@ -167,14 +177,14 @@ unsigned long *pulLowerCSA = NULL;
portEXIT_CRITICAL();
/* Clear the upper CSA. */
memset( pulUpperCSA, 0, portNUM_WORDS_IN_CSA * sizeof( unsigned portBASE_TYPE ) );
memset( pulUpperCSA, 0, portNUM_WORDS_IN_CSA * sizeof( unsigned long ) );
/* Upper Context. */
pulUpperCSA[ 2 ] = ( unsigned long )pxTopOfStack; /* A10; Stack Return aka Stack Pointer */
pulUpperCSA[ 1 ] = portSYSTEM_PROGRAM_STATUS_WORD; /* PSW */
/* Clear the lower CSA. */
memset( pulLowerCSA, 0, portNUM_WORDS_IN_CSA * sizeof( unsigned portBASE_TYPE ) );
memset( pulLowerCSA, 0, portNUM_WORDS_IN_CSA * sizeof( unsigned long ) );
/* Lower Context. */
pulLowerCSA[ 8 ] = ( unsigned long ) pvParameters; /* A4; Address Type Parameter Register */
@ -193,29 +203,43 @@ unsigned long *pulLowerCSA = NULL;
}
/*-----------------------------------------------------------*/
portBASE_TYPE xPortStartScheduler( void )
long xPortStartScheduler( void )
{
extern void vTrapInstallHandlers( void );
unsigned long ulMFCR = 0UL;
unsigned long *pulUpperCSA = NULL;
unsigned long *pulLowerCSA = NULL;
/* Interrupts at or below configMAX_SYSCALL_INTERRUPT_PRIORITY are disable
when this function is called. */
/* Set-up the timer interrupt. */
prvSetupTimerInterrupt();
/* Install the Trap Handlers. */
vTrapInstallHandlers();
/* Install the Syscall Handler. */
if( 0 == _install_trap_handler( portSYSCALL_TRAP, prvPortYield ) )
/* Install the Syscall Handler for yield calls. */
if( 0 == _install_trap_handler( portSYSCALL_TRAP, prvTrapYield ) )
{
/* Failed to install the yield handler, force an assert. */
configASSERT( ( ( volatile void * ) NULL ) );
}
/* Enable then install the priority 1 interrupt for pending context
switches from an ISR. See mod_SRC in the TriCore manual. */
CPU_SRC0.reg = ( portENABLE_CPU_INTERRUPT ) | ( configKERNEL_YIELD_PRIORITY );
if( 0 == _install_int_handler( configKERNEL_YIELD_PRIORITY, prvInterruptYield, 0 ) )
{
/* Failed to install the yield handler, force an assert. */
configASSERT( ( ( volatile void * ) NULL ) );
}
_disable();
/* Load the initial SYSCON. */
_dsync();
_mtcr( $SYSCON, portINITIAL_SYSCON );
_isync();
/* ENDINIT has already been applied in the 'cstart.c' code. */
@ -223,14 +247,16 @@ unsigned long *pulLowerCSA = NULL;
exception because this code is not genuinely in an exception. */
ulMFCR = _mfcr( $PSW );
ulMFCR &= portRESTORE_PSW_MASK;
_dsync();
_mtcr( $PSW, ulMFCR );
_isync();
/* Finally, perform the equivalent of a portRESTORE_CONTEXT() */
pulLowerCSA = portCSA_TO_ADDRESS( ( *pxCurrentTCB ) );
pulUpperCSA = portCSA_TO_ADDRESS( pulLowerCSA[0] );
_mtcr( $PCXI, *pxCurrentTCB );
_dsync();
_mtcr( $PCXI, *pxCurrentTCB );
_isync();
_nop();
_rslcx();
_nop();
@ -285,6 +311,11 @@ static void prvSetupTimerInterrupt( void )
static void prvSystemTickHandler( int iArg )
{
unsigned long ulSavedInterruptMask;
unsigned long *pxUpperCSA = NULL;
unsigned long xUpperCSA = 0UL;
extern volatile unsigned long *pxCurrentTCB;
COUNT_NEST();
/* Just to avoid compiler warnings about unused parameters. */
( void ) iArg;
@ -321,8 +352,36 @@ unsigned long ulSavedInterruptMask;
#if configUSE_PREEMPTION == 1
{
portYIELD_FROM_ISR( pdTRUE );
/* Save the context of a task.
The upper context is automatically saved when entering a trap or interrupt.
Need to save the lower context as well and copy the PCXI CSA ID into
pxCurrentTCB->pxTopOfStack. Only Lower Context CSA IDs may be saved to the
TCB of a task.
Call vTaskSwitchContext to select the next task, note that this changes the
value of pxCurrentTCB so that it needs to be reloaded.
Call vPortSetMPURegisterSetOne to change the MPU mapping for the task
that has just been switched in.
Load the context of the task.
Need to restore the lower context by loading the CSA from
pxCurrentTCB->pxTopOfStack into PCXI (effectively changing the call stack).
In the Interrupt handler post-amble, RSLCX will restore the lower context
of the task. RFE will restore the upper context of the task, jump to the
return address and restore the previous state of interrupts being
enabled/disabled. */
_disable();
_dsync();
xUpperCSA = _mfcr( $PCXI );
pxUpperCSA = portCSA_TO_ADDRESS( xUpperCSA );
*pxCurrentTCB = pxUpperCSA[ 0 ];
vTaskSwitchContext();
pxUpperCSA[ 0 ] = *pxCurrentTCB;
CPU_SRC0.bits.SETR = 0;
_isync();
}
ulNest--;
#endif
}
/*-----------------------------------------------------------*/
@ -345,10 +404,10 @@ unsigned long ulSavedInterruptMask;
* than they can be freed assuming that tasks are being spawned and
* deleted frequently.
*/
void vPortReclaimCSA( unsigned portBASE_TYPE *pxTCB )
void vPortReclaimCSA( unsigned long *pxTCB )
{
unsigned portBASE_TYPE pxHeadCSA, pxTailCSA, pxFreeCSA;
unsigned portBASE_TYPE *pulNextCSA;
unsigned long pxHeadCSA, pxTailCSA, pxFreeCSA;
unsigned long *pulNextCSA;
/* A pointer to the first CSA in the list of CSAs consumed by the task is
stored in the first element of the tasks TCB structure (where the stack
@ -382,7 +441,7 @@ unsigned portBASE_TYPE *pulNextCSA;
pulNextCSA = portCSA_TO_ADDRESS( pxTailCSA );
}
taskENTER_CRITICAL();
_disable();
{
/* Look up the current free CSA head. */
_dsync();
@ -394,11 +453,9 @@ unsigned portBASE_TYPE *pulNextCSA;
/* Move the head of the reclaimed into the Free. */
_dsync();
_mtcr( $FCX, pxHeadCSA );
/* ISync to commit the change to the FCX. */
_isync();
}
taskEXIT_CRITICAL();
_enable();
}
/*-----------------------------------------------------------*/
@ -408,13 +465,43 @@ void vPortEndScheduler( void )
}
/*-----------------------------------------------------------*/
static void prvPortYield( int iTrapIdentification )
static void prvTrapYield( int iTrapIdentification )
{
unsigned long *pxUpperCSA = NULL;
unsigned long xUpperCSA = 0UL;
extern volatile unsigned long *pxCurrentTCB;
switch( iTrapIdentification )
{
case portSYSCALL_TASK_YIELD:
/* Select another task to run. */
portYIELD_FROM_ISR( pdTRUE );
/* Save the context of a task.
The upper context is automatically saved when entering a trap or interrupt.
Need to save the lower context as well and copy the PCXI CSA ID into
pxCurrentTCB->pxTopOfStack. Only Lower Context CSA IDs may be saved to the
TCB of a task.
Call vTaskSwitchContext to select the next task, note that this changes the
value of pxCurrentTCB so that it needs to be reloaded.
Call vPortSetMPURegisterSetOne to change the MPU mapping for the task
that has just been switched in.
Load the context of the task.
Need to restore the lower context by loading the CSA from
pxCurrentTCB->pxTopOfStack into PCXI (effectively changing the call stack).
In the Interrupt handler post-amble, RSLCX will restore the lower context
of the task. RFE will restore the upper context of the task, jump to the
return address and restore the previous state of interrupts being
enabled/disabled. */
_disable();
_dsync();
xUpperCSA = _mfcr( $PCXI );
pxUpperCSA = portCSA_TO_ADDRESS( xUpperCSA );
*pxCurrentTCB = pxUpperCSA[ 0 ];
vTaskSwitchContext();
pxUpperCSA[ 0 ] = *pxCurrentTCB;
CPU_SRC0.bits.SETR = 0;
_isync();
break;
default:
@ -425,20 +512,60 @@ static void prvPortYield( int iTrapIdentification )
}
/*-----------------------------------------------------------*/
unsigned portBASE_TYPE uxPortSetInterruptMaskFromISR( void )
static void prvInterruptYield( int iId )
{
unsigned portBASE_TYPE uxReturn = 0UL;
unsigned long *pxUpperCSA = NULL;
unsigned long xUpperCSA = 0UL;
extern volatile unsigned long *pxCurrentTCB;
COUNT_NEST();
/* Just to remove compiler warnings. */
( void ) iId;
/* Save the context of a task.
The upper context is automatically saved when entering a trap or interrupt.
Need to save the lower context as well and copy the PCXI CSA ID into
pxCurrentTCB->pxTopOfStack. Only Lower Context CSA IDs may be saved to the
TCB of a task.
Call vTaskSwitchContext to select the next task, note that this changes the
value of pxCurrentTCB so that it needs to be reloaded.
Call vPortSetMPURegisterSetOne to change the MPU mapping for the task
that has just been switched in.
Load the context of the task.
Need to restore the lower context by loading the CSA from
pxCurrentTCB->pxTopOfStack into PCXI (effectively changing the call stack).
In the Interrupt handler post-amble, RSLCX will restore the lower context
of the task. RFE will restore the upper context of the task, jump to the
return address and restore the previous state of interrupts being
enabled/disabled. */
_disable();
_dsync();
xUpperCSA = _mfcr( $PCXI );
pxUpperCSA = portCSA_TO_ADDRESS( xUpperCSA );
*pxCurrentTCB = pxUpperCSA[ 0 ];
vTaskSwitchContext();
pxUpperCSA[ 0 ] = *pxCurrentTCB;
CPU_SRC0.bits.SETR = 0;
_isync();
ulNest--;
}
/*-----------------------------------------------------------*/
unsigned long uxPortSetInterruptMaskFromISR( void )
{
unsigned long uxReturn = 0UL;
_disable();
uxReturn = _mfcr( $ICR );
_mtcr( $ICR, ( ( uxReturn & ~portCCPN_MASK ) | configMAX_SYSCALL_INTERRUPT_PRIORITY ) );
_isync();
_enable();
/* Return just the interrupt mask bits. */
return ( uxReturn & portCCPN_MASK );
}
/*-----------------------------------------------------------*/
void vPortClearInterruptMaskFromISR( unsigned portBASE_TYPE uxSavedStatusValue )
{
_mtcr( $ICR, ( uxSavedStatusValue & portCCPN_MASK ) );
}
/*-----------------------------------------------------------*/

@ -114,16 +114,12 @@ extern void vTaskExitCritical( void );
#define portEXIT_CRITICAL() vTaskExitCritical()
/*---------------------------------------------------------------------------*/
/* Task utilities. */
extern void vPortReclaimCSA( unsigned portBASE_TYPE *pxTCB );
/* CSA Manipulation. */
#define portCSA_TO_ADDRESS( pCSA ) ( ( unsigned portBASE_TYPE * )( ( ( ( pCSA ) & 0x000F0000 ) << 12 ) | ( ( ( pCSA ) & 0x0000FFFF ) << 6 ) ) )
#define portADDRESS_TO_CSA( pAddress ) ( ( unsigned portBASE_TYPE )( ( ( ( (unsigned portBASE_TYPE)( pAddress ) ) & 0xF0000000 ) >> 12 ) | ( ( (unsigned portBASE_TYPE)( pAddress ) & 0x003FFFC0 ) >> 6 ) ) )
#define portCSA_TO_ADDRESS( pCSA ) ( ( unsigned long * )( ( ( ( pCSA ) & 0x000F0000 ) << 12 ) | ( ( ( pCSA ) & 0x0000FFFF ) << 6 ) ) )
#define portADDRESS_TO_CSA( pAddress ) ( ( unsigned long )( ( ( ( (unsigned long)( pAddress ) ) & 0xF0000000 ) >> 12 ) | ( ( ( unsigned long )( pAddress ) & 0x003FFFC0 ) >> 6 ) ) )
/*---------------------------------------------------------------------------*/
#define portYIELD() _syscall(0)
#define portYIELD() _syscall( 0 )
/* Port Restore is implicit in the platform when the function is returned from the original PSW is automatically replaced. */
#define portSYSCALL_TASK_YIELD 0
#define portSYSCALL_RAISE_PRIORITY 1
@ -131,68 +127,53 @@ extern void vPortReclaimCSA( unsigned portBASE_TYPE *pxTCB );
/* Critical section management. */
/* Clear the ICR.IE bit. */
#define portDISABLE_INTERRUPTS() _mtcr( $ICR, ( ( _mfcr( $ICR ) & ~portCCPN_MASK ) | configMAX_SYSCALL_INTERRUPT_PRIORITY ) )
/* Set the ICR.IE bit. */
#define portENABLE_INTERRUPTS() { unsigned long ulCurrentICR = _mfcr( $ICR ); _mtcr( $ICR, ( ulCurrentICR & ~portCCPN_MASK ) ) }
/* Set ICR.CCPN to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
#define portDISABLE_INTERRUPTS() { \
unsigned long ulICR; \
_disable(); \
ulICR = _mfcr( $ICR ); /* Get current ICR value. */ \
ulICR &= ~portCCPN_MASK; /* Clear down mask bits. */ \
ulICR |= configMAX_SYSCALL_INTERRUPT_PRIORITY; /* Set mask bits to required priority mask. */ \
_mtcr( $ICR, ulICR ); /* Write back updated ICR. */ \
_isync(); \
_enable(); \
}
/* Clear ICR.CCPN to allow all interrupt priorities. */
#define portENABLE_INTERRUPTS() { \
unsigned long ulICR; \
_disable(); \
ulICR = _mfcr( $ICR ); /* Get current ICR value. */ \
ulICR &= ~portCCPN_MASK; /* Clear down mask bits. */ \
_mtcr( $ICR, ulICR ); /* Write back updated ICR. */ \
_isync(); \
_enable(); \
}
/* Set ICR.CCPN to uxSavedMaskValue. */
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedMaskValue ) { \
unsigned long ulICR; \
_disable(); \
ulICR = _mfcr( $ICR ); /* Get current ICR value. */ \
ulICR &= ~portCCPN_MASK; /* Clear down mask bits. */ \
ulICR |= uxSavedMaskValue; /* Set mask bits to previously saved mask value. */ \
_mtcr( $ICR, ulICR ); /* Write back updated ICR. */ \
_isync(); \
_enable(); \
}
extern unsigned portBASE_TYPE uxPortSetInterruptMaskFromISR( void );
extern void vPortClearInterruptMaskFromISR( unsigned portBASE_TYPE uxSavedStatusValue );
/* Set ICR.CCPN to configMAX_SYSCALL_INTERRUPT_PRIORITY */
extern unsigned long uxPortSetInterruptMaskFromISR( void );
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMaskFromISR()
/* Set ICR.CCPN to uxSavedInterruptStatus */
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) vPortClearInterruptMaskFromISR( uxSavedStatusValue )
/* As this port holds a CSA address in pxTopOfStack, the assert that checks the
pxTopOfStack alignment is removed. */
#define portALIGNMENT_ASSERT_pxCurrentTCB ( void )
/*---------------------------------------------------------------------------*/
/* Pend a priority 1 interrupt, which will take care of the context switch. */
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken != pdFALSE ) { CPU_SRC0.bits.SETR = 1; _isync(); }
/*
* Save the context of a task.
* The upper context is automatically saved when entering a trap or interrupt.
* Need to save the lower context as well and copy the PCXI CSA ID into
* pxCurrentTCB->pxTopOfStack. Only Lower Context CSA IDs may be saved to the
* TCB of a task.
*
* Call vTaskSwitchContext to select the next task, note that this changes the
* value of pxCurrentTCB so that it needs to be reloaded.
*
* Call vPortSetMPURegisterSetOne to change the MPU mapping for the task
* that has just been switched in.
*
* Load the context of the task.
* Need to restore the lower context by loading the CSA from
* pxCurrentTCB->pxTopOfStack into PCXI (effectively changing the call stack).
* In the Interrupt handler post-amble, RSLCX will restore the lower context
* of the task. RFE will restore the upper context of the task, jump to the
* return address and restore the previous state of interrupts being
* enabled/disabled.
*/
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) \
{ \
unsigned portBASE_TYPE *pxUpperCSA = NULL; \
unsigned portBASE_TYPE xUpperCSA = 0UL; \
extern volatile unsigned long *pxCurrentTCB; \
if ( pdTRUE == xHigherPriorityTaskWoken ) \
{ \
_disable(); \
_isync(); \
xUpperCSA = _mfcr( $PCXI ); \
pxUpperCSA = portCSA_TO_ADDRESS( xUpperCSA ); \
*pxCurrentTCB = pxUpperCSA[0]; \
vTaskSwitchContext(); \
pxUpperCSA[0] = *pxCurrentTCB; \
_dsync(); \
_isync(); \
_nop(); \
_nop(); \
} \
}
/*---------------------------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */
@ -204,8 +185,8 @@ extern volatile unsigned long *pxCurrentTCB; \
* Port specific clean up macro required to free the CSAs that were consumed by
* a task that has since been deleted.
*/
void vPortReclaimCSA( unsigned portBASE_TYPE *pxTCB );
#define portCLEAN_UP_TCB( pxTCB ) vPortReclaimCSA( ( unsigned portBASE_TYPE *) ( pxTCB ) )
void vPortReclaimCSA( unsigned long *pxTCB );
#define portCLEAN_UP_TCB( pxTCB ) vPortReclaimCSA( ( unsigned long * ) ( pxTCB ) )
#ifdef __cplusplus
}

Loading…
Cancel
Save