软件工具下载地址:https://download.csdn.net/download/mygod2008ok/11154112
在系统环境变量的path中加入以下路径后,再重启电脑使环境变量生效
C:\Program Files (x86)\GnuWin32;
C:\Program Files (x86)\GnuWin32\bin;
C:\Program Files (x86)\GNU Tools ARM Embedded\6 2017-q2-update\bin;
C:\Python27\Scripts;
C:\Python27\Lib;
C:\Python27;
1.首先要保证电脑连上网络,打开命令行,输入python -m pip install nrfutil后回车,等待联网下载安装,过一会提示pip版本不够,然后在命令行中输入python -m pip install --upgrade pip后回车,等待联网更新pip
2.再次输入python -m pip install nrfutil后回车,等待联网下载安装,此时会安装成功
*** Using Compiler 'V5.06 update 5 (build 528)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin'
Build target 'nrf52832_xxaa_s132'
compiling nrf_crypto_ecdsa.c...
..\..\..\..\..\components\libraries\crypto\backend\micro_ecc\micro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..\..\..\..\..\components\libraries\crypto\nrf_crypto_ecdsa.c: 0 warnings, 1 error
compiling micro_ecc_backend_ecdh.c...
..\..\..\..\..\components\libraries\crypto\backend\micro_ecc\micro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..\..\..\..\..\components\libraries\crypto\backend\micro_ecc\micro_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...
..\..\..\..\..\components\libraries\crypto\backend\micro_ecc\micro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..\..\..\..\..\components\libraries\crypto\backend\micro_ecc\micro_ecc_backend_ecdsa.c: 0 warnings, 1 error
compiling micro_ecc_backend_ecc.c...
..\..\..\..\..\components\libraries\crypto\backend\micro_ecc\micro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..\..\..\..\..\components\libraries\crypto\backend\micro_ecc\micro_ecc_backend_ecc.c: 0 warnings, 1 error
compiling nrf_crypto_ecc.c...
..\..\..\..\..\components\libraries\crypto\backend\micro_ecc\micro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..\..\..\..\..\components\libraries\crypto\nrf_crypto_ecc.c: 0 warnings, 1 error
compiling nrf_dfu_ver_validation.c...
..\..\..\..\..\components\libraries\crypto\backend\micro_ecc\micro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..\..\..\..\..\components\libraries\bootloader\dfu\nrf_dfu_ver_validation.c: 0 warnings, 1 error
compiling nrf_dfu_req_handler.c...
..\..\..\..\..\components\libraries\crypto\backend\micro_ecc\micro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..\..\..\..\..\components\libraries\bootloader\dfu\nrf_dfu_req_handler.c: 0 warnings, 1 error
compiling nrf_dfu_validation.c...
..\..\..\..\..\components\libraries\crypto\backend\micro_ecc\micro_ecc_backend_ecc.h(52): error: #5: cannot open source input file "uECC.h": No such file or directory
#include "uECC.h"
..\..\..\..\..\components\libraries\bootloader\dfu\nrf_dfu_validation.c: 0 warnings, 1 error
".\_build\nrf52832_xxaa_s132.axf" - 9 Error(s), 0 Warning(s).
Target not created.
Build Time Elapsed: 00:00:03
1.首先保证电脑连上网络,然后在nRF5_SDK_15.2.0_9412b96\external\micro-ecc\目录下,找到build_all.bat文件,双击
运行从github上复制micro-ecc文件包到nRF5_SDK_15.2.0_9412b96\external\micro-ecc\目录下,并会在nRF5_SDK_15.2.0_9412b96\external\micro-ecc\nrf52nf_keil\armgcc\目录下生成micro_ecc_lib_nrf52.lib文件
1.再次编译工程,会提示缺少 public key.
2.在nRF5_SDK_15.2.0_9412b96\examples\dfu\的目录下打开命令行,输入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.再次编译工程将会通过
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;
}
#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
#ifndef NRF_BL_DFU_ENTER_METHOD_BUTTON
#define NRF_BL_DFU_ENTER_METHOD_BUTTON 0
#endif
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_enter = dfu_enter_check();
/*代码片段*/
/**@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;
}
0x78000是用户程序结束地址
0x6000是bootloader的大小
0x1000是4K的setting配置信息
在sdk_config.h增加dfu相关宏,以及添加ble_dfu.c,ble_dfu_unbonded.c和nrf_dfu_svci.c三个文件到工程
在C/C++选项中添加2个NRF_DFU_TRANSPORT_BLE=1和BL_SETTINGS_ACCESS_ONLY宏定义
在C/C++选项中添加以下路径
在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;
}
}
在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);
增加ble_bas.c和ble_dis.c两个文件到工程
在C/C++选项中添加以下路径
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},
};
在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();
}
在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"
修改sdk_config.h中的宏,如下
// BLE_DIS_ENABLED - ble_dis - Device Information Service
#ifndef BLE_DIS_ENABLED
#define BLE_DIS_ENABLED 1
#endif
//
//==========================================================
#ifndef BLE_BAS_ENABLED
#define BLE_BAS_ENABLED 1
#endif
//
//==========================================================
#ifndef BLE_BAS_CONFIG_LOG_ENABLED
#define BLE_BAS_CONFIG_LOG_ENABLED 0
#endif
//
// <0=> Off
// <1=> Error
// <2=> Warning
// <3=> Info
// <4=> Debug
#ifndef BLE_BAS_CONFIG_LOG_LEVEL
#define BLE_BAS_CONFIG_LOG_LEVEL 3
#endif
//
// <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
//
// <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
//
#ifndef NRF_SDH_BLE_VS_UUID_COUNT
#define NRF_SDH_BLE_VS_UUID_COUNT 2
#endif
用户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空间的大小
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大小
烧录工具下载地址:https://download.csdn.net/download/mygod2008ok/11157992
安装nrfgostudio_win-64_1.21.2_installer.msi和nRF5x-Command-Line-Tools_9_6_0_Installer.exe两个烧录工具
在系统环境变量path中加入路径C:\Program Files (x86)\Nordic Semiconductor\nrf5x\bin\;然后重启电脑使设置生效
将nrf52832_xxaa_s132.hex ,nrf52832_xxaa.hex和s132_nrf52_6.1.0_softdevice.hex用户程序hex文档复制到
nRF5_SDK_15.2.0_9412b96\examples\目录下,并在此目录下打开命令行,输入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配置文件
在命令行中输入mergehex.exe --merge nrf52832_xxaa_s132.hex s132_nrf52_6.1.0_softdevice.hex --output
production_final1.hex后回车,生成production_final1.hex临时文件
在命令行中输入mergehex.exe --merge production_final1.hex nrf52832_xxaa.hex --output production_final2.hex
后回车,生成production_final2.hex 临时文件
在命令行中输入mergehex.exe --merge production_final2.hex bootloader_settings.hex --output nrf52832_final.hex
后回车,生成nrf52832_final.hex最终烧录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_9412b96\examples\目录下新建一个
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 .\dfu\secure_bootloader\pca10040_ble\arm5_no_packs\_build\nrf52832_xxaa_s132.hex .\
copy .\ble_peripheral\ble_app_uart\pca10040\s132\arm5_no_packs\_build\nrf52832_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 .\dfu\secure_bootloader\pca10040_ble\arm5_no_packs\_build\nrf52832_xxaa_s132.hex .\
copy .\ble_peripheral\ble_app_uart\pca10040\s132\arm5_no_packs\_build\nrf52832_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 菜单
1.将private.pem和nrf52832_xxaa.hex文件复制到nRF5_SDK_15.2.0_9412b96\examples\目录下,在此目录下打开命
令行输入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
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>
一键式升级工具下载地址:https://download.csdn.net/download/mygod2008ok/10538088
安装一键式升级升级工具(适合用android 7及以前的手机)
将nrf52832_xxaa_app.zip升级包复制到手机,打开APP连接上蓝牙,点开始DFU升级按键加载nrf52832_xxaa_app.zip升级
文件后,稍后APP会自动进行蓝牙升级,升级百分比进度会显示在APP上
如果工具不适用,你也可以从官网下载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升级