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

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

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

你可能感兴趣的:(TI,CC2541,OSAL,添加,任务,osal_run_system)