-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
88 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 not shown.