2017年4月19日 星期三

nRF5X: prevent bootloader from erased after programming

Board : nRF52832_xxac / SDK11/s132  (but not only these have the problem)

After add DFU service in application, we have to program bootloader. In nRFgo , the IROM must be look like this :


but after you compile and program your application again, and open nRFgo next time , you might see :
and that means your bootloader is erased by application.

That's because a mistake of project setting of application



this is project setting of SDK11/ble_app_template
the start point + size = 0x1c000 + 0x64000 = 0x7f000 = the end point.
So, the application is end at 0x7f000 in default.

But in the project setting of SDK 11/bootloader/ dual_bank_dfu_s132
It shows that bootloader start at 0x7a000.

So, if you program application again , it is necessary to erase bootloader for application space.


And the solution I suggest you is :


change application size  0x62000 ->0x5e000


0x1c000+ 0x5d000 = 0x79000 to prevent bootloader from erased after programming


Note:
let the application size smaller than the start point of bootloader for 0x2000 is more stable.

Reference :
https://devzone.nordicsemi.com/question/100609/sdk-12-bootloader-erased-after-programming/

nRF5x: how to use UICR as your signature

board: nRF52832_xxac_s132/ SDK11

After developing a firmware, you can use UICR as a mark to use .
because UICR can not be erased by DFU-OTA

STEP 1
copy file "uicr_config.h" at:
C:\..\nRF5x_SDK_11.0.0\examples\peripheral\uicr_config
to your project file.









STEP 2
open your project in IDE
add this in main.c :


//power by Agatha Kuan
//add uicr
#include "uicr_config.h"
then compile your project first.

STEP 3
open uicr_config.h
I add my family name like this:


// const uint32_t UICR_CLENR0    __attribute__((at(0x10001000))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_RBPCONF   __attribute__((at(0x10001004))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_XTALFREQ  __attribute__((at(0x10001008))) __attribute__((used)) = 0xFFFFFFFF;
const uint32_t UICR_ADDR_0x04 __attribute__((at(0x10001004))) __attribute__((used)) = 0x6e61754b;
//const uint32_t UICR_ADDR_0x80 __attribute__((at(0x1000108c))) __attribute__((used)) = 0x69617354;
//const uint32_t UICR_ADDR_0x84 __attribute__((at(0x10001084))) __attribute__((used)) = 0x6e656843;
//const uint32_t UICR_ADDR_0x88 __attribute__((at(0x10001090))) __attribute__((used)) = 0x53334955;
// const uint32_t UICR_ADDR_0x8C __attribute__((at(0x1000108C))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0x90 __attribute__((at(0x10001090))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0x94 __attribute__((at(0x10001094))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0x98 __attribute__((at(0x10001098))) __attribute__((used)) = 0xFFFFF
then compile , program to your nRF52

STEP 4
open command line, type :


:: power by Agatha Kuan  2017.04.18

.\nrfjprog.exe --family NRF52 --memrd 0x10001004 --n 4

it shows:














be careful that the ascii shows in Little Endian
parameter "--n" write the length to read, "4" means 4 bytes.

Reference:
https://devzone.nordicsemi.com/documentation/nrf51/4.4.1/html/group__uicr__config__example.html

nRF52 avoid "DfuTarg": how to prevent from staying stuck in bootloader mode without starting the application

board: nRF52832_xxac_s132 nordic / SDK 11

While you try to add DFU  OTA service and flash softdevice, application ,and bootloader to your nRF52 (by nRFgo or command line tools),  you might see its BLE Advertising name as "Dfutarg". Like this :



and that means your application does not start. The device stays stuck in bootloader.

There are 2 ways to solve this problem:

First solution: program by command line tools and write memory

1. go to
C:\..\Nordic Semiconductor\nrf5x\bin
open command line, and write :


:: power by Agatha Kuan 20170419

.\nrfjprog.exe --family NRF52 --eraseall
.\nrfjprog.exe --family NRF52 --program %your_softdevice_name%
.\nrfjprog.exe --family NRF52 --program %your_application_name%
.\nrfjprog.exe --family NRF52 --program %your_bootloader_name%
.\nrfjprog.exe --family NRF52 --memwr 0x7f000 --val 1
.\nrfjprog.exe --family NRF52 --reset

then after it reset , the application will start.

Second solution : add patch file 

I provide you a patch file to force the device to start application after reset.
please download by this link :
https://drive.google.com/open?id=0ByqJaZSFoV7Hb190d1l4UjNzb28

