Skip to content

Commit 6a81e58

Browse files
committed
tinyprog: ensure start at multiple of 256
The SPI Flash method used by program_sectors() will wrap around from the end of the 256-octet sector to the start of the 256-octet sector if a write starts part way into the 256-octet sector and writes more octets than (256-start_offset), due to only incrementing the low address bits. Add checks to ensure program_sectors() is only usable with a start address that is a multiple of 256 to avoid scrambled data in the flash due this SPI Flash wrap around.
1 parent 959ab55 commit 6a81e58

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

programmer/tinyprog/__init__.py

+24-3
Original file line numberDiff line numberDiff line change
@@ -497,16 +497,27 @@ def program_fast(self, addr, data):
497497
return False
498498

499499
def program_sectors(self, addr, data):
500+
minor_sector_size = 256
500501
sector_size = 4 * 1024
501502

503+
# The SPI flash program sector action will wrap around if we
504+
# start part way into a 256-octet sector and program 256 octets, due
505+
# to the way that it increments the address. So ensure that the
506+
# addresses are always a multiple of 256 octets.
507+
#
508+
if ((addr % minor_sector_size) != 0):
509+
raise ValueError("Address must be a multiple of {0}, not {1}".
510+
format(minor_sector_size, addr))
511+
502512
with tqdm(desc=" Programming and Verifying", unit="B",
503513
unit_scale=True, total=len(data)) as pbar:
504514
for offset in range(0, len(data), sector_size):
505515
current_addr = addr + offset
516+
assert((current_addr % minor_sector_size) == 0)
517+
506518
current_write_data = data[offset:offset + sector_size]
507519
self.erase(current_addr, sector_size, disable_progress=True)
508520

509-
minor_sector_size = 256
510521
for minor_offset in range(0, 4 * 1024, minor_sector_size):
511522
minor_write_data = current_write_data[
512523
minor_offset:minor_offset + minor_sector_size]
@@ -519,12 +530,22 @@ def program_sectors(self, addr, data):
519530
# only happen on the final minor sector to be written.)
520531
#
521532
if (len(minor_write_data) < minor_sector_size):
522-
pad_len = minor_sector_size - len(minor_write_data)
533+
offset_from_start_of_sector = (
534+
(current_addr + minor_offset) %
535+
minor_sector_size
536+
)
537+
expected_write_size = (
538+
minor_sector_size - offset_from_start_of_sector
539+
)
540+
assert(offset_from_start_of_sector == 0)
541+
542+
pad_len = (minor_sector_size - len(minor_write_data) -
543+
offset_from_start_of_sector)
523544
padding = b'\xff' * pad_len
524545

525546
minor_write_data = bytearray(minor_write_data)
526547
minor_write_data.extend(padding)
527-
assert(len(minor_write_data) == minor_sector_size)
548+
assert(len(minor_write_data) == expected_write_size)
528549

529550
self.write(
530551
current_addr + minor_offset,

0 commit comments

Comments
 (0)