Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: GlasgowEmbedded/glasgow
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d494ace23fc8
Choose a base ref
...
head repository: GlasgowEmbedded/glasgow
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: b8f138fcfdc4
Choose a head ref
  • 1 commit
  • 2 files changed
  • 1 contributor

Commits on Jan 13, 2020

  1. applet.memory.24x: use chunked reads.

    Currently the I2C applet cannot handle reads of 64K and more,
    and 64K I2C EEPROMs exist; before this commit, trying to read exactly
    64K from one would result in a hang.
    whitequark committed Jan 13, 2020
    Copy the full SHA
    b8f138f View commit details
Showing with 30 additions and 18 deletions.
  1. +1 −0 software/glasgow/applet/interface/i2c_master/__init__.py
  2. +29 −18 software/glasgow/applet/memory/_24x/__init__.py
1 change: 1 addition & 0 deletions software/glasgow/applet/interface/i2c_master/__init__.py
Original file line number Diff line number Diff line change
@@ -141,6 +141,7 @@ async def _cmd_stop(self):
await self.lower.write([CMD_STOP])

async def _cmd_count(self, count):
assert count < 0xffff
msb = (count >> 8) & 0xff
lsb = (count >> 0) & 0xff
await self.lower.write([CMD_COUNT, msb, lsb])
47 changes: 29 additions & 18 deletions software/glasgow/applet/memory/_24x/__init__.py
Original file line number Diff line number Diff line change
@@ -27,24 +27,35 @@ def _carry_addr(self, addr):
return (i2c_addr, [addr & 0xff])

async def read(self, addr, length):
i2c_addr, addr_bytes = self._carry_addr(addr)

# Note that even if this is a 1-byte address EEPROM and we write 2 bytes here, we will not
# overwrite the contents, since the actual write is only initiated on stop, not repeated
# start condition.
self._log("i2c-addr=%#04x addr=%#06x", i2c_addr, addr)
result = await self.lower.write(i2c_addr, addr_bytes)
if result is False:
self._log("unacked")
return None

self._log("read=%d", length)
data = await self.lower.read(i2c_addr, length, stop=True)
if data is None:
self._log("unacked")
else:
self._log("data=<%s>", data.hex())
return data
chunks = []

while length > 0:
i2c_addr, addr_bytes = self._carry_addr(addr)

# Our lower layer can't do reads of 64K and higher, so use 32K chunks.
chunk_size = min(length, 0x8000)

# Note that even if this is a 1-byte address EEPROM and we write 2 bytes here,
# we will not overwrite the contents, since the actual write is only initiated
# on stop, not repeated start condition.
self._log("i2c-addr=%#04x addr=%#06x", i2c_addr, addr)
result = await self.lower.write(i2c_addr, addr_bytes)
if result is False:
self._log("unacked")
return None

self._log("read=%d", chunk_size)
chunk = await self.lower.read(i2c_addr, chunk_size, stop=True)
if chunk is None:
self._log("unacked")
else:
self._log("chunk=<%s>", chunk.hex())
chunks.append(chunk)

length -= chunk_size
addr += chunk_size

return b"".join(chunks)

async def write(self, addr, data):
while len(data) > 0: