




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、本系列教程將結合TI推出的CC254x SoC 系列,講解從環(huán)境的搭建到藍牙4.0協(xié)議棧的開發(fā)來深入學習藍牙4.0的開發(fā)過程。教程共分為六部分,本文為第三部分:第三部分知識點:第十一節(jié) 串口通信第十二節(jié) Flash的讀寫第十三節(jié) BLE協(xié)議棧簡介第十四節(jié) OSAL工作原理第十五節(jié) BLE藍牙4.0協(xié)議棧啟動分析有關TI 的CC254x芯片介紹,可點擊下面鏈接查看:主流藍牙BLE控制芯片詳解(1):TI CC2540同系列資料推薦:由淺入深,藍牙4.0/BLE協(xié)議棧開發(fā)攻略大全(1)由淺入深,藍牙4.0/BLE協(xié)議棧開發(fā)攻略大全(2)有關本文的工具下載,大家可以到以下這個地址:朱兆祺ForARM
2、第十一節(jié) 串口通信在軟件開發(fā)過程中調試是一個很關鍵的過程,而調試用的最多的手段就是打印Log,嵌入式平臺很少有顯示設備,所以我們需要將信息通過串口打印到PC端。MT254xboard上已經通過RS232芯片將UART0連接到DB9,我們只需要將DB9連接到電腦即可,UART0 對應的外部設備 IO 引腳關系為:P0_2-RX,P0_3-TX。我們需要將這兩個IO配置為復用功能,CC2540的USART可以配置為SPI模式或者異步UART模式,這里我們需要配置為異步UART模式。首先配置IO為UART模式:PERCFG &= 0x01; / 配置UART為位置 1P0SEL = 0x3c; /
3、P0_2,P0_3,P0_4,P0_5用作串口功能P2DIR &= 0XC0; / P0 優(yōu)先作為UART0配置UART0寄存器,將UART0配置為8N1模式,波特率為115200。U0CSR |= 0x80; / UART 方式U0GCR |= 11; / U0GCR與U0BAUD配合U0BAUD |= 216; / 波特率設為115200UTX0IF = 0; / 清除中斷標志U0CSR |= 0X40; / 允許接收IEN0 |= 0x84; / 開總中斷,接收中斷這里采用中斷方式來接收串口數據,并在中斷中回調應用層的接收處理函數。#pragma vector = URX0_VECTOR
4、_interrupt void UART0_ISR(void)uint8 ch;URX0IF = 0; / 清中斷標志ch = U0DBUF;if ( NULL != RecvCb ) / 調用回調函數RecvCb(ch);為了測試串口的通訊功能,這里我們通過串口接收命令的方式來控制LED的亮滅和蜂鳴器的響和停止,并且顯示當前的狀態(tài)。根據串口輸出提示,發(fā)送對應字符可以實現相應功能,并且顯示狀態(tài)。第十二節(jié) Flash的讀寫嵌入式系統(tǒng)中需要存儲數據,而片內的Flash資源很匱乏,所以我們經常需要使用SpiFlash來存儲數據,MT254xboard中板載了一個 512Kbyte的Flash,下面我
5、們來驅動此Flash。上一小節(jié)中我們用SPI的方式驅動了LCD12864,這節(jié)我們繼續(xù)用SPI來驅動板載的 Flash,詳細的說明了如何驅動這片Flash,在此不做累述,我們復制LCD12864工程,重命名為SpiFlash,在此工程中添加GD25Q40的兩個驅動文件。下面我們來檢測這個Flash,檢測的方法為,全部寫入0xAA,然后再讀出,對比是否為0xAA,如果是,那Flash是沒有問題的,否則Flash可能已經有壞塊。具體的代碼見例程,這個過程所需要的時間取決于我們需要檢測的區(qū)域大小,如果完全檢測,則可能需要幾分鐘的時間。int main(void)SysStartXOSC();LCD1
6、2864_Init(); / LCD初始化GD25Q40_Init(); / Flash初始化LCD12864_DisStr(0, “Flash Check.?!保?sprintf(LCDBuf, “Flash ID :%04X”, GD25Q40_ReadID(); / 讀取器件IDLCD12864_DisStr(1, LCDBuf);GD25Q40_EraseChip(); / 擦除整片Flash 大約需要10SLCD12864_DisStr(2, “Erase Chip Complete”);uint32 iCnt = 0;/ 全部寫入0xAAconst uint8 Write = 0x
7、AA;for(iCnt=0; iCnt CHECK_ADDR_RANGE; iCnt+)GD25Q40_Write(&Write, iCnt, 1); / 寫入0xAA/ 讀取Flash內部的值,與寫入的值對比uint8 Read;for(iCnt=0; iCnt = CHECK_ADDR_RANGE)LCD12864_DisStr(3, “Flash Check Success”);GD25Q40_EraseChip(); / 再次擦除while(1);return 0;MT254X藍牙4.0開發(fā)板Flash效果:第十三節(jié) BLE協(xié)議棧簡介TI的協(xié)議棧分為兩部分:控制器和主機。對于4.0以前
8、的藍牙,這兩部分是分開的。所有profile和應用都建構在GAP或GATT之上。根據這張圖,我們從底層開始介紹。TI的這款CC2540器件可以單芯片實現BLE藍牙協(xié)議棧結構圖的所有組件,包括應用程序。1.1.1 PHY層1Mbps自適應跳頻GFSK(高斯頻移鍵控),運行在免證的2.4GHz。1.1.2 LL層LL層為RF控制器,控制設備處于準備(standby)、廣播、監(jiān)聽/掃描(scan)、初始化、連接,這五種狀態(tài)中一種。五種狀態(tài)切換描述為:未連接時,設備廣播信息,另外一個設備一直監(jiān)聽或按需掃描,兩個設備連接初始化,設備連接上了。發(fā)起聊天的設備為主設備,接受聊天的設備為從設備,同一次聊天只能
9、有一個意見領袖,即主設備和從設備不能切換。1.1.3 HCI層HCI層為接口層,向上為主機提供軟件應用程序接口(API),對外為外部硬件控制接口,可以通過串口、SPI、USB來實現設備控制。1.1.4 L2CAP層L2CAP層提供數據封裝服務,允許邏輯上的點對點通訊。1.1.5 SM層SM層提供配對和密匙分發(fā),實現安全連接和數據交換。1.1.6 ATT層ATT層負責數據檢索,允許設備向另外一個設備展示一塊特定的數據稱之為屬性,在ATT環(huán)境中,展示屬性的設備稱之為服務器,與它配對的設備稱之為客戶端。鏈路層的主機從機和這里的服務器、客服端是兩種概念,主設備既可以是服務器,也可以是客戶端。從設備毅然
10、。1.1.7 GATT層GATT層定義了使用 ATT 的服務框架和配置文件(profiles)的結構。BLE 中所有的數據通信都需要經過 GATT。GATT負責處理向上與應用打交道,其關鍵工作是把為檢索工作提供合適的profile結構,而profile由檢索關鍵詞(characteristics)組成。1.1.8 GAP層GAP直接與應用程序或配置文件(profiles)通信的接口,處理設備發(fā)現和連接相關服務。另外還處理安全特性的初始化。對上級,提供應用程序接口,對下級,管理各級職能部門,尤其是指示LL層控制室五種狀態(tài)切換,指導保衛(wèi)處做好機要工作。1.2 TI協(xié)議棧源碼介紹在第二章我們講解了源
11、碼的安裝,這里我們就來剖析源碼的結構。打開協(xié)議棧目錄我們可以看到下圖:BLE源碼:目錄名內容說明Accessories一些工具和已經編譯好的Hex文件此文件夾中有Btool的安裝包、USB-CDC的驅動。ComponentsHal驅動,OSAL源碼、協(xié)議棧通用源碼此文件夾是OSAL各層組件的實現Documents幫助文檔協(xié)議棧說明文檔,這是學習BLE最好的資料。Projects工程文件這里有一些TI的Demo,我們開發(fā)一般是在Demo的基礎上進行這里TI給出了很多Demo,這些例程都是經過了SIG評審的,ble 文件夾中有很多工程文件,有些是具體的應用,例如BloodPressure、Gluc
12、oseCollector 、GlucoseSensor 、 HeartRate 、HIDEmuKbd 等都為傳感器的實際應用,有相應標準的 Profile。其中有4種角色: SimpleBLEBroadcaster 、 SimpleBLECentral 、SimpleBLEObserver、SimpleBLEPeripheral。他們都有自己的特點。1.Broadcaster 廣播員 非連接性的信號裝置2.Observer 觀察者 掃描得到,但不能鏈接3.Peripheral 從機 可鏈接,在單個鏈路層鏈接中作為從機4.Central 主機 掃描設備并發(fā)起鏈接,在單鏈路層或多鏈路層中作為主機。
13、我們的講解將圍繞這主機和從機進行。因為其它的設備都是基于這兩種設備擴展開來的。第十四節(jié) OSAL工作原理藍牙為了實現同多個設備相連,或實現多功能,也實現了功能擴充,這就產生了調度問題。因為,雖然軟件和協(xié)議棧可擴充,但終究最底層的執(zhí)行部門只有一個。為了實現多事件和多任務切換,需要把事件和任務對應的應用,并起一個名字OSAL操作系統(tǒng)抽象層。OSAL管理的實現如果實現軟件和硬件的低耦合,使軟件不經改動或很少改動即可應用在另外的硬件上,這樣就方便硬件改造、升級、遷移后,軟件的移植。HAL硬件抽象層正是用來抽象各種硬件的資源,告知給軟件。其作用類似于嵌入式系統(tǒng)設備驅動的定義硬件資源的h頭文件。BLE低功
14、耗藍牙系統(tǒng)架構:OSAL作為調度核心,BLE協(xié)議棧、profile定義、所有的應用都圍繞它來實現。OSAL不是傳統(tǒng)大家使用的操作系統(tǒng),而是一個允許軟件建立和執(zhí)行事件的循環(huán)。軟件功能是由任務事件來實現的,創(chuàng)建一個任務事件需要以下工作:1. 創(chuàng)建task identifier任務ID;2. 編寫任務初始化(task initialization routine)進程,并需要添加到OSAL初始化進程中,這就是說系統(tǒng)啟動后不能動態(tài)添加功能;3. 編寫任務處理程序;4. 如有需要提供消息服務。BLE協(xié)議棧的各層都是以OSAL任務方式實現,由于LL控制室的時間要求最為迫切,所以其任務優(yōu)先級最高。為了實現任
15、務管理,OSAL通過消息處理(messageprocess),存儲管理,計時器定時等附加服務實現。系統(tǒng)啟動流程:為了使用OSAL,在main函數的最后要啟動一個名叫osal_start_system的進程,該進程會調用由特定應用決定的啟動函數 osalInitTasks(來啟動系統(tǒng))。osalInitTasks逐個調用BLE協(xié)議棧各層的啟動進程來初始化協(xié)議棧。隨后,設置一個任務的 8bit任務ID(task ID),跳入循環(huán)等待執(zhí)行任務,系統(tǒng)啟動完成。1. 任務優(yōu)先級決定于任務ID,任務ID越小,優(yōu)先級越高2. BLE協(xié)議棧各層的任務優(yōu)先級比應用程序的高3. 初始化協(xié)議棧后,越早調入的任務,任
16、務ID越高,優(yōu)先級越低,即系統(tǒng)傾向于處理新到的任務每個事件任務由對應的16bit事件變量來標示,事件狀態(tài)由旗號(taskflag)來標示。如果事件處理程序已經完成,但其旗號并沒有移除,OSAL會認為事情還沒有完成而繼續(xù)在該程序中不返回。比如,在SimpleBLEPeripheral實例工程中,當事件START_DEVICE_EVT發(fā)生,其處理函數SimpleBLEPeripheral_ProcessEvent就運行,結束后返回16bit事件變量,并清除旗語 SBP_START_DEVICE_EVT。每當OSAL事件檢測到了有任務事件,其相應的處理進程將被添加到由處理進程指針構成的事件處理表單中
17、,該表單名叫taskArr(taskarray)。taskArr中各個事件進程的順序和osalInitTasks初始化函數中任務ID的順序是對應的。有兩種,最簡單的方法是使用osal_set_event函數(函數原型在OSAL.h文件中),在這個函數中,用戶可以像定義函數參數一樣設置任務ID 和事件旗語。第二種方法是使用osal_start_timerEx函數(函數原型在OSAL_Timers.h文件中),使用方法同 osal_set_event函數,而第三個以毫秒為單位的參數osal_start_timerEx則指示該事件處理必須要在這個限定時間內,通過定時器來為事件處理計時。類似于Linu
18、x嵌入式系統(tǒng)內存分配C函數mem_alloc,OSAL利用osal_mem_alloc提供基本的存儲管理,但osal_mem_alloc只有一個用于定義byte數的參數。對應的內存釋放函數為osal_mem_free。不同的子系統(tǒng)通過OSAL的消息機制通信。消息即為數據,數據種類和長度都不限定。消息收發(fā)過程描述如下:接收信息,調用函數osal_msg_allocate創(chuàng)建消息占用內存空間(已經包含了osal_mem_alloc函數功能),需要為該函數指定空間大小,該函數返回內存空間地址指針,利用該指針就可把所需數據拷貝到該空間。發(fā)送數據,調用函數osal_msg_send,需為該函數指定發(fā)送目
19、標任務,OSAL通過旗語SYS_EVENT_MSG告知目標任務,目標任務的處理函數調用osal_msg_receive來接收發(fā)來的數據。建議每個OSAL任務都有一個消息處理函數,每當任務收到一個消息后,通過消息的種類來確定需要本任務做相應處理。消息接收并處理完成,調用函數osal_msg_deallocate來釋放內存(已經包含了osal_mem_free函數功能)。為了實現更好的移植性,協(xié)議棧將硬件層抽象出了一個HAL硬件抽象層,當新的硬件平臺做好后,只需修改HAL,而不需修改HAL之上的協(xié)議棧的其他組件和應用程序。第十五節(jié) BLE藍牙4.0協(xié)議棧啟動分析TI的這款CC2540/CC2541
20、器件可以單芯片實現BLE藍牙協(xié)議棧結構圖的所有組件,包括應用程序。從這章開始我們來剖析協(xié)議棧源碼,我們選用 SimpleBLEPeripheral工程開刀,這是一個從機的例程,基本的工作是對外廣播,等待主機來連接,讀寫展示的屬性。首先打開工程文件,打開后可以看到整個工程的結構。我們按照系統(tǒng)的啟動順序來一步一步走,我們都知道在C代碼中,一般啟動的首個函數為main,這個函數在 SimpleBLEPeripheral_Main.c中,打開文件,可以看到這個文件只有一個main函數和一個函數的申明,我們暫時不理會那個申明的函數,先看main都做了些什么工作:Int main(void)/* Init
21、ialize hardware */HAL_BOARD_INIT(); / 硬件初始化/ Initialize board I/OInitBoard( OB_COLD ); / 板級初始化/* Initialze the HAL driver */HalDriverInit(); / Hal驅動初始化/* Initialize NV system */osal_snv_init(); / Flash存儲SNV初始化/* Initialize LL */* Initialize the operating system */osal_init_system(); / OSAL初始化/* Enab
22、le interrupts */HAL_ENABLE_INTERRUPTS(); / 使能總中斷/ Final board initializationInitBoard( OB_READY ); / 板級初始化#if defined ( POWER_SAVING )osal_pwrmgr_device( PWRMGR_BATTERY ); / 低功耗管理#endif/* Start OSAL */osal_start_system(); / No Return from here 啟動OSALreturn 0;通過代碼我們可以看到,系統(tǒng)啟動的過程,主要是做了一些初始化,如果開啟了低功耗,則還
23、需要開啟低功耗管理。我們先不去理會初始化做了什么,但是我們知道在main函數的最后啟動了OSAL,那么我們就進去看看OSAL是如何運作的。在IAR中如果需要跳轉到某個函數或變量的定義,可以在此函數名中右擊然后選擇Go To Definition就可以調到相應的定義。void osal_start_system( void )#if !defined ( ZBIT ) & !defined ( UBIT )for(;) / Forever Loop#endifosal_run_system();這里看到我們進入了一個死循環(huán),并且一直調用osal_run_system(),那我們再進入此函數。vo
24、id osal_run_system( void )uint8 idx = 0;#ifndef HAL_BOARD_CC2538osalTimeUpdate(); / 定時器更新#endifHal_ProcessPoll(); / Hal層信息處理do if (tasksEventsidx) / Task is highest priority that is ready.break; while (+idx tasksCnt); / 檢查每個人任務是否有事件if (idx tasksCnt) / 有事件發(fā)生uint16 events;halIntState_t intState;HAL_EN
25、TER_CRITICAL_SECTION(intState); / 進入臨界區(qū)events = tasksEventsidx;tasksEventsidx = 0; / Clear the Events for this task. 清除事件標志HAL_EXIT_CRITICAL_SECTION(intState); / 退出臨界區(qū)activeTaskID = idx;events = (tasksArridx)( idx, events ); / 執(zhí)行事件處理函數activeTaskID = TASK_NO_TASK;HAL_ENTER_CRITICAL_SECTION(intState);
26、 / 進入臨界區(qū)tasksEventsidx |= 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)進入低功耗模式osal_pwrmgr_powerconserve(); / Put the processor/sy
27、stem into sleep#endif/* Yield in case cooperative scheduling is being used. */#if defined (configUSE_PREEMPTION) & (configUSE_PREEMPTION = 0)osal_task_yield();#endif在這里可以看到這個OSAL的核心,整個OSAL通過檢測每個任務是否有事件發(fā)生,如果有則執(zhí)行相應的任務,處理相應的事件。如果沒有事件需要處理并且開啟了低功耗模式,則系統(tǒng)就會進入低功耗模式。這里有一個很關鍵的地方,OSAL是如何知道哪個事件需要哪個任務來處理呢?events
28、 = (tasksArridx)( idx, events ); / 執(zhí)行事件處理函數我們看這里有一個很關鍵的數組tasksArr,很顯然,這是一個函數指針數組,我們看看它的定義。const pTaskEventHandlerFn tasksArr =LL_ProcessEvent, / task 0Hal_ProcessEvent, / task 1HCI_ProcessEvent, / task 2#if defined ( OSAL_CBTIMER_NUM_TASKS )OSAL_CBTIMER_PROCESS_EVENT( osal_CbTimerProcessEvent ), / t
29、ask 3#endifL2CAP_ProcessEvent, / task 4GAP_ProcessEvent, / task 5GATT_ProcessEvent, / task 6SM_ProcessEvent, / task 7GAPRole_ProcessEvent, / task 8GAPBondMgr_ProcessEvent, / task 9GATTServApp_ProcessEvent, / task 10SimpleBLEPeripheral_ProcessEvent / task 11;可以看到在這個數組的定義中,每個成員都是任務的執(zhí)行函數,按照任務的優(yōu)先級排序,并且在
30、osalInitTasks中初始化的時候,我們可以看到每個任務都有一個對應的初始化函數,并且傳遞了一個taskID,此ID從0開始自增,這里有一點非常重要,初始化的順序和任務數組的定義順序是一樣的,這就保證了我們給任務發(fā)生消息或事件時能夠準確的傳遞到相應的任務處理函數。void osalInitTasks( void )uint8 taskID = 0;tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);osal_memset( tasksEvents, 0, (sizeof( uint16 ) * task
31、sCnt);/* 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 );應用層的初始化
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 鹽城市公積金管理辦法
- 定興縣公租房管理辦法
- 庫存物品采購管理辦法
- 肝腎虧虛中醫(yī)辨證課件
- 東莞小學3年級數學試卷
- 恩施定向招聘數學試卷
- 固安初一期末數學試卷
- 高考必修一數學試卷
- 肌腱術后護理課件
- 德州初中數學試卷
- (高清版)CJJT 30-2024 糞便處理廠運行維護及其安全技術標準
- 安全檢查工安全培訓教學教案
- 2024年浙江省新華書店集團招聘筆試參考題庫附帶答案詳解
- 1.知識點1-2-1 理解曝光三要素與曝光量
- 《中華民族共同體概論》考試復習題庫(含答案)
- PTBD管路維護技術
- 220kV變電運行中的故障排除方法
- 30題投資管理類崗位常見面試問題含HR問題考察點及參考回答
- 煤礦典型事故案例分析培訓課件
- 15D501 建筑物防雷設施安裝
- 電氣設備運行與維護-開關電器的運行與維護
評論
0/150
提交評論