diff --git a/portable/ARMv8M/non_secure/port.c b/portable/ARMv8M/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/ARMv8M/non_secure/port.c +++ b/portable/ARMv8M/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM23/non_secure/port.c b/portable/GCC/ARM_CM23/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/GCC/ARM_CM23/non_secure/port.c +++ b/portable/GCC/ARM_CM23/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM23_NTZ/non_secure/port.c b/portable/GCC/ARM_CM23_NTZ/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/GCC/ARM_CM23_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM23_NTZ/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33/non_secure/port.c b/portable/GCC/ARM_CM33/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/GCC/ARM_CM33/non_secure/port.c +++ b/portable/GCC/ARM_CM33/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33_NTZ/non_secure/port.c b/portable/GCC/ARM_CM33_NTZ/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/GCC/ARM_CM33_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM33_NTZ/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM35P/non_secure/port.c b/portable/GCC/ARM_CM35P/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/GCC/ARM_CM35P/non_secure/port.c +++ b/portable/GCC/ARM_CM35P/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c b/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM55/non_secure/port.c b/portable/GCC/ARM_CM55/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/GCC/ARM_CM55/non_secure/port.c +++ b/portable/GCC/ARM_CM55/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM55_NTZ/non_secure/port.c b/portable/GCC/ARM_CM55_NTZ/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/GCC/ARM_CM55_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM55_NTZ/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM85/non_secure/port.c b/portable/GCC/ARM_CM85/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/GCC/ARM_CM85/non_secure/port.c +++ b/portable/GCC/ARM_CM85/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM85_NTZ/non_secure/port.c b/portable/GCC/ARM_CM85_NTZ/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/GCC/ARM_CM85_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM85_NTZ/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM23/non_secure/port.c b/portable/IAR/ARM_CM23/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/IAR/ARM_CM23/non_secure/port.c +++ b/portable/IAR/ARM_CM23/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM23_NTZ/non_secure/port.c b/portable/IAR/ARM_CM23_NTZ/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/IAR/ARM_CM23_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM23_NTZ/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM33/non_secure/port.c b/portable/IAR/ARM_CM33/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/IAR/ARM_CM33/non_secure/port.c +++ b/portable/IAR/ARM_CM33/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM33_NTZ/non_secure/port.c b/portable/IAR/ARM_CM33_NTZ/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/IAR/ARM_CM33_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM33_NTZ/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM35P/non_secure/port.c b/portable/IAR/ARM_CM35P/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/IAR/ARM_CM35P/non_secure/port.c +++ b/portable/IAR/ARM_CM35P/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c b/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM55/non_secure/port.c b/portable/IAR/ARM_CM55/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/IAR/ARM_CM55/non_secure/port.c +++ b/portable/IAR/ARM_CM55/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM55_NTZ/non_secure/port.c b/portable/IAR/ARM_CM55_NTZ/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/IAR/ARM_CM55_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM55_NTZ/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM85/non_secure/port.c b/portable/IAR/ARM_CM85/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/IAR/ARM_CM85/non_secure/port.c +++ b/portable/IAR/ARM_CM85/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM85_NTZ/non_secure/port.c b/portable/IAR/ARM_CM85_NTZ/non_secure/port.c index 9976daee49a..5b162a9bb1b 100644 --- a/portable/IAR/ARM_CM85_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM85_NTZ/non_secure/port.c @@ -393,7 +393,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; #if ( configUSE_TICKLESS_IDLE == 1 ) __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + uint32_t ulControlStatusValue, ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; TickType_t xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ @@ -422,7 +422,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); /* Use the SysTick current-value register to determine the number of * SysTick decrements remaining until the next tick interrupt. If the @@ -458,8 +458,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; /* Set the new reload value. */ portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Clear the SysTick count flag and set the count value back to - * zero. */ + /* Clear the SysTick count flag and set the count value back to 0. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Restart SysTick. */ @@ -497,17 +496,29 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; __asm volatile ( "dsb" ); __asm volatile ( "isb" ); - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can + /* + * Read the contents of the portNVIC_SYSTICK_CTRL_REG register into + * ulControlStatusValue to ensure portNVIC_SYSTICK_COUNT_FLAG_BIT is taken + * into account later on. + */ + ulControlStatusValue = portNVIC_SYSTICK_CTRL_REG; + + /* Disable the SysTick timer. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* + * The time the SysTick is stopped for 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_CONFIG | portNVIC_SYSTICK_INT_BIT ); + * time. + */ /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { uint32_t ulCalculatedLoadValue; @@ -531,6 +542,9 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * function exits, the tick value maintained by the tick is stepped * forward by one less than the time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } else { @@ -568,34 +582,64 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; } - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + /* + * Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load + * use the core clock. This configuration forces the SysTick to load * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ + * cycle of the external clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. + */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) { portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Enable SysTick */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; } #else { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + /* Temporarily switch to core clock */ + ulControlStatusValue |= portNVIC_SYSTICK_CLK_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Enable SysTick */ + ulControlStatusValue |= portNVIC_SYSTICK_ENABLE_BIT; + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Read portNVIC_SYSTICK_CTRL_REG into ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; + + /* Disable SysTick */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + /* Update ulControlStatusValue */ + ulControlStatusValue |= portNVIC_SYSTICK_CTRL_REG; - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + /* Switch back to external clock. */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_CLK_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; + + if( ( ulControlStatusValue & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) { /* The partial tick period already ended. Be sure the SysTick * counts it only once. */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + + /* Clear portNVIC_SYSTICK_COUNT_FLAG_BIT */ + ulControlStatusValue &= ~( portNVIC_SYSTICK_COUNT_FLAG_BIT ); } portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Enable SysTick */ + ulControlStatusValue |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); + portNVIC_SYSTICK_CTRL_REG = ulControlStatusValue; } #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ @@ -620,13 +664,26 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU } #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; + /* Stop the SysTick timer, clear the value. */ + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_ENABLE_BIT ); portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* Configure SysTick to interrupt at the requested rate. */ + /* Configure SysTick to interrupt at the requested rate with the request clock source. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + + /* Set or clear the portNVIC_SYSTICK_CLK_BIT as required. */ + + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_CLK_BIT; + } + #else /* portNVIC_SYSTICK_CLK_BIT_CONFIG == 0 */ + { + portNVIC_SYSTICK_CTRL_REG &= ~( portNVIC_SYSTICK_CLK_BIT_CONFIG ); + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_ENABLE_BIT | portNVIC_SYSTICK_INT_BIT ); } /*-----------------------------------------------------------*/