涉及文件
OSAL_PwrMgr.h OSAL电源管理的API头文件
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;
定义一个电源管理的全局变量。
函数
void osal_pwrmgr_init( void )
{
pwrmgr_attribute.pwrmgr_device = PWRMGR_ALWAYS_ON; //默认没有睡眠模式
pwrmgr_attribute.pwrmgr_task_state = 0; //清零
}
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 )
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
加红部分是一个宏定义,在OnBoard.h里面定义的。
#define OSAL_SET_CPU_INTO_SLEEP(timeout) halSleep(timeout);
halSleep(timeout)是在hal_sleep.c中定义的。
这里面涉及的就是关于CC2530的电源管理寄存器的一些操作。具体可以看代码。
#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中断或者休眠定时器中断退出之后将回到进入休眠的地方继续向下执行,复位退出的话进入程序的初部分执行。
原文地址:http://blog.21ic.com/user1/6983/archives/2010/75055.html