|
18 | 18 |
|
19 | 19 | sys.stdout.flush() |
20 | 20 |
|
21 | | -def StatusCallback(total_packets, success_count, error_count): |
22 | | - #sys.stdout.write(".") |
23 | | - sys.stdout.flush() |
24 | | - |
25 | | - if(total_packets % 10 == 0): |
26 | | - |
27 | | - if(error_count > 0): |
28 | | - sys.stdout.write(str(round((total_packets/filechunks)*100)) + "% err: " + str(error_count) + "\n") |
29 | | - else: |
30 | | - sys.stdout.write(str(round((total_packets/filechunks)*100)) + "%\n") |
31 | | - |
32 | | - sys.stdout.flush() |
| 21 | +try: |
| 22 | + filename = sys.argv[1] |
| 23 | +except: |
| 24 | + dbg_print("Filename not provided, going to use default firmware.bin") |
| 25 | + filename = "firmware.bin" |
33 | 26 |
|
34 | | -def getc(size, timeout=3): |
35 | | - return s.read(size) |
| 27 | +if not os.path.exists(filename): |
| 28 | + msg = "[FAILED] bin file '%s' does not exist\n" % filename |
| 29 | + dbg_print(msg) |
| 30 | + raise EnvironmentError(msg) |
36 | 31 |
|
37 | | -def putc(data, timeout=3): |
38 | | - s.write(data) |
| 32 | +def dbg_print(line): |
| 33 | + sys.stdout.write(line) |
| 34 | + sys.stdout.flush() |
39 | 35 |
|
40 | 36 | def serial_ports(): |
41 | 37 | """ Lists serial port names |
@@ -70,101 +66,111 @@ def serial_ports(): |
70 | 66 | #sys.stdout.write(str(serial_ports())[1:-1]) |
71 | 67 | #sys.stdout.write("\n") |
72 | 68 |
|
73 | | -sys.stdout.write("Going to use "+ result[0] + "\n") |
| 69 | +if not result: |
| 70 | + msg = "\n[FAILED] Cannot find suitable serial port\n\n" |
| 71 | + dbg_print(msg) |
| 72 | + raise EnvironmentError(msg) |
74 | 73 |
|
75 | | -s = serial.Serial(port=result[0], baudrate=420000, bytesize=8, parity='N', stopbits=1, timeout=5, xonxoff=0, rtscts=0) |
76 | | - |
77 | | -alreadyInBootloader = False |
78 | | -s.flush() |
79 | | -time.sleep(1) |
| 74 | +dbg_print("Going to use "+ result[0]+"\n") |
80 | 75 |
|
| 76 | +s = serial.Serial(port=result[0], baudrate=420000, bytesize=8, parity='N', stopbits=1, timeout=.5, xonxoff=0, rtscts=0) |
81 | 77 |
|
| 78 | +s.timeout = 1. |
82 | 79 | try: |
83 | | - reading = s.read(3).decode('utf-8') |
| 80 | + already_in_bl = s.read(3).decode('utf-8') |
84 | 81 | except UnicodeDecodeError: |
85 | | - reading = "" |
86 | | - |
87 | | -if('C' in reading): |
88 | | - alreadyInBootloader = True |
| 82 | + already_in_bl = "" |
89 | 83 |
|
90 | | -MaxBootloaderAttempts = 20 |
91 | | -currAttempt = 0 |
92 | | -gotBootloader = False |
| 84 | +if 'CC' not in already_in_bl: |
| 85 | + s.timeout = .5 |
| 86 | + s.write_timeout = .5 |
93 | 87 |
|
94 | | -if(alreadyInBootloader == False): |
| 88 | + currAttempt = 0 |
| 89 | + gotBootloader = False |
95 | 90 |
|
96 | | - sys.stdout.write("\nAttempting to reboot into bootloader...\n") |
| 91 | + dbg_print("\nAttempting to reboot into bootloader...\n") |
97 | 92 |
|
98 | 93 | while gotBootloader == False: |
99 | 94 |
|
100 | | - s.flush() |
101 | | - s.write(BootloaderInitSeq1) |
102 | | - time.sleep(1) |
103 | | - s.write(BootloaderInitSeq2) |
104 | | - |
105 | | - lines = [] |
106 | | - inChars = "" |
| 95 | + currAttempt += 1 |
| 96 | + dbg_print("[%2u] retry...\n" % currAttempt) |
| 97 | + time.sleep(.5) |
| 98 | + if 10 < currAttempt: |
| 99 | + msg = "Failed to get to BL in reasonable time\n" |
| 100 | + dbg_print(msg) |
| 101 | + raise EnvironmentError(msg) |
107 | 102 |
|
108 | | - while s.in_waiting: |
| 103 | + # request reboot |
| 104 | + s.write(BootloaderInitSeq1) |
| 105 | + s.flush() |
| 106 | + start = time.time() |
| 107 | + while ((time.time() - start) < 2): |
109 | 108 | try: |
110 | | - inChars += s.read().decode('utf-8') |
| 109 | + line = s.readline().decode('utf-8') |
| 110 | + if not line and s.in_waiting: |
| 111 | + line = s.read(1000).decode('utf-8') |
111 | 112 | except UnicodeDecodeError: |
112 | | - pass |
113 | | - |
114 | | - for line in inChars.split('\n'): |
115 | | - if "UART Bootloader for ExpressLRS" in line: |
116 | | - sys.stdout.write("Got into bootloader after: ") |
117 | | - sys.stdout.write(str(currAttempt+1)) |
118 | | - sys.stdout.write(" attempts\n") |
119 | | - sys.stdout.flush() |
| 113 | + continue |
| 114 | + #dbg_print("line : '%s'\n" % (line.strip(), )) |
| 115 | + if "'2bl', 'bbb'" in line: |
| 116 | + # notify bootloader to start uploading |
| 117 | + s.write(BootloaderInitSeq2) |
| 118 | + s.flush() |
| 119 | + dbg_print("Got into bootloader after: %u attempts\n" % (currAttempt)) |
120 | 120 | gotBootloader = True |
121 | 121 | break |
122 | 122 |
|
123 | | - if('C' in line): |
124 | | - gotBootloader = True |
125 | | - break |
| 123 | + # change timeout to 30sec |
| 124 | + s.timeout = 30. |
| 125 | + s.write_timeout = 5. |
126 | 126 |
|
127 | | - if(currAttempt == 20): |
128 | | - sys.stdout.write("Failed to get to BL in reasonable time\n") |
129 | | - raise SystemExit |
| 127 | + # sanity check! Make sure the bootloader is started |
| 128 | + start = time.time() |
| 129 | + while True: |
| 130 | + char = s.read().decode('utf-8') |
| 131 | + if char == 'C': |
130 | 132 | break |
131 | | - |
132 | | - currAttempt = currAttempt + 1 |
133 | | - |
134 | | - s.write(BootloaderInitSeq2) |
135 | | - |
| 133 | + if ((time.time() - start) > 10): |
| 134 | + msg = "[FAILED] Unable to communicate with bootloader...\n" |
| 135 | + dbg_print(msg) |
| 136 | + raise EnvironmentError(msg) |
136 | 137 | else: |
137 | | - sys.stdout.write("\nWe were already in bootloader\n") |
138 | | - sys.stdout.flush() |
139 | | - |
140 | | - |
141 | | -time.sleep(0.2) |
142 | | -s.close() |
143 | | -s.open() |
144 | | - |
| 138 | + dbg_print("\nWe were already in bootloader\n") |
145 | 139 |
|
146 | | -try: |
147 | | - filename = sys.argv[1] |
148 | | -except: |
149 | | - print("Filename not provided, going to use default firmware.bin") |
150 | | - filename = "firmware.bin" |
| 140 | +# change timeout to 5sec |
| 141 | +s.timeout = 5. |
| 142 | +s.write_timeout = 5. |
151 | 143 |
|
| 144 | +# open binary |
152 | 145 | stream = open(filename, 'rb') |
153 | 146 | filesize = os.stat(filename).st_size |
154 | 147 | filechunks = filesize/128 |
155 | 148 |
|
156 | | -sys.stdout.write("uploading ") |
157 | | -sys.stdout.write(str(filesize)+" bytes...\n") |
158 | | -sys.stdout.flush() |
| 149 | +dbg_print("uploading %d bytes...\n" % (filesize,)) |
159 | 150 |
|
160 | | -modem = XMODEM(getc, putc) |
161 | | -status = modem.send(stream, retry=10, callback=StatusCallback) |
| 151 | +def StatusCallback(total_packets, success_count, error_count): |
| 152 | + sys.stdout.flush() |
| 153 | + if (total_packets % 10 == 0): |
| 154 | + if (error_count > 0): |
| 155 | + dbg_print(str(round((total_packets/filechunks)*100)) + "% err: " + str(error_count) + "\n") |
| 156 | + else: |
| 157 | + dbg_print(str(round((total_packets/filechunks)*100)) + "%\n") |
162 | 158 |
|
163 | | -if(status): |
164 | | - print("100%\nSuccess!!!!") |
165 | | -else: |
166 | | - print("FAILED") |
167 | | - raise EnvironmentError('Failed to Upload') |
| 159 | +def getc(size, timeout=3): |
| 160 | + return s.read(size) or None |
| 161 | + |
| 162 | +def putc(data, timeout=3): |
| 163 | + return s.write(data) |
| 164 | + |
| 165 | +modem = XMODEM(getc, putc, mode='xmodem') |
| 166 | +#modem.log.setLevel(logging.DEBUG) |
| 167 | +status = modem.send(stream, retry=10, callback=StatusCallback) |
168 | 168 |
|
169 | 169 | s.close() |
170 | 170 | stream.close() |
| 171 | + |
| 172 | +if (status): |
| 173 | + dbg_print("Success!!!!\n\n") |
| 174 | +else: |
| 175 | + dbg_print("[FAILED] Upload failed!\n\n") |
| 176 | + raise EnvironmentError('Failed to Upload') |
0 commit comments