]> 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
Add Pearl Gecko demo.
[freertos] / FreeRTOS / Demo / CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio / Source / Low_Power_Demo / low_power_tick_management_BURTC.c
index 6f3e3808547cbfce886682fab2df29e94b275c3b..218dd7a4cd94ec262763caaefd5cb14dfe178a65 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.\r
+    FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.\r
     All rights reserved\r
 \r
     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
@@ -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 set to take into account a partial time slice, but\r
+       just reading the count assumes it is counting up to a full ticks worth - so\r
+       add in the difference 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,19 +320,20 @@ TickType_t xModifiableIdleTime;
 \r
 void BURTC_IRQHandler( void )\r
 {\r
-       if( ulTickFlag == pdFALSE )\r
+       ulTickFlag = pdTRUE;\r
+\r
+       if( BURTC_CompareGet( 0 ) != ulReloadValueForOneTick )\r
        {\r
                /* Set BURTC 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
-       BURTC_IntClear( _RTC_IFC_MASK );\r
+       BURTC_IntClear( _BURTC_IFC_MASK );\r
 \r
-       /* Critical section which protect incrementing the tick*/\r
-       ( void ) portSET_INTERRUPT_MASK_FROM_ISR();\r
+       /* Critical section which protect incrementing the tick*/\r
+       portDISABLE_INTERRUPTS();\r
        {\r
                if( xTaskIncrementTick() != pdFALSE )\r
                {\r
@@ -325,7 +341,7 @@ void BURTC_IRQHandler( void )
                        portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
                }\r
        }\r
-       portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );\r
+       portENABLE_INTERRUPTS();\r
 }\r
 \r
 #endif /* ( configCREATE_LOW_POWER_DEMO == 1 ) */\r