Zigbee Osal Sleep Management

Source: Internet
Author: User
Tags message queue sleep
ZigBee node only the terminal device type can set the sleep mode, to set the sleep mode, on the configuration first to ensure that:

The drfd_rcvc_always_on in the 1.f8wconfig.cfg file is defined as false;

/****************************************
 * The following is for End Devices only
 ************************** /

-drfd_rcvc_always_on=false

2. Pre-compiling power_saving in the IAR engineering options->c/c++compiler->preprocessor->defined symbols;


In addition, the device enters sleep mode during operation to meet:

1. Power Management device property is pwrmgr_battery;

2. All tasks support low power consumption;

3. There are no events to be dealt with at present;

After meeting the above conditions, the terminal equipment will go to sleep state. The third condition actually implies that the wake-up condition of the terminal equipment, enter the sleep mode need to ensure that the current no event processing, if there is a timed trigger event before sleep, then when the timing of the event is set, the terminal device will be awakened to deal with this event, This mechanism also determines the length of time that ZigBee sleeps is determined by the scheduling of events.

How does ZigBee osal manage sleep at all? Entering Osal's main loop Osal_start_system () from the main () function in ZMAIN.C, the program polls the function over and over for events to be processed, each time a poll is made, when no event is required and the power_ is defined Saving calls Osal_pwrmgr_powerconserve () to consider whether to enter sleep mode.


Enter Osal_pwrmgr_powerconserve ()


It is found that this function can call Osal_set_cpu_into_sleep (next) to put the device into sleep mode, but it needs to meet two conditions:

1.pwrmgr_attribute.pwrmgr_device! = pwrmgr_always_on;

2. Pwrmgr_attribute.pwrmgr_task_state = = 0

Two conditions all involve a pwrmgr_attribute_t type of global variable Pwrmgr_attribute, which is used for power management.

/* This global variable stores the power management attributes.
 */
pwrmgr_attribute_t Pwrmgr_attribute;
/* These attributes define sleep beheaver. The attributes can changed * For each
 sleep cycle or when the device characteristic a change.
 */
typedef struct
{
  uint16 pwrmgr_task_state;       Task status
  uint16 pwrmgr_next_timeout;     Next time Out
  uint16 accumulated_sleep_time;  Sleep time
  uint8  pwrmgr_device;           Power Management device Properties, there are pwrmgr_always_on and pwrmgr_battery two kinds of
} pwrmgr_attribute_t;      

The pwrmgr_attribute contains four elements, and the Pwrmgr_task_state records whether all tasks support low power, Pwrmgr_device is the device property of power management, These two correspond to the first two of the three conditions that the device mentioned at the beginning must meet in order to successfully enter the sleep state:

1. Power Management device property is pwrmgr_battery;

2. All tasks support low power consumption;

3. There are no events to be dealt with at present;

Pwrmgr_sleep_time as the name suggests is sleep time, Pwrmgr_next_timeout is the next time out.

At this point, obviously if you cannot meet pwrmgr_attribute.pwrmgr_device! = pwrmgr_always_on and Pwrmgr_attribute.pwrmgr_task_state = = 0, you cannot call OSAL_ Set_cpu_into_sleep (next) so that the device goes into sleep mode, where is the global variable pwrmgr_attribute initialized?

Enter Osal_init_system () of the main () function in Zmain () to discover that there is a function to initialize the Power configuration osal_pwrmgr_init ()

Uint8 osal_init_system (void)
{
  //Initialize the Memory Allocation system
  osal_mem_init ();

  Initialize the message queue
  osal_qhead = NULL;

  Initialize The Timers
  osaltimerinit ();

  Initialize the Power Management System
  osal_pwrmgr_init ();

  Initialize the system tasks.
  Osalinittasks ();

  Setup efficient search for the first free block of heap.
  Osal_mem_kick ();

  return (SUCCESS);
}

Osal_pwrmgr_init () initializes the two elements of the Pwrmgr_attribute

void Osal_pwrmgr_init (void)
{
  pwrmgr_attribute.pwrmgr_device = pwrmgr_always_on;//Default to no power conse Rvation.
  pwrmgr_attribute.pwrmgr_task_state = 0;            Cleared.  All set to conserve
}

Due to the initialization of Pwrmgr_device = pwrmgr_always_on, it is obviously not supported to go to sleep mode by default. Fortunately, Pwrmgr_attribute is defined in the form of global variables, so we can change pwrmgr_device directly at the application level to make it pwrmgr_battery. A function osal_pwrmgr_device () that can change Pwrmgr_device directly is set in OSAL_PWRMGR.C, so you can also call Osal_pwrmgr_device (Pwrmgr_battery) at the application layer Change the power management device properties to Pwrmgr_battery.

void Osal_pwrmgr_device (uint8 pwrmgr_device)
{
  pwrmgr_attribute.pwrmgr_device = Pwrmgr_device;
}

The OSAL.C also defines osal_pwrmgr_task_state (Uint8 task_id, uint8 State), which can be used by any task to flag whether it supports low power, or Pwrmgr_conserve, Pwrmgr_hold is not supported.

