Skip to content

Commit 9a7ea5e

Browse files
committed
Improve reset stability
1 parent b93c13c commit 9a7ea5e

File tree

1 file changed

+29
-33
lines changed

1 file changed

+29
-33
lines changed

src/modulino/firmware_flasher.py

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@
1111
CMD_GET = const(0x00) # Gets the version and the allowed commands
1212
CMD_GET_VERSION = const(0x01) # Gets the protocol version
1313
CMD_GET_ID = const(0x02) # Get chip ID
14+
CMD_ERASE = const(0x44) # Erase memory
15+
CMD_GO = const(0x21) # Jumps to user application code located in the internal flash memory
16+
CMD_WRITE = const(0x32) # Write memory
1417

1518
# Define I2C pins and initialize I2C
16-
i2c = I2C(0, freq=100000, timeout=50000 * 2)
19+
i2c = I2C(0, freq=100000)
1720

1821
def send_reset(address):
1922
"""
@@ -23,25 +26,23 @@ def send_reset(address):
2326
:return: 0 if the reset command was sent successfully, otherwise -1.
2427
"""
2528
buffer = b'DIE'
26-
# Pad buffer to 40 bytes
27-
buffer += b'\x00' * (40 - len(buffer))
29+
buffer += b'\x00' * (8 - len(buffer)) # Pad buffer to 8 bytes
2830

2931
try:
3032
print(f"Sending reset command to address {hex(address)}")
3133
i2c.writeto(address, buffer, True)
32-
return False
33-
except OSError as e:
34-
# pass
35-
time.sleep(0.25)
34+
print("Reset command sent successfully")
35+
time.sleep(0.25) # Wait for the device to reset
3636
return True
37-
38-
# time.sleep(0.25)
39-
# devices = i2c.scan()
40-
41-
# if address in devices:
42-
# return False
43-
# elif BOOTLOADER_I2C_ADDRESS in devices:
44-
# return True
37+
except OSError as e:
38+
# ENODEV can be thrown if either the device reset while writing out the buffer or if the device
39+
# was already in bootloader mode in which case there is no device at the original address
40+
if e.errno == 19:
41+
time.sleep(0.25) # Wait for the device to reset
42+
return True
43+
else:
44+
print(f"Error sending reset command: {e}")
45+
return False
4546

4647
def wait_for_ack():
4748
"""
@@ -98,7 +99,7 @@ def execute_command(opcode, command_data, response_length = 0, verbose=True):
9899

99100
return data[1 : amount_of_bytes + 1]
100101

101-
def flash_firmware(firmware, length, verbose=True):
102+
def flash_firmware(firmware, verbose=True):
102103
"""
103104
Flash the firmware to the I2C device.
104105
@@ -127,32 +128,27 @@ def flash_firmware(firmware, length, verbose=True):
127128

128129
return True # Debug. Remove when done
129130

130-
if verbose:
131-
print("Mass erase")
132-
erase_buffer = bytearray([0xFF, 0xFF, 0x0])
133-
if execute_command(0x44, erase_buffer, 3, None, 0, verbose) < 0:
134-
print("Failed to mass erase")
135-
return False
131+
print("Erasing memory...")
132+
erase_buffer = bytearray([0xFF, 0xFF, 0x0]) # Mass erase flash
133+
execute_command(CMD_ERASE, erase_buffer, 0, verbose)
136134

137-
for i in range(0, length, 128):
135+
for i in range(0, len(firmware), 128):
138136
progress_bar(i, length)
139137
write_buffer = bytearray([8, 0, i // 256, i % 256])
140-
if write_firmware_page(0x32, write_buffer, 5, firmware[i:i + 128], 128, verbose) < 0:
138+
if write_firmware_page(write_buffer, 5, firmware[i:i + 128], 128, verbose) < 0:
141139
print(f"Failed to write page {hex(i)}")
142140
return False
143141
time.sleep(0.01)
144142

145143
progress_bar(length, length) # Complete the progress bar
146144

147145
print("Starting firmware")
148-
jump_buffer = bytearray([0x8, 0x00, 0x00, 0x00, 0x8])
149-
if execute_command(0x21, jump_buffer, 5, None, 0, verbose) < 0:
150-
print("Failed to start firmware")
151-
return False
146+
go_params = bytearray([0x8, 0x00, 0x00, 0x00, 0x8])
147+
execute_command(CMD_GO, go_params, 0, verbose) # Jump to the application
152148

153149
return True
154150

155-
def write_firmware_page(opcode, command_buffer, command_length, firmware_buffer, firmware_length, verbose=True):
151+
def write_firmware_page(command_buffer, command_length, firmware_buffer, firmware_length, verbose=True):
156152
"""
157153
Write a page of the firmware to the I2C device.
158154
@@ -164,7 +160,7 @@ def write_firmware_page(opcode, command_buffer, command_length, firmware_buffer,
164160
:param verbose: Whether to print debug information.
165161
:return: The number of bytes written, or -1 if an error occurred.
166162
"""
167-
cmd = bytes([opcode, 0xFF ^ opcode])
163+
cmd = bytes([CMD_WRITE, 0xFF ^ CMD_WRITE])
168164
i2c.writeto(100, cmd)
169165

170166
if command_length > 0:
@@ -273,10 +269,10 @@ def setup():
273269
with open(bin_file, 'rb') as file:
274270
firmware = file.read()
275271

276-
if flash_firmware(firmware, len(firmware)):
277-
print("PASS")
272+
if flash_firmware(firmware):
273+
print("Firmware flashed successfully")
278274
else:
279-
print("FAIL")
275+
print("Failed to flash firmware")
280276

281277
# Start the setup
282278
setup()

0 commit comments

Comments
 (0)