• 工具准备(windows 64位)

    软件工具下载地址:https://download.csdn.net/download/mygod2008ok/11154112

step 1:  安装软件

  1. 安装coreutils-5.3.0.exe
  2. 安装gcc-arm-none-eabi-6-2017-q2-update-win32-sha2.exe
  3. 安装make-3.81.exe
  4. 安装Git-2.21.0-64-bit.exe
  5. 安装python-2.7.12.amd64.msi

step 2: 设置系统环境变量

在系统环境变量的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;

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_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

step 2: 解决uECC.h缺失问题

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文件

step 3: 解决Public key问题

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.再次编译工程将会通过

  • 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 implementedret_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 nameret_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.cnrf_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_handlerNRF_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 Semiconductor\nrf5x\bin\;然后重启电脑使设置生效

step 3: 生成bootloader_setting

将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配置文件

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_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.hexmergehex.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_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

如果不知道sd req,可以通过在命令行输入以下命令得到:  |s132_nrf52_6.1.0|0xAF|

nrfutil pkg generate --help

E:\jzhou>nrfutil pkg generate --help
Usage: nrfutil pkg generate [OPTIONS] ZIPFILEGenerate a zip package for distribution to apps that support Nordic DFUOTA. The application, bootloader, and SoftDevice files are converted to.bin if supplied as .hex files. For more information on the generatedpackage, 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 checkskipping.--application TEXT              The application firmware file.--application-version INTEGER   The application version.--application-version-string TEXTThe 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 onthe target device. Each item on the listmust be a two- or four-digit hex numberprefixed with "0x" (e.g. "0x12", "0x1234").A non-exhaustive list of well-known valuesto 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 theZIP contains a SoftDevice and anApplication.--softdevice TEXT               The SoftDevice firmware file.--sd-boot-validation TEXT       The method of boot validation forSoftdevice. Choose from:NO_VALIDATIONVALIDATE_GENERATED_CRCVALIDATE_GENERATED_SHA256VALIDATE_ECDSA_P256_SHA256--app-boot-validation TEXT      The method of boot validation forapplication. Choose from:NO_VALIDATIONVALIDATE_GENERATED_CRCVALIDATE_GENERATED_SHA256VALIDATE_ECDSA_P256_SHA256--key-file FILE                 The private (signing) key in PEM fomat.--external-app                  Indicates that the FW upgrade is intendedto be passed through (not applied on thereceiving device)--zigbee BOOLEAN                Create an image and distribution packagefor Zigbee DFU server.--zigbee-manufacturer-id INTEGERManufacturer ID to be used in Zigbee OTAheader.--zigbee-image-type INTEGER     Image type to be used in Zigbee OTA header.--zigbee-comment TEXT           Firmware comment to be used in Zigbee OTAheader.--zigbee-ota-hw-version INTEGERThe zigbee OTA hw version.--zigbee-ota-fw-version INTEGERThe 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升级攻略相关推荐

  1. 爱江山更爱美人服务器维护,爱江山更爱美人,不花钱的升级攻略

    原标题:爱江山更爱美人,不花钱的升级攻略 最近玩了一款换装游戏,剧情可圈可点,既像看小说,又像看电视剧,而且完全不用担心演技累人,如果不想看剧情可以快进跳过,作为一款休闲游戏也是很上心了.下面给大家讲 ...

  2. 舰r经验计算机,战舰少女R提督经验怎么得 提督快速升级攻略

    战舰少女R提督经验怎么得?分享战舰少女R提督快速经验方法,下面我们就一起来看看战舰少女R提督升级攻略,希望对大家有所帮助. 提督等级有什么用? 主要是前期10-50级,有一定的奖励,尤其太太.小姨子. ...

  3. cad2016中选择全图字体怎么操作_DNF手游快速升级攻略 DNF手游怎么快速升级

    DNF手游中等级对玩家来说是至关重要的,等级越高可体验更多新玩法,而装备等级越高就代表着玩家的实力越强,所以大家都想知道怎么快速升级和提高装备强化成功率,下面就让小编聊聊个人的经验! DNF手游升级攻 ...

  4. 永恒边境白羊座服务器维护,永恒边境升级攻略 速升50级技巧

    永恒边境怎么升级快?分享永恒边境升级攻略,下面我们就一起来看看永恒边境速刷主线支线任务技巧,希望对大家有所帮助. 20-30级篇 在这个阶段,我们就主线任务和支线任务大家都不要错过了,都要好好抓住,我 ...

  5. 神武4手游服务器维护,神武4手游快速升级攻略 神武4手游新区老区冲级攻略

    神武4手游当中等级提升说快不快说慢也不慢,主要还是看自己的等级和服务器等级相比较,今天小编就带来神武4手游快速升级攻略.一些玩家重新找到了一个区想要冲级要先了解两件事情,第一件事情就是服务器是新区还是 ...

  6. 剑网3指尖江湖快速升级攻略 悄悄抱走月儿

    叉叉帮你玩游戏,大家好,这里是叉叉君! 等级就是战力!剑网3指尖江湖中,玩家想要快速提升角色的等级,其实是有窍门的.叉叉君为大家整理出全网最全的剑网3指尖江湖快速升级方法,大伙儿只要按照这几个方法来, ...

  7. 倩女手游经验计算机,倩女幽魂手游怎么快速升级 新手升级攻略详解

    倩女幽魂手游的公测已经开启啦!相信大家上了游戏第一件事就是快速的冲级,那么在倩女幽魂手游中要怎样升级呢?就让4399熊猫来为你带来倩女幽魂手游新手升级攻略详解~ 在倩女幽魂手游中获得经验的方法大致可以 ...

  8. 倩女手游经验计算机,倩女幽魂手游升级攻略 如何保证每天获经验最大

    倩女幽魂手游如何保证每天获得经验最大化?这是一款即时制MMORPG手游.现在就和小编一起来看看倩女幽魂手游升级攻略. 技巧1:卡龙 1.在设备多的情况下,注册至少5个小号 2.一条龙一轮是5环,3个小 ...

  9. 青云志鸿蒙争霸位置,青云志手游快速升级攻略,技巧分享 ,新手升级方法

    原标题:青云志手游快速升级攻略,技巧分享 ,新手升级方法 青云志手游新手怎么才能快速冲级?青云志手游升级有什么技巧方法?对于青云志手游中的升级问题, 今天唯游沫沫就为各位小伙伴们带来,青云志手游新手升 ...

