Skip to content

Commit 153a12d

Browse files
authored
scripts: some cleanup + reboot sequence generation moved to own file (ExpressLRS#637)
* scripts: some cleanup + reboot sequence generation moved to own file * scripst: reset_to_bl moved to function * scripts: serial write_str to make sure the line ending is always correct
1 parent 35d4209 commit 153a12d

6 files changed

Lines changed: 82 additions & 34 deletions

File tree

src/python/BFinitPassthrough.py

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import serial, time, sys, re
22
import argparse
3-
from xmodem import XMODEM
43
import serials_find
54
import SerialHelper
5+
import bootloader
66

77
SCRIPT_DEBUG = 0
88

@@ -25,7 +25,7 @@ def _validate_serialrx(rl, config, expected):
2525
expected = [expected]
2626
rl.set_delimiters(["# "])
2727
rl.clear()
28-
rl.write("get serialrx_%s\r\n" % config)
28+
rl.write_str("get serialrx_%s" % config)
2929
line = rl.read_line(1.).strip()
3030
for key in expected:
3131
key = " = %s" % key
@@ -35,7 +35,7 @@ def _validate_serialrx(rl, config, expected):
3535
return found
3636

3737

38-
def bf_passthrough_init(port, requestedBaudrate, half_duplex=False, reset_to_bl=False):
38+
def bf_passthrough_init(port, requestedBaudrate, half_duplex=False):
3939
debug = SCRIPT_DEBUG
4040

4141
sys.stdout.flush()
@@ -49,7 +49,7 @@ def bf_passthrough_init(port, requestedBaudrate, half_duplex=False, reset_to_bl=
4949
rl = SerialHelper.SerialHelper(s, 3., ['CCC', "# "])
5050
rl.clear()
5151
# Send start command '#'
52-
rl.write("#\r\n", half_duplex)
52+
rl.write_str("#", half_duplex)
5353
start = rl.read_line(2.).strip()
5454
#dbg_print("BF INIT: '%s'" % start.replace("\r", ""))
5555
if "CCC" in start:
@@ -79,7 +79,7 @@ def bf_passthrough_init(port, requestedBaudrate, half_duplex=False, reset_to_bl=
7979

8080
rl.set_delimiters(["\n"])
8181
rl.clear()
82-
rl.write("serial\r\n")
82+
rl.write_str("serial")
8383

8484
while True:
8585
line = rl.read_line().strip()
@@ -104,39 +104,51 @@ def bf_passthrough_init(port, requestedBaudrate, half_duplex=False, reset_to_bl=
104104

105105
dbg_print("Enabling serial passthrough...")
106106
dbg_print(" CMD: '%s'" % cmd)
107-
rl.write(cmd + '\n')
108-
107+
rl.write_str(cmd)
108+
time.sleep(.2)
109+
s.close()
109110
dbg_print("======== PASSTHROUGH DONE ========")
110111

111-
if(reset_to_bl):
112-
dbg_print("======== RESET TO BOOTLOADER ========")
113-
if half_duplex == True:
114-
BootloaderInitSeq1 = bytes([0x89,0x04,0x32,0x62,0x6c,0x0A]) # GHST
115-
dbg_print(" Using GHST (half duplex)!\n")
116-
else:
117-
BootloaderInitSeq1 = bytes([0xEC,0x04,0x32,0x62,0x6c,0x0A]) # CRSF
118-
119-
s.write(BootloaderInitSeq1)
120112

121-
time.sleep(.2)
113+
def reset_to_bootloader(args):
114+
dbg_print("======== RESET TO BOOTLOADER ========")
115+
s = serial.Serial(port=args.port, baudrate=args.baud,
116+
bytesize=8, parity='N', stopbits=1,
117+
timeout=1, xonxoff=0, rtscts=0)
118+
if args.half_duplex:
119+
BootloaderInitSeq = bootloader.get_init_seq('GHST', args.type)
120+
dbg_print(" * Using half duplex (GHST)")
121+
else:
122+
BootloaderInitSeq = bootloader.get_init_seq('CRSF', args.type)
123+
dbg_print(" * Using full duplex (CFSF)")
124+
s.write(BootloaderInitSeq)
125+
s.flush()
126+
time.sleep(.5)
122127
s.close()
123128

124129

125130
if __name__ == '__main__':
126-
parser = argparse.ArgumentParser(description="Initialize BetaFlight passthrough and optionally send a reboot comamnd sequence")
131+
parser = argparse.ArgumentParser(
132+
description="Initialize BetaFlight passthrough and optionally send a reboot comamnd sequence")
127133
parser.add_argument("-b", "--baud", type=int, default=420000,
128134
help="Baud rate for passthrough communication")
129135
parser.add_argument("-p", "--port", type=str,
130136
help="Override serial port autodetection and use PORT")
131137
parser.add_argument("-nr", "--no-reset", action="store_false",
132-
dest="reset_to_bl",
133-
help="Do not send reset_to_bootloader command sequence")
138+
dest="reset_to_bl", help="Do not send reset_to_bootloader command sequence")
139+
parser.add_argument("-hd", "--half-duplex", action="store_true",
140+
dest="half_duplex", help="Use half duplex mode")
141+
parser.add_argument("-t", "--type", type=str, default="ESP82",
142+
help="Defines flash target type which is sent to target in reboot command")
134143
args = parser.parse_args()
135144

136145
if (args.port == None):
137146
args.port = serials_find.get_serial_port()
138147

139148
try:
140-
bf_passthrough_init(args.port, args.baud, reset_to_bl=args.reset_to_bl)
149+
bf_passthrough_init(args.port, args.baud)
141150
except PassthroughEnabled as err:
142151
dbg_print(str(err))
152+
153+
if args.reset_to_bl:
154+
reset_to_bootloader(args)

src/python/SerialHelper.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ def write(self, data, half_duplex=None):
7474
# All written data is read into RX buffer
7575
serial.read(cnt)
7676

77+
def write_str(self, data, half_duplex=None):
78+
self.write(data+'\r\n', half_duplex)
79+
7780
def __convert_to_str(self, data):
7881
try:
7982
return data.decode(encoding)

src/python/UARTupload.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import BFinitPassthrough
99
import SerialHelper
1010
import re
11+
import bootloader
1112

1213
SCRIPT_DEBUG = 0
1314
BAUDRATE_DEFAULT = 420000
@@ -19,7 +20,7 @@ def dbg_print(line=''):
1920
return
2021

2122

22-
def uart_upload(port, filename, baudrate, ghst=False):
23+
def uart_upload(port, filename, baudrate, ghst=False, key=None):
2324
half_duplex = False
2425

2526
dbg_print("=================== FIRMWARE UPLOAD ===================\n")
@@ -28,11 +29,13 @@ def uart_upload(port, filename, baudrate, ghst=False):
2829

2930
logging.basicConfig(level=logging.ERROR)
3031

31-
BootloaderInitSeq1 = bytes([0xEC,0x04,0x32,0x62,0x6c,0x0A]) # CRSF
3232
if ghst:
33-
BootloaderInitSeq1 = bytes([0x89,0x04,0x32,0x62,0x6c,0x0A]) # GHST
33+
BootloaderInitSeq1 = bootloader.get_init_seq('GHST', key)
3434
half_duplex = True
3535
dbg_print(" Using GHST (half duplex)!\n")
36+
else:
37+
BootloaderInitSeq1 = bootloader.get_init_seq('CRSF', key)
38+
dbg_print(" Using CRSF (full duplex)!\n")
3639
BootloaderInitSeq2 = bytes([0x62,0x62,0x62,0x62,0x62,0x62])
3740

3841
if not os.path.exists(filename):
@@ -199,6 +202,7 @@ def putc(data, timeout=3):
199202

200203

201204
def on_upload(source, target, env):
205+
envkey = None
202206
ghst = False
203207
firmware_path = str(source[0])
204208

@@ -215,9 +219,11 @@ def on_upload(source, target, env):
215219
for flag in flags:
216220
if "GHST=" in flag:
217221
ghst = eval(flag.split("=")[1])
222+
elif "BL_KEY=" in flag:
223+
envkey = flag.split("=")[1]
218224

219225
try:
220-
uart_upload(upload_port, firmware_path, upload_speed, ghst)
226+
uart_upload(upload_port, firmware_path, upload_speed, ghst, key=envkey)
221227
except Exception as e:
222228
dbg_print("{0}\n".format(e))
223229
return -1

src/python/bootloader.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
ELRS_BOOT_CMD_DEST = ord('b')
3+
ELRS_BOOT_CMD_ORIG = ord('l')
4+
5+
INIT_SEQ = {
6+
"CRSF": [0xEC,0x04,0x32,ELRS_BOOT_CMD_DEST,ELRS_BOOT_CMD_ORIG],
7+
"GHST": [0x89,0x04,0x32,ELRS_BOOT_CMD_DEST,ELRS_BOOT_CMD_ORIG],
8+
}
9+
10+
def calc_crc8(payload, poly=0xD5):
11+
crc = 0
12+
for data in payload:
13+
crc ^= data
14+
for _ in range(8):
15+
if crc & 0x80:
16+
crc = (crc << 1) ^ poly
17+
else:
18+
crc = crc << 1
19+
return crc & 0xFF
20+
21+
def get_init_seq(module, key=None):
22+
payload = list(INIT_SEQ.get(module, []))
23+
if payload:
24+
if key:
25+
if type(key) == str:
26+
key = [ord(x) for x in key]
27+
payload += key
28+
payload[1] += len(key)
29+
payload += [calc_crc8(payload[2:])]
30+
return bytes(payload)
31+
32+
if __name__ == '__main__':
33+
print("CRC: %s" % get_init_seq('CRSF', [ord(x) for x in 'R9MM']))
34+
print("CRC: %s" % get_init_seq('CRSF', 'R9MM'))

src/python/esp_compress.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import shutil
33
import os, glob
44

5-
FIRMWARE_PACKING_ENABLED = False
5+
FIRMWARE_PACKING_ENABLED = True
66

77

88
#
@@ -49,7 +49,7 @@ def compressFirmware(source, target, env):
4949
build_dir = env.subst("$BUILD_DIR")
5050
image_name = env.subst("$PROGNAME")
5151
source_file = os.path.join(build_dir, image_name + ".bin")
52-
target_file = source_file
52+
target_file = source_file + ".gz"
5353
binary_compress(target_file, source_file)
5454

5555

src/python/stlink.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,6 @@ def get_commands(env, firmware):
4343
if bootloader is not None:
4444
BL_CMD = [TOOL, "write", bootloader, hex(flash_start)]
4545
APP_CMD = [TOOL, "--reset", "write", firmware, hex(app_start)]
46-
elif "darwin" in platform_name:
47-
TOOL = os.path.join(
48-
env_dir,
49-
"tool-stm32duino", "stlink", "st-flash")
50-
if bootloader is not None:
51-
BL_CMD = [TOOL, "write", bootloader, hex(flash_start)]
52-
APP_CMD = [TOOL, "--reset", "write", firmware, hex(app_start)]
5346
elif "os x" in platform_name:
5447
print("OS X not supported at the moment\n")
5548
raise OSError

0 commit comments

Comments
 (0)