and program by command line tools. Open command line and write:



:: power by Agatha Kuan 20170419

.\nrfjprog.exe --family NRF52 --eraseall
.\nrfjprog.exe --family NRF52 --program %your_softdevice_name%
.\nrfjprog.exe --family NRF52 --program %your_application_name%
.\nrfjprog.exe --family NRF52 --program %your_bootloader_name%
.\nrfjprog.exe --family NRF52 --program patch.hex
.\nrfjprog.exe --family NRF52 --reset

Note:
1.the patch.hex file can only use on nRF52832 SDK11
2.these 2 solution does not work after reset or DFU
3.if you want to use the first solution on nRF51, please see  here
(it is 0x3FC00 for nrf51)



Reference:

https://devzone.nordicsemi.com/question/22056/combining-sd-dfu-and-application-hex-and-programming/
https://devzone.nordicsemi.com/question/37880/initdat-file-for-dfu-gets-crc-error-correct-order-nrf-beacon-help/
https://devzone.nordicsemi.com/question/70738/bootloader-does-not-start-application/

2017年2月8日 星期三

J-Link as UART- Logging Output for nRF51/52

I use SEGGER RTT to replace UART logging .

STEP 1.
Download J-Link RTT Viewer and install it.
Download the RTT library files from SEGGER site and unzip them into a folder of your BLE SDK:

nRF51_SDK_10.0.0\nRF51_SDK_10.0.0\components\RTT










STEP 2.
Add the folder to  your project.

STEP 3.
add the RTT folder path to config your Project

STEP 4. my example code for main function printf


#include "SEGGER_RTT.h"

//SEGGER Delay
static void _Delay(int period) {
  int i = 100000*period;
  do { ; } while (i--);
}

int main(void)
{
    uint32_t err_code;
    bool erase_bonds;

    // Initialize.
    timers_init();
    buttons_leds_init(&erase_bonds);
    ble_stack_init();
    device_manager_init(erase_bonds);
    gap_params_init();
    advertising_init();
    services_init();
    conn_params_init();

    // Start execution.
    application_timers_start();
    err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
    APP_ERROR_CHECK(err_code);

    // Enter main loop.
    for (;;)
    {
        power_manage();
    SEGGER_RTT_SetTerminal(0);
    SEGGER_RTT_WriteString(0, "Hello from SEGGER!\r\n");
    _Delay(100);
   
    SEGGER_RTT_TerminalOut(1,"terminalOut 1 \r\n");
    _Delay(100);
   
   int terminalNumber=2;
    SEGGER_RTT_SetTerminal(terminalNumber);
    SEGGER_RTT_printf(0, "terminal = %u \r\n",terminalNumber);
    _Delay(100);
   
    SEGGER_RTT_WriteString(0, "terminal 2\r\n");
    _Delay(100);
   
    SEGGER_RTT_TerminalOut(1,"terminalOut from 1 \r\n");
    _Delay(100);    
    }
}
then rebuild.

 If nothing is configured, all data is sent to Terminal 0.

The Teminal to output all following via Write(), WriteString() or printf() can be set with SEGGER_RTT_SetTerminal() .

Output of only one string via a specific Terminal can be done with SEGGER_RTT_TerminalOut(). I could set the parameter to specify which terminal would be the output target.

STEP 5. Open J-Link RTT Viewer

While I want 2 threads( maybe one is main thread, the other one is  interrupt thread) to print in the same terminal, the output message might be disorder or  tattered.

First, config your channel

press "OK".
press File-> connect


the main function output will be like :

STEP 6. my example code for button interrupt printf

add the following code demonstrating a button interrupt

//Add SEGGER_RTT
#include "SEGGER_RTT.h"

