如何实现蓝牙空中升级BLE OTA
如何實現BLE OTA?什么叫DFU?如何通過UART實現固件升級?又如何通過USB實現固件升級?怎么保證升級的安全性?什么叫雙備份(dual bank)DFU?什么叫單備份(single bank)DFU?什么叫后臺式(background)DFU?本文將對上述問題進行探討。
1.概述
所謂DFU(Device Firmware Update),就是設備固件升級的意思,而OTA是DFU的一種類型,準確說,OTA的全稱應該是OTA DFU,只不過大家為了方便起見,直接用OTA來指代固件空中升級(有時候大家也將OTA稱為FOTA)。DFU除了可以通過無線方式(OTA)進行升級,也可以通過有線方式進行升級,比如通過UART,USB或者SPI通信接口來升級設備固件。
不管采用OTA方式還是有線通信方式,DFU包括后臺式(background)和非后臺式兩種模式,目前的智能手機升級Android或者iOS系統都是采用background DFU方式,即新固件在后臺悄悄下載,下載成功后,再提示用戶升級,整個升級過程中對用戶手機使用沒有任何影響。而早先的功能機就是采用非后臺式 DFU來升級操作系統的,即用戶需要先長按某些按鍵進入bootloader模式,然后再進行升級,在升級過程中,手機的正常功能無法使用。Background DFU必須采用雙備份(dual bank)模式進行升級,即老系統(老固件)和新系統(新固件)各占一塊存儲區,只有當新系統下載完成并校驗成功后才會去升級老系統。而非后臺式DFU可以采用dual bank或者single bank模式,dual bank的做法是升級時系統先進入bootloader,然后把新系統(新固件)下載下來并校驗成功,然后再擦除老系統(老固件)并升級新系統,dual bank方式雖然犧牲了很多存儲空間,但是換來了更好的升級體驗。Single bank的做法是升級時系統也是先進入bootloader,然后立馬把老系統擦除,然后直接把新系統下載到老系統區域,跟dual bank相比,single bank將大大節省Flash存儲區域,在系統資源比較緊張的時候,推薦使用single bank方式。不管是single bank還是dual bank,升級過程出現問題后,都可以進行二次升級,都不會出現“變磚”情況。不過dual bank有一個好處,如果升級過程中出現問題或者新固件有問題,它還可以選擇之前的老系統繼續執行而不受其影響。而single bank碰到這種情況就只能一直待在bootloader中,然后等待二次或者多次升級,此時設備的正常功能就無法使用了,從用戶使用這個角度來說,你也可以認為此時設備已經“變磚”了。可參考下面三個圖來理解上述過程。
??
?
如果你是第一次接觸Nordic nRF5 SDK,那么建議你先看一下這篇文章:開發你的第一個BLE應用程序—Blinky,或者看一下這一篇文章:手把手教你開發BLE數據透傳應用程序,以建立Nordic nRF5 SDK的一些基本知識,然后再往下看以下章節。
2. Nordic nRF5 SDK DFU例程
Nordic 原生態SDK就提供了OTA(BLE)DFU,UART DFU,以及USB DFU例程,大家可以直接參考Nordic例程來實現自己的DFU。由于Nordic SDK版本很多,而且每個版本之間都或多或少有些差異,下面將分SDK版本來闡述Nordic每個版本SDK中如何實現OTA,至于UART DFU和USB DFU,這里就不再闡述了。感興趣的同學可以參考Nordic nRF5 SDK v15.0.0如下目錄:
UART serial DFU目錄(nRF52832):nRF5_SDK_15.0.0_a53641a\examples\dfu\secure_bootloader\pca10040_uart\arm5_no_packs
USB serial DFU目錄(nRF52840):
nRF5_SDK_15.0.0_a53641a\examples\dfu\secure_bootloader\pca10056_usb\arm5_no_packs
這里說明一下,目前Nordic只提供非后臺式DFU例子,SDK中還沒有后臺式DFU例子(不過這個實現起來并不難,只要大家搞明白了里面的原理,自己開發起來會很快的),所以下面的論述都是基于非后臺式DFU。另外,SDK9/10/11,Nordic只有明文DFU。從SDK12開始,Nordic 開始支持安全DFU(secure DFU)。所謂secure DFU,不是指升級時固件是加密的,而是指升級之前bootloader會先驗證新固件的簽名,只有驗簽通過后,才允許后續升級,此時的升級方式仍然是明文;驗簽失敗,則拒絕后續升級。Secure DFU將杜絕黑客的惡意攻擊,大大提高系統的安全性。
Nordic nRF5 SDK軟件架構跟其他家有點不一樣,程序存儲區最開始部分放得不是bootloader,而是藍牙協議棧softdevice,bootloader則被nRF5 SDK放在程序存儲區的最上面,整個存儲區結構圖如下所示:
?
根據升級時如何跳轉到Bootloader,nRF5 SDK又將DFU分為按鍵式DFU和非按鍵式(Buttonless)DFU,所謂按鍵式DFU,就是上電時長按某個按鍵以進入bootloader模式。而buttonless DFU,就是整個DFU過程中設備端無任何人工干預,通過BLE指令方式讓設備進入bootloader模式。
按鍵式DFU比較簡單,你只需將softdevice和bootloader image燒入到設備中(application可燒可不燒),按住button4然后上電,設備就會自動進入bootloader模式,然后就可以通過nRF Connect或者nRF Toolbox對設備進行OTA了。一旦buttonless DFU例子從app跳到了bootloader,后續DFU升級過程就跟按鍵式DFU一模一樣,所以如果你對按鍵式DFU操作過程中有什么不明白的地方,可以參考后面的buttonless DFU的說明,這里就不單獨對按鍵式DFU操作過程進行說明了。
下面將對buttonless DFU實現過程按照SDK版本一一進行闡述,請選擇你感興趣的SDK版本進行閱讀。下文的所有操作步驟所對應的腳本都放在百度云盤上,云盤鏈接如下所示:
- 鏈接:?https://pan.baidu.com/s/1FKTfY3Q_zBVvviO7KC7Gyg#list/path=%2Fblog???密碼: y8fb
建議大家先把對應的腳本下下來,然后對著操作步驟去實現自己的DFU過程。
2.1 nRF5 SDK v15.0.0 OTA
SDK15既支持明文DFU又支持安全DFU(實際上是簽名DFU),而且SDK15既可以實現OTA DFU,也可以實現基于UART或者USB通信的DFU。所謂簽名DFU,就是bootloader中預先裝載一個公鑰,升級時,主機先發一個簽名給bootloader,bootloader會對這個簽名進行驗簽,驗簽通過才能繼續DFU,否則拒絕DFU。SDK15 OTA DFU是基于例程ble_app_buttonless_dfu來實現的,而且SDK15只支持nRF52系列產品,它不支持nRF51系列產品,下面我們以nRF52832(開發板編號:PCA10040)為例,來闡述SDK15是如何實現OTA的。
nRF52832 OTA
請大家先到百度云盤下載壓縮包:“DFU/SDK15_0/ Script_SDK15_S132_nRF52832.rar”并解壓,然后對照以下步驟進行操作:
1)???? 準備。請先執行如下的“build_all.bat”腳本(Windows系統),以生成相應的micro-ecc庫(micro-ecc會用來對簽名進行驗簽等安全功能)。請注意,欲成功執行build_all.bat,大家必須先安裝好git和gcc編譯器。如果你嫌麻煩,可以到百度云盤下載: micro-ecc_sdk14_15_newer.rar,然后覆蓋相關文件,效果也是一樣的。
?
?
然后請按照http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.tools%2Fdita%2Ftools%2Fnrfutil%2Fnrfutil_installing.html&cp=5_5_1安裝最新版nrfutil,nrfutil安裝有兩種方式,一種是直接下載exe文件,一種是以Python的方式進行安裝。
nrfutil.exe直接下載鏈接為:(注:如果大家不熟悉Python,推薦使用這種方式)
https://github.com/NordicSemiconductor/pc-nrfutil/releases,記得把nrfutil.exe所在目錄放在Windows環境變量中。
或者你按照如下步驟去安裝nrfutil:
- 下載安裝Python2.7(2.7.6 or later, but not Python 3),下載地址:https://www.python.org/downloads/
注:安裝完Python2.7后,需要修改Windows path變量值,如果你安裝了老版本nrfutil,請先把老版本所在的目錄C:\Program Files (x86)\Nordic Semiconductor\nRFgo Studio從path變量中刪除,然后添加這2個目錄:C:\Python27;C:\Python27\Scripts;
- 通過pip安裝最新版的nrfutil,即打開Windows命令行工具CMD,輸入如下命令:pip install nrfutil,即可以完成nrfutil的安裝。
- 安裝完成后,在Windows命令行工具輸入:nrfutil version,其版本應該在3.2.0以上。
- 對于Windows用戶,nrfutil運行需要幾個特殊的DLL庫,而這幾個庫有些Windows機器是沒有的,如此,可往:https://www.microsoft.com/en-us/download/details.aspx?id=40784下載。
2)???? 通過nrfutil生成公私鑰對。大家可以直接雙擊“key_generate.bat”以生成相應的私鑰(priv.pem)和公鑰(dfu_public_key.c)。大家務必要保存好私鑰priv.pem,以后每個新image要升級時,都會先通過這個私鑰對它進行簽名,一旦priv.pem丟失或者被暴露,DFU將無法進行或者變得不安全。
3)???? 編譯bootloader代碼。將剛才的dfu_public_key.c取代目錄nRF5_SDK_15.0.0_a53641a\examples\dfu下的同名文件,然后編譯如下目錄中的工程:
nRF5_SDK_15.0.0_a53641a\examples\dfu\secure_bootloader\pca10040_ble\arm5_no_packs,將hex改為:bootloader.hex
4)???? 編譯application代碼。請編譯工程:nRF5_SDK_15.0.0_a53641a\examples\ble_peripheral\ble_app_buttonless_dfu\pca10040\s132\arm5_no_packs,將hex修改為:app.hex
5)???? 生成bootloader settings page。Bootloader settings存儲在Flash最后一個page,它將決定復位后芯片的行為,比如是進入DFU模式還是應用模式,同時它還包含image的CRC值和版本等信息。如果要求芯片復位后進入application,必須正確生成該bootloader settings hex,生成腳本見“settings_page_generate.bat”
6)???? 燒寫softdevice,app和bootloader。請雙擊“mass_program.bat”來完成整個燒寫過程
7)???? 生成新image對應的zip包。請雙擊“zip_generate.bat”,以生成SDK15_app_s132.zip,升級時,該zip包將會由云端下發到手機app中。
8)???? 將“SDK15_app_s132.zip”拷貝到手機上。安卓和蘋果手機都可以通過微信的‘文件傳輸助手’拷過去,非常方便。請注意,手機nRF Connect和nRF Toolbox都支持DFU功能,蘋果手機拷貝的時候可以隨便選擇其中一個app。
9)???? 使用nRF Connect或者nRF Toolbox來完成DFU過程。這里以nRF Connect為例來闡述整個升級過程
- DK廣播為Nordic_Buttonless,如下
?
- 連接該設備,使能CCCD,并選擇“DFU”
?
?
?
- 選擇升級用的zip包。有些安卓系統自帶的文件瀏覽器會有問題,建議使用ES explorer來選擇zip包,如下:
?
?
?
?
- 開始升級
?
??
- 升級成功,設備將自動啟動,此時你會看到新image已經在運行,廣播名字也變成Nordic_new,如下:
?
?
后面我會以SDK15.0.0 ble_app_uart為例,詳細闡述如何把ble_app_buttonless_dfu的DFU功能移植到ble_app_uart上,從而讓ble_app_uart也具有DFU功能,有興趣的的讀者請參考第3章。
nRF52840 OTA
nRF52840 OTA過程與nRF52832非常相似,唯一不同的是選擇pca10056目錄,請下載百度云盤腳本“DFU/SDK15_0/ Script_SDK15_S140_nRF52840.rar”,然后按照上述52832的步驟來實現52840的OTA DFU。
?
2.2 nRF5 SDK v14.2.0 OTA
SDK14目前只支持安全DFU(實際上是簽名DFU),所謂簽名DFU,就是bootloader中預先裝載一個公鑰,升級時,主機先發一個簽名給bootloader,bootloader會對這個簽名進行驗簽,驗簽通過后才能繼續DFU,否則拒絕DFU。SDK14既可以實現OTA DFU,也可以實現基于UART或者USB通信的DFU。SDK14 OTA DFU是基于例程ble_app_buttonless_dfu來實現的,而且SDK14只支持nRF52系列產品,它不支持nRF51系列產品,下面我們以nRF52832(開發板編號:PCA10040)為例,來闡述SDK14是如何實現OTA的。
nRF52832 OTA
請大家先到百度云盤下載壓縮包:“DFU/SDK14_2/ Script_SDK14_S132_nRF52832.rar”并解壓,然后對照以下步驟進行操作:
1)???? 準備。請先執行如下的“build_all.bat”腳本(Windows系統),以生成相應的micro-ecc庫(micro-ecc會用來對簽名進行驗簽等安全功能)。請注意,欲成功執行build_all.bat,大家必須先安裝好git和gcc編譯器。如果你嫌麻煩,可以到百度云盤下載: micro-ecc_sdk14_15_newer.rar,然后覆蓋相關文件,效果也是一樣的。
然后請按照http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.tools%2Fdita%2Ftools%2Fnrfutil%2Fnrfutil_installing.html&cp=5_5_1安裝最新版nrfutil,nrfutil安裝有兩種方式,一種是直接下載exe文件,一種是以Python的方式進行安裝。
nrfutil.exe直接下載鏈接為:(注:如果大家不熟悉Python,推薦使用這種方式)
https://github.com/NordicSemiconductor/pc-nrfutil/releases,記得把nrfutil.exe所在目錄放在Windows環境變量中。
或者你按照如下步驟去安裝nrfutil:
- 下載安裝Python2.7(2.7.6 or later, but not Python 3),下載地址:https://www.python.org/downloads/
注:安裝完Python2.7后,需要修改Windows path變量值,如果你安裝了老版本nrfutil,請先把老版本所在的目錄C:\Program Files (x86)\Nordic Semiconductor\nRFgo Studio從path變量中刪除,然后添加這2個目錄:C:\Python27;C:\Python27\Scripts;
- 通過pip安裝最新版的nrfutil,即打開Windows命令行工具CMD,輸入如下命令:pip install nrfutil,即可以完成nrfutil的安裝。
- 安裝完成后,在Windows命令行工具輸入:nrfutil version,其版本應該在3.2.0以上。
- 對于Windows用戶,nrfutil運行需要幾個特殊的DLL庫,而這幾個庫有些Windows機器是沒有的,如此,可往:https://www.microsoft.com/en-us/download/details.aspx?id=40784下載。
2)???? 通過nrfutil生成公私鑰對。大家可以直接雙擊“key_generate.bat”以生成相應的私鑰(priv.pem)和公鑰(dfu_public_key.c)。大家務必要保存好私鑰priv.pem,以后每個新image要升級時,都會先通過這個私鑰對它進行簽名,一旦priv.pem丟失或者被暴露,DFU將無法進行或者變得不安全。
3)???? 編譯bootloader代碼。將剛才的dfu_public_key.c取代目錄nRF5_SDK_14.2.0_17b948a\examples\dfu\dfu_req_handling下的同名文件,然后編譯如下目錄中的工程:
nRF5_SDK_14.2.0_17b948a\examples\dfu\bootloader_secure_ble\pca10040\arm5_no_packs,將hex改為:bootloader.hex
4)???? 編譯application代碼。請編譯工程:nRF5_SDK_14.2.0_17b948a\examples\ble_peripheral\ble_app_buttonless_dfu\pca10040\s132\arm5_no_packs,將hex修改為:app.hex
5)???? 生成bootloader settings page。Bootloader settings存儲在Flash最后一個page,它將決定復位后芯片的行為,比如是進入DFU模式還是應用模式,同時它還包含image的CRC值和版本等信息。如果要求芯片復位后進入application,必須正確生成該bootloader settings hex,生成腳本見“settings_page_generate.bat”
6)???? 燒寫softdevice,app和bootloader。請雙擊“mass_program.bat”來完成整個燒寫過程
7)???? 生成新image對應的zip包。請雙擊“zip_generate.bat”,以生成SDK14_app_s132.zip,升級時,該zip包將會由云端下發到手機app中。
8)???? 將“SDK14_app_s132.zip”拷貝到手機上。安卓和蘋果手機都可以通過微信的‘文件傳輸助手’拷過去,非常方便。請注意,手機nRF Connect和nRF Toolbox都支持DFU功能,蘋果手機拷貝的時候可以隨便選擇其中一個app。
9)???? 使用nRF Connect或者nRF Toolbox來完成DFU過程。這里以nRF Connect為例來闡述整個升級過程
- DK廣播為Nordic_Buttonless,如下
?
- 連接該設備,使能CCCD,并選擇“DFU”
?
?
?
- 選擇升級用的zip包。有些安卓系統自帶的文件瀏覽器會有問題,建議使用ES explorer來選擇zip包,如下:?
?
?
?
- 開始升級
?
?
?
- 升級成功,設備將自動啟動,此時你會看到新image已經在運行,廣播名字也變成Nordic_new,如下:
?
?
后面我們會以SDK15.0.0 ble_app_uart為例,詳細闡述如何把ble_app_buttonless_dfu的DFU功能移植到ble_app_uart上,從而讓ble_app_uart也具有DFU功能,有興趣的的讀者請參考第3章。注意:SDK14.2.0 DFU原理跟SDK15.0.0一模一樣,大家可以依葫蘆畫瓢,完成SDK14.2.0的DFU移植工作。
?
2.3 nRF5 SDK v12.3.0 OTA
SDK12目前只支持安全DFU(實際上是簽名DFU),所謂簽名DFU,就是bootloader中預先裝載一個公鑰,升級時,主機先發一個簽名給bootloader,bootloader會對這個簽名進行驗簽,驗簽通過后才能繼續DFU,否則拒絕DFU。SDK12只有OTA DFU例子,而沒有基于串口的DFU例程。SDK12 OTA DFU是基于例程ble_app_buttonless_dfu來實現的,而且SDK12同時支持nRF52832以及nRF51系列產品,下面我們以nRF52832(開發板編號:PCA10040)為例,來詳細闡述SDK12是如何實現OTA的。
nRF52832 OTA
請大家先到百度云盤下載壓縮包:“DFU/SDK12_3/ Script_SDK12_S132_nRF52832.rar”并解壓,然后對照以下步驟進行操作:
1)???? 準備。請先到百度云盤下載: micro-ecc_sdk12.rar,然后覆蓋如下目錄:
?
然后請按照http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.tools%2Fdita%2Ftools%2Fnrfutil%2Fnrfutil_installing.html&cp=5_5_1安裝最新版nrfutil,nrfutil安裝有兩種方式,一種是直接下載exe文件,一種是以Python的方式進行安裝。
nrfutil.exe直接下載鏈接為:(注:如果大家不熟悉Python,推薦使用這種方式)
https://github.com/NordicSemiconductor/pc-nrfutil/releases,記得把nrfutil.exe所在目錄放在Windows環境變量中。
或者你按照如下步驟去安裝nrfutil:
- 下載安裝Python2.7(2.7.6 or later, but not Python 3),下載地址:https://www.python.org/downloads/
注:安裝完Python2.7后,需要修改Windows path變量值,如果你安裝了老版本nrfutil,請先把老版本所在的目錄C:\Program Files (x86)\Nordic Semiconductor\nRFgo Studio從path變量中刪除,然后添加這2個目錄:C:\Python27;C:\Python27\Scripts;
- 通過pip安裝最新版的nrfutil,即打開Windows命令行工具CMD,輸入如下命令:pip install nrfutil,即可以完成nrfutil的安裝。
- 安裝完成后,在Windows命令行工具輸入:nrfutil version,其版本應該在3.2.0以上。
- 對于Windows用戶,nrfutil運行需要幾個特殊的DLL庫,而這幾個庫有些Windows機器是沒有的,如此,可往:https://www.microsoft.com/en-us/download/details.aspx?id=40784下載。
2)???? 通過nrfutil生成公私鑰對。大家可以直接雙擊“key_generate.bat”以生成相應的私鑰(priv.pem)和公鑰(dfu_public_key.c)。大家務必要保存好私鑰priv.pem,以后每個新image要升級時,都會先通過這個私鑰對它進行簽名,一旦priv.pem丟失或者被暴露,DFU將無法進行或者變得不安全。
3)???? 編譯bootloader代碼。將剛才的dfu_public_key.c取代目錄nRF5_SDK_12.3.0_d7731ad\examples\dfu\bootloader_secure下的同名文件,然后編譯如下目錄中的工程:
nRF5_SDK_12.3.0_d7731ad\examples\dfu\bootloader_secure\pca10040\arm5_no_packs,將hex改為:bootloader.hex
4)???? 編譯application代碼。請編譯工程:nRF5_SDK_12.3.0_d7731ad\examples\ble_peripheral\experimental_ble_app_buttonless_dfu\pca10040\s132\arm5_no_packs,將hex修改為:app.hex
5)???? 生成bootloader settings page。Bootloader settings存儲在Flash最后一個page,它將決定復位后芯片的行為,比如是進入DFU模式還是應用模式,同時它還包含image的CRC值和版本等信息。如果要求芯片復位后進入application,必須正確生成該bootloader settings hex,生成腳本見“settings_page_generate.bat”
6)???? 燒寫softdevice,app和bootloader。請雙擊“mass_program.bat”來完成整個燒寫過程。請注意,在燒寫前,請把app.hex倒數第3行和倒數第4行刪除,因為bootloader.hex也包含一模一樣的內容,會導致merge的時候hex定義沖突,如下:
?
或者編譯application的時候,把如下語句注掉:
?
7)???? 生成新image對應的zip包。請雙擊“zip_generate.bat”,以生成SDK12_app_s132.zip,升級時,該zip包將會由云端下發到手機app中。
8)???? 將“SDK12_app_s132.zip”拷貝到手機上。安卓和蘋果手機都可以通過微信的‘文件傳輸助手’拷過去,非常方便。請注意,手機nRF Connect和nRF Toolbox都支持DFU功能,蘋果手機拷貝的時候可以隨便選擇其中一個app。
9)???? 使用nRF Connect或者nRF Toolbox來完成DFU過程。這里以nRF Connect為例來闡述整個升級過程
- DK廣播為Nordic_Buttonless,如下
?
- 連接該設備,使能CCCD,并選擇“DFU”
?
?
?
- 選擇升級用的zip包。有些安卓系統自帶的文件瀏覽器會有問題,建議使用ES explorer來選擇zip包,如下:
?
?
?
- 開始升級
?
?
?
- 升級成功,設備將自動啟動,此時你會看到新image已經在運行,廣播名字也變成Nordic_new,如下:
?
?
nRF51系列 OTA
nRF51822 OTA過程與nRF52832非常相似,唯一不同的是選擇pca10028目錄,請下載百度云盤腳本“DFU/SDK12_3/ Script_SDK12_S130_nRF51.rar”,然后按照上述52832的步驟來實現51822的OTA DFU。
后面我們會以SDK15.0.0 ble_app_uart為例,詳細闡述如何把ble_app_buttonless_dfu的DFU功能移植到ble_app_uart上,從而讓ble_app_uart也具有DFU功能,有興趣的的讀者請參考第3章。注意:SDK12.3.0 DFU原理跟SDK15.0.0非常相似,大家可以依葫蘆畫瓢,完成SDK12.3.0的DFU移植工作。
?
2.4 nRF5 SDK v11.0.0 OTA
SDK11使用的是明文OTA DFU,其DFU是基于例程ble_app_hrs來實現的,并同時支持nRF52832和nRF51系列。下面以nRF52832為例來闡述DFU過程。
nRF52832 OTA
請大家先到百度云盤下載壓縮包:“DFU/SDK11_0/ Script_SDK11_S132_nRF52.rar”并解壓,然后對照以下步驟進行操作:
1)?????? 編譯bootloader代碼,請編譯目錄“nRF5_SDK_11.0.0_89a8197\examples\dfu\bootloader\pca10040\dual_bank_ble_s132\arm5_no_packs”中的工程,將hex改為bootloader.hex
2)?????? 編譯app,請編譯目錄“nRF5_SDK_11.0.0_89a8197\examples\ble_peripheral\ble_app_hrs\pca10040\s132_with_dfu\arm5_no_packs”中的工程,將hex改為app.hex
3)?????? 將softdevice,bootloader和app三者同時下載到設備中,另外我們還需要在Flash中寫一個app有效標志位,從而上電后程序直接跑到app執行,而不是停留在bootloader中不出來。我已經把相關燒寫腳本:mass_program.bat放在百度云盤中,大家直接雙擊就可以完成本步操作。
4)?????? 將新image打包成一個zip包。除了包含新image,該zip包還包含一些配置信息。升級時,zip包會通過云端下發到手機端app,手機端app再把zip包傳給藍牙設備以進行固件升級。請使用老版本nrfutil(版本號0.3.0)來生成該升級包(注:老版本nrfutil在目錄“C:\Program Files (x86)\Nordic Semiconductor\nRFgo Studio”中)。我已經把相關生成腳本zip_generate.bat放在百度云盤上,大家直接雙擊就可以完成本步操作,并生成SDK11_app_s132.zip。
5)?????? 把上述的‘SDK11_app_s132.zip’拷到手機中,安卓和蘋果手機都可以通過微信的‘文件傳輸助手’拷過去,非常方便。注:手機nRF Connect和nRF Toolbox都支持DFU功能,蘋果手機拷貝的時候可以隨便選擇其中一個app。
6)?????? 使用nRF Connect或者nRF Toolbox來完成DFU過程。這里以nRF Connect為例來闡述整個升級過程。
- DK廣播為Nordic_HRM
?
- 連接該設備,并使能CCCD,然后選擇“DFU”
?
?
- 選擇升級用的zip包。有些安卓系統自帶的文件瀏覽器會有問題,建議使用ES explorer來選擇zip包,如下:
?
?
?
?
- 開始升級
?
?
- 升級成功,設備將自動啟動,此時你會看到新image已經在運行,廣播名字也變成Nordic_HRM_new,如下:
?
?
?
nRF51系列OTA
nRF51822 OTA DFU實現過程跟上述的nRF52832基本上一模一樣,唯一不同的是選擇pca10028目錄,我已把相關腳本打包并放在百度云盤中,請直接下載“DFU/SDK11_0/ Script_SDK11_S130_nRF51.rar”,來實現nRF51系列 OTA。
如果你的應用是基于SDK11開發的,并且需要集成DFU功能,請參考上述例子ble_app_hrs來移植DFU功能,主要工作包括兩部分:一把BLE_DFU_APP_SUPPORT這個宏包括的所有代碼拷到你的工程中,二如果你的設備支持bonding的話,還需把Device manager相關代碼也拷到你的工程中,如此即可完成DFU功能的移植。
3. 給ble_app_uart加上OTA功能
為了讓ble_app_uart具有DFU功能,有2種做法,一是把NUS服務移植到ble_app_buttonless_dfu中,這種方法相對來說更簡單,但不利于理解DFU的移植原理;二是把DFU服務移植到ble_app_uart中,我們現以第2種做法來詳細闡述如何在SDK15.0.0中把DFU服務移植到ble_app_uart中。
3.1 正常連接OTA(無bonding)
1)???? 打開如下工程:nRF5_SDK_15.0.0_a53641a\examples\ble_peripheral\ble_app_uart\pca10040\s132\arm5_no_packs
2)???? 添加DFU服務。代碼如下:
#ifdef DFU_SUPPORTble_dfu_buttonless_init_t dfus_init = {0};// Initialize the async SVCI interface to bootloader. err_code = ble_dfu_buttonless_async_svci_init();APP_ERROR_CHECK(err_code); dfus_init.evt_handler = ble_dfu_evt_handler; err_code = ble_dfu_buttonless_init(&dfus_init);APP_ERROR_CHECK(err_code);#endif?
定義ble_dfu_evt_handler,大家只要按照要求來,就沒問題,這里就不貼代碼了。
Nordic對每一個模塊都有一個編譯總開關,因此還需到sdk_config.h中使能DFU模塊,如下:
#ifndef BLE_DFU_ENABLED#define BLE_DFU_ENABLED 1#endif// <q> NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS - Buttonless DFU supports bonds. #ifndef NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS#define NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS 0#endif?
3)???? 修改softdevice配置。現在整個應用包括2個vs_uuid:NUS和DFU,相應地ATT table size也要變大,然后應用程序RAM起始地址也需要跟著變,如下(注:這里的attr_tab_size設置得稍稍偏大):
// <o> NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE - Attribute Table size in bytes. The size must be a multiple of 4. #ifndef NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE#define NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE 1600#endif// <o> NRF_SDH_BLE_VS_UUID_COUNT - The number of vendor-specific UUIDs. #ifndef NRF_SDH_BLE_VS_UUID_COUNT#define NRF_SDH_BLE_VS_UUID_COUNT 2#endif?
修改應用程序RAM起始地址,如下:
?
4)???? 添加上述函數涉及到的文件,宏定義及包含相關目錄。首先添加如下DFU目錄及相關文件:
?
在define中添加這些宏:DEBUG DFU_SUPPORT BL_SETTINGS_ACCESS_ONLY NRF_DFU_SVCI_ENABLED NRF_DFU_TRANSPORT_BLE=1,其中DEBUG宏只是為了調試方便而設置的,跟DFU本身無關。DFU_SUPPORT是我用來控制我添加的DFU代碼的,刪掉DFU_SUPPORT,將不編譯所有DFU有關代碼。其余的宏都是系統自帶的,如果要支持DFU,也是必須要定義的。
?
然后包含如下目錄:
?
?
5)???? 在main.c中添加如下頭文件定義:
#ifdef DFU_SUPPORT#include "ble_dfu.h"#endif?
6)???? 在跳轉到bootloader之前,如果你想做一些專門的代碼處理,比如完成pending的Flash操作,比如關閉某些模塊,那么你可以注冊一個app_shutdown_handler來做這些工作。(注:這一步不是必須的,是可選的!)
NRF_PWR_MGMT_HANDLER_REGISTER(app_shutdown_handler, 0);?
7)???? 編譯工程,將hex改為“app.hex”
8)???? 按照2.1節“nRF5 SDK v15.0.0 OTA”步驟來執行OTA過程,你會發現ble_app_uart已經具備DFU功能了。我已把OTA過程所有步驟打成一個包:Script_SDK15_S132_NUS_NoBonding.rar,大家可以到百度云盤去下載。
3.2 bonding連接OTA
我們在3.1節基礎上,再加上bonding功能,以讓ble_app_uart同時支持DFU和bonding。
1)???? 打開3.1節的工程
2)???? 添加如下文件:
?
3)???? 在main函數中添加peer_manager_init,定義如下:
static void peer_manager_init(){ble_gap_sec_params_t sec_param;ret_code_t err_code;err_code = pm_init();APP_ERROR_CHECK(err_code);memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));// Security parameters to be used for all security procedures. sec_param.bond = SEC_PARAM_BOND;sec_param.mitm = SEC_PARAM_MITM;sec_param.lesc = SEC_PARAM_LESC;sec_param.keypress = SEC_PARAM_KEYPRESS;sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES;sec_param.oob = SEC_PARAM_OOB;sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE;sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE;sec_param.kdist_own.enc = 1;sec_param.kdist_own.id = 1;sec_param.kdist_peer.enc = 1;sec_param.kdist_peer.id = 1;err_code = pm_sec_params_set(&sec_param);APP_ERROR_CHECK(err_code);err_code = pm_register(pm_evt_handler);APP_ERROR_CHECK(err_code);}?
然后將上面新出現的符號定義一一拷貝過來,這里不再贅述
4)???? 修改advertising_start定義,增加刪除bonding信息功能(如果你不需要這個功能,也可以不改)
static void advertising_start(bool erase_bonds) {if (erase_bonds == true){delete_bonds();// Advertising is started by PM_EVT_PEERS_DELETE_SUCCEEDED event. }else{uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);APP_ERROR_CHECK(err_code);NRF_LOG_DEBUG("advertising is started");} }?
5)???? 修改allow_repairing = true,這一步也是可選的。allow_repairing = true的好處是,當手機端的bonding信息被用戶誤刪掉了,設備會允許這臺手機的第二次配對bonding請求。如果allow_repairing = false,在這種情況下,就會拒絕手機的第二次配對請求,以提高安全性。
6)???? 在main.c文件開頭,包含如下頭文件:
#include "peer_manager.h"?
7)???? 在ble_evt_handler中刪除BLE_GAP_EVT_SEC_PARAMS_REQUEST分支,因為這個分支在peer_manager模塊中已經進行處理了,這里再處理一次,會產生異常:
// case BLE_GAP_EVT_SEC_PARAMS_REQUEST:// // Pairing not supported// err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);// APP_ERROR_CHECK(err_code);// break;?
8)???? 將ble_nus.c文件從\components目錄中拷出來,放在自己工程目錄下,因為我們接下來需要對它進行修改,后續項目直接引用自己的ble_nus,而不要再引用components目錄下的原始文件了。將TX characteristic的CCCD寫屬性從open改為加密,這樣將自動觸發手機端的bonding請求,修改代碼如下:
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&cccd_md.write_perm);?
9)???? 修改sdk_config.h文件,需要修改多個地方,如下:
#define PEER_MANAGER_ENABLED 1#define FDS_ENABLED 1#define NRF_SDH_BLE_SERVICE_CHANGED 1#define NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS 0?
請注意NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS可以為0,也可以為1,兩種情況下,DFU成功后,bonding信息都可以保持。兩者的區別是,當NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS為0,進入DFU模式后,bootloader將用普通模式跟手機相連,這種方式兼容性好,可靠性高,但安全等級稍低;當NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS為1時,bootloader將共享application的bonding信息,也就是說,哪怕進入bootloader模式,設備還是跟手機處于bonding狀態,這種方式安全級別比較高,但容易產生兼容性問題,極端情況下,如果DFU過程中用戶把手機端的bonding信息刪除,系統將會變磚,而且無法恢復。推薦將NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS設為0,以獲得最好的兼容性和可靠性。
?
如果你在應用中把NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS設為1,那么還需要添加ble_dfu_bonded.c文件,如下:
?
?
而且,如果NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS設為1,那么bootloader代碼也就不能采用默認配置,請修改bootloader工程中的sdk_config.h如下宏定義,然后重新編譯生成新的bootloader hex。
#define NRF_DFU_BLE_REQUIRES_BONDS 1#define NRF_SDH_BLE_SERVICE_CHANGED 1?
10)? 在C/C++ define里面定義“BONDING_SUPPORT”宏。
11)? 編譯工程,將hex改為app.hex
12)? 按照2.1節“nRF5 SDK v15.0.0 OTA”步驟來執行OTA過程,不過如下幾點需要注意:
-
- 在nRF Connect中勾選“keep bond information”選項,如下:
?
?
-
- 當你使能CCCD的時候,手機將會自動與設備進行bonding,如下
?
?
-
- DFU升級成功后,設備將會與手機自動重連,此時需點擊“Refresh services”,以獲得設備最新服務列表,如下:
?
?
上述代碼工程我已打包成:OTA_ble_app_uart_SDK15_0_0.rar,另外三種DFU模式對應的腳本,我也打成了包,其中沒有bonding對應Script_SDK15_S132_NUS_NoBonding.rar,application單獨bonding對應Script_SDK15_S132_NUS_Bonding_SUPPORTS_BONDS_0.rar,application和bootloader同時bonding對應Script_SDK15_S132_NUS_Bonding_SUPPORTS_BONDS_1.rar,請大家到百度云盤目錄DFU\ble_app_uart中下載。代碼工程解壓縮到nRF5_SDK_15.0.0_a53641a\examples\ble_peripheral這個目錄下,就可以直接編譯和運行。
轉載于:https://www.cnblogs.com/iini/p/9314246.html
總結
以上是生活随笔為你收集整理的如何实现蓝牙空中升级BLE OTA的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 优化网站性能的35条规则
- 下一篇: 生了娃照样能打,两位母亲温网会师