zigbee学习笔记--电源管理OSAL机制的ZigBee低功耗管理(CC2530)


OSAL_PwrMgr.C      OSAL电源管理的API C文件

hal_sleep.c                底层的电源管理文件

 

电源管理结构体

typedef struct

{

  uint16 pwrmgr_task_state;                    //任务状态

  uint16 pwrmgr_next_timeout;             //下一次超时

  uint16 accumulated_sleep_time;        //睡眠时间

  uint8  pwrmgr_device;                         //电源管理设备属性,有PWRMGR_ALWAYS_ON和

                                                                  //PWRMGR_BATTERY两种

} pwrmgr_attribute_t;

 

#define PWRMGR_ALWAYS_ON    0

#define PWRMGR_BATTERY          1

选择PWRMGR_ALWAYS_ON的话将不会进入睡眠模式,选择PWRMGR_BATTERY将允许HAL管理CPU进入SLEEP LITE或者SLEEP DEEP状态。

 

#define PWRMGR_CONSERVE 0

#define PWRMGR_HOLD     1

低功耗标志,主要用于osal_pwrmgr_task_state()这个函数中,用于标志每一任务是否需要低功耗。

 

extern pwrmgr_attribute_t    pwrmgr_attribute;

定义一个电源管理的全局变量。

 

函数

/*********************************************************************

 * @fn      osal_pwrmgr_init

 *

 * @brief   初始化电源管理函数,这个函数在OSAL.C里面的osal_init_system( )调用,也就 *                           是在OSAL系统初始化的时候将电源管理模式调成了不会进入睡眠模式的状态。

 *

 * @param   none.

 *

 * @return  none.

 */

void osal_pwrmgr_init( void )

{

  pwrmgr_attribute.pwrmgr_device = PWRMGR_ALWAYS_ON; //默认没有睡眠模式

  pwrmgr_attribute.pwrmgr_task_state = 0;            //清零

}

/*********************************************************************

 * @fn      osal_pwrmgr_device

 *

 * @brief   设置电源管理设备属性。

 *

 * @param   pwrmgr_device -选择PWRMGR_ALWAYS_ON的话将不会进入睡眠模式,选择

*                       PWRMGR_BATTERY将允许HAL管理CPU进入SLEEP LITE或者SLEEP DEEP状态。

 *

 * @return  none

void osal_pwrmgr_device( uint8 pwrmgr_device )

{

  pwrmgr_attribute.pwrmgr_device = pwrmgr_device;

}

 

/*********************************************************************

 * @fn      osal_pwrmgr_task_state

 *

 * @brief   这个函数可以被每一个任务调用,用于设置这个任务是否支持低功耗运行,如

*                       果每一个任务不支持低功耗将无法进入低功耗模式运行。

 *

 * @param   task_id – 任务ID

 *          state – 任务是否需要低功耗

 *

 * @return  SUCCESS if task complete

 */

uint8 osal_pwrmgr_task_state( uint8 task_id, uint8 state )

{

  if ( task_id >= tasksCnt )

    return ( INVALID_TASK );

 

  if ( state == PWRMGR_CONSERVE )

  {

    // 清零

   pwrmgr_attribute.pwrmgr_task_state &= ~(1 << task_id );

  }

  else

  {

    //置位

    pwrmgr_attribute.pwrmgr_task_state |= (1 << task_id);

  }

 

  return ( SUCCESS );

}

 

#if defined( POWER_SAVING )

/*********************************************************************

 * @fn      osal_pwrmgr_powerconserve

 *

 *@brief   这个函数在OSAL循环中如果没有任何事件需要执行的话将被调用,将设备进入

*                       睡眠模式,不可以在其他地方调用该函数。

*                       需要打开POWER_SAVING的宏定义。

 *

 * @param   none.

 *

 * @return  none.

 */

void osal_pwrmgr_powerconserve( void )

{

  uint16        next;

  halIntState_t  intState;

 

  // 首先检查是否支持低功耗

  if ( pwrmgr_attribute.pwrmgr_device != PWRMGR_ALWAYS_ON )

  {

    //是否所有任务支持低功耗

    if ( pwrmgr_attribute.pwrmgr_task_state == 0 )

    {

      //关中断

      HAL_ENTER_CRITICAL_SECTION( intState );

      //查询软件定时器链表得到最近一次溢出时间

      next = osal_next_timeout();

      //开中断

      HAL_EXIT_CRITICAL_SECTION( intState );

      //将系统进入睡眠模式

      OSAL_SET_CPU_INTO_SLEEP( next );

    }

  }

}

#endif /* POWER_SAVING */

 

 

加红部分是一个宏定义,在OnBoard.h里面定义的。

#define  OSAL_SET_CPU_INTO_SLEEP(timeout)  halSleep(timeout);

 

halSleep(timeout)是在hal_sleep.c中定义的。

这里面涉及的就是关于CC2530的电源管理寄存器的一些操作。具体可以看代码。

 

/* HAL电源管理模式是设置电源管理状态的,默认状态是HAL_SLEEP_OFF。其余设置均会关*闭系统时钟停止CPU。

 * HAL_SLEEP_TIMER模式可以被睡眠定时器中断和IO中断以及复位唤起。

 * HAL_SLEEP_DEEP模式可以被IO中断以及复位唤起。

 */

#define HAL_SLEEP_OFF         CC2530_PM0

#define HAL_SLEEP_TIMER       CC2530_PM2

#define HAL_SLEEP_DEEP        CC2530_PM3

 

#define CC2530_PM0            0 

#define CC2530_PM1            1 

#define CC2530_PM2            2 

#define CC2530_PM3            3 

 

#define MAX_SLEEP_TIME       510000 

最大睡眠时间是510000ms。

 

 

总结

其实可以在这个函数中可以看到在OSAL中是使用的睡眠定时器来控制睡眠时间的,在系统初始化的是将电源控制结构体中的pwrmgr_device设备属性设置为PWRMGR_ALWAYS_ON,这样默认就不进入休眠状态。必须在应用层里面调用void osal_pwrmgr_device( uint8 pwrmgr_device )这个OSAL的API来设置使得OSAL能够进入休眠状态。

在用户任务中需要用的这样一个API——uint8 osal_pwrmgr_task_state( uint8 task_id, uint8 state )来设置这个任务是否支持休眠,如果有一个任务不支持休眠的话,整个系统就将不会进入休眠模式。这个在void osal_pwrmgr_powerconserve( void )中有相关的查询。

在OSAL的主循环中void osal_start_system( void )调用了osal_pwrmgr_powerconserve这个函数。

void osal_start_system( void )

{

#if !defined ( ZBIT ) && !defined ( UBIT )

  for(;;)  // Forever Loop

#endif

  {

    uint8 idx = 0;

    osalTimeUpdate();

    Hal_ProcessPoll();  // This replaces MT_SerialPoll() and osal_check_timer().

   do {

      if (tasksEvents[idx])  // Task is highest priority that is ready.

      {

        break;

      }

    } while (++idx < tasksCnt);

    if (idx < tasksCnt)

    {

      uint16 events;

      halIntState_t intState;

      HAL_ENTER_CRITICAL_SECTION(intState);

      events = tasksEvents[idx];

      tasksEvents[idx] = 0;  // Clear the Events for this task.

      HAL_EXIT_CRITICAL_SECTION(intState);

      events = (tasksArr[idx])( idx, events ); //最关键的一句话,如图一中,运行对应的任务

      HAL_ENTER_CRITICAL_SECTION(intState);

      tasksEvents[idx] |= events;  // Add back unprocessed events to the current task.

      HAL_EXIT_CRITICAL_SECTION(intState);

    }

#if defined( POWER_SAVING )

    else  // Complete pass through all task events with no activity?

    {

      osal_pwrmgr_powerconserve();  // Put the processor/system into sleep

    }

#endif

  }

}

表示OSAL系统在检查完所有的任务事件之后发现没有事件需要处理,这样在POWER_SAVING宏定义打开的情况下将调用osal_pwrmgr_powerconserve();函数,在这函数中将会根据选择系统进入休眠。

 

退出休眠

当出现IO中断或者复位时候会退出休眠,或者在休眠定时器中断时候也将会退出休眠。如果是IO中断或者休眠定时器中断退出之后将回到进入休眠的地方继续向下执行,复位退出的话进入程序的初部分执行。

你可能感兴趣的:(物联网,嵌入式学习)