最新文章

  1. 身份证号码对应地区-官方措辞:行政区划代码
  2. 薛澜:人工智能发展要让创新驱动和敏捷治理并驾齐驱
  3. Python操作git
  4. Hibernate中保存与持久性以及saveOrUpdate之间的区别
  5. php需要什么技能,PHP初学者必备的技能
  6. JAVA并发七(多线程环境中安全使用集合API)
  7. “Chrome不能访问更新服务器(错误:3)”的解决方法
  8. [SoapUI] Mock Service
  9. 四川大学锦城学院计算机考试题,四川大学锦城学院期考试试题(B卷)_15889.doc
  10. 自己写Cache数据库之设计之初——想办法让16颗CPU扛住3w/s的压力?
  11. java处理文本的方法
  12. Windows安装WSL详解
  13. Linux Mint 19.2版安装教程
  14. 服务器使用CDN加速的优劣势分析
  15. vue中全局定义mintUI中toast
  16. Android Studio Logcat 截断问题(cocos2d-x 篇)
  17. 2023年全国最新工会考试精选真题及答案10
  18. css font size 单位,css中font-size的单位总结:px、em、pt
  19. JSP及MVC三层架构
  20. 关于Office正版验证

热门文章

  1. C++11多线程第三篇:线程传参详解,detach()大坑,成员函数做线程参数
  2. 注册表设置计算机开机启动项
  3. ORA-12737:Instant Client Light:unsupported server character set ZHS16GBK
  4. windows权限管理
  5. 怎么把好几行弄成一行_【excle 如何多行变一行】excel中怎么把多行同一个人的数据变成一行?...
  6. Hash Exercise 21.11.27
  7. 30.1lvs-adm与ipvsadm命令
  8. 《Python黑帽子》python3代码实现(第四章)
  9. 恭喜湖人夺得NBA总冠军
  10. 月薪20KPython程序员2018年Python学习进阶书籍推荐