文章總列表

假日嵌入式藍芽開發工程師:nRF51822 (5)

Introduction of SoftDevice

這一篇我要介紹Nordic SDK的用法,我第一次讀完寫的筆記。自己也都不大會,只好寫下來給社會大眾笑了。

通信系統一般會包括 {Antenna, LNA, RF filter-chain, Digital-front-end, Baseband, BLE protocol}。Baseband/ protocol包括硬體加速器和軟體,這邊的軟體就是SoftDevice,Nordic提供編譯好的binary,燒進指定區域就有BLE protocol可以用。Nordic提供一系列的SoftDevice,我只用過S110,其他的都是照著網頁的寫(心虛)
  • S110:BLE Peripheral
  • S120:BLE Peripheral or Central
  • S130:BLE Central, Observer, Broadcaster
  • S210:ANT+
  • S310:BLE & ANT+ concurrent

Nordic的SoftDevice燒進去後,memory map如下圖,S110占Flash(96KB),RAM(8KB),這個數量級證明BLE protocol沒辦法自幹。Nordic SDK讓BLE protocol和User code跑在同個space裡,使用MPU(Memory Protection Unit)保護記憶體不互踩,只是debug要花點心思。另外SoftDevice會佔某些MCU的硬體,用戶要知道哪些硬體還可以用。這種做法最優的地方是BLE protocol能無痛升級,怎麼設計SoftDevice也很有趣。用戶的code用SVC(Supervisor Call)呼叫SoftDevice,這部分等有空再寫一下。我在用的S110 SoftDevice這裡有文件可以閱讀。



Basic Program Structure of LBS Example

底下介紹上一篇的程式,Nordic sample code結構都差不多,先把周邊設備都初始化,然後初始化BLE stack,最後進入一個low power的main-loop等待事件。Nordic整份SDK都用了event-driven思維,這部分也很值得學習。




看懂這個範例,免不了要到跨檔案到處讀,我也沒打算寫清楚所有細節(做不到啊...)。底下就盡量用註解的方法,大概描述一下。首先是Device driver initialization的部分:

  • timers_init()
    • SoftDevice本體會拿RTC0去用,這裡在配置RTC1。SoftDevice有部分是用source code形式,而且他們假設RTC1也有得用。
    • 簡而言之,要用SoftDevice其實RTC0/RTC1就都老實的配置下去,這樣程式才跑得起來,參考資料
  • leds_init()
    • 這個function容易一點,配置幾根LED pins而已。
  • button_init()
    • Nordic的範例程式包括debounce和完整的IRQ handling,有興趣可以追整包code。這個function設定button按下時,對應的event handler。
    • Event handler code比較麻煩一點,因為這個範例按下按鈕後,會呼叫BLE framework,通知手機說現在按鈕是按下或放開。
    • Nordic把和BLE相關實作放一個獨立的檔案,這個檔案後面還會不斷出現,用力讀吧!
      • components/ble/ble_services/ble_lbs/ble_lbs.c


整份程式和底下資料結構強相關,Softdevice回傳的handler都存在裡面。像fopen()回傳FILE*,這個指標要再塞給fwrite()/ fread()。資料結構還包括一個service_handle,和好幾個char_handle。這些Handle的data-type看起來很恐怖,其實只是uint16。使用Debugger連進去看,正好和BLE scanner看到的數值一致。



然後來介紹BLE相關的程式。

  • ble_stack_init()
    • SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false);
      • 設定BLE device使用那種crystal
    • ble_enable_params_t ble_enable_params = {0};
      err_code = sd_ble_enable(&ble_enable_params);
      • 啟動BLE service
    • ble_gap_addr_t addr;
      sd_ble_gap_address_get(&addr);
      sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr);
      • 設定BLE的MAC addresss,首先讀取晶片內的FICR裡的address,然後設定到softdevice。Reference
      • SoftDevice似乎支援run-time變化MAC address,我在這裡有看到人家在發問。這個範例直接讓ADDR從頭到尾都不變。
      • FICR定義:
        根據NRF51 manual,Device Address放在0x100000A4/ 0x100000A8,我用Debugger讀出來如下
      • 我用Debugger讀到的Device Driver是0xEF77_8B5B7E0C,和上述address MSB不一樣是因為BLE規定bit[47:46]必須是11,所以從AF->EF。
    • softdevice_ble_evt_handler_set(ble_evt_dispatch);
      • 前面提到SoftDevice是Event-Driven的程式寫法,所以告訴SoftDevice是哪個function負責處理events也是合情合理的。
      • 這包程式和前面提到的ble_lbs.c牽連極深,想看懂BLE做什麼,讀吧!
  • gap_params_init()
    • 這裡面設定security mode,device-name,以及連線參數。
    • 連線參數會大幅影響電池壽命,超級重要;security mode也很重樣;這裡可以故意把device name改掉,看nRF會不會有反應。
  • services_init()
    • 首先告訴BLE protocol我們現在UUID多少,這裡我承認講不清楚(自己也沒多懂)。欲知詳情,查一下BLE protocol裡的UUID規劃,網路上滿容易找的。
    • 然後會呼叫BLE protocol,新增一個service,把回傳的handler填進上述的資料結構。
    • 最後是把所有characteristics依序加入上一步的service裡。Nordic有個專門的寫法,裡面還有一堆參數可以填,用力的查文件吧。
      • LED characteristic很簡單,就是手機叫他亮就亮,暗就暗。
      • Button characteristic就複雜得多,裡面還有一個CCC要設定。
    • 我覺得這個function是使用Nordic SDK的精華,要弄清楚要有些BLE底子;但是我們不可能都看完文件再開始寫code,比較合理的做法是邊試邊改
  • advertising_init()
  • conn_params_init()
    • 這個function設定BLE在connection mode底下,使用的參數
  • advertising_start()
    • 上面參數都設定完,呼叫這個function就會開始動


Final Word

寫了很多,又好像什麼都沒寫,我也不是專業藍芽開發者,實在不曉得怎麼寫清楚(好想放棄啊)。但是起碼用這個範例,我們就有個會動的BLE系統,理論上可以拿它來改東改西,做成自己要的東西。

留言

這個網誌中的熱門文章

STM32 UART + DMA,使用HAL實作TX/RX,以及不定長度接收

幼犬書桌椅選擇心得 升降桌 兒童桌椅

CANON G3000 廢墨瓶改裝