第十五節(jié) BLE藍(lán)牙4.0協(xié)議棧啟動(dòng)分析
TI的這款CC2540/CC2541器件可以單芯片實(shí)現(xiàn)BLE藍(lán)牙協(xié)議棧結(jié)構(gòu)圖的所有組件,包括應(yīng)用程序。從這章開始我們來剖析協(xié)議棧源碼,我們選用 SimpleBLEPeripheral工程開刀,這是一個(gè)從機(jī)的例程,基本的工作是對(duì)外廣播,等待主機(jī)來連接,讀寫展示的屬性。

首先打開工程文件,打開后可以看到整個(gè)工程的結(jié)構(gòu)。

我們按照系統(tǒng)的啟動(dòng)順序來一步一步走,我們都知道在C代碼中,一般啟動(dòng)的首個(gè)函數(shù)為main,這個(gè)函數(shù)在 SimpleBLEPeripheral_Main.c中,打開文件,可以看到這個(gè)文件只有一個(gè)main函數(shù)和一個(gè)函數(shù)的申明,我們暫時(shí)不理會(huì)那個(gè)申明的函數(shù),先看main都做了些什么工作:
Int main(void)
{
/* Initialize hardware */
HAL_BOARD_INIT(); // 硬件初始化
// Initialize board I/O
InitBoard( OB_COLD ); // 板級(jí)初始化
/* Initialze the HAL driver */
HalDriverInit(); // Hal驅(qū)動(dòng)初始化
/* Initialize NV system */
osal_snv_init(); // Flash存儲(chǔ)SNV初始化
/* Initialize LL */
/* Initialize the operating system */
osal_init_system(); // OSAL初始化
/* Enable interrupts */
HAL_ENABLE_INTERRUPTS(); // 使能總中斷
// Final board initialization
InitBoard( OB_READY ); // 板級(jí)初始化
#if defined ( POWER_SAVING )
osal_pwrmgr_device( PWRMGR_BATTERY ); // 低功耗管理
#endif
/* Start OSAL */
osal_start_system(); // No Return from here 啟動(dòng)OSAL
return 0;
}
通過代碼我們可以看到,系統(tǒng)啟動(dòng)的過程,主要是做了一些初始化,如果開啟了低功耗,則還需要開啟低功耗管理。我們先不去理會(huì)初始化做了什么,但是我們知道在main函數(shù)的最后啟動(dòng)了OSAL,那么我們就進(jìn)去看看OSAL是如何運(yùn)作的。
在IAR中如果需要跳轉(zhuǎn)到某個(gè)函數(shù)或變量的定義,可以在此函數(shù)名中右擊然后選擇Go To Definition……就可以調(diào)到相應(yīng)的定義。

void osal_start_system( void )
{
#if !defined ( ZBIT ) && !defined ( UBIT )
for(;;) // Forever Loop
#endif
{
osal_run_system();
}
}
這里看到我們進(jìn)入了一個(gè)死循環(huán),并且一直調(diào)用osal_run_system(),那我們?cè)龠M(jìn)入此函數(shù)。
void osal_run_system( void ){
uint8 idx = 0;
#ifndef HAL_BOARD_CC2538
osalTimeUpdate(); // 定時(shí)器更新
#endif
Hal_ProcessPoll(); // Hal層信息處理
do {
if (tasksEvents[idx]) // Task is highest priority that is ready.
{
break;
}
} while (++idx < tasksCnt); // 檢查每個(gè)人任務(wù)是否有事件
if (idx < tasksCnt) // 有事件發(fā)生
{
uint16 events;
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState); // 進(jìn)入臨界區(qū)
events = tasksEvents[idx];
tasksEvents[idx] = 0; // Clear the Events for this task. 清除事件標(biāo)志
HAL_EXIT_CRITICAL_SECTION(intState); // 退出臨界區(qū)
activeTaskID = idx;
events = (tasksArr[idx])( idx, events ); // 執(zhí)行事件處理函數(shù)
activeTaskID = TASK_NO_TASK;
HAL_ENTER_CRITICAL_SECTION(intState); // 進(jìn)入臨界區(qū)
tasksEvents[idx] |= events; // Add back unprocessed events to the current task.
HAL_EXIT_CRITICAL_SECTION(intState); // 退出臨界區(qū)
}
#if defined( POWER_SAVING ) // 沒有事件發(fā)生,并且開啟了低功耗模式
else // Complete pass through all task events with no activity?
{ // 系統(tǒng)進(jìn)入低功耗模式
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
}
在這里可以看到這個(gè)OSAL的核心,整個(gè)OSAL通過檢測(cè)每個(gè)任務(wù)是否有事件發(fā)生,如果有則執(zhí)行相應(yīng)的任務(wù),處理相應(yīng)的事件。如果沒有事件需要處理并且開啟了低功耗模式,則系統(tǒng)就會(huì)進(jìn)入低功耗模式。
這里有一個(gè)很關(guān)鍵的地方,OSAL是如何知道哪個(gè)事件需要哪個(gè)任務(wù)來處理呢?
events = (tasksArr[idx])( idx, events ); // 執(zhí)行事件處理函數(shù)
我們看這里有一個(gè)很關(guān)鍵的數(shù)組tasksArr,很顯然,這是一個(gè)函數(shù)指針數(shù)組,我們看看它的定義。
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
};
可以看到在這個(gè)數(shù)組的定義中,每個(gè)成員都是任務(wù)的執(zhí)行函數(shù),按照任務(wù)的優(yōu)先級(jí)排序,并且在osalInitTasks中初始化的時(shí)候,我們可以看到每個(gè)任務(wù)都有一個(gè)對(duì)應(yīng)的初始化函數(shù),并且傳遞了一個(gè)taskID,此ID從0開始自增,這里有一點(diǎn)非常重要,初始化的順序和任務(wù)數(shù)組的定義順序是一樣的,這就保證了我們給任務(wù)發(fā)生消息或事件時(shí)能夠準(zhǔn)確的傳遞到相應(yīng)的任務(wù)處理函數(shù)。
void osalInitTasks( void )
{
uint8 taskID = 0;
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
/* LL Task */
LL_Init( taskID++ );
/* Hal Task */
Hal_Init( taskID++ );
/* HCI Task */
HCI_Init( taskID++ );
#if defined ( OSAL_CBTIMER_NUM_TASKS )
/* Callback Timer Tasks */
osal_CbTimerInit( taskID );
taskID += OSAL_CBTIMER_NUM_TASKS;
#endif
/* L2CAP Task */
L2CAP_Init( taskID++ );
/* GAP Task */
GAP_Init( taskID++ );
/* GATT Task */
GATT_Init( taskID++ );
/* SM Task */
SM_Init( taskID++ );
/* Profiles */
GAPRole_Init( taskID++ );
GAPBondMgr_Init( taskID++ );
GATTServApp_Init( taskID++ );
/* Application */
SimpleBLEPeripheral_Init( taskID );
}
應(yīng)用層的初始化SimpleBLEPeripheral_Init,SimpleBLEPeripheral_Init( uint8task_id )主要對(duì) GAP 和 GATT 進(jìn)行配置,最后調(diào)用osal_set_event(simpleBLEPeripheral_TaskID, SBP_START_DEVICE_EVT )啟動(dòng)設(shè)備。
設(shè)備啟動(dòng)后應(yīng)用層就能接收到這個(gè)設(shè)置的事件并進(jìn)行處理,可以看到設(shè)備啟動(dòng)中主要是啟動(dòng)設(shè)備,注冊(cè)綁定管理,并且啟動(dòng)了一個(gè)定時(shí)器,這個(gè)定時(shí)器是一個(gè)周期事件的第一次啟動(dòng)。
周期事件中每次都會(huì)重啟這個(gè)定時(shí)器,并且處理周期事件。
在初始化的時(shí)候我們注冊(cè)了一個(gè)很重要的函數(shù),設(shè)備狀態(tài)改變時(shí)的回調(diào)函數(shù),這個(gè)函數(shù)在設(shè)備的狀態(tài)改變時(shí)會(huì)被底層的協(xié)議?;卣{(diào),我們可以從這個(gè)回調(diào)函數(shù)中看的設(shè)備的狀態(tài)的改變。
static void peripheralStateNotificationCB( gaprole_States_t newState);
從函數(shù)的定義可以看出,設(shè)備的狀態(tài)類型都在數(shù)據(jù)類型gaprole_States_t中定義了,我們看一下這個(gè)數(shù)據(jù)類型的定義:
typedef enum
{
GAPROLE_INIT = 0, //!< Waiting to be started
GAPROLE_STARTED, //!< Started but not advertising
GAPROLE_ADVERTISING, //!< Currently Advertising
GAPROLE_WAITING, //!< Device is started but not advertising, is in waiting period before advertising again
GAPROLE_WAITING_AFTER_TIMEOUT, //!< Device just timed out from a connection but is not yet advertising, is in waiting period before advertising again
GAPROLE_CONNECTED, //!< In a connection
GAPROLE_CONNECTED_ADV, //!< In a connection + advertising
GAPROLE_ERROR //!< Error occurred - invalid state
} gaprole_States_t;
看到這個(gè)定義就很明確了,設(shè)備的狀態(tài)就在這幾種狀態(tài)間切換。
本文導(dǎo)航
- 第 1 頁:由淺入深,藍(lán)牙4.0/BLE協(xié)議棧開發(fā)攻略大全(3)
- 第 2 頁:第十二節(jié) Flash的讀寫
- 第 3 頁:第十三節(jié) BLE協(xié)議棧簡(jiǎn)介
- 第 4 頁:第十四節(jié) OSAL工作原理
- 第 5 頁:第十五節(jié) BLE藍(lán)牙4.0協(xié)議棧啟動(dòng)分析
- TI公司(74974)
- 協(xié)議棧(34533)
- 藍(lán)牙BLE(24681)
由淺入深,藍(lán)牙4.0/BLE協(xié)議棧開發(fā)攻略大全(1)
142619由淺入深,藍(lán)牙4.0/BLE協(xié)議棧開發(fā)攻略大全(5)
37224由淺入深,藍(lán)牙4.0/BLE協(xié)議棧開發(fā)攻略大全(2)
14662由淺入深,藍(lán)牙4.0/BLE協(xié)議棧開發(fā)攻略大全(4)
22316由淺入深,藍(lán)牙4.0/BLE協(xié)議棧開發(fā)攻略大全(6)
26606藍(lán)牙4.0 BLE 技術(shù)為何如此受青睞?
152402.4GRF協(xié)議BLE藍(lán)牙4.0協(xié)議芯片NRF51822是什么
4.2BLE藍(lán)牙簡(jiǎn)介_SKYLAB BLE藍(lán)牙模塊SKB369
BLE4.0藍(lán)牙微信版 mesh藍(lán)牙自組網(wǎng) 數(shù)據(jù)透?jìng)?歡迎咨詢交流
BLE Scanner應(yīng)用開發(fā)實(shí)例
BLE藍(lán)牙相比經(jīng)典藍(lán)牙區(qū)別是什么
ble協(xié)議棧
ble協(xié)議該怎么學(xué)習(xí)啊 藍(lán)牙低功耗 基于協(xié)議棧的工程代碼
藍(lán)牙4.0 BLE NRF51822開發(fā)套件
藍(lán)牙4.0 BLE 模塊
藍(lán)牙4.0串口模塊解決方案
藍(lán)牙4.0模塊基礎(chǔ)理論
藍(lán)牙4.0模塊有哪些
藍(lán)牙4.0芯片nrf51822資料
藍(lán)牙4.0芯片選型
藍(lán)牙4.0(CC2540/CC2541)BLE協(xié)議棧開發(fā)(連載)
藍(lán)牙協(xié)議4.0、4.1、4.2的比較
藍(lán)牙協(xié)議4.0、4.1、4.2的比較
藍(lán)牙協(xié)議4.0、4.1、4.2的比較
藍(lán)牙協(xié)議棧開發(fā)板跑傳統(tǒng)藍(lán)牙搜索AT指令以及上位機(jī)操作步驟
藍(lán)牙協(xié)議棧iAP和AAP區(qū)別
藍(lán)牙mesh協(xié)議棧具備哪些特性?
藍(lán)牙雙模解決方案
藍(lán)牙雙模解決方案
AliOS Things藍(lán)牙協(xié)議棧及應(yīng)用開發(fā)框架介紹
Cypress PSoC藍(lán)牙低功耗開發(fā)設(shè)計(jì)攻略
Hollong 藍(lán)牙4.0/4.1/4.2 BLE協(xié)議監(jiān)控分析儀
Hollong 藍(lán)牙4.0/4.1/4.2 BLE協(xié)議監(jiān)控分析儀
Hollong 藍(lán)牙4.0/4.1/4.2 BLE協(xié)議監(jiān)控分析儀
Hollong 低功耗藍(lán)牙4.0/4.1/4.2 BLE Sniffer協(xié)議分析儀
Hollong藍(lán)牙4.0/4.1/4.2 BLE協(xié)議監(jiān)控分析儀
Hollong藍(lán)牙4.0/4.1/4.2 BLE協(xié)議監(jiān)控分析儀
LED燈RGB藍(lán)牙4.0控制方案
MM32W0x2xxB的藍(lán)牙協(xié)議棧部分對(duì)應(yīng)各接口
Nordic NRF51822藍(lán)牙BLE 4.0 芯片資料
SBM14580思卡樂科技超低功耗藍(lán)牙4.0 BLE模塊功能簡(jiǎn)介
STM32WB BLE協(xié)議棧編程指南
【藍(lán)牙4.1試用體驗(yàn)】藍(lán)牙BLE經(jīng)典介紹(八)
【TI SimpleLink SensorTag試用體驗(yàn)】+ BLE協(xié)議棧的安裝
低功耗BLE藍(lán)牙4.0模塊
低功耗BLE藍(lán)牙4.0模塊
關(guān)于藍(lán)牙協(xié)議棧的應(yīng)用
分享幾款基于TI的BLE藍(lán)牙模塊技術(shù)資料
如何修改BLE藍(lán)牙連接速度?
招聘BLE協(xié)議棧開發(fā)工程師【上?!?/a>
有無藍(lán)牙4.0BLE簡(jiǎn)單有效的調(diào)試辦法?
爆炸性 BLE4.0藍(lán)牙微信 MESH藍(lán)牙自組網(wǎng) 新鮮出爐 歡迎技術(shù)討論
網(wǎng)蜂科技藍(lán)牙4.0開源發(fā)布會(huì)
請(qǐng)教CC2650 BLE協(xié)議棧相關(guān)等問題
請(qǐng)問BLE協(xié)議棧如何處理中斷?
請(qǐng)問藍(lán)牙2.1+edr模塊和4.0+edr/BLE模塊的EDR速率一樣嗎?
請(qǐng)問藍(lán)牙4.0如何實(shí)現(xiàn)密碼配對(duì)啊,協(xié)議棧的程序該怎么改啊
請(qǐng)問有藍(lán)牙舊版本協(xié)議棧下載地址嗎?
超低jia藍(lán)牙4.0BLE數(shù)傳模塊LED無線智能燈控
超低功率、小尺寸藍(lán)牙4.0透?jìng)髂K
CC2541藍(lán)牙BLE數(shù)傳模塊
低功耗藍(lán)牙技術(shù)(BLE)4.0主要內(nèi)容
33藍(lán)牙協(xié)議棧的研究及其MAP剖面開發(fā)
12BLE低功耗藍(lán)牙模塊為何如此受歡迎?
18android藍(lán)牙4.0開發(fā)教程
6798基于STM32的虛擬多線程(TI_BLE協(xié)議棧_ZStack協(xié)議棧)
7279
XLW-BLE003U藍(lán)牙模塊的使用手冊(cè)詳細(xì)概述免費(fèi)下載
15XLW-BLE003U藍(lán)牙BLE4.0模塊的詳細(xì)使用手冊(cè)資料免費(fèi)下載
5低功耗藍(lán)牙的協(xié)議與BLE外設(shè)如何與BLE中心進(jìn)行通信
6546盤點(diǎn)BLE低功耗藍(lán)牙和傳統(tǒng)藍(lán)牙之間的五大區(qū)別
6992CC2541開發(fā)環(huán)境BLE-CC254x1.3藍(lán)牙協(xié)議棧的應(yīng)用程序免費(fèi)下載
53STM32WB55 藍(lán)牙協(xié)議棧運(yùn)行流程解析
17藍(lán)牙協(xié)議棧開發(fā)板 STM32F1 跑藍(lán)牙協(xié)議棧 --傳統(tǒng)藍(lán)牙串口協(xié)議SPP演示以及實(shí)現(xiàn)原理
8奧格無線藍(lán)牙標(biāo)準(zhǔn)BLE部分協(xié)議翻譯版
0BLE技術(shù)的特點(diǎn)、協(xié)議棧組成和應(yīng)用難點(diǎn)
4327E104-BT01超低功耗藍(lán)牙模塊BLE4.0協(xié)議的片載系統(tǒng)解決方案
1771
海凌科BLE低功耗藍(lán)牙模塊物聯(lián)網(wǎng)應(yīng)用
2352
虹科WiFi藍(lán)牙協(xié)議棧解決方案
2
電子發(fā)燒友App




評(píng)論