#define PWRMGR_CONSERVE 0
#define Pwrmgr_hold     1
/*********************************************************************
 * @fn      osal_pwrmgr_task_state
 *
 * @brief This function was called by each task to state   whether or
 * not this          task wants to conserve Power.
 *
 * @param   task_id-calling task ID.
 *          State-whether The calling task wants to
 *          conserve power or not.
 *
 * @return  SUCCESS If task complete
 *
/uint8 osal_pwrmgr_task_state (uint8 task_id, uint8 State) c19/>{
  if (task_id >= taskscnt)
    return (invalid_task);

  if (state = = Pwrmgr_conserve)
  {
    //Clear The Task state flag
    Pwrmgr_attribute.pwrmgr_task_state &= ~ ( 1 << task_id);
  }
  else
  {
    //Set The Task state flag
    Pwrmgr_attribute.pwrmgr_task_state |= (1 << task_id);
  }

  return (SUCCESS);
}

Back to Osal_pwrmgr_powerconserve () in Osal_pwrmgr.c, when the application layer changes pwemgr_device to pwrmgr_battery and all tasks support low power, the

1.pwrmgr_attribute.pwrmgr_device! = pwrmgr_always_on;

2. Pwrmgr_attribute.pwrmgr_task_state = = 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)
  {
    // is all tasks in agreement to conserve
    if (pwrmgr_attribute.pwrmgr_task_state = = 0)
    {
      //Hold off interrupt S.
      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);}}
Will call Osal_set_cpu_into_sleep (next), Osal_set_cpu_into_sleep is a macro, here is actually called halsleep (next), Halsleep (next) describes the device sleep related configuration.
 #define OSAL_SET_CPU_INTO_SLEEP (timeout) halsleep (timeout);/* Called from Osal_pwrmgr */
void Halsleep (UInt16 osal_timeout) {UInt32 timeout;

  UInt32 mactimeout = 0;

  Halaccumulatedsleeptime = 0;
  /* Get next Osal timer expiration converted to 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 timeouts */if ((mactimeout! = 0) && (Mactimeout < timeout)) {timeout = Mac
    Timeout;
   }}/* 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 is entered when zgpollrate = = 0.
   * This was to eliminate any possibility of entering PM3 between * the 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 (mac_pwroffreq (mac_pwr_sleep_deep) = = mac_success) {#if (defined Hal_key) && (Hal_key = = TRUE)/* Get peripherals ready for sleep */Halkeyentersle
EP ();
#endif #ifdef hal_sleep_debug_led hal_turn_off_led3 ();
#else/* Use the this to turn LEDs off during sleep */halledentersleep (); #endif/* 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/* Save interrupt Enable registers and disable all interrupts */hal_sleep_ie_backup_and_disable (Ien
      0, Ien1, ien2);

      Hal_enable_interrupts ();

      /* Set CC2530 power mode, interrupt is disabled after this function */Hal_sleep_set_power_mode (Halpwrmgtmode); /* The interrupt is Disabled-see halsetsleepmode () */* Restore interrupt Enable registers */Hal_slee

      P_ie_restore (Ien0, Ien1, ien2);

      /* Disable Sleep Timer interrupt */Hal_sleep_timer_disable_int ();
/* Calculate Timer elasped */halaccumulatedsleeptime + = (haltimerelapsed ()/Tick_count);

#ifdef hal_sleep_debug_led hal_turn_on_led3 ();
#else/* Use the 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 don't was 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 was waking up from sleep, there was a small window * that the count could be grater than the comparator
       , therefore, missing the interrupt. * This workaround would call the T2 ISR if the current T2 count is greater than the * comparator.  The problem only occurs when power_saving are turned on, i.e. the 32KHz * drives the chip in sleep and SYNC start is
       Used.
  */    Macmcutimer2overflowworkaround ();
    } else {hal_enable_interrupts (); }
  }
}

The Halsleep (next) parameter next is determined in Osal_pwrmgr_powerconserve (), which is the time-out of the application layer's next timer.

      Get Next time-out
      next = Osal_next_timeout ();

There are two kinds of timers in the protocol stack, the one is the hardware driver count of the timers in the Cc2xxx, the second is the software timer, which is added to the soft timer chain by the Osal_start_timer (), Osal_start_reload_timer and other timer setting functions. The system clocks are then uniformly counted, meaning that these soft timers are driven by the system clock. In OnBoard.h, the system clock is defined with a beat of 1ms, which means that each 1ms system clock drives the timer in the software time list minus 1, and when a software timer count is reduced to 0 (that is, it expires), the software timer is deleted and the osal_set_event () is called. Set the appropriate event flags to notify the system that it is time to handle the event.

/* Osal Timer defines */

#define TICK_TIME   //timer per tick-in micro-sec
As mentioned earlier, there are events to be processed when you can not sleep, so before going to sleep must know the most recent timer timeout is long, and in its time to wake up to deal with the corresponding event in a timely manner. Halsleep () compares the duration of the next time-out between the application layer and the MAC layer and takes a minimum of sleep time, and then calls Halsleepsettimer () to configure the sleep timer.
      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));
        }





Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.