void bsp_event_handler(bsp_event_t event)
{
    uint32_t err_code;
    switch (event)
    {
        case BSP_EVENT_SLEEP:
            sleep_mode_enter();
            break;

        case BSP_EVENT_DISCONNECT:
            err_code = sd_ble_gap_disconnect(m_conn_handle,
                       BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            if (err_code != NRF_ERROR_INVALID_STATE)
            {
                APP_ERROR_CHECK(err_code);
            }
            break;

        case BSP_EVENT_WHITELIST_OFF:
            err_code = ble_advertising_restart_without_whitelist();
            if (err_code != NRF_ERROR_INVALID_STATE)
            {
                APP_ERROR_CHECK(err_code);
            }
            break;
 
// add button interrupt      
 case BSP_EVENT_KEY_0:
     break;       

        default:
            break;
    }
}


// add button interrupt handler
static void button_event_handler(uint8_t pin_no, uint8_t button_action)
{
    uint32_t err_code;

    switch (pin_no)
    {
        case BSP_BUTTON_0:
  if(0 != button_action)
  {       
   SEGGER_RTT_TerminalOut(3,"BUTTON ACTION \r\n"); 
   button_action = 1; 
  } 
        
  if(1 == button_action)
  {
   LEDS_ON(BSP_LED_1_MASK);
     
   SEGGER_RTT_TerminalOut(3,"BUTTON on \r\n");
   break;
  }
  else
  {    
   LEDS_OFF(BSP_LED_1_MASK); 
    
   SEGGER_RTT_TerminalOut(3,"BUTTON off \r\n");
   break;
  }
    
   
        default:
            APP_ERROR_HANDLER(pin_no);
            break;
    }
}



/**@brief Function for initializing buttons and leds.
 *
 * @param[out] p_erase_bonds  Will be true if the clear bonding button was pressed to wake the application up.
 */
static void buttons_leds_init(bool * p_erase_bonds)
{
    bsp_event_t startup_event;

#if (0)
    uint32_t err_code = bsp_init(BSP_INIT_LED | BSP_INIT_BUTTONS,
                                 APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), 
                                 bsp_event_handler);
#else
  uint32_t err_code = bsp_init(BSP_INIT_NONE,
                                 APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), 
                                 bsp_event_handler);
 static app_button_cfg_t buttons[] =
    {
        {BSP_BUTTON_0, false, BUTTON_PULL, button_event_handler}
    };

    err_code = app_button_init(buttons, sizeof(buttons) / sizeof(buttons[0]),
                               APP_TIMER_TICKS(300, APP_TIMER_PRESCALER));
    APP_ERROR_CHECK(err_code);
 app_button_enable();
#endif
    APP_ERROR_CHECK(err_code);

    err_code = bsp_btn_ble_init(NULL, &startup_event);
    APP_ERROR_CHECK(err_code);

    *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA);
}
then rebuild.


Now,  press button 0 (for pin define, please open  pca100xx.h)













the output will be

























You can try what will happen if 2 threads(interrupt and main thread) print in same terminal.

while you press down, it shows "BUTTON ACTION" and "BUTTON on".
And while you release the button, it shows "BUTTON off"




APPENDIX.
0.For more example, please check the following web site:

https://www.segger.com/jlink-rtt.html#RTT_Example_Code
http://blog.blecentral.com/2015/06/22/rtt_debugging/
http://dl.btc.pl/kamami_wa/j_link_edu_segger.pdf


1.J-Link RTT has function to input , just like what UART logging has done.

2017年1月10日 星期二

nRF5x: How to Set Version Checking in the DFU Zip File

This article is to provide a security solution for DFU.

My application is based on Heart rate Service 
( s110 with dfu in Nordic SDK)

C:\..\..\..\nRF51_SDK_10.0.0\nRF51_SDK_10.0.0_dc26b5e\examples\ble_peripheral\ble_app_hrs

the firmware can check if the DFU .zip file is authorized by manifest.json 
(in.zip ,usually called INIT file in Nordic Website).

The PASSWORD could be set in the zip file parameters while packed, and you should modify the bootloader code, to consist with the parameters. 



step 0.my environment:

  • nRF51822DK xxac
  • softdevice s110 8.0.0
  • Keil_v5 
  • nrf SDK 10.0.0
  • bootloader_s110      <--will be changed by me in step 2
  • master control panel 3.10.0.8

  • Android 6.0.1
  • windows 7
  • nrf Connect (for android) <--download the latest version
  • Samsung J7 prime

step 1.set password in .zip file

There are 3 options to place my password: device version, device type and application version.



To simply my example, , I adopt the "application version" as my password column at first .

(About how to adopt device revision or device type ,see Note.3)


password :0x03734301

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 0xFFFF --sd-req 0x4f,0x5a,0x64 app_version_password.zip


add the .zip file to smartphone

step 2.customized your bootloader

copy bootloader folder  from:
C:\\nRF51_SDK_10.0.0\nRF51_SDK_10.0.0_dc26b5e\examples\dfu\bootloader

rename it as bootloader_with_password

