在写用户任务事件处理函数和初始化函数之前,我们先说一下系统是如何循环检测是否有事件发生的;
/*********************************************************************
* @fn osal_run_system
*
* @brief
* 循环检测是否有事件发生,假如有事件的话,退出检测,根据 idx 调用相关
* 任务的事件处理函数,若没有事件的话,进入睡眠
* This function will make one pass through the OSAL taskEvents table
* and call the task_event_processor() function for the first task that
* is found with at least one event pending. If there are no pending
* events (all tasks), this function puts the processor into Sleep.
*
* @param void
*
* @return none
*/
void osal_run_system( void )
{
uint8 idx = 0;
#ifndef HAL_BOARD_CC2538
osalTimeUpdate(); /* 获取定时器时间,更新系统时间及每个软件定时器,减去一定的时间 */
#endif
Hal_ProcessPoll(); /* 查询数据,比如串口数据,usb数据等,这个函数以后再说 */
do { /* 训环寻找是否有事件,有事件的话,就立马退出,app应用优先级最低 */
if (tasksEvents[idx]) /* 假如为非0,则代表有事件发生,始终运行优先级高的任务 */
{
break;
}
} while (++idx < tasksCnt);
if (idx < tasksCnt) /* 找到了事件 */
{
uint16 events;
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState); /* 关闭中断 */
events = tasksEvents[idx]; /* 读取该任务的事件(事件可能不止1个) */
tasksEvents[idx] = 0; /* 清除时间记录,在执行任务处理函数期间有可置上新事件 */
HAL_EXIT_CRITICAL_SECTION(intState); /* 开启中断 */
activeTaskID = idx; /* 设置当前正在运行的任务 */
events = (tasksArr[idx])( idx, events ); /* tasksArr 是任务处理函数指针,运行对应任务的事件处理函数 */
activeTaskID = TASK_NO_TASK; /* 当前没有运行的任务 */
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
/* Yield in case cooperative scheduling is being used. */
#if defined (configUSE_PREEMPTION) && (configUSE_PREEMPTION == 0)
{
osal_task_yield(); /* 还不知道是干什么用的 */
}
#endif
}
从上面可以看出很重要的一个数组,tasksEvents[] ,指向任务事件数组的指针,这个数组在osalInitTasks()中初始化,每一个任务对应数组中的一个元素,当某个任务有事件有任务发生时,就会在相应的元素的一位上置1;因为tasksEvents是 uint16,所以一个任务最多对应16中事件;
在osal_pwrmgr_powerconserve()这个函数中会检测Timer时间链表中Timeout最小的值,假设为next,然后设定CPU进入休眠模式next个毫秒。
休眠时间到了苏醒过来立即就会有Timer事件需要处理,这样就可以达到省电的目的。
现在我们来说说事件是如何产生的,上一回我们说了产生事件事件有两种方式,循环和触发;
先来说下循环方式:在OSAL中,有一个函数
uint8 osal_start_reload_timer( uint8 taskID, uint16 event_id, uint32 timeout_value )
这个函数的功能就是每隔 timeout_value毫秒,系统最终会调用 osal_set_event()这个函数来发送事件,及在任务号为taskID的对应的数组元素tasksEvents[taskID]上的某一位置1,这样当系统运行osal_run_system()时,就会检测到事件发生,这要就定时的运行了这个任务;
再来说下触发方式:在OSAL中,假如有按键按下会其他什么事件已经完成,则同样会调用 osal_set_event()这个函数来发送事件;结果同上;