找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 3757|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

cc2531電源管理和節(jié)能

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:76127 發(fā)表于 2015-4-18 00:29 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
Power Modes

Active mode: The fully functional mode. The voltage regulator to the digital core is on, and either the
16-MHz RC oscillator or the 32-MHz crystal oscillator or both are running. Either the 32-kHz RCOSC or the 32-kHz XOSC is running.
Idle mode: Identical to active mode, except that the CPU core stops operating (is idle).
PM1: The voltage regulator to the digital part is on. Neither the 32-MHz XOSC nor the 16-MHz RCOSC is running. Either the 32-kHz RCOSC or the 32-kHz XOSC is running. The system goes to active mode on reset, an external interrupt, or when the Sleep Timer expires.
PM2: The voltage regulator to the digital core is turned off. Neither the 32-MHz XOSC nor the 16-MHz RCOSC is running. Either the 32-kHz RCOSC or the 32-kHz XOSC is running. The system goes to active mode on reset, an external interrupt, or when the Sleep Timer expires.
PM3: The voltage regulator to the digital core is turned off. None of the oscillators is running. The system goes to active mode on reset or an external interrupt.The POR is active in PM2/PM3, but the BOD is powered down, which gives a limited voltage supervision.
If the supply voltage is lowered to below 1.4 V during PM2/PM3, at temperatures of 70°C or higher, and then brought back up to good operating voltage before active mode is re-entered, registers and RAM contents that are saved in PM2/PM3 may become altered. Hence, care should be taken in the design of the system power supply to ensure that this does not occur. The voltage can be periodically supervised accurately by entering active mode, as a BOD reset is triggered if the supply voltage is below approximately 1.7 V.
The CC2533 and CC2541 have functionality to perform automatically a CRC check of the retained
configuration register values in PM2/PM3 to check that the device state was not altered during sleep. The bits in SRCRC.CRC_RESULT indicate whether there were any changes, and by enabling
SRCRC.CRC_RESET_EN, the device immediately resets itself with a watchdog reset if SRCRC.CRC_RESULT is not 00 (= CRC of retained registers passed) after wakeup from PM2/PM3. The SRCRC register also contains the SRCRC.FORCE_RESET bit that can be used by software to immediately trigger a watchdog reset to reboot the device.
必須滿足下面所有條件才能進(jìn)入休眠模式
1. ZDO節(jié)點(diǎn)描述符指定“Rx is off when idle,在f8wConfig.cfg文件中將RFD_RCVC_ALWAYS_ON設(shè)為false實(shí)現(xiàn)
2. 所有zstack 任務(wù)”贊同“進(jìn)入睡眠模式
3. zstack各個(gè)任務(wù)都沒(méi)有預(yù)定的活動(dòng)
4.MAC層沒(méi)有預(yù)定的活動(dòng)
cc2531和cc2530 zigbee協(xié)議棧工程中調(diào)用以下函數(shù)使設(shè)備進(jìn)入低功耗狀態(tài)。在這里(osal_pwrmgr_powerconserve()函數(shù)中),在嘗試進(jìn)入休眠模式時(shí)會(huì)做另外兩個(gè)檢查。首先,檢查變量pwrmgr_device是否被設(shè)置為電池設(shè)備。這項(xiàng)設(shè)定在設(shè)備入網(wǎng)后執(zhí)行—詳情見(jiàn)例程的ZDApp.c源文件。其次,檢查變量pwrmgr_task_state確認(rèn)沒(méi)有任務(wù)的節(jié)能狀態(tài)是“put a hold”。該機(jī)制允許每個(gè)Z-Stack任務(wù)在臨界區(qū)操作時(shí)禁止休眠。當(dāng)這兩個(gè)條件都滿足時(shí),預(yù)期的休眠時(shí)間取決于OSAL定時(shí)器的下一次溢出時(shí)間。如果下一次溢出時(shí)間大于0小于MIN_SLEEP_TIME,選擇SLEEP_LITE模式。在這種模式下,系統(tǒng)定時(shí)器被調(diào)整為首先到期的定時(shí)器事件提供一個(gè)“喚醒”中斷。MIN_SLEEP_TIME定義在hal_sleep.c中,為了防止很短時(shí)間的休眠。當(dāng)沒(méi)有預(yù)定的Z-Stack 事件或者定時(shí)器時(shí),選擇SLEEP_DEEP模式,因此下一次溢出時(shí)間為0,允許最大限度的節(jié)能:
void osal_pwrmgr_powerconserve( void )
{
  uint16        next;
  halIntState_t intState;
  // Should we even look into power conservation
  if ( pwrmgr_attribute.pwrmgr_device != PWRMGR_ALWAYS_ON )
  {
    // Are all tasks in agreement to conserve
    if ( pwrmgr_attribute.pwrmgr_task_state == 0 )
    {
      // Hold off interrupts.
      HAL_ENTER_CRITICAL_SECTION( intState );
      // Get next time-out
      next = osal_next_timeout();
      // Re-enable interrupts.
      HAL_EXIT_CRITICAL_SECTION( intState );
      // Put the processor into sleep mode
      OSAL_SET_CPU_INTO_SLEEP( next );
    }
  }
}
以上函數(shù)實(shí)際調(diào)用的是halSleep(),該函數(shù)通過(guò)對(duì)休眠時(shí)間,設(shè)定條件和堆棧分配情況的判斷來(lái)選擇節(jié)點(diǎn)進(jìn)入PM1,PM2,PM3。halSleep()函數(shù)被OSAL_SET_CPU_INTO_SLEEP調(diào)用,該函數(shù)執(zhí)行一系列有序的操作:關(guān)閉MAC層,關(guān)斷外設(shè),使MCU進(jìn)入休眠模式,休眠后喚醒MCU,開(kāi)啟外設(shè),最后重啟MAC層。Z-Stack OSAL主循環(huán)獨(dú)立運(yùn)行于MAC層,因此Z-Stack不知道MAC層的運(yùn)行狀態(tài)。調(diào)用MAC_PwrOffReq()函數(shù)可以關(guān)閉MAC層。需要注意的是,當(dāng)設(shè)置空閑時(shí)接收器使能會(huì)導(dǎo)致MAC層休眠時(shí)不關(guān)閉,這會(huì)阻止設(shè)備進(jìn)入休眠模式
/**************************************************************************************************
* @fn          halSleep
*
* @brief       This function is called from the OSAL task loop using and existing OSAL
*              interface.  It sets the low power mode of the MAC and the CC2530.
*
* input parameters
*
* @param       osal_timeout - Next OSAL timer timeout.
*
* output parameters
*
* None.
*
* @return      None.
**************************************************************************************************
*/
void halSleep( uint16 osal_timeout )
{
  uint32        timeout;
  uint32        macTimeout = 0;
  /* get next OSAL timer expiration converted to 320 usec units */
  timeout = HAL_SLEEP_MS_TO_320US(osal_timeout);
  if (timeout == 0)
  {
    timeout = MAC_PwrNextTimeout();
  }
  else
  {
    /* get next MAC timer expiration */
    macTimeout = MAC_PwrNextTimeout();
    /* get lesser of two timeouts */
    if ((macTimeout != 0) && (macTimeout < timeout))
    {
      timeout = macTimeout;
    }
  }
  /* HAL_SLEEP_PM2 is entered only if the timeout is zero and
   * the device is a stimulated device.
   */
  halPwrMgtMode = (timeout == 0) ? HAL_SLEEP_DEEP : HAL_SLEEP_TIMER;
  /* DEEP sleep can only be entered when zgPollRate == 0.
   * This is to eliminate any possibility of entering PM3 between
   * two network timers.
   */
#if ZG_BUILD_ENDDEVICE_TYPE && 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 ien0, ien1, ien2;
    HAL_ASSERT(HAL_INTERRUPTS_ARE_ENABLED());
    HAL_DISABLE_INTERRUPTS();
    /* always use "deep sleep" to turn off radio VREG on CC2530 */
    if (halSleepPconValue != 0 && MAC_PwrOffReq(MAC_PWR_SLEEP_DEEP) == MAC_SUCCESS)
    {
      /* The PCON value is not zero. There is no interrupt overriding the
       * sleep decision. Also, the radio granted the sleep request.
       */
#if ((defined HAL_KEY) && (HAL_KEY == TRUE))
      /* get peripherals ready for sleep */
      HalKeyEnterSleep();
#endif
#ifdef HAL_SLEEP_DEBUG_LED
      HAL_TURN_OFF_LED3();
#else
      /* use this to turn LEDs off during sleep */
      HalLedEnterSleep();
#endif
      if(timeout > maxSleepLoopTime)
      {
        timeout = maxSleepLoopTime;
      }
      /* 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 == CC2530_PM1)
      {
        HAL_TURN_ON_LED1();
      }
      else
      {
        HAL_TURN_OFF_LED1();
      }
#endif
      /* Prep CC2530 power mode */
      HAL_SLEEP_PREP_POWER_MODE(halPwrMgtMode);
      /* save interrupt enable registers and disable all interrupts */
      HAL_SLEEP_IE_BACKUP_AND_DISABLE(ien0, ien1, ien2);
      HAL_ENABLE_INTERRUPTS();
      /* set CC2530 power mode, interrupt is disabled after this function
       * Note that an ISR (that could wake up from power mode) which runs
       * between the previous instruction enabling interrupts and before
       * power mode is set would switch the halSleepPconValue so that
       * power mode shall not be entered in such a case.
       */
      HAL_SLEEP_SET_POWER_MODE();
      /* the interrupt is disabled - see halSetSleepMode() */
      /* restore interrupt enable registers */
      HAL_SLEEP_IE_RESTORE(ien0, ien1, ien2);
      /* disable sleep timer interrupt */
      HAL_SLEEP_TIMER_DISABLE_INT();
#ifdef HAL_SLEEP_DEBUG_LED
      HAL_TURN_ON_LED3();
#else
      /* use this to turn LEDs back on after sleep */
      HalLedExitSleep();
#endif
#if ((defined HAL_KEY) && (HAL_KEY == TRUE))
      /* handle peripherals */
      (void)HalKeyExitSleep();
#endif
      /* power on the MAC; blocks until completion */
      MAC_PwrOnReq();
      HAL_ENABLE_INTERRUPTS();
      /* For CC2530, T2 interrupt won抰 be generated when the current count is greater than
       * the comparator. The interrupt is only generated when the current count is equal to
       * the comparator. When the CC2530 is waking up from sleep, there is a small window
       * that the count may be grater than the comparator, therefore, missing the interrupt.
       * This workaround will call the T2 ISR when the current T2 count is greater than the
       * comparator. The problem only occurs when POWER_SAVING is turned on, i.e. the 32KHz
       * drives the chip in sleep and SYNC start is used.
       */
      macMcuTimer2OverflowWorkaround();
    }
    else
    {
      /* An interrupt may have changed the sleep decision. Do not sleep at all. Turn on
       * the interrupt, exit normally, and the next sleep will be allowed.
       */
      HAL_ENABLE_INTERRUPTS();
    }
  }
}






分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表