copy dfu_init_template.c from nRF51_SDK_10.0.0_dc26b5e\components\libraries\bootloader_dfu 

modift the project setting to depend on the dfu_init_template.c 
which be inside folder bootloader_with_password, instead of the one in components\libraries\bootloader_dfu .

In dfu_init_template.c

#include "dfu_init.h"
#include <stdint.h>
#include <string.h>
#include "dfu_types.h"
#include "nrf_error.h"
#include "crc16.h"

#define DFU_INIT_PACKET_EXT_LENGTH_MIN      2                       
#define DFU_INIT_PACKET_EXT_LENGTH_MAX      10                      

static uint8_t m_extended_packet[DFU_INIT_PACKET_EXT_LENGTH_MAX];   
static uint8_t m_extended_packet_length;                            

#define APP_VERSION_PASSWORD                  ((uint32_t)0x03734301)

uint32_t dfu_init_prevalidate(uint8_t * p_init_data, uint32_t init_data_len)
{
    uint32_t i = 0;
    
    
    if (init_data_len < sizeof(dfu_init_packet_t))
    {
        return NRF_ERROR_INVALID_LENGTH;
    }

    // Current template uses clear text data so they can be casted for pre-check.
    dfu_init_packet_t * p_init_packet = (dfu_init_packet_t *)p_init_data;

    m_extended_packet_length = ((uint32_t)p_init_data + init_data_len) -
                   (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len];
    
    if (m_extended_packet_length < DFU_INIT_PACKET_EXT_LENGTH_MIN)
    {
        return NRF_ERROR_INVALID_LENGTH;
    }

    if (((uint32_t)p_init_data + init_data_len) < 
        (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len])
    {
        return NRF_ERROR_INVALID_LENGTH;
    }

    memcpy(m_extended_packet,
           &p_init_packet->softdevice[p_init_packet->softdevice_len],
           m_extended_packet_length);

/** [DFU init application version] */
    // To support application versioning, this check should be updated.
    // This template allows for any application to be installed. However, 
    // customers can place a revision number at the bottom of the application 
    // to be verified by the bootloader. This can be done at a location 
    // relative to the application, for example the application start 
    // address + 0x0100.
/** [DFU init application version] */
    
    // First check to verify the image to be transfered matches the device type.
    // If no Device type is present in DFU_DEVICE_INFO then any image will be accepted.
  

    /*agatha: set application version check*/ 
    if ((p_init_packet->app_version!= APP_VERSION_PASSWORD))
    {
        return NRF_ERROR_INVALID_DATA;
    }/*app_version check*/ 
    
    //First check 
    if ((DFU_DEVICE_INFO->device_type != DFU_DEVICE_TYPE_EMPTY) &&
   (p_init_packet->device_type != DFU_DEVICE_INFO->device_type))
    {
        return NRF_ERROR_INVALID_DATA;
    }
   
    // Second check to verify the image to be transfered matches the device revision.
    
    if ((DFU_DEVICE_INFO->device_rev != DFU_DEVICE_REVISION_EMPTY) &&
        (p_init_packet->device_rev != DFU_DEVICE_INFO->device_rev))
    {
        return NRF_ERROR_INVALID_DATA;
    }

    // Third check: Check the array of supported SoftDevices by this application.
    // If the installed SoftDevice does not match any SoftDevice in the list then an
    // error is returned.
    while (i < p_init_packet->softdevice_len)
    {
        if (p_init_packet->softdevice[i] == DFU_SOFTDEVICE_ANY ||
            p_init_packet->softdevice[i++] == SOFTDEVICE_INFORMATION->firmware_id)
        {
            return NRF_SUCCESS;
        }
    }
    
    // No matching SoftDevice found - Return NRF_ERROR_INVALID_DATA.
    return NRF_ERROR_INVALID_DATA;
}


uint32_t dfu_init_postvalidate(uint8_t * p_image, uint32_t image_len)
{
    uint16_t image_crc;
    uint16_t received_crc;
    
    
    // calculate CRC from active block.
    image_crc = crc16_compute(p_image, image_len, NULL);

    // Decode the received CRC from extended data.    
    received_crc = uint16_decode((uint8_t *)&m_extended_packet[0]);

    // Compare the received and calculated CRC.
    if (image_crc != received_crc)
    {
        return NRF_ERROR_INVALID_DATA;
    }

    return NRF_SUCCESS;
}

