From 9f27eae3036eb87c87ebdb99fc23882adc2304e6 Mon Sep 17 00:00:00 2001 From: rtel Date: Thu, 12 Dec 2013 14:07:20 +0000 Subject: [PATCH] Update Cortex-M3 and Cortex-M4F ports to allow the SysTick to be clocked at a different speed than the system clock (as is done in the recent STM32L demo. ). Add additional asserts and isb instructions into the Cortex-M3 and Cortex-M4F ports. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2129 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- FreeRTOS/Source/portable/GCC/ARM_CM3/port.c | 28 ++++++++++++------- FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c | 28 ++++++++++++------- FreeRTOS/Source/portable/IAR/ARM_CM3/port.c | 17 +++++------ .../Source/portable/IAR/ARM_CM3/portasm.s | 22 +++++++++------ FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c | 17 +++++------ .../Source/portable/IAR/ARM_CM4F/portasm.s | 7 +++-- FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c | 22 +++++++++------ FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c | 25 ++++++++++------- .../portable/Tasking/ARM_CM4F/port_asm.asm | 7 +++++ FreeRTOS/Source/timers.c | 4 +-- 10 files changed, 110 insertions(+), 67 deletions(-) diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c index 1a33e7380..206e70d25 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c +++ b/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c @@ -237,6 +237,7 @@ void vPortSVCHandler( void ) " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " 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. */ + " isb \n" " mov r0, #0 \n" " msr basepri, r0 \n" " orr r14, #0xd \n" @@ -256,6 +257,8 @@ static void prvPortStartFirstTask( void ) " ldr r0, [r0] \n" " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ " cpsie i \n" /* Globally enable interrupts. */ + " dsb \n" + " isb \n" " svc 0 \n" /* System call to start first task. */ " nop \n" ); @@ -342,8 +345,9 @@ portBASE_TYPE xPortStartScheduler( void ) void vPortEndScheduler( void ) { - /* It is unlikely that the CM3 port will require this function as there - is nothing to return to. */ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); } /*-----------------------------------------------------------*/ @@ -370,6 +374,7 @@ void vPortEnterCritical( void ) void vPortExitCritical( void ) { + configASSERT( uxCriticalNesting ); uxCriticalNesting--; if( uxCriticalNesting == 0 ) { @@ -416,6 +421,7 @@ void xPortPendSVHandler( void ) __asm volatile ( " mrs r0, psp \n" + " isb \n" " \n" " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ " ldr r2, [r3] \n" @@ -435,6 +441,7 @@ void xPortPendSVHandler( void ) " 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" + " isb \n" " bx r14 \n" " \n" " .align 2 \n" @@ -468,7 +475,7 @@ void xPortSysTickHandler( void ) __attribute__((weak)) void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) { - unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; + unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; portTickType xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -481,7 +488,7 @@ void xPortSysTickHandler( void ) is accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; /* Calculate the reload value required to wait xExpectedIdleTime tick periods. -1 is used because this code will execute part way @@ -505,7 +512,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Reset the reload register to the value required for normal tick periods. */ @@ -525,7 +532,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can set its parameter to 0 to indicate that its implementation contains @@ -546,13 +553,14 @@ void xPortSysTickHandler( void ) accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); /* Re-enable interrupts - see comments above the cpsid instruction() above. */ __asm volatile( "cpsie i" ); - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { unsigned long ulCalculatedLoadValue; @@ -604,7 +612,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portENTER_CRITICAL(); { - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; vTaskStepTick( ulCompleteTickPeriods ); portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; } @@ -632,7 +640,7 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* Configure SysTick to interrupt at the requested rate. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); } /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c index c009b4bce..98c301ba7 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c +++ b/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c @@ -256,6 +256,7 @@ void vPortSVCHandler( void ) " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldmia r0!, {r4-r11, r14} \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. */ + " isb \n" " mov r0, #0 \n" " msr basepri, r0 \n" " bx r14 \n" @@ -274,6 +275,8 @@ static void prvPortStartFirstTask( void ) " ldr r0, [r0] \n" " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ " cpsie i \n" /* Globally enable interrupts. */ + " dsb \n" + " isb \n" " svc 0 \n" /* System call to start first task. */ " nop \n" ); @@ -366,8 +369,9 @@ portBASE_TYPE xPortStartScheduler( void ) void vPortEndScheduler( void ) { - /* It is unlikely that the CM4F port will require this function as there - is nothing to return to. */ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); } /*-----------------------------------------------------------*/ @@ -394,6 +398,7 @@ void vPortEnterCritical( void ) void vPortExitCritical( void ) { + configASSERT( uxCriticalNesting ); uxCriticalNesting--; if( uxCriticalNesting == 0 ) { @@ -440,6 +445,7 @@ void xPortPendSVHandler( void ) __asm volatile ( " mrs r0, psp \n" + " isb \n" " \n" " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ " ldr r2, [r3] \n" @@ -470,6 +476,7 @@ void xPortPendSVHandler( void ) " vldmiaeq r0!, {s16-s31} \n" " \n" " msr psp, r0 \n" + " isb \n" " \n" #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */ #if WORKAROUND_PMU_CM001 == 1 @@ -511,7 +518,7 @@ void xPortSysTickHandler( void ) __attribute__((weak)) void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) { - unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; + unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; portTickType xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -524,7 +531,7 @@ void xPortSysTickHandler( void ) is accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; /* Calculate the reload value required to wait xExpectedIdleTime tick periods. -1 is used because this code will execute part way @@ -548,7 +555,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Reset the reload register to the value required for normal tick periods. */ @@ -568,7 +575,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can set its parameter to 0 to indicate that its implementation contains @@ -589,13 +596,14 @@ void xPortSysTickHandler( void ) accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); /* Re-enable interrupts - see comments above the cpsid instruction() above. */ __asm volatile( "cpsie i" ); - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { unsigned long ulCalculatedLoadValue; @@ -647,7 +655,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portENTER_CRITICAL(); { - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; vTaskStepTick( ulCompleteTickPeriods ); portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; } @@ -675,7 +683,7 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* Configure SysTick to interrupt at the requested rate. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); } /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c b/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c index 4e718a4ac..d902851d1 100644 --- a/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c +++ b/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c @@ -357,7 +357,7 @@ void xPortSysTickHandler( void ) __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) { - unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; + unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; portTickType xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -370,7 +370,7 @@ void xPortSysTickHandler( void ) is accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; /* Calculate the reload value required to wait xExpectedIdleTime tick periods. -1 is used because this code will execute part way @@ -394,7 +394,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Reset the reload register to the value required for normal tick periods. */ @@ -414,7 +414,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can set its parameter to 0 to indicate that its implementation contains @@ -435,13 +435,14 @@ void xPortSysTickHandler( void ) accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); /* Re-enable interrupts - see comments above __disable_interrupt() call above. */ __enable_interrupt(); - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { unsigned long ulCalculatedLoadValue; @@ -493,7 +494,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portENTER_CRITICAL(); { - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; vTaskStepTick( ulCompleteTickPeriods ); portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; } @@ -521,7 +522,7 @@ __weak void vPortSetupTimerInterrupt( void ) /* Configure SysTick to interrupt at the requested rate. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); } /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM3/portasm.s b/FreeRTOS/Source/portable/IAR/ARM_CM3/portasm.s index 5b4af0c5c..b6bc1b12a 100644 --- a/FreeRTOS/Source/portable/IAR/ARM_CM3/portasm.s +++ b/FreeRTOS/Source/portable/IAR/ARM_CM3/portasm.s @@ -1,5 +1,5 @@ /* - FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd. + FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. @@ -82,9 +82,10 @@ /*-----------------------------------------------------------*/ xPortPendSVHandler: - mrs r0, psp + mrs r0, psp + isb ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ - ldr r2, [r3] + ldr r2, [r3] stmdb r0!, {r4-r11} /* Save the remaining registers. */ str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ @@ -92,16 +93,17 @@ xPortPendSVHandler: stmdb sp!, {r3, r14} mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY msr basepri, r0 - bl vTaskSwitchContext + bl vTaskSwitchContext mov r0, #0 msr basepri, r0 ldmia sp!, {r3, r14} - ldr r1, [r3] + ldr r1, [r3] ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ ldmia r0!, {r4-r11} /* Pop the registers. */ - msr psp, r0 - bx r14 + msr psp, r0 + isb + bx r14 /*-----------------------------------------------------------*/ @@ -111,7 +113,7 @@ ulPortSetInterruptMask: mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY msr basepri, r1 bx r14 - + /*-----------------------------------------------------------*/ vPortClearInterruptMask: @@ -128,6 +130,7 @@ vPortSVCHandler: /* Pop the core registers. */ ldmia r0!, {r4-r11} msr psp, r0 + isb mov r0, #0 msr basepri, r0 orr r14, r14, #13 @@ -144,7 +147,8 @@ vPortStartFirstTask msr msp, r0 /* Call SVC to start the first task. */ cpsie i + dsb + isb svc 0 END - \ No newline at end of file diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c b/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c index 95b8b1870..7c287649e 100644 --- a/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c +++ b/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c @@ -383,7 +383,7 @@ void xPortSysTickHandler( void ) __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) { - unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; + unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; portTickType xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -396,7 +396,7 @@ void xPortSysTickHandler( void ) is accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; /* Calculate the reload value required to wait xExpectedIdleTime tick periods. -1 is used because this code will execute part way @@ -420,7 +420,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Reset the reload register to the value required for normal tick periods. */ @@ -440,7 +440,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can set its parameter to 0 to indicate that its implementation contains @@ -461,13 +461,14 @@ void xPortSysTickHandler( void ) accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); /* Re-enable interrupts - see comments above __disable_interrupt() call above. */ __enable_interrupt(); - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { unsigned long ulCalculatedLoadValue; @@ -519,7 +520,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portENTER_CRITICAL(); { - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; vTaskStepTick( ulCompleteTickPeriods ); portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; } @@ -547,7 +548,7 @@ __weak void vPortSetupTimerInterrupt( void ) /* Configure SysTick to interrupt at the requested rate. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); } /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM4F/portasm.s b/FreeRTOS/Source/portable/IAR/ARM_CM4F/portasm.s index 72bf98e33..b0123a4a7 100644 --- a/FreeRTOS/Source/portable/IAR/ARM_CM4F/portasm.s +++ b/FreeRTOS/Source/portable/IAR/ARM_CM4F/portasm.s @@ -83,7 +83,7 @@ xPortPendSVHandler: mrs r0, psp - + isb /* Get the location of the current TCB. */ ldr r3, =pxCurrentTCB ldr r2, [r3] @@ -121,7 +121,7 @@ xPortPendSVHandler: vldmiaeq r0!, {s16-s31} msr psp, r0 - + isb #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */ #if WORKAROUND_PMU_CM001 == 1 push { r14 } @@ -156,6 +156,7 @@ vPortSVCHandler: /* Pop the core registers. */ ldmia r0!, {r4-r11, r14} msr psp, r0 + isb mov r0, #0 msr basepri, r0 bx r14 @@ -171,6 +172,8 @@ vPortStartFirstTask msr msp, r0 /* Call SVC to start the first task. */ cpsie i + dsb + isb svc 0 /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c b/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c index 8e881953f..c3fe7088a 100644 --- a/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c +++ b/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c @@ -243,6 +243,7 @@ __asm void vPortSVCHandler( void ) ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ ldmia r0!, {r4-r11} /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ msr psp, r0 /* Restore the task stack pointer. */ + isb mov r0, #0 msr basepri, r0 orr r14, #0xd @@ -262,6 +263,8 @@ __asm void prvStartFirstTask( void ) msr msp, r0 /* Globally enable interrupts. */ cpsie i + dsb + isb /* Call SVC to start the first task. */ svc 0 nop @@ -385,6 +388,7 @@ __asm void xPortPendSVHandler( void ) PRESERVE8 mrs r0, psp + isb ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ ldr r2, [r3] @@ -404,6 +408,7 @@ __asm void xPortPendSVHandler( void ) ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ ldmia r0!, {r4-r11} /* Pop the registers and the critical nesting count. */ msr psp, r0 + isb bx r14 nop } @@ -433,7 +438,7 @@ void xPortSysTickHandler( void ) __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) { - unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; + unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; portTickType xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -446,7 +451,7 @@ void xPortSysTickHandler( void ) is accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; /* Calculate the reload value required to wait xExpectedIdleTime tick periods. -1 is used because this code will execute part way @@ -470,7 +475,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Reset the reload register to the value required for normal tick periods. */ @@ -490,7 +495,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can set its parameter to 0 to indicate that its implementation contains @@ -511,13 +516,14 @@ void xPortSysTickHandler( void ) accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); /* Re-enable interrupts - see comments above __disable_irq() call above. */ __enable_irq(); - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { unsigned long ulCalculatedLoadValue; @@ -569,7 +575,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portENTER_CRITICAL(); { - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; vTaskStepTick( ulCompleteTickPeriods ); portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; } @@ -600,7 +606,7 @@ void xPortSysTickHandler( void ) /* Configure SysTick to interrupt at the requested rate. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); } #endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c b/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c index 615f2fa8b..6141aa9a3 100644 --- a/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c +++ b/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c @@ -266,6 +266,7 @@ __asm void vPortSVCHandler( void ) /* Pop the core registers. */ ldmia r0!, {r4-r11, r14} msr psp, r0 + isb mov r0, #0 msr basepri, r0 bx r14 @@ -284,6 +285,8 @@ __asm void prvStartFirstTask( void ) msr msp, r0 /* Globally enable interrupts. */ cpsie i + dsb + isb /* Call SVC to start the first task. */ svc 0 nop @@ -429,7 +432,7 @@ __asm void xPortPendSVHandler( void ) PRESERVE8 mrs r0, psp - + isb /* Get the location of the current TCB. */ ldr r3, =pxCurrentTCB ldr r2, [r3] @@ -467,11 +470,12 @@ __asm void xPortPendSVHandler( void ) vldmiaeq r0!, {s16-s31} msr psp, r0 - + isb #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */ #if WORKAROUND_PMU_CM001 == 1 push { r14 } pop { pc } + nop #endif #endif @@ -504,7 +508,7 @@ void xPortSysTickHandler( void ) __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) { - unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; + unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; portTickType xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -517,7 +521,7 @@ void xPortSysTickHandler( void ) is accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; /* Calculate the reload value required to wait xExpectedIdleTime tick periods. -1 is used because this code will execute part way @@ -541,7 +545,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Reset the reload register to the value required for normal tick periods. */ @@ -561,7 +565,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can set its parameter to 0 to indicate that its implementation contains @@ -582,13 +586,14 @@ void xPortSysTickHandler( void ) accounted for as best it can be, but using the tickless mode will inevitably result in some tiny drift of the time maintained by the kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); /* Re-enable interrupts - see comments above __disable_irq() call above. */ __enable_irq(); - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { unsigned long ulCalculatedLoadValue; @@ -640,7 +645,7 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portENTER_CRITICAL(); { - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; vTaskStepTick( ulCompleteTickPeriods ); portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; } @@ -671,7 +676,7 @@ void xPortSysTickHandler( void ) /* Configure SysTick to interrupt at the requested rate. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); } #endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ diff --git a/FreeRTOS/Source/portable/Tasking/ARM_CM4F/port_asm.asm b/FreeRTOS/Source/portable/Tasking/ARM_CM4F/port_asm.asm index aa3e99f33..d6c70a2fe 100644 --- a/FreeRTOS/Source/portable/Tasking/ARM_CM4F/port_asm.asm +++ b/FreeRTOS/Source/portable/Tasking/ARM_CM4F/port_asm.asm @@ -73,6 +73,7 @@ _vector_14: .type func mrs r0, psp + isb ;Get the location of the current TCB. ldr.w r3, =pxCurrentTCB @@ -110,6 +111,7 @@ _vector_14: .type func vldmiaeq r0!, {s16-s31} msr psp, r0 + isb bx r14 .size _vector_14, $-_vector_14 @@ -125,6 +127,7 @@ _vector_14: .type func _lc_ref__vector_pp_14: .type func mrs r0, psp + isb ;Get the location of the current TCB. ldr.w r3, =pxCurrentTCB @@ -162,6 +165,7 @@ _lc_ref__vector_pp_14: .type func vldmiaeq r0!, {s16-s31} msr psp, r0 + isb push { lr } pop { pc } ; XMC4000 specific errata workaround. Do not used "bx lr" here. @@ -181,6 +185,7 @@ SVC_Handler: .type func ;Pop the core registers. ldmia r0!, {r4-r11, r14} msr psp, r0 + isb mov r0, #0 msr basepri, r0 bx r14 @@ -201,6 +206,8 @@ vPortStartFirstTask .type func msr msp, r0 ;Call SVC to start the first task. cpsie i + dsb + isb svc 0 .size vPortStartFirstTask, $-vPortStartFirstTask .endsec diff --git a/FreeRTOS/Source/timers.c b/FreeRTOS/Source/timers.c index d29c071f4..5b389c2cf 100644 --- a/FreeRTOS/Source/timers.c +++ b/FreeRTOS/Source/timers.c @@ -242,12 +242,12 @@ portBASE_TYPE xReturn = pdFAIL; { /* Create the timer task, storing its handle in xTimerTaskHandle so it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */ - xReturn = xTaskCreate( prvTimerTask, ( const signed char * const ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle ); + xReturn = xTaskCreate( prvTimerTask, ( signed char * ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle ); } #else { /* Create the timer task without storing its handle. */ - xReturn = xTaskCreate( prvTimerTask, ( const signed char * const ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL); + xReturn = xTaskCreate( prvTimerTask, ( signed char * ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL); } #endif } -- 2.39.5