由浅入深,蓝牙4.0/BLE协议栈开发攻略大全(3)
SAL初始化
/* Enable interrupts */
HAL_ENABLE_INTERRUPTS(); // 使能总中断
// Final board initialization
InitBoard( OB_READY ); // 板级初始化
#if defined ( POWER_SAVING )
osal_pwrmgr_device( PWRMGR_BATTERY ); // 低功耗管理
#endif
/* Start OSAL */
osal_start_system(); // No Return from here 启动OSAL
return 0;
}
通过代码我们可以看到,系统启动的过程,主要是做了一些初始化,如果开启了低功耗,则还需要开启低功耗管理。我们先不去理会初始化做了什么,但是我们知道在main函数的最后启动了OSAL,那么我们就进去看看OSAL是如何运作的。
在IAR中如果需要跳转到某个函数或变量的定义,可以在此函数名中右击然后选择Go To Definition……就可以调到相应的定义。
void osal_start_system( void )
{
#if !defined ( ZBIT ) && !defined ( UBIT )
for(;;) // Forever Loop
#endif
{
osal_run_system();
}
}
这里看到我们进入了一个死循环,并且一直调用osal_run_system(),那我们再进入此函数。
</blockquote></div><div style="text-align: left;"><div class="blockcode"><blockquote>void osal_run_system( void )
{
uint8 idx = 0;
#ifndef HAL_BOARD_CC2538
osalTimeUpdate(); // 定时器更新
#endif
Hal_ProcessPoll(); // Hal层信息处理
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); // 退出临界区
activeTaskID = idx;
events = (tasksArr[idx])( idx, events ); // 执行事件处理函数
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
}
在这里可以看到这个OSAL的核心,整个OSAL通过检测每个任务是否有事件发生,如果有则执行相应的任务,处理相应的事件。如果没有事件需要处理并且开启了低功耗模式,则系统就会进入低功耗模式。
这里有一个很关键的地方,OSAL是如何知道哪个事件需要哪个任务来处理呢?
events = (tasksArr[idx])( idx, events ); // 执行事件处理函数
我们看这里有一个很关键的数组tasksArr,很显然,这是一个函数指针数组,我们看看它的定义。
const pTaskEventHandlerFn tasksArr[] =
{
LL_ProcessEvent, // task 0
Hal_ProcessEvent, // task 1
HCI_ProcessEvent, // task 2
#if defined ( OSAL_CBTIMER_NUM_TASKS )
OSAL_CBTIMER_PROCESS_EVENT( osal_CbTimerProcessEvent ), // task 3
#endif
L2CAP_ProcessEvent, // task 4
GAP_ProcessEvent, // task 5
GATT_ProcessEvent, // task 6
SM_ProcessEvent, // task 7
GAPRole_ProcessEvent, // task 8
GAPBondMgr_ProcessEvent, // task 9
GATTServApp_ProcessEvent, // task 10
SimpleBLEPeripheral_ProcessEvent // task 11
};
可以看到在这个数组的定义中,每个成员都是任务的执行函数,按照任务的优先级排序,并且在osalInitTasks中初始化的时候,我们可以看到每个任务都有一个对应的初始化函数,并且传递了一个taskID,此ID从0开始自增
- 主流蓝牙BLE控制芯片详解(3):创杰 IS1685S(07-18)
- 苹果光环加持,蓝牙Beacon技术成室内定位应用最大黑马(08-02)
- 主流蓝牙BLE控制芯片详解(4):Nordic nRF51822(07-20)
- 蓝牙BLE之室内定位iBeacon应用测验(08-02)
- 由浅入深,蓝牙4.0/BLE协议栈开发攻略大全(5)(08-02)
- 由浅入深,蓝牙4.0/BLE协议栈开发攻略大全(2)(07-18)