diff --git a/eeprom.py b/eeprom.py index ed6b07d..42fea59 100755 --- a/eeprom.py +++ b/eeprom.py @@ -19,13 +19,11 @@ gpio_r = [14, 15, 18, 23, 24, 25, 8, 7, 12, 16, 20, 21] A = [ # 27, 22, 10, 9, 11, 5, 6, 13, 13, 6, 5, 11, 9, 10, 22, 27, # A0 - A7 - 2, 3, 17, 4, # A8 - A11 - 23, 18, 15 # A12 - A14 + 3, 4, 18, 17, # A8 - A11 + 23, 2, 15 # A12 - A14 ] -# IO = gpio_r[4:12] # 8 io pins -# IO.reverse() -IO = [ 24, 25, 8, 7, 12, 16, 20, 21 ] +IO = [ 16, 20, 21, 12, 7, 8, 25, 24] OEb = 26 # Output Enable WEb = 19 # Write Enable @@ -35,17 +33,36 @@ controls = [CEb, WEb, OEb] # TIMES # 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: -t_AS = 0 # Address Setup time -t_AH = 50 * 1e-9 # Address Hold Time -t_CS = 0 # Chip Select Hold Time -t_WP = 100 * 1e-9 # Write Pulse Width -t_DS = 50 * 1e-9 # Data Setup Time_CS = 0 -t_DH = 0 # Data Hold Time -t_WPH = 50 * 1e-9 # Write Puls High -t_WPH = 50 * 1e-4 # Write Pulse High !!!2*e5 longer than in Datasheet, since shorter high caused Problems with my Chip!!! +t_write_AS = 0 # Address Setup time +t_write_OES = 0 # OEb Setup time +t_write_AH = 50 * 1e-9 # Address Hold Time +t_write_CS = 0 # Chip Select Setup Time +t_write_CH = 0 # Chip Select Hold Time +t_write_WP = 100 * 1e-9 # Write Pulse Width +t_write_DS = 50 * 1e-9 # Data Setup Time +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_BIN = False @@ -53,7 +70,6 @@ PRINT_DEC = False REP_CHAR = '\n' - # # UTILITY # @@ -117,13 +133,14 @@ def get_bit(value: int, n: int): 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: bindata = [] for byte in file.read(): 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) # setup the address 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) + + # wait setup time + sleep(max(t_write_CS, t_write_AS, t_write_OES)) # Start the write pulse -> enable WEb GPIO.output(WEb, 0) - # wait until minimum write pulse width is reached. in theory, should be t_WP-t_DS but this caused problems - sleep(t_WP) + # Setup Data + 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: clear_line() echo(address, byte, mode="w", message="DEBUG: Press enter to continue") input() - # End Write Pulse -> disable WEb GPIO.output(WEb, 1) - GPIO.output(CEb, 1) # wait "Data Hold" - sleep(t_DH) + sleep(max(t_write_DH, t_write_WPH)) - GPIO.output(CEb, 0) GPIO.cleanup(IO) 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 + sleep(t_toggle_OEH) timeout = 0 while timeout < 1e3: GPIO.output(OEb, 0) - sleep(1e-9) + sleep(t_toggle_OE) bit1 = GPIO.input(IO[6]) + sleep(t_toggle_OEH) GPIO.output(OEb, 1) - sleep(1e-9) + sleep(t_toggle_OEHP) GPIO.output(OEb, 0) - sleep(1e-9) + sleep(t_toggle_OE) bit2 = GPIO.input(IO[6]) + sleep(t_toggle_OEH) GPIO.output(OEb, 1) - sleep(1e-9) + sleep(t_toggle_OEHP) if bit1 == bit2: - timeout = 1e3 + break timeout += 1 - GPIO.output(CEb, 1) 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) # 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 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(CEb, 1) + sleep(t_read_DF) + if verbose: echo(address, byte, mode="r") return byte @@ -262,12 +321,15 @@ def read(from_ad=0, to_ad=255, delay=1e-3, ignore=[0xff], debug=False, compare:l content = [] 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): byte = read_byte(i, verbose=verbose, debug=debug) content.append(byte) if compare: - if not compare[i-from_ad] == byte: + if not compare[i-from_ad] == content[i-from_ad]: 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") @@ -279,7 +341,7 @@ def read(from_ad=0, to_ad=255, delay=1e-3, ignore=[0xff], debug=False, compare:l 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. WEb controlled @@ -289,21 +351,43 @@ def write(content: list[int], from_ad=0, delay=0, debug=False, only_diff=True, v if only_diff: print(f"Reading EEPROM and only writing deviating values") current_content = read(from_ad, to_ad=to_ad, delay=delay, debug=debug, verbose=True) - assert len(content) == len(current_content) + assert len(content) == len(current_content) failed = [] 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)): - if not only_diff or (only_diff and content[i] != current_content[i]): - write_byte(content[i], from_ad + i, verbose=True, debug=debug) + n_written = 0 + n_written_pages = 0 + + 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 sleep(delay) + + 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: print("Comparing EEPROM to file...") - failed = read(from_ad=from_ad, to_ad=to_ad, delay=delay, debug=debug, verbose=False, compare=content) - retries = 1 + failed = read(from_ad=from_ad, to_ad=to_ad, delay=delay, debug=debug, verbose=True, compare=content) + retries = 2 while len(failed) > 0 and retries > 0: print(f"Found {len(failed)} bytes deviating from the file - retrying: {retries} times") 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'", ) 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("--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") @@ -363,17 +449,25 @@ def main(): if args.no_hex: PRINT_HEX = False 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: print_pins() exit(0) 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: - 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: - 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: - 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")