The structure  p_init_packet  would pass the password from INIT file, in here, modify the code to check its value consisted with true password .

Rebuild bootloader.hex and application. Then use nRFgo Studio to program:
  • softdevice
  • application
  • bootloader (be changed by you)




step 3.test 


open Nordic nRF connecter app

connect your board

press the DFU button above

press "Distribution packet" and select the .zip file we made in STEP 1
start DFU
After DFU , reset the board

if you add the zip file that the parameter  --application-version is incorrect, your smartphone will soon disconnect to device .


Additional notes:


0. This implement check the number of application version to achieve "set a password to avoid unknown .zip file ".


1. In my experience,Samsung smartphone has a higher probability to DFU failed.

(whether using which smartphone app)

2. nRF connect ,the app I used , has some problem in DFU mode and connect the device after DFU. 


3. I suggest not to check dev_type and dev_rev,but use application version ,because application version isn't used in normal bootloader.


However, if you want to check device type, that is feasible :


add in bootloader
/*agatha: how to check  device type*/
#define DEV_TYPE_PASSWORD  0x1618  
  
   if ((p_init_packet->device_type != DEV_TYPE_PASSWORD))
    {
        return NRF_ERROR_INVALID_DATA;
    }
  
#if (0)
   
    if ((DFU_DEVICE_INFO->device_type != DFU_DEVICE_TYPE_EMPTY) &&
   (p_init_packet->device_type != DFU_DEVICE_INFO->device_type))
    {
        return NRF_ERROR_INVALID_DATA;
    }
#endif   
and make the .zip file


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 0x4f,0x5a,0x64 app_version_password.zip

you could adopt device_type and/or device_revision as further checking.


3. This method above can work in SDK11 , when the chip is nRF52 with softdevice s132.
But that can not be adopted to SDK12  and s232, s332. 



2017年1月6日 星期五

nRF51822 mergeHex 三合一量產用燒錄檔案

nRF51822 用 nRFgo studio 燒寫的時候需要三個 hex檔案,
(按燒寫順序)

  1. softdevice
  2. application
  3. bootloader


此三個hex可合併為一,用於量產較為方便,本篇介紹三合一hex檔案的製作方法


  • 官方流程(優點,可自定或製作批次檔,缺點,首次進行很慢)請依照step 進行下去
  • 簡化流程(優點,單次很快缺點無法自動化)請跳到 STEP 6


環境:

  • nRF51822EK
  • nRF Tools 7.5.2
  • Master Control Panel 3.10.0.4
  • Keil version 5
  • Windows 7
  • nordic SDK 10.0.0
  • softdevice s110 8.0.0
  • bootloader : dual bank s110 bootloader


STEP 0.找到

  1. sotfdevice 默認檔名 s110_nrf51_8.0.0_softdevice.hex
  2. application 默認路徑: project\pca10028\_build 選擇 .hex


STEP 1. 編譯 bootloader

bootloader 在SDK裡面並沒有.hex 要自己編

默認路徑:
C:\..\..\..\..\nRF51_SDK_10.0.0\nRF51_SDK_10.0.0_dc26b5e\examples\dfu\bootloader
點選dual_bank_ble_s110項目檔,按下build

在 \_build 產生 .hex檔案



STEP 2.找到此三 .hex 檔案,修改檔名為:

  • s110_SD.hex
  • bootloader.hex
  • application.hex

此動作是為了防止下一步搞錯,可自定名稱



STEP 3.將三個檔案複製到

C:\Program Files (x86)\Nordic Semiconductor\nrf5x\bin

確認該資料夾中有另三個檔案:


  • app_valid_setting_apply.hex
  • mergehex.exe
  • nrfproj.exe


如果沒有或不在資料夾內,請集中到此資料夾,或是重新安裝 nRF Tools


STEP 4. 開啟 command line 輸入


1
2
cd C:\Program Files (x86)\Nordic Semiconductor\nrf5x\bin  
mergehex -m s110_SD.hex bootloader.hex -o SD_BL.hex -m SD_BL.hex application.hex -o SD_BL_APP.hex -m SD_BL_APP.hex app_valid_setting_apply.hex -o SD_BL_APP_Settings.hex

資料夾中產生:

SD_BL_APP_Setting.hex 

是為三合一檔案


STEP 5 驗證三合一檔案是否正常運行

再次打開 command line 
(同時確認連上nRF51822與 JLink)

輸入:

