3. Protocol¶
This document describes the communications protocol for the bootypic repository
There are two primary layers that this document is concerned with, framing and command. The framing layer is primarily concerned with delimiting the packet boundaries along with ensuring data integrity of the packet using a fletcher16 checksum. The command layer is concerned with interpreting the payload of the frame so that the software layer may respond accordingly.
3.1. Framing¶
All frames have a Start of Frame (SOF) byte at the beginning and an End of Frame (EOF) byte at the end. The bytes between the SOF and EOF comprise the data being transmitted. Any byte that corresponds to the SOF, EOF, or Escape (ESC) characters will be escaped and XORed so that they do not interfere with the overall transmission process. The last two bytes of the data bytes will be the fletcher16 checksum of the payload.
3.1.1. Escaping¶
Any byte between the SOF and EOF that corresponds to SOF, EOF, or ESC will be replaced by two bytes, the first will be the ESC byte and the second will be the data byte XORed with the XOR value.
3.1.2. Structure¶
The structure, without escaping, is as follows:
[SOF] [dat0] [data1] [data2] [...] [dataX] [F16(0:7)] [F16(15:8)] [EOF]
Note that if F16 bytes correspond to special characters, they will be properly escaped.
If, for instance, data4 corresponded to the SOF byte, the stream would be modified as follows:
[data2] [data3] [ESC] [ESC_XOR ^ data4] [data5]
In this way, it is possible to give up a small amount of transmission efficiency in order to be able to transmit the entire range of data.
3.1.3. Special Characters¶
The special characters are the SOF, EOF, ESC, and ESC_XOR. These values are ONLY to be used as part of the framing protocol. All payload bytes that correspond to these values are to be escaped:
[SOF] 0xf7
[EOF] 0x7f
[ESC] 0xf6
[ESC_XOR] 0x20
3.1.4. Behavior¶
If a F16 value is correct, then the packet is forwarded up to the next software layer. If it is incorrect, then the packet is discarded.
3.1.5. Fletcher 16 Verification¶
Each frame is verified using a fletcher16 algorithm on all data bytes. The Python implementation of the fletcher16 algorithm is as follows:
sum1 = 0
sum2 = 0
for i, b in enumerate(data):
sum1 += b
sum1 &= 0xff # Results wrapped at 16 bits
sum2 += sum1
sum2 &= 0xff
return sum1, sum2
A similar implementation in C is as follows:
uint16_t fletcher16(uint8_t* data, uint16_t length){
uint16_t sum1 = 0, sum2 = 0, checksum;
uint16_t i = 0;
while(i < length){
sum1 = (sum1 + (uint16_t)data[i]) & 0xff;
sum2 = (sum2 + sum1) & 0xff;
i++;
}
checksum = (sum2 << 8) | sum1;
return checksum;
}
3.2. Commands¶
The command layer may have multiple versions, which will be saved to the microcontroller at compile time.
3.2.1. Command Structure¶
A typical command packet, stripped of framing information:
[reserve0] [reserve1] [CMD] [payload0] [payload1] [...] [payloadX]
The first two bytes are reserved for future use. They may contain any type of data the user prefers. For the remainder of this document, these reserved bytes will be ignored.
CMD refers to a 1-byte command. The command will determine how the remainder of the payload is interpreted. In some cases, there may be no additional bytes after the command, such as in the CMD_START_APP command.
3.2.2. Behavior¶
The PC will typically be the server and the microcontroller will simply respond to the commands as a directed client. Many commands have no required response, such as CMD_ERASE_PAGE. Others that require a response will simply embed the same command into the structure of the response.
When strings are being passed, they will be passed as ASCII bytes and transmitted with the null
string terminator \0
. These are represented in the commands as a string with quotes.:
representation: "my str\0"
transmitted: [0x6d] [0x79] [0x20] [0x73] [0x74] [0x72] [0x00]
3.3. Command Sets¶
In order to increase flexibility across devices, command version sets are created
which will allow the server software to determine the command set that may be
utilized with the particular device and bootloader variant. At this time, there
is only one command set called 0.1
, which includes all commands as listed below.
All of the below commands will be included as a subset of future command sets for
backward compatibility.
3.4. Supported Commands¶
3.4.1. Read Platform¶
Character: 0x00 Command Sets: 0.1
The CMD_READ_PLATFORM
command instructs the microcontroller to return a string containing
the platform, which usually corresponds to a microcontroller part number:
master: [CMD_READ_PLATFORM]
response: [CMD_READ_PLATFORM] "dspic33ep32mc204\0"
3.4.2. Read Version¶
Character: 0x01 Command Sets: 0.1
The CMD_READ_VERSION
command instructs the microcontroller to return a string containing
the instruction set that it supports:
master: [CMD_READ_VERSION]
response: [CMD_READ_VERSION] "0.1\0"
3.4.3. Read Row Length¶
Character: 0x02 Command Sets: 0.1
The CMD_READ_ROW_LENGTH
command instructs the microcontroller to return the smallest row length
that can be programmed at one time:
master: [CMD_READ_ROW_LENGTH]
response: [CMD_READ_ROW_LENGTH] [length(7:0)] [length(15:8)]
3.4.4. Read Page Length¶
Character: 0x03 Command Sets: 0.1
The CMD_READ_PAGE_LENGTH
command instructs the microcontroller to return the page erasure size
in instructions:
master: [CMD_READ_PAGE_LENGTH]
response: [CMD_READ_PAGE_LENGTH] [length(7:0)] [length(15:8)]
3.4.5. Read Max Program Memory Length¶
Character: 0x04 Command Sets: 0.1
The CMD_READ_PROG_LENGTH
command instructs the microcontroller to return the program length,
which is the maximum address that may be programmed to:
master: [CMD_READ_PROG_LENGTH]
response: [CMD_READ_PROG_LENGTH] [length(7:0)] [length(15:8)] [length(23:16)] [length(31:24)]
3.4.6. Read Max Program Size¶
Character: 0x05 Command Sets: 0.1
The CMD_READ_MAX_PROG_SIZE
command instructs the microcontroller to return the maximum programming
size that it will support in instructions:
master: [CMD_READ_MAX_PROG_SIZE]
response: [CMD_READ_MAX_PROG_SIZE] [length(7:0)] [length(15:8)]
3.4.7. Read App Start Address¶
Character: 0x06 Command Sets: 0.1
The CMD_READ_APP_START_ADDRESS
command instructs the microcontroller to return the starting address
of the application. This will usually be 0x1000. This will be utilized for checking application integrity
during the verification stage.:
master: [CMD_READ_MAX_PROG_SIZE]
response: [CMD_READ_MAX_PROG_SIZE] [address(7:0)] [address(15:8)]
3.4.8. Erase Page¶
Character: 0x10 Command Sets: 0.1
The CMD_ERASE_PAGE
command instructs the microcontroller erase a page of flash memore starting
at the provided address.:
master: [CMD_ERASE_PAGE] [address(7:0)] [address(15:8)] [address(23:16)] [address(31:24)]
response: -
3.4.9. Read Address¶
Character: 0x20 Command Sets: 0.1
The CMD_READ_ADDRESS
command instructs the microcontroller read a single value from flash memory
and to return that value.:
master: [CMD_READ_ADDRESS] [address(7:0)] [address(15:8)] [address(23:16)] [address(31:24)]
response: [CMD_READ_ADDRESS] [address(7:0)] [address(15:8)] [address(23:16)] [address(31:24)]
[value(7:0)] [value(15:8)] [value(23:16)] [value(31:24)]
3.4.10. Read Max¶
Character: 0x21 Command Sets: 0.1
The CMD_READ_MAX
command instructs the microcontroller read the maximum number of values from
flash memory and return them as an array of values. This allows for much more efficient reading
of memory:
master: [CMD_READ_ADDRESS] [address(7:0)] [address(15:8)] [address(23:16)] [address(31:24)]
response: [CMD_READ_ADDRESS] [address(7:0)] [address(15:8)] [address(23:16)] [address(31:24)]
[value0(7:0)] [value0(15:8)] [value0(23:16)] [value0(31:24)]
[value1(7:0)] [value1(15:8)] [value1(23:16)] [value1(31:24)]
[...]
[valueX(7:0)] [valueX(15:8)] [valueX(23:16)] [valueX(31:24)]
3.4.11. Write Row¶
Character: 0x30 Command Sets: 0.1
The CMD_WRITE_ROW
command instructs the microcontroller to write an entire row of data, as defined
by the microcontroller datasheet, starting at the address. In many cases, a row consists of only 2
instructions, so it may not be very efficient.:
master: [CMD_WRITE_ROW] [address(7:0)] [address(15:8)] [address(23:16)] [address(31:24)]
[value0(7:0)] [value0(15:8)] [value0(23:16)] [value0(31:24)]
[value1(7:0)] [value1(15:8)] [value1(23:16)] [value1(31:24)]
[...]
[valueX(7:0)] [valueX(15:8)] [valueX(23:16)] [valueX(31:24)]
response: -
3.4.12. Write Max¶
Character: 0x31 Command Sets: 0.1
The CMD_WRITE_ROW
command instructs the microcontroller to write an entire row of data, as defined
by the return value of READ_MAX_PROG_SIZE
, starting at the address. This is usually a much more
efficient method of writing.:
master: [CMD_WRITE_ROW] [address(7:0)] [address(15:8)] [address(23:16)] [address(31:24)]
[value0(7:0)] [value0(15:8)] [value0(23:16)] [value0(31:24)]
[value1(7:0)] [value1(15:8)] [value1(23:16)] [value1(31:24)]
[...]
[valueX(7:0)] [valueX(15:8)] [valueX(23:16)] [valueX(31:24)]
response: -
3.4.13. Start Application¶
Character: 0x40 Command Sets: 0.1
The CMD_WRITE_ROW
command instructs the microcontroller to start the application. Note that the
bootloader will no longer respond after the application is started.:
master: [CMD_START_APP]
response: -