發表文章

文章總列表

假日嵌入式藍芽開發工程師: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思維,這部分也很值得學習。 ...

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

圖片
Introduction 這篇開始要進入BLE主題,首先會介紹怎麼跑起來BLE-blinky這個範例,然後介紹Nordic的BLE protocol怎麼使用。 Compile & Flash Nordic LBS Example Against PCA10001 Nordic提供不少BLE的範例,裡面最簡單的就是LBS(LED-Button Service)。這個範例讓手機透過BLE遠端控制板子的LED亮暗;按下button時候,手機也可以即時收到通知。這個範例包括central和peripheral雙向通訊,仔細研究大概就能抓住Nordic SDK怎麼用。編譯和Flash的步驟如下: Sample code路徑如下: nRF51_SDK_10.0.0_dc26b5e/ examples/ ble_peripheral/ experimental_ble_app_blinky/ 把裡面的pca10028整個複製一份叫pca10001,把裡面S110的Makefile和Linker script做必要的修改,然後Makefile也可以補強一點。這裡不再重寫一次,直接參考前一篇文章。 然後下去build,送你一個build error應該是合情合理的 (3)的原因是某個目錄找不到,名稱和board name以及softdevice name有關。我們換了一個board,這裡也得幫他準備 從這個:experimental_ble_app_blinky/ config/ experimental_ble_app_blinky_s110_pca10028 複製到:experimental_ble_app_blinky/ config/ experimental_ble_app_blinky_s110_pca10001 這個目錄只有一個檔案,叫nrf_drv_config.h,這個檔案其實是SDK的一部分,調整那些功能要啟動。Nordic也不希望直接改SDK裡的這個檔案,正確的做法是拷貝這個檔案到project底下,然後修改inclusion search path,把private header放到最前面。這也是實戰中非常常見的做法。 然後理論上就可以build以及燒錄進去,接下來開發版就變成一個BL...

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

圖片
Introduction 這篇文章介紹怎麼用Makefile + GCC搭建NRF51的開發環境,我試著結合自己工作經驗,聊一下我對建構開發環境的看法。另外我在Windows/ Linux/ Mac三個作業系統都試過可以用,投資時間在GCC開發環境其實是值得的。 我認為工程師一定要自己親手架設過開發環境,親身體驗所有細節,才會成為高手。我工作的地方選擇專業分工,大多環境的東西都有專人維護,團隊成員只要會用會抱怨就可以了。但是compiler如果出問題,最好的手法是單獨抽出compile command,修改compile flag,或著丟出pre-processor output來觀察。能弄清楚程式怎麼編譯,連結,image檔怎麼出來,真的是好處多多。 我過去我用過Keil ARM寫Samsung S3C2410的bootloader。產生好ELF以後,抽出text/data section,自己寫工具下載到NAND Flash,然後看CPU開機載入我寫的程式 -> 爽!不過前面的敘述裡,還是有個版權物Keil ARM。所以這次我要脫離舒適圈,採用GCC + Makefile做一樣的事。 目錄結構 好的目錄結構帶你上天堂!這個題目其實沒有聖杯,端看規劃的目的。我規劃的目錄結構如下,設計初衷是整個目錄能放在隨身碟帶著走,所以compiler也解壓縮到裡面去。但我還是得安裝另外一些小工具。最後我還是用安裝檔裝到/c/Program Files/底下,這樣能大幅壓縮開發包目錄。開發包目錄我會搭配版本控制一起用,預期裡面的東西 一行都不能改 (不過後面有些原因會放寬),我選擇用另外一個git project來儲存user code(但最後也不是,呵呵)。 雖然不完美,還是放出來給大家見笑一下,過幾個月我再回來笑自己。 nrf51822_dev_pkg/ dist/ 放下載回來的安裝包,比如compiler,SDK,Nordic-Tool都放這裡 doc/ 放網路上找到的文件,比如板子的schematic,IC的data sheet,Application Note SDK/ 放Nordic SDK解壓縮的本體 tool/ 放工具解壓縮後的目錄,比如compiler...

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

圖片
Introduction 這篇文章想介紹怎麼建構土炮研究BLE環境,包括我的2014/2016環境。在真的拿MCU寫BLE FW之前,先找個BLE裝置玩一下人家的產品比較有趣。 BLE Development Tool, 2014 我和BLE結緣是因為一邊跑步想一邊觀測心跳,所以我買了藍芽心跳帶。那時我的小米2s還停在Android 4.1.1,根本不支援BLE。我刷上了Ivan秋葉隨風提供的AOSP Android 4.4,然後就抓得到心跳錶了! 小米2s,刷機note 我買的心跳帶是 雙揚i-GotU HRM-10 ,我懷疑他感應的是我的步伐而不是心跳,也常常抓不到,整個就很爛。最初懷疑是手機BLE收不好,我想透過Raspberry Pi和心跳帶打交道看看,畢竟Android/ Raspberry Pi都是基於Linux。我插上藍芽Dongle,編譯bluez,使用附贈的gatt-tool研究BLE原理。因為心跳帶很爛,研究做得很辛苦,BLE link經常斷線。但是從tool終究是看到心跳值,成就感滿點。 假日藍芽工程師,架設環境 假日藍芽工程師,先動起來再說 透過gatt-tool繼續探索BLE,在bluetooth的網站到處查那堆UUID,還真的給我參透了!我寫了兩篇文章講ATT/GATT,這兩篇點閱率滿高的,表示應該很多人都想研究BLE。如果我想賺100USD廣告費,多寫一點就對了(笑)。 後來我也成功在Android上寫程式讀到心跳。 假日藍芽工程師,ATT protocol 假日藍芽工程師,GATT protocol 假日藍芽/Android工程師: 寫個APP讀心跳 BLE Development Tool, 2016 我還是推薦透過心跳帶研究BLE,平常運動可用,不研究也不會浪費。我推薦名世電子的 Echowell DMH-30 ,他是BLE/ANT+雙介面,可以同時連到我的Garmin碼表(ANT+)和手機(BLE)。這間公司的產品和服務都很到位,比上面那間雙揚好多了。 2014年在Raspberry Pi開發BLE的方法還可以用,只是不大舒服,事實上我寫完文章就沒再去玩gatt-tool了。我改用Nordic Semiconductor的nRF Co...

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

Introduction 2014/10買回來的nRF51822開發版,兩年來斷斷續續學習我終於大概有點成果了。接下來想寫一些文章把這些東西紀錄一下。希望可以早日收到Google給我的100USD廣告費支票(哈)。 http://lihgong.blogspot.tw/2014/10/ble.html 開發版 我手邊的開發版是淘寶買的nRF51822EK_TM,他是Nordic Semiconductor的nRF51822 EK, PCA1001仿製品,上面多放了常見的周邊(如下),可以視為原廠的加強版,而且還賣得便宜一點,像是三軸加速器感應器就直接放上去,拿來學習還滿好的。 JLINK-OB MPU6050 (三軸加速度感應器 + Gyro) 1x 三色LED 3A Relay UART to USB (PL2308) 128M SPI Flash 1x buzzer nRF51-EK (Evaluation Kit), PCA10001 https://www.nordicsemi.com/eng/Products/Bluetooth-low-energy/nRF51822-Evaluation-Kit 時至今日,我大概不會推薦上面的方案。因為Nordic後來推的開發版叫nRF51-DK (PCA10028),支援Ardunino Uno Revision 3接頭。他也援mbed開發,這個很酷,板子上的J-Link會變成一個磁碟機,把ELF檔拖進去就可以燒錄。最要命的是新出的SDK已經不直接支援PCA10001,要稍微動點手腳才能用範例。我如果不是已經買了板子也懶得弄了。推薦直接到mouser電子買一片,只是要折騰一下他的網站就是... (但是真的滿便宜的)。 nRF51-DK (Development Kit), PCA10028 https://developer.nordicsemi.com/nRF5_SDK/ Mouser電子nRF510DK http://www.mouser.tw/ProductDetail/Nordic-Semiconductor/nRF51-DK/?qs=%2fha2pyFadugZXgh3xrn3AtVnVqf%...

假日嵌入式系統工程師:SEGGER RTT (3)

圖片
假日嵌入式系統工程師:SEGGER RTT (3) 專業的Trace系統 在前面的文章[1][2],我介紹怎麼用SEGGER RTT搭配printf()。這個方法有幾個明顯的缺點: printf()需要Data memory存format字串,在SRAM受限的場合會很傷腦筋 printf()需要花時間產生字串 舉例來說,產生十進位數值(%d)一定不是瑣碎的工作 回頭看SEGGER RTT,既然已經有路能送字串,為什麼不直接送binary values,由PC產生字串就好?以下面這段code為例: printf("idx1=%d, idx2=%d\n", idx1, idx2); 上面的code,format string起碼要 >16 bytes,而且MCU要花cycles來產生字串,最後字串也要 >16 bytes;還不包括code size的開銷。如果丟binary values就可以只傳必要的資訊 (12 bytes) ID碼,表示format string是哪一個 ID=1 -> “idx1=%d, idx2=%d\n” 參數 idx1 idx2 這篇文章介紹怎麼在MCU/PC實作這個idea。另外我認為 SEGGER SystemView 實作的方法也是同一招,底層都是RTT,只是PC端的程式換另外一套。 MCU-Side 程式 和所有通訊系統一樣,發送端比較簡單。我們定義一道macro來產生ID,裡面包括magic number來讓PC偵測trace起點,以及trace-ID本體。程式的主體是一個loop,透過SEGGER_RTT_Write不停送出 {ID, i, i<<16}。如果接收端能正確解出來,那我們就成功了。 #define MK_TRACE_HEADER(id) ((0xABCD<<16) | ((id)<<0)) int main(void) { unsigned int buf_idx = 0; while(1) { unsigned int i; for(i=0; i<256; i++) { unsigned in...

假日嵌入式系統工程師:SEGGER RTT (2)

圖片
假日嵌入式系統工程師:SEGGER RTT (2) 簡介 這篇文章介紹我怎麼在WINDOWS平台跑起SEGGER-RTT。看完以後,你大概會發現這東西比想像還要容易設定。因為SEGGER RTT Viewer只提供WINDOWS版,所以這篇文章沒得選;不過下一篇SEGGER RTT (3)就會介紹怎麼在Linux/ Mac使用。而且這個形式是我個人最滿意的Log system的樣貌。 再聊一下SEGGER JLINK 我用中國做的NRF51822板子,上面有謎版的JLINK。我有買一顆JLINK-EDU,也算是合法使用吧。SEGGER的JLINK是相當出色的工具,基礎版的JLINK-EDU價格殺到2400NTD,值得投資一套。另一個合法管道是買 NRF51-DK ,上面也有JLINK on board。 RTT 程式碼 安裝完SEGGER driver以後,可以在底下目錄找到壓縮檔 /c/Program Files (x86)/SEGGER/JLink_V50i/Samples/SEGGER_RTT_V510i.zip 解壓縮以後,把裡面的這些檔案拷貝到自己的MCU projects裡: RTT/SEGGER_RTT.c RTT/SEGGER_RTT.h RTT/SEGGER_RTT_Conf.h RTT/SEGGER_RTT_printf.c 我用的NRF SDK (nRF51_SDK_10.0.0_dc26b5e)也有RTT library,路徑是 $(NRF51_SDK)/components/drivers_ext/segger_rtt/ 編譯 RTT 程式 把上面四個C file加到MCU project某個目錄,應該很容易就能編譯過。我用了GCC & KEIL-C都沒問題。 SEGGER RTT Library提供一個簡化版的printf() int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); 我們在MCU寫一個簡單的程式: unsigned int buf_idx = 0; while(1) { unsigned int i; for(i=0; i<256; i++) { ...

假日嵌入式系統工程師:SEGGER RTT (1)

圖片
假日嵌入式系統工程師:SEGGER RTT (1) UART真的很麻煩 (Target-Side) 從我學C語言開始,我認定最好用的debug工具叫printf()。在嵌入式系統的世界,一般我們會用UART (Universal Asynchronous Receiver/Transmitter)來印出printf()。幾年下來,學的東西稍微多一點以後,我實在是越來越討厭這東西。 首先UART很慢,9600bps傳1byte大概要0.1ms。如果CPU跑在16Mhz,代表1byte需要1600 CPU cycles。 一般的UART硬體緩衝區都少得可憐( 16550 UART , 16bytes),一般embedded MCU只有4bytes這種數量級。如果用polling簡單實作的UART driver,MCU跑BLE這種應用時,根本不可能透過UART丟訊息。 另一招是UART-IRQ功能,在buffer快光的時候打中斷出來,然後再塞資料給他。這需要額外的工作去搞定這個模式。而且還需要設計一個ring buffer來當write buffer存字串。 為了要有(3)描述的 先進 功能,我們還得逐一搞定UART HW。更天怒人怨的是:這東西每顆晶片玩都還不一樣。 最後一點和UART無關,只是printf()合成字串也要花不少時間,沒準還得準備個小型的C library,不然Code size可能無法接受。 UART在PC更麻煩 1994年USB推出以後,配備COM port的電腦大概已經絕跡了15年以上了。其實也不是絕跡, 想要還是有的 。不要問我怎麼讓他會動,很麻煩的!現代流行的貨色是UART轉USB的晶片,有家叫 FTDI 的公司,或著台灣的 旺玖 也有做這種產品。2016年買得到的開發板,上面都會有這種晶片。不過這個解法還是不夠完美。 要看到開發版丟出的資訊,一般會開個叫做"TeraTerm"的程式,人類需要設定底下的參數: UART速度 COM port編號 Start bits數目 Data bits數目 End bits數目 Parity bit是否存在 這些參數真的很不直覺,開發嵌入式系統這麼多年了,每次我都會遲疑。這裡面最討厭的是COM port編號,就算是同一片板子,只要插的USB孔不一...

SEGGER RTT (3)

圖片
SEGGER RTT (3) Let’s Build a Trace System In previous article articles [1][2], I’ve introduced how to use SEGGER RTT as conventional printf method. I’m not fully satisfied with this method as I mentioned in [2]. Because it had several drawbacks printf() requires SRAM to store format string, which may be a problem is SRAM size is limited printf() takes cycles to generate string It must not be trivial job to generate decimal value (%d) Since a channel (SEGGER RTT) already exists to transmit string, why not reuse the channel to transmit essential values and do string composing in PC-side. Take following code as an example: printf("idx1=%d, idx2=%d\n", idx1, idx2); In legacy method, it may require >16bytes and MCU does string formatting. In proposed method, one could only transmit essential values (12bytes) An ID code which indicates the format string ID=1 -> “idx1=%d, idx2=%d\n” Parameters idx1 idx2 The article would introduce how to implement the...

SEGGER RTT (2)

圖片
SEGGER RTT (2) SEGGER RTT (2) Introduction The article introduce how to use SEGGER-RTT in WIN32. I guess you will be amazing how east it is to setup RTT. I did my experiment over my NRF51822 board with a on-board JLINK. If you don’t have a JLINK, I recommend to invest one. SEGGER also provides inexpensive JLINK-EDU at 2400NTD (roughly 80USD). I think that’s quite affortable and worth of buying one. This article is written under WIN32 because SEGGER only provides RTT viewer utility in WIN32. I will show how to use RTT in Linux/ Mac in SEGGER RTT (3), which is the final form of logging service (I’m 100% satisfied with). RTT Source Code In SEGGER driver installation folder, you could find a zipped file /c/ Program Files (x86) /SEGGER/ JLink_V50i /Samples/ SEGGER_RTT_V510i.zip Uncompressed the file, and copy following files to your MCU project RTT/SEGGER_RTT .c RTT/SEGGER_RTT .h RTT/SEGGER_RTT_Conf .h RTT/SEGGER_RTT_...