Skip to content

Commit

Permalink
add documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
mhils committed Feb 19, 2016
1 parent 91f3f83 commit b22f318
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 1 deletion.
89 changes: 88 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,89 @@
# flysky-updater
An cross-platform open source updater for the FlySky i6

A cross-platform open source command-line firmware updater for the FlySky i6.
Precompiled binaries for Windows and Linux can be found on the [releases page](https://github.com/mhils/flysky-updater/releases).

To my best understanding, it is not possible to accidentally brick the remote by flashing firmware; the initial bootloader is never overwritten.

Usage:

```
λ ./flysky-updater-win64.exe COM3 flyplus_beta.hex
0 B / 55.92 KB [--------------------------------------------] 0.00 %
27.25 KB / 55.92 KB [===================>------------------------] 48.73 % 4s
56.00 KB / 55.92 KB [============================================] 100.15 % 7s
Upload completed.
Success!
```

## Firmware Update Mode

If the remote does not start anymore, one can access the firmware update mode as follows:

![](https://maximilianhils.com/upload/2016-02/i6firmwaremodepic.jpg)


## Protocol details

The serial communication between computer and remote follows a simple protocol.
Messages sent by the computer are constructed as follows:
```
length | payload | checksum
```
Messages sent by the remote are simply prefixed with `0x55`:
```
0x55 | length | payload | checksum
```

### Length
The message length is a little-endian two-byte integer. It accounts for the full message, including optional prefix and checksum.

### Payload
The payload is the actual message. From observing the original updater (see [serial-port-dump.txt](serial-port-dump.txt)), we can deduce the following message types (written in hexadecimal notation):

#### Ping Command
```
>> c0
<< c0 0a 00 01 00 00 00 00 00 00
```
The response seems to contain the firmware version, but I did not investigate this any further.

#### Restart Command
This command just restarts the remote, e.g. after a successful firmware update.
```
>> c1 00
```
#### "Can we write?" Command
The updater sends a "can we write now?" message every 1024 bytes, which, after confirmation, is followed by four write commands à 256 bytes.
```
>> c2 LL LL 00 09 00 00 00 00 00 00 00 00
<< c2 80 LL LL 00 09 00 00 00 00 00 00 00 00
```
where `LL LL` denotes the offset we want to start writing to (little-endian two-byte integer).

#### Write command
```
>> c3 LL LL 00 00 00 01 DATA
<< c3 00 00 00 00
```
where `DATA`is 256 bytes that should be written on the memory.
If the updater does not receive a response quickly, it will re-send the write command. Interestingly, this results in a race condition in the original updater: If the updater does not receive a confirmation for `WRITE 0x1800` in time (the timeout here is very low), it will re-send the same command. The remote may however process both commands successfully and then return two confirmations. The updater treats the second confirmation for `0x1800` as a confirmation for the next offset, which may not have been transmitted properly. This updater addresses the problem with very conservative timeouts.

### checksum
The checksum is a little-endian two-byte integer that is computed as follows:
```python
checksum = 0xFFFF
for byte in payload: # this includes prefix and length
checksum -= byte
return checksum
```

### Example

The ping message is simply `c0` - including prefix and checksum it has a total length of 5:
`05 00 c0 XX XX`.
We can now compute the checksum: `0xFFFF - 0x05 - 0x00 - 0xc0 = 0xff3a`
For example, for the ping message (`05 00 c0`), the checksum is `0xFFFF-0x05-0xc0 = 0xff3a`. Thus, the complete ping message is:
`05 00 c0 3a ff`
Binary file added serial-port-dump.txt
Binary file not shown.

0 comments on commit b22f318

Please sign in to comment.