📄 hal_sleep.c
字号:
/* DEEP sleep can only be entered when zgPollRate == 0.
* This is to eliminate any possibility of entering PM3 between
* two network timers.
*/
#if !defined (RTR_NWK) && defined (NWK_AUTO_POLL)
if ((timeout > HAL_SLEEP_MS_TO_320US(PM_MIN_SLEEP_TIME)) ||
(timeout == 0 && zgPollRate == 0))
#else
if ((timeout > HAL_SLEEP_MS_TO_320US(PM_MIN_SLEEP_TIME)) ||
(timeout == 0))
#endif
{
halIntState_t intState, ien0, ien1, ien2;
HAL_ENTER_CRITICAL_SECTION(intState);
/* always use "deep sleep" to turn off radio VREG on CC2430 */
if (MAC_PwrOffReq(MAC_PWR_SLEEP_DEEP) == MAC_SUCCESS)
{
while ( (HAL_SLEEP_MS_TO_320US(halAccumulatedSleepTime) < timeout) || (timeout == 0) )
{
/* get peripherals ready for sleep */
HalKeyEnterSleep();
#ifdef HAL_SLEEP_DEBUG_LED
HAL_TURN_OFF_LED3();
#else
/* use this to turn LEDs off during sleep */
HalLedEnterSleep();
#endif
/* set main clock source to RC oscillator for Rev B and Rev D */
HAL_SLEEP_SET_MAIN_CLOCK_RC();
/* enable sleep timer interrupt */
if (timeout != 0)
{
if (timeout > HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME ))
{
timeout -= HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME );
halSleepSetTimer(HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME ));
}
else
{
/* set sleep timer */
halSleepSetTimer(timeout);
}
/* set up sleep timer interrupt */
HAL_SLEEP_TIMER_CLEAR_INT();
HAL_SLEEP_TIMER_ENABLE_INT();
}
#ifdef HAL_SLEEP_DEBUG_LED
if (halPwrMgtMode == CC2430_PM1)
{
HAL_TURN_ON_LED1();
}
else
{
HAL_TURN_OFF_LED1();
}
#endif
/* save interrupt enable registers and disable all interrupts */
HAL_SLEEP_IE_BACKUP_AND_DISABLE(ien0, ien1, ien2);
/* This is to check if the stack is exceeding the disappearing
* RAM boundary of 0xF000. If the stack does exceed the boundary
* (unlikely), do not enter sleep until the stack is back to normal.
*/
if ( ((uint16)(*( __idata uint16*)(CSTK_PTR)) >= 0xF000) )
{
HAL_EXIT_CRITICAL_SECTION(intState);
/* AN044 - DELAYING EXTERNAL INTERRUPTS, do not relocate this line.
* it has to stay as close to PCON.IDLE = 1 as possible.
*/
//EXTERNAL_INTERRUPT_DELAY(); //屏蔽低功郝
/* set CC2430 power mode */
HAL_SLEEP_SET_POWER_MODE(halPwrMgtMode);
/* wake up from sleep */
HAL_ENTER_CRITICAL_SECTION(intState);
}
/* restore interrupt enable registers */
HAL_SLEEP_IE_RESTORE(ien0, ien1, ien2);
/* disable sleep timer interrupt */
HAL_SLEEP_TIMER_DISABLE_INT();
/* set main clock source to crystal for Rev B and Rev D only */
HAL_SLEEP_SET_MAIN_CLOCK_CRYSTAL();
/* Calculate timer elasped */
halAccumulatedSleepTime += (HalTimerElapsed() / TICK_COUNT);
/* deduct the sleep time for the next iteration */
if ( osal_timeout > halAccumulatedSleepTime)
{
osal_timeout -= halAccumulatedSleepTime;
}
/* if the remaining time is less than the PM_MIN_SLEEP_TIME
* burn the remaining time in a delay loop
* AN044 - MINIMUM SLEEP PERIODS WITH PULL-DOWN RESISTOR
*/
if ( osal_timeout < PM_MIN_SLEEP_TIME )
{
halSleepWait(osal_timeout*1000);
halAccumulatedSleepTime += osal_timeout;
osal_timeout = halAccumulatedSleepTime;
}
#ifdef HAL_SLEEP_DEBUG_LED
HAL_TURN_ON_LED3();
#else
/* use this to turn LEDs back on after sleep */
HalLedExitSleep();
#endif
/* handle peripherals; exit loop if key presses */
if ( HalKeyExitSleep() )
{
#if defined (PM2_HOLDOFF_TIME) && (PM2_HOLDOFF_TIME > 0)
/* The deepest sleep alowwed is PM1 until after the timer expired
* AN044 - COMBINING POWER MODES
*/
halSleepLevel = CC2430_PM1;
osal_stop_timerEx (Hal_TaskID, HAL_SLEEP_TIMER_EVENT);
osal_start_timerEx (Hal_TaskID, HAL_SLEEP_TIMER_EVENT, PM2_HOLDOFF_TIME);
#endif /* (PM2_HOLDOFF_TIME > 0) */
break;
}
/* exit loop if no timer active */
if ( timeout == 0 ) break;
}
/* power on the MAC; blocks until completion */
MAC_PwrOnReq();
/* adjust OSAL timers */
osal_adjust_timers();
}
HAL_EXIT_CRITICAL_SECTION(intState);
}
}
/**************************************************************************************************
* @fn halSleepSetTimer
*
* @brief This function sets the CC2430 sleep timer compare value. First it reads and
* stores the value of the sleep timer; this value is used later to update OSAL
* timers. Then the timeout value is converted from 320 usec units to 32 kHz
* period units and the compare value is set to the timeout.
*
* input parameters
*
* @param timeout - Timeout value in 320 usec units. The sleep timer compare is set to
* this value.
*
* output parameters
*
* None.
*
* @return None.
**************************************************************************************************
*/
void halSleepSetTimer(uint32 timeout)
{
uint32 ticks;
/* read the sleep timer; ST0 must be read first */
((uint8 *) &ticks)[UINT32_NDX0] = ST0;
((uint8 *) &ticks)[UINT32_NDX1] = ST1;
((uint8 *) &ticks)[UINT32_NDX2] = ST2;
((uint8 *) &ticks)[UINT32_NDX3] = 0;
/* store value for later */
halSleepTimerStart = ticks;
/* Compute sleep timer compare value. The ratio of 32 kHz ticks to 320 usec ticks
* is 32768/3125 = 10.48576. This is nearly 671/64 = 10.484375.
*/
ticks += (timeout * 671) / 64;
/* subtract the processing time spent in function halSleep() */
ticks -= HAL_SLEEP_ADJ_TICKS;
/* CC2430 Rev. B bug: compare value must not be set higher than 0xFFFF7F */
if((ticks & 0xFFFFFF) > 0xFFFF7F)
{
ticks = 0xFFFF7F;
}
/* set sleep timer compare; ST0 must be written last */
ST2 = ((uint8 *) &ticks)[UINT32_NDX2];
ST1 = ((uint8 *) &ticks)[UINT32_NDX1];
ST0 = ((uint8 *) &ticks)[UINT32_NDX0];
}
/**************************************************************************************************
* @fn TimerElapsed
*
* @brief Determine the number of OSAL timer ticks elapsed during sleep.
*
* input parameters
*
* @param None.
*
* output parameters
*
* None.
*
* @return Number of timer ticks elapsed during sleep.
**************************************************************************************************
*/
uint32 TimerElapsed( void )
{
return ( halAccumulatedSleepTime );
}
/**************************************************************************************************
* @fn HalTimerElapsed
*
* @brief Determine the number of OSAL timer ticks elapsed during sleep. This function
* relies on OSAL macro TICK_COUNT to be set to 1; then ticks are calculated in
* units of msec. (Setting TICK_COUNT to 1 avoids a costly uint32 divide.)
*
* input parameters
*
* @param None.
*
* output parameters
*
* None.
*
* @return Number of timer ticks elapsed during sleep.
**************************************************************************************************
*/
uint32 HalTimerElapsed( void )
{
uint32 ticks;
/* read the sleep timer; ST0 must be read first */
((uint8 *) &ticks)[UINT32_NDX0] = ST0;
((uint8 *) &ticks)[UINT32_NDX1] = ST1;
((uint8 *) &ticks)[UINT32_NDX2] = ST2;
/* set bit 24 to handle wraparound */
((uint8 *) &ticks)[UINT32_NDX3] = 0x01;
/* calculate elapsed time */
ticks -= halSleepTimerStart;
/* add back the processing time spent in function halSleep() */
ticks += HAL_SLEEP_ADJ_TICKS;
/* mask off excess if no wraparound */
ticks &= 0x00FFFFFF;
/* Convert elapsed time in milliseconds with round. 1000/32768 = 125/4096 */
return ( ((ticks * 125) + 4095) / 4096 );
}
/**************************************************************************************************
* @fn halSleepWait
*
* @brief Perform a blocking wait.
*
* input parameters
*
* @param duration - Duration of wait in microseconds.
*
* output parameters
*
* None.
*
* @return None.
**************************************************************************************************
*/
void halSleepWait(uint16 duration)
{
while (duration--)
{
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
}
}
/**************************************************************************************************
* @fn halRestoreSleepLevel
*
* @brief Restore the deepest timer sleep level.
*
* input parameters
*
* @param None
*
* output parameters
*
* None.
*
* @return None.
**************************************************************************************************
*/
void halRestoreSleepLevel( void )
{
halSleepLevel = CC2430_PM2;
}
/**************************************************************************************************
* @fn halSleepTimerIsr
*
* @brief Sleep timer ISR.
*
* input parameters
*
* None.
*
* output parameters
*
* None.
*
* @return None.
**************************************************************************************************
*/
HAL_ISR_FUNCTION(halSleepTimerIsr, ST_VECTOR)
{
HAL_SLEEP_TIMER_CLEAR_INT();
if( CHVER >= REV_E )
{
CLEAR_SLEEP_MODE();
}
#ifdef HAL_SLEEP_DEBUG_POWER_MODE
halSleepInt = TRUE;
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -