概述
-
工具准备(windows 64位)
软件工具下载地址:https://download.csdn.net/download/mygod2008ok/11154112
step 1: 安装软件
- 安装coreutils-5.3.0.exe
- 安装gcc-arm-none-eabi-6-2017-q2-update-win32-sha2.exe
- 安装make-3.81.exe
- 安装Git-2.21.0-64-bit.exe
- 安装python-2.7.12.amd64.msi
step 2: 设置系统环境变量
在系统环境变量的path中加入以下路径后,再重启电脑使环境变量生效
C:Program Files (x86)GnuWin32;
C:Program Files (x86)GnuWin32bin;
C:Program Files (x86)GNU Tools ARM Embedded6 2017-q2-updatebin;
C:Python27Scripts;
C:Python27Lib;
C:Python27;
step 3: 安装nrfutil
1.首先要保证电脑连上网络,打开命令行,输入python -m pip install nrfutil后回车,等待联网下载安装,过一会提示pip版本不够,然后在命令行中输入python -m pip install --upgrade pip后回车,等待联网更新pip
2.再次输入python -m pip install nrfutil后回车,等待联网下载安装,此时会安装成功
-
bootloader工程(SDK15.2.0的dfu目录下secure_bootloader工程)
step 1: 打开工程并编译,会报以下错误
*** Using Compiler 'V5.06 update 5 (build 528)', folder: 'C:Keil_v5ARMARMCCBin'
Build target 'nrf52832_xxaa_s132'
compiling nrf_crypto_ecdsa.c...
..........componentslibrariescryptobackendmicro_eccmicro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..........componentslibrariescryptonrf_crypto_ecdsa.c: 0 warnings, 1 error
compiling micro_ecc_backend_ecdh.c...
..........componentslibrariescryptobackendmicro_eccmicro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..........componentslibrariescryptobackendmicro_eccmicro_ecc_backend_ecdh.c: 0 warnings, 1 error
compiling dfu_public_key.c...
......dfu_public_key.c(29): error: #35: #error directive: "Debug public key not valid for production. Please see https://github.com/NordicSemiconductor/pc-nrfutil/blob/master/README.md to generate it"
#error "Debug public key not valid for production. Please see https://github.com/NordicSemiconductor/pc-nrfutil/blob/master/README.md to generate it"
......dfu_public_key.c: 0 warnings, 1 error
compiling micro_ecc_backend_ecdsa.c...
..........componentslibrariescryptobackendmicro_eccmicro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..........componentslibrariescryptobackendmicro_eccmicro_ecc_backend_ecdsa.c: 0 warnings, 1 error
compiling micro_ecc_backend_ecc.c...
..........componentslibrariescryptobackendmicro_eccmicro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..........componentslibrariescryptobackendmicro_eccmicro_ecc_backend_ecc.c: 0 warnings, 1 error
compiling nrf_crypto_ecc.c...
..........componentslibrariescryptobackendmicro_eccmicro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..........componentslibrariescryptonrf_crypto_ecc.c: 0 warnings, 1 error
compiling nrf_dfu_ver_validation.c...
..........componentslibrariescryptobackendmicro_eccmicro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..........componentslibrariesbootloaderdfunrf_dfu_ver_validation.c: 0 warnings, 1 error
compiling nrf_dfu_req_handler.c...
..........componentslibrariescryptobackendmicro_eccmicro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..........componentslibrariesbootloaderdfunrf_dfu_req_handler.c: 0 warnings, 1 error
compiling nrf_dfu_validation.c...
..........componentslibrariescryptobackendmicro_eccmicro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..........componentslibrariesbootloaderdfunrf_dfu_validation.c: 0 warnings, 1 error
"._buildnrf52832_xxaa_s132.axf" - 9 Error(s), 0 Warning(s).
Target not created.
Build Time Elapsed: 00:00:03
step 2: 解决uECC.h缺失问题
1.首先保证电脑连上网络,然后在nRF5_SDK_15.2.0_9412b96externalmicro-ecc目录下,找到build_all.bat文件,双击
运行从github上复制micro-ecc文件包到nRF5_SDK_15.2.0_9412b96externalmicro-ecc目录下,并会在nRF5_SDK_15.2.0_9412b96externalmicro-eccnrf52nf_keilarmgcc目录下生成micro_ecc_lib_nrf52.lib文件
step 3: 解决Public key问题
1.再次编译工程,会提示缺少 public key.
2.在nRF5_SDK_15.2.0_9412b96examplesdfu的目录下打开命令行,输入nrfutil.exe keys generate private.pem回车,
会产生一个private.pem文件
3.再次在命令行中输入nrfutil.exe keys display --key pk --format code private.pem --out_file public_key.c回车,产生
一个public_key.c文件
4.打开public_key.c文件,将以下的内容复制
粘贴到dfu_public_key.c文件中(粘贴前先将#error这行删除掉)
5.再次编译工程将会通过
-
bootloader工程分析
1.main.c文件中的static void dfu_observer(nrf_dfu_evt_type_t evt_type)函数被传入nrf_bootloader_init函数的函数指针参数
/**
* @brief Function notifies certain events in DFU process.
*/
static void dfu_observer(nrf_dfu_evt_type_t evt_type)
{
switch (evt_type)
{
case NRF_DFU_EVT_DFU_FAILED: //dfu 失败
case NRF_DFU_EVT_DFU_ABORTED: //dfu 中断
case NRF_DFU_EVT_DFU_INITIALIZED: //dfu 初时化完成
bsp_board_init(BSP_INIT_LEDS);
bsp_board_led_on(BSP_BOARD_LED_0);
bsp_board_led_on(BSP_BOARD_LED_1);
bsp_board_led_off(BSP_BOARD_LED_2);
break;
case NRF_DFU_EVT_TRANSPORT_ACTIVATED: //dfu 传输激活
bsp_board_led_off(BSP_BOARD_LED_1);
bsp_board_led_on(BSP_BOARD_LED_2);
break;
case NRF_DFU_EVT_DFU_STARTED: //dfu 开始
break;
default:
break;
}
}
ret_val = nrf_bootloader_init(dfu_observer); // bootloader初时化函数,传入dfu_observer函数作参数
APP_ERROR_CHECK(ret_val);
2.在nrf_bootloader_init函数中,检测了各种进入dfu方式
ret_code_t nrf_bootloader_init(nrf_dfu_observer_t observer)
{
NRF_LOG_DEBUG("In nrf_bootloader_init");
ret_code_t ret_val;
nrf_bootloader_fw_activation_result_t activation_result;
uint32_t initial_timeout;
bool dfu_enter = false;
m_user_observer = observer;
if (NRF_BL_DFU_ENTER_METHOD_BUTTON) //检查按键进入dfu方法
{
dfu_enter_button_init(); //按键初时化
}
ret_val = nrf_dfu_settings_init(false); //检查设置区信息是否有正确
if (ret_val != NRF_SUCCESS)
{
return NRF_ERROR_INTERNAL;
}
// Check if an update needs to be activated and activate it.
activation_result = nrf_bootloader_fw_activate();
switch (activation_result)
{
case ACTIVATION_NONE: //未激活状态
initial_timeout = NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS);
dfu_enter = dfu_enter_check(); //dfu进入检查
break;
case ACTIVATION_SUCCESS_EXPECT_ADDITIONAL_UPDATE: //DFU 附加信息更新
initial_timeout = NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_CONTINUATION_TIMEOUT_MS);
dfu_enter = true; //DFU标志设为真
break;
case ACTIVATION_SUCCESS: //DFU成功
bootloader_reset(); //系统复位
NRF_LOG_ERROR("Should never come here: After bootloader_reset()");
return NRF_ERROR_INTERNAL; // Should not reach this.
case ACTIVATION_ERROR:
default:
return NRF_ERROR_INTERNAL;
}
if (dfu_enter)
{
nrf_bootloader_wdt_init(); //wdt初时化
scheduler_init(); //调度机制初时化
// Clear all DFU stop flags.
dfu_enter_flags_clear(); //清除标记
// Call user-defined init function if implemented
ret_val = nrf_dfu_init_user(); //用户实现功能初时化
if (ret_val != NRF_SUCCESS)
{
return NRF_ERROR_INTERNAL;
}
nrf_bootloader_dfu_inactivity_timer_restart(initial_timeout, inactivity_timeout);
ret_val = nrf_dfu_init(dfu_observer); //dfu初时化
if (ret_val != NRF_SUCCESS)
{
return NRF_ERROR_INTERNAL;
}
NRF_LOG_DEBUG("Enter main loop");
loop_forever(); // This function will never return.
NRF_LOG_ERROR("Should never come here: After looping forever.");
}
else
{
// Erase additional data like peer data or advertisement name
ret_val = nrf_dfu_settings_additional_erase(); //擦除设置附加信息
if (ret_val != NRF_SUCCESS)
{
return NRF_ERROR_INTERNAL;
}
m_flash_write_done = false;
nrf_dfu_settings_backup(flash_write_callback); //dfu设置flash写回调函数
ASSERT(m_flash_write_done);
nrf_bootloader_app_start(); //应用程序启动
NRF_LOG_ERROR("Should never come here: After nrf_bootloader_app_start()");
}
// Should not be reached.
return NRF_ERROR_INTERNAL;
}
宏NRF_BL_DFU_ENTER_METHOD_BUTTON决定是否使用按键方式进入dfu升级模式
#ifndef NRF_BL_DFU_ENTER_METHOD_BUTTON
#define NRF_BL_DFU_ENTER_METHOD_BUTTON 1
#endif
if (NRF_BL_DFU_ENTER_METHOD_BUTTON)
{
dfu_enter_button_init(); //按键初时化
}
/**@brief Function for initializing button used to enter DFU mode.
*/
static void dfu_enter_button_init(void)
{
nrf_gpio_cfg_sense_input(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN,
BUTTON_PULL,
NRF_GPIO_PIN_SENSE_LOW);
}
宏NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN定义了使用哪个gpio引脚
#ifndef NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN
#define NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN 16 //P0.16
#endif
如果不使用按键方式,将NRF_BL_DFU_ENTER_METHOD_BUTTON宏定义值由1改成0
#ifndef NRF_BL_DFU_ENTER_METHOD_BUTTON
#define NRF_BL_DFU_ENTER_METHOD_BUTTON 0
#endif
检查设置区信息是否正确有效(设置配置hex文件由nrfutil命令生成)
ret_val = nrf_dfu_settings_init(false); //检查设置区信息是否有正确
if (ret_val != NRF_SUCCESS)
{
return NRF_ERROR_INTERNAL;
}
/*代码片段*/
ret_code_t nrf_dfu_settings_init(bool sd_irq_initialized)
{
NRF_LOG_DEBUG("Calling nrf_dfu_settings_init()...");
ret_code_t err_code = nrf_dfu_flash_init(sd_irq_initialized);
if (err_code != NRF_SUCCESS)
{
NRF_LOG_ERROR("nrf_dfu_flash_init() failed with error: %x", err_code);
return NRF_ERROR_INTERNAL;
}
bool settings_valid = settings_crc_ok();
bool settings_backup_valid = settings_backup_crc_ok();
if (settings_valid &&
settings_backup_valid &&
!settings_forbidden_parts_equal_to_backup(m_dfu_settings_buffer))
{
NRF_LOG_WARNING("Restoring settings from backup since the app has tampered with the "
"off-limit parts of the settings page.");
memcpy(&s_dfu_settings,
mp_dfu_settings_backup_buffer,
sizeof(nrf_dfu_settings_t));
}
else if (!settings_valid)
{
if (settings_backup_valid)
{
NRF_LOG_INFO("Restoring settings from backup since the settings page contents are "
"invalid (CRC error).");
memcpy(&s_dfu_settings,
mp_dfu_settings_backup_buffer,
sizeof(nrf_dfu_settings_t));
}
else
{
NRF_LOG_WARNING("Resetting bootloader settings since neither the settings page nor the "
"backup are valid (CRC error).");
memset(&s_dfu_settings, 0x00, sizeof(nrf_dfu_settings_t));
s_dfu_settings.settings_version = NRF_DFU_SETTINGS_VERSION;
}
}
else
{
NRF_LOG_DEBUG("Settings OK");
memcpy(&s_dfu_settings, m_dfu_settings_buffer, sizeof(nrf_dfu_settings_t));
return NRF_SUCCESS;
}
err_code = nrf_dfu_settings_write(NULL);
if (err_code != NRF_SUCCESS)
{
NRF_LOG_ERROR("settings_write() failed with error: %x", err_code);
return NRF_ERROR_INTERNAL;
}
return NRF_SUCCESS;
}
dfu进入检查
dfu_enter = dfu_enter_check();
dfu_enter_check函数中有5种方式进入DFU模式
/*代码片段*/
/**@brief Function for checking whether to enter DFU mode or not.
*/
static bool dfu_enter_check(void)
{
if (!nrf_dfu_app_is_valid(crc_on_valid_app_required())) //app crc方式进入DFU
{
NRF_LOG_DEBUG("DFU mode because app is not valid.");
return true;
}
//=========================================================================
// #ifndef NRF_BL_DFU_ENTER_METHOD_BUTTON
// #define NRF_BL_DFU_ENTER_METHOD_BUTTON 1
// #endif
//==========================================================================
if (NRF_BL_DFU_ENTER_METHOD_BUTTON && //是否按键方式进入DFU
(nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 0))
{
NRF_LOG_DEBUG("DFU mode requested via button.");
return true;
}
//============================================================================
// #ifndef NRF_BL_DFU_ENTER_METHOD_PINRESET
// #define NRF_BL_DFU_ENTER_METHOD_PINRESET 0
// #endif
//=============================================================================
if (NRF_BL_DFU_ENTER_METHOD_PINRESET && //是否复位方式进入DFU
(NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk))
{
NRF_LOG_DEBUG("DFU mode requested via pin-reset.");
return true;
}
//================================================================================
// #ifndef NRF_BL_DFU_ENTER_METHOD_GPREGRET
// #define NRF_BL_DFU_ENTER_METHOD_GPREGRET 1
// #endif
//=================================================================================
if (NRF_BL_DFU_ENTER_METHOD_GPREGRET && //是否GPREGRET寄存器方式进入DFU
(nrf_power_gpregret_get() & BOOTLOADER_DFU_START))
{
NRF_LOG_DEBUG("DFU mode requested via GPREGRET.");
return true;
}
//=================================================================================
// #ifndef NRF_BL_DFU_ENTER_METHOD_BUTTONLESS
// #define NRF_BL_DFU_ENTER_METHOD_BUTTONLESS 0
// #endif
//=================================================================================
if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS && //是否buttonless方式进入DFU
(s_dfu_settings.enter_buttonless_dfu == 1))
{
NRF_LOG_DEBUG("DFU mode requested via bootloader settings.");
return true;
}
return false;
}
-
bootloader的ROM和RAM空间设置(S132,nRF52832_xxAA)
0x78000是用户程序结束地址
0x6000是bootloader的大小
0x1000是4K的setting配置信息
-
用户程序增加DFU服务
step 1: (ble_dfu_bonded.c暂时不用)
在sdk_config.h增加dfu相关宏,以及添加ble_dfu.c,ble_dfu_unbonded.c和nrf_dfu_svci.c三个文件到工程
step 2:
在C/C++选项中添加2个NRF_DFU_TRANSPORT_BLE=1和BL_SETTINGS_ACCESS_ONLY宏定义
step 3:
在C/C++选项中添加以下路径
step 4:
在main.c中引入头文件#include "ble_dfu.h"并加入以下代码片段
static void advertising_config_get(ble_adv_modes_config_t * p_config)
{
memset(p_config, 0, sizeof(ble_adv_modes_config_t));
p_config->ble_adv_fast_enabled = true;
p_config->ble_adv_fast_interval = APP_ADV_INTERVAL;
p_config->ble_adv_fast_timeout = APP_ADV_DURATION;
}
static void disconnect(uint16_t conn_handle, void * p_context)
{
UNUSED_PARAMETER(p_context);
ret_code_t err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
if (err_code != NRF_SUCCESS)
{
NRF_LOG_WARNING("Failed to disconnect connection. Connection handle: %d Error: %d", conn_handle, err_code);
}
else
{
NRF_LOG_DEBUG("Disconnected connection handle %d", conn_handle);
}
}
// YOUR_JOB: Update this code if you want to do anything given a DFU event (optional).
/**@brief Function for handling dfu events from the Buttonless Secure DFU service
*
* @param[in] event Event from the Buttonless Secure DFU service.
*/
static void ble_dfu_evt_handler(ble_dfu_buttonless_evt_type_t event)
{
switch (event)
{
case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE:
{
NRF_LOG_INFO("Device is preparing to enter bootloader mode.");
// Prevent device from advertising on disconnect.
ble_adv_modes_config_t config;
advertising_config_get(&config);
config.ble_adv_on_disconnect_disabled = true;
ble_advertising_modes_config_set(&m_advertising, &config);
// Disconnect all other bonded devices that currently are connected.
// This is required to receive a service changed indication
// on bootup after a successful (or aborted) Device Firmware Update.
uint32_t conn_count = ble_conn_state_for_each_connected(disconnect, NULL);
NRF_LOG_INFO("Disconnected %d links.", conn_count);
break;
}
case BLE_DFU_EVT_BOOTLOADER_ENTER:
// YOUR_JOB: Write app-specific unwritten data to FLASH, control finalization of this
// by delaying reset by reporting false in app_shutdown_handler
NRF_LOG_INFO("Device will enter bootloader mode.");
break;
case BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED:
NRF_LOG_ERROR("Request to enter bootloader mode failed asynchroneously.");
// YOUR_JOB: Take corrective measures to resolve the issue
// like calling APP_ERROR_CHECK to reset the device.
break;
case BLE_DFU_EVT_RESPONSE_SEND_ERROR:
NRF_LOG_ERROR("Request to send a response to client failed.");
// YOUR_JOB: Take corrective measures to resolve the issue
// like calling APP_ERROR_CHECK to reset the device.
APP_ERROR_CHECK(false);
break;
default:
NRF_LOG_ERROR("Unknown event from ble_dfu_buttonless.");
break;
}
}
step 5:
在main.c中的services_init函数中添加DFU服务初时化代码
ble_dfu_buttonless_init_t dfus_init = {0};
dfus_init.evt_handler = ble_dfu_evt_handler;
err_code = ble_dfu_buttonless_init(&dfus_init);
APP_ERROR_CHECK(err_code);
step 6:
增加ble_bas.c和ble_dis.c两个文件到工程
step 7:
在C/C++选项中添加以下路径
step 8:
1.在main.c中引入头文件
#include "ble_dis.h"
#include "ble_bas.h"
2. 在main.c文件加定义m_bas
BLE_BAS_DEF(m_bas);
3. 在m_adv_uuids数组中添加uuid服务
static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */
{
{BLE_UUID_NUS_SERVICE, BLE_UUID_TYPE_VENDOR_BEGIN},
{BLE_UUID_BATTERY_SERVICE, BLE_UUID_TYPE_BLE},
{BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE},
};
step 9:
在main.c中增加bas_init和dis_init服务初时化代码,并在services_init函数中调用
/**@snippet [UART Initialization] */
/**@snippet [Handling the data received over BLE] */
/**@brief Function for initializing Battery Service.
*/
static void bas_init(void)
{
ret_code_t err_code;
ble_bas_init_t bas_init;
// Initialize Battery Service.
memset(&bas_init, 0, sizeof(bas_init));
bas_init.evt_handler = NULL;
bas_init.support_notification = true;
bas_init.p_report_ref = NULL;
bas_init.initial_batt_level = 100;
// Here the sec level for the Battery Service can be changed/increased.
bas_init.bl_rd_sec = SEC_OPEN;
bas_init.bl_cccd_wr_sec = SEC_OPEN;
bas_init.bl_report_rd_sec = SEC_OPEN;
err_code = ble_bas_init(&m_bas, &bas_init);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for initializing Device Information Service.
*/
static void dis_init(void)
{
ret_code_t err_code;
ble_dis_init_t dis_init;
// ble_dis_pnp_id_t pnp_id;
// ble_dis_sys_id_t sys_id;
// pnp_id.vendor_id_source = PNP_ID_VENDOR_ID_SOURCE;
// pnp_id.vendor_id = PNP_ID_VENDOR_ID;
// pnp_id.product_id = PNP_ID_PRODUCT_ID;
// pnp_id.product_version = PNP_ID_PRODUCT_VERSION;
// Initialize Device Information Service.
memset(&dis_init, 0, sizeof(dis_init));
ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, (char *)MANUFACTURER_NAME);
ble_srv_ascii_to_utf8(&dis_init.model_num_str, MODEL_NUMBER);
ble_srv_ascii_to_utf8(&dis_init.serial_num_str, SERIAL_NUMBER);
ble_srv_ascii_to_utf8(&dis_init.hw_rev_str, HARDWARE_VERSION);
ble_srv_ascii_to_utf8(&dis_init.fw_rev_str, FIRMWARE_VERSION);
ble_srv_ascii_to_utf8(&dis_init.sw_rev_str, SOFTWARE_VERSION);
// sys_id.manufacturer_id = MANUFACTURER_ID;
// sys_id.organizationally_unique_id = ORG_UNIQUE_ID;
// dis_init.p_sys_id = &sys_id;
// dis_init.p_pnp_id = &pnp_id;
dis_init.dis_char_rd_sec = SEC_OPEN;
err_code = ble_dis_init(&dis_init);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for initializing services that will be used by the application.
*/
static void services_init(void)
{
uint32_t err_code;
ble_nus_init_t nus_init;
nrf_ble_qwr_init_t qwr_init = {0};
ble_dfu_buttonless_init_t dfus_init = {0};
// Initialize Queued Write Module.
qwr_init.error_handler = nrf_qwr_error_handler;
err_code = nrf_ble_qwr_init(&m_qwr, &qwr_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);
// Initialize NUS.
memset(&nus_init, 0, sizeof(nus_init));
nus_init.data_handler = nus_data_handler;
err_code = ble_nus_init(&m_nus, &nus_init);
APP_ERROR_CHECK(err_code);
bas_init();
dis_init();
}
step 10:
在main.c中定义以下宏
#define SOFTWARE_VERSION_STR "1.0.0.0"
#define MODEL_NUMBER "DFU_TEST"
#define SERIAL_NUMBER "123456789"
#define HARDWARE_VERSION "H001"
#define FIRMWARE_VERSION "S001"
#define SOFTWARE_VERSION SOFTWARE_VERSION_STR
#define MANUFACTURER_NAME "NORDIC TECHOLOGY LTD"
step 11:
修改sdk_config.h中的宏,如下
// <q> BLE_DIS_ENABLED - ble_dis - Device Information Service
#ifndef BLE_DIS_ENABLED
#define BLE_DIS_ENABLED 1
#endif
// <e> BLE_BAS_ENABLED - ble_bas - Battery Service
//==========================================================
#ifndef BLE_BAS_ENABLED
#define BLE_BAS_ENABLED 1
#endif
// <e> BLE_BAS_CONFIG_LOG_ENABLED - Enables logging in the module.
//==========================================================
#ifndef BLE_BAS_CONFIG_LOG_ENABLED
#define BLE_BAS_CONFIG_LOG_ENABLED 0
#endif
// <o> BLE_BAS_CONFIG_LOG_LEVEL - Default Severity level
// <0=> Off
// <1=> Error
// <2=> Warning
// <3=> Info
// <4=> Debug
#ifndef BLE_BAS_CONFIG_LOG_LEVEL
#define BLE_BAS_CONFIG_LOG_LEVEL 3
#endif
// <o> BLE_BAS_CONFIG_INFO_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef BLE_BAS_CONFIG_INFO_COLOR
#define BLE_BAS_CONFIG_INFO_COLOR 0
#endif
// <o> BLE_BAS_CONFIG_DEBUG_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef BLE_BAS_CONFIG_DEBUG_COLOR
#define BLE_BAS_CONFIG_DEBUG_COLOR 0
#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
step 12:
用户ROM和RAM配置
0x26000是协议栈s132_nrf52_6.1.0_softdevice.hex所占的ROM空间大小,即协议栈地址范围是0~0x26000
0x52000是用户程序可用ROM空间的大小
0x20002AA8是协议栈s132_nrf52_6.1.0_softdevice.hex所占的RAM空间大小,范围是0x20000000~0x20002AA8
0xD558是用户程序可能RAM空间的大小
如果不确定协议栈所占RAM的空间大小,可以使用以下方法来确定
1.在nrf_sdh_ble.c中定义变量startRam,ramSize;然后在nrf_sdh_ble_enable函数中添加2行代码后编译一下
2.在nrf_sdh_ble_enable函数中的最后一行设置一个断点,点击DEBUG并全速运行,待停到断点处后,将变量startRam,ramSize
加入到Watch 2中,startRam的值为用户程序RAM的起始地址(即协议栈的大小),ramSize的值为用户程序可用的RAM大小
-
合并bootloader,用户程序,协议栈,配置信息文件成一个hex档
烧录工具下载地址:https://download.csdn.net/download/mygod2008ok/11157992
step 1: 安装工具
安装nrfgostudio_win-64_1.21.2_installer.msi和nRF5x-Command-Line-Tools_9_6_0_Installer.exe两个烧录工具
step 2:设置环境变量
在系统环境变量path中加入路径C:Program Files (x86)Nordic Semiconductornrf5xbin;然后重启电脑使设置生效
step 3: 生成bootloader_setting
将nrf52832_xxaa_s132.hex ,nrf52832_xxaa.hex和s132_nrf52_6.1.0_softdevice.hex用户程序hex文档复制到
nRF5_SDK_15.2.0_9412b96examples目录下,并在此目录下打开命令行,输入nrfutil.exe settings generate --family
NRF52 --application nrf52832_xxaa.hex --application-version 3 --bootloader-version 2 --bl-settings-version 1
bootloader_settings.hex后回车生成bootloader_settings.hex配置文件
step 4:合并bootloader和协议栈
在命令行中输入mergehex.exe --merge nrf52832_xxaa_s132.hex s132_nrf52_6.1.0_softdevice.hex --output
production_final1.hex后回车,生成production_final1.hex临时文件
step 5:合并临时文件和用户程序
在命令行中输入mergehex.exe --merge production_final1.hex nrf52832_xxaa.hex --output production_final2.hex
后回车,生成production_final2.hex 临时文件
step 6: 合并临时文件和配置文件
在命令行中输入mergehex.exe --merge production_final2.hex bootloader_settings.hex --output nrf52832_final.hex
后回车,生成nrf52832_final.hex最终烧录hex文档
step 7:烧录nrf52832_final.hex到芯片
1.在命令行中输入nrfjprog -f NRF52 --eraseall后回车擦除整个芯片
2.在命令行中输入nrfjprog.exe -f NRF52 --program "nrf52832_final.hex" --verify后回车烧录最终程序到芯片
3.在命令行中输入nrfjprog -f NRF52 --reset后回车复位并运行
如果为了方便操作,可以将上述操作整合到批处理文件中,在 nRF5_SDK_15.2.0_9412b96examples目录下新建一个
dfu.bat文件,打开编辑以下内容后保存
@echo off
:菜单
echo =======================
echo 批处理菜单
echo =======================
echo ====================================================
echo 1.生成bootloader_setting
echo 2.合并所有
echo ====================================================
echo 3.烧录所有
echo =======================
set /p 选择=请进入命令:
if %选择%==1 (goto :1生成bootloader_setting)
if %选择%==2 (goto :2合并所有)
if %选择%==3 (goto :3烧录所有)
::else (goto : 菜单)
:1生成bootloader_setting
copy .dfusecure_bootloaderpca10040_blearm5_no_packs_buildnrf52832_xxaa_s132.hex .
copy .ble_peripheralble_app_uartpca10040s132arm5_no_packs_buildnrf52832_xxaa.hex .
nrfutil.exe settings generate --family NRF52 --application nrf52832_xxaa.hex --application-version 3 --bootloader-version 2 --bl-settings-version 1 bootloader_settings.hex
echo 已生成bootloader_setting...
:pause>nul
goto 菜单
:2合并所有
copy .dfusecure_bootloaderpca10040_blearm5_no_packs_buildnrf52832_xxaa_s132.hex .
copy .ble_peripheralble_app_uartpca10040s132arm5_no_packs_buildnrf52832_xxaa.hex .
nrfutil.exe settings generate --family NRF52 --application nrf52832_xxaa.hex --application-version 3 --bootloader-version 2 --bl-settings-version 1 bootloader_settings.hex
mergehex.exe --merge nrf52832_xxaa_s132.hex s132_nrf52_6.1.0_softdevice.hex --output production_final1.hex
mergehex.exe --merge production_final1.hex nrf52832_xxaa.hex --output production_final2.hex
mergehex.exe --merge production_final2.hex bootloader_settings.hex --output nrf52832_final.hex
del production_final1.hex
del production_final2.hex
:pause>nul
goto 菜单
:3烧录所有
::nrfjprog.exe -f NRF52 --program "app_test.hex" --verify
::nrfjprog.exe -f NRF52 --program "dfu_bootloader.hex" --verify
::nrfjprog.exe -f NRF52 --program "bootloader_settings.hex" --verify
cls
nrfjprog -f NRF52 --eraseall
::nrfjprog --family NRF52 --recovers
nrfjprog.exe -f NRF52 --program "nrf52832_final.hex" --verify
nrfjprog -f NRF52 --reset
echo ......
:pause>nul
goto 菜单
:无效命令
echo 无效的指令 指令范围(1-20)重新选择
goto 菜单
-
生成DFU升级文件
1.将private.pem和nrf52832_xxaa.hex文件复制到nRF5_SDK_15.2.0_9412b96examples目录下,在此目录下打开命
令行输入nrfutil pkg generate --hw-version 52 --sd-req 0xaf --application-version 0x03 --application nrf52832_xxaa.hex --key-file
private.pem nrf52832_xxaa_app.zip后回车会生成nrf52832_xxaa_app.zip蓝牙DFU升级包
nrfutil pkg generate --hw-version 52 --sd-req 0xaf --application-version 0x03 --application nrf52832_xxaa.hex --key-file
private.pem nrf52832_xxaa_app.zip
如果不知道sd req,可以通过在命令行输入以下命令得到: |s132_nrf52_6.1.0|0xAF|
nrfutil pkg generate --help
E:jzhou>nrfutil pkg generate --help
Usage: nrfutil pkg generate [OPTIONS] ZIPFILE
Generate a zip package for distribution to apps that support Nordic DFU
OTA. The application, bootloader, and SoftDevice files are converted to
.bin if supplied as .hex files. For more information on the generated
package, see: http://developer.nordicsemi.com/nRF5_SDK/doc/
The following combinations are supported by this command:
* BL only: Supported.
* SD only: Supported (SD of same Major Version).
* APP only: Supported (external or internal).
* BL + SD: Supported.
* BL + APP: Not supported (use two packages instead).
* BL + SD + APP: Supported.
* SD + APP: Supported (SD of same Major Version).
Options:
--debug-mode Debug mode switch, enables version check
skipping.
--application TEXT The application firmware file.
--application-version INTEGER The application version.
--application-version-string TEXT
The application version string, e.g
"2.7.31".
--bootloader TEXT The bootloader firmware file.
--bootloader-version INTEGER The bootloader version.
--hw-version INTEGER The hardware version.
--sd-req TEXT The SoftDevice requirements. A comma-
separated list of SoftDevice firmware IDs
(1 or more) of which one must be present on
the target device. Each item on the list
must be a two- or four-digit hex number
prefixed with "0x" (e.g. "0x12", "0x1234").
A non-exhaustive list of well-known values
to use with this option follows:
|s112_nrf52_6.0.0|0xA7|
|s112_nrf52_6.1.0|0xB0|
|s112_nrf52_6.1.1|0xB8|
|s130_nrf51_1.0.0|0x67|
|s130_nrf51_2.0.0|0x80|
|s132_nrf52_2.0.0|0x81|
|s130_nrf51_2.0.1|0x87|
|s132_nrf52_2.0.1|0x88|
|s132_nrf52_3.0.0|0x8C|
|s132_nrf52_3.1.0|0x91|
|s132_nrf52_4.0.0|0x95|
|s132_nrf52_4.0.2|0x98|
|s132_nrf52_4.0.3|0x99|
|s132_nrf52_4.0.4|0x9E|
|s132_nrf52_4.0.5|0x9F|
|s132_nrf52_5.0.0|0x9D|
|s132_nrf52_5.1.0|0xA5|
|s132_nrf52_6.0.0|0xA8|
|s132_nrf52_6.1.0|0xAF|
|s132_nrf52_6.1.1|0xB7|
|s140_nrf52_6.0.0|0xA9|
|s140_nrf52_6.1.0|0xAE|
|s140_nrf52_6.1.1|0xB6|
--sd-id TEXT The new SoftDevice ID to be used as --sd-
req for the Application update in case the
ZIP contains a SoftDevice and an
Application.
--softdevice TEXT The SoftDevice firmware file.
--sd-boot-validation TEXT The method of boot validation for
Softdevice. Choose from:
NO_VALIDATION
VALIDATE_GENERATED_CRC
VALIDATE_GENERATED_SHA256
VALIDATE_ECDSA_P256_SHA256
--app-boot-validation TEXT The method of boot validation for
application. Choose from:
NO_VALIDATION
VALIDATE_GENERATED_CRC
VALIDATE_GENERATED_SHA256
VALIDATE_ECDSA_P256_SHA256
--key-file FILE The private (signing) key in PEM fomat.
--external-app Indicates that the FW upgrade is intended
to be passed through (not applied on the
receiving device)
--zigbee BOOLEAN Create an image and distribution package
for Zigbee DFU server.
--zigbee-manufacturer-id INTEGER
Manufacturer ID to be used in Zigbee OTA
header.
--zigbee-image-type INTEGER Image type to be used in Zigbee OTA header.
--zigbee-comment TEXT Firmware comment to be used in Zigbee OTA
header.
--zigbee-ota-hw-version INTEGER
The zigbee OTA hw version.
--zigbee-ota-fw-version INTEGER
The zigbee OTA fw version.
--help Show this message and exit.
E:jzhou>
-
DFU升级工具升级操作
一键式升级工具下载地址:https://download.csdn.net/download/mygod2008ok/10538088
step 1:
安装一键式升级升级工具(适合用android 7及以前的手机)
step 2:
将nrf52832_xxaa_app.zip升级包复制到手机,打开APP连接上蓝牙,点开始DFU升级按键加载nrf52832_xxaa_app.zip升级
文件后,稍后APP会自动进行蓝牙升级,升级百分比进度会显示在APP上
如果工具不适用,你也可以从官网下载nRF Connect工具进行升级
-
nRF Connect工具进行升级
1.打开nRF Connect扫描设备
2.连接设备
3.打开DFU服务notify开关
4.点击notify左边的按钮打开写数据界面,打send发送使设备进入bootloader 模式
5.重新扫描
6.连接DfuTarg后打开notify开关
7.点击右上角的DFU按钮打开加载升级文件页面,点击OK键去加载nrf52832_xxaa_app.zip升级包
8.升级包加载完后会开始DFU升级
-
Demo下载地址:
https://download.csdn.net/download/mygod2008ok/11158400
最后
以上就是殷勤皮带为你收集整理的nrf52832 sdk15.2.0 dfu升级攻略工具准备(windows 64位)bootloader工程(SDK15.2.0的dfu目录下secure_bootloader工程)bootloader工程分析 bootloader的ROM和RAM空间设置(S132,nRF52832_xxAA) 用户程序增加DFU服务合并bootloader,用户程序,协议栈,配置信息文件成一个hex档 生成DFU升级文件 DFU升级工具升级操作nRF Connect工具进行升的全部内容,希望文章能够帮你解决nrf52832 sdk15.2.0 dfu升级攻略工具准备(windows 64位)bootloader工程(SDK15.2.0的dfu目录下secure_bootloader工程)bootloader工程分析 bootloader的ROM和RAM空间设置(S132,nRF52832_xxAA) 用户程序增加DFU服务合并bootloader,用户程序,协议栈,配置信息文件成一个hex档 生成DFU升级文件 DFU升级工具升级操作nRF Connect工具进行升所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复