Advertisement
KiviE

low_power_tick_management.c

Aug 26th, 2015
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 22.98 KB | None | 0 0
  1. /*
  2.  *  FreeRTOS V7.4.2 - Copyright (C) 2013 Real Time Engineers Ltd.
  3.  *
  4.  *  FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME.  PLEASE VISIT
  5.  *  http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
  6.  *
  7.  ***************************************************************************
  8.  *                                                                       *
  9.  *    FreeRTOS tutorial books are available in pdf and paperback.        *
  10.  *    Complete, revised, and edited pdf reference manuals are also       *
  11.  *    available.                                                         *
  12.  *                                                                       *
  13.  *    Purchasing FreeRTOS documentation will not only help you, by       *
  14.  *    ensuring you get running as quickly as possible and with an        *
  15.  *    in-depth knowledge of how to use FreeRTOS, it will also help       *
  16.  *    the FreeRTOS project to continue with its mission of providing     *
  17.  *    professional grade, cross platform, de facto standard solutions    *
  18.  *    for microcontrollers - completely free of charge!                  *
  19.  *                                                                       *
  20.  *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *
  21.  *                                                                       *
  22.  *    Thank you for using FreeRTOS, and thank you for your support!      *
  23.  *                                                                       *
  24.  ***************************************************************************
  25.  *
  26.  *
  27.  *  This file is part of the FreeRTOS distribution.
  28.  *
  29.  *  FreeRTOS is free software; you can redistribute it and/or modify it under
  30.  *  the terms of the GNU General Public License (version 2) as published by the
  31.  *  Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
  32.  *
  33.  *  >>>>>>NOTE<<<<<< The modification to the GPL is included to allow you to
  34.  *  distribute a combined work that includes FreeRTOS without being obliged to
  35.  *  provide the source code for proprietary components outside of the FreeRTOS
  36.  *  kernel.
  37.  *
  38.  *  FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
  39.  *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  40.  *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  41.  *  details. You should have received a copy of the GNU General Public License
  42.  *  and the FreeRTOS license exception along with FreeRTOS; if not it can be
  43.  *  viewed here: http://www.freertos.org/a00114.html and also obtained by
  44.  *  writing to Real Time Engineers Ltd., contact details for whom are available
  45.  *  on the FreeRTOS WEB site.
  46.  *
  47.  *  1 tab == 4 spaces!
  48.  *
  49.  ***************************************************************************
  50.  *                                                                       *
  51.  *    Having a problem?  Start by reading the FAQ "My application does   *
  52.  *    not run, what could be wrong?"                                     *
  53.  *                                                                       *
  54.  *    http://www.FreeRTOS.org/FAQHelp.html                               *
  55.  *                                                                       *
  56.  ***************************************************************************
  57.  *
  58.  *
  59.  *  http://www.FreeRTOS.org - Documentation, books, training, latest versions,
  60.  *  license and Real Time Engineers Ltd. contact details.
  61.  *
  62.  *  http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
  63.  *  including FreeRTOS+Trace - an indispensable productivity tool, and our new
  64.  *  fully thread aware and reentrant UDP/IP stack.
  65.  *
  66.  *  http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
  67.  *  Integrity Systems, who sell the code with commercial support,
  68.  *  indemnification and middleware, under the OpenRTOS brand.
  69.  *
  70.  *  http://www.SafeRTOS.com - High Integrity Systems also provide a safety
  71.  *  engineered and independently SIL3 certified version for use in safety and
  72.  *  mission critical applications that require provable dependability.
  73.  */
  74.  
  75. /* Scheduler includes. */
  76. #include "FreeRTOS.h"
  77. #include "task.h"
  78.  
  79. /* emlib includes. */
  80. #include "em_cmu.h"
  81. #include "em_emu.h"
  82. #include "em_rtc.h"
  83. #include "em_burtc.h"
  84. #include "em_rmu.h"
  85. #include "em_int.h"
  86.  
  87. /* emdrv includes */
  88. #include "sleep.h"
  89.  
  90. #if (configUSE_SLEEP_MODE_IN_IDLE == 1)
  91. /**************************************************************************//**
  92.  * @brief vApplicationIdleHook
  93.  * Override the default definition of vApplicationIdleHook()
  94.  *****************************************************************************/
  95. void vApplicationIdleHook(void)
  96. {
  97.     SLEEP_Sleep();
  98. }
  99. #endif
  100.  
  101. /* Including only if tickless_idle is set to 1 or ( configUSE_TICKLESS_IDLE is set to 0  and  configUSE_SLEEP_MODE_IN_IDLE is set to 1 ) and EM2 or EM3 mode is choosed
  102.  * in other hand standard Cortex M3 FreeRTOS functions are used. */
  103. #if (((configUSE_TICKLESS_IDLE == 1) || ((configUSE_TICKLESS_IDLE == 0) && (configUSE_SLEEP_MODE_IN_IDLE == 1))) && (configSLEEP_MODE == 2 || configSLEEP_MODE == 3))
  104. /* Constants required to pend a PendSV interrupt from the tick ISR if the
  105.  * preemptive scheduler is being used.  These are just standard bits and registers
  106.  * within the Cortex-M core itself. */
  107. #define port_NVIC_INT_CTRL_REG     (*(( volatile unsigned long * ) 0xe000ed04))
  108. #define port_NVIC_PENDSVSET_BIT    (1UL << 28UL)
  109.  
  110. #if (configUSE_TICKLESS_IDLE == 1)
  111. /* Flag used only in EM2 and EM3 to get know whether
  112.  * sleep mode was exited because of an interrupt */
  113. static volatile bool intTickFlag = false;
  114. #endif /* (configUSE_TICKLESS_IDLE == 1) */
  115.  
  116. /* Preload value for RTC and BURTC counter */
  117. #define SYSTICK_LOAD_VALUE    ((configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ))
  118.  
  119. /*
  120.  * The number of SysTick increments that make up one tick period.
  121.  */
  122. static unsigned long ulTimerReloadValueForOneTick = 0;
  123. /*
  124.  * The maximum number of tick periods that can be suppressed is limited by the
  125.  * 24 bit resolution RTC and 32 bit BURTC.
  126.  */
  127. #if (configUSE_TICKLESS_IDLE == 1)
  128. static unsigned long xMaximumPossibleSuppressedTicks = 0;
  129.  
  130. /*
  131.  * Compensate for the CPU cycles that pass while the SysTick is stopped (low
  132.  * power functionality only.
  133.  */
  134.  
  135. static unsigned long ulStoppedTimerCompensation = 0;
  136. #endif /* (configUSE_TICKLESS_IDLE == 1) */
  137.  
  138. /* Functions which are used in EM2 mode*/
  139. #if (configSLEEP_MODE == 2)
  140. #define TIMER_CAPACITY        (0xFFFFFF)
  141. #if (configUSE_TICKLESS_IDLE == 1)
  142. #define TIMER_COMPENSATION    (45)
  143. #endif /* (configUSE_TICKLESS_IDLE == 1) */
  144.  
  145. /**************************************************************************//**
  146.  * @brief RTC_IRQHandler
  147.  * Interrupt Service Routine for RTC which is used as system tick counter in EM2
  148.  *****************************************************************************/
  149. void RTC_IRQHandler(void)
  150. {
  151.   /* If using preemption, also force a context switch. */
  152. #if (configUSE_PREEMPTION == 1)
  153.   port_NVIC_INT_CTRL_REG = port_NVIC_PENDSVSET_BIT;
  154. #endif /* (configUSE_PREEMPTION == 1) */
  155.   /* Set RTC interrupt to one system tick period*/
  156.   RTC_Enable(false);
  157.   RTC_CompareSet(0, ulTimerReloadValueForOneTick);
  158.   /* Restart the counter */
  159. #if (configUSE_TICKLESS_IDLE == 1)
  160.   /* Set flag that interrupt was made*/
  161.   intTickFlag = true;
  162. #endif /* (configUSE_TICKLESS_IDLE == 1) */
  163.  
  164.   /* Critical section which protect incrementing the tick*/
  165.   ( void ) portSET_INTERRUPT_MASK_FROM_ISR();
  166.   {
  167.     xTaskIncrementTick();
  168.   }
  169.   portCLEAR_INTERRUPT_MASK_FROM_ISR(0);
  170.   /* Clear interrupt */
  171.   RTC_IntClear(_RTC_IFC_MASK);
  172.   RTC_CounterReset();
  173. }
  174.  
  175. /**************************************************************************//**
  176.  * @brief vPortSetupTimerInterrupt
  177.  * Override the default definition of vPortSetupTimerInterrupt() that is weakly
  178.  * defined in the FreeRTOS Cortex-M3, which set source of system tick interrupt
  179.  *****************************************************************************/
  180. void vPortSetupTimerInterrupt(void)
  181. {
  182.   /* Set our data about timer used as system ticks*/
  183.   ulTimerReloadValueForOneTick = SYSTICK_LOAD_VALUE ;
  184.   #if (configUSE_TICKLESS_IDLE == 1)
  185.   xMaximumPossibleSuppressedTicks = TIMER_CAPACITY / (SYSTICK_LOAD_VALUE);
  186.   ulStoppedTimerCompensation      = TIMER_COMPENSATION / (configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ);
  187. #endif /* (configUSE_TICKLESS_IDLE == 1) */
  188.   /* Configure RTC as system tick source */
  189.   /* Structure of RTC init */
  190.   RTC_Init_TypeDef init;
  191. #if (configCRYSTAL_IN_EM2 == 1)
  192.   /* LFXO setup */
  193.   /* For cut D, use 70% boost */
  194. // this is already done in mains init()
  195. //  CMU->CTRL    = (CMU->CTRL & ~_CMU_CTRL_LFXOBOOST_MASK) | CMU_CTRL_LFXOBOOST_70PCENT;
  196. //  #if defined( EMU_AUXCTRL_REDLFXOBOOST )
  197. //  EMU->AUXCTRL = (EMU->AUXCTRL & ~_EMU_AUXCTRL_REDLFXOBOOST_MASK) | EMU_AUXCTRL_REDLFXOBOOST;
  198. //  #endif
  199. #else
  200.   /* RC oscillator */
  201.   CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
  202. #endif
  203.   /* Ensure LE modules are accessible */
  204.   CMU_ClockEnable(cmuClock_CORELE, true);
  205. #if (configCRYSTAL_IN_EM2 == 1)
  206.   /* Enable osc as LFACLK in CMU (will also enable oscillator if not enabled) */
  207.   CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO);
  208. #else
  209.   /* Enable osc as LFACLK in CMU (will also enable oscillator if not enabled) */
  210.   CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO);
  211. #endif
  212.   /* Set 2 times divider to reduce energy*/
  213.   CMU_ClockDivSet(cmuClock_RTC, configCLOCK_DIVIDER);
  214.  
  215.   /* Enable clock to RTC module */
  216.   CMU_ClockEnable(cmuClock_RTC, true);
  217.   init.enable   = false;
  218.   init.debugRun = false;
  219.   init.comp0Top = false;         /* Count to max value before wrapping */
  220.   /* Initialization of RTC */
  221.   RTC_Init(&init);
  222.  
  223.   /* Disable interrupt generation from RTC0 */
  224.   RTC_IntDisable(RTC_IFC_COMP0);
  225.  
  226.   /* Tick interrupt MUST execute at the lowest interrupt priority. */
  227.   NVIC_SetPriority(RTC_IRQn, 255);
  228.  
  229.   /* Enable interrupts */
  230.   NVIC_ClearPendingIRQ(RTC_IRQn);
  231.   NVIC_EnableIRQ(RTC_IRQn);
  232.   RTC_CompareSet(0, SYSTICK_LOAD_VALUE);
  233.   RTC_IntClear(RTC_IFC_COMP0);
  234.   RTC_IntEnable(RTC_IF_COMP0);
  235.   RTC_Enable(true);
  236.   //RTC_CounterReset();
  237. }
  238. #if (configUSE_TICKLESS_IDLE == 1)
  239. /**************************************************************************//**
  240.  * @brief vPortSuppressTicksAndSleep
  241.  * Override the default definition of vPortSuppressTicksAndSleep() that is weakly
  242.  * defined in the FreeRTOS Cortex-M3 port layer layer
  243.  *****************************************************************************/
  244. void vPortSuppressTicksAndSleep(portTickType xExpectedIdleTime)
  245. {
  246.   unsigned long ulReloadValue, ulCompleteTickPeriods;
  247.   portTickType  xModifiableIdleTime;
  248.   /* Make sure the SysTick reload value does not overflow the counter. */
  249.   if (xExpectedIdleTime > xMaximumPossibleSuppressedTicks)
  250.   {
  251.     xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
  252.   }
  253.  
  254.   /* Calculate the reload value required to wait xExpectedIdleTime
  255.    * tick periods.
  256.   */
  257.   ulReloadValue = (ulTimerReloadValueForOneTick * (xExpectedIdleTime ));
  258.   if (ulReloadValue > ulStoppedTimerCompensation)
  259.   {
  260.     ulReloadValue -= ulStoppedTimerCompensation;
  261.   }
  262.  
  263.   /* Stop the System Tick momentarily.  The time the System Tick is stopped for
  264.    * is accounted for as best it can be, but using the tickless mode will
  265.    * inevitably result in some tiny drift of the time maintained by the
  266.    * kernel with respect to calendar time. */
  267.  
  268.   /* Stop the RTC clock*/
  269.   RTC_Enable(false);
  270. /* Enter a critical section but don't use the taskENTER_CRITICAL()
  271.  * method as that will mask interrupts that should exit sleep mode. */
  272.   INT_Disable();
  273.  
  274.   /* The tick flag is set to false before sleeping.  If it is true when sleep
  275.    * mode is exited then sleep mode was probably exited because the tick was
  276.    * suppressed for the entire xExpectedIdleTime period. */
  277.   intTickFlag = false;
  278.   /* If a context switch is pending or a task is waiting for the scheduler
  279.    * to be unsuspended then abandon the low power entry. */
  280.   if (eTaskConfirmSleepModeStatus() == eAbortSleep)
  281.   {
  282.     RTC_Enable(true);
  283.     /* Re-enable interrupts - see comments above __disable_interrupt()
  284.      * call above. */
  285.     INT_Enable();
  286.   }
  287.   else
  288.   {
  289.     /* Set the new reload value. */
  290.     ulReloadValue -= RTC_CounterGet();
  291.     RTC_CompareSet(0, ulReloadValue);
  292.     /* Restart the counter*/
  293.     RTC_CounterReset();
  294.     /* Sleep until something happens.  configPRE_SLEEP_PROCESSING() can
  295.      * set its parameter to 0 to indicate that its implementation contains
  296.      * its own wait for interrupt or wait for event instruction, and so wfi
  297.      * should not be executed again.  However, the original expected idle
  298.      * time variable must remain unmodified, so a copy is taken. */
  299.     xModifiableIdleTime = xExpectedIdleTime;
  300.     configPRE_SLEEP_PROCESSING(xModifiableIdleTime);
  301.     if (xModifiableIdleTime > 0)
  302.     {
  303.       SLEEP_Sleep();
  304.       __DSB();
  305.       __ISB();
  306.     }
  307.     configPOST_SLEEP_PROCESSING(xExpectedIdleTime);
  308.     /* Stop SysTick.  Again, the time the SysTick is stopped for is
  309.      * accounted for as best it can be, but using the tickless mode will
  310.      * inevitably result in some tiny drift of the time maintained by the
  311.      * kernel with respect to calendar time. */
  312.  
  313.     /* Stop the RTC clock*/
  314.     RTC_Enable(false);
  315.     /* Re-enable interrupts */
  316.     INT_Enable();
  317.     if (intTickFlag != false)
  318.     {
  319.       /* The tick interrupt has already executed,
  320.        * Reset the alarm value with whatever remains of this tick period. */
  321.       RTC_CompareSet(0, TIMER_CAPACITY & (ulTimerReloadValueForOneTick - RTC_CounterGet()));
  322.  
  323.       /* The tick interrupt handler will already have pended the tick
  324.        * processing in the kernel.  As the pending tick will be
  325.        * processed as soon as this function exits, the tick value
  326.        * maintained by the tick is stepped forward by one less than the
  327.        * time spent waiting. */
  328.       ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
  329.     }
  330.     else
  331.     {
  332.       /* Some other interrupt than system tick ended the sleep.
  333.        * Calculate how many tick periods passed while the processor
  334.        * was waiting */
  335.       ulCompleteTickPeriods = RTC_CounterGet() / ulTimerReloadValueForOneTick;
  336.  
  337.       /* The reload value is set to whatever fraction of a single tick
  338.        * period remains. */
  339.       if (ulCompleteTickPeriods == 0)
  340.       {
  341.         ulReloadValue = ulTimerReloadValueForOneTick - RTC_CounterGet();
  342.       }
  343.       else
  344.       {
  345.         ulReloadValue = RTC_CounterGet() - (ulCompleteTickPeriods * ulTimerReloadValueForOneTick);
  346.       }
  347.       RTC_CompareSet(0, ulReloadValue);
  348.     }
  349.     /* Restart the RTCounter */
  350.     RTC_CounterReset();
  351.     /* The tick forward by the number of tick periods that
  352.      * remained in a low power state. */
  353.     vTaskStepTick(ulCompleteTickPeriods);
  354.   }
  355. }
  356. #endif /* (configUSE_TICKLESS_IDLE == 1) */
  357. #endif /* (configSLEEP_MODE == 2) */
  358.  
  359. /* Functions which are used in EM3 mode*/
  360. #if (configSLEEP_MODE == 3)
  361.  
  362. #define TIMER_CAPACITY        (0xFFFFFFFF)
  363. #if (configUSE_TICKLESS_IDLE == 1)
  364. #define TIMER_COMPENSATION    (45)
  365. #endif /* (configUSE_TICKLESS_IDLE == 1) */
  366. /**************************************************************************//**
  367.  * @brief BURTC_IRQHandler
  368.  * Interrupt Service Routine for RTC which is used as system tick counter in EM3
  369.  *****************************************************************************/
  370. void BURTC_IRQHandler(void)
  371. {
  372.   /* If using preemption, also force a context switch. */
  373. #if (configUSE_PREEMPTION == 1)
  374.   port_NVIC_INT_CTRL_REG = port_NVIC_PENDSVSET_BIT;
  375. #endif /* (configUSE_PREEMPTION == 1) */
  376.   /* Set BURTC interrupt to one system tick period*/
  377.   BURTC_Enable(false);
  378.   BURTC_CompareSet(0, ulTimerReloadValueForOneTick);
  379.   /* Restart the counter */
  380.   BURTC_CounterReset();
  381. #if (configUSE_TICKLESS_IDLE == 1)
  382.   /* Set flag that interrupt was made*/
  383.   intTickFlag = true;
  384. #endif /* (configUSE_TICKLESS_IDLE == 1) */
  385.   /* Critical section which protect incrementing the tick*/
  386.   ( void ) portSET_INTERRUPT_MASK_FROM_ISR();
  387.   {
  388.     xTaskIncrementTick();
  389.   }
  390.   portCLEAR_INTERRUPT_MASK_FROM_ISR(0);
  391.   /* Clear interrupt */
  392.   BURTC_IntClear(_RTC_IFC_MASK);
  393.   BURTC_CounterReset();
  394. }
  395.  
  396. /**************************************************************************//**
  397.  * @brief vPortSetupTimerInterrupt
  398.  * Override the default definition of vPortSetupTimerInterrupt() that is weakly
  399.  * defined in the FreeRTOS Cortex-M3, which set source of system tick interrupt
  400.  *****************************************************************************/
  401. void vPortSetupTimerInterrupt(void)
  402. {
  403.   /* Set our timer's data used as system ticks*/
  404.   ulTimerReloadValueForOneTick = SYSTICK_LOAD_VALUE;
  405. #if (configUSE_TICKLESS_IDLE == 1)
  406.   xMaximumPossibleSuppressedTicks = TIMER_CAPACITY / (SYSTICK_LOAD_VALUE);
  407.   ulStoppedTimerCompensation      = TIMER_COMPENSATION / (configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ);
  408. #endif /* (configUSE_TICKLESS_IDLE == 1) */
  409.   /* Ensure LE modules are accessible */
  410.   CMU_ClockEnable(cmuClock_CORELE, true);
  411.  
  412.   /* Enable access to BURTC registers */
  413.   RMU_ResetControl(rmuResetBU, false);
  414.  
  415.   /* Configure BURTC as system tick source */
  416.   BURTC_Init_TypeDef burtcInit = BURTC_INIT_DEFAULT;
  417.   burtcInit.mode   = burtcModeEM3;                      /* BURTC is enabled to EM3 */
  418.   burtcInit.clkSel = burtcClkSelULFRCO;                 /* Select ULFRCO as clock source */
  419.   burtcInit.clkDiv = burtcClkDiv_1;                     /* Choose 2kHz ULFRCO clock frequency */
  420.   /* Initialization of BURTC */
  421.   BURTC_Init(&burtcInit);
  422.  
  423.   /* Disable interrupt generation from BURTC */
  424.   BURTC_IntDisable(BURTC_IF_COMP0);
  425.  
  426.   /* Tick interrupt MUST execute at the lowest interrupt priority. */
  427.   NVIC_SetPriority(BURTC_IRQn, 255);
  428.  
  429.   /* Enable interrupts */
  430.   NVIC_ClearPendingIRQ(BURTC_IRQn);
  431.   NVIC_EnableIRQ(BURTC_IRQn);
  432.   BURTC_CompareSet(0, SYSTICK_LOAD_VALUE);
  433.   BURTC_IntClear(BURTC_IF_COMP0);
  434.   BURTC_IntEnable(BURTC_IF_COMP0);
  435.   BURTC_CounterReset();
  436. }
  437. #if (configUSE_TICKLESS_IDLE == 1)
  438. /**************************************************************************//**
  439.  * @brief vPortSetupTimerInterrupt
  440.  * Override the default definition of vPortSuppressTicksAndSleep() that is weakly
  441.  * defined in the FreeRTOS Cortex-M3 port layer layer
  442.  *****************************************************************************/
  443. void vPortSuppressTicksAndSleep(portTickType xExpectedIdleTime)
  444. {
  445.   unsigned long ulReloadValue, ulCompleteTickPeriods;
  446.   portTickType  xModifiableIdleTime;
  447.   /* Make sure the SysTick reload value does not overflow the counter. */
  448.   if (xExpectedIdleTime > xMaximumPossibleSuppressedTicks)
  449.   {
  450.     xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
  451.   }
  452.  
  453.   /* Calculate the reload value required to wait xExpectedIdleTime
  454.    * tick periods.  -1 is used because this code will execute part way
  455.    * through one of the tick periods, and the fraction of a tick period is
  456.    * accounted for later. */
  457.   ulReloadValue = (ulTimerReloadValueForOneTick * (xExpectedIdleTime ));
  458.   if (ulReloadValue > ulStoppedTimerCompensation)
  459.   {
  460.     ulReloadValue -= ulStoppedTimerCompensation;
  461.   }
  462.  
  463.   /* Stop the SysTick momentarily.  The time the SysTick is stopped for
  464.    * is accounted for as best it can be, but using the tickless mode will
  465.    * inevitably result in some tiny drift of the time maintained by the
  466.    * kernel with respect to calendar time. */
  467.   /* Stop the RTC clock*/
  468.   BURTC_Enable(false);
  469.   /* Enter a critical section but don't use the taskENTER_CRITICAL()
  470.    * method as that will mask interrupts that should exit sleep mode. */
  471.   INT_Disable();
  472.   /* The tick flag is set to false before sleeping.  If it is true when sleep
  473.    * mode is exited then sleep mode was probably exited because the tick was
  474.    * suppressed for the entire xExpectedIdleTime period. */
  475.   intTickFlag = false;
  476.   /* If a context switch is pending or a task is waiting for the scheduler
  477.    * to be unsuspended then abandon the low power entry. */
  478.   if (eTaskConfirmSleepModeStatus() == eAbortSleep)
  479.   {
  480.     BURTC_Enable(true);
  481.     /* Re-enable interrupts */
  482.     INT_Enable();
  483.   }
  484.   else
  485.   {
  486.     /* Set the new reload value. */
  487.     ulReloadValue -= BURTC_CounterGet();
  488.     BURTC_CompareSet(0, ulReloadValue);
  489.     /* Restart the counter*/
  490.     BURTC_CounterReset();
  491.     /* Sleep until something happens.  configPRE_SLEEP_PROCESSING() can
  492.      * set its parameter to 0 to indicate that its implementation contains
  493.      * its own wait for interrupt or wait for event instruction, and so wfi
  494.      * should not be executed again.  However, the original expected idle
  495.      * time variable must remain unmodified, so a copy is taken. */
  496.     xModifiableIdleTime = xExpectedIdleTime;
  497.     configPRE_SLEEP_PROCESSING(xModifiableIdleTime);
  498.     if (xModifiableIdleTime > 0)
  499.     {
  500.       SLEEP_Sleep();
  501.       __DSB();
  502.       __ISB();
  503.     }
  504.     configPOST_SLEEP_PROCESSING(xExpectedIdleTime);
  505.     /* Stop SysTick.  Again, the time the SysTick is stopped for is
  506.      * accounted for as best it can be, but using the tickless mode will
  507.      * inevitably result in some tiny drift of the time maintained by the
  508.      * kernel with respect to calendar time. */
  509.     BURTC_Enable(false);
  510.     /* Re-enable interrupts - see comments above __disable_interrupt()
  511.      * call above. */
  512.     INT_Enable();
  513.     if (intTickFlag != false)
  514.     {
  515.       /* The tick interrupt has already executed,
  516.        * Reset the alarm value with whatever remains of this tick period. */
  517.       BURTC_CompareSet(0, TIMER_CAPACITY & (ulTimerReloadValueForOneTick - BURTC_CounterGet()));
  518.       /* The tick interrupt handler will already have pended the tick
  519.        * processing in the kernel.  As the pending tick will be
  520.        * processed as soon as this function exits, the tick value
  521.        * maintained by the tick is stepped forward by one less than the
  522.        * time spent waiting. */
  523.       ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
  524.     }
  525.     else
  526.     {
  527.       /* Some other interrupt than system tick ended the sleep.
  528.        * Calculate how many tick periods passed while the processor
  529.        * was waiting */
  530.       ulCompleteTickPeriods = BURTC_CounterGet() / ulTimerReloadValueForOneTick;
  531.  
  532.       /* The reload value is set to whatever fraction of a single tick
  533.        * period remains. */
  534.       if (ulCompleteTickPeriods == 0)
  535.       {
  536.         ulReloadValue = ulTimerReloadValueForOneTick - BURTC_CounterGet();
  537.       }
  538.       else
  539.       {
  540.         ulReloadValue = BURTC_CounterGet() - (ulCompleteTickPeriods * ulTimerReloadValueForOneTick);
  541.       }
  542.       BURTC_CompareSet(0, ulReloadValue);
  543.     }
  544.     /* Restart the RTCounter*/
  545.     BURTC_CounterReset();
  546.     /* The tick forward by the number of tick periods that
  547.      * remained in a low power state. */
  548.     vTaskStepTick(ulCompleteTickPeriods);
  549.   }
  550. }
  551. #endif /* (configUSE_TICKLESS_IDLE == 1) */
  552. #endif /* (configSLEEP_MODE == 3) */
  553. #endif /* (((configUSE_TICKLESS_IDLE == 1) ||  (( configUSE_TICKLESS_IDLE == 0 ) && ( configUSE_SLEEP_MODE_IN_IDLE == 1 ))) && (configSLEEP_MODE == 2 || configSLEEP_MODE == 3)) */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement