假日嵌入式藍芽開發工程師: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本體,或著Nordic-tool
下載GCC
以前我用過Code Sourcery的GCC,這間公司做toolchain很強大,後來被Mentor Graphics買走,現在比較沒那麼活耀。現在我改用Launchpad提供的GCC-ARM,這是Canonical(發行Ubuntu公司 )提供的平台,應該是比較穩定一點。安裝包有portable的zip file或安裝檔,我最後選用安裝檔(理由如上)。
- https://launchpad.net/gcc-arm-embedded/+download
- gcc-arm-none-eabi-5_2-2015q4-20151219-win32.exe
下載mingw (for Windows)
Nordic SDK支援跨平台GCC + Makefile,為了能在各種作業系統用(Win/ Linux/ Mac),一定是用UNIX系列指令而不是WINDOWS指令。其實微軟就老實在cmd.exe底下,給出cp/ rm/ make/ awd/ sed這些常用工具不就結案了?我一共評估了這些解法:
- 下載Win32專用的Makefile執行檔,並且修改Nordic的Makefile。把rm改del,把cp改copy,然後每次我都覺得很累很委屈=>放棄這招。
- 使用Bash on Ubuntu on Windows,在windows 10透過kernel service跑一個user mode的Ubuntu Linux,然後直接原生跑bash,使用體驗就真的和跑Linux一樣!現在微軟CEO的作風和Steve Ballmer真的大不同!但是這招的本質是跑真實的Linux,所以整套toolchain都要是Linux版。當前的Windows Subsystem for Linux根本摸不到J-Link driver,所以這招根本也不合用。
- 最後一招就是用cygwin/ msys這類的外掛解決方案(真是不情願啊)。cygwin是老牌解決方案,但我很不喜歡,主因是terminal很醜,很肥大。msys是一組小型的toolchain,提供windows的cmd.exe的替代品,加上常見UNIX command,輕薄短小,就用它吧。
家裡的電腦要拿來打電動,使我離不開windows;如果有第二台開發專用機,直接裝一套Linux桌面其實會省事一點;上面這些事就不用折騰了。
下載SEGGER JLink Driver, SEGGER Ozone, NRFJPROG
SEGGER JLink driver
我一直很推SEGGER的JLink,裝個driver應該不為過。現在SEGGER JLink driver也有Linux/ Mac版,跨平台開發不是問題。
SEGGER Ozone Debugger
我們總是想要設斷點和單步執行,SEGGER有提供跨平台的Ozone debugger,裝起來用吧
nrfjprog
nRFJPROG這個檔案比較有趣,是Nordic用JLink SDK寫的燒錄工具,可以方便地把hex file寫進IC裡,想土炮也可以自己用Jlink command製作。在這裡,Nordic SDK預設會用NRFJPROG來燒MCU,所以就先裝吧!
下載和設定Nordic SDK
Nordic最早文件和SDK要買開發工具才能看,所以我去淘寶開發板只能去百度網盤下載,我也不好意思說出來。物聯網時代開發者才是寶,不然CPU像廢鐵。後來Nordic直接開放下載,我才能大方寫文章,不然我在這裡附上百度網盤還真得不好意思… Nordic SDK可以在這裡下載,我用v10.0。Nordic semiconductor的開發者網站資源也蠻豐富的,他們有員工回答問題,以及寫tutorial文件。
跑LED Blinky範例
終於到了最後一段了,怎麼用Nordic SDK的範例。因為我的板子PCA10001已經沒有標準支援,所以會較辛苦一點。首先複製一包code避免改錯:
before:
nRF51_SDK_10.0.0_dc26b5e/ examples/ peripheral/ blinky/
after:
nRF51_SDK_10.0.0_dc26b5e/ examples/ peripheral/ blinky_test/
目錄裡面長得像下圖,這裡簡單介紹一下裡面的結構。
- main.c
這個檔案有個while-loop,不斷toggle LED。底下有個delay 500ms,等一下成功下載以後,可以回來再改這個數字,看看有沒有生效 - pca10028/ blinky/
這個目錄代表PCA10028這塊板子,整顆IC都是空的,裡面想做什麼都自己控管。 - pca10028/ s110/
Nordic的BLE protocol名叫softdevice,會占用一定區塊的Flash/RAM。這個範例包括S110 (純粹的BLE peripheral)的範例。 - pca10028/ s110/ arm4/
pca10028/ s110/ arm5_no_packs/
pca10028/ s110/ armgcc/
pca10028/ s110/ iar/
Nordic SDK每個範例都提供4種toolchain的project file,這篇文章的範例是針對ARM-GCC
我手邊這片PCA10001沒有直接支援,所以我把pca10028目錄整個複製一份叫pca10001,然後切到pca10001/s110/armgcc進行以下修改
- 修改Makefile
- 把所有10028改成10001
- 把所有51422改成51822
- 修改blinky_gcc_nrf51.ld,這個檔案是linker script,要告訴linker每段記憶體大小多少。範例的Flash/RAM是256KB/32KB;我的NRF51822 Flash/RAM是256KB/ 16KB。修改如下
Before:
RAM (rwx) : ORIGIN = 0x20002000, LENGTH = 0x6000
After:
RAM (rwx) : ORIGIN = 0x20002000, LENGTH = 0x2000
Reference:
http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk51.v10.0.0%2Findex.html
一些make command,依序照順序key下去,就會動了!當然啦,原理還是得自己K了。
- make help
列出支援的targets,我這邊印出了nrf51822_xxac_s110 , flash_softdevice - make flash_softdevice
燒寫softdevice(只要做一次即可) - make clean
砍掉所有obj files - make nrf51822_xxac_s110 flash
重新build,然後把user code燒進去。這裡有個tricky的地方:燒flash的時候,不能只打make flash,不然沒用
Hack一下Makefile...
前面寫了我覺得自己弄開發環境很重要,這裡我也來擺弄一下Makefile,讓他更合用一點。
- 首先他的Makefile default target,對應的dependency是{clean, nrf51822_xxac_s110}。這表示會無條件clean再build,把clean拔掉讓他變incremental build。
- 要燒flash竟然要打make nrf51822_xxac_s110 flash,實在麻煩。為什麼不能打make flash就自動build並且燒錄?這邊的patch繼承上一個定義的變數"build_target",避免duplication
- Nordic預設的compile option竟然沒有開啟debug information,到了debugger很難用。這邊等一下會搭配Debugger使用,可以試試看沒有-g會怎樣。
設定SEGGER OZone Debugger for NRF51822
用慣Keil切gcc已經不大舒服;如果還要再用gdb(GNU debugger),我大概會立馬放棄。但這不表示gdb不值得學習,他最大的好處(也是缺點)是吃command line,這代表他有scriptting的能力,也許某些場合用得上。還好有SEGGER Ozone能用,打開以後可以用Project wizard設定環境,底下放幾張截圖示範怎麼設定他:
- 第一張圖設定是哪個device,tool需要知道device資訊看是哪種CPU family(這樣才能正確顯示core peripheral registers),以及相關的Flash/RAM資訊。第二個Peripherals是ARM制定的CMSIS-SVD (System View Description)格式,使用XML描述CPU周邊registers。只要CPU製造商提供這檔案,各家tool也吃這個檔案,就能在工具裡正確顯示CPU周邊registers。目前ARM陣營已經都用這個標準,Nordic也在SDK提供,位在$SDK_ROOT/SVD/nrf51.svd。
- 第二張圖設定J-Link的速度。
- 最後一張圖設定ELF file在哪裡,這樣等一下就能step by C-code(否則只能step by instruction)
OZone debugger的Project file格式是文字檔,可以動手改東改西。這部分能參考User manual,比如說連上debugger立刻想看某個記憶體,或著讀寫某些記憶體,這類scriptting能力都非常好用。
下圖是實際跑起來的screenshot
- 左上角有functions view/ source files view
- 中間有source code以及右上角的有disasm view
- 右邊中間有registers可以看,包括CPU registers以及Peripherals。如果上面的SVD files沒有設定,那麼Peripherals這群就不會出現。
- 其他功能就和一般debugger一樣,可以試試看如果CFLGAG沒有開-g的差異。
Final
嗯,都寫道第三篇了,竟然還沒寫到和藍芽開發有關的東西(笑)
Reference
留言