Skip to content

Commit 5dbfd98

Browse files
committed
espflash: Reduce the memory fragmentation during write.
espflash used to implicitely allocate four times per write the ~4k buffer for the data. That caused devices with smaller memory to fail due to memory fragmentation. This change reduces it to once per block.
1 parent a080872 commit 5dbfd98

File tree

1 file changed

+20
-17
lines changed

1 file changed

+20
-17
lines changed

micropython/espflash/espflash.py

+20-17
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from micropython import const
3232
from time import sleep
3333
import binascii
34+
import gc
3435

3536
_CMD_SYNC = const(0x08)
3637
_CMD_CHANGE_BAUDRATE = const(0x0F)
@@ -113,8 +114,11 @@ def _poll_reg(self, addr, flag, retry=10, delay=0.050):
113114
raise Exception(f"Register poll timeout. Addr: 0x{addr:02X} Flag: 0x{flag:02X}.")
114115

115116
def _write_slip(self, pkt):
117+
gc.collect()
116118
pkt = pkt.replace(b"\xDB", b"\xdb\xdd").replace(b"\xc0", b"\xdb\xdc")
117-
self.uart.write(b"\xC0" + pkt + b"\xC0")
119+
self.uart.write(b"\xC0")
120+
self.uart.write(pkt)
121+
self.uart.write(b"\xC0")
118122
self._log(pkt)
119123

120124
def _read_slip(self):
@@ -256,32 +260,31 @@ def flash_write_file(self, path, blksize=0x1000):
256260
total_blocks = (size + blksize - 1) // blksize
257261
erase_blocks = 1
258262
print(f"Flash write size: {size} total_blocks: {total_blocks} block size: {blksize}")
263+
gc.collect()
264+
buf = bytearray(blksize + 16)
265+
erase_cmd = bytearray(16)
266+
mv = memoryview(buf)
259267
with open(path, "rb") as f:
260268
seq = 0
261269
subseq = 0
262270
for i in range(total_blocks):
263-
buf = f.read(blksize)
271+
nread = f.readinto(mv[16: 16 + blksize])
264272
# Update digest
265273
if self.md5sum is not None:
266-
self.md5sum.update(buf)
274+
self.md5sum.update(mv[16:16 + blksize])
267275
# The last data block should be padded to the block size with 0xFF bytes.
268-
if len(buf) < blksize:
269-
buf += b"\xFF" * (blksize - len(buf))
270-
checksum = self._checksum(buf)
276+
if nread < blksize:
277+
mv[nread + 16, blksize + 16] = b"\xFF" * (blksize - nread)
278+
checksum = self._checksum(mv[16: 16 + blksize])
271279
if seq % erase_blocks == 0:
272280
# print(f"Erasing {seq} -> {seq+erase_blocks}...")
273-
self._command(
274-
_CMD_SPI_FLASH_BEGIN,
275-
struct.pack(
276-
"<IIII", erase_blocks * blksize, erase_blocks, blksize, seq * blksize
277-
),
278-
)
281+
struct.pack_into(
282+
"<IIII", erase_cmd, 0, erase_blocks * blksize, erase_blocks, blksize, seq * blksize
283+
),
284+
self._command(_CMD_SPI_FLASH_BEGIN, erase_cmd)
279285
print(f"Writing sequence number {seq}/{total_blocks}...")
280-
self._command(
281-
_CMD_SPI_FLASH_DATA,
282-
struct.pack("<IIII", len(buf), seq % erase_blocks, 0, 0) + buf,
283-
checksum,
284-
)
286+
struct.pack_into("<IIII", mv[0: 16], 0, nread, seq % erase_blocks, 0, 0)
287+
self._command(_CMD_SPI_FLASH_DATA, buf, checksum)
285288
seq += 1
286289

287290
print("Flash write finished")

0 commit comments

Comments
 (0)