Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Firmware Update over UART Interface

Hello,

Background: I have a custom board that contains nRF52832 module and exposes UART pins (RX, TX, RTS, CTS). I have developed an application using nRF5 SDK v17.0.2. The application does not use any so -called SoftDevice.

Objective: I want to develop a mechanism to update the application firmware of on the nRF52832 module over the UART interface from another micro-controller.

Seeking Help: After searching through the SDK and the forum, it looks like I have to use libraries under Bootloader and DFU modules But I am still confused which components to use and in what order. On the nRF52832 module, do I need to program, as part of my application, routines to receive and process DFU commands/data packets. I am also using the same UART port to exchange application data (from sensors attached sensors )  with the other micro-controller.

I would appreciate any help that can get me started on the right path to achieve the objective.

Parents
  • Hi Jatala, 

    I would suggest you to get started with our uart bootloader located inside examples\dfu folder. There are 2 options, secured DFU and open DFU. It depends on your need you can choose to use one. 

    The DFU example allow you to do DFU via UART from either PC (nrfutil.exe on PC) or from external MCU (official example is not included). 

    I have made an example of doing DFU from one MCU to another MCU here.

    I would suggest to get familiar with these resource first, so that you can do DFU from one MCU to another MCU. 

    What's missing here is to combine that to your application. What you want to achieve may be accomplished by implementing a command to switch from your application to the bootloader and from there the bootloader can receive the image and update the application. The limitation is that your application will be stopped when the bootloader receiving the image. But the advantage is that you only need to switch to the bootloader, and don't need to modify anything. 
    Another option is to implement background DFU where your application will receive the image and then only switch to the bootloader to swap the image. This would require some implement on your application code to receive image that we don't have example code for now. 

    Note that the bootloader, when not to be used with the softdevice would need the MBR to be flashed to run. Please refer to the bootloader documentation. 

  • Hi Hung,

    Thanks for the insight. I will go though the sources that you have pointed out and will come back to this thread if stumbled upon any issue.

    The first approach seems simpler to implement. "...implementing a command to switch from your application to the bootloader and from there the bootloader can receive the image and update the application", so in this case, the bootloader will be responsible to receive the application over the UART. But how the configuration and registration of the UART will be handled. I suppose it has to done from my application, right?

  • Please try debugging the bootloader, you can put a breakpoint in dfu_enter_check() in nrf_bootloader.c It's where the bootloader check if it would need to enter DFU mode or not. 

    You may need to compile the bootloader in debug mode (no optimization) to be able to put breakpoint and step in the code of the bootloader. 

    I assume that you have tested the functionality of the bootloader (DFU update) and also know how to create bootloader settting etc. 

    Please also try testing that you can enter the bootloader by holding a button when you reset. 

  • - When I set the optimization level to zero, for debugging the bootloader,  I get the following errors:

    ../SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: error: .text is too large to fit in FLASH memory segment
    ../SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: error: .dfu_trans is too large to fit in FLASH memory segment
    ../SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: error: .nrf_balloc is too large to fit in FLASH memory segment
    ../SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: error: .fs_data is too large to fit in FLASH memory segment
    ../SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: error: .rodata is too large to fit in FLASH memory segment
    ../SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: error: .data is too large to fit in FLASH memory segment
    ../SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: error: section .tdata overlaps absolute placed section .mbr_params_page

    For  optimization level > 0, some break points show message no code for breakpoint. Anyway I noticed that the bootloader repeatedly enters and exits the main() function. Not sure if it is normal behavior?

    - From your tutorial, I know how to create the bootloader setttings file. But I must say I still struggling to comprehend the complete sequence to flash the bootloader, and the application.

  • Please try to follow my steps and made sure  you can do a normal DFU udpate. 

    When you change optimization level to 0, the size of the bootloader getting bigger. So it won't fit into the current setting of the flash size and location. 
    You would need to move it down in flash and extend the size of the bootloader. Please have a look at the project configuration to increase the allocated flash for bootloader. 

  • Thanks for the insight. Please bear with me, this is my first attempt at this kind of task.  By normal DFU update, do you mean without using the security keys?

  • I meant just do a DFU update, without trying to implement switching to DFU from application. 

Reply Children
  • That is clear. To 'increase the allocated flash for bootloader', I need to change of the start address of the bootloader, but I do not see such a parameter in the project flash_placement.xml file.  I also do not see any option in the SEGGER project options.  Any idea how to go about it.

  • Hi Jatala, 

    You can follow what we have in the _debug bootloader. For example here you have the project setting with 100kB of flash reserved for the bootloader: 

  • Hi Hung,

    Thanks. I tested the bootloader in debug mode and apparently the bootloader throws an error from the UART port, please see attached call-stack trace where I have marked the code lines in respective functions where failure is occurring.  

    I noticed that in sdk_config.h both UARTE and UART drivers are enabled, not sure if this is causing the error.

  • Hi, 

    Please show the log you have on RTT viewer. Basically we need to know which function throwed the error and which error code. 

    Please try to test the secure bootloader debug project with no modification and list the steps you did for testing. 

  • I tested the secure bootloader debug project. It seems to work fine. But the bootloader program crashes when I change the UART pin assignment in pca10040.h  as follows.

    Original Changed
    #define RX_PIN_NUMBER  8
    #define TX_PIN_NUMBER  6
    #define CTS_PIN_NUMBER 7
    #define RTS_PIN_NUMBER 5
    #define RX_PIN_NUMBER  11
    #define TX_PIN_NUMBER  5
    #define CTS_PIN_NUMBER 7
    #define RTS_PIN_NUMBER 6

    Following is the RTT viewer log:

    <info> app: Inside main
    00> <debug> app: In nrf_bootloader_init
    00> <debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> <debug> nrf_dfu_settings: Using settings page.
    00> <debug> nrf_dfu_settings: Copying forbidden parts from backup page.
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    00> <debug> app: Enter nrf_bootloader_fw_activate
    00> <info> app: No firmware to activate.
    00> <info> app: Boot validation failed. No valid app to boot.
    00> <debug> app: DFU mode because app is not valid.
    00> <info> nrf_bootloader_wdt: WDT is not enabled
    00> <debug> app: in weak nrf_dfu_init_user
    00> <debug> app: timer_stop (0x20000024)
    00> <debug> app: timer_activate (0x20000024)
    00> <info> app: Entering DFU mode.
    00> <debug> app: Initializing transports (found: 1)
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init()
    00> <debug> nrf_dfu_serial_uart: serial_dfu_transport_init() completed
    00> <debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
    00> <debug> app: Enter main loop
    00> <error> app: Received an error: 0x00000004!

    I did a few more tests where I changed  RX_PIN_NUMBER to 8, 9, 10, 11, 12, 13. The same error occurs for pin 9, 10, 11 but not for the others. My challenge is in my board the pin 11 is used as RX and is interfaced with another board (cannot change this pin assignment). So either the same pin number is used for some other purpose in the bootloader program, although I do not see that in the code. Or some special configuration has to be applied to configure this pin as UART_RX.

Related