在51822中增加buttonless DFU功能是必不可少的過程。但是很多教程中都只是簡單介紹了如何在APP中增加DFU的service;如何利用BOOTLOADER加載新的app,其實這些都是現(xiàn)成的實例程序。但是對于一個產(chǎn)品來講,不能讓所有的代碼都可以輕松的對你的產(chǎn)品做升級,這樣的產(chǎn)品很容易被攻擊成一個無用的轉頭。所以我把這兩天看到的資料做個整理,記錄一下。
下面介紹之前,有些概念內(nèi)容需要先了解的,否則這些內(nèi)容是看不明白的;
- 環(huán)境介紹:
1.1 KEIL5
1.2 SDK10 SD8.0.0
1.3 nrf51822qfaa - 首先使用了現(xiàn)成bootloader例子程序;并且使用了HRM例子,含有DFU的service;
- 使用手機端nrftoolbox 作為控制端
- 首先需要了解DFU 的profile http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk51.v10.0.0%2Fbledfu_transport.html&cp=4_0_10_4_3_1_4 文章中詳細講解了control端和target端,如何觸發(fā)DFU功能,觸發(fā)后如何進入bootloader并開始交互數(shù)據(jù)的。
- 需要了解官方文檔介紹的safety-checking 的功能和含義 http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk51.v10.0.0%2Fbledfu_example_init.html
- 對上面的文章大致內(nèi)容做個基本介紹;
在升級NRF51IC的應用程序時,需要一個混合有初始包的鏡像文件(固件文件),在使用工具對設備升級時,將對初始包的內(nèi)容做判斷,檢測內(nèi)容是否有效,并確定是否開始做升級功能。
初始化包包含有以下內(nèi)容:
·Device type: 設備類型,有兩個字節(jié)數(shù)據(jù)組成,用于制定開發(fā)這的設備類型,可以自定義。
·Device revision: 設備修訂,有兩個字節(jié)數(shù)據(jù)組成,用于限制只能有修訂的設備用于升級服務。
·Supported SoftDevices: 支持的SD版本類型,有個固定的SD列表對應SD的版本。
SoftDevice FWID
S110 v7.0.0 0x004F
S110 v7.1.0 0x005A
S110 v8.0.0 0x0064
S120 v2.0.0 0x0060
S130 v1.0.0 0x0067
S310 v2.0.0 0x005D
Development/any 0xFFFE
·Checksum 兩個字節(jié)的CRC-16-CCITT校驗。
下圖是一個初始包包含的內(nèi)容:
DFU init packet.png
這篇文章后面介紹了上面對應的數(shù)組是在UICR的寄存器中存儲;但是沒有介紹如何將固定的數(shù)據(jù)寫入到UICR中。也沒有提到這個機制是如何工作的。例如到今后的批量生產(chǎn),如何快速將這些UICR初始化為需要的值等等。
在網(wǎng)上也找過一些資料,但是很少。基本沒有提到這類功能的說明,只看到一篇國內(nèi)轉載過來的文章吧(因為全是E文),however,我根據(jù)這篇文章得到一個新的思路,拋棄之前使用UICR寄存器的想法,直接用宏定義的方式定義固定值,并判斷這些值是否符合要求,從而確定是否啟動升級。
修改位置: 在自己bootloader的工程下找到 dfu_init_template.c, 目錄可以根據(jù)下面提示查找
The nRF51 SDK provides a template, dfu_init_template.c,
to perform safety checks of the init packet.
The template is located in the <BaseFolder>\bootloader_dfu folder.
If you are using Keil packs, the default <BaseFolder>
is C:\Keil\ARM\Pack\NordicSemiconductor\nRF_Libraries\<version>.
If you are using the repository distribution variant of the SDK,
<BaseFolder> is <InstallFolder>\components\libraries.
在 dfu_init_template.c中增加或者修改
#define APP_VERSION_PASSWORD ((uint32_t)0x03734301)
#define DEV_REVISION ((uint16_t)0x1234)
#define DEV_TYEP ((uint16_t)0x2345)
/*agatha: set application version check*/
if (p_init_packet->app_version!= APP_VERSION_PASSWORD)
{
return NRF_ERROR_INVALID_DATA;
}/*app_version check*/
if (DFU_DEVICE_INFO->device_rev!= DEV_REVISION)
{
return NRF_ERROR_INVALID_DATA;
}/*dev_revision check*/
if (DFU_DEVICE_INFO->device_type!= DEV_REVISION)
{
return NRF_ERROR_INVALID_DATA;
}/*dev_type check*/
重新對BOOTLOAD編譯,然后使用NRFGO工具對設備重新燒寫,SD,BOOTLOAD和APP;
然后使用nrfutil 工具在打包時將對應的密碼或者初始包信息寫入
cd C:\Program Files (x86)\Nordic Semiconductor\Master Control Panel\3.10.0.14\nrf\
nrfutil.exe dfu genpkg --nRF51422_xxac_s110.bin --application-version 0x03734301 --dev-revision 0xFFFF --dev-type 0x1618 --sd-req 100 app_version_password.zip
生成的ZIP文件可以解壓后觀察內(nèi)部初始包信息是否正確
DFU init packet 內(nèi)容.png
遺留問題:
- 根據(jù)官方文檔,我還沒有搞明白,如何將初始包信息寫到UICR寄存器中。如何使用方便簡潔的方法用于批量生產(chǎn);
- 和這片文章關系不大的問題。在Hrm例子中, dfu_start()函數(shù)中,對使用函數(shù)重啟芯片,并將啟動地址指向了bootloader的地址,但是我在整個工程文件中沒有找到bootloader的地址是多少?是如何賦值的?在哪里?
bootloader_util_app_start(NRF_UICR->BOOTLOADERADDR); - 引用文章內(nèi)容地址:https://blog.csdn.net/agathakuan/article/details/54572470