Which protocol to update firmware for bw16 by MCU?

I can flash new bin file to bw16 by Image Tool on Window.
But now, I need update bin file from MCU ( Cortex-M4). So I need to know the serial protocol between Image Tool and BW16. Is it Xmodem? Based on the example uart_firmware_update ?
Xmodem start frame by 0x01.
But when flash bin file from Image Tool, I capture by logic analyzer in channel TX. I see frames that don’t start with 0x01 like the picture:
I also tried the following:

  • Put bw16 into download mode
  • Erase flash
  • Use teraterm for send bin file according to Xmodem protocol
    But failed.
    So can someone help me get more information about the protocol used to flash bw16 ?
    Thank very much,

Hi @Truong_Giang

The image upload process is not exactly XModem, but may be similar in some ways.

The process can be generally divided into a few steps:

  1. Establish contact and change communication speed
  2. Send flashloader binary
  3. Re-establish contact and change communication speed
  4. Send km0_boot_all.bin km4_boot_all.bin km0_km4_image2.bin

Establish Contact and change communication speed

  • BW16 sends 0x15 (NAK) repeatedly at 115200 baud rate while in image download mode
  • Image tool replies with 0x05 (ENQ) followed by a byte that indicates a higher UART speed
  • E.g. 0x18 for 1500000, 0x17 for 1444400
  • BW16 replies with 0x06 (ACK) to agree to change speed
  • both sides change UART speed
  • Image tool tests new UART speed with 0x07, BW16 replies with 0x06

Send binary

  • The flashloader binary needs to be sent first, as this contains code that enables BW16 to receive UART firmware binary and write it to flash
  • binary data is send in blocks of 1024 bytes
  • each block contains these fields:
    • one byte header 0x02
    • one byte block number starting with 0x01
    • one byte bit-inverse of block number
    • four byte flash address of following binary data
    • 1024 bytes of binary data
    • one byte checksum
  • BW16 replies with 0x06 for each correctly received block

After sending the flashloader, BW16 reboots into the flashloader code. Communication is re-established and the three firmware binaries are sent in the same method. You may choose to only send one of the three firmware binaries, and it will only update that part.

There are a few other minor details that I may have missed out, but the overall flow is still there.

I suggest you look at this code. It can be used to upload images, and will also provide detailed information on what it is sending and receiving. Comparing the source code with logic analyzer captures should give you a better idea of what the upload process is doing.

1 Like

Hi @wyy
Please clarify one thing. I there was set speed other than 115200 what speed should be after EOT after flash loader image loading?

after flashloader, the chip reboots, thus the speed used is back to the default 115200, and a higher speed needs to be changed to again.

1 Like

Hi @wyy
Thanks you very much.

In my case I see that after uploading flasher, reset and speed setup it data transfer works fine. Last telegram is accepted and chip answer with ACK. In second after it begins to send NAC with same interval. Is it good?

When I can reset the chip to start new firmware?


I would still suggest using a logic analyzer to capture a regular image upload and comparing the process with the linked code.

The program_spi_flash function has all the steps of the upload process, including some parts that I missed out in the previous post, such as erasing flash regions after sending the flashloader binary, and verifying flash checksums after sending the three firmware binaries.

Hi @wyy
Is erase before flashing mandatory or it is recommended?


It is required, otherwise it results in an invalid image in the flash.

1 Like

Hi @wyy
Thank you very much.
I hope it is last question in this topic.

bool erase_block(FD fd, int addr,long size) {

    printf("erase addr: 0x%07X, size:%ldKB.\n", addr,size/1024);

    cmd_buff[0] = 0x17;
    *(uint32_t *)&cmd_buff[1] = addr;
    *(uint32_t *)&cmd_buff[4] = (size+4095)/4096;

    if(!send_cmd(fd,cmd_buff,6)) return false;
    return true;

I this code I that command size is 9 as 1 byte i command, next four bytes are address and the last four bytes are blocks count.
But there is a command send send_cmd(fd,cmd_buff,6) accepts six bytes. Where is mistake?


to me, it looks like since the flash address to erase always starts with 0x08 (e.g. 0x08002000, 0x08004000, 0x08006000), the protocol simplified it by removing the first byte 0x08. The size to erase also has two bytes removed, probably for a similar reason.

Using uint32_t is just how the original author of the code choose to implement this requirement.

Hi @wyy
Thank you.
So. We have next layout:
0 1 2 3 4 5
| cmd | address w/o 08 | blocks cnt |

Is it correct?

yes, that is correct