首先需要了解一下原理,很多大佬已经讲的很清楚,可以看下这个链接
Nordic官方提供的步骤
详解蓝牙空中升级(BLE OTA)原理与步骤
UART升级的步骤与BLE类似,可以查看这个链接
nrf52——DFU升级USB/UART升级方式详解(基于SDK开发例程)
不过如果程序中没有使用蓝牙相关的模块,其中的一些步骤可能存在问题。
以下是我遇到的问题:
1. 首先,因为没有使用蓝牙模块所以没有协议栈,也就不需要softdevice,这里需要使用mbr来代替,可以在SDK的components/softdevice/mbr/hex找到。
2. 在首次测试升级时,可以仅烧录mbr与BootLoader,不烧录App。
3. 在我首次测试时,我遇到了这几个问题:
- 3.1. 等待半天提示升级失败,log显示 No ping response after opening COM port. RTT log显示received ping XX
- 由于bootloader默认是开启流控的,如果你的设备不需要流控,修改这个宏#define NRF_DFU_SERIAL_UART_USES_HWFC 1
- 将默认1 改为0
- 3.2. RTT log 提示 app:Received an error: 0x0000004!
- 波特率与设置的不匹配,检查nrf_dfu_serial_uart.c中设置的波特率,将命令中波特率改为一样的,如果没有主动修改,那就是默认的115200.
- nrfutil dfu serial -fc 0 -pkg dfu_uart.zip -p COM3 -b 115200
4. 因为我的板子没有按键,而且没有使用协议栈,所以example中的进入DFU模式就无法套用,如果你跟我相同的情况,可以使用以下代码。
#define BOOTLOADER_DFU_GPREGRET (0xB0)
#define BOOTLOADER_DFU_START_BIT_MASK (0x01)
#define BOOTLOADER_DFU_START (BOOTLOADER_DFU_GPREGRET | BOOTLOADER_DFU_START_BIT_MASK)
{
uint32_t old_gpregret = nrf_power_gpregret_get();
uint32_t new_gpregret = old_gpregret & BOOTLOADER_DFU_START; //Just to retain other things written to gpregret. Not necessarily needed.
uint32_t temp = 0;
nrf_power_gpregret_set(new_gpregret);
while ((temp & BOOTLOADER_DFU_START) != BOOTLOADER_DFU_START)
{
// Wait until the gpregret is written, and refresh the value of temp.
temp = nrf_power_gpregret_get();
}
// When this is reached, the gpregret is successfully written.
nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU);
}
尽量打印一下temp的值,防止temp为0,一直在循环。
如果无法进入DFU:
可以直接将这里nrf_power_gpregret_set(new_gpregret);
修改为nrf_power_gpregret_set(BOOTLOADER_DFU_START);
附,贴一下我的升级命令,也可以按照上面链接中merge后升级。
nrfutil settings generate --family NRF52 --application app.hex --application-version 0 --bootloader-version 0 --bl-settings-version 2 settings.hex
nrfutil pkg generate --application app.hex --application-version 2 --sd-req 0x00 --hw-version 52 --key-file priv.pem dfu_image.zip
nrfjprog --eraseall -f NRF52
nrfjprog --program mbr_nrf52_2.4.1_mbr.hex --verify -f NRF52
nrfjprog --program bootloader.hex --verify -f NRF52
nrfjprog --program app.hex --verify -f NRF52
nrfjprog --program settings.hex --verify -f NRF52
nrfjprog --reset -f NRF52
nrfutil dfu serial -pkg dfu_image.zip -p COM3 -fc 0 -b 115200
nrfjprog --memrd 0x20000000 --n 0x10000 >> ram_dump.txt -f NRF52
:: 这里是dump RAM信息
暂时想到这些,后续遇到问题再补充。。。
更新
注意修改起始地址,由于我并未使用softdevice,所以ROM1起始地址仅为MBR占用地址,0x1000.
RAM1起始地址加0x8,同时size减去0x8.
更新
上述升级命令在不修改bootloader代码情况下,升级时会等待30S左右才进行升级,可使用以下命令缩减等待时间
nrfutil dfu serial -pkg XXX.zip -p COM3 -fc 0 -b 115200 -t 5 -cd 0 -prn 0
参数解释如下:
-pkg,–package PATH: DFU包的文件名[必须]。
-p,–port TEXT: 指定串口。
-fc,–flow-control BOOLEAN: 使能流控这个值为1。
-prn,–packet-receipt-notification INTEGER: Set the packet receipt notification value
-b,–baud-rate INTEGER: 设置串口波特率
-t, --timeout
-cd, -connect-delay
或者去修改nrf-util的python库,注释掉这里,然后重新编译(不建议,可能会引起其他问题)
def open(self):
super().open()
try:
# self.__ensure_bootloader()
PS:由于我需要在其他平台来升级Nordic,附上官方提供的DFU-master的源代码,可在非Linux/Windows平台移植使用,且以验证过。
Nordic DFU-master