Skip to content

Commit b74eb7a

Browse files
author
Dario Cammi
committed
Fixed a bug in hat initialization and reduced memory required to load the firmware
1 parent 7f0dbca commit b74eb7a

File tree

1 file changed

+48
-22
lines changed

1 file changed

+48
-22
lines changed

buildhat/hat.py

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
import io
12
import sys
2-
import board
33
import busio
44
import time
55
import digitalio
@@ -143,14 +143,14 @@ def _init_hat(self) -> None:
143143
if self._debug and line:
144144
print(line)
145145

146-
if line.startswith(_FIRMWARE):
146+
if line and line.startswith(_FIRMWARE):
147147
hat_version = line[len(_FIRMWARE) :].split(" ")
148148
file_version = self._get_firmware_file_version()
149149
if int(hat_version[0]) == file_version:
150150
status = "firmare_ok"
151151
else:
152152
status = "need_new_firmware"
153-
elif line.startswith(_BOOTLOADER):
153+
elif line and line.startswith(_BOOTLOADER):
154154
status = "bootloader"
155155
elif attempt == 0:
156156
if not line:
@@ -200,34 +200,39 @@ def _load_firmware(self):
200200
firmware_file = f"{firmware_folder}/firmware.bin"
201201
signature_file = f"{firmware_folder}/signature.bin"
202202

203+
# Calculate file leght and checksum
204+
if self._debug:
205+
print("Calculating firmware checksum...")
203206
try:
204207
with open(firmware_file, "rb") as f:
205-
firm = f.read()
208+
fimware_len, firmware_checksum = self._checksum(f)
206209
except Exception as e:
207210
raise Exception(
208211
f"Build Hat firmare load failed: failed to read '{firmware_file}'"
209212
) from e
210213

211214
# Load firmaware file in the hat
212215
if self._debug:
213-
print("Loading firmware int the hat...")
216+
print("Loading firmware into the hat...")
214217
try:
215218
self._serial.write(b"clear\r")
216219
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())
218221
time.sleep(0.1)
219222
# STX = 0x02
220223
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)
222229
# ETX = 0x03
223230
self._serial.write(b"\x03\r")
224231
self._get_prompt()
225232
except Exception as e:
226233
raise Exception(
227234
"Build Hat firmare load failed: failed to load fimware file in the hat"
228235
) from e
229-
finally:
230-
del firm
231236

232237
try:
233238
with open(signature_file, "rb") as f:
@@ -248,12 +253,21 @@ def _load_firmware(self):
248253
self._serial.write(sig)
249254
# ETX = 0x03
250255
self._serial.write(b"\x03\r")
251-
self._get_prompt()
252256
except Exception as e:
253257
raise Exception(
254258
"Build Hat firmare load failed: failed to load signature file in the hat"
255259
) from e
256260

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+
257271
# Reboot the hat and wait for done message
258272
if self._debug:
259273
print("Reboot the the hat and wait for done message...")
@@ -268,20 +282,28 @@ def _load_firmware(self):
268282
if self._debug:
269283
print("Firmware loading completed")
270284

271-
def _checksum(self, data):
285+
def _checksum(self, file: io.FileIO):
272286
"""Calculate checksum from data
273287
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
276290
"""
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)
285307

286308
def readline(self, skip=None) -> str | None:
287309
"""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:
317339
start_time = time.monotonic_ns()
318340
timeout_ns = timeout_ms * 1e6
319341
while True:
320-
line = self.readline()
342+
try:
343+
line = self.readline()
344+
except:
345+
line = None
346+
321347
if line and line.startswith(message):
322348
break
323349
if timeout_ns > 0:

0 commit comments

Comments
 (0)