nrf52832 OTA over ESB based on SDK17.1.0

Hi everyone:    I developed an application based on ESB wireless communication protocol ofr the nRF52832, and I would like to perform an OTA DFU with it.    Do you know any example of some over the air FW upgrade of nRF52832 chip via ESB protocol.

    SDK is 17.1.0.

Best regards,

Lurn.

Parents
  • I only found examples of ble and uart in the dfu/secure_bootloader folder, Which one should I use or how should I modify it to adapt my program.

  • Hello,

    It is correct that you will only find BLE and UART in our samples, but I know that several customers have ported this to SPI, so if you need it over ESB, then that should also be possible. The transport layers in the bootloader for the nRF5 SDK are on purpose quite separated from the rest of the libraries, to make it easier to change the transport layer, or to add your own transport layer.

    But you do need to implement it yourself. Also note that we do not have the "DFU Master" as an official part of our SDK. We have tools like nrfutil (open source) or nRF Connect for Desktop (not open source), and applications for mobile phones that are open source (but mobile phones doesn't have ESB). However, there is an unofficial implementation (not properly tested. You can use it, but on your own "risk"), which you can find here. I have not tested these myself, but you can give it a go. I suggest you test out the UART master, in combination with the uart bootloader, and then you can port both to ESB once you are up and running.

    Best regards,

    Edvin

  • OK, I was update successfully one time(I think), after I modify the TX pin state, and then, I never success.

    The last log shows:

    # SEGGER J-Link RTT Viewer V7.00a Terminal Log File
    # Compiled: 15:35:52 on Apr 16 2021
    # Logging started @ 21 Apr 2023 18:28:08
    00> <debug> nrf_dfu_serial: Received ping 1
    00> 
    00> <info> nrf_dfu_serial_uart: Allocated buffer 20000558
    00> 
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_PING
    00> 
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> 
    00> <debug> nrf_dfu_serial: Sending Response: [0x9, 0x1]
    00> 
    00> <debug> app: Shutting down transports (found: 1)
    00> 
    00> <info> nrf_dfu_serial_uart: Allocated buffer 20000558
    00> 
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_CREATE (command)
    00> 
    00> <debug> app: timer_stop (0x20000020)
    00> 
    00> <debug> app: timer_activate (0x20000020)
    00> 
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> 
    00> <debug> nrf_dfu_serial: Sending Response: [0x1, 0x1]
    00> 
    00> <info> nrf_dfu_serial_uart: Allocated buffer 200005DC
    00> 
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (command)
    00> 
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> 
    00> <info> nrf_dfu_serial_uart: Allocated buffer 20000558
    00> 
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (command)
    00> 
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> 
    00> <info> nrf_dfu_serial_uart: Allocated buffer 200005DC
    00> 
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (command)
    00> 
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> 
    00> <info> nrf_dfu_serial_uart: Allocated buffer 200005DC
    00> 
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_CRC_GET (command)
    00> 
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> 
    00> <debug> nrf_dfu_serial: Sending Response: [0x3, 0x1]
    00> 
    00> <info> nrf_dfu_serial_uart: Allocated buffer 200005DC
    00> 
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_EXECUTE (command)
    00> 
    00> <debug> nrf_dfu_validation: PB: Init packet data len: 63
    00> 
    00> <debug> app: Enter nrf_dfu_cache_prepare()
    00> 
    00> <debug> app: required_size: 0x9E60.
    00> 
    00> <debug> app: single_bank: false.
    00> 
    00> <debug> app: keep_app: true.
    00> 
    00> <debug> app: keep_softdevice: false.
    00> 
    00> <debug> app: SD_PRESENT: false.
    00> 
    00> <debug> app: Bank contents:
    00> 
    00> <debug> app: Bank 0 code: 0x01: Size: 0x39A0
    00> 
    00> <debug> app: Bank 1 code: 0x00: Size: 0x0
    00> 
    00> <debug> app: pass: 0.
    00> 
    00> <debug> app: cache_address: 0x5000.
    00> 
    00> <debug> app: cache_too_small: false.
    00> 
    00> <debug> app: keep_firmware: true.
    00> 
    00> <debug> app: delete_more: false.
    00> 
    00> <debug> nrf_dfu_validation: Write address set to 0x00005000
    00> 
    00> <debug> nrf_dfu_settings: Writing settings...
    00> 
    00> <debug> nrf_dfu_settings: Erasing old settings at: 0x0007F000
    00> 
    00> <debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x0007F000, len=1 pages), queue usage: 0
    00> 
    00> <debug> nrf_dfu_flash: Flash erase success: addr=0x0007F000, pending 0
    00> 
    00> <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x0007F000, src=0x20000848, len=896 bytes), queue usage: 1
    00> 
    00> <debug> nrf_dfu_flash: Flash write success: addr=0x0007F000, pending 0
    00> 
    00> <info> nrf_dfu_settings: Backing up settings page to address 0x7E000.
    00> 
    00> <debug> nrf_dfu_settings: Writing settings...
    00> 
    00> <debug> nrf_dfu_settings: Erasing old settings at: 0x0007E000
    00> 
    00> <debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x0007E000, len=1 pages), queue usage: 1
    00> 
    00> <debug> nrf_dfu_flash: Flash erase success: addr=0x0007E000, pending 0
    00> 
    00> <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x0007E000, src=0x20000BC8, len=896 bytes), queue usage: 1
    00> 
    00> <debug> nrf_dfu_flash: Flash write success: addr=0x0007E000, pending 0
    00> 
    00> <debug> nrf_dfu_req_handler: Writing valid init command to flash.
    00> 
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> 
    00> <debug> nrf_dfu_serial: Sending Response: [0x4, 0x1]
    00> 
    00> <info> nrf_dfu_serial_uart: Allocated buffer 200005DC
    00> 
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_CREATE (data)
    00> 
    00> <debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x00005000, len=1 pages), queue usage: 1
    00> 
    00> <debug> nrf_dfu_flash: Flash erase success: addr=0x00005000, pending 0
    00> 
    00> <debug> nrf_dfu_req_handler: Creating object with size: 4096. Offset: 0x00000000, CRC: 0x00000000
    00> 
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> 
    00> <debug> nrf_dfu_serial: Sending Response: [0x1, 0x1]
    00> 
    00> <info> nrf_dfu_serial_uart: Allocated buffer 20000558
    00> 
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (data)
    00> 
    00> <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x00005000, src=0x200005E0, len=64 bytes), queue usage: 1
    00> 
    00> <debug> nrf_dfu_flash: Flash write success: addr=0x00005000, pending 0
    00> 
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> 
    00> <info> nrf_dfu_serial_uart: Allocated buffer 200005DC
    00> 
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (data)
    00> 
    00> <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x00005040, src=0x2000055C, len=64 bytes), queue usage: 1
    00> 
    00> <debug> nrf_dfu_flash: Flash write success: addr=0x00005040, pending 0
    00> 
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> 
    00> <info> nrf_dfu_serial_uart: Allocated buffer 20000558
    00> 
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (data)
    00> 
    00> <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x00005080, src=0x200005E0, len=64 bytes), queue usage: 1
    00> 
    00> <debug> nrf_dfu_flash: Flash write success: addr=0x00005080, pending 0
    00> 
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> 
    00> <info> nrf_dfu_serial_uart: Allocated buffer 200005DC
    00> 
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (data)
    00> 
    00> <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x000050C0, src=0x2000055C, len=64 bytes), queue usage: 1
    00> 
    00> <debug> nrf_dfu_flash: Flash write success: addr=0x000050C0, pending 0
    00> 
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> 
    00> <info> nrf_dfu_serial_uart: Allocated buffer 20000558
    00> 
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (data)
    00> 
    00> <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x00005100, src=0x200005E0, len=64 bytes), queue usage: 1
    00> 
    00> <debug> nrf_dfu_flash: Flash write success: addr=0x00005100, pending 0
    00> 
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> 
    00> <info> nrf_dfu_serial_uart: Allocated buffer 200005DC
    00> 
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (data)
    00> 
    00> <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x00005140, src=0x2000055C, len=64 bytes), queue usage: 1
    00> 
    00> <debug> nrf_dfu_flash: Flash write success: addr=0x00005140, pending 0
    00> 
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> 
    00> <error> app: Received an error: 0x00000004!
    00> 
    
    # Logging stopped @ 21 Apr 2023 18:31:39
    

    And I still get the error “ Hash verification failed. ”

  • Hi Edvin,

    First of all thank you for taking so much time to help me with this problem.

    Now I can update successfully although I always get something wrong, but I think the question is on my hardware and the connect way.

    I'll start porting it to other devices to test.

    Thanks again for your help

    Best regards,

    Lurn

  • Sorry for the late reply. I have been out of office. 

    I am sorry, but I am a bit confused.

    Did you figure out the length problem? If the length of the .bin / .dat file is not n*4 bytes, you can try to open it in a binary editor (e.g. Hex Editor Neo), and add 0xFF's until it is n*4 bytes long before you convert it to a hex file. 

    And on your failing tests, are you running this on 2x DKs, or do you have some custom HW? Are you using UART Flow Control (on both sides) of the UART connection?

    Regarding the Error 4 it is a bit difficult to say, because the error handler in the bootloader is very limited. You can try to set a breakpoint there, and look at the callstack to see if you can figure out what triggered the error handler to be triggered. It should be an APP_ERROR_CHECK() or an assert of some sort.

    Best regards,

    Edvin

  • Hi Edvin,

    I used a custom board, and the UART connection method is jump wire. So the connection will be a bit unstable.

    After I ported the code to an Android device(No more jump wire connections), it works fine.

    And I only change the MAX_ACTUAL_PAYLOAD to MTU_SIZE/2 as you do.

    On the Android device I tested 5 times, they are all successful, althougt the final package isn't 64 bytes. and I checked it that only the final package isn't n*4 bytes.

    00> <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x0000AA40, src=0x20000558, len=64 bytes), queue usage: 1
    00> <debug> nrf_dfu_flash: Flash write success: addr=0x0000AA40, pending 0
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
    00> <info> nrf_dfu_serial_uart: Allocated buffer 20000554
    00> <debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (data)
    00> <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x0000AA80, src=0x200005DC, len=52 bytes), queue usage: 1
    00> <debug> nrf_dfu_flash: Flash write success: addr=0x0000AA80, pending 0
    00> <debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1

    Update:

    If you want I can show you the code on android, but it is not much different with DFU master, just modified the underlying code of the serial port communication.

    Best regards,

    Lurn

  • 52=n*4, where n = 13, so that is fine. 

    If you want to skip this part, you can adjust the bootloader to pad the remaining 1, 2 or 3 bytes with 0xFF. It is probably better than just asserting. 

    I discussed the MTU_SIZE/2 fix with the colleague who wrote the DFU_Master application a few years ago, and we figured out that the reason faulted now is a change in the bootloader. Before, it would gather up several packets, and do a big write containing more packets. The default behavior now is that it writes to flash after every package, which is why it failed.

    We also looked at the buffer size, and found the reasoning behind why it was divided by 2. 

    If you look in the bootloader, you will find:

    #define RX_BUF_SIZE                     (64) //to get 64bytes payload
    #define OPCODE_OFFSET                   (sizeof(uint32_t) - NRF_SERIAL_OPCODE_SIZE)
    #define DATA_OFFSET                     (OPCODE_OFFSET + NRF_SERIAL_OPCODE_SIZE)
    #define UART_SLIP_MTU                   (2 * (RX_BUF_SIZE + 1) + 1)

    So the reason behind this is that the "SLIP" encoding will sometimes have to add an extra byte in cases where the actual payload byte is the same as the END or ESC character in the SLIP library. 

    Hence, it needs to double the buffer size. On the last line there, you can see that we take the RX_BUF_SIZE+1, which would be the actual buffer + one byte (I don't remember. It could be the byte indicating the length or something). Then double it, in case all bytes are escape or end characters (which in theory could happen, but probably won't happen). Then you add 1 in the end to account for the actual end byte of the buffer. So you end up with a buffer size of: (2 * (64 +1) + 1 ) = 2*65 + 1 = 130 + 1 = 131 bytes. 

    So in order to do the exact opposite of this, you can use:

    MAX_ACTUAL_PAYLOAD = (((MAX_MTU - 1) / 2) -1) 

    which will be 64. So if the payload buffer is maximum 64 bytes, it should always be safe:

    #define MTU_SIZE 131
    #define MAX_ACTUAL_PAYLOAD (((MTU_SIZE - 1)/2) - 1) // = 64 bytes.

    Note that MTU_SIZE is also increased to 131, which corresponds to the actual MTU size of the UART buffer in the bootloader from SDK17.1.0.

    Best regards,

    Edvin

Reply
  • 52=n*4, where n = 13, so that is fine. 

    If you want to skip this part, you can adjust the bootloader to pad the remaining 1, 2 or 3 bytes with 0xFF. It is probably better than just asserting. 

    I discussed the MTU_SIZE/2 fix with the colleague who wrote the DFU_Master application a few years ago, and we figured out that the reason faulted now is a change in the bootloader. Before, it would gather up several packets, and do a big write containing more packets. The default behavior now is that it writes to flash after every package, which is why it failed.

    We also looked at the buffer size, and found the reasoning behind why it was divided by 2. 

    If you look in the bootloader, you will find:

    #define RX_BUF_SIZE                     (64) //to get 64bytes payload
    #define OPCODE_OFFSET                   (sizeof(uint32_t) - NRF_SERIAL_OPCODE_SIZE)
    #define DATA_OFFSET                     (OPCODE_OFFSET + NRF_SERIAL_OPCODE_SIZE)
    #define UART_SLIP_MTU                   (2 * (RX_BUF_SIZE + 1) + 1)

    So the reason behind this is that the "SLIP" encoding will sometimes have to add an extra byte in cases where the actual payload byte is the same as the END or ESC character in the SLIP library. 

    Hence, it needs to double the buffer size. On the last line there, you can see that we take the RX_BUF_SIZE+1, which would be the actual buffer + one byte (I don't remember. It could be the byte indicating the length or something). Then double it, in case all bytes are escape or end characters (which in theory could happen, but probably won't happen). Then you add 1 in the end to account for the actual end byte of the buffer. So you end up with a buffer size of: (2 * (64 +1) + 1 ) = 2*65 + 1 = 130 + 1 = 131 bytes. 

    So in order to do the exact opposite of this, you can use:

    MAX_ACTUAL_PAYLOAD = (((MAX_MTU - 1) / 2) -1) 

    which will be 64. So if the payload buffer is maximum 64 bytes, it should always be safe:

    #define MTU_SIZE 131
    #define MAX_ACTUAL_PAYLOAD (((MTU_SIZE - 1)/2) - 1) // = 64 bytes.

    Note that MTU_SIZE is also increased to 131, which corresponds to the actual MTU size of the UART buffer in the bootloader from SDK17.1.0.

    Best regards,

    Edvin

Children
  • Sorry, I didn't do the calculations just saw that the last packet was not 64 bytes.

    And yes I saw the code here,

    nrf_drv_uart_tx(&p_dfu->uart_instance, encoded_slip_packet, encoded_slip_packet_length+1);

    So as you said, I should modify the MTU_SIZE to 131 it will be batter than now.

    I will try this.

    Update:

    After change the values, I can update successfully too. But for now I can't see different whit it, but as you said, I can find that in my bootloader.  

    ...

    #define UART_SLIP_MTU                   (2 * (RX_BUF_SIZE + 1) + 1)

    ...

    so I think the value you suggested should be better than before.

    Thanks a lot.

    Best regards,

    Lurn

Related