ZIGBEE--CC2430低功耗模式

来源:互联网 发布:淘宝卖零食的店铺 编辑:程序博客网 时间:2024/04/26 03:05
使用的协议栈版本信息: ZigBee2006\ZStack-1.4.3-1.2.1

       The CC2430 has four major power modes, called PM0, PM1, PM2 and PM3. PM0 is the active mode while PM3 has the lowest power consumption. The power modes are shown in Table 23 together with voltage regulator and oscillator options.

CC2430低功耗模式 - 小峰 - happy~

 

PM0  : The full functional mode. The voltage regulator to the digital core is on and either the HS-RCOSC or the 32 MHz XOSC or both are running. Either the 32.768 kHz RCOSC or the 32.768 kHz XOSC is running.
(PM0 is the full functional mode of operation where the CPU, peripherals and RF transceiver are active. The voltage
regulator is turned on. PM0 is used for normal operation.)

PM1  : The voltage regulator to the digital part is on. Neither the 32 MHz XOSC nor the HS-RCOSC are running. Either the 32.768 kHz RCOSC or the 32.768 kHz XOSC is running. The system will go to  PM0 on reset or an external interrupt or when the sleep timer expires.
(In PM1, the high-speed oscillators are powered down. The voltage regulator and the 32.768 kHz oscillators are on. When PM1 is entered, a power down sequence is run. When the device is taken out of PM1 to PM0, the high-speed oscillators are started. The device will run on the high speed RC oscillator until the high speed XOSC has settled. 
PM1 is used when the expected time until a wakeup event is relatively short since PM1 uses a fast power down/up sequence. )

PM2 : The voltage regulator to the digital core is turned off. Neither the 32 MHz XOSC nor the HS-RCOSC are running. Either the 32.768 kHz RCOSC or the 32.768 kHz XOSC is running. The system will go to PM0 on reset or an external interrupt or when the sleep timer expires.
(PM2 has the second lowest power consumption. In stand-by mode the power-on reset, external interrupts, 32.768 kHz oscillator and sleep timer peripherals are active. All other internal circuits are powered down. The voltage regulator is also turned off. When PM2 is entered, a power down sequence is run. PM2 is used when the expected time until a wakeup event is relatively long since the power up/down sequence is relatively long. PM2 is typically entered when using the sleep timer. )

PM3 : The voltage regulator to the digital core is turned off. None of the oscillators are running. The system will go to PM0 on reset or an external interrupt.
(PM3 is used to achieve the operating mode with the lowest power consumption. In PM3 all internal circuits that are powered from the voltage regulator are turned off. The internal voltage regulator and all oscillators are also turned off. Power-on reset and external interrupts are the only functions that are operating in power-down mode, thus only a reset or external interrupt condition will wake the device up and place it into active mode. The contents of RAM and registers are preserved in power-down mode. PM3 uses the same power down/up sequence as PM2. PM3 is used to achieve ultra low power consumption when waiting for an external event.)

 

协议栈对低功耗模式的配置:(具体参见hal_sleep.c)

//---------------------------------------------------
/* POWER CONSERVATION DEFINITIONS
 * Sleep mode H/W definitions (enabled with POWER_SAVING compile option)
 */

#define CC2430_PM0            0  /* PM0, Clock oscillators on, voltage regulator on */
#define CC2430_PM1            1  /* PM1, 32.768 kHz oscillators on, voltage regulator on */
#define CC2430_PM2            2  /* PM2, 32.768 kHz oscillators on, voltage regulator off */
#define CC2430_PM3            3 
/* PM3, All clock oscillators off, voltage regulator off */

//---------------------------------------------------
/* HAL power management mode is set according to the power management state. The default
 * setting is HAL_SLEEP_OFF.
The actual value is tailored to different HW platform. Both
 * HAL_SLEEP_TIMER and HAL_SLEEP_DEEP selections will:
 *   1. turn off the system clock, and
 *   2. halt the MCU.
 * HAL_SLEEP_TIMER can be woken up by sleep timer interrupt, I/O interrupt and reset.!!
 * HAL_SLEEP_DEEP can be woken up by I/O interrupt and reset.!!
 */

#define HAL_SLEEP_OFF         CC2430_PM0    //PM0
#define HAL_SLEEP_TIMER       CC2430_PM2  //PM2
#define HAL_SLEEP_DEEP        CC2430_PM3  
//PM3

//---------------------------------------------------最大最小睡眠时间

/* MAX_SLEEP_TIME calculation: 
 *   Sleep timer maximum duration = 0xFFFF7F / 32768 Hz = 511.996 seconds
 *   Round it to 510 seconds or 510000 ms (四舍五入)
 */
#define MAX_SLEEP_TIME                   510000           
  /* maximum time to sleep allowed by ST */

/* minimum time to sleep, this macro is to:
 * 1. avoid thrashing in-and-out of sleep with short OSAL timer (~2ms)
 * 2. define minimum safe sleep period for different CC2430 revisions
 * AN044 - MINIMUM SLEEP PERIODS WITH PULL-DOWN RESISTOR
 */
#if !defined (PM_MIN_SLEEP_TIME)
#define PM_MIN_SLEEP_TIME                14                 /* default to minimum safe sleep time for CC2430 Rev B */
#endif

//---------------------------------------------------
/* HAL power management mode is set according to the power management state.
 */
