]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio/Source/Low_Power_Demo/low_power_tick_management_BURTC.c
Test the RTC and BURTC tickless implementations on the Gecko parts, and make correct...
[freertos] / FreeRTOS / Demo / CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio / Source / Low_Power_Demo / low_power_tick_management_BURTC.c
index 6f3e3808547cbfce886682fab2df29e94b275c3b..6f3e51c2d03c7fb4549390f116a0a22e6b4caf55 100644 (file)
@@ -150,7 +150,7 @@ BURTC_Init_TypeDef xBURTCInitStruct = BURTC_INIT_DEFAULT;
        BURTC_Init( &xBURTCInitStruct );\r
 \r
        /* The tick interrupt must be set to the lowest priority possible. */\r
-       NVIC_SetPriority( BURTC_IRQn, configKERNEL_INTERRUPT_PRIORITY );\r
+       NVIC_SetPriority( BURTC_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY );\r
        NVIC_ClearPendingIRQ( BURTC_IRQn );\r
        NVIC_EnableIRQ( BURTC_IRQn );\r
        BURTC_CompareSet( 0, ulReloadValueForOneTick );\r
@@ -162,7 +162,7 @@ BURTC_Init_TypeDef xBURTCInitStruct = BURTC_INIT_DEFAULT;
 \r
 void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )\r
 {\r
-uint32_t ulReloadValue, ulCompleteTickPeriods, ulCurrentCount;\r
+uint32_t ulReloadValue, ulCompleteTickPeriods, ulCountBeforeSleep, ulCountAfterSleep;\r
 eSleepModeStatus eSleepAction;\r
 TickType_t xModifiableIdleTime;\r
 \r
@@ -189,12 +189,20 @@ TickType_t xModifiableIdleTime;
        result in some tiny drift of the time maintained by the kernel with respect\r
        to calendar time.  The count is latched before stopping the timer as\r
        stopping the timer appears to clear the count. */\r
-       ulCurrentCount = BURTC_CounterGet();\r
+       ulCountBeforeSleep = BURTC_CounterGet();\r
        BURTC_Enable( false );\r
 \r
+       /* If this function is re-entered before one complete tick period then the\r
+       reload value might be to take into account a partial tick, but just reading\r
+       the count assumes it is counting up to a full ticks worth - so add in the\r
+       different if any. */\r
+       ulCountBeforeSleep += ( ulReloadValueForOneTick - BURTC_CompareGet( 0 ) );\r
+\r
        /* Enter a critical section but don't use the taskENTER_CRITICAL() method as\r
        that will mask interrupts that should exit sleep mode. */\r
        INT_Disable();\r
+       __asm volatile( "dsb" );\r
+       __asm volatile( "isb" );\r
 \r
        /* The tick flag is set to false before sleeping.  If it is true when sleep\r
        mode is exited then sleep mode was probably exited because the tick was\r
@@ -209,7 +217,7 @@ TickType_t xModifiableIdleTime;
        {\r
                /* Restart tick and count up to whatever was left of the current time\r
                slice. */\r
-               BURTC_CompareSet( 0, ulReloadValueForOneTick - ulCurrentCount );\r
+               BURTC_CompareSet( 0, ( ulReloadValueForOneTick - ulCountBeforeSleep ) + ulStoppedTimerCompensation );\r
                BURTC_Enable( true );\r
 \r
                /* Re-enable interrupts - see comments above the cpsid instruction()\r
@@ -220,7 +228,7 @@ TickType_t xModifiableIdleTime;
        {\r
                /* Adjust the reload value to take into account that the current time\r
                slice is already partially complete. */\r
-               ulReloadValue -= ulCurrentCount;\r
+               ulReloadValue -= ulCountBeforeSleep;\r
                BURTC_CompareSet( 0, ulReloadValue );\r
 \r
                /* Restart the BURTC. */\r
@@ -248,12 +256,14 @@ TickType_t xModifiableIdleTime;
                result in some tiny drift of the time maintained by the kernel with\r
                respect to calendar time.  The count value is latched before stopping\r
                the timer as stopping the timer appears to clear the count. */\r
-               ulCurrentCount = BURTC_CounterGet();\r
+               ulCountAfterSleep = BURTC_CounterGet();\r
                BURTC_Enable( false );\r
 \r
                /* Re-enable interrupts - see comments above the cpsid instruction()\r
                above. */\r
                INT_Enable();\r
+               __asm volatile( "dsb" );\r
+               __asm volatile( "isb" );\r
 \r
                if( ulTickFlag != pdFALSE )\r
                {\r
@@ -261,7 +271,7 @@ TickType_t xModifiableIdleTime;
                        function is called with the scheduler suspended the actual tick\r
                        processing will not occur until after this function has exited.\r
                        Reset the reload value with whatever remains of this tick period. */\r
-                       ulReloadValue = ulReloadValueForOneTick - ulCurrentCount;\r
+                       ulReloadValue = ulReloadValueForOneTick - ulCountAfterSleep;\r
                        BURTC_CompareSet( 0, ulReloadValue );\r
 \r
                        /* The tick interrupt handler will already have pended the tick\r
@@ -275,12 +285,17 @@ TickType_t xModifiableIdleTime;
                {\r
                        /* Something other than the tick interrupt ended the sleep.  How\r
                        many complete tick periods passed while the processor was\r
-                       sleeping? */\r
-                       ulCompleteTickPeriods = ulCurrentCount / ulReloadValueForOneTick;\r
+                       sleeping?  Add back in the adjustment that was made to the reload\r
+                       value to account for the fact that a time slice was part way through\r
+                       when this function was called. */\r
+                       ulCountAfterSleep += ulCountBeforeSleep;\r
+                       ulCompleteTickPeriods = ulCountAfterSleep / ulReloadValueForOneTick;\r
 \r
                        /* The reload value is set to whatever fraction of a single tick\r
                        period remains. */\r
-                       ulReloadValue = ulCurrentCount - ( ulCompleteTickPeriods * ulReloadValueForOneTick );\r
+                       ulCountAfterSleep -= ( ulCompleteTickPeriods * ulReloadValueForOneTick );\r
+                       ulReloadValue = ulReloadValueForOneTick - ulCountAfterSleep;\r
+\r
                        if( ulReloadValue == 0 )\r
                        {\r
                                /* There is no fraction remaining. */\r
@@ -305,12 +320,13 @@ TickType_t xModifiableIdleTime;
 \r
 void BURTC_IRQHandler( void )\r
 {\r
-       if( ulTickFlag == pdFALSE )\r
+       ulTickFlag = pdTRUE;\r
+\r
+       if( RTC_CompareGet( 0 ) != ulReloadValueForOneTick )\r
        {\r
-               /* Set BURTC interrupt to one RTOS tick period. */\r
+               /* Set RTC interrupt to one RTOS tick period. */\r
                BURTC_Enable( false );\r
                BURTC_CompareSet( 0, ulReloadValueForOneTick );\r
-               ulTickFlag = pdTRUE;\r
                BURTC_Enable( true );\r
        }\r
 \r