Providing 'out-of-band' data with I2C EEPROM emulation - Page 1
Forum section: electronics / general

author: HwAoRrDk
author_rank: Super Contributor
timestamp: October 17, 2022, 08:34:13 pm
content: In an existing project I am emulating an I2C EEPROM using a microcontroller acting as an I2C slave device. I'm thinking about whether there's a way for the master I2C device (a Raspberry Pi) to be able to read certain other data (some kind of status info, etc.) in a kind of 'out-of-band' manner - that is, such that a request to read that data is distinct from reading the emulated EEPROM data.The first thing I thought of is to simply use some memory addresses outside the normal range of the emulated EEPROM. For example, if I'm emulating a 24C32 EEPROM, it has a capacity of 4096 bytes and only 12-bits (out of 16) of the read/write address are significant. This means the top 4 bits are normally unused, so I could possibly use for example 0xF000 and upwards for reading 'out-of-band' data.I was thinking of making it so that there is a defined range of 'registers' in this out-of-range address space, so if the master device wants to read one it simply does a selective single-byte read at that address. That is, it issues an I2C write with the relevant address, then reads a single byte. I suppose in the case of a sequential read by the master (it writes an address, then reads multiple bytes), I could do one of two things: a) repeat the same register's data byte over and over again; or, b) increment to the next register, return its data byte, and so on, wrapping the address within the range of registers if the end is reached. Not sure which would be best.Does anyone have any other ideas? Any gotchas with my proposed approach?

author: HwAoRrDk
author_rank: Super Contributor
timestamp: October 17, 2022, 08:38:14 pm
content: Oh, and before anyone asks: "Why don't you just implement another slave device on a separate I2C address that communicates however you want?"My microcontroller's I2C peripheral only supports specifying a single slave address (which is matched in hardware). So everything I want to do will have to be through the same address - i.e. that of the EEPROM being emulated.

author: redkitedesign
author_rank: Regular Contributor
timestamp: October 17, 2022, 10:48:34 pm
content: Reads beyond the address range can be wrapped, so that is not an reliable way of differentiating between a 4096 byte device and your implementation.My idea would be to find an access (maybe two writes in quick succession?) that would yield an non-Ack in the original device. As the result of a non-ack in the original device can be undefined, you can define any result as you like and communicate in that way.An slightly less neat alternative would be an consecutive read over the entire address range, repeated. As it is quite unlikely that any application using the original device would do this, you can return other information on the second read. Optionally with a NACK to prevent code expecting the original device interpreting this as real data.

author: PCB.Wiz
author_rank: Super Contributor
timestamp: October 17, 2022, 11:03:46 pm
content: Quote from: HwAoRrDk on October 17, 2022, 08:34:13 pmIf you are in control of both ends, that should work fine.if you do need to distinguish between data wrap (no special region), and your added info, you could read the two addresses, and implement burst read.The first byte can be the NOT of the legal address data, and following bytes can be your register map. If you start with a 1 offset, this is valid for any size reads.The Pi checks legal and phantom address info and if same, it is not phantom data.

author: Foxxz
author_rank: Regular Contributor
timestamp: October 17, 2022, 11:16:26 pm
content: I'd use something akin to port knocking. Call it address knocking or an escape sequence. Where you pick an unlikely sequence of addresses, that when read in a specific order, signify to the Pi that you want to enter a different mode or perhaps like switching address banks. Easy to implement as a state machine..Read0xDEAD (returns EEPROM data as normal)0xBEEF (returns EEPROM data as normal)0xCAFE (returns EEPROM data as normal)Pi now recognizes this as an escape sequence and switches to command mode or whatever custom implementation you come up with. Once done you can give it a command to exit this mode and return to normal EEPROM mode. Maybe thats writing a particular byte to 0xFFFF or whatever. Go wild.

author: JPortici
author_rank: Super Contributor
timestamp: October 18, 2022, 06:02:22 am
content: I would keep things simple, as suggested:Successive read/writes started on a legal address perform address wrap around the memory.Read/write on special address read the special data page and wraps around that page.

author: DavidAlfa
author_rank: Super Contributor
timestamp: October 18, 2022, 03:02:54 pm
content: *Unlocks heaven*

author: HwAoRrDk
author_rank: Super Contributor
timestamp: October 18, 2022, 03:08:04 pm
content: Quote from: redkitedesign on October 17, 2022, 10:48:34 pmYes. My emulation code handles wrapping. But I don't think it would be a problem, because in the case an auto-incrementing address from a sequential read wraps around, the original address specified was in the normal EEPROM range, so I would still be in that 'mode', and know to wrap the address rather than carry on into the 'special' area.Quote from: redkitedesign on October 17, 2022, 10:48:34 pmI don't think there is anything that would do that. I2C EEPROMs are pretty 'dumb' - the only time the slave EEPROM will nack the master is when it hasn't finished writing data. But my emulation doesn't do writing at all, because the application is strictly read-only.Quote from: PCB.Wiz on October 17, 2022, 11:03:46 pmI don't understand this.What two addresses?Quote from: Foxxz on October 17, 2022, 11:16:26 pmThat would no doubt greatly complicate my emulation code. I'd rather keep things as simple as possible. My proposed solution in the first post would fit in fairly well with my existing code.I think I might just have to go ahead and try my proposed solution and see if it works without any trouble, and then try and come up with some other ideas if it doesn't work. Like JPortici said, keep things simple as possible.

author: voltsandjolts
author_rank: Unknown
timestamp: October 18, 2022, 05:09:22 pm
content: Quote from: HwAoRrDk on October 17, 2022, 08:38:14 pmNothing stopping you from changing that slave address at run time.Lots of eeproms have address selection pins, you could emulate that.Host would control the address selection pins, slave firmware sets appropriate address in the i2c peripheral.You could emulate different size eeproms at different addresses.

author: HwAoRrDk
author_rank: Super Contributor
timestamp: October 18, 2022, 06:12:33 pm
content: Quote from: voltsandjolts on October 18, 2022, 05:09:22 pmHost does not (and cannot) interface with the address selection pins of a real EEPROM - there are only SCL/SDA lines. And the host only ever communicates with the EEPROM at a fixed slave address of 0x50.

author: PCB.Wiz
author_rank: Super Contributor
timestamp: October 18, 2022, 07:29:31 pm
content: Quote from: HwAoRrDk on October 18, 2022, 03:08:04 pmThis detail only matters, if you need to check to identify for your peripheralora standard EEPROM.If you already have spare address space, and control both ends, the simple address window works fine for a new design.You can make that keyhole window any size, as you have a full 16 bit address.You could also emulate a part like the 24AA256UID-256K-I2C-Serial-EEPROM-with-EUI48-EUI64 - that places various ID infos into the upper 1/8 of the 256k

author: bson
author_rank: Unknown
timestamp: October 26, 2022, 07:43:14 pm
content: If you emulate a part with a command structure then you could just extend the command set.