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.
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!
If the remote does not start anymore, one can access the firmware update mode as follows:
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
The message length is a little-endian two-byte integer. It accounts for the full message, including optional prefix and checksum.
The payload is the actual message. From observing the original updater (see serial-port-dump.txt), we can deduce the following message types (written in hexadecimal notation):
>> 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.
This command just restarts the remote, e.g. after a successful firmware update.
>> c1 00
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).
>> 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.
The checksum is a little-endian two-byte integer that is computed as follows:
checksum = 0xFFFF
for byte in payload: # this includes prefix and length
checksum -= byte
return checksum
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
Thus, the complete ping message is: 05 00 c0 3a ff