找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3215|回复: 0
打印 上一主题 下一主题
收起左侧

cc2531电源管理和节能

[复制链接]
跳转到指定楼层
楼主
ID:76127 发表于 2015-4-18 00:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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.
必须满足下面所有条件才能进入休眠模式
1. ZDO节点描述符指定“Rx is off when idle,在f8wConfig.cfg文件中将RFD_RCVC_ALWAYS_ON设为false实现
2. 所有zstack 任务”赞同“进入睡眠模式
3. zstack各个任务都没有预定的活动
4.MAC层没有预定的活动
cc2531和cc2530 zigbee协议栈工程中调用以下函数使设备进入低功耗状态。在这里(osal_pwrmgr_powerconserve()函数中),在尝试进入休眠模式时会做另外两个检查。首先,检查变量pwrmgr_device是否被设置为电池设备。这项设定在设备入网后执行—详情见例程的ZDApp.c源文件。其次,检查变量pwrmgr_task_state确认没有任务的节能状态是“put a hold”。该机制允许每个Z-Stack任务在临界区操作时禁止休眠。当这两个条件都满足时,预期的休眠时间取决于OSAL定时器的下一次溢出时间。如果下一次溢出时间大于0小于MIN_SLEEP_TIME,选择SLEEP_LITE模式。在这种模式下,系统定时器被调整为首先到期的定时器事件提供一个“唤醒”中断。MIN_SLEEP_TIME定义在hal_sleep.c中,为了防止很短时间的休眠。当没有预定的Z-Stack 事件或者定时器时,选择SLEEP_DEEP模式,因此下一次溢出时间为0,允许最大限度的节能:
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 );
    }
  }
}
以上函数实际调用的是halSleep(),该函数通过对休眠时间,设定条件和堆栈分配情况的判断来选择节点进入PM1,PM2,PM3。halSleep()函数被OSAL_SET_CPU_INTO_SLEEP调用,该函数执行一系列有序的操作:关闭MAC层,关断外设,使MCU进入休眠模式,休眠后唤醒MCU,开启外设,最后重启MAC层。Z-Stack OSAL主循环独立运行于MAC层,因此Z-Stack不知道MAC层的运行状态。调用MAC_PwrOffReq()函数可以关闭MAC层。需要注意的是,当设置空闲时接收器使能会导致MAC层休眠时不关闭,这会阻止设备进入休眠模式
/**************************************************************************************************
* @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空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表