上一篇文章《藍牙單芯片DA14580的硬件架構和低功耗》闡述了DA14580的硬件架構和低功耗的工做原理。本文文章闡述該平臺的軟件體系,並着重分析消息事件的處理機制。 編程
1、DA14580SOC硬件組成和軟件體系組成數組
DA14580芯片硬件架構包括三個部分:微信
1)使用ARM公司的cortex M0做爲CPUprocessor處理器。數據結構
2)使用RivieraWaves公司的IP核做爲BLEcore和基帶、射頻部分。架構
3)集成時鐘管理CMU、電源管理PMU、memory控制存儲和其餘外圍模塊控制器,如GPIO、UART、I2C、SPI和timer等等。函數
相應地,DA14580平臺SDK的軟件組成也包括如下組成部分:ui
1)ARMcortex M0平臺相關的庫文件,如啓動、CMSIS(the cortex Microcontroller software interface standard)支持的寄存器訪問、中斷異常訪問接口等。接口
2)RW公司的BLE驅動、射頻驅動,此外RW BLE還集成了系統的內核部分,其提供消息處理、定時器和任務調度等核心功能。因此DA14580平臺SDK的開發是基於RW公司研發的內核,而不是DIALOG公司研發的。此部分大部分的代碼都是固化在ROM裏面。隊列
3)SOC集成的其餘模塊的驅動,由DIALOG公司提供,如UART驅動等,此外其調用RW內核的相關接口來完成消息循環和低功耗功能。事件
4)應用程序,調用以上三個部分的接口來完成自定義功能。
咱們重點分析2)中的RW內核機制和功能。
2、RW內核
RW內核的指導文檔爲《RW-BT-KERNEL-SW-FS.pdf》。其主要包括如下三個部分:
1)Message,消息處理機制。
2)Taskand Schedule,任務和調度。
3)Timer,定時器使用方法。
3、Task
RW在BLE協議棧層次的基礎上抽象了多個任務task,每一個task完成一個軟件層次的功能。因此說RW內核是支持多個任務task的,但本質上,RW內核也是一個單任務內核,因此各個task能夠當作是可以完成特定功能的獨立函數體或者函數集合。
每一個task都有一個task ID,其具備優先級功能,相似於UCOS的優先級。
RW內核和UCOS的區別是:UCOS是多任務內核,具備時間片輪流執行,並具備互斥同步。
4、Message
4.1 消息標識
一個消息就要區分它是屬於哪一個task的,並且還要區分同一個task裏面的不一樣消息。因此一個Message包括兩個部分:
TASK_TYPE便是task的ID。在調度時,優先級高的task的消息會先獲得執行處理。
4.2 消息結構體元素
咱們只須要關注紅色圈着的這五個元素,第一個元素能夠看出消息結構體節點是以鏈表的形式來管理的。HCI相關的是指USB dongle這種應用形式,由PC主機控制藍牙BLE,我們不討論這種應用。
紅色圈到的五個元素分別的是:
1)id,即第一點說到的消息標識。
2)消息由哪一個目標task處理。
3)發出消息的task
4)消息參數的長度
5)消息參數的結構體地址
消息參數結構體是能夠自定義的,這裏經過void*轉換傳入地址。
4.3 消息動態內存管理
RW內核專門給消息處理提供動態內存管理機制,接口是:
void*ke_msg_alloc(ke_msg_id_t const id, ke_task_id_t const dest_id,
ke_task_id_t const src_id,uint16_t const param_len);
通常給應用提供一個宏,用於簡化寫法:
#defineKE_MSG_ALLOC(id, dest, src, param_str) \
(struct param_str*) ke_msg_alloc(id, dest, src, sizeof(structparam_str))
釋放接口是:void ke_msg_free(struct ke_msg const *param);. 在調度機制裏面會經過判斷消息處理的返回值對消息進行相應的處理,如釋放消息的內存。用戶編程通常不用調用釋放接口。
4.4 消息接口
1)帶參數的消息發送
voidke_msg_send(void const *param_ptr); param_ptr須要經過ke_msg_alloc接口申請動態內存。
通常的命令消息發送寫法以下:
structgapm_set_dev_config_cmd* cmd = KE_MSG_ALLOC(GAPM_SET_DEV_CONFIG_CMD,
TASK_GAPM, TASK_APP,gapm_set_dev_config_cmd);
ke_msg_send(cmd);
2)不帶參數的消息發送
voidke_msg_send_basic(ke_msg_id_t const id, ke_task_id_t const dest_id,ke_task_id_t const src_id)
5、TIMER
5.1 定時單位
10ms,RW內核提供一個定時器,其並非DA14580集成的TIMER1和TIMER3。對定時器的初始化等工做是在BLE初始化內部的,不須要用戶編程設置。用戶只須要調用RW內核的TIMER接口便可。
5.2 設置timer
voidke_timer_set(ke_msg_id_t const timer_id, ke_task_id_t const task, uint16_tconst delay);
timer_id是定時器消息,其屬於一種不帶參數的MESSAGE,delay是定時時間,10ms爲單位,當時間到達時,RW內核會發送timer_id到目標task的消息隊列。當內核schedule時即會執行定時器相應的回調。
6、Schedule
1.先取出最高優先級task的消息事件,該消息從消息隊列中pop出來
2.根據task的狀態和消息ID來獲得對應的handler
3.執行該handler回調
4.根據回調的返回值對消息進行處理
1)若是返回KE_MSG_CONSUMED,則內核free掉該消息。
2)若是返回KE_MSG_NO_FREE,則內核不處理該消息,但該消息也不會從新放到消息隊列,即內核不能再從消息隊列中得到該消息。
3)若是返回KE_MSG_SAVED,則內核不free該消息,而且將該消息從新入列。
7、基於狀態機的RW內核消息處理機制
Task數據結構以下:
RW內核是基於狀態機對消息進行處理的。從ke_task_desc看來,一個task包括顯式的狀態處理state_handler和默認的狀態處理default_handler。
state是task的狀態機變量,task可能有多個狀態,那麼state_handler是狀態處理集合,每一個狀態可能會處理多個消息回調,例如上層task會發送消息來執行調用,或者下層task發送消息來執行回調。
default_handler處理的消息表明該task在任意狀態時均可能受到的消息,例如底層task發出的斷開鏈接消息。
咱們也能夠得出,ke_state_handler表明一個狀態下的多個消息處理。所以,state_handler是一個ke_state_handler數組,而default_handler則是ke_state_handler元素。
8、參考文獻:
《UM-B-015_DA14580 Software architecture v4.0.pdf》、
《RW-BT-KERNEL-SW-FS.pdf》。
下一篇,敬請期待:
全球最低功耗藍牙單芯片DA14580的軟件體系
-層次架構和BLE消息事件處理過程
技術諮詢請發郵件:yqwucheng@163.com。
百分百原創,每週兩篇,阿里、魅族、nvidia、龍芯、炬力、拓爾思等頂級企業資深工程師分享----嵌入式、Linux、物聯網、GPU、Android、自動駕駛等技術,歡迎掃碼關注微信公衆號:嵌入式企鵝圈,實時推送原創文章!