micropython_eeprom/eeprom/i2c/eep_i2c.py

155 wiersze
4.6 KiB
Python
Czysty Zwykły widok Historia

# eep_i2c.py MicroPython test program for Microchip I2C EEPROM devices.
2019-12-11 09:23:17 +00:00
# Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2019 Peter Hinch
import uos
import time
2019-12-11 09:23:17 +00:00
from machine import I2C, Pin
from eeprom_i2c import EEPROM, T24C512
2019-12-11 09:23:17 +00:00
# Return an EEPROM array. Adapt for platforms other than Pyboard or chips
# smaller than 64KiB.
def get_eep():
2022-09-22 09:04:29 +00:00
if uos.uname().machine.split(" ")[0][:4] == "PYBD":
2019-12-11 09:23:17 +00:00
Pin.board.EN_3V3.value(1)
time.sleep(0.1) # Allow decouplers to charge
2019-12-11 09:23:17 +00:00
eep = EEPROM(I2C(2), T24C512)
2022-09-22 09:04:29 +00:00
print("Instantiated EEPROM")
2019-12-11 09:23:17 +00:00
return eep
2022-09-22 09:04:29 +00:00
2019-12-11 09:23:17 +00:00
# Dumb file copy utility to help with managing EEPROM contents at the REPL.
def cp(source, dest):
2022-09-22 09:04:29 +00:00
if dest.endswith("/"): # minimal way to allow
dest = "".join((dest, source.split("/")[-1])) # cp /sd/file /eeprom/
with open(source, "rb") as infile: # Caller should handle any OSError
with open(dest, "wb") as outfile: # e.g file not found
2019-12-11 09:23:17 +00:00
while True:
buf = infile.read(100)
outfile.write(buf)
if len(buf) < 100:
break
2022-09-22 09:04:29 +00:00
2019-12-17 17:10:43 +00:00
# ***** TEST OF DRIVER *****
def _testblock(eep, bs):
2022-09-22 09:04:29 +00:00
d0 = b"this >"
d1 = b"<is the boundary"
2019-12-17 17:10:43 +00:00
d2 = d0 + d1
2022-09-22 09:04:29 +00:00
garbage = b"xxxxxxxxxxxxxxxxxxx"
2019-12-17 17:10:43 +00:00
start = bs - len(d0)
end = start + len(garbage)
2022-09-22 09:04:29 +00:00
eep[start:end] = garbage
res = eep[start:end]
2019-12-17 17:10:43 +00:00
if res != garbage:
2022-09-22 09:04:29 +00:00
return "Block test fail 1:" + str(list(res))
2019-12-17 17:10:43 +00:00
end = start + len(d0)
2022-09-22 09:04:29 +00:00
eep[start:end] = d0
2019-12-17 17:10:43 +00:00
end = start + len(garbage)
2022-09-22 09:04:29 +00:00
res = eep[start:end]
if res != b"this >xxxxxxxxxxxxx":
return "Block test fail 2:" + str(list(res))
2019-12-17 17:10:43 +00:00
start = bs
end = bs + len(d1)
2022-09-22 09:04:29 +00:00
eep[start:end] = d1
2019-12-17 17:10:43 +00:00
start = bs - len(d0)
end = start + len(d2)
2022-09-22 09:04:29 +00:00
res = eep[start:end]
2019-12-17 17:10:43 +00:00
if res != d2:
2022-09-22 09:04:29 +00:00
return "Block test fail 3:" + str(list(res))
2019-12-17 17:10:43 +00:00
Add support of Microchip AT24C32 and support of single chip for `EEPROM` class [Description] Adds support of: 1. Microchip AT24C32 (4 KiB) 2. Support of single chip setup for `EEPROM` class when single chip has address is 0x57 so entire set of chips (1 chip in our case) addresses are not started from 0x50. Example: ```python from eeprom_i2c import EEPROM, T24C32 eeprom = PROM(machine.I2C(0), T24C32) ``` Improves tests implementation by adding dependency injection of `EEPROM` object used during testing with support of old use case when object had not been provided for testing. Example (for AT24C32 connected to I2C0 of my Raspberry Pi Pico W) when we creating instance of `EEPROM` and then passing it to `full_test` and also providing proper block size for this chip: ```python import machine from eeprom_i2c import EEPROM, T24C32 from eep_i2c import full_test def get_eep(): return EEPROM(machine.I2C(0), T24C32) def main(): print("App started") print("Running tests") eep = get_eep() full_test(eep, block_size=32) print("App finished") if __name__ == "__main__": main() ``` [Motivation] Have DS3231 with soldered AT24C32 chip and want to use both RTC and EEPROM. In my case AT24C32 has 0x57 as it's address and `EEPROM` class refused to work with this setup. [Testing] Executed `full_test` from `eep_i2c` against AT24C32 (with address 0x57) connected to my Raspberry Pi Pico W. Test code: ```python import machine from eeprom_i2c import EEPROM, T24C32 from eep_i2c import full_test def get_eep(): return EEPROM(machine.I2C(0), T24C32) def main(): print("App started") print("Running tests") eep = get_eep() full_test(eep, block_size=32) print("App finished") if __name__ == "__main__": main() ```
2022-09-24 16:42:58 +00:00
def test(eep=None):
eep = eep if eep else get_eep()
2019-12-11 09:23:17 +00:00
sa = 1000
for v in range(256):
eep[sa + v] = v
for v in range(256):
if eep[sa + v] != v:
2022-09-22 09:04:29 +00:00
print(
"Fail at address {} data {} should be {}".format(sa + v, eep[sa + v], v)
)
2019-12-11 09:23:17 +00:00
break
else:
2022-09-22 09:04:29 +00:00
print("Test of byte addressing passed")
2019-12-11 09:23:17 +00:00
data = uos.urandom(30)
sa = 2000
2022-09-22 09:04:29 +00:00
eep[sa : sa + 30] = data
if eep[sa : sa + 30] == data:
print("Test of slice readback passed")
2019-12-11 09:23:17 +00:00
2019-12-17 17:10:43 +00:00
block = 256
res = _testblock(eep, block)
if res is None:
2022-09-22 09:04:29 +00:00
print("Test block boundary {} passed".format(block))
2019-12-17 17:10:43 +00:00
else:
2022-09-22 09:04:29 +00:00
print("Test block boundary {} fail".format(block))
2019-12-17 17:10:43 +00:00
print(res)
block = eep._c_bytes
if eep._a_bytes > block:
res = _testblock(eep, block)
if res is None:
2022-09-22 09:04:29 +00:00
print("Test chip boundary {} passed".format(block))
2019-12-17 17:10:43 +00:00
else:
2022-09-22 09:04:29 +00:00
print("Test chip boundary {} fail".format(block))
2019-12-17 17:10:43 +00:00
print(res)
else:
2022-09-22 09:04:29 +00:00
print("Test chip boundary skipped: only one chip!")
2019-12-17 17:10:43 +00:00
# ***** TEST OF FILESYSTEM MOUNT *****
Add support of Microchip AT24C32 and support of single chip for `EEPROM` class [Description] Adds support of: 1. Microchip AT24C32 (4 KiB) 2. Support of single chip setup for `EEPROM` class when single chip has address is 0x57 so entire set of chips (1 chip in our case) addresses are not started from 0x50. Example: ```python from eeprom_i2c import EEPROM, T24C32 eeprom = PROM(machine.I2C(0), T24C32) ``` Improves tests implementation by adding dependency injection of `EEPROM` object used during testing with support of old use case when object had not been provided for testing. Example (for AT24C32 connected to I2C0 of my Raspberry Pi Pico W) when we creating instance of `EEPROM` and then passing it to `full_test` and also providing proper block size for this chip: ```python import machine from eeprom_i2c import EEPROM, T24C32 from eep_i2c import full_test def get_eep(): return EEPROM(machine.I2C(0), T24C32) def main(): print("App started") print("Running tests") eep = get_eep() full_test(eep, block_size=32) print("App finished") if __name__ == "__main__": main() ``` [Motivation] Have DS3231 with soldered AT24C32 chip and want to use both RTC and EEPROM. In my case AT24C32 has 0x57 as it's address and `EEPROM` class refused to work with this setup. [Testing] Executed `full_test` from `eep_i2c` against AT24C32 (with address 0x57) connected to my Raspberry Pi Pico W. Test code: ```python import machine from eeprom_i2c import EEPROM, T24C32 from eep_i2c import full_test def get_eep(): return EEPROM(machine.I2C(0), T24C32) def main(): print("App started") print("Running tests") eep = get_eep() full_test(eep, block_size=32) print("App finished") if __name__ == "__main__": main() ```
2022-09-24 16:42:58 +00:00
def fstest(eep=None, format=False):
eep = eep if eep else get_eep()
try:
2022-09-22 09:04:29 +00:00
uos.umount("/eeprom")
except OSError:
pass
# ***** CODE FOR FATFS *****
2022-09-22 09:04:29 +00:00
# if format:
# os.VfsFat.mkfs(eep)
# ***** CODE FOR LITTLEFS *****
2019-12-11 09:23:17 +00:00
if format:
uos.VfsLfs2.mkfs(eep)
# General
2019-12-11 09:23:17 +00:00
try:
2022-09-22 09:04:29 +00:00
uos.mount(eep, "/eeprom")
except OSError:
raise OSError("Can't mount device: have you formatted it?")
2022-09-22 09:04:29 +00:00
print('Contents of "/": {}'.format(uos.listdir("/")))
print('Contents of "/eeprom": {}'.format(uos.listdir("/eeprom")))
print(uos.statvfs("/eeprom"))
2019-12-11 09:23:17 +00:00
Add support of Microchip AT24C32 and support of single chip for `EEPROM` class [Description] Adds support of: 1. Microchip AT24C32 (4 KiB) 2. Support of single chip setup for `EEPROM` class when single chip has address is 0x57 so entire set of chips (1 chip in our case) addresses are not started from 0x50. Example: ```python from eeprom_i2c import EEPROM, T24C32 eeprom = PROM(machine.I2C(0), T24C32) ``` Improves tests implementation by adding dependency injection of `EEPROM` object used during testing with support of old use case when object had not been provided for testing. Example (for AT24C32 connected to I2C0 of my Raspberry Pi Pico W) when we creating instance of `EEPROM` and then passing it to `full_test` and also providing proper block size for this chip: ```python import machine from eeprom_i2c import EEPROM, T24C32 from eep_i2c import full_test def get_eep(): return EEPROM(machine.I2C(0), T24C32) def main(): print("App started") print("Running tests") eep = get_eep() full_test(eep, block_size=32) print("App finished") if __name__ == "__main__": main() ``` [Motivation] Have DS3231 with soldered AT24C32 chip and want to use both RTC and EEPROM. In my case AT24C32 has 0x57 as it's address and `EEPROM` class refused to work with this setup. [Testing] Executed `full_test` from `eep_i2c` against AT24C32 (with address 0x57) connected to my Raspberry Pi Pico W. Test code: ```python import machine from eeprom_i2c import EEPROM, T24C32 from eep_i2c import full_test def get_eep(): return EEPROM(machine.I2C(0), T24C32) def main(): print("App started") print("Running tests") eep = get_eep() full_test(eep, block_size=32) print("App finished") if __name__ == "__main__": main() ```
2022-09-24 16:42:58 +00:00
def cptest(eep=None): # Assumes pre-existing filesystem of either type
eep = eep if eep else get_eep()
2022-09-22 09:04:29 +00:00
if "eeprom" in uos.listdir("/"):
print("Device already mounted.")
2019-12-17 17:10:43 +00:00
else:
try:
2022-09-22 09:04:29 +00:00
uos.mount(eep, "/eeprom")
2019-12-17 17:10:43 +00:00
except OSError:
2022-09-22 09:04:29 +00:00
print("Fail mounting device. Have you formatted it?")
2019-12-17 17:10:43 +00:00
return
2022-09-22 09:04:29 +00:00
print("Mounted device.")
cp(__file__, "/eeprom/")
# We may have the source file or a precompiled binary (*.mpy)
suffix = __file__[__file__.rfind('.'):]
cp("eeprom_i2c" + suffix, "/eeprom/")
2022-09-22 09:04:29 +00:00
print('Contents of "/eeprom": {}'.format(uos.listdir("/eeprom")))
print(uos.statvfs("/eeprom"))
2019-12-17 17:10:43 +00:00
# ***** TEST OF HARDWARE *****
Add support of Microchip AT24C32 and support of single chip for `EEPROM` class [Description] Adds support of: 1. Microchip AT24C32 (4 KiB) 2. Support of single chip setup for `EEPROM` class when single chip has address is 0x57 so entire set of chips (1 chip in our case) addresses are not started from 0x50. Example: ```python from eeprom_i2c import EEPROM, T24C32 eeprom = PROM(machine.I2C(0), T24C32) ``` Improves tests implementation by adding dependency injection of `EEPROM` object used during testing with support of old use case when object had not been provided for testing. Example (for AT24C32 connected to I2C0 of my Raspberry Pi Pico W) when we creating instance of `EEPROM` and then passing it to `full_test` and also providing proper block size for this chip: ```python import machine from eeprom_i2c import EEPROM, T24C32 from eep_i2c import full_test def get_eep(): return EEPROM(machine.I2C(0), T24C32) def main(): print("App started") print("Running tests") eep = get_eep() full_test(eep, block_size=32) print("App finished") if __name__ == "__main__": main() ``` [Motivation] Have DS3231 with soldered AT24C32 chip and want to use both RTC and EEPROM. In my case AT24C32 has 0x57 as it's address and `EEPROM` class refused to work with this setup. [Testing] Executed `full_test` from `eep_i2c` against AT24C32 (with address 0x57) connected to my Raspberry Pi Pico W. Test code: ```python import machine from eeprom_i2c import EEPROM, T24C32 from eep_i2c import full_test def get_eep(): return EEPROM(machine.I2C(0), T24C32) def main(): print("App started") print("Running tests") eep = get_eep() full_test(eep, block_size=32) print("App finished") if __name__ == "__main__": main() ```
2022-09-24 16:42:58 +00:00
def full_test(eep=None, block_size = 128):
eep = eep if eep else get_eep()
2019-12-11 09:23:17 +00:00
page = 0
Add support of Microchip AT24C32 and support of single chip for `EEPROM` class [Description] Adds support of: 1. Microchip AT24C32 (4 KiB) 2. Support of single chip setup for `EEPROM` class when single chip has address is 0x57 so entire set of chips (1 chip in our case) addresses are not started from 0x50. Example: ```python from eeprom_i2c import EEPROM, T24C32 eeprom = PROM(machine.I2C(0), T24C32) ``` Improves tests implementation by adding dependency injection of `EEPROM` object used during testing with support of old use case when object had not been provided for testing. Example (for AT24C32 connected to I2C0 of my Raspberry Pi Pico W) when we creating instance of `EEPROM` and then passing it to `full_test` and also providing proper block size for this chip: ```python import machine from eeprom_i2c import EEPROM, T24C32 from eep_i2c import full_test def get_eep(): return EEPROM(machine.I2C(0), T24C32) def main(): print("App started") print("Running tests") eep = get_eep() full_test(eep, block_size=32) print("App finished") if __name__ == "__main__": main() ``` [Motivation] Have DS3231 with soldered AT24C32 chip and want to use both RTC and EEPROM. In my case AT24C32 has 0x57 as it's address and `EEPROM` class refused to work with this setup. [Testing] Executed `full_test` from `eep_i2c` against AT24C32 (with address 0x57) connected to my Raspberry Pi Pico W. Test code: ```python import machine from eeprom_i2c import EEPROM, T24C32 from eep_i2c import full_test def get_eep(): return EEPROM(machine.I2C(0), T24C32) def main(): print("App started") print("Running tests") eep = get_eep() full_test(eep, block_size=32) print("App finished") if __name__ == "__main__": main() ```
2022-09-24 16:42:58 +00:00
for sa in range(0, len(eep), block_size):
data = uos.urandom(block_size)
eep[sa : sa + block_size] = data
if eep[sa : sa + block_size] == data:
2022-09-22 09:04:29 +00:00
print("Page {} passed".format(page))
2019-12-11 09:23:17 +00:00
else:
2022-09-22 09:04:29 +00:00
print("Page {} readback failed.".format(page))
2019-12-11 09:23:17 +00:00
page += 1