This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Generating Production Image without DFU OTA

Due to time pressure, I'm starting this thread based on an existing ticket: https://devzone.nordicsemi.com/f/nordic-q-a/51423/firmware-on-custom-board-application-bootloader, so that I can get as many eyes on this as possible.

My setup:

  • Board: Custom PCB based on NRF52840
  • SDK: 15.2.0
  • Development Environment: Segger Embedded Studio

I am trying to assemble an image that can be flashed on the custom board at the factory. I have followed the Nordic tutorials, and I've gotten to the point where I can assemble an image (Application, Bootloader (+bootloader settings) and Softdevice). The problem is the device does not boot up.

Here's the situation:

  1. The custom board does not yet have a BLE antenna, so we cant do BLE DFU, yet
  2. All UARTS have been used up, so we can't do DFU via UART either
  3. The only viable path for now is to program the image using nrfjprog.

Questions:

  1. Any insights on why the device does not boot up?
  2. Regarding the private/public key aspects of the process, I understand the public key is linked with the bootloader project. How does one link the private key with the bootloader settings, if possible?
  3. Is there a way to bypass the key validation, because, again, right now we can't do DFU.
  4. There is a chance the issue might be the same as this: https://devzone.nordicsemi.com/f/nordic-q-a/19068/uploading-application-and-bootloader-application-not-starting.How do I do this in SDK 15.2.0?

Any and all insights are appreciated!

Thanks a mil,

Tim

Parents
  • Hello Tim,

     

    Any insights on why the device does not boot up?

     Probably something wrong with the bootloader settings (not present, or not using the correct key).

     

    Regarding the private/public key aspects of the process, I understand the public key is linked with the bootloader project. How does one link the private key with the bootloader settings, if possible?

     Yes. You must sign the bootloader settings with the private key. Please see the example nrfutil command here. The only thing that is missing is the private.key. It should look something like this:

    nrfutil settings generate --family NRF52840 --application app.hex --application-version 3 --bootloader-version 2 --bl-settings-version 1 --key-file private.key settings.hex

    (assuming that the private key is located in the same folder as you run cmd from.

     

    Is there a way to bypass the key validation, because, again, right now we can't do DFU.

     Yes, but to be fair, I don't see why you want the bootloader if you can't use it at this point in time. But yes, there is a way to bypass the key check, by using the pca10056_ble_debug bootloader instead of the pca10056_ble bootloader. Please note that the debug bootloader uses more flash. You can also just sign the bootloader settings with the key. If you don't have the possibility to do DFU, this is just as good as using the debug bootloader, and in addition, it doesn't take up as much flash as the debug bootloader. 

     

    There is a chance the issue might be the same as this: https://devzone.nordicsemi.com/f/nordic-q-a/19068/uploading-application-and-bootloader-application-not-starting.How do I do this in SDK 15.2.0?

     I don't think it is related. Do you use the NFC pins for something else?

    When you generate the bootloader settings, and flash it with the application, the bootloader and the softdevice, then the application should start. If not, please give me a detailed description on how you performed it. Maybe it reveals some information on where the issue is. 

    But I suspect the only thing you are missing is the "--private-key private.key" in the command you use to generate the bootloader settings.

Reply
  • Hello Tim,

     

    Any insights on why the device does not boot up?

     Probably something wrong with the bootloader settings (not present, or not using the correct key).

     

    Regarding the private/public key aspects of the process, I understand the public key is linked with the bootloader project. How does one link the private key with the bootloader settings, if possible?

     Yes. You must sign the bootloader settings with the private key. Please see the example nrfutil command here. The only thing that is missing is the private.key. It should look something like this:

    nrfutil settings generate --family NRF52840 --application app.hex --application-version 3 --bootloader-version 2 --bl-settings-version 1 --key-file private.key settings.hex

    (assuming that the private key is located in the same folder as you run cmd from.

     

    Is there a way to bypass the key validation, because, again, right now we can't do DFU.

     Yes, but to be fair, I don't see why you want the bootloader if you can't use it at this point in time. But yes, there is a way to bypass the key check, by using the pca10056_ble_debug bootloader instead of the pca10056_ble bootloader. Please note that the debug bootloader uses more flash. You can also just sign the bootloader settings with the key. If you don't have the possibility to do DFU, this is just as good as using the debug bootloader, and in addition, it doesn't take up as much flash as the debug bootloader. 

     

    There is a chance the issue might be the same as this: https://devzone.nordicsemi.com/f/nordic-q-a/19068/uploading-application-and-bootloader-application-not-starting.How do I do this in SDK 15.2.0?

     I don't think it is related. Do you use the NFC pins for something else?

    When you generate the bootloader settings, and flash it with the application, the bootloader and the softdevice, then the application should start. If not, please give me a detailed description on how you performed it. Maybe it reveals some information on where the issue is. 

    But I suspect the only thing you are missing is the "--private-key private.key" in the command you use to generate the bootloader settings.

Children
  • Well, to start with, the entire process is scripted, as typing in all the commands manually can be quite tedious.

    Step 1: I start by generating the public and private keys:

    private_key_path="../path_to_private_key/private.key"
    public_key_file_path="../path_to_public_key/public_key.c"
    
    #Delete any existing keys before generating new ones
    echo "Deleting any existing keys.."
    rm -f $private_key_path
    rm -f $public_key_file_path
    echo "OK!"
    
    # Generate private key
    echo "Generating private key.."
    nrfutil keys generate $private_key_path
    echo "OK!"
    
    # Generate public key based on private key
    echo "Generating public key.."
    nrfutil keys display --key pk --format code $private_key_path --out_file $public_key_file_path
    echo "OK!"

    Both keys are generated in the same folder. I have linked that directory inside segger embedded studio so that everytime i generate a new pair of keys, I don't need to manually copy them all the time.

    Step2: Build the pca10056_ble bootloader project.

    Step 3: I use a script to assemble all the components in a single folder (MBR, BL, SD and App). The script merely copies them from their default destinations:

    #---------- Settings ----------------#
    # Application and Bootloader images (need to be built)
    application_path="../path_to_compiled_app/Exe/nordsense_wms_application_v2.hex"
    bootloader_path="../path_to_compiled_bootloader/secure_ble_s140_bootloader.hex"
    
    # Softdevice and MBR paths (exist as precompiled images in the Nordic SDK)
    softdevice_path="../sdk_15_2_0/components/softdevice/s140/hex/s140_nrf52_6.1.0_softdevice.hex"
    master_boot_record_path="../sdk_15_2_0/components/softdevice/mbr/nrf52840/hex/mbr_nrf52_2.3.0_mbr.hex"
    
    # Destination to copy the images to
    components_destination="../production/images"
    #-----------------------------------#
    
    # Copy master boot record
    echo "Fetching Master Boot Record (MBR) Image..."
    cp -p $master_boot_record_path $components_destination
    echo "OK!"
    
    # Copy Softdevice
    echo "Fetching Softdevice (SD) Image..."
    cp -p $softdevice_path $components_destination
    echo "OK!"
    
    # Copy Bootloader 
    echo "Fetching Bootloader Image..."
    cp -p $bootloader_path $components_destination
    echo "OK!"
    
    # Copy Application 
    echo "Fetching Application Image..."
    cp -p $application_path $components_destination
    echo "OK!"

    Step 4: Generate the bootloader settings:

    #---------- Settings ----------------#
    device_family="NRF52840"
    app_image_path="../path_to_compiled_app/application.hex"
    app_version="0"
    bl_version="0"
    bl_settings_version="1"
    key_file="../path_to_private_key/private.key"
    output_file="../production/images/ns_wms_bootloader_settings.hex"
    softdevice_file="../production/images/s140_nrf52_6.1.0_softdevice.hex"
    #-----------------------------------#
    
    #Delete any existing bootloader settings image
    rm -f $output_file
    nrfutil settings generate --family $device_family --application $app_image_path --application-version $app_version --bootloader-version $bl_version --bl-settings-version $bl_settings_version --softdevice $softdevice_file --key-file $key_file $output_file
    nrfutil settings display $output_file

    And finally step 5: assemble the images (now all images are in one folder):

    #---------- Settings ----------------#
    production_images_folder="../production/images"
    
    bl_image_path=$production_images_folder/secure_ble_s140_bootloader.hex
    bl_settings_path=$production_images_folder/bootloader_settings.hex
    app_path=$production_images_folder/nordsense_wms_application_v2.hex
    sd_path=$production_images_folder/s140_nrf52_6.1.0_softdevice.hex
    mbr_path=$production_images_folder/mbr_nrf52_2.3.0_mbr.hex
    
    merged_bl_path=$production_images_folder/m_wms_bootloader.hex
    merged_app_path=$production_images_folder/m_wms_application.hex
    production_image_path=$production_images_folder/m_wms_app_production_1_0_0.hex
    #-----------------------------------#
    
    echo "---------------------------------------------------------------"
    
    # Delete any existing images
    echo "Deleting existing images.."
    rm -f $production_images_folder/*.hex
    echo "OK!"
    
    # Fetch the production image components (Master Boot Record, Softdevice, Bootloader and Application image)
    echo "Fetching Production Image Components.."
    ./fetch_production_image_components.sh
    
    # Generate bootloader settings image
    echo "Generating Bootloader Setting image.."
    ./build_bootloader_settings.sh
    echo "OK!"
    
    # Merge bootloader and bootloader settings
    echo "Merging Bootloader and Bootloader Settings Images.."
    mergehex -m $bl_image_path $bl_settings_path -o $merged_bl_path
    echo "OK!"
    
    # Merge bootloader (+settings) and Application
    echo "Merging Updated Bootloader and Application Images.."
    mergehex -m $merged_bl_path $app_path -o $merged_app_path
    echo "OK!"

    I run these scripts from my "scripts" folder.

    I open the compiled hex using NRF connect programmer, and it looks good. All the components start at the right addresses (could you please verify that?):

    app_production_1_0_0.hex

    I feel like I've done everything right up till now (thanks for your help in the previous post). I still can't get the application to boot.

    A LED normally lights up when I'm debugging the code. I also expect the LED to light up when I flash the assembled images, but nothing happens.

    I also saw something a little weird (maybe it's nothing), but when I generated the bootloader settings and ran the command "nrfutil settings display" right after, the outputs are a little different, plus there's a warning: Bad access at 0x7F000: not enough data to read 4 contiguous bytes:

    Generated Bootloader DFU settings .hex file and stored it in: ../production/images/ns_wms_bootloader_settings.hex
    
    Bootloader DFU Settings:
    * File:                     ../production/images/ns_wms_bootloader_settings.hex
    * Family:                   NRF52840
    * Start Address:            0x000FF000
    * CRC:                      0x390CDFC7
    * Settings Version:         0x00000001 (1)
    * App Version:              0x00000000 (0)
    * Bootloader Version:       0x00000000 (0)
    * Bank Layout:              0x00000000
    * Current Bank:             0x00000000
    * Application Size:         0x0002AD34 (175412 bytes)
    * Application CRC:          0x2D2EC708
    * Bank0 Bank Code:          0x00000001
    * Softdevice Size:          0x00024E7C (151164 bytes)
    * Boot Validation CRC:      0x00000000
    * SD Boot Validation Type:  0x00000000 (0)
    * App Boot Validation Type: 0x00000000 (0)
    
    Bad access at 0x7F000: not enough data to read 4 contiguous bytes
    
    Bootloader DFU Settings:
    * File:                     ../production/images/ns_wms_bootloader_settings.hex
    * Family:                   NRF52840
    * Start Address:            0x000FE000
    * CRC:                      0x390CDFC7
    * Settings Version:         0x00000001 (1)
    * App Version:              0x00000000 (0)
    * Bootloader Version:       0x00000000 (0)
    * Bank Layout:              0x00000000
    * Current Bank:             0x00000000
    * Application Size:         0x0002AD34 (175412 bytes)
    * Application CRC:          0x2D2EC708
    * Bank0 Bank Code:          0x00000001
    * Softdevice Size:          0x00000000 (0 bytes)
    * Boot Validation CRC:      0x00000000
    * SD Boot Validation Type:  0x00000000 (0)
    * App Boot Validation Type: 0x00000000 (0)

    Any insights you have will be very much appreciated.

    Until then I'll try running the debug version of the bootloader.

    Thanks Edvin,

    Tim

  • Hello Tim,

    Is it possible to zip all 4 hex files and upload them here? The bootloader, application, SD and BL_settings that you have created?

    BR,

    Edvin

  • Thank you, Tim.

    I see the same output as you when I try to use "nrfutil settings display" but it still works. Please note that this message does not appear when I generate the settings. 

    So, if you don't see the application starting, can you describe how you determine that it doesn't start? It is the lack of the LED, right?

    Does the LED show up if you only program the SD + application (but not the bootloader or BL settings)?

    You still use Segger Embedded Studio (SES), right?

    Can you try to recompile your application without optimization (please let me know if you are not sure how to do this), and then try to repeat the procedure?

    Then try to open your application project in SES, and then press "Tools" -> "Attach Debugger". Set a breakpoint in the top of your main() function, and then reset the device. Does that breakpoint hit?

    Can you also try to enable logging in your application project, and see if anything pops up there?

    NB: When I program all your 4 .hex files, LED1 on my DK lights up. Does it do that on your side? What HW are you running on? Is it the nRF52840 DK? How do you program your files? nRF Connect programmer? I tried both this and nrfjprog, and when I program all 4 hex files, it turns on LED1. Do you program the hex files at the same time, or one at the time? (I did all 4 at once)

  • Thanks for your elaborate troubleshooting! Very much appreciated!

    Well, I have been using a custom board based on the NRF52840.

    I decided yesterday to take a step back and try a much simpler application (the blinky freertos example), and the NRF52840 DK. I repeated the exact steps I've been doing so far (I expected all 4 LEDS to be blinking in a certain pattern as soon as the programming was finished). Instead LED1 and LED2 just lights up.

    Funny enough I then tried using my own application image, but this time on the DK. It was the same result - LED1 and LED2 just lights up. This is definitely some kind of error, as my custom board LED is mapped to P0.20, and the LEDs on the DK are mapped to P0.13 - P0.16.

    Can you try building an image using the blinky freertos example? If you can get that to work, then perhaps you could share exactly how you did it. That could hopefully be a good start to figuring this out.

    To answer your questions:

    1. Yes, I use SES,
    2. Regarding optimization, I open the project options, choose the Configuration (Debug/Release), then go to Code Generation. Finally I set the optimization level to None. Can you confirm this is the proper way to do it?

    In the meantime, I'll try using the debug version of the bootloader.

Related