From 240e04ecf284b824cc85652c000cdcce5519ab2b Mon Sep 17 00:00:00 2001 From: richardbarry Date: Fri, 25 Jul 2008 02:33:56 +0000 Subject: [PATCH] Improve efficiency even further. Introduce the configMAX_SYSCALL_INTERRUPT_PRIORITY feature. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@415 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Source/portable/GCC/ARM_CM3/port.c | 123 +++++++++++------------- Source/portable/GCC/ARM_CM3/portmacro.h | 38 ++++---- 2 files changed, 79 insertions(+), 82 deletions(-) diff --git a/Source/portable/GCC/ARM_CM3/port.c b/Source/portable/GCC/ARM_CM3/port.c index 8c5ab7fce..59798ebca 100644 --- a/Source/portable/GCC/ARM_CM3/port.c +++ b/Source/portable/GCC/ARM_CM3/port.c @@ -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(); } /*-----------------------------------------------------------*/ diff --git a/Source/portable/GCC/ARM_CM3/portmacro.h b/Source/portable/GCC/ARM_CM3/portmacro.h index 30747086c..4362f1439 100644 --- a/Source/portable/GCC/ARM_CM3/portmacro.h +++ b/Source/portable/GCC/ARM_CM3/portmacro.h @@ -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() /*-----------------------------------------------------------*/ -- 2.39.5