TI BLE協議棧軟體架構分析

來源:互聯網
上載者:User

標籤:ble   主程式   低功耗   藍芽   流程詳解   

看原始碼的時候,一般都是從整個代碼的入口處開始,TI  BLE 協議棧源碼也不例外。它的入口main()函數就是整個程式的入口,由系統上電時自動調用。

 

它主要做了以下幾件事情:

(一)底層硬體初始化配置

(二)建立任務並初始化任務配置

(三)檢測並執行有效任務事件

 

Main() 函數源碼如下:


一:底層硬體初始化設定

75行,設定系統時鐘,使能記憶體緩衝功能。

78行,關中斷,剛啟動時,系統運行不穩定,一般會首先關中斷。

81行,硬體相關的I/O 口配置。

84行,初始化mcu 內部的flash。

92行,開中斷,當系統運行到這裡的時候,狀態已經很穩定,可以將中斷開啟。

95行,I/O功能配置,及設定按鍵回呼函數指標。

98行,配置省電模式。

 

二:建立任務並初始化任務配置

89行,最主要的功能就是給建立所有的任務。

 

三:檢測並執行有效任務事件

 

102行,此函數是整個程式啟動並執行核心,一旦進入,就迴圈執行所有的任務,永遠不會結束。

 

 

 

下面分別列出這3個部分的主要原始碼,並以按鍵KEY的配置為線索進行分析:

===================================================================

一:底層硬體初始化設定


a.        HalDriverInit() 主要是硬體抽象層初始化,配置PIN腳的工作模式。

比如ADC,UART,KEY,LCD等。

147行,HalKeyInit()是按鍵I/O配置,下面以此舉例說明:



211-223行,將相應的PIN配置為GPIO,輸入模式。

226行,初始化按鍵回呼函數指標pHalKeyProcessFunction為NULL。

此回呼函數在程式中的作用是,當driver層檢測到按鍵中斷後,只需要調用回呼函數指標即可,至於函數執行什麼功能則完全由使用者層自己決定,這樣的做的好處是將使用者層與driver層分離,提高代碼的模組化及可操作特性。

 

b.        InitBoard( OB_READY ),配置KEY  GPIO的中斷功能


126行,HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback)此函數中配置中斷使能,設定按鍵回呼函數指標pHalKeyProcessFunction為OnBoard_KeyCallback。

OnBoard_KeyCallback()裡面會繼續調用函數OnBoard_SendKeys(),其功能是發送按鍵message給相應的任務。

 

硬體設定好後,只能說明硬體具備完成相應功能的條件,但是如何讓它的功能實現,那就需要建立相應的應用程式來讓硬體工作起來,這個程式就叫task,那task是如何建立的呢?

 

下面接著分析,如何建立task。

 

二:建立任務並初始化任務配置

 

前面講過主函數main()89行osal_init_system(),主要功能是初始化系統設定,其中最重要的一個功能就是建立task,下面是建立task的原始碼

 

122行,申請tasksEvents記憶體空間

123行,清零tasksEvents記憶體空間

126行,鏈路層task初始化

129行,硬體抽象層task初始化

132行,主機控制介面層task初始化

141行,邏輯鏈路控制及自適應協議層task初始化

144-156行,通用屬性設定檔層task初始化

150行,安全管理層task初始化

159行,客戶應用程式層task初始化

 

每個task 初始化時都會分配一個taskID,而且是從0 遞增。

以Hal_Init(taskID++ )為例,從上面代碼可以看出來,硬體抽象層的taskID值是1

 

92行,將task_id形參賦值給Hal_TaskID,故初始化後Hal_TaskID等於1

由於Hal_TaskID是定義為一個全域變數,因此,整個程式中,只要是與Hal_TaskID有關係的事情,都會交給Hal 層的task處理。

 

同樣的道理,SimpleBLECentral_Init(taskID++)中會定義一個simpleBLETaskId,那麼所有與simpleBLETaskId有關係的事情,也都會交給應用程式層任務函數處理。

 

 

那各層的任務函數是在哪裡定義的呢?

在OSAL_simpleBLECentral.c檔案中,定義了一個函數指標數組如下:


87行,Hal_ProcessEvent即為Hal層的任務處理函數指標,它是數組的第2個元素tasksArr[1],也就是說如果程式中要調用Hal層任務,直接寫語句“tasksArr[1]();”

函數Hal_ProcessEvent()就會被執行了。

 

Task雖然被建立好了,但是task是要執行我們給它規定的功能的,那它是在哪裡執行的呢?

接下來詳細分析task 的執行的問題。

 

 

 

 

三:檢測並執行有效任務事件

 

系統中task 的執行,是由事件(evnet)來驅動的,程式會迴圈檢測所有的task,如果發現某個task有新的event未被處理,那麼這個task就會被調用。

 

osal_start_system()是整個程式的核心,裡面是一個for死迴圈,不停調用函數osal_run_system(),它的實際功能就是不停檢測是否有event產生,如果有event,就執行對應的task,請看源碼:


1105行,定時器查詢函數,它會檢查所有的定時器,如果某個定時時間到達,就將相應的event 加入到tasksEvents[task_id],這裡task_id的值是添加定時器時設定好的,具體請看osal_set_event()函數代碼。

1110-1115行,檢查所有任務,是否有需要執行的event發生,並記錄這個event的索引idx。

1117行,taskCnt 是系統添加的任務個數,也就是tasksArr[]數組中元素的個數。

1123行,儲存當前任務的將要執行的所有event。

1124行,清除當前任務的所有event。

1127行,儲存當前任務的idx,供系統自己使用。

1128行,根據當前任務索引idx,在指標數組tasksArr[]中定址當前任務的函數指標,調用當前任務函數,處理其中一個event,處理完畢後,返回還未處理的event。

1132行,將未處理的event恢複給當前任務事件變數儲存,等待下一次再處理,直至處理問所有的event。

 

 

 

總結:

 

本節只是講解了協議棧的主體架構,協議棧只是一個基礎平台,在不同的方案中,就有不同的應用功能,相應的就必須為應用添加不同的task來實現實際的功能。

 

通過本節講解,添加一個task的基本步驟如下:

1.        在HAL層配置任務要用到的I/O 的屬性(如果不涉及I/O操作,則可省略此步驟)

2.        在數組tasksArr[]中新增工作(task)處理函數

3.        在函數osalInitTasks()中初始化任務task

 

根據上面的步驟我們可以很容易建立一個task。但是,如果程式中沒有產生task的事件(event),task永遠都不會運行。

 

這就有一個新的問題:event在什麼情況下產生?它又是如何產生?

我們將在【事件和訊息工作機制】一節中詳細分解。

 

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.