From 0cc4e786ed17f7bfe0a3094a52e0d2f7a551b275 Mon Sep 17 00:00:00 2001 From: richardbarry Date: Sun, 23 Mar 2008 15:53:37 +0000 Subject: [PATCH] Performance optimisation. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@251 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Source/portable/IAR/ARM_CM3/port.c | 50 +++++------- Source/portable/IAR/ARM_CM3/portasm.s | 108 +++++++++++--------------- 2 files changed, 62 insertions(+), 96 deletions(-) diff --git a/Source/portable/IAR/ARM_CM3/port.c b/Source/portable/IAR/ARM_CM3/port.c index 87caec32d..1a744bcf5 100644 --- a/Source/portable/IAR/ARM_CM3/port.c +++ b/Source/portable/IAR/ARM_CM3/port.c @@ -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. +++ http://www.FreeRTOS.org +++ - Documentation, latest information, license and contact details. + Documentation, latest information, license and contact details. +++ http://www.SafeRTOS.com +++ 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_INT_CTRL ( ( volatile unsigned portLONG *) 0xe000ed04 ) #define portNVIC_SYSPRI2 ( ( volatile unsigned portLONG *) 0xe000ed20 ) -#define portNVIC_SYSPRI1 ( ( volatile unsigned portLONG *) 0xe000ed1c ) #define portNVIC_SYSTICK_CLK 0x00000004 #define portNVIC_SYSTICK_INT 0x00000002 #define portNVIC_SYSTICK_ENABLE 0x00000001 @@ -88,16 +87,14 @@ unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; static void prvSetupTimerInterrupt( void ); /* - * Set the MSP/PSP to a known value. + * Exception handlers. */ -extern void vSetMSP( unsigned long ulValue ); -extern void vSetPSP( unsigned long ulValue ); +void xPortSysTickHandler( void ); /* - * Utilities called from the assembler code. + * Start first task is a separate function so it can be tested in isolation. */ -void vPortSwitchContext( void ); -void vPortIncrementTick( void ); +extern void vPortStartFirstTask( unsigned portLONG ulValue ); /*-----------------------------------------------------------*/ @@ -112,7 +109,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxTopOfStack--; *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ pxTopOfStack--; - *pxTopOfStack = 0xfffffffd; /* LR */ + *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. */ @@ -136,12 +133,7 @@ portBASE_TYPE xPortStartScheduler( void ) prvSetupTimerInterrupt(); /* Start the first task. */ - vSetPSP( 0 ); - vSetMSP( *((unsigned portLONG *) 0 ) ); - *(portNVIC_INT_CTRL) |= portNVIC_PENDSVSET; - - /* Enable interrupts */ - portENABLE_INTERRUPTS(); + vPortStartFirstTask( *((unsigned portLONG *) 0 ) ); /* Should not get here! */ 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 @@ -196,19 +198,3 @@ void prvSetupTimerInterrupt( void ) } /*-----------------------------------------------------------*/ -void vPortSwitchContext( void ) -{ - vPortSetInterruptMask(); - vTaskSwitchContext(); - vPortClearInterruptMask(); -} -/*-----------------------------------------------------------*/ - -void vPortIncrementTick( void ) -{ - vPortSetInterruptMask(); - vTaskIncrementTick(); - vPortClearInterruptMask(); -} - - diff --git a/Source/portable/IAR/ARM_CM3/portasm.s b/Source/portable/IAR/ARM_CM3/portasm.s index 32e79796b..ad2cde1fe 100644 --- a/Source/portable/IAR/ARM_CM3/portasm.s +++ b/Source/portable/IAR/ARM_CM3/portasm.s @@ -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. +++ http://www.FreeRTOS.org +++ - Documentation, latest information, license and contact details. + Documentation, latest information, license and contact details. +++ http://www.SafeRTOS.com +++ 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 EXTERN vPortYieldFromISR - EXTERN vPortSwitchContext - EXTERN vPortIncrementTick EXTERN uxCriticalNesting EXTERN pxCurrentTCB + EXTERN vTaskSwitchContext - PUBLIC vSetPSP PUBLIC vSetMSP PUBLIC xPortPendSVHandler - PUBLIC xPortSysTickHandler PUBLIC vPortSetInterruptMask PUBLIC vPortClearInterruptMask + PUBLIC vPortSVCHandler + PUBLIC vPortStartFirstTask -vSetPSP: - msr psp, r0 - bx lr - /*-----------------------------------------------------------*/ vSetMSP @@ -88,67 +83,34 @@ vSetMSP xPortPendSVHandler: mrs r0, psp - cbz r0, no_save - /* Save the context into the TCB. */ - stmdb r0!, {r4-r11} - sub r0, r0, #0x04 - ldr r1, =uxCriticalNesting - ldr r2, =pxCurrentTCB - ldr r1, [r1] - ldr r2, [r2] - str r1, [r0] - str r0, [r2] - -no_save: - push {r14} - bl vPortSwitchContext - pop {r14} - /* Restore the context. */ - ldr r1, =pxCurrentTCB + ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ + ldr r2, [r3] + + ldr r1, =uxCriticalNesting /* Save the remaining registers and the critical nesting count onto the task stack. */ ldr r1, [r1] - ldr r0, [r1] - ldmia r0!, {r1, r4-r11} - ldr r2, =uxCriticalNesting - str r1, [r2] + stmdb r0!, {r1,r4-r11} + str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ + + stmdb sp!, {r3, r14} + bl vTaskSwitchContext + ldmia sp!, {r3, r14} + + ldr r1, [r3] + ldr r2, =uxCriticalNesting + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + ldmia r0!, {r1, r4-r11} /* Pop the registers and the critical nesting count. */ + str r1, [r2] /* Save the new critical nesting value into ulCriticalNesting. */ msr psp, r0 - orr r14, r14, #0xd - /* Exit with interrupts in the state required by the task. */ - cbnz r1, sv_disable_interrupts + orr r14, r14, #13 + + cbnz r1, sv_disable_interrupts /* If the nesting count is greater than 0 we need to exit with interrupts masked. */ bx r14 - + sv_disable_interrupts: mov r1, #configKERNEL_INTERRUPT_PRIORITY - msr basepri, R1 + msr basepri, r1 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: @@ -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 \ No newline at end of file -- 2.39.5