Update to use the kernel critical nesting.

pull/4/head
Richard Barry 17 years ago
parent f3eb5028a3
commit 66fc3b8092

@ -131,11 +131,6 @@
mflo s6 mflo s6
sw s6, 8(s5) sw s6, 8(s5)
/* Each task maintains its own nesting count. */
la s6, uxCriticalNesting
lw s6, (s6)
sw s6, 4(s5)
/* Update the task stack pointer value if nesting is zero. */ /* Update the task stack pointer value if nesting is zero. */
la s6, uxInterruptNesting la s6, uxInterruptNesting
lw s6, (s6) lw s6, (s6)
@ -199,13 +194,6 @@
addiu k1, k1, -1 addiu k1, k1, -1
sw k1, 0(k0) sw k1, 0(k0)
/* Restore the critical nesting count. */
la k0, uxCriticalNesting
lw k1, 4(s5)
sw k1, (k0)
/* If the critical nesting is not zero then set status as if within
a critical section. */
lw k0, portSTATUS_STACK_LOCATION(s5) lw k0, portSTATUS_STACK_LOCATION(s5)
lw k1, portEPC_STACK_LOCATION(s5) lw k1, portEPC_STACK_LOCATION(s5)

@ -62,24 +62,15 @@
#define portIE_BIT ( 0x00000001 ) #define portIE_BIT ( 0x00000001 )
#define portEXL_BIT ( 0x00000002 ) #define portEXL_BIT ( 0x00000002 )
#define portSW0_ENABLE ( 0x00000100 ) #define portSW0_ENABLE ( 0x00000100 )
#define portIPL_SHIFT ( 10 )
#define portALL_IPL_BITS ( 0x3f << portIPL_SHIFT )
/* The EXL bit is set to ensure interrupts do not occur while the context of /* The EXL bit is set to ensure interrupts do not occur while the context of
the first task is being restored. */ the first task is being restored. */
#define portINITIAL_SR ( portIE_BIT | portEXL_BIT | portSW0_ENABLE ) #define portINITIAL_SR ( portIE_BIT | portEXL_BIT | portSW0_ENABLE )
/* Records the nesting depth of calls to portENTER_CRITICAL(). */
unsigned portBASE_TYPE uxCriticalNesting = 0x55555555;
/* Records the interrupt nesting depth. This starts at one as it will be /* Records the interrupt nesting depth. This starts at one as it will be
decremented to 0 when the first task starts. */ decremented to 0 when the first task starts. */
volatile unsigned portBASE_TYPE uxInterruptNesting = 0x01; volatile unsigned portBASE_TYPE uxInterruptNesting = 0x01;
/* Used to store the original interrupt mask when the mask level is temporarily
raised during an ISR. */
volatile unsigned portBASE_TYPE uxSavedStatusRegister = 0;
/* Stores the task stack pointer when a switch is made to use the system stack. */ /* Stores the task stack pointer when a switch is made to use the system stack. */
unsigned portBASE_TYPE uxSavedTaskStackPointer = 0; unsigned portBASE_TYPE uxSavedTaskStackPointer = 0;
@ -126,7 +117,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
*pxTopOfStack = (portSTACK_TYPE) pvParameters; /* Parameters to pass in */ *pxTopOfStack = (portSTACK_TYPE) pvParameters; /* Parameters to pass in */
pxTopOfStack -= 14; pxTopOfStack -= 14;
*pxTopOfStack = (portSTACK_TYPE) 0x00000000; /* critical nesting level */ *pxTopOfStack = (portSTACK_TYPE) 0x00000000; /* critical nesting level - no longer used. */
pxTopOfStack--; pxTopOfStack--;
return pxTopOfStack; return pxTopOfStack;
@ -154,39 +145,6 @@ void vPortEndScheduler(void)
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical(void)
{
unsigned portLONG ulStatus;
/* Mask interrupts at and below the kernel interrupt priority. */
ulStatus = _CP0_GET_STATUS();
ulStatus |= ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT );
_CP0_SET_STATUS( ulStatus );
/* Once interrupts are disabled we can access the nesting count directly. */
uxCriticalNesting++;
}
/*-----------------------------------------------------------*/
void vPortExitCritical(void)
{
unsigned portLONG ulStatus;
/* If we are in a critical section then we can access the nesting count
directly. */
uxCriticalNesting--;
/* Has the nesting unwound? */
if( uxCriticalNesting == 0 )
{
/* Unmask all interrupts. */
ulStatus = _CP0_GET_STATUS();
ulStatus &= ~portALL_IPL_BITS;
_CP0_SET_STATUS( ulStatus );
}
}
/*-----------------------------------------------------------*/
portBASE_TYPE xPortStartScheduler( void ) portBASE_TYPE xPortStartScheduler( void )
{ {
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
@ -224,9 +182,11 @@ unsigned portLONG ulStatus;
void vPortIncrementTick( void ) void vPortIncrementTick( void )
{ {
vPortSetInterruptMaskFromISR(); unsigned portBASE_TYPE uxSavedStatus;
uxSavedStatus = uxPortSetInterruptMaskFromISR();
vTaskIncrementTick(); vTaskIncrementTick();
vPortClearInterruptMaskFromISR(); vPortClearInterruptMaskFromISR( uxSavedStatus );
/* If we are using the preemptive scheduler then we might want to select /* If we are using the preemptive scheduler then we might want to select
a different task to execute. */ a different task to execute. */
@ -239,15 +199,19 @@ void vPortIncrementTick( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortSetInterruptMaskFromISR( void ) unsigned portBASE_TYPE uxPortSetInterruptMaskFromISR( void )
{ {
unsigned portBASE_TYPE uxSavedStatusRegister;
asm volatile ( "di" ); asm volatile ( "di" );
uxSavedStatusRegister = _CP0_GET_STATUS() | 0x01; uxSavedStatusRegister = _CP0_GET_STATUS() | 0x01;
_CP0_SET_STATUS( ( uxSavedStatusRegister | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); _CP0_SET_STATUS( ( uxSavedStatusRegister | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) );
return uxSavedStatusRegister;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortClearInterruptMaskFromISR( void ) void vPortClearInterruptMaskFromISR( unsigned portBASE_TYPE uxSavedStatusRegister )
{ {
_CP0_SET_STATUS( uxSavedStatusRegister ); _CP0_SET_STATUS( uxSavedStatusRegister );
} }

@ -57,7 +57,6 @@
.set noreorder .set noreorder
.extern pxCurrentTCB .extern pxCurrentTCB
.extern uxCriticalNesting
.extern vTaskSwitchContext .extern vTaskSwitchContext
.extern vPortIncrementTick .extern vPortIncrementTick
.extern xISRStackTop .extern xISRStackTop
@ -189,11 +188,6 @@ vPortYieldISR:
mflo s7 mflo s7
sw s7, 8(s5) sw s7, 8(s5)
/* Each task maintains its own nesting count. */
la s7, uxCriticalNesting
lw s7, (s7)
sw s7, 4(s5)
/* Save the stack pointer to the task. */ /* Save the stack pointer to the task. */
la s7, pxCurrentTCB la s7, pxCurrentTCB
lw s7, (s7) lw s7, (s7)
@ -276,33 +270,19 @@ vPortYieldISR:
/* Switch back to use the real stack pointer. */ /* Switch back to use the real stack pointer. */
add sp, zero, s5 add sp, zero, s5
/* Restore the critical nesting depth. */ /* Restore the real s5 value. */
la s5, uxCriticalNesting lw s5, 40(sp)
lw k0, 4(sp)
sw k0, (s5)
/* If the critical nesting is not zero and a yield is not pended /* If the critical nesting is not zero and a yield is not pended
then set status as if within a critical section. */ then set status as if within a critical section. */
lw s5, portSTATUS_STACK_LOCATION(sp) lw k1, portSTATUS_STACK_LOCATION(sp)
beq k0, zero, .+28
nop
mfc0 k1, _CP0_CAUSE
andi k1, k1, 256
bne k1, zero, .+12
nop
or s5, s5, (configMAX_SYSCALL_INTERRUPT_PRIORITY<<10)
lw k0, portEPC_STACK_LOCATION(sp) lw k0, portEPC_STACK_LOCATION(sp)
mtc0 s5, _CP0_STATUS
ehb
/* Restore the real s5 value. */
lw s5, 40(sp)
/* Remove stack frame. */ /* Remove stack frame. */
addiu sp, sp, portCONTEXT_SIZE addiu sp, sp, portCONTEXT_SIZE
mtc0 k1, _CP0_STATUS
ehb
mtc0 k0, _CP0_EPC mtc0 k0, _CP0_EPC
eret eret
nop nop

@ -92,18 +92,40 @@ extern "C" {
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
#define portDISABLE_INTERRUPTS() INTDisableInterrupts() #define portIPL_SHIFT ( 10 )
#define portENABLE_INTERRUPTS() INTEnableInterrupts() #define portALL_IPL_BITS ( 0x3f << portIPL_SHIFT )
extern void vPortEnterCritical( void ); #define portDISABLE_INTERRUPTS() \
extern void vPortExitCritical( void ); { \
#define portENTER_CRITICAL() vPortEnterCritical() unsigned portLONG ulStatus; \
#define portEXIT_CRITICAL() vPortExitCritical() \
/* Mask interrupts at and below the kernel interrupt priority. */ \
extern void vPortSetInterruptMaskFromISR(); ulStatus = _CP0_GET_STATUS(); \
extern void vPortClearInterruptMaskFromISR(); ulStatus |= ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ); \
#define portSET_INTERRUPT_MASK_FROM_ISR() vPortSetInterruptMaskFromISR() _CP0_SET_STATUS( ulStatus ); \
#define portCLEAR_INTERRUPT_MASK_FROM_ISR() vPortClearInterruptMaskFromISR() }
#define portENABLE_INTERRUPTS() \
{ \
unsigned portLONG ulStatus; \
\
/* Unmask all interrupts. */ \
ulStatus = _CP0_GET_STATUS(); \
ulStatus &= ~portALL_IPL_BITS; \
_CP0_SET_STATUS( ulStatus ); \
}
extern void vTaskEnterCritical( void );
extern void vTaskExitCritical( void );
#define portCRITICAL_NESTING_IN_TCB 1
#define portENTER_CRITICAL() vTaskEnterCritical()
#define portEXIT_CRITICAL() vTaskExitCritical()
extern unsigned portBASE_TYPE uxPortSetInterruptMaskFromISR();
extern void vPortClearInterruptMaskFromISR( unsigned portBASE_TYPE );
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMaskFromISR()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) vPortClearInterruptMaskFromISR( uxSavedStatusRegister )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

Loading…
Cancel
Save