Improve efficiency even further. Introduce the configMAX_SYSCALL_INTERRUPT_PRIORITY feature.

pull/4/head
Richard Barry 17 years ago
parent 3ab4d1f87f
commit 32592e1385

@ -19,7 +19,7 @@
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
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
can be applied.
@ -37,13 +37,13 @@
Please ensure to read the configuration and relevant port sections of the
online documentation.
http://www.FreeRTOS.org - Documentation, latest information, license and
http://www.FreeRTOS.org - Documentation, latest information, license and
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.
http://www.OpenRTOS.com - Commercial support, development, porting,
http://www.OpenRTOS.com - Commercial support, development, porting,
licensing and training services.
*/
@ -55,8 +55,8 @@
#include "FreeRTOS.h"
#include "task.h"
/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is
defined. The value should also ensure backward compatibility.
/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is
defined. The value should also ensure backward compatibility.
FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
#ifndef configKERNEL_INTERRUPT_PRIORITY
#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
variable. */
unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa;
static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa;
/*
/*
* Setup the timer to generate the tick interrupts.
*/
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 )
{
@ -118,8 +118,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
*pxTopOfStack = 0; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
*pxTopOfStack = 0x00000000; /* uxCriticalNesting. */
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
return pxTopOfStack;
}
@ -131,18 +130,15 @@ void vPortSVCHandler( void )
" ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
" 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. */
" ldmia r0!, {r1, 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"
" ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \n" /* Restore the task stack pointer. */
" mov r0, #0 \n"
" msr basepri, r0 \n"
" msr basepri, r0 \n"
" orr r14, #0xd \n"
" bx r14 \n"
" \n"
" .align 2 \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
this so remove the warning. */
( void ) ulValue;
asm volatile(
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" svc 0 \n" /* System call to start first task. */
asm volatile(
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
" 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 )
{
@ -172,7 +171,10 @@ portBASE_TYPE xPortStartScheduler( void )
/* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */
prvSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0;
/* Start the first task. */
vPortStartFirstTask( *((unsigned portLONG *) 0 ) );
@ -192,10 +194,6 @@ void vPortYieldFromISR( void )
{
/* Set a PendSV to request a context switch. */
*(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. */
__asm volatile
(
" mrs r0, psp \n"
" \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" ldr r1, uxCriticalNestingConst \n" /* Save the remaining registers and the critical nesting count onto the task stack. */
" ldr r1, [r1] \n"
" stmdb r0!, {r1,r4-r11} \n"
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" \n"
" stmdb sp!, {r3, r14} \n"
" bl vTaskSwitchContext \n"
" ldmia sp!, {r3, r14} \n"
" \n" /* Restore the context, including the critical nesting count. */
" ldr r1, [r3] \n"
" ldr r2, uxCriticalNestingConst \n"
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r1, r4-r11} \n" /* Pop the registers and the critical nesting count. */
" str r1, [r2] \n" /* Save the new critical nesting value into ulCriticalNesting. */
" msr psp, r0 \n"
" orr r14, #0xd \n"
" \n" /* Exit with interrupts in the state required by the task. */
" cbnz r1, sv_disable_interrupts \n" /* If the nesting count is greater than 0 we need to exit with interrupts masked. */
" bx r14 \n"
" \n"
"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"
(
" mrs r0, psp \n"
" \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" \n"
" stmdb sp!, {r3, r14} \n"
" mov r0, %0 \n"
" msr basepri, r0 \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" ldmia sp!, {r3, r14} \n"
" \n" /* Restore the context, including the critical nesting count. */
" ldr r1, [r3] \n"
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11} \n" /* Pop the registers. */
" msr psp, r0 \n"
" bx r14 \n"
" \n"
" .align 2 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n"
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
);
}
/*-----------------------------------------------------------*/
@ -264,10 +253,14 @@ void xPortSysTickHandler( void )
{
/* If using preemption, also force a context switch. */
#if configUSE_PREEMPTION == 1
*(portNVIC_INT_CTRL) |= portNVIC_PENDSVSET;
*(portNVIC_INT_CTRL) |= portNVIC_PENDSVSET;
#endif
vTaskIncrementTick();
portSET_INTERRUPT_MASK_FROM_ISR();
{
vTaskIncrementTick();
}
portCLEAR_INTERRUPT_MASK_FROM_ISR();
}
/*-----------------------------------------------------------*/

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

Loading…
Cancel
Save