热度 23
2015-9-21 16:09
6586 次阅读|
5 个评论
接下来我们再看 main() 函数中另一个跟 OSAL 相关的函数—— osal_start_system() ,也位于 OSAL.c 中。 void osal_start_system( void ) { #if !defined ( ZBIT ) !defined ( UBIT ) for(;;) // Forever Loop #endif { osal_run_system(); } } 一看这是个死循环,相当于单片机程序最后一行 while(1); 。这个函数最主要的部分还是 osal_run_system() ,找到它,也在 OSAL.c 中。 void osal_run_system( void ) { uint8 idx = 0; #ifndef HAL_BOARD_CC2538 osalTimeUpdate(); #endif Hal_ProcessPoll(); do { if (tasksEvents ) // 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 ; tasksEvents = 0; // Clear the Events for this task. HAL_EXIT_CRITICAL_SECTION(intState); activeTaskID = idx; events = (tasksArr )( idx, events ); activeTaskID = TASK_NO_TASK; HAL_ENTER_CRITICAL_SECTION(intState); tasksEvents |= 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 } 去掉条件编译部分,最核心的是一个 do-while 循环,一个 if 判断。 do-while 循环: do { if (tasksEvents ) // 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 ; tasksEvents = 0; // Clear the Events for this task. HAL_EXIT_CRITICAL_SECTION(intState); activeTaskID = idx; events = (tasksArr )( idx, events ); activeTaskID = TASK_NO_TASK; HAL_ENTER_CRITICAL_SECTION(intState); tasksEvents |= events; // Add back unprocessed events to the current task. HAL_EXIT_CRITICAL_SECTION(intState); } 这部分代码应该是 OSAL 最核心最精髓的部分了。前面的循环中已经确定有事件发生了。 HAL_ENTER_CRITICAL_SECTION(intState); 和 HAL_EXIT_CRITICAL_SECTION(intState); 分别是关中断和使能中断,以防止在执行代码时被中断打断。将事件表 tasksEvents )( idx, events ); 就是去处理事件了,这里的 tasksArr |= events; 就是把没有响应的事件再放回到 tasksEvents ,它被定义在 OSAL_KeyFobDemo.c 中。 // The order in this table must be identical to the task initialization calls below in osalInitTask. const pTaskEventHandlerFn tasksArr 是一个函数指针数组,里面保存了所有事件处理函数的地址。当有事件发生时,就执行 events = (tasksArr )( idx, events ); 一句,就是对应的 tasksArr 。 tasksEvents 中哪个事件非 0 ,即事件被触发了;然后在 if 中把该事件清 0 ,执行 tasksArr 中。这也是为什么在 osalInitTask() 中进行初始化的时候,初始化的顺序要和 tasksArr[] 一致。 以上是我对 OSAL 的理解,因为 C 语言的基本不够瓷实,说得也很大白话。之所以敢这么大胆贴出来,也是请大家多批评指正,让我能得到提高。