The sensor bus: one I2C (Inter-Integrated Circuit) bus with current monitors on it, as the drivers see it.
More...
|
| void | sense_bus_init (sense_bus_t *b, const sense_i2c_t *io) |
| | Set up a bus over a wire.
|
| sense_err_t | sense_bus_read (sense_bus_t *b, uint8_t addr, uint8_t reg, uint8_t *buf, size_t n) |
| | A register read: n bytes, most significant first, into buf.
|
| sense_err_t | sense_bus_write16 (sense_bus_t *b, uint8_t addr, uint8_t reg, uint16_t value) |
| | A 16-bit register write.
|
| void | sense_bus_note (sense_bus_t *b, sense_err_t e) |
| | A transaction made on the wire without this module – an address scan – and what it came to, for the stuck decision: a held line or a timeout counts as one of this module's would, and marks the bus stuck by the same rule.
|
| bool | sense_bus_recovery_due (const sense_bus_t *b, uint32_t now_ms) |
| | Whether a recovery is to be run now: the bus is stuck, and none has run since, or the last ran SENSE_RECOVER_MS or more ago without a transaction proving the bus free.
|
| void | sense_bus_recovered (sense_bus_t *b, uint32_t now_ms) |
| | The caller has run a recovery.
|
| void | sense_part_init (sense_part_t *p, sense_bus_t *bus, uint8_t addr) |
| | Set up a part record on a bus.
|
| bool | sense_part_probe_due (sense_part_t *p, uint32_t now_ms) |
| | Every tick, with the time: whether the part is to be probed now.
|
| void | sense_part_probed (sense_part_t *p, sense_state_t state) |
| | The probe's result; a part left anything but online is probed again SENSE_RETRY_MS on.
|
| sense_err_t | sense_part_read (sense_part_t *p, uint8_t reg, uint8_t *buf, size_t n) |
| | A read or write of an online part, counted towards taking it offline.
|
| sense_err_t | sense_part_write16 (sense_part_t *p, uint8_t reg, uint16_t value) |
| | Write a 16-bit register of a part, counted towards taking it offline.
|
| void | sense_part_sample_failed (sense_part_t *p, uint8_t before) |
| | After a sample of two reads whose second failed: the failure run is before plus one, as if the first read had not reset it. before is the part's fails count taken ahead of the sample.
|
| void | sense_part_lost (sense_part_t *p) |
| | An online part that answers and no longer holds the set-up written to it: offline, and probed again SENSE_RETRY_MS on.
|
| uint16_t | sense_be16 (const uint8_t *b) |
| | Big-endian register contents, most significant byte first.
|
| uint32_t | sense_be24 (const uint8_t *b) |
| | Read a big-endian 24-bit value.
|
| uint64_t | sense_be40 (const uint8_t *b) |
| | Read a big-endian 40-bit value.
|
| int32_t | sense_sext32 (uint32_t v, unsigned bits) |
| | The low bits of v as a two's complement number (1 to 32 bits).
|
| int64_t | sense_sext64 (uint64_t v, unsigned bits) |
| | The same for up to 64 bits.
|
| int64_t | sense_muldiv (int64_t a, uint32_t mul, uint64_t div) |
| | a × mul / div without the product overflowing, truncated towards zero.
|
The sensor bus: one I2C (Inter-Integrated Circuit) bus with current monitors on it, as the drivers see it.
The drivers (ina228.h, ina3221.h) reach the wire through two callbacks, a register read and a register write, each answering with an error code. The IOmcu supplies them from its I2C block; the host suite supplies a fake that answers as each part does. Both parts send the most significant byte first (INA228 SLYS021A §7.5.1, INA3221 SBOS576C §8.2) and keep the register pointer between transactions, so a read is the pointer write and n bytes back, and a write is the pointer and 2 bytes.
What this module decides:
- Bus stuck. A transaction that finds SDA or SCL held low (SENSE_BUS_LOW), or SENSE_STUCK_TIMEOUTS transactions in a row that do not finish (SENSE_TIMEOUT), mark the bus stuck. A NACK (not acknowledged) does not: the address byte went out and the lines came back, so the bus works and a part is missing. While the bus is stuck nothing is sent; a recovery is due at once and every SENSE_RECOVER_MS after that. The caller runs it – 9 clocks on SCL as GPIO (general-purpose input/output), a STOP, the I2C block re-initialised – and reports it with sense_bus_recovered(). The next transaction then goes out as the test: one that ends with OK or a NACK clears the stuck flag. The INA3221 also frees the bus by itself after SCL is held low for 28ms to 35ms (SBOS576C §6.5, SMBus timeout); the INA228's datasheet states no such timeout.
- A part online or offline. A part is probed (identity read, set-up written and read back) before anything else is said to it. SENSE_FAILS failed transactions in a row take an online part offline: 6ms of readings at 500Hz. So does a set-up register that reads back another value than the one written, twice in a row: the part reset itself and runs on its power-on set-up (sense_part_lost()). A part that is not online is probed again every SENSE_RETRY_MS. Nothing is acted on here: an offline part is reported, its readings stop, and the bench is not disarmed.
Pure C, no SDK (software development kit): host-tested against a fake bus in test_ina228 and test_ina3221.
SPDX-License-Identifier: MIT