Improve efficiency even further. Introduce the configMAX_SYSCALL_INTERRUPT_PRIORITY feature.

This commit is contained in:
Richard Barry 2008-07-25 02:33:56 +00:00
parent 3ab4d1f87f
commit 32592e1385
2 changed files with 79 additions and 82 deletions

View file

@ -19,7 +19,7 @@
A special exception to the GPL can be applied should you wish to distribute A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception of http://www.FreeRTOS.org for full details of how and when the exception
can be applied. can be applied.
@ -37,13 +37,13 @@
Please ensure to read the configuration and relevant port sections of the Please ensure to read the configuration and relevant port sections of the
online documentation. online documentation.
http://www.FreeRTOS.org - Documentation, latest information, license and http://www.FreeRTOS.org - Documentation, latest information, license and
contact details. contact details.
http://www.SafeRTOS.com - A version that is certified for use in safety http://www.SafeRTOS.com - A version that is certified for use in safety
critical systems. critical systems.
http://www.OpenRTOS.com - Commercial support, development, porting, http://www.OpenRTOS.com - Commercial support, development, porting,
licensing and training services. licensing and training services.
*/ */
@ -55,8 +55,8 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is /* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is
defined. The value should also ensure backward compatibility. defined. The value should also ensure backward compatibility.
FreeRTOS.org versions prior to V4.4.0 did not include this definition. */ FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
#ifndef configKERNEL_INTERRUPT_PRIORITY #ifndef configKERNEL_INTERRUPT_PRIORITY
#define configKERNEL_INTERRUPT_PRIORITY 255 #define configKERNEL_INTERRUPT_PRIORITY 255
@ -83,9 +83,9 @@ const unsigned portLONG ulKernelPriority = configKERNEL_INTERRUPT_PRIORITY;
/* Each task maintains its own interrupt status in the critical nesting /* Each task maintains its own interrupt status in the critical nesting
variable. */ variable. */
unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa;
/* /*
* Setup the timer to generate the tick interrupts. * Setup the timer to generate the tick interrupts.
*/ */
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
@ -104,8 +104,8 @@ void vPortStartFirstTask( unsigned long ulValue ) __attribute__ (( naked ));
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* See header file for description. * See header file for description.
*/ */
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
{ {
@ -118,8 +118,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
*pxTopOfStack = 0; /* LR */ *pxTopOfStack = 0; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
*pxTopOfStack = 0x00000000; /* uxCriticalNesting. */
return pxTopOfStack; return pxTopOfStack;
} }
@ -131,18 +130,15 @@ void vPortSVCHandler( void )
" ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
" ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r1, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" ldr r2, uxCriticalNestingConst2 \n" /* Restore the critical nesting count used by the task. */
" str r1, [r2] \n"
" msr psp, r0 \n" /* Restore the task stack pointer. */ " msr psp, r0 \n" /* Restore the task stack pointer. */
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" orr r14, #0xd \n" " orr r14, #0xd \n"
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .align 2 \n" " .align 2 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
"uxCriticalNestingConst2: .word uxCriticalNesting \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -152,16 +148,19 @@ void vPortStartFirstTask( unsigned long ulValue )
/* ulValue is used from the asm code, but the compiler does not know /* ulValue is used from the asm code, but the compiler does not know
this so remove the warning. */ this so remove the warning. */
( void ) ulValue; ( void ) ulValue;
asm volatile( asm volatile(
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */ " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
" svc 0 \n" /* System call to start first task. */ " ldr r0, [r0] \n"
" ldr r0, [r0] \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" svc 0 \n" /* System call to start first task. */
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* See header file for description. * See header file for description.
*/ */
portBASE_TYPE xPortStartScheduler( void ) portBASE_TYPE xPortStartScheduler( void )
{ {
@ -172,7 +171,10 @@ portBASE_TYPE xPortStartScheduler( void )
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0;
/* Start the first task. */ /* Start the first task. */
vPortStartFirstTask( *((unsigned portLONG *) 0 ) ); vPortStartFirstTask( *((unsigned portLONG *) 0 ) );
@ -192,10 +194,6 @@ void vPortYieldFromISR( void )
{ {
/* Set a PendSV to request a context switch. */ /* Set a PendSV to request a context switch. */
*(portNVIC_INT_CTRL) |= portNVIC_PENDSVSET; *(portNVIC_INT_CTRL) |= portNVIC_PENDSVSET;
/* This function is also called in response to a Yield(), so we want
the yield to occur immediately. */
portENABLE_INTERRUPTS();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -221,41 +219,32 @@ void xPortPendSVHandler( void )
/* This is a naked function. */ /* This is a naked function. */
__asm volatile __asm volatile
( (
" mrs r0, psp \n" " mrs r0, psp \n"
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n" " ldr r2, [r3] \n"
" \n" " \n"
" ldr r1, uxCriticalNestingConst \n" /* Save the remaining registers and the critical nesting count onto the task stack. */ " stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */
" ldr r1, [r1] \n" " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" stmdb r0!, {r1,r4-r11} \n" " \n"
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ " stmdb sp!, {r3, r14} \n"
" \n" " mov r0, %0 \n"
" stmdb sp!, {r3, r14} \n" " msr basepri, r0 \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" ldmia sp!, {r3, r14} \n" " mov r0, #0 \n"
" \n" /* Restore the context, including the critical nesting count. */ " msr basepri, r0 \n"
" ldr r1, [r3] \n" " ldmia sp!, {r3, r14} \n"
" ldr r2, uxCriticalNestingConst \n" " \n" /* Restore the context, including the critical nesting count. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldr r1, [r3] \n"
" ldmia r0!, {r1, r4-r11} \n" /* Pop the registers and the critical nesting count. */ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" str r1, [r2] \n" /* Save the new critical nesting value into ulCriticalNesting. */ " ldmia r0!, {r4-r11} \n" /* Pop the registers. */
" msr psp, r0 \n" " msr psp, r0 \n"
" orr r14, #0xd \n" " bx r14 \n"
" \n" /* Exit with interrupts in the state required by the task. */ " \n"
" cbnz r1, sv_disable_interrupts \n" /* If the nesting count is greater than 0 we need to exit with interrupts masked. */ " .align 2 \n"
" bx r14 \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
" \n" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
"sv_disable_interrupts: \n"
" ldr r1, =ulKernelPriority \n"
" ldr r1, [r1] \n"
" msr basepri, r1 \n"
" bx r14 \n"
" \n"
" .align 2 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n"
"uxCriticalNestingConst: .word uxCriticalNesting \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -264,10 +253,14 @@ void xPortSysTickHandler( void )
{ {
/* If using preemption, also force a context switch. */ /* If using preemption, also force a context switch. */
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
*(portNVIC_INT_CTRL) |= portNVIC_PENDSVSET; *(portNVIC_INT_CTRL) |= portNVIC_PENDSVSET;
#endif #endif
vTaskIncrementTick(); portSET_INTERRUPT_MASK_FROM_ISR();
{
vTaskIncrementTick();
}
portCLEAR_INTERRUPT_MASK_FROM_ISR();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -101,35 +101,39 @@ extern void vPortYieldFromISR( void );
/* Critical section management. */ /* Critical section management. */
#define vPortSetInterruptMask() \ /*
* Set basepri to portMAX_SYSCALL_INTERRUPT_PRIORITY without effecting other
* registers. r0 is clobbered.
*/
#define portSET_INTERRUPT_MASK() \
__asm volatile \ __asm volatile \
( \ ( \
" push { r0 } \n" \ " mov r0, %0 \n" \
" ldr r0, =ulKernelPriority \n" \
" ldr r0, [r0] \n" \
" msr basepri, r0 \n" \ " msr basepri, r0 \n" \
" pop { r0 } " \ ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY):"r0" \
) )
/*-----------------------------------------------------------*/ /*
* Set basepri back to 0 without effective other registers.
#define vPortClearInterruptMask() \ * r0 is clobbered.
__asm volatile \ */
( \ #define portCLEAR_INTERRUPT_MASK() \
" push { r0 } \n" \ __asm volatile \
" mov r0, #0 \n" \ ( \
" msr basepri, r0 \n" \ " mov r0, #0 \n" \
" pop { r0 } " \ " msr basepri, r0 \n" \
:::"r0" \
) )
/*-----------------------------------------------------------*/ #define portSET_INTERRUPT_MASK_FROM_ISR() 0;portSET_INTERRUPT_MASK()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portCLEAR_INTERRUPT_MASK()
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portDISABLE_INTERRUPTS() vPortSetInterruptMask(); #define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask(); #define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK()
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/