Performance optimisation.

This commit is contained in:
Richard Barry 2008-03-23 15:53:37 +00:00
parent b53d20dfd2
commit a8d03f24e3
2 changed files with 62 additions and 96 deletions

View File

@ -25,11 +25,11 @@
*************************************************************************** ***************************************************************************
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 +++ +++ http://www.FreeRTOS.org +++
Documentation, latest information, license and contact details. Documentation, latest information, license and contact details.
+++ http://www.SafeRTOS.com +++ +++ http://www.SafeRTOS.com +++
A version that is certified for use in safety critical systems. A version that is certified for use in safety critical systems.
@ -60,7 +60,6 @@
#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned portLONG *) 0xe000e014 ) #define portNVIC_SYSTICK_LOAD ( ( volatile unsigned portLONG *) 0xe000e014 )
#define portNVIC_INT_CTRL ( ( volatile unsigned portLONG *) 0xe000ed04 ) #define portNVIC_INT_CTRL ( ( volatile unsigned portLONG *) 0xe000ed04 )
#define portNVIC_SYSPRI2 ( ( volatile unsigned portLONG *) 0xe000ed20 ) #define portNVIC_SYSPRI2 ( ( volatile unsigned portLONG *) 0xe000ed20 )
#define portNVIC_SYSPRI1 ( ( volatile unsigned portLONG *) 0xe000ed1c )
#define portNVIC_SYSTICK_CLK 0x00000004 #define portNVIC_SYSTICK_CLK 0x00000004
#define portNVIC_SYSTICK_INT 0x00000002 #define portNVIC_SYSTICK_INT 0x00000002
#define portNVIC_SYSTICK_ENABLE 0x00000001 #define portNVIC_SYSTICK_ENABLE 0x00000001
@ -88,16 +87,14 @@ unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa;
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
/* /*
* Set the MSP/PSP to a known value. * Exception handlers.
*/ */
extern void vSetMSP( unsigned long ulValue ); void xPortSysTickHandler( void );
extern void vSetPSP( unsigned long ulValue );
/* /*
* Utilities called from the assembler code. * Start first task is a separate function so it can be tested in isolation.
*/ */
void vPortSwitchContext( void ); extern void vPortStartFirstTask( unsigned portLONG ulValue );
void vPortIncrementTick( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -112,7 +109,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xfffffffd; /* 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 -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
@ -136,12 +133,7 @@ portBASE_TYPE xPortStartScheduler( void )
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
vSetPSP( 0 ); vPortStartFirstTask( *((unsigned portLONG *) 0 ) );
vSetMSP( *((unsigned portLONG *) 0 ) );
*(portNVIC_INT_CTRL) |= portNVIC_PENDSVSET;
/* Enable interrupts */
portENABLE_INTERRUPTS();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
@ -183,6 +175,16 @@ void vPortExitCritical( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void xPortSysTickHandler( void )
{
vTaskIncrementTick();
/* If using preemption, also force a context switch. */
#if configUSE_PREEMPTION == 1
*(portNVIC_INT_CTRL) |= portNVIC_PENDSVSET;
#endif
}
/*-----------------------------------------------------------*/
/* /*
* Setup the systick timer to generate the tick interrupts at the required * Setup the systick timer to generate the tick interrupts at the required
@ -196,19 +198,3 @@ void prvSetupTimerInterrupt( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortSwitchContext( void )
{
vPortSetInterruptMask();
vTaskSwitchContext();
vPortClearInterruptMask();
}
/*-----------------------------------------------------------*/
void vPortIncrementTick( void )
{
vPortSetInterruptMask();
vTaskIncrementTick();
vPortClearInterruptMask();
}

View File

@ -25,11 +25,11 @@
*************************************************************************** ***************************************************************************
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 +++ +++ http://www.FreeRTOS.org +++
Documentation, latest information, license and contact details. Documentation, latest information, license and contact details.
+++ http://www.SafeRTOS.com +++ +++ http://www.SafeRTOS.com +++
A version that is certified for use in safety critical systems. A version that is certified for use in safety critical systems.
@ -61,23 +61,18 @@ FreeRTOS.org versions prior to V4.3.0 did not include this definition. */
thumb thumb
EXTERN vPortYieldFromISR EXTERN vPortYieldFromISR
EXTERN vPortSwitchContext
EXTERN vPortIncrementTick
EXTERN uxCriticalNesting EXTERN uxCriticalNesting
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN vTaskSwitchContext
PUBLIC vSetPSP
PUBLIC vSetMSP PUBLIC vSetMSP
PUBLIC xPortPendSVHandler PUBLIC xPortPendSVHandler
PUBLIC xPortSysTickHandler
PUBLIC vPortSetInterruptMask PUBLIC vPortSetInterruptMask
PUBLIC vPortClearInterruptMask PUBLIC vPortClearInterruptMask
PUBLIC vPortSVCHandler
PUBLIC vPortStartFirstTask
vSetPSP:
msr psp, r0
bx lr
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vSetMSP vSetMSP
@ -88,67 +83,34 @@ vSetMSP
xPortPendSVHandler: xPortPendSVHandler:
mrs r0, psp mrs r0, psp
cbz r0, no_save ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */
/* Save the context into the TCB. */ ldr r2, [r3]
stmdb r0!, {r4-r11}
sub r0, r0, #0x04 ldr r1, =uxCriticalNesting /* Save the remaining registers and the critical nesting count onto the task stack. */
ldr r1, =uxCriticalNesting
ldr r2, =pxCurrentTCB
ldr r1, [r1] ldr r1, [r1]
ldr r2, [r2] stmdb r0!, {r1,r4-r11}
str r1, [r0] str r0, [r2] /* Save the new top of stack into the first member of the TCB. */
str r0, [r2]
stmdb sp!, {r3, r14}
no_save: bl vTaskSwitchContext
push {r14} ldmia sp!, {r3, r14}
bl vPortSwitchContext
pop {r14} ldr r1, [r3]
/* Restore the context. */ ldr r2, =uxCriticalNesting
ldr r1, =pxCurrentTCB ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
ldr r1, [r1] ldmia r0!, {r1, r4-r11} /* Pop the registers and the critical nesting count. */
ldr r0, [r1] str r1, [r2] /* Save the new critical nesting value into ulCriticalNesting. */
ldmia r0!, {r1, r4-r11}
ldr r2, =uxCriticalNesting
str r1, [r2]
msr psp, r0 msr psp, r0
orr r14, r14, #0xd orr r14, r14, #13
/* Exit with interrupts in the state required by the task. */
cbnz r1, sv_disable_interrupts cbnz r1, sv_disable_interrupts /* If the nesting count is greater than 0 we need to exit with interrupts masked. */
bx r14 bx r14
sv_disable_interrupts: sv_disable_interrupts:
mov r1, #configKERNEL_INTERRUPT_PRIORITY mov r1, #configKERNEL_INTERRUPT_PRIORITY
msr basepri, R1 msr basepri, r1
bx r14 bx r14
/*-----------------------------------------------------------*/
xPortSysTickHandler:
/* Call the scheduler tick function. */
push {r14}
bl vPortIncrementTick
pop {r14}
/* If using preemption, also force a context switch. */
#if configUSE_PREEMPTION == 1
push {r14}
bl vPortYieldFromISR
pop {r14}
#endif
/* Exit with interrupts in the correct state. */
ldr r2, =uxCriticalNesting
ldr r2, [r2]
cbnz r2, tick_disable_interrupts
bx r14
tick_disable_interrupts:
mov r1, #configKERNEL_INTERRUPT_PRIORITY
msr basepri, R1
bx r14
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vPortSetInterruptMask: vPortSetInterruptMask:
@ -171,5 +133,23 @@ vPortClearInterruptMask:
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vPortSVCHandler;
ldr r3, =pxCurrentTCB
ldr r1, [r3]
ldr r0, [r1]
ldmia r0!, {r1, r4-r11}
ldr r2, =uxCriticalNesting
str r1, [r2]
msr psp, r0
orr r14, r14, #13
bx r14
/*-----------------------------------------------------------*/
vPortStartFirstTask
msr msp, r0
svc 0
END END