static uint8 halPwrMgtMode = HAL_SLEEP_OFF;  //PM0

/* stores the sleep timer count upon entering sleep */
static uint32 halSleepTimerStart;  
//当进入睡眠时存储睡眠定时器计数值

/* stores the accumulated sleep time */
static uint32 halAccumulatedSleepTime; 
//存储睡眠定时器累积的计数值

/* stores the deepest level the device is allowed to sleep
 * See AN044 - COMBINING POWER MODES
 */
static uint8 halSleepLevel = CC2430_PM2;  
//PM2 2

#ifdef HAL_SLEEP_DEBUG_POWER_MODE
static bool halSleepInt = FALSE;
#endif

//---------------------------------------------------

OSAL_PwrMgr.h中:睡眠模式相关属性参数

/* These attributes define sleep beheaver. The attributes can be changed
 * for each sleep cycle or when the device characteristic change.
 */
typedef struct
{
  uint16 pwrmgr_task_state;
  uint16 pwrmgr_next_timeout;
  uint16 accumulated_sleep_time;
  uint8  pwrmgr_device;
} pwrmgr_attribute_t;

/* With PWRMGR_ALWAYS_ON selection, there is no power savings and the
 * device is most likely on mains power. The PWRMGR_BATTERY selection allows
 * the HAL sleep manager to enter SLEEP LITE state or SLEEP DEEP state.
 */
#define PWRMGR_ALWAYS_ON  0
#define PWRMGR_BATTERY    1

/* The PWRMGR_CONSERVE selection turns power savings on, all tasks have to
 * agree. The PWRMGR_HOLD selection turns power savings off.
 */
#define PWRMGR_CONSERVE 0
#define PWRMGR_HOLD     1

//---------------------------------------------------
OSAL_pwrmgr.c中:

With PWRMGR_ALWAYS_ON selection, there is no power savings and
the device is most likely on mains power
. The PWRMGR_BATTERY
selection allows the HAL sleep manager to enter sleep.

void osal_pwrmgr_init( void )
{
//  pwrmgr_attribute.pwrmgr_device = PWRMGR_BATTERY;
  pwrmgr_attribute.pwrmgr_device = PWRMGR_ALWAYS_ON;   // Default to no power conservation.
  pwrmgr_attribute.pwrmgr_task_state = 0;            // Cleared.  All set to conserve
}


//********************************************************
void halSleep( uint16 osal_timeout )
{
  uint32        timeout;
  uint32        macTimeout;

  halAccumulatedSleepTime = 0;  //睡眠定时器累积的计数值
 
//-----------------------------------
  /* get next OSAL timer expiration converted to 320 usec units */
  //把osal_timeout转换成以320微秒为单位的时间值
  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.
   */ //timeout=0 且 device =stimulated device
  //timeout!=0则halPwrMgtMode=HAL_SLEEP_TIMER PM2 2
  //timeout=0则halPwrMgtMode=HAL_SLEEP_DEEP PM3 3

  halPwrMgtMode = (timeout == 0) ? HAL_SLEEP_DEEP : HAL_SLEEP_TIMER;
 
//-----------------------------------
  /* The sleep mode is also controlled by halSleepLevel which
   * defined the deepest level of sleep allowed. This is applied
   * to timer sleep only.
   */

  //halSleepLevel = CC2430_PM2 = 2
  if ( timeout > 0 && halPwrMgtMode > halSleepLevel )  //PM3 深度睡眠
  {
    halPwrMgtMode = halSleepLevel;
  }

//----------------------------------- 
  /* Allow PM1 only.
   * AN044 - RESTRICT USE TO PM1 ONLY
   */

#if defined (PM1_ONLY) && (PM1_ONLY == TRUE)
    if (timeout > 0)
    {
      halPwrMgtMode = CC2430_PM1;
    }
    else
    {
      /* do not allow PM3 either */
      return;
    }
#endif
 
//-----------------------------------
  /* 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
    //timeout=0或<最小睡眠时间
  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 */
        //设置主时钟,准备进入睡眠. RC osc

        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 );
            ////设置sleeptimer定时时间
            halSleepSetTimer(HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME ));
          }
          else
          {
            /* set sleep timer */
            //设置sleeptimer定时时间

            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.
         */
        //检测有没有超出RAM界限

        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 */
        //设置主时钟,退出睡眠. 32MHx XOSC

        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 */
      //开RF振荡器

      MAC_PwrOnReq();

      /* adjust OSAL timers */
      //调整系统时间

      osal_adjust_timers();

    }

    HAL_EXIT_CRITICAL_SECTION(intState);
  }
}
//********************************************************

 低功耗这块内容一直没有实验成功,不知是没设置好还是硬件模块有问题,以后有时间再琢磨琢磨……

相关学习网址:

http://group.ednchina.com/673/22580.aspx
http://www.feibit.com/bbs/viewthread.php?tid=463&extra=&page=1
http://e2e.ti.com/support/low_power_rf/f/158/t/17544.aspx
http://e2e.ti.com/support/low_power_rf/f/158/t/17523.aspx
http://e2e.ti.com/support/low_power_rf/f/158/t/47870.aspx
http://e2e.ti.com/support/low_power_rf/f/158/p/17379/67296.aspx
http://e2e.ti.com/support/low_power_rf/f/158/t/17413.aspx?PageIndex=1

原创粉丝点击