This issue is related to #33 and to the discussion in #28 about how to expose async in ECMA-419.
The core question I'd like to examine is whether on an I2C bus with multiple devices the "SMBus network layer protocol" style register accesses require atomicity and if so how to achieve that and if not what the requirements on I2C bus implementations are. The question conceptually extends beyond the SMBus-like register accesses but right now I can't name a specific device where this is an issue.
Suppose I'm implementing a register read using ECMA-419 async in a BME280 or Si7021 driver (just to pick two different popular chips). At some point I will have a code fragment that writes the register address without stop condition followed by a read of the register. E.g. using promisified read/write methods I might have:
await i2cAsync.write(register_address, 0)
const value = await i2cAsync.read(register_length)
Clearly the write and read combination is not atomic and specifically, another driver could issue a synchronous bus transaction to a different device right in the middle. Is this a problem? If yes, how can it be avoided or corrected? If not, what does the I2C bus implementation have to do?
In researching the above question I have made a couple of observations:
the i2c bus spec equates repeated-start with stop+start, it also allows a repeated-start to address a different device, it seems to follow that the following sequence of bus operations would be entirely correct:
bus write to device A (the async device), w/out stop condition
bus read or write to device B (the sync device), presumably ending with a stop condition
bus read from device A (completion of the register read sketched above)
the BME280 data sheet specifically mentions that the register read operation can use either a repeated-start or a stop-start, so the above sequence ought to work just fine, the Si7021 datasheet only shows register read with repeated-start, so without testing it's not obvious whether this would work
the SMBus spec is not clear about repeated-start vs. stop+start, at least I can't find an unambiguous statement
I could side-step this whole issue for the BME280 and Si7021 by using the SMBus class, however, neither of the two devices are SMBus devices (I can't find the word "SMBus" anywhere in the datasheet). See #33.
I'm arriving at the following tentative conclusions:
use the SMBus class for devices that use an "SMBus-like" register access protocol even if they are not SMBus devices
or use the I2C class as depicted above and trust that the implementation performs the interleaving of accesses to devices and that the devices react correctly
Even if all this turns into a non-issue I must admit that I would have appreciated if the proposed 2nd edition ECMA-419 spec had said something about atomicity :-) .
Edit:
Thinking about this some more, I believe that the source of my confusion comes from not understanding that the I2C start and stop conditions are purely about bus mastership/arbitration and that stop+start vs. repeated start carries no meaning WRT the operations being performed. So the repeated-start between the write and read phase of a SMBus-like register read simply keeps other bus masters at bay and doesn't mean "the following read relates to the preceding write". Apologies if this is obvious to everyone else.
This issue is related to #33 and to the discussion in #28 about how to expose async in ECMA-419.
The core question I'd like to examine is whether on an I2C bus with multiple devices the "SMBus network layer protocol" style register accesses require atomicity and if so how to achieve that and if not what the requirements on I2C bus implementations are. The question conceptually extends beyond the SMBus-like register accesses but right now I can't name a specific device where this is an issue.
Suppose I'm implementing a register read using ECMA-419 async in a BME280 or Si7021 driver (just to pick two different popular chips). At some point I will have a code fragment that writes the register address without stop condition followed by a read of the register. E.g. using promisified read/write methods I might have:
Clearly the write and read combination is not atomic and specifically, another driver could issue a synchronous bus transaction to a different device right in the middle. Is this a problem? If yes, how can it be avoided or corrected? If not, what does the I2C bus implementation have to do?
In researching the above question I have made a couple of observations:
the i2c bus spec equates repeated-start with stop+start, it also allows a repeated-start to address a different device, it seems to follow that the following sequence of bus operations would be entirely correct:
the BME280 data sheet specifically mentions that the register read operation can use either a repeated-start or a stop-start, so the above sequence ought to work just fine, the Si7021 datasheet only shows register read with repeated-start, so without testing it's not obvious whether this would work
the SMBus spec is not clear about repeated-start vs. stop+start, at least I can't find an unambiguous statement
I could side-step this whole issue for the BME280 and Si7021 by using the SMBus class, however, neither of the two devices are SMBus devices (I can't find the word "SMBus" anywhere in the datasheet). See #33.
I'm arriving at the following tentative conclusions:
Even if all this turns into a non-issue I must admit that I would have appreciated if the proposed 2nd edition ECMA-419 spec had said something about atomicity :-) .
Edit: Thinking about this some more, I believe that the source of my confusion comes from not understanding that the I2C start and stop conditions are purely about bus mastership/arbitration and that stop+start vs. repeated start carries no meaning WRT the operations being performed. So the repeated-start between the write and read phase of a SMBus-like register read simply keeps other bus masters at bay and doesn't mean "the following read relates to the preceding write". Apologies if this is obvious to everyone else.