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

Download firmware over BLE for another MCU

Hi,

I've a custom board which has NRF51822 SOC and STM32 SOC. These two are connected over UART. In past I've successfully performed DFU OTA (BLE) for nrf51822 MCU, and now I'd like to use the nrf51 to download firmware over BLE for this other SOC, which is connected over UART. In nutshell, I'd like to

  1. Download firmware image (firmware for another SOC in plain binary format) over BLE using nrf51.
  2. Transfer the firmware image to it's intended host (STM32)

What is the most simplest method to achieve this ? I understand that, in order to send and receive large file (bigger than the maximum payload), I would need to do some segmentation at the sender side (central) and reassembly at the receive side (peripheral). Is there a sample example on such large file transfer? The sample bootloader example provided by Nordic could be a starting point, but at the moment, it seems like an overkill for this particular requirement. I'm looking for something more simpler. Ideally, I'd like to just use some custom service and Bluetooth characteristic to transfer the binary image. Also, At the application/central side, I'd like to use Nordic's Master Control Panel for Android phone or something similar.

Please advice.

Update: 22.07.2016

For the time being, I need to use the same Nordic MCP app for android to achieve OTA for the other MCU that I have on my custom board. Recall that the target MCU is connected to NRF51 over UART interface. As I'm using the same MCP app, I made some changes in my bluetooth application on the periperhal side for NRF51822 and also in the Nordic provided Bootloader for the peripheral. No changes are done in Nordic MCP application.

My current problem is, how do I capture the data packet and send it to STM over UART. The format that I use for control and data transfer between NRF51 and STM over UART is as follows:

Sample control instruction format to STM:

$NRF,CONTROL_CMD,*8-bit XOR checksum of entire packet

$NRF,1,*57 <-- telling STM application to switch to bootloader mode

Similarly I plan to achieve a data packet, something like this:

$NRF,DATA_CMD,DATA_LEN,*8-bit XOR checksum of entire packet

$NRF,2,20,blahblahblahblahblah,*57

The receiver (STM bootloader) will parse these messages. Seeing a data instruction (represented by 2 here), STM will find the length of data (20) and hence will create a buffer of 20 bytes and will program the internal main flash memory of STM. It will then return fail or pass status back to Nordic bootloader. Note that the STM bootloader is seperate piece of code that I wrote and occupies a part of the main flash memory of STM.

dfu_dual_bank.c::dfu_data_pkt_handle() seem like a correct place to capture the data.

case DFU_STATE_RX_DATA_PKT:
     data_length = p_packet->params.data_packet.packet_length * sizeof(uint32_t);
     uint32_t *p_data = (uint32_t *)p_packet->params.data_packet.p_data_packet;

So, I have both the data buffer and the packet size, but how do I copy data from this 32 bit data stream and create a buffer filled with $NRF,2,20,[payload]*[cksum]. The following does not work :(

enum {
    DATA = 3,
    NOK,
};

char buff[256];
char *p;
// clear the buffer
strcpy(buff, "");

sprintf(buff, "$NRF,%d,%d,", DATA, data_length);

// searching for last occurance of ','
p = strrchr(buff, ',');

// advance one position, after the ',' character
p++;
// fill the buffer with the data.
// XXX: p_data is 32 bit pointer, will this work ?
memcpy(p, (char *)p_data, data_length);

// append '*'
*(p + data_length) = '*';

// Terminate with '\0' to use string library function (strlen) later 
*(p + data_length + 1) = '\0';

char checksum = 0;

// 8 bit xor
for (int i = 0; i < strlen(buff); ++i)
{
    checksum ^= buff[i];·
}
char cksum[10];
sprintf(cksum, "%d", checksum);

// concatenate the checksum
strcat(buff, cksum);
// At this point, send the entire frame over UART

With this approach, on the sender (NRF51) side, I see (listening on the Tx pin of Nrf by using a serial terminal program and serial wire):

$NRF,3,20,99

Something went wrong; the terminating * is missing (before 99) and there is no data (after 20 and comma, it should be filled with data)

Update: 25.07.2016

Made some changes for serial communication between the two MCUs (Nordic and STM) and I'm now able to capture more data packets, however I'm still NOT able to capture the entire firmware. In routine dfu_transport_ble.c::app_data_process(), we have:

uint32_t length = p_evt->evt.ble_dfu_pkt_write.len;
uint8_t * p_data_packet = p_evt->evt.ble_dfu_pkt_write.p_data;

So, all I do now,

strcpy(uart_send_buff, "");
sprintf(uart_send_buff, "$NRF,3,%d,", length);
p = strrchr(uart_send_buff, ',');   
p++; // advance one position, after the ',' character
memcpy(p, p_data_packet, length); // copy data packet
// send data packet - uart_put(uart_send_buff);

With the above packet formation for serial transfer, I see the following on serial console (Note that the display mode is Ascii, so I guess that there might be some characters that the serial console could not display. The data length shows that the packet received over BLE was of 20 bytes in length (verified in BLE sniffer capture as well), but as you can see below, most of the packet contents here seem to be empty. I think, i'm making some mistake in packet formation for serial transfer. Your suggestions would be very helpful to debug this further.

$NRF,3,20,^M
$NRF,3,20,^M
$NRF,3,20,^M
$NRF,3,20,<95>«^M
$NRF,3,20,^EQ^M
$NRF,3,20,^EQ^M
$NRF,3,20,^EQ^M
$NRF,3,20,^EQ^M
$NRF,3,20,^EQ^M
$NRF,3,20,ù³^M
$NRF,3,20,^M
$NRF,3,20,^Ah»»»^N^KJ<91>B^EÑ^KH^KI^A`^KH^LI^M
$NRF,3,20,^A`^LH<80>G^LH^M
$NRF,3,20,þç^M
$NRF,3,20,^A^M
$NRF,3,20,0µ^KF^AF^M
$NRF,3,20,^EÓ^]F<95>@I^[%F<95>@@^Y^UFR^^^M
$NRF,3,20,ñÜ0½pµ^M

Final Update: 28.07.2016

Finally, I was able to perform OTA over BLE for the other MCU (This MCU is connected to NRF51 over UART, so I send the firmware image over BLE to NRF51, which sends each chunk of firmware image over UART to the targeted MCU) that I have on my custom board. I implemented a simple flow control mechanism and made improvements in packet parsing at the receiver end and life is good once again :)

Parents
  • Thank you for swift response. I'm also looking at the nordic bootloader example for the peripheral side implementation. Using a hex file instead of a binary would require additional parsing either at the central or at the peripheral. Luckily ARM buildtool already provides the conversion (ARM binary .axf to plain binary, .bin) utility called nrftool. I had use this same utility while developing a bootloader that would allow over the air update of STM32 SOC firmware over GSM/GPRS network.

Reply
  • Thank you for swift response. I'm also looking at the nordic bootloader example for the peripheral side implementation. Using a hex file instead of a binary would require additional parsing either at the central or at the peripheral. Luckily ARM buildtool already provides the conversion (ARM binary .axf to plain binary, .bin) utility called nrftool. I had use this same utility while developing a bootloader that would allow over the air update of STM32 SOC firmware over GSM/GPRS network.

Children
Related