cc2531电源管理和节能

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();

    }

  }

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值