Nordic有2套并存的SDK
1、老的nRF5 SDK
2、新的NCS SDK
兩套SDK相互獨(dú)立,
大家選擇其中一套進(jìn)行開(kāi)發(fā)即可。
一般而言,如果你選擇的芯片是nRF51或者nRF52系列,那么推薦使用nRF5 SDK
如果你選擇的是Nordic最新產(chǎn)品系列,比如nRF53或者nRF9160,那么請(qǐng)選擇NCS SDK
還有一種特殊情況,雖然你選擇的是nRF52芯片,但需要使用最新的一些射頻技術(shù),比如藍(lán)牙測(cè)向,藍(lán)牙Mesh v1.1,低功耗藍(lán)牙音頻,那么也需要使用NCS SDK。
換句話(huà)說(shuō),最新的射頻技術(shù),Nordic都只會(huì)在NCS上進(jìn)行開(kāi)發(fā),而nRF5 SDK將進(jìn)入維護(hù)階段不再增加新的特性(如發(fā)現(xiàn)bug,會(huì)對(duì)其進(jìn)行修復(fù)的)。
目錄
1、NCS SDK介紹
2、NCS SDK 安裝
2.1 - 百度網(wǎng)盤(pán)下載 (僅適用于Windows)
2.2 - 通過(guò)nRF connect桌面版直接下載GitHub下載(Windows/ Linux/ macOS)
2.3 - nRF command line tools安裝
3、NCS SDK開(kāi)發(fā)環(huán)境說(shuō)明
3.1 - SES 開(kāi)發(fā)環(huán)境搭建
3.1.1. nRF52項(xiàng)目示例
3.1.2.nRF53項(xiàng)目示例
3.1.3.nRF9160項(xiàng)目示例
3.1.4. 自定義項(xiàng)目裝載示例
3.2 - 命令行方式開(kāi)發(fā)環(huán)境搭建
3.2.1.nRF52項(xiàng)目示例
3.2.2. nRF53項(xiàng)目示例
3.2.3. nRF9160項(xiàng)目示例
3.3 - 命令行方式開(kāi)發(fā)環(huán)境搭建
4、NCS SDK項(xiàng)目的配置或選項(xiàng)
4.1 - NSC項(xiàng)目配置介紹(autoconf.h和devicetree_unfixed.h)
4.1.1.Kconfig (Kconfig, prj.conf及autoconf.h)
4.1.2.Device Tree (*.dts, *.overlay及devicetree_unfixed.h)
4.1.3. 配置程序起始地址和大小
4.2 - 圖形化查看Kconfig選項(xiàng)
4.2.1.SES查看
4.2.2.命令行方式查看
5、NCS SDK中幾個(gè)比較重要的目錄
5.1- 例子目錄
5.2 - API目錄
5.3 板子定義目錄
6、開(kāi)發(fā)你的第一個(gè)NCS程序
6.1- 修改hello_world main.c文件
6.2 - 在項(xiàng)目中添加一個(gè)新的文件blinky.c
6.3 修改blinky.c文件
6.4 編譯和運(yùn)行你的第一個(gè)hello_world程序
6.5 使用prj.conf和
7、開(kāi)發(fā)你的第一個(gè)multi-image(多image)應(yīng)用
7.1 - 分區(qū)管理 (Partition Manager)
7.2 多image的hello_world程序開(kāi)發(fā)
8、NCS編譯系統(tǒng)幾個(gè)要注意的點(diǎn)
8.1 - NCS幾個(gè)重要的編譯系統(tǒng)變量
8.2 - conf文件命名規(guī)則及編譯順序
8.3 - overlay 文件命名規(guī)則及編譯順序
nRF5 SDK的介紹
關(guān)于nRF5 SDK的介紹,請(qǐng)參考這篇博文之前的博文,基本上都是基于nRF5 SDK進(jìn)行闡述的,尤其是這篇:
Nordic nRF51/nRF52開(kāi)發(fā)環(huán)境搭建
詳細(xì)講解了nRF5 SDK開(kāi)發(fā)環(huán)境的搭建,這里不再贅述。下面將只對(duì)NCS SDK進(jìn)行闡述,以期讓大家快速了解這個(gè)Nordic最新SDK,并盡快熟悉和上手。
1、NCS SDK介紹
NCS全稱(chēng)nRF Connect SDK,是Nordic最新的SDK平臺(tái),該平臺(tái)將支持Nordic所有產(chǎn)品線(xiàn),包括低功耗藍(lán)牙,蜂窩網(wǎng),2.4G,藍(lán)牙Mesh,Zigbee,Thread,CHIP等。
換句話(huà)說(shuō),由于短距離無(wú)線(xiàn)網(wǎng)絡(luò)和長(zhǎng)距離無(wú)線(xiàn)網(wǎng)絡(luò)共用同一個(gè)SDK,將使得你同時(shí)具備兩種網(wǎng)絡(luò)的開(kāi)發(fā)經(jīng)驗(yàn),因?yàn)樗麄兊目蚣苁且粯拥模?qū)動(dòng)是一樣的,網(wǎng)絡(luò)協(xié)議棧的編寫(xiě)風(fēng)格也是相仿的。
只要你熟悉了其中一種網(wǎng)絡(luò)的開(kāi)發(fā),那么相關(guān)的經(jīng)驗(yàn)可以迅速?gòu)?fù)制到新網(wǎng)絡(luò)平臺(tái)上。
NCS SDK內(nèi)嵌Zephyr RTOS,并沿用了Zephyr project的編譯系統(tǒng)。Zephyr Project是Linux基金會(huì)推出的一個(gè)Apache2.0開(kāi)源項(xiàng)目,版權(quán)非常友好,適合用于商業(yè)項(xiàng)目開(kāi)發(fā)。
°Zephyr Project
Zephyr Project是一個(gè)合作社區(qū),其產(chǎn)品就是Zephyr,具體包括Zephyr RTOS,Zephyr組件以及Zephyr編譯系統(tǒng)等
Zephyr很多地方都模擬了Linux,比如使用了DeviceTree和Kconfig,對(duì)Linux很熟的同學(xué),閱讀Zephyr代碼會(huì)感到很親切的
經(jīng)常有人問(wèn):為什么NCS要使用Zephyr RTOS?
其實(shí)答案就蘊(yùn)含在Zephyr Project的愿景中:The Zephyr Project strives to deliver thebest-in-class RTOS for connected resource-constrained devices, built be secureand safe
Zephyr的愿景跟Nordic的產(chǎn)品策略高度吻合,這也是為什么Nordic要選Zephyr的主要原因
NCS SDK和Zephyr Project兩者最大的區(qū)別有3個(gè):
owner不同,NCS SDK由Nordic負(fù)責(zé),Zephyr SDK由Linux基金會(huì)負(fù)責(zé)。NCS開(kāi)發(fā)中碰到的所有問(wèn)題,Nordic都將負(fù)責(zé)解決
產(chǎn)品管理不一樣,NCS SDK將由Nordic完成所有相關(guān)測(cè)試和考核,并符合Nordic產(chǎn)品開(kāi)發(fā),測(cè)試,發(fā)布和質(zhì)量控制流程,因此NCS有自己的版本,并跟Zephyr版本控制解耦
NCS具有很多增強(qiáng)特性,比如Nordic特有的藍(lán)牙鏈路層等
所以,從產(chǎn)品角度看,NCS SDK和Zephyr SDK是兩套完全不同的SDK。但是,如果從代碼角度看,那么NCS SDK和Zephyr SDK又基本上是一樣的。
在本文章的下面部分,在不引起混淆的情況下,經(jīng)常會(huì)把NCS和Zephyr兩個(gè)概念換著使用,因?yàn)楸举|(zhì)上他們是一個(gè)東西。
°NCS使用了CMake編譯系統(tǒng)
并使用了大量Python腳本以輔助生成一些頭文件,代碼和hex,這些都大大增加開(kāi)發(fā)的可移植性和便利性。
°NCS SDK放在GitHub上
里面包含多個(gè)代碼庫(kù),其主代碼庫(kù)(Manifest)是nrf,同時(shí)還包含Zephyr,MCUBoot,mbedtls,nrfxlib等其他代碼庫(kù)。NCS SDK可以同時(shí)在Windows,macOS和Linux上運(yùn)行。
°于Zephyr和NCS的build系統(tǒng)是一樣的
于Zephyr和NCS的build系統(tǒng)是一樣的,如果你正在學(xué)習(xí)Zephyr RTOS,那么也可以參考本篇文章,從NCS SDK開(kāi)始學(xué)習(xí)Zephyr。由于NCS SDK新增了很多特性,比如圖形化的DEBUG,豐富的例程,你會(huì)發(fā)現(xiàn)從NCS SDK學(xué)習(xí)Zephyr是一條便捷通道。
2、NCS SDK安裝
NCS SDK開(kāi)發(fā)包比較大,目前大概4G(后續(xù)有可能會(huì)更大),由于GitHub網(wǎng)絡(luò)帶寬的問(wèn)題,很多人下載的時(shí)候會(huì)出現(xiàn)超時(shí)錯(cuò)誤,為此我們提供如下兩種安裝方案。
如果你能在早上6點(diǎn)左右起床,請(qǐng)參考2.2方案(GitHub直接下載);如果你不想早點(diǎn)起來(lái),請(qǐng)參考2.1方案(百度網(wǎng)盤(pán)下載)。
°2.1 百度網(wǎng)盤(pán)下載(僅適用于Windows)
代碼鏈接
地址如下所示:
下載鏈接:https://pan.baidu.com/s/1FKTfY3Q_zBVvviO7KC7Gyg#list/path=%2Fblog
提取碼:y8fb
進(jìn)入目錄“開(kāi)發(fā)你的第一個(gè)NCS(Zephyr)應(yīng)用程序”,選擇相應(yīng)的版本,推薦使用最新版本。本篇博文完成之時(shí)最新量產(chǎn)tag為:
ncs_v1.4.1
后續(xù)還會(huì)有ncs_v1.5.0,ncs_v1.6.0等。
直接把相應(yīng)的壓縮包下載下來(lái)并解壓到本地目錄,SDK即算安裝完成。
注意,這個(gè)壓縮包只能在Windows系統(tǒng)上運(yùn)行,不能在Linux和macOS上運(yùn)行。
*注:ncs_v1.4.99-dev1是專(zhuān)為nRF53準(zhǔn)備的一個(gè)臨時(shí)開(kāi)發(fā)版本,量產(chǎn)版本需要等到v1.5.0或者更新。
°2.2 通過(guò)nRF connect桌面版直接GitHub下載(同時(shí)支持Windows, Linux和macOS)
采用這個(gè)方案,你必須早上6:00左右起床,切記!
首先,下載桌面版nRF connect (同時(shí)支持Windows/macOS/Linux平臺(tái))。下載鏈接為:
https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Connect-for-desktop/Download#infotabs,選擇你的平臺(tái)和版本。
桌面版nRF connect安裝成功后,將如下所示:
在nRF connect桌面版中有2個(gè)app都可以完成NCS SDK安裝:
一個(gè)是Toolchain Manager
一個(gè)是Getting Started Assistant
如果你是GitHub老手,可以按照Getting Started Assistant的步驟一步一步來(lái)安裝。如果你嫌一步一步安裝麻煩,那么建議你使用Toolchain Manager一鍵安裝。
下面將會(huì)以Toolchain Manager的方式(支持Windows和macOS)來(lái)講解安裝過(guò)程(Getting Started Assistant的方式自己有興趣可以自己去摸索,而且Linux系統(tǒng)目前只能采用這種方式)。
首先install Toolchain Manager,然后open,進(jìn)入settings界面,選擇安裝目錄,如下:
然后重新選擇SDK ENVIRONMENTS頁(yè)面,并選擇SDK相應(yīng)版本進(jìn)行安裝,如下所示:
根據(jù)網(wǎng)速不同,這個(gè)過(guò)程持續(xù)時(shí)間變化很大,我這邊網(wǎng)絡(luò)大概需要20分鐘完成所有下載和安裝,安裝成功后你將得到如下目錄內(nèi)容:
°2.3nRF command line tools安裝
下載完SDK壓縮包,再下載 “nRF-Command-Line-Tools_10_11_1_Installer.exe”, 即nRF command line tools,nRFcommand line tools包括Jlink驅(qū)動(dòng)以及Nordic自己開(kāi)發(fā)的一些命令行工具,如nrfjprog,nrfutil以及mergehex等,這些工具對(duì)開(kāi)發(fā)非常有幫助。nRF command line tools下載鏈接為: https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Command-Line-Tools/Download#infotabs
3、NCS SDK開(kāi)發(fā)環(huán)境說(shuō)明
NCS支持的工具鏈有2套:
一套是SEGGER Embedded Studio,簡(jiǎn)稱(chēng)SES,圖形化的IDE
一套是命令行方式(沿用了Zephyr工具鏈),其實(shí)就是GCC工具鏈
兩套工具鏈選其一即可,推薦大家使用SES,因?yàn)樗膁ebug功能非常好使。(GCC工具鏈的debug功能使用起來(lái)就比較復(fù)雜了)。
下面將分別對(duì)SES和命令行方式兩種開(kāi)發(fā)環(huán)境進(jìn)行介紹,大家可以參考其中一種或者兩種結(jié)合一起使用。
°3.1SES開(kāi)發(fā)環(huán)境搭建
通過(guò)百度網(wǎng)盤(pán)或者Toolchain Manager安裝的SDK,必須進(jìn)入如下目錄:install folder oolchain并雙擊SEGGER Embedded Studio.cmd以打開(kāi)SES,而不能在其他地方直接打開(kāi)SES,如下所示:
SES啟動(dòng)成功后,進(jìn)入Tools->Options,我們需要先對(duì)IDE進(jìn)行配置。
如下兩種方式的配置有可能都能工作起來(lái),選擇一種適合你的(一般來(lái)說(shuō),推薦配置二,這個(gè)配置方式可以適用任何電腦環(huán)境)。
°配置一:
°配置二:
配置好了之后,我們就可以打開(kāi)一個(gè)工程進(jìn)行編譯了。進(jìn)入File->Open nRF Connect SDK Project。
在NCS中,項(xiàng)目是通過(guò)CMakeLists.txt表示的,如下:
而開(kāi)發(fā)板一般是在如下目錄的:
選擇開(kāi)發(fā)板,就是選擇芯片,除此之外,開(kāi)發(fā)板還規(guī)定了芯片的一些外設(shè)使能情況,以及一些基本外圍電路連接情況,這個(gè)跟Keil如下選擇Device的操作是異曲同工的,而且NCS這種做法更靈活,功能也更多,擴(kuò)展性也更好。
如下為hello_world項(xiàng)目的裝載圖:
下面將對(duì)nRF52/nRF9160/nRF53項(xiàng)目,以及客戶(hù)自定義項(xiàng)目,分別進(jìn)行闡述,以詳細(xì)說(shuō)明如何裝載一個(gè)項(xiàng)目,編譯一個(gè)項(xiàng)目,下載一個(gè)項(xiàng)目和debug一個(gè)項(xiàng)目。 °3.1.1nRF52項(xiàng)目示例 以nrfapplications rf_desktop項(xiàng)目為例,開(kāi)發(fā)板選擇支持LLPM的gaming mouse:nrf52840gmouse_nrf52840
裝載成功后,編譯,如下所示:
然后下載,如下所示:
如果要Debug,按如下界面進(jìn)入:
°3.1.2nRF53項(xiàng)目示例 Nordic第一個(gè)支持nRF53的tag是v1.4.99-dev1,v1.5.0將正式支持nRF53的量產(chǎn)開(kāi)發(fā),如果你需要開(kāi)發(fā)nRF53,請(qǐng)使用v1.4.99以上版本。 由于nRF53包括兩個(gè)核:
app核:用來(lái)運(yùn)行應(yīng)用程序
network核:network核用來(lái)運(yùn)行射頻協(xié)議棧
所以每次下載的時(shí)候需要同時(shí)把兩個(gè)核的hex都下載進(jìn)去,但是SES只支持一次下載一個(gè)核(west可以同時(shí)下載兩個(gè)核,具體請(qǐng)參考第3.2節(jié))。 在使用SES開(kāi)發(fā)nRF53的時(shí)候,項(xiàng)目裝載/編譯/下載/debug跟其他芯片是一樣的,但這些操作只是針對(duì)一個(gè)核(一般來(lái)說(shuō)都是app核),此時(shí)如果還需要network核配合的話(huà),那么需要你手動(dòng)先把network核的image下載進(jìn)去,這個(gè)可以通過(guò)nrfjprog或者west來(lái)完成。
這里要強(qiáng)調(diào)一點(diǎn)的是,當(dāng)你選擇一個(gè)藍(lán)牙項(xiàng)目,這個(gè)項(xiàng)目默認(rèn)會(huì)同時(shí)把a(bǔ)pp核和network核對(duì)應(yīng)的工程都進(jìn)行編譯,然后生成各自的hex文件,然后你通過(guò)nrfjprog或者west把network核的image下載進(jìn)去,通過(guò)SES本身的Target->Download菜單把a(bǔ)pp核的image下載進(jìn)去。 以nrfsamplesluetoothperipheral_uart藍(lán)牙透?jìng)黜?xiàng)目為例:
編譯如下所示:
編譯成功后,先下載network核里面的image,我們以west flash來(lái)下載。進(jìn)入目錄: nrfsamplesluetoothperipheral_uartuild_nrf5340dk_nrf5340_cpuapphci_rpmsg,然后在cmd輸入: west flash 即可將image下載到network核里面,如下所示:
如果west flash在你的環(huán)境跑不通,那么你可以直接使用nrfjprog來(lái)下載network核的image,進(jìn)入目錄: nrfsamplesluetoothperipheral_uartuild_nrf5340dk_nrf5340_cpuapphci_rpmsg,然后在cmd輸入如下命令: nrfjprog -f NRF53 --coprocessor CP_NETWORK --sectorerase--program merged_CPUNET.hex --verify
然后下載app核image,app核image可以直接通過(guò)SES下載,如下:
如需debug,按如下界面進(jìn)入:
°3.1.3 nRF9160項(xiàng)目示例 以nrfsamples rf9160mqtt_simple項(xiàng)目為例:
編譯如下所示:
下載如下所示:
如需debug,按如下界面進(jìn)行:
°3.1.4 自定義項(xiàng)目裝載示例 如果是你的自定義項(xiàng)目或者Zephyr項(xiàng)目或者不使用toolchain自帶的SES,此時(shí)就不能使用SES自帶的快捷方式來(lái)裝載項(xiàng)目,而需要自己去相應(yīng)的目錄找到項(xiàng)目工程和開(kāi)發(fā)板,比如我們裝載Zephyr的blinky例子。先選擇項(xiàng)目工程CMakeLists.txt所在的目錄,如下:
再選擇相應(yīng)的開(kāi)發(fā)板,如下:
然后項(xiàng)目就裝載成功了,如下:
后面編譯,下載和調(diào)試,和之前一樣,就不再贅述。 °3.2 命令行方式開(kāi)發(fā)環(huán)境搭建 NCS或者Zephyr項(xiàng)目命令行編譯的時(shí)候,一般使用west命令,west語(yǔ)法可以通過(guò)west –help獲得,如下:
如果你能看到上面的界面,那么你的環(huán)境基本上就沒(méi)問(wèn)題了。 一個(gè)典型的west命令如下所示: west build -bnrf52840dk_nrf52840 *注:-b指定開(kāi)發(fā)板,這里使用nRF52840開(kāi)發(fā)板 通過(guò)百度網(wǎng)盤(pán)或者Toolchain Manager安裝的SDK,必須進(jìn)入如下目錄:install folder oolchain并雙擊git-cmd.cmd以打開(kāi)命令行,而不能直接打開(kāi)CMD,如下所示:
git-cmd.cmd會(huì)自動(dòng)把環(huán)境變量設(shè)好,否則后續(xù)編譯會(huì)有問(wèn)題。 下面分別以nRF52/nRF53/nRF9160開(kāi)發(fā)為例,展示相應(yīng)的編譯和下載命令。 °3.2.1 nRF52項(xiàng)目示例
下面以編譯nrfapplications rf_desktop項(xiàng)目為例來(lái)講解。首先進(jìn)入項(xiàng)目所在的目錄
cd nrfapplications rf_desktop 界面將如下所示:
由于已經(jīng)進(jìn)入了項(xiàng)目所在的目錄,編譯的時(shí)候就無(wú)需再指定項(xiàng)目目錄了,由于nrf_desktop支持多個(gè)開(kāi)發(fā)板,我們還需要指定用哪一個(gè)開(kāi)發(fā)板,如下所示: west build -bnrf52840gmouse_nrf52840 或者 west build -bnrf52840gmouse_nrf52840 -p *注:-p用來(lái)清除build目錄緩存
由于上面沒(méi)有指定build目錄,上面的命令會(huì)自動(dòng)生成一個(gè)build目錄(名字就是build),然后所有的編譯文件會(huì)自動(dòng)放在該build目錄下: build目錄如下所示:
編譯成功后,就可以燒寫(xiě)了,使用如下命令進(jìn)行燒寫(xiě): west flash 或者 west flash –erase
°3.2.2nRF53項(xiàng)目示例 以nrfsamplesluetoothperipheral_uart為例來(lái)講解。首先進(jìn)入目錄:nrfsamplesluetoothperipheral_uart,然后輸入如下編譯命令: west build -bnrf5340dk_nrf5340_cpuapp--build-dir build_nrf5340dk_nrf5340_cpuapp -p *注:-b指定開(kāi)發(fā)板,--build-dir指定編譯目錄,-p清除老的編譯目錄內(nèi)容
編譯成功后,就可以燒寫(xiě)了,使用如下命令進(jìn)行燒寫(xiě):
west flash--build-dir build_nrf5340dk_nrf5340_cpuapp
°3.2.3nRF9160項(xiàng)目示例
以nrfsamples rf9160mqtt_simple為例來(lái)講解。首先進(jìn)入目錄: nrfsamples rf9160mqtt_simple 然后輸入如下編譯命令: west build -bnrf9160dk_nrf9160ns --build-dir build_nrf9160dk_nrf9160ns -p *注:-b指定開(kāi)發(fā)板,--build-dir指定編譯目錄,-p清除老的編譯目錄內(nèi)容
編譯成功后,就可以燒寫(xiě)了,使用如下命令進(jìn)行燒寫(xiě): west flash--build-dir build_nrf9160dk_nrf9160ns
°3.3 NCS SDK版本說(shuō)明 NCS SDK開(kāi)發(fā)包目錄如下所示:
可以看出,NCS SDK包含nrf,zephyr,bootloader,nrfxlib,modules等多個(gè)代碼庫(kù),其中nrf代碼庫(kù)就是NCS SDK的主代碼庫(kù)(manifest),nrf代碼庫(kù)的版本就是NCS SDK的版本,所以要查看NCS SDK當(dāng)前版本號(hào),進(jìn)入nrf目錄,輸入git branch,如下:
熟悉git的同學(xué)都知道,一個(gè)SDK如果包含多個(gè)代碼庫(kù),那么每個(gè)代碼庫(kù)都有自己的版本,而且代碼庫(kù)版本之間是相互關(guān)聯(lián)的。 以NCS SDK為例,當(dāng)nrf版本切換為v1.4.0時(shí),其他代碼庫(kù)的版本也需要做相應(yīng)切換。 那么對(duì)應(yīng)nrf v1.4.0的Zephyr代碼庫(kù)版本是多少呢?mcuboot代碼庫(kù)版本是多少呢?
如果直接使用git工具,那么你需要一個(gè)一個(gè)記,然后一個(gè)一個(gè)checkout。在NCS或者Zephyr中,引入了west工具,這樣通過(guò)管理nrf代碼庫(kù)版本就可以間接管理其他代碼庫(kù)的版本,比如我們現(xiàn)在把NCS SDK版本切換到v1.4.0,指令如下所示: git checkout v1.4.0 然后通過(guò)west update命令,就可以讓其他代碼庫(kù)版本自動(dòng)跟v1.4.0 nrf代碼庫(kù)同步,這樣你不需要記住或者管理其他代碼庫(kù)版本,只需管理nrf代碼庫(kù)版本即可。 west update
4、NCS 項(xiàng)目的配置或選項(xiàng)
°4.1 NCS項(xiàng)目配置介紹(autoconf.h和devicetree_unfixed.h)
每一個(gè)NCS或者Zephyr項(xiàng)目都包含了非常多的配置項(xiàng)或選項(xiàng),總數(shù)有可能達(dá)幾千項(xiàng)之多,然而絕大多數(shù)配置項(xiàng)我們都不需要去管他們,只需要使用默認(rèn)值即可,所以開(kāi)發(fā)一個(gè)簡(jiǎn)單的NCS應(yīng)用程序,有可能我們不需做任何配置,就可以跑起來(lái)。
當(dāng)你開(kāi)發(fā)復(fù)雜的應(yīng)用程序的時(shí)候,你又會(huì)體會(huì)到NCS配置的靈活性和方便性了,這其實(shí)也是NCS一個(gè)很大的優(yōu)勢(shì)。
本章我們先講如何查看配置項(xiàng),后面一章我們?cè)僖岳觼?lái)說(shuō)明如何更改配置項(xiàng)。
NCS或者Zephyr里面主要包含兩種配置項(xiàng):
Kconfig:主要負(fù)責(zé)軟件的配置
DeviceTree:主要負(fù)責(zé)板子硬件的配置
兩者最終都會(huì)生成一個(gè).h文件,其Kconfig生成的頭文件為:autoconf.h,而DeviceTree生成的頭文件為devicetree_unfixed.h,他們都在如下目錄:
autoconf.h文件示例如下:
devicetree_unfixed.h文件示例如下:
如果大家開(kāi)發(fā)過(guò)nRF5 SDK的話(huà),一定記得里面有個(gè):sdk_config.h,從機(jī)理上,sdk_config.h和上面的autoconf.h/devicetree_unfixed.h并沒(méi)有本質(zhì)區(qū)別,他們都是完成同樣的功能。 但是很多人都覺(jué)得Kconfig和DeviceTree很復(fù)雜,其實(shí)他們復(fù)雜之處在于如何生成這兩個(gè)頭文件,但是頭文件本身并不復(fù)雜。 在nRF5 SDK中,用戶(hù)可以直接修改sdk_config.h文件,由于sdk_config.h文件太大,所以Nordic使用了CMSIS_Configuration_Wizard來(lái)格式化這個(gè)頭文件,以形成如下的圖形化界面方便大家去修改它:
在NCS或者Zephyr里面,由于autoconf.h/devicetree_unfixed.h是由Python腳本自動(dòng)生成的,所以用戶(hù)不能直接修改autoconf.h/devicetree_unfixed.h這兩個(gè)頭文件。 用戶(hù)只能去修改生成這兩個(gè)頭文件的輸入,以達(dá)到間接修改他們的目的。這樣做的好處是:更靈活,而且不容易出錯(cuò)(Python會(huì)自動(dòng)幫你找出配置不合理的地方或者語(yǔ)法錯(cuò)誤)。 可以說(shuō),一旦你熟悉了這套配置機(jī)制,你就會(huì)愛(ài)上它。 下面分別對(duì)autoconf.h和devicetree_unfixed.h兩者的生成過(guò)程進(jìn)行闡述。 °4.1.1 Kconfig(Kconfig, prj.conf及autoconf.h) 我們先把生成autoconf.h文件的整體流程圖貼出來(lái),后面再對(duì)這個(gè)圖進(jìn)行解釋?zhuān)?
autoconf.h文件是由許許多多的Kconfig文件生成的(注:其實(shí)Kconfig來(lái)源于Linux系統(tǒng),NCS或者Zephyr對(duì)其進(jìn)行了繼承和定制),基本上每個(gè)模塊都有自己的Kconfig文件,比如藍(lán)牙controller模塊:
使用文本編輯器打開(kāi)Kconfig,你將會(huì)看到它的內(nèi)容大概如下所示:
除了系統(tǒng)模塊可以定義Kconfig文件,你自己的項(xiàng)目模塊也可以定義自己的Kconfig文件。 如何定義? 依葫蘆畫(huà)瓢,仿照例子來(lái)即可。 記住,在NCS或者Zephyr里面,只要可以用文本編輯器打開(kāi)的文件,他們的語(yǔ)法都是直接可讀的,不需要你另外去學(xué)習(xí)他們,直接仿照例子,你就可以定制自己的內(nèi)容。 除了Kconfig,autoconf.h還有一個(gè)輸入來(lái)源: 本項(xiàng)目的配置文件。 前面說(shuō)過(guò),Kconfig文件都是模塊自帶的,模塊為每一個(gè)選項(xiàng)都設(shè)了一個(gè)默認(rèn)值。 如果你想修改這個(gè)默認(rèn)值,怎么辦? 你不需要跑到模塊下面直接把Kconfig文件改了(這樣不方便,而且也會(huì)影響到其他項(xiàng)目工程的運(yùn)行)。為此NCS或者Zephyr引入了prj.conf文件,prj.conf文件內(nèi)容大概如下所示:
通過(guò)prj.conf,大家就可以更改默認(rèn)的Kconfig選項(xiàng)了,而且這個(gè)更改是永久的,并只適用于本項(xiàng)目。 所有的Kconfig和prj.conf結(jié)合,先生成一個(gè).conf文件,最后再生成autoconfig.h。.conf文件在如下目錄:
其內(nèi)容大概如下所示:
可以看出,.config文件格式更接近Kconfig和prj.conf,起到了一個(gè)中間橋梁作用。 .config和autoconfig.h兩者內(nèi)容是可以一一對(duì)應(yīng)的,因此大部分圖形配置系統(tǒng)都是直接調(diào)用.config文件來(lái)完成圖形化配置Kconfig的,后面我們會(huì)講解如何使用SES和menuconfig來(lái)圖形化配置.config文件。 .config是一個(gè)臨時(shí)文件,編譯系統(tǒng)默認(rèn)會(huì)以它為基準(zhǔn)來(lái)生成autoconfig.h,所以一旦你的Kconfig或者prj.conf更新了,記得一定要重新裝載項(xiàng)目,以更新.config文件,從而生成新的autoconfig.h文件。 °4.1.2Device Tree (*.dts, *.overlay及devicetree_unfixed.h) 同樣我們先把生成devicetree_unfixed.h的整體流程圖列出來(lái),后面再對(duì)其進(jìn)行解釋?zhuān)?
DeviceTree也是Linux里面的概念,NCS或者Zephyr對(duì)其進(jìn)行了繼承和定制。在DeviceTree里面,每一種硬件比如芯片或者板子,都可以使用DeviceTree語(yǔ)言進(jìn)行描述。 DeviceTree使用了樹(shù)形結(jié)構(gòu),按照層級(jí)關(guān)系把板子包含的組件一一描述清楚,每塊板子都會(huì)定義一個(gè)dts文件,比如nrf52840dk_nrf52840開(kāi)發(fā)板,它對(duì)應(yīng)的dts文件是nrf52840dk_nrf52840.dts,其內(nèi)容如下所示:
可以看到板子dts文件包含了一個(gè)nrf52840_qiaa.dtsi,nrf52840_qiaa.dtsi對(duì)應(yīng)的就是nRF52840這顆芯片本身的dts文件。nrf52840 dtsi里面定義的內(nèi)容,nRF52840dk開(kāi)發(fā)板直接包含進(jìn)來(lái),然后在此基礎(chǔ)上進(jìn)行定制。 比如dtsi里面將UART0配置為關(guān)閉,nRF52840dk可以將其改配為使能;另一種需要修改的情況,nRF52840dk增加了一些其他組件 比如LED/Button/外部Flash等,這些設(shè)備都可以成為nrf52840dk_nrf52840.dts里面的一個(gè)節(jié)點(diǎn)。
nrf52840dk_nrf52840.dts是一種比較簡(jiǎn)單的板子,因此一個(gè)dts文件就可以將其表達(dá)清楚。我們還會(huì)碰到一種情況,幾塊板子大部分特性都是相同的,只有少數(shù)組件不一樣,這個(gè)時(shí)候,我們會(huì)把相同的地方拎出來(lái)組成一個(gè)common.dts,然后這幾塊板子再引用這個(gè)common.dts文件,比如目錄: zephyroardsarm rf9160dk_nrf9160,里面包含兩塊開(kāi)發(fā)板:
nrf9160dk_nrf9160ns
nrf9160dk_nrf9160
兩塊開(kāi)發(fā)板內(nèi)容基本上是一樣的,所以在這里把相同的內(nèi)容拎出來(lái)組成了一個(gè):
nrf9160dk_nrf9160_common.dts
然后nrf9160dk_nrf9160ns.dts和nrf9160dk_nrf9160.dts
再引用nrf9160dk_nrf9160_common.dts
這樣拆分一下,邏輯關(guān)系更清晰,將使系統(tǒng)變得更靈活,擴(kuò)展性更好。
除了
通過(guò)
其內(nèi)容大概如下所示:
可以看出zephyr.dts就是
在NCS或者Zephyr中,如果是一個(gè)單image應(yīng)用,程序的起始地址和大小是在DeviceTree中配置的,如下:
對(duì)于單image應(yīng)用,最有用的就是上面三個(gè)紅框標(biāo)出來(lái)的地方,其他配置選項(xiàng)你可以忽略不管,一般來(lái)說(shuō)能改的就一項(xiàng): storage_partition的起始地址和大小, storage_partition就是分配給用戶(hù)用來(lái)存儲(chǔ)數(shù)據(jù)的區(qū)域。 一般來(lái)說(shuō),無(wú)線(xiàn)IoT應(yīng)用都是要求具有固件升級(jí)功能,為了升級(jí)固件,BootLoader就必不可少,此時(shí)一個(gè)應(yīng)用至少有兩個(gè)image:BootLoader對(duì)應(yīng)的image,以及app對(duì)應(yīng)的image,對(duì)于這種多image應(yīng)用,程序起始地址和大小配置一般不通過(guò)DeviceTree直接來(lái)修改,而是交由partition manager(PM)模塊來(lái)管理,具體請(qǐng)參考第7章:開(kāi)發(fā)你的第一個(gè)multi-image(多image)應(yīng)用。
°4.2圖形化查看Kconfig選項(xiàng) 上面說(shuō)了,大家可以通過(guò).config文件去查看最終的Kconfig配置,然后通過(guò)zephyr.dts文件去查看最終的DeviceTree配置。 zephyr.dts文件不是很大,因此推薦使用這種方法去查看。但是.config文件有點(diǎn)長(zhǎng),直接查看它有點(diǎn)累,而且容易搞錯(cuò),為此NCS推出了兩個(gè)圖形化查看工具:SES配置和基于命令行方式的menuconfig或者guiconfig °4.2.1SES查看項(xiàng) 進(jìn)入Project->Configure nRF Connect SDK Project,如下所示:
由于一個(gè)項(xiàng)目的配置項(xiàng)太多,我們一般在右上角搜索配置項(xiàng)名字,找到它,然后查看它的說(shuō)明。同時(shí)我們可以去嘗試修改它,修改成功后,點(diǎn)擊“Configure”,配置才能生效。 通過(guò)圖形化界面進(jìn)行修改,我們可以很快找到合適的配置選項(xiàng),當(dāng)大家對(duì)系統(tǒng)還不是很熟的時(shí)候,推薦使用這種方式去試錯(cuò)。這里強(qiáng)調(diào)一下,通過(guò)這種方式所做的修改是臨時(shí)的,一旦項(xiàng)目重啟或者緩存刷新了,這里的更改就會(huì)失效,所以我們一般推薦使用上面的prj.conf去永久修改配置項(xiàng)。
對(duì)于multi-image(多image)應(yīng)用,點(diǎn)擊Project->Configure nRF Connect SDK Project,會(huì)同時(shí)出現(xiàn)所有image的配置菜單,其中“menuconfig”對(duì)應(yīng)的是主應(yīng)用的配置項(xiàng)(其他menuconfig對(duì)應(yīng)的是子image的配置項(xiàng),具體請(qǐng)參考第7章:開(kāi)發(fā)你的第一個(gè)multi-image(多image)應(yīng)用),如下:
°4.2.2命令行方式查看項(xiàng) 命令行方式使用如下命令查看項(xiàng)目配置: west build -tmenuconfig 執(zhí)行上述命令后,將顯示如下界面:
注:上述命令需要先安裝windows-curses ,即在cmd中執(zhí)行如下命令:pip install windows-curses –user,此命令的執(zhí)行需要聯(lián)網(wǎng)。如果你的電腦無(wú)法聯(lián)網(wǎng),建議使用guiconfig查看工程配置,其對(duì)應(yīng)的命令為: west build -tguiconfig 執(zhí)行上述命令后顯示的界面如下所示:
由于一個(gè)項(xiàng)目的配置項(xiàng)太多,我們一般使用Jump to進(jìn)行搜索,找到它,然后查看它的說(shuō)明。同時(shí)我們可以去嘗試修改它,修改成功后,選擇“Save”,配置才能生效。 通過(guò)圖形化界面進(jìn)行修改,我們可以很快找到合適的配置選項(xiàng),當(dāng)大家對(duì)系統(tǒng)還不是很熟的時(shí)候,推薦使用這種方式去試錯(cuò)。這里強(qiáng)調(diào)一下,通過(guò)這種方式所做的修改是臨時(shí)的,一旦項(xiàng)目重啟或者緩存刷新了,這里的更改就會(huì)失效,所以我們一般推薦使用上面的prj.conf去永久修改配置項(xiàng)。 5、NCS SDK中幾個(gè)比較重要的目錄
如前所述,NCS SDK中包括了多個(gè)代碼庫(kù),每個(gè)代碼庫(kù)都是相互獨(dú)立的,而且每個(gè)代碼庫(kù)包含的代碼都很多,如果一行一行代碼讀下去,那將是一個(gè)無(wú)底洞。所以實(shí)際開(kāi)發(fā)中,我們都是參考例子,按照例子去做,碰到不懂的API,再去看API說(shuō)明,循環(huán)往復(fù),最終完成自己的開(kāi)發(fā)。 °5.1例子目錄 我們先說(shuō)說(shuō)例子所在的目錄。NCS中商業(yè)級(jí)的應(yīng)用程序是放在如下目錄: nrfapplications
如果你的應(yīng)用跟上面的應(yīng)用相似,那么推薦使用上面的例子,因?yàn)樗麄兓旧蠈儆趖urn-key級(jí)的方案,跟成熟的商業(yè)應(yīng)用差不多,你需要的開(kāi)發(fā)工作量最少。 其次是如下例子目錄nrfsamples,這個(gè)都是Nordic自己開(kāi)發(fā)的一些例程:
然后就是Zephyr自帶的例子zephyrsamples:
大家有時(shí)候會(huì)覺(jué)得NCS或者Zephyr例子還是不夠多,比如很多驅(qū)動(dòng)API怎么用,好像沒(méi)有例子。其實(shí)Zephyr所有API的的使用,都可以在zephyr ests下面找到示例,所以當(dāng)你找不到例子的時(shí)候,不妨在這里找一找:
°5.2API目錄 NCS里面這么多API,到底該使用哪些API?API說(shuō)明又在哪里? 一般而言,我們只使用代碼庫(kù)里面的include目錄下的API,API說(shuō)明也在那里。 比如nrf代碼庫(kù)的include目錄: nrfinclude
Zephyr標(biāo)準(zhǔn)API的include目錄zephyrinclude:
其他代碼庫(kù)也是遵守這個(gè)規(guī)范的,比如Nordic開(kāi)發(fā)的底層驅(qū)動(dòng)API(與RTOS無(wú)關(guān)): moduleshal ordic rfxdriversinclude
*注:有些人會(huì)問(wèn):
moduleshal ordic rfxdriversinclude
zephyrincludedrivers
兩個(gè)目錄里面的驅(qū)動(dòng)API,我到底該使用哪個(gè)呢?
zephyrincludedrivers這個(gè)是Zephyr標(biāo)準(zhǔn)的驅(qū)動(dòng)API,按照Z(yǔ)ephyr標(biāo)準(zhǔn)來(lái)定義的,它調(diào)用了底層API:
moduleshal ordic rfxdriversinclude
moduleshal ordic rfxdriversinclude這里面的API都是Nordic自己實(shí)現(xiàn)的,跟平臺(tái)無(wú)關(guān)。
所以說(shuō),一般推薦使用zephyrincludedrivers這里面的API,只有這里面沒(méi)有或者實(shí)現(xiàn)不了的功能(比如將同一個(gè)引腳動(dòng)態(tài)分配給UART和SPI,Zephyr標(biāo)準(zhǔn)API就無(wú)能為力),這個(gè)時(shí)候才使用moduleshal ordic rfxdriversinclude這里面的API。 °5.3 板子定義目錄 通過(guò)在cmd輸入: west boards 就可以查看目前Zephyr支持哪些標(biāo)準(zhǔn)板子:
上面這些板子都是在如下目錄定義的:
zephyroardsarm。 由于Cortex-M33內(nèi)核支持secure和non-secure(ns)兩種應(yīng)用,所以每一個(gè)Cortex-M33內(nèi)核都包含兩種硬件定義:安全和非安全。 比如nrf9160dk,雖然物理上只有一塊板子,邏輯上我們把它劃分成兩塊板子:
nrf9160dk_nrf9160是跑安全應(yīng)用
而nrf9160dk_nrf9160ns是跑非安全應(yīng)用
同樣nRF5340dk,雖然物理上只有一塊板子,但是它有兩個(gè)核都可以供用戶(hù)使用,其中app核既可以跑安全應(yīng)用又可以跑非安全應(yīng)用,而網(wǎng)絡(luò)核只能跑一種應(yīng)用類(lèi)型,所以nrf5340dk在邏輯上就劃分成三塊板子:
nrf5340dk_nrf5340_cpuapp(app核,跑安全應(yīng)用)
nrf5340dk_nrf5340_cpuappns(app核,跑非安全應(yīng)用)
以及nrf5340dk_nrf5340_cpunet(network核,跑非安全應(yīng)用)
除了這些標(biāo)準(zhǔn)Zephyr板子,NCS還有一些自定義板子,他們?cè)谌缦履夸洠? nrfoardsarm
如果你要自定義自己的板子,可以參考上面例子來(lái)。 6、開(kāi)發(fā)你的第一個(gè)NCS 程序
現(xiàn)在我們開(kāi)始我們第一個(gè)NCS程序或者Zephyr程序的開(kāi)發(fā),在NCS中,有如下兩個(gè)現(xiàn)成的例子:
zephyrsampleshello_world:hello_world例子就是在串口中打印一串字符串
zephyrsamplesasiclinky:而blinky例子就是讓開(kāi)發(fā)板的LED1一閃一閃
這兩個(gè)程序直接就可以編譯和運(yùn)行,而且應(yīng)該所有的Zephyr開(kāi)發(fā)板都可以跑這兩個(gè)程序。現(xiàn)在我們把這兩個(gè)程序合成一個(gè)程序,即既打印字符串給串口助手,又讓開(kāi)發(fā)板LED1一閃一閃,同時(shí)我們把字符串打印變成循環(huán)打印,并將字符串同時(shí)輸出到串口助手和RTT viewer。 下面我們一步一步給大家演示這個(gè)開(kāi)發(fā)過(guò)程。
開(kāi)發(fā)NCS程序
本章所有代碼可以到如下百度網(wǎng)盤(pán)鏈接獲取,進(jìn)入“開(kāi)發(fā)你的第一個(gè)NCS(Zephyr)應(yīng)用程序”->“hello_world”,下載hello_world_ncsv140.rar:
下載鏈接:
https://pan.baidu.com/s/1FKTfY3Q_zBVvviO7KC7Gyg#list/path=%2Fblog
提取碼:y8fbz
°6.1 修改hello_world main.c文件 首先,我們以hello_world例子為基礎(chǔ),將這個(gè)例子拷到一個(gè)其他目錄下(任何目錄都可(不要有中文和空格等),只要你的環(huán)境變量都設(shè)好了,所有NCS例子的目錄可以隨意更改,這個(gè)真是非常方便!),這里讓大家拷貝到其他目錄,只是為了演示NCS編譯路徑的依賴(lài)性做得非常好,沒(méi)有別的意思。 如果你不想拷貝,也沒(méi)關(guān)系,咱們可以直接在原始目錄上進(jìn)行修改,NCS自帶git管理系統(tǒng),非常方便你進(jìn)行版本管理。我們做如下修改,以循環(huán)打印同一條日志:
°6.2 在項(xiàng)目中添加一個(gè)新文件blinky.c 然后把blinky代碼加到hello_world,這里面就會(huì)用到添加一個(gè)新文件的技能。我們先把zephyrsamplesasiclinkysrc里面的main.c改名為blinky.c,然后拷貝到hello_worldsrc目錄下。 如何把blinky.c添加到項(xiàng)目中來(lái)呢? 推薦的方法是修改CMakelists.txt文件,通過(guò)它加入新的編譯文件或者庫(kù),或者包含新的目錄。我們做如下修改,就可以把blinky.c加進(jìn)來(lái)了:
這種方式不管是NCS項(xiàng)目還是Zephyr項(xiàng)目,都能工作成功,而且是我們首推的方式。 至于CMakeLists的語(yǔ)法怎么理解和使用? 還是那句話(huà): 參考例子,不要專(zhuān)門(mén)去學(xué)習(xí)。除了修改CMakeLists方法外,NCS還引入了一種圖形化方法,使用SES來(lái)添加文件,如下所示:
這種方式只有nrfsamples這個(gè)目錄下的例子才支持,zephyrsamples這個(gè)目錄下的例子默認(rèn)不支持這種方式。 其實(shí)通過(guò)SES添加文件,本質(zhì)上跟修改CMakeLists方法一樣,它只不過(guò)在CMakeLists文件里面預(yù)先放入如下兩行標(biāo)識(shí),這樣SES就可以把新添加的文件塞到這兩行標(biāo)識(shí)之間:
我們把這兩行標(biāo)識(shí)放在我們的hello_world例子里面,這樣我們也可以通過(guò)SES添加文件了。blinky.c文件添加成功后,相應(yīng)的CMakelists文件也更新了,如下所示:
°6.3 修改blinky.c文件 好了,現(xiàn)在blinky.c文件已經(jīng)添加成功了,我們?cè)賹?duì)其進(jìn)行修改,修改代碼如下所示:
如上,我們直接把blinky代碼變成另外一個(gè)線(xiàn)程以達(dá)到我們的目的(當(dāng)然你也可以把blinky代碼變成一個(gè)模塊,以供hello_world的main調(diào)用,這里就不演示這種方式了)。 °6.4編譯和運(yùn)行你的第一個(gè)hello_world程序 上述修改結(jié)束后,我們可以使用任何Zephyr標(biāo)準(zhǔn)板運(yùn)行這個(gè)例子,以nrf52840dk為例,SES工程裝載如下所示,然后編譯和下載。
或者使用west命令進(jìn)行編譯和下載,命令如下所示: west build -b nrf52840dk_nrf52840 -dbuild_nrf52840dk_nrf52840 -p west flash --build-dirbuild_nrf52840dk_nrf52840 不管是SES下載完程序還是west下載完程序,可以看到程序正常執(zhí)行,串口助手在循環(huán)打印“Hello World! nrf52840dk_nrf52840”,然后開(kāi)發(fā)板上LED1在一閃一閃。串口截圖如下:
我們第一個(gè)hello_world程序算是 正式大功告成了。 °6.5 使用prj.conf和
一是修改sdk_config.h文件
二是添加相應(yīng)文件
但是在NCS SDK里面,你只需在prj.conf里面做如下修改即可達(dá)到同樣的目的:
運(yùn)行后結(jié)果如下所示:
按道理說(shuō),上面的例子已經(jīng)把日志輸出改為RTT Viewer了,這時(shí)去測(cè)量nrf52840dk電流,應(yīng)該很低才對(duì),但實(shí)際上此時(shí)電流大概為500多微安。 這是什么原因呢? 我們看一下zephyr.dts文件,如下:
可以看出,uart0和uart1都處于使能狀態(tài),從而導(dǎo)致功耗偏高。我們通過(guò)nrf52840dk_nrf52840.overlay文件,將uart0和uart1關(guān)閉,修改如下所示:
同時(shí)在prj.conf把serial模塊關(guān)掉(注:serial模塊在所有項(xiàng)目默認(rèn)是打開(kāi)的),如下: CONFIG_SERIAL=n 實(shí)際上,serial模塊只使用了uart0模塊,所以只需把uart0關(guān)掉即可,如下:
重新編譯和下載,這時(shí)我們?cè)偃y(cè)量nrf52840dk電流,此時(shí)電流只有幾微安,符合預(yù)期。 7、開(kāi)發(fā)multi-image應(yīng)用
°第一個(gè)multi-image(多image)應(yīng)用
有時(shí)一個(gè)應(yīng)用會(huì)包含多個(gè)image,最典型的情況有兩種:
一是BootLoader+app,BootLoader一個(gè)image,app一個(gè)image
二是spm+app,spm一個(gè)image,app一個(gè)image
*注:spm是Nordic為Cortex-M33非安全應(yīng)用設(shè)計(jì)的一個(gè)引導(dǎo)程序,像nRF9160/nRF5340這種M33內(nèi)核,所有非安全應(yīng)用都會(huì)默認(rèn)使能spm。 在NCS SDK中,編譯一個(gè)項(xiàng)目,會(huì)同時(shí)生成多個(gè)不同image,這種應(yīng)用就稱(chēng)為multi-image應(yīng)用。單image應(yīng)用其生成的hex名為:zephy.hex,multi-image應(yīng)用其生成的hex名為:merged.hex merged.hex意味著這個(gè)項(xiàng)目會(huì)生成多個(gè)image,然后將他們合并(merge)成一個(gè)hex: merged.hex 因此multi-image應(yīng)用對(duì)用戶(hù)來(lái)說(shuō),最終也只有一個(gè)image,用戶(hù)只需下載這個(gè)image即可。 nrfsamples rf9160http_application_update為例,這是一個(gè)典型的多image應(yīng)用,它包含3個(gè)image:
BootLoader image
spm image
以及app image
這三個(gè)image都是在nrfsamples rf9160http_application_update編譯目錄下生成的,編譯成功后,我們將同時(shí)看到三個(gè)image的編譯目錄,如下所示:
°7.1 分區(qū)管理(Partition Manager) 傳統(tǒng)的SDK,如果一個(gè)產(chǎn)品包含多個(gè)image,那么每個(gè)image都會(huì)對(duì)應(yīng)一個(gè)項(xiàng)目,用戶(hù)需要同時(shí)維護(hù)多個(gè)項(xiàng)目,而且需要同時(shí)維護(hù)這幾個(gè)項(xiàng)目的版本關(guān)聯(lián)關(guān)系。 NCS中引入了partition manager(PM)模塊(注:PM和前面的SPM是兩個(gè)完全不同的模塊,二者之間沒(méi)有任何聯(lián)系),由PM完成對(duì)多個(gè)image的管理,以及存儲(chǔ)劃分。 在PM中,主應(yīng)用稱(chēng)為parent應(yīng)用,其他應(yīng)用稱(chēng)為child應(yīng)用,通過(guò)使能parent應(yīng)用的某些Kconfig,可以自動(dòng)裝載child應(yīng)用,然后自動(dòng)編譯child應(yīng)用,然后生成child應(yīng)用的hex,并將child應(yīng)用的hex和parent應(yīng)用的hex合并在一起生成前文所述的merged.hex,這一切都發(fā)生在parent應(yīng)用的build目錄中。
PM是如何工作的呢? PM首先假定有一個(gè)app image,也就是我們的parent應(yīng)用,這個(gè)應(yīng)用對(duì)應(yīng)的hex就是前文所述的zephyr.hex。 那么app image放在Flash什么地方呢? 這個(gè)是由PM動(dòng)態(tài)決定的,PM將根據(jù)各個(gè)image的相對(duì)位置,來(lái)決定最終的image排列。 一般來(lái)說(shuō),parent應(yīng)用是默認(rèn)應(yīng)用,它不需要特別去指定自己的位置,而child應(yīng)用則需要告訴PM自己的位置在哪里,這個(gè)是通過(guò)child應(yīng)用目錄下面的pm.yml文件來(lái)實(shí)現(xiàn)的,pm.yml會(huì)告訴PM本child應(yīng)用會(huì)放在那里,pm.yml文件內(nèi)容大概如下所示:
pm.yml是按照相對(duì)位置來(lái)決定本child應(yīng)用的位置的,而且里面會(huì)用到Kconfig或者DeviceTree的宏定義,所以前面的
而且一般開(kāi)發(fā)過(guò)程中,大家也不需要關(guān)心child應(yīng)用目錄下的文件,大家只需關(guān)心parent應(yīng)用目錄下的相關(guān)PM文件即可。 那么parent應(yīng)用目錄下有哪些PM文件呢? 首先就是build根目錄下多image最終布局的partitions.yml文件,以nrfsamples rf9160http_application_update為例,其partitions.yml文件如下所示:
partitions.yml文件是由PM模塊自動(dòng)生成的,用戶(hù)不能直接修改。 然后就是pm.config 和pm_config.h文件,這兩個(gè)文件一一對(duì)應(yīng),pm.config和partitions.yml放在同一個(gè)目錄下,其內(nèi)容大概如下所示:
而pm_config.h是C語(yǔ)言代碼直接引用的文件,它在buildzephyrincludegenerated目錄下。 nrfsamples rf9160http_application_update為例,其pm_config.h文件如下所示:
一般來(lái)說(shuō),使用PM自動(dòng)生成的存儲(chǔ)layout就可以了,只有一個(gè)配置有可能需要改: settings_storage的大小。 這個(gè)可以通過(guò)Kconfig選項(xiàng)CONFIG_PM_PARTITION_SIZE_SETTINGS_STORAGE直接修改就可以了。 如果需要人為指定某個(gè)image的位置,也就是說(shuō)需要對(duì)自動(dòng)生成的partitions.yml進(jìn)行修改, 怎么辦呢?
其實(shí)很簡(jiǎn)單,把partitions.yml這個(gè)文件拷出來(lái),放在項(xiàng)目的根目錄下,然后將其重新命名為: pm_static.yml 然后大家就可以按照自己的需求將里面的值進(jìn)行修改。這里補(bǔ)充一下PM的另一個(gè)工作機(jī)理,當(dāng)PM檢測(cè)到parent應(yīng)用目錄下面有pm_static.yml文件,它就不會(huì)再自動(dòng)去分配存儲(chǔ)空間,而是直接使用這個(gè)靜態(tài)的存儲(chǔ)空間layout。 °7.2 多image的hello_world程序開(kāi)發(fā)
多image的hello_world程序開(kāi)發(fā)
本節(jié)所有代碼可以到如下百度網(wǎng)盤(pán)鏈接獲取,進(jìn)入“開(kāi)發(fā)你的第一個(gè)NCS(Zephyr)應(yīng)用程序”->“hello_world”,下載hello_world_ncsv140.rar:
下載鏈接: https://pan.baidu.com/s/1FKTfY3Q_zBVvviO7KC7Gyg#list/path=%2Fblog
提取碼:y8fb
我們現(xiàn)在將第6章的hello_world程序跑在多image環(huán)境下。 現(xiàn)在我們以nrf9160dk_nrf9160ns為例,重新編譯一下前述的hello_world程序,由于nrf9160dk_nrf9160ns為非安全應(yīng)用,前面也說(shuō)過(guò),所有Cortex-M33非安全應(yīng)用都會(huì)默認(rèn)使能spm模塊,所以spm image將會(huì)自動(dòng)加載進(jìn)來(lái)并進(jìn)行編譯。
裝載成功后,你可以看到build和download的target都變成: merged.hex,而不是以前的zephyr.hex,如下:
而且build目錄也會(huì)多一個(gè)spm的build目錄,如下所示:
程序跑起來(lái)后,log如下所示:
跟第6章一樣,我們?cè)俣x一個(gè)overlay文件,以將uart0關(guān)掉,此時(shí)我們?nèi)y(cè)9160dk的電流,應(yīng)該只有幾微安,但實(shí)際上我們測(cè)下來(lái)還是500多微安。 這是為什么呢? 因?yàn)閟pm還使能了serial和uart0,這個(gè)可以從spm的.config和zephyr.dts文件得到驗(yàn)證,如下:
所以u(píng)art0在spm中打開(kāi)了,然后程序跳到app,uart0還是處于打開(kāi)狀態(tài),從而導(dǎo)致功耗偏高。 那么我們?cè)趺纯梢员憬莸年P(guān)閉spm里面的serial模塊和uart0?
方法一,大家跑到spm例子里面,然后定義前述的prj.conf和
方法二,我們?cè)趐arent應(yīng)用中定義spm的prj.conf和
為了將parent應(yīng)用中的conf和overlay文件傳給spm,需要用到NCS編譯系統(tǒng)的編譯變量,給相應(yīng)的變量賦值,從而可以將相關(guān)文件傳遞給spm,具體請(qǐng)參考第8章。 我們對(duì)CMakelists文件做如下修改:
通過(guò)設(shè)置spm_CONF_FILE和spm_DTC_OVERLAY_FILE兩個(gè)變量,我們將spm.conf和spm.overlay兩個(gè)文件傳給了spm image編譯過(guò)程,從而達(dá)到控制spm image編譯配置目的。 spm.conf我們定義如下選項(xiàng):
spm.overlay我們定義如下節(jié)點(diǎn):
我們?cè)僦匦卵b載hello_world程序,可以看到在spm中,serial和uart0都關(guān)閉了,如下:
此時(shí)再去測(cè)量9160dk電流,就降到幾微安了。 上面日志要不打印到串口助手,要不打印到RTT viewer,而且都是堵塞式打印。 我們現(xiàn)在將打印改成異步的,而且同時(shí)打印到串口助手和RTT viewer。為此我們將logging模塊打開(kāi),同時(shí)設(shè)置如下Kconfig:
只需做上述修改,就可以達(dá)到我們前述的目的,非常方便(無(wú)需添加文件,無(wú)需修改include目錄,這就是NCS!)。這次大家可以使用nrf5340dk_nrf5340_cpuapp跑一下試試。 *注:上述日志配置直接從nrf_desktop拷貝過(guò)來(lái),大家以后也可以參考它來(lái)使能自己的log模塊。 8、NCS 編譯系統(tǒng)幾個(gè)要注意的點(diǎn)
°8.1 NCS幾個(gè)重要的編譯系統(tǒng)變量 在NCS或者Zephyr編譯系統(tǒng)中,有幾個(gè)變量非常重要,每個(gè)人最好掌握他們,把他們使用好,會(huì)讓你的編譯變得得心應(yīng)手,這幾個(gè)變量是:
ZEPHYR_BASE:用來(lái)指示你的Zephyr代碼庫(kù)的絕對(duì)目錄,比如取值:C:NordicNCSSDK agv1.4.0zephyr
BOARD:用來(lái)指定編譯用的板子,比如取值:nrf52840dk_nrf52840
CONF_FILE:用來(lái)指定項(xiàng)目的conf文件,如果沒(méi)有指定,默認(rèn)用prj.conf,詳細(xì)說(shuō)明見(jiàn)8.1節(jié)
DTC_OVERLAY_FILE:用來(lái)指定項(xiàng)目的overlay文件,如果沒(méi)有指定,默認(rèn)用
PM_STATIC_YML_FILE:用來(lái)指定parent應(yīng)用,即app的pm_static文件,如果沒(méi)有指定,默認(rèn)用pm_static.yml,詳細(xì)說(shuō)明見(jiàn)7.1節(jié)
CMAKE_BUILD_TYPE:命令行可以通過(guò)這個(gè)變量傳遞一個(gè)參數(shù)給CMakelists.txt文件或者其他build過(guò)程
°上述變量量不分大小寫(xiě)
所以CONF_FILE和conf_file是一樣的,其他類(lèi)同。因?yàn)檫@些變量是針對(duì)每一個(gè)image的,所以每一個(gè)image都有自己的board,conf_file,dtc_overlay_file等。
對(duì)于單image應(yīng)用,這個(gè)好理解也好區(qū)分。 那如果是多image應(yīng)用,該如何區(qū)分每個(gè)image的conf_file和dtc_overlay_file呢? 這可以通過(guò)使用image專(zhuān)用變量來(lái)實(shí)現(xiàn)。如前所述,conf_file這個(gè)變量本身是作用于app image的,實(shí)際上你可以把這個(gè)變量看成:app_conf_file,只不過(guò)默認(rèn)都是app image,所以就把a(bǔ)pp_省略了。
當(dāng)你需要在parent應(yīng)用中去設(shè)置child應(yīng)用的conf_file,你就不能直接使用conf_file這個(gè)變量了(因?yàn)樗怯脕?lái)設(shè)置parent應(yīng)用本身的conf文件),而需使用childImageName_conf_file。 比如上面的hello_world程序,我們使用了spm_conf_file這個(gè)變量,用來(lái)設(shè)置子image spm的conf_file。跟conf_file變量一樣,dtc_overlay_file變量使用了同樣的規(guī)則。NCS中目前主要有如下4個(gè)child image:
mcuboot。可升級(jí)的BootLoader
b0。不可升級(jí)的BootLoader
spm。Cortex-M33非安全應(yīng)用的引導(dǎo)程序,Nordic自己開(kāi)發(fā)的
tfm。trusted-firmware-m,作用跟spm相似,但是符合PSA標(biāo)準(zhǔn),由第三方開(kāi)發(fā)
除了上述child image,在編譯nRF5340 app核的時(shí)候,我們也可以自動(dòng)包含如下network核的child image:
b0n。nRF5340 network核的b0程序
hci_rpmsg。nRF5340 network核的藍(lán)牙controller
802154_rpmsg。nRF5340 network核的802.15.4 controller
通過(guò)上面的childImage名字加上前面的編譯系統(tǒng)變量,就可以通過(guò)parent應(yīng)用去控制child應(yīng)用的編譯過(guò)程,大大方便了多image的開(kāi)發(fā)流程。 關(guān)于上述編譯系統(tǒng)變量的使用,大家可以參考:
nrfapplications rf_desktop
nrf_desktop雖然只有一個(gè)CMakeLists.txt,但實(shí)際上這個(gè)CMakeLists.txt包含了20多個(gè)項(xiàng)目。 它是怎么做到的呢? 它就是通過(guò)board和cmake_build_type這兩個(gè)變量來(lái)實(shí)現(xiàn)的。比如要設(shè)置某一塊板子對(duì)應(yīng)的某一個(gè)項(xiàng)目的conf文件,它使用了如下語(yǔ)句:
比如說(shuō): $BOARD=nrf52840dk_nrf52840,$CMAKE_BUILD_TYPE=ZDebug_keyboard,那么它對(duì)應(yīng)的conf文件就是如下這個(gè):
asset_tracker的CMakeLists.txt文件定義了子image spm的conf文件,以及定義了一個(gè)靜態(tài)的pm文件,如下所示:
大家在寫(xiě)自己的multi image應(yīng)用的時(shí)候,可以多借鑒上面的例子,尤其是nrf_desktop,這是一個(gè)非常全面的例子,基本上你要的功能,它都可能有參考。 °8.2 conf文件命名規(guī)則及編譯順序 如前所述,可以通過(guò)多種方法指定用戶(hù)自定義Kconfig文件,除了上面講的prj.conf,符合如下命名標(biāo)準(zhǔn)的conf文件也可以被系統(tǒng)自動(dòng)加載進(jìn)來(lái)。
首先讀取CONF_FILE變量,我們可以將多個(gè)conf文件都賦給這個(gè)變量(每個(gè)conf文件之間以分號(hào)或者空格隔開(kāi)),這些配置文件最終會(huì)合并成一個(gè)。我們可以通過(guò)三種方式設(shè)置CONF_FILE變量
通過(guò)命令行方式傳遞:-DCONF_FILE=
在CMakeLists.txt中并且必須在調(diào)用find_package(Zephyr)之前(也就是包含boilerplate.cmake之前)
通過(guò)CMake變量cache
否則,系統(tǒng)將使用應(yīng)用目錄下的prj_
否則,系統(tǒng)將使用應(yīng)用目錄下的prj_
否則,系統(tǒng)將使用應(yīng)用目錄下的boards/
否則,系統(tǒng)將使用應(yīng)用目錄下的prj.conf
記住:如果同一個(gè)Kconfig選項(xiàng)或者符號(hào)被配置多次,以最后一次配置為準(zhǔn)。 °8.3 overlay文件命名規(guī)則及編譯順序 系統(tǒng)也可以有多個(gè)overlay文件,overlay文件裝載的順序是:
首先讀取DTC_OVERLAY_FILE變量,我們可以同時(shí)將多個(gè)overlay文件賦給這個(gè)變量(每個(gè)overlay文件之間以分號(hào)或者空格隔開(kāi)),這些overlay文件最終合并為一個(gè)文件。我們可以通過(guò)如下方式設(shè)置DTC_OVERLAY_FILE變量
通過(guò)命令行方式傳遞:-DDTC_OVERLAY_FILE="file1.overlay;file2.overlay"
在CMakeLists.txt中并且必須在調(diào)用find_package(Zephyr)之前(也就是包含boilerplate.cmake之前)
否則,系統(tǒng)將使用應(yīng)用目錄下的boards/
否則,系統(tǒng)將使用應(yīng)用目錄下的
責(zé)任編輯:xj
原文標(biāo)題:【Nordic博文分享系列】開(kāi)發(fā)你的第一個(gè)NCS(Zephyr)應(yīng)用程序
文章出處:【微信公眾號(hào):Nordic半導(dǎo)體】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
-
NCS
+關(guān)注
關(guān)注
1文章
8瀏覽量
9076 -
Nordic
+關(guān)注
關(guān)注
9文章
168瀏覽量
47322
原文標(biāo)題:【Nordic博文分享系列】開(kāi)發(fā)你的第一個(gè)NCS(Zephyr)應(yīng)用程序
文章出處:【微信號(hào):nordicsemi,微信公眾號(hào):Nordic半導(dǎo)體】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論