OSAL 如何添加用户任务 - 记2

来源:互联网 发布:定制家居管理系统源码 编辑:程序博客网 时间:2024/06/11 00:55

        在写用户任务事件处理函数和初始化函数之前,我们先说一下系统是如何循环检测是否有事件发生的;

/********************************************************************* * @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()这个函数来发送事件;结果同上;

0 1
原创粉丝点击