add page write
This commit is contained in:
parent
1eb3435181
commit
b48947d9b1
200
eeprom.py
200
eeprom.py
@ -19,13 +19,11 @@ gpio_r = [14, 15, 18, 23, 24, 25, 8, 7, 12, 16, 20, 21]
|
|||||||
A = [
|
A = [
|
||||||
# 27, 22, 10, 9, 11, 5, 6, 13,
|
# 27, 22, 10, 9, 11, 5, 6, 13,
|
||||||
13, 6, 5, 11, 9, 10, 22, 27, # A0 - A7
|
13, 6, 5, 11, 9, 10, 22, 27, # A0 - A7
|
||||||
2, 3, 17, 4, # A8 - A11
|
3, 4, 18, 17, # A8 - A11
|
||||||
23, 18, 15 # A12 - A14
|
23, 2, 15 # A12 - A14
|
||||||
]
|
]
|
||||||
|
|
||||||
# IO = gpio_r[4:12] # 8 io pins
|
IO = [ 16, 20, 21, 12, 7, 8, 25, 24]
|
||||||
# IO.reverse()
|
|
||||||
IO = [ 24, 25, 8, 7, 12, 16, 20, 21 ]
|
|
||||||
|
|
||||||
OEb = 26 # Output Enable
|
OEb = 26 # Output Enable
|
||||||
WEb = 19 # Write Enable
|
WEb = 19 # Write Enable
|
||||||
@ -35,17 +33,36 @@ controls = [CEb, WEb, OEb]
|
|||||||
|
|
||||||
# TIMES
|
# TIMES
|
||||||
# Read:
|
# Read:
|
||||||
t_ACC = 150 * 1e-9 # Address to Output Delay
|
t_read_ACC = 150 * 1e-9 # Address to Output Delay
|
||||||
|
t_read_CE = 70 * 1e-9 # CE to output delay
|
||||||
|
t_read_OE = 150 * 1e-9 # OE to output delay
|
||||||
|
t_read_DF = 50 * 1e-9 # data float
|
||||||
|
|
||||||
# Write:
|
# Write:
|
||||||
t_AS = 0 # Address Setup time
|
t_write_AS = 0 # Address Setup time
|
||||||
t_AH = 50 * 1e-9 # Address Hold Time
|
t_write_OES = 0 # OEb Setup time
|
||||||
t_CS = 0 # Chip Select Hold Time
|
t_write_AH = 50 * 1e-9 # Address Hold Time
|
||||||
t_WP = 100 * 1e-9 # Write Pulse Width
|
t_write_CS = 0 # Chip Select Setup Time
|
||||||
t_DS = 50 * 1e-9 # Data Setup Time_CS = 0
|
t_write_CH = 0 # Chip Select Hold Time
|
||||||
t_DH = 0 # Data Hold Time
|
t_write_WP = 100 * 1e-9 # Write Pulse Width
|
||||||
t_WPH = 50 * 1e-9 # Write Puls High
|
t_write_DS = 50 * 1e-9 # Data Setup Time
|
||||||
t_WPH = 50 * 1e-4 # Write Pulse High !!!2*e5 longer than in Datasheet, since shorter high caused Problems with my Chip!!!
|
t_write_DH = 10 * 1e-9 # Data Hold Time
|
||||||
|
t_write_OEH = 0 # OEb Hold Time
|
||||||
|
t_write_WPH = 50 * 1e-9 # Write Puls High
|
||||||
|
t_write_WC = 10 * 1e-3 # Write Cycle Time
|
||||||
|
|
||||||
|
# t_write_WP = 100 * 1e-6 # Write Pulse Width
|
||||||
|
# t_write_WPH = 50 * 1e-6 # Write Pulse High !!!2*e5 longer than in Datasheet, since shorter high caused Problems with my Chip!!!
|
||||||
|
# t_read_ACC = 150 * 1e-6 # Address to Output Delay
|
||||||
|
# t_write_DH = 1 * 1e-5 # Data Hold Time
|
||||||
|
|
||||||
|
# Toggle
|
||||||
|
t_toggle_OE = 0 # OE to output delay
|
||||||
|
t_toggle_OEH = 10 * 1e-9 # OE hold time
|
||||||
|
t_toggle_OEHP = 150 * 1e-9 # OE high pulse
|
||||||
|
|
||||||
|
# t_toggle_OEH = 500 * 1e-7 # OE hold time
|
||||||
|
# t_toggle_OEHP = 500 * 1e-7 # OE high pulse
|
||||||
|
|
||||||
PRINT_HEX = True
|
PRINT_HEX = True
|
||||||
PRINT_BIN = False
|
PRINT_BIN = False
|
||||||
@ -53,7 +70,6 @@ PRINT_DEC = False
|
|||||||
REP_CHAR = '\n'
|
REP_CHAR = '\n'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# UTILITY
|
# UTILITY
|
||||||
#
|
#
|
||||||
@ -117,13 +133,14 @@ def get_bit(value: int, n: int):
|
|||||||
return value & (1 << n)
|
return value & (1 << n)
|
||||||
|
|
||||||
|
|
||||||
def read_binary_file(filepath, from_ad=0) -> list[int]:
|
def read_binary_file(filepath, from_ad=0, to_ad=-1) -> list[int]:
|
||||||
with open(filepath, "rb") as file:
|
with open(filepath, "rb") as file:
|
||||||
bindata = []
|
bindata = []
|
||||||
for byte in file.read():
|
for byte in file.read():
|
||||||
bindata.append(byte)
|
bindata.append(byte)
|
||||||
return bindata[from_ad:]
|
if to_ad < 0:
|
||||||
|
to_ad = len(bindata) - 1
|
||||||
|
return bindata[from_ad:to_ad+1]
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -164,56 +181,97 @@ def write_byte(byte: int, address: int, verbose=True, debug=False):
|
|||||||
GPIO.output(OEb, 1)
|
GPIO.output(OEb, 1)
|
||||||
# setup the address
|
# setup the address
|
||||||
set_address(address, bits=15)
|
set_address(address, bits=15)
|
||||||
setup_io_pins(OUT)
|
|
||||||
# Setup Data
|
|
||||||
for j in range(8):
|
|
||||||
GPIO.output(IO[j], get_bit(byte, j))
|
|
||||||
# wait "Address" Setup Time
|
|
||||||
sleep(t_AS)
|
|
||||||
# wait "Data Setup Time"
|
|
||||||
sleep(t_DS)
|
|
||||||
|
|
||||||
GPIO.output(CEb, 0)
|
GPIO.output(CEb, 0)
|
||||||
|
|
||||||
|
# wait setup time
|
||||||
|
sleep(max(t_write_CS, t_write_AS, t_write_OES))
|
||||||
# Start the write pulse -> enable WEb
|
# Start the write pulse -> enable WEb
|
||||||
GPIO.output(WEb, 0)
|
GPIO.output(WEb, 0)
|
||||||
|
|
||||||
# wait until minimum write pulse width is reached. in theory, should be t_WP-t_DS but this caused problems
|
# Setup Data
|
||||||
sleep(t_WP)
|
setup_io_pins(OUT)
|
||||||
|
for j in range(8):
|
||||||
|
GPIO.output(IO[j], get_bit(byte, j))
|
||||||
|
sleep(t_write_DS)
|
||||||
|
|
||||||
|
# wait until minimum write pulse width
|
||||||
|
sleep(t_write_WP)
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
clear_line()
|
clear_line()
|
||||||
echo(address, byte, mode="w", message="DEBUG: Press enter to continue")
|
echo(address, byte, mode="w", message="DEBUG: Press enter to continue")
|
||||||
input()
|
input()
|
||||||
|
|
||||||
|
|
||||||
# End Write Pulse -> disable WEb
|
# End Write Pulse -> disable WEb
|
||||||
GPIO.output(WEb, 1)
|
GPIO.output(WEb, 1)
|
||||||
GPIO.output(CEb, 1)
|
|
||||||
|
|
||||||
# wait "Data Hold"
|
# wait "Data Hold"
|
||||||
sleep(t_DH)
|
sleep(max(t_write_DH, t_write_WPH))
|
||||||
|
|
||||||
GPIO.output(CEb, 0)
|
|
||||||
GPIO.cleanup(IO)
|
GPIO.cleanup(IO)
|
||||||
setup_io_pins(IN)
|
setup_io_pins(IN)
|
||||||
|
|
||||||
|
wait_write_finished()
|
||||||
|
GPIO.output(CEb, 1)
|
||||||
|
|
||||||
|
|
||||||
|
def write_page(address: int, page: list[int], verbose=True) -> int:
|
||||||
|
GPIO.output(OEb, 1)
|
||||||
|
# setup the address
|
||||||
|
set_address(address, bits=15)
|
||||||
|
GPIO.output(CEb, 0)
|
||||||
|
|
||||||
|
echo(address, 0, mode="p")
|
||||||
|
|
||||||
|
assert 64 - (address % 64) >= len(page), f"64 - (address % 64) ={64 - (address % 64)}!>={len(page)}=len(page)"
|
||||||
|
|
||||||
|
# wait setup time
|
||||||
|
sleep(max(t_write_CS, t_write_AS, t_write_OES))
|
||||||
|
|
||||||
|
# Setup Data
|
||||||
|
setup_io_pins(OUT)
|
||||||
|
|
||||||
|
for i in range(len(page)):
|
||||||
|
set_address(address + i, bits=6)
|
||||||
|
# Start the write pulse -> enable WEb
|
||||||
|
GPIO.output(WEb, 0)
|
||||||
|
|
||||||
|
for j in range(8):
|
||||||
|
GPIO.output(IO[j], get_bit(page[i], j))
|
||||||
|
|
||||||
|
sleep(max(t_write_DS, t_write_WP))
|
||||||
|
GPIO.output(WEb, 1)
|
||||||
|
sleep(t_write_WPH)
|
||||||
|
|
||||||
|
GPIO.cleanup(IO)
|
||||||
|
setup_io_pins(IN)
|
||||||
|
|
||||||
|
# wait_write_finished()
|
||||||
|
sleep(t_write_WC)
|
||||||
|
|
||||||
|
# print(f"Toggled {timeout} times")
|
||||||
|
GPIO.output(CEb, 1)
|
||||||
|
|
||||||
|
def wait_write_finished():
|
||||||
# check the toggle bit IO6, if it stops toggling the write is done
|
# check the toggle bit IO6, if it stops toggling the write is done
|
||||||
|
sleep(t_toggle_OEH)
|
||||||
timeout = 0
|
timeout = 0
|
||||||
while timeout < 1e3:
|
while timeout < 1e3:
|
||||||
GPIO.output(OEb, 0)
|
GPIO.output(OEb, 0)
|
||||||
sleep(1e-9)
|
sleep(t_toggle_OE)
|
||||||
bit1 = GPIO.input(IO[6])
|
bit1 = GPIO.input(IO[6])
|
||||||
|
sleep(t_toggle_OEH)
|
||||||
GPIO.output(OEb, 1)
|
GPIO.output(OEb, 1)
|
||||||
sleep(1e-9)
|
sleep(t_toggle_OEHP)
|
||||||
GPIO.output(OEb, 0)
|
GPIO.output(OEb, 0)
|
||||||
sleep(1e-9)
|
sleep(t_toggle_OE)
|
||||||
bit2 = GPIO.input(IO[6])
|
bit2 = GPIO.input(IO[6])
|
||||||
|
sleep(t_toggle_OEH)
|
||||||
GPIO.output(OEb, 1)
|
GPIO.output(OEb, 1)
|
||||||
sleep(1e-9)
|
sleep(t_toggle_OEHP)
|
||||||
if bit1 == bit2:
|
if bit1 == bit2:
|
||||||
timeout = 1e3
|
break
|
||||||
timeout += 1
|
timeout += 1
|
||||||
GPIO.output(CEb, 1)
|
|
||||||
|
|
||||||
|
|
||||||
def read_byte(address: int, verbose=True, debug=False) -> int:
|
def read_byte(address: int, verbose=True, debug=False) -> int:
|
||||||
@ -227,8 +285,7 @@ def read_byte(address: int, verbose=True, debug=False) -> int:
|
|||||||
GPIO.output(OEb, 0)
|
GPIO.output(OEb, 0)
|
||||||
|
|
||||||
# wait the "Address to Output Delay" until the output is valid
|
# wait the "Address to Output Delay" until the output is valid
|
||||||
sleep(t_ACC)
|
sleep(max(t_read_ACC, t_read_CE, t_read_OE))
|
||||||
|
|
||||||
|
|
||||||
byte = 0
|
byte = 0
|
||||||
for j in range(8):
|
for j in range(8):
|
||||||
@ -243,6 +300,8 @@ def read_byte(address: int, verbose=True, debug=False) -> int:
|
|||||||
GPIO.output(OEb, 1)
|
GPIO.output(OEb, 1)
|
||||||
GPIO.output(CEb, 1)
|
GPIO.output(CEb, 1)
|
||||||
|
|
||||||
|
sleep(t_read_DF)
|
||||||
|
|
||||||
if verbose: echo(address, byte, mode="r")
|
if verbose: echo(address, byte, mode="r")
|
||||||
|
|
||||||
return byte
|
return byte
|
||||||
@ -262,12 +321,15 @@ def read(from_ad=0, to_ad=255, delay=1e-3, ignore=[0xff], debug=False, compare:l
|
|||||||
content = []
|
content = []
|
||||||
unequal = []
|
unequal = []
|
||||||
|
|
||||||
|
if compare:
|
||||||
|
assert len(compare) == to_ad - from_ad + 1, f"{len(compare)} vs = {to_ad - from_ad + 1} {to_ad} - {from_ad} + 1"
|
||||||
|
|
||||||
for i in range(from_ad, to_ad + 1):
|
for i in range(from_ad, to_ad + 1):
|
||||||
byte = read_byte(i, verbose=verbose, debug=debug)
|
byte = read_byte(i, verbose=verbose, debug=debug)
|
||||||
content.append(byte)
|
content.append(byte)
|
||||||
|
|
||||||
if compare:
|
if compare:
|
||||||
if not compare[i-from_ad] == byte:
|
if not compare[i-from_ad] == content[i-from_ad]:
|
||||||
unequal.append(i)
|
unequal.append(i)
|
||||||
echo(i, byte, "vs {" + format_number(compare[i-from_ad], hex_digits=2, bin_digits=8, dec_digits=3) + "} in file", mode="c", end="\n")
|
echo(i, byte, "vs {" + format_number(compare[i-from_ad], hex_digits=2, bin_digits=8, dec_digits=3) + "} in file", mode="c", end="\n")
|
||||||
|
|
||||||
@ -279,7 +341,7 @@ def read(from_ad=0, to_ad=255, delay=1e-3, ignore=[0xff], debug=False, compare:l
|
|||||||
return content
|
return content
|
||||||
|
|
||||||
|
|
||||||
def write(content: list[int], from_ad=0, delay=0, debug=False, only_diff=True, verbose=True, check_written=True):
|
def write(content: list[int], from_ad=0, delay=0, debug=False, only_diff=True, verbose=True, check_written=True, use_page_write=False):
|
||||||
"""
|
"""
|
||||||
Write a list if bytes to the eeprom.
|
Write a list if bytes to the eeprom.
|
||||||
WEb controlled
|
WEb controlled
|
||||||
@ -293,17 +355,39 @@ def write(content: list[int], from_ad=0, delay=0, debug=False, only_diff=True, v
|
|||||||
failed = []
|
failed = []
|
||||||
print(f"Writing to EEPROM: {len(content)} bytes from address {format(from_ad, '04x')} to {format(to_ad, '04x')}.")
|
print(f"Writing to EEPROM: {len(content)} bytes from address {format(from_ad, '04x')} to {format(to_ad, '04x')}.")
|
||||||
|
|
||||||
for i in range(len(content)):
|
n_written = 0
|
||||||
if not only_diff or (only_diff and content[i] != current_content[i]):
|
n_written_pages = 0
|
||||||
write_byte(content[i], from_ad + i, verbose=True, debug=debug)
|
|
||||||
|
if use_page_write:
|
||||||
|
# assert from_ad == 0, "from_ad != 0 not supported yet"
|
||||||
|
# assert (to_ad+1) % 64 == 0, f"to_ad-1 % 64 != 0 not supported yet. to_ad={to_ad}, to_ad+1% 64 = {(to_ad+1) % 64}"
|
||||||
|
for i in range(from_ad, to_ad, 64):
|
||||||
|
# print(i, i+64, i+64 - (i%64))
|
||||||
|
page_end = i + 64 - (i % 64)
|
||||||
|
page = content[i:page_end]
|
||||||
|
# print(page, current_content[i:page_end])
|
||||||
|
if only_diff and page == current_content[i:page_end]:
|
||||||
|
continue
|
||||||
|
write_page(i, page)
|
||||||
|
n_written_pages += 1
|
||||||
|
n_written += len(page)
|
||||||
|
sleep(delay)
|
||||||
|
else:
|
||||||
|
for i in range(from_ad, to_ad + 1):
|
||||||
|
if only_diff and (only_diff and content[i-from_ad] != current_content[i-from_ad]):
|
||||||
|
continue
|
||||||
|
write_byte(content[i-from_ad], i, verbose=True, debug=debug)
|
||||||
|
n_written += 1
|
||||||
# wait artifical delay
|
# wait artifical delay
|
||||||
sleep(delay)
|
sleep(delay)
|
||||||
|
|
||||||
|
|
||||||
clear_line()
|
clear_line()
|
||||||
print("Write to EEPROM - Done!")
|
print(f"Written " + (f"{n_written_pages} pages / " if use_page_write else "") + f"{n_written} bytes")
|
||||||
if check_written:
|
if check_written:
|
||||||
print("Comparing EEPROM to file...")
|
print("Comparing EEPROM to file...")
|
||||||
failed = read(from_ad=from_ad, to_ad=to_ad, delay=delay, debug=debug, verbose=False, compare=content)
|
failed = read(from_ad=from_ad, to_ad=to_ad, delay=delay, debug=debug, verbose=True, compare=content)
|
||||||
retries = 1
|
retries = 2
|
||||||
while len(failed) > 0 and retries > 0:
|
while len(failed) > 0 and retries > 0:
|
||||||
print(f"Found {len(failed)} bytes deviating from the file - retrying: {retries} times")
|
print(f"Found {len(failed)} bytes deviating from the file - retrying: {retries} times")
|
||||||
for ad in failed:
|
for ad in failed:
|
||||||
@ -340,6 +424,8 @@ def main():
|
|||||||
epilog="Numbers can be passed as int, hex prefixed with '0x' and binary prefixed with '0b'",
|
epilog="Numbers can be passed as int, hex prefixed with '0x' and binary prefixed with '0b'",
|
||||||
)
|
)
|
||||||
parser.add_argument("--write", "-w", dest="write", action="store_true", default=False, help="write binary file onto the EEPROM")
|
parser.add_argument("--write", "-w", dest="write", action="store_true", default=False, help="write binary file onto the EEPROM")
|
||||||
|
parser.add_argument("--page", "-p", dest="use_page_write", action="store_true", default=False, help="use page write mode")
|
||||||
|
parser.add_argument("--no-validate", dest="validate_write", action="store_false", default=True, help="dont validate write operations")
|
||||||
parser.add_argument("--compare", "-c", dest="compare", action="store_true", default=False, help="compare EEPROM content to binary file")
|
parser.add_argument("--compare", "-c", dest="compare", action="store_true", default=False, help="compare EEPROM content to binary file")
|
||||||
parser.add_argument("--read", "-r", dest="read", action="store_true", default=False, help="read the contents of the EEPROM")
|
parser.add_argument("--read", "-r", dest="read", action="store_true", default=False, help="read the contents of the EEPROM")
|
||||||
parser.add_argument("--erase", "-e", dest="erase", action="store_true", default=False, help="erase the contents of the EEPROM")
|
parser.add_argument("--erase", "-e", dest="erase", action="store_true", default=False, help="erase the contents of the EEPROM")
|
||||||
@ -363,17 +449,25 @@ def main():
|
|||||||
if args.no_hex: PRINT_HEX = False
|
if args.no_hex: PRINT_HEX = False
|
||||||
if args.bin: PRINT_BIN = True
|
if args.bin: PRINT_BIN = True
|
||||||
|
|
||||||
|
if args.file:
|
||||||
|
file = read_binary_file(args.file, from_ad=args.from_ad, to_ad=args.to_ad)
|
||||||
|
if args.to_ad != args.from_ad + len(file) - 1:
|
||||||
|
args.to_ad = args.from_ad + len(file) - 1
|
||||||
|
|
||||||
|
else:
|
||||||
|
file = None
|
||||||
|
|
||||||
if args.print_pins:
|
if args.print_pins:
|
||||||
print_pins()
|
print_pins()
|
||||||
exit(0)
|
exit(0)
|
||||||
if args.erase:
|
if args.erase:
|
||||||
erase(from_ad=args.from_ad, to_ad=args.to_ad, delay=args.delay, debug=args.debug, verbose=args.verbose)
|
erase(from_ad=args.from_ad, to_ad=args.to_ad, delay=args.delay, debug=args.debug, verbose=True)
|
||||||
if args.write:
|
if args.write:
|
||||||
write(read_binary_file(args.file, from_ad=args.from_ad), from_ad=args.from_ad, delay=args.delay, debug=args.debug, verbose=args.verbose)
|
write(file, from_ad=args.from_ad, delay=args.delay, debug=args.debug, verbose=True, check_written=args.validate_write, use_page_write=args.use_page_write)
|
||||||
if args.read:
|
if args.read:
|
||||||
read(from_ad=args.from_ad, to_ad=args.to_ad, delay=args.delay, debug=args.debug, verbose=args.verbose, ignore=args.ignore)
|
read(from_ad=args.from_ad, to_ad=args.to_ad, delay=args.delay, debug=args.debug, verbose=True, ignore=args.ignore)
|
||||||
if args.compare:
|
if args.compare:
|
||||||
unequal = read(from_ad=args.from_ad, to_ad=args.to_ad, delay=args.delay, debug=args.debug, verbose=args.verbose, ignore=args.ignore, compare=read_binary_file(args.file))
|
unequal = read(from_ad=args.from_ad, to_ad=args.to_ad, delay=args.delay, debug=args.debug, verbose=args.verbose, ignore=args.ignore, compare=file)
|
||||||
print(f"Found {len(unequal)} deviating values")
|
print(f"Found {len(unequal)} deviating values")
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user