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: Place a firmware image next to the updater and double-click the updater.
Alternatively, use the command line interface:
λ ./flysky-updater-win64.exe --port COM3 --image flyplus.hex
0 B / 55.92 KB [--------------------------------------------] 0.00 %
27.25 KB / 55.92 KB [===================>------------------------] 48.73 % 4s
55.92 KB / 55.92 KB [============================================] 100.00 % 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 AD DR 00 09 00 00 00 00 00 00 00 00
<< c2 80 AD DR 00 09 00 00 00 00 00 00 00 00
where AD DR
denotes the offset we want to start writing to (little-endian two-byte integer).
>> c3 AD DR 00 00 SI ZE DATA
<< c3 00 00 00 00
where AD DR
is the offset (see above), SI ZE
the number of bytes (little-endian two-byte integer, usually 256), and DATA
the bytes that should be written to 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 however 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