1
+ import io
1
2
import sys
2
- import board
3
3
import busio
4
4
import time
5
5
import digitalio
@@ -143,14 +143,14 @@ def _init_hat(self) -> None:
143
143
if self ._debug and line :
144
144
print (line )
145
145
146
- if line .startswith (_FIRMWARE ):
146
+ if line and line .startswith (_FIRMWARE ):
147
147
hat_version = line [len (_FIRMWARE ) :].split (" " )
148
148
file_version = self ._get_firmware_file_version ()
149
149
if int (hat_version [0 ]) == file_version :
150
150
status = "firmare_ok"
151
151
else :
152
152
status = "need_new_firmware"
153
- elif line .startswith (_BOOTLOADER ):
153
+ elif line and line .startswith (_BOOTLOADER ):
154
154
status = "bootloader"
155
155
elif attempt == 0 :
156
156
if not line :
@@ -200,34 +200,39 @@ def _load_firmware(self):
200
200
firmware_file = f"{ firmware_folder } /firmware.bin"
201
201
signature_file = f"{ firmware_folder } /signature.bin"
202
202
203
+ # Calculate file leght and checksum
204
+ if self ._debug :
205
+ print ("Calculating firmware checksum..." )
203
206
try :
204
207
with open (firmware_file , "rb" ) as f :
205
- firm = f . read ( )
208
+ fimware_len , firmware_checksum = self . _checksum ( f )
206
209
except Exception as e :
207
210
raise Exception (
208
211
f"Build Hat firmare load failed: failed to read '{ firmware_file } '"
209
212
) from e
210
213
211
214
# Load firmaware file in the hat
212
215
if self ._debug :
213
- print ("Loading firmware int the hat..." )
216
+ print ("Loading firmware into the hat..." )
214
217
try :
215
218
self ._serial .write (b"clear\r " )
216
219
self ._get_prompt ()
217
- self ._serial .write (f"load { len ( firm ) } { self . _checksum ( firm ) } \r " .encode ())
220
+ self ._serial .write (f"load { fimware_len } { firmware_checksum } \r " .encode ())
218
221
time .sleep (0.1 )
219
222
# STX = 0x02
220
223
self ._serial .write (b"\x02 " )
221
- self ._serial .write (firm )
224
+ with open (firmware_file , "rb" ) as f :
225
+ data = f .read (1024 )
226
+ while len (data ) > 0 :
227
+ self ._serial .write (data )
228
+ data = f .read (1024 )
222
229
# ETX = 0x03
223
230
self ._serial .write (b"\x03 \r " )
224
231
self ._get_prompt ()
225
232
except Exception as e :
226
233
raise Exception (
227
234
"Build Hat firmare load failed: failed to load fimware file in the hat"
228
235
) from e
229
- finally :
230
- del firm
231
236
232
237
try :
233
238
with open (signature_file , "rb" ) as f :
@@ -248,12 +253,21 @@ def _load_firmware(self):
248
253
self ._serial .write (sig )
249
254
# ETX = 0x03
250
255
self ._serial .write (b"\x03 \r " )
251
- self ._get_prompt ()
252
256
except Exception as e :
253
257
raise Exception (
254
258
"Build Hat firmare load failed: failed to load signature file in the hat"
255
259
) from e
256
260
261
+ # Wait for build hat serial prompt
262
+ if self ._debug :
263
+ print ("Wait for hat serial pomprt ..." )
264
+ try :
265
+ self ._get_prompt ()
266
+ except Exception as e :
267
+ raise Exception (
268
+ "Build Hat firmare load failed: failed to reach serial prompt"
269
+ ) from e
270
+
257
271
# Reboot the hat and wait for done message
258
272
if self ._debug :
259
273
print ("Reboot the the hat and wait for done message..." )
@@ -268,20 +282,28 @@ def _load_firmware(self):
268
282
if self ._debug :
269
283
print ("Firmware loading completed" )
270
284
271
- def _checksum (self , data ):
285
+ def _checksum (self , file : io . FileIO ):
272
286
"""Calculate checksum from data
273
287
274
- :param data: Data to calculate the checksum from
275
- :return: Checksum that has been calculated
288
+ :param file: File to calculate the checksum from
289
+ :return: File lenght in bytes and file checksum
276
290
"""
277
- u = 1
278
- for i in range (0 , len (data )):
279
- if (u & 0x80000000 ) != 0 :
280
- u = (u << 1 ) ^ 0x1D872B41
281
- else :
282
- u = u << 1
283
- u = (u ^ data [i ]) & 0xFFFFFFFF
284
- return u
291
+ file_lenght = 0
292
+ checksum = 1
293
+
294
+ file .seek (0 )
295
+ data = file .read (1024 )
296
+ while len (data ) > 0 :
297
+ file_lenght += len (data )
298
+ for i in range (0 , len (data )):
299
+ if (checksum & 0x80000000 ) != 0 :
300
+ checksum = (checksum << 1 ) ^ 0x1D872B41
301
+ else :
302
+ checksum = checksum << 1
303
+ checksum = (checksum ^ data [i ]) & 0xFFFFFFFF
304
+ data = file .read (1024 )
305
+
306
+ return (file_lenght , checksum )
285
307
286
308
def readline (self , skip = None ) -> str | None :
287
309
"""Read data from the serial port of Build HAT
@@ -317,7 +339,11 @@ def _wait_for_message(self, message: str, timeout_ms: int = 2000) -> None:
317
339
start_time = time .monotonic_ns ()
318
340
timeout_ns = timeout_ms * 1e6
319
341
while True :
320
- line = self .readline ()
342
+ try :
343
+ line = self .readline ()
344
+ except :
345
+ line = None
346
+
321
347
if line and line .startswith (message ):
322
348
break
323
349
if timeout_ns > 0 :
0 commit comments