1
2
cd  C:\Program Files (x86)\Nordic Semiconductor\nrf5x\bin
nrfjprog.exe --eraseall  --program SD_BL_APP_Settings.hex --pinreset

執行完畢後將蕊片重新上電,並確認各服務是否正常運行

_____________________________________________________________________________


STEP 6 快速方法: NRF_ISP

請點選下載 訊聯電子 NRF_ISP 軟件後安裝


  1. 按下browse 分別選擇 appliacation / softdevice/bootloader 檔案 
  2. 點選 merge
  3. 勾選 on/off  按下 configure
  4. 勾選 Downloader1 
  5. 按下 program


以上動作相當於取代nRFGO 分別燒寫的功能,
然後此時到\NRF_ISP 資料夾內,

點選 \_build 資料夾 內有一個最後產生的 hex檔案
即為三合一 hex

(更多資訊請洽訊聯電子,此軟件非nordic官方發布)


2017年1月5日 星期四

nRF51822 空中升級 .zip壓縮/製作

nRF51822 支援固件空中升級(下稱OTA)服務,本篇說明如何製作升級用 .zip 檔案

(關於什麼是DFU服務、如何添加,請參考以下)

第一次實作,請按照step慢慢做完
加速方法,請直接跳到 Step 5

環境:

  • 蕊片:nRF51822EK
  • bootloader: dual bank s110 bootloader
  • softdevice: s110
  • windows 7
  • IDE: Keil version 5
  • Master control panel (for PC) 3.10.0.14
  • nRF Tools 7.5.2
Step 0.被升級的裝置,必須燒寫與softdevice相同版本的 bootloader
如本次我使用的是 S110 

Step 1.在IDE裡面 build application,之後  \_build 會產生 .axf檔案
默認名稱: nrf51422_xxac_s110.axf 
(此名稱可在 project>options 裡面修改)

Step 2.將此 .axf檔案複製到 Keil_v5\ARM\ARMCC\bin資料夾
確認這個資料夾裡面有一個fromelf.exe

(如果是使用 Keil_v4 相同的執行檔是 hex2bin.exe)

Step 3. 打開Command line,輸入:

1
2
cd C:\Keil_v5\ARM\ARMCC\bin\      ::進入資料夾
fromelf.exe nRF51422_xxac_s110.axf --output nRF51422_xxac_s110.bin --bin --output nRF51422_xxac_s110.bin --bin

nRF51422_xxac_s110.axf 即 .axf 檔的名稱
nRF51422_xxac_s110.bin 可替換成其他自訂名稱

隨後資料夾內會產生 nRF51422_xxac_s110.bin檔案
複製此檔案到
C:\Program Files (x86)\Nordic Semiconductor\Master Control Panel\3.10.0.14\nrf\

step 4.此資料夾內有 nrfutil.exe,如果沒有,請重新安裝Master Control Panel 最新版本 
打開Command line, 輸入:

1
2
3
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 0xFFFFFFFF --dev-revision 0xFFFF --dev-type 0xFFFF --sd-req 0x4f,0x5a,0x64 nRF51422_xxac_s110.zip


(命令行中的參數,與 .zip內的 INIT file有關,可參閱)

Step 5.製作批次檔加速此流程

請先找到
  • nrf51422_xxac_s110.axf
  • fromelf.exe
  • nrfutil.exe
相對位置
Step 6.建立空白txt檔案

輸入:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
::分別可改為自定的檔案名稱
:: " "內輸入相對位置
SET zipName=nrf51422_xxac_s110
SET binName=nrf51422_xxac_s110

"C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe" ..\pca10028\s110\arm5\_build\nrf51422_xxac_s110.axf  --output %binName%.bin --bin --output %binName%.bin --bin
"C:\Program Files (x86)\Nordic Semiconductor\Master Control Panel\3.10.0.14\nrf\nrfutil.exe" dfu genpkg --application %binName%.bin --application-version 0xFFFFFFFF --dev-revision 0xFFFF --dev-type 0xFFFF --sd-req 0x4f,0x5a,0x64 %zipName%.zip

SET zipName=
SET binName=
::歸零

Step 7.將txt的副檔名 改為.bat


Step 8. 將.zip 檔案放入DFU主機
(這邊介紹的是用Android市場  nrf Connect 應用程式升級,
另外MacBook 有支援用 Master Control Panel (for Mac) 進行空中升級,此不作討論)

點選 DFU 選項
Select File > .zip file> 選擇檔案