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

How to merge serial and BLE DFU without flow control?

We wanted to implement both BLE and serial DFU on nRF52832 without serial flow control. The main procedure is as follows:

  1. Use the Nordic BLE DFU example as a start point

  2. Add nrf_serial_dfu.c to your project

  3. Add other files related to serial DFU. For example, nrf_drv_uart.c. You can check the Nordic serial DFU example to find the required files.

  4. Edit sdk_config.h for these added files.

  5. Change the dfu transport variable name as below to ensure BLE and serial have different names.

    A) In nrf_serial_dfu.c DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const dfu_serial_trans)

    B) In nrf_ble_dfu.c DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const dfu_ble_trans)

  6. Change the serial port settings if no flow control is required.

uint32_t serial_dfu_transport_init(void) { uint32_t err_code;

#if 0 leds_init(); #endif

...
nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG;

uart_config.pseltxd            = TX_PIN_NUMBER;
uart_config.pselrxd            = RX_PIN_NUMBER;

#if 0
uart_config.pselcts = CTS_PIN_NUMBER; uart_config.pselrts = RTS_PIN_NUMBER; uart_config.hwfc = NRF_UART_HWFC_ENABLED; #else uart_config.pselcts = NRF_UART_PSEL_DISCONNECTED; uart_config.pselrts = NRF_UART_PSEL_DISCONNECTED; uart_config.hwfc = NRF_UART_HWFC_DISABLED; uart_config.baudrate = NRF_UART_BAUDRATE_9600; #endif ... }

  1. Fix the potential issue of passing a local buffer to nrf_drv_uart_tx(). It causes update to fail when BLE is combined. Use a static buffer "static uint8_t encoded_response[]".

static void response_send( serial_dfu_t * p_dfu, serial_dfu_response_t * p_response) { uint8_t response_buffer[MAX_RESPONSE_SIZE]; static uint8_t encoded_response[MAX_RESPONSE_SIZE*2 + 1]; uint32_t encoded_response_length;

...

// encode into slip
(void)slip_encode(encoded_response, response_buffer, index, &encoded_response_length);

// send
(void)nrf_drv_uart_tx(&p_dfu->uart_instance, encoded_response, encoded_response_length);

}

  1. Remove all codes related to the LEDs and buttons if not used in your project

  2. To work with your DFU boot loader, you need to change the nrfutil source code dfu_transport_serial.py as below, and then build them. The instruction refers to nrfutil link.

class DfuTransportSerial(DfuTransport):

DEFAULT_BAUD_RATE = 9600
DEFAULT_FLOW_CONTROL = False 
  1. Below is an example of serial update from my modified nrfutil software. The update progress indication is added, so it's easy to see the progress.

Using board at serial port: COM11

Sending Application image.

Opened COM11: Baud Rate=9600, Flow Control=N

Sending init packet...

Sending firmware file...

Offset= 0, Packet Length=4096, Firmware Length=124980. 3.28% complete

Offset= 4096, Packet Length=4096, Firmware Length=124980. 6.55% complete

Offset= 8192, Packet Length=4096, Firmware Length=124980. 9.83% complete

Offset= 12288, Packet Length=4096, Firmware Length=124980. 13.11% complete

Offset= 16384, Packet Length=4096, Firmware Length=124980. 16.39% complete

Offset= 20480, Packet Length=4096, Firmware Length=124980. 19.66% complete

Offset= 24576, Packet Length=4096, Firmware Length=124980. 22.94% complete

Offset= 28672, Packet Length=4096, Firmware Length=124980. 26.22% complete

Offset= 32768, Packet Length=4096, Firmware Length=124980. 29.50% complete

Offset= 36864, Packet Length=4096, Firmware Length=124980. 32.77% complete

Offset= 40960, Packet Length=4096, Firmware Length=124980. 36.05% complete

Offset= 45056, Packet Length=4096, Firmware Length=124980. 39.33% complete

Offset= 49152, Packet Length=4096, Firmware Length=124980. 42.61% complete

Offset= 53248, Packet Length=4096, Firmware Length=124980. 45.88% complete

Offset= 57344, Packet Length=4096, Firmware Length=124980. 49.16% complete

Offset= 61440, Packet Length=4096, Firmware Length=124980. 52.44% complete

Offset= 65536, Packet Length=4096, Firmware Length=124980. 55.71% complete

Offset= 69632, Packet Length=4096, Firmware Length=124980. 58.99% complete

Offset= 73728, Packet Length=4096, Firmware Length=124980. 62.27% complete

Offset= 77824, Packet Length=4096, Firmware Length=124980. 65.55% complete

Offset= 81920, Packet Length=4096, Firmware Length=124980. 68.82% complete

Offset= 86016, Packet Length=4096, Firmware Length=124980. 72.10% complete

Offset= 90112, Packet Length=4096, Firmware Length=124980. 75.38% complete

Offset= 94208, Packet Length=4096, Firmware Length=124980. 78.66% complete

Offset= 98304, Packet Length=4096, Firmware Length=124980. 81.93% complete

Offset=102400, Packet Length=4096, Firmware Length=124980. 85.21% complete

Offset=106496, Packet Length=4096, Firmware Length=124980. 88.49% complete

Offset=110592, Packet Length=4096, Firmware Length=124980. 91.77% complete

Offset=114688, Packet Length=4096, Firmware Length=124980. 95.04% complete

Offset=118784, Packet Length=4096, Firmware Length=124980. 98.32% complete

Offset=122880, Packet Length=2100, Firmware Length=124980. 100.00% complete

Image sent in 135.644999981s

Device programmed.

Now my question is how to increase the baud rate? As seen above, the baud rate is set to 9600. From my test, the firmware update may fail if it's more than 9600. When it is traced during
update, the uart hardware overrun occurred if it failed. This indicates that the uart interrupt is disabled more than one serial character interval by some other higher priority interrupt handler.

In my project, Easy DMA is enabled for uart(UARTE is used). But unfortunately one byte buffer is used for DMA, so it doesn't help solve this issue. However if more than one byte buffer is used, we must monitor the DMA receive timeout, for example using a MCU timer. I tried to use UART RXTO interrupt, but it didn't work as I expected.
Your ideas are very appreciated.

Related