|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
SMBus 3.2 protocol layer over an injected I2C bus seam – implementation. More...
#include "ra8_smbus.h"#include <stdint.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_i2c_bus_ops.h"#include "ra8_log.h"Go to the source code of this file.
Data Structures | |
| struct | ra8_smbus_state_t |
| Module state: latched at init time. More... | |
Enumerations | |
| enum | smbus_buf_size_t : uint16_t { k_smbus_frame_bytes = 258U , k_smbus_rx_bytes = 257U } |
| SMBus scratch buffer sizes (max 255-byte payload + overhead). More... | |
| enum | ra8_smbus_internal_t : uint16_t { k_ra8_smbus_pec_poly = 0x07U , k_ra8_smbus_pec_init = 0x00U , k_ra8_smbus_addr_shift = 1U , k_ra8_smbus_rw_write = 0U , k_ra8_smbus_rw_read = 1U , k_ra8_smbus_msb_for_byte = 8U , k_ra8_smbus_pec_top_bit = 0x80U , k_ra8_smbus_byte_mask = 0xFFU } |
| Implementation constants. More... | |
Functions | |
| static uint8_t | internal_pec_update (uint8_t crc, uint8_t b) |
| Update one byte into a running CRC-8/SMBus accumulator. | |
| uint8_t | ra8_smbus_pec (const uint8_t *data, uint32_t len) |
| Compute CRC-8/SMBus over a buffer. | |
| static uint8_t | internal_make_addr_byte (uint8_t target_7b, uint8_t rw_bit) |
| ra8_err_t | ra8_smbus_init (const ra8_smbus_cfg_t *cfg) |
| Initialise the SMBus layer over the injected bus seam. | |
| ra8_err_t | ra8_smbus_deinit (void) |
| Tear the SMBus layer down and release the driver slot. | |
| ra8_err_t | ra8_smbus_send_byte (uint8_t target_7b, uint8_t data) |
| Send Byte transaction (SMBus 3.2 section 6.5.2). | |
| ra8_err_t | ra8_smbus_receive_byte (uint8_t target_7b, uint8_t *out_data) |
| Receive Byte transaction (SMBus 3.2 section 6.5.3). | |
| ra8_err_t | ra8_smbus_write_byte_data (uint8_t target_7b, uint8_t cmd, uint8_t data) |
| Write Byte Data: register-indexed byte write (SMBus 3.2 sec 6.5.4). | |
| ra8_err_t | ra8_smbus_read_byte_data (uint8_t target_7b, uint8_t cmd, uint8_t *out_data) |
| Read Byte Data: register-indexed byte read (SMBus 3.2 sec 6.5.5). | |
| ra8_err_t | ra8_smbus_block_write (uint8_t target_7b, uint8_t cmd, const uint8_t *data, uint8_t len) |
| Block Write (SMBus 3.2 section 6.5.7). | |
| static ra8_err_t | internal_block_read_pec_check (uint8_t target_7b, uint8_t cmd, const uint8_t *buf, uint8_t count, uint8_t pec_rx) |
| Verify the PEC byte of a completed Block Read transfer. | |
| static ra8_err_t | internal_block_read_finish (uint8_t target_7b, uint8_t cmd, const uint8_t *rx, uint8_t cap, uint8_t *buf, uint8_t *out_len) |
| Unpack a completed Block Read transfer into the caller buffer. | |
| ra8_err_t | ra8_smbus_block_read (uint8_t target_7b, uint8_t cmd, uint8_t *buf, uint8_t cap, uint8_t *out_len) |
| Block Read (SMBus 3.2 section 6.5.8). | |
| ra8_err_t | ra8_smbus_alert_register_callback (ra8_smbus_alert_fn_t fn, void *ctx) |
| Register a callback fired when ra8_smbus_alert_dispatch successfully reads the Alert Response Address. | |
| ra8_err_t | ra8_smbus_alert_dispatch (void) |
| Dispatch a single SMBALERT# event: read the ARA and fire the registered callback. | |
Variables | |
| static const char * | s_tag = "SMBUS" |
| Log tag for this driver. | |
| static ra8_smbus_state_t | s_state |
| Singleton driver state. | |
SMBus 3.2 protocol layer over an injected I2C bus seam – implementation.
Builds the SMBus 3.2 wire frames into a small stack scratch buffer and hands them to the injected I2C bus seam (ra8_i2c_bus_ops_t) latched at init. PEC (Packet Error Code) is computed with the SMBus 3.2 section 5.4 CRC-8 (poly 0x07, init 0). The bus drivers are untouched – this file is pure protocol framing.
Section references in the comment headers below are to the SMBus 3.2 specification (SBS-IF, December 2018).
Definition in file ra8_smbus.c.
| enum ra8_smbus_internal_t : uint16_t |
Implementation constants.
Definition at line 46 of file ra8_smbus.c.
| enum smbus_buf_size_t : uint16_t |
SMBus scratch buffer sizes (max 255-byte payload + overhead).
| Enumerator | |
|---|---|
| k_smbus_frame_bytes | Smbus frame bytes. |
| k_smbus_rx_bytes | Smbus RX bytes. |
Definition at line 37 of file ra8_smbus.c.
|
static |
Unpack a completed Block Read transfer into the caller buffer.
The combined transfer left [count] [data...] [optional PEC] in rx. Publish the peripheral-reported count, bound it against the caller's capacity, copy the payload out, and (when PEC is enabled) verify the trailing PEC byte via internal_block_read_pec_check.
| [in] | target_7b | 7-bit peripheral address (for the PEC frame). |
| [in] | cmd | Command code that selected the block. |
| [in] | rx | Raw transfer buffer from the bus seam. |
| [in] | cap | Caller buffer capacity in bytes. |
| [out] | buf | Receives the payload bytes. |
| [out] | out_len | Receives the peripheral-reported byte count. |
| k_ra8_ok | Payload copied (and PEC verified). |
| k_ra8_err_invalid_size | Peripheral count exceeds cap. |
| k_ra8_err_crc_mismatch | PEC byte did not match the frame. |
Definition at line 406 of file ra8_smbus.c.
References internal_block_read_pec_check(), k_ra8_err_invalid_size, k_ra8_ok, and s_state.
Referenced by ra8_smbus_block_read().
|
static |
Verify the PEC byte of a completed Block Read transfer.
Recomputes the SMBus 3.2 5.4 CRC-8 over the full wire frame of the combined transfer – write-address byte, command, read-address byte, byte count, then the count payload bytes – and compares it with the PEC byte the peripheral appended after the payload.
| [in] | target_7b | 7-bit peripheral address. |
| [in] | cmd | Command code that selected the block. |
| [in] | buf | Payload bytes copied out of the transfer. |
| [in] | count | Payload byte count reported by the peripheral. |
| [in] | pec_rx | PEC byte received after the payload. |
| k_ra8_ok | PEC matches the received frame. |
| k_ra8_err_crc_mismatch | Computed PEC differs from pec_rx. |
Definition at line 353 of file ra8_smbus.c.
References internal_make_addr_byte(), internal_pec_update(), k_ra8_err_crc_mismatch, k_ra8_ok, k_ra8_smbus_pec_init, k_ra8_smbus_rw_read, k_ra8_smbus_rw_write, ra8_log_error, and s_tag.
Referenced by internal_block_read_finish().
|
static |
Definition at line 141 of file ra8_smbus.c.
References k_ra8_smbus_addr_shift, and RA8_INTERNAL.
Referenced by internal_block_read_pec_check(), ra8_smbus_block_write(), ra8_smbus_read_byte_data(), ra8_smbus_receive_byte(), ra8_smbus_send_byte(), and ra8_smbus_write_byte_data().
|
static |
Update one byte into a running CRC-8/SMBus accumulator.
Bitwise implementation – 8 shifts per byte. With the firmware's call frequency (a handful of SMBus transactions per second) a table lookup would be premature optimisation, and it would burn 256 bytes of MRAM. The poly and init values are mandated by SMBus 3.2 5.4.
| [in] | crc | Current CRC. |
| [in] | b | Byte to fold in. |
| 0 | Success or default value. |
Definition at line 109 of file ra8_smbus.c.
References k_ra8_smbus_msb_for_byte, k_ra8_smbus_pec_poly, k_ra8_smbus_pec_top_bit, and RA8_INTERNAL.
Referenced by internal_block_read_pec_check(), ra8_smbus_block_write(), ra8_smbus_pec(), ra8_smbus_read_byte_data(), ra8_smbus_receive_byte(), ra8_smbus_send_byte(), and ra8_smbus_write_byte_data().
|
nodiscard |
Dispatch a single SMBALERT# event: read the ARA and fire the registered callback.
Reads one byte from address k_ra8_smbus_alert_addr_7b (0x0C). The returned byte's upper 7 bits are the 7-bit address of the peripheral that asserted ALERT (SMBus 3.2 section 6.5.13). The LSB is the device status. If no callback has been registered the read still happens (so the bus line is released) but no further action is taken.
Test-callable: unit tests invoke this directly to simulate an ALERT event.
| k_ra8_ok | Dispatch completed (callback fired if registered). |
| k_ra8_err_not_initialized | Init not run. |
| Forwarded | codes from the bus seam read. |
Definition at line 472 of file ra8_smbus.c.
References k_ra8_err_not_initialized, k_ra8_ok, k_ra8_smbus_addr_shift, k_ra8_smbus_alert_addr_7b, and s_state.
|
nodiscard |
Register a callback fired when ra8_smbus_alert_dispatch successfully reads the Alert Response Address.
SMBus 3.2 section 6.5.13 specifies that a peripheral asserts SMBALERT# (an open-drain side-band line, not SDA/SCL) and the controller responds by reading from address 0x0C (ARA). The peripheral that won arbitration writes its 7-bit address back into the LSBs of the response byte. Because SMBALERT# is a board-level GPIO interrupt, this driver does not own the IRQ wiring – the caller arms ra8_icu to call ra8_smbus_alert_dispatch() from the SMBALERT# ISR, and the dispatch helper performs the ARA read and fires the registered callback.
| [in] | fn | Callback to fire, or NULL to detach. |
| [in] | ctx | Context pointer passed back unchanged. |
| k_ra8_ok | Callback registered or detached. |
| k_ra8_err_not_initialized | Init not run. |
Definition at line 461 of file ra8_smbus.c.
References k_ra8_err_not_initialized, k_ra8_ok, and s_state.
|
nodiscard |
Block Read (SMBus 3.2 section 6.5.8).
Wire format with PEC disabled: S | addr_w | cmd | Sr | addr_r | count | data[0..count-1] | P With PEC enabled the PEC trails the data run.
| [in] | target_7b | 7-bit peripheral address. |
| [in] | cmd | Command / register index byte. |
| [out] | buf | Destination buffer (non-NULL, capacity cap). |
| [in] | cap | Capacity of buf (1..255). |
| [out] | out_len | Bytes actually returned by the peripheral (the count field). Always populated on k_ra8_ok and on k_ra8_err_invalid_size. |
| k_ra8_ok | Block received and PEC matched if on. |
| k_ra8_err_null_ptr | buf / out_len NULL. |
| k_ra8_err_invalid_arg | cap is 0 or > 255. |
| k_ra8_err_invalid_size | Returned count exceeds cap. |
| k_ra8_err_not_initialized | Init not run. |
| k_ra8_err_crc_mismatch | PEC verification failed. |
| Forwarded | codes from the bus seam write / read. |
Definition at line 433 of file ra8_smbus.c.
References internal_block_read_finish(), k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_ok, k_smbus_rx_bytes, RA8_CHECK_NULL_PTR, s_state, and s_tag.
|
nodiscard |
Block Write (SMBus 3.2 section 6.5.7).
Wire format with PEC disabled: S | addr_w | cmd | count | data[0..count-1] | P With PEC enabled the PEC byte is inserted before the STOP. The count byte is mandatory and must equal len (1..255).
| [in] | target_7b | 7-bit peripheral address. |
| [in] | cmd | Command / register index byte. |
| [in] | data | Payload buffer (non-NULL when len > 0). |
| [in] | len | Number of bytes (1..255). |
| k_ra8_ok | Block written. |
| k_ra8_err_null_ptr | data NULL with non-zero len. |
| k_ra8_err_invalid_arg | len is 0 or > 255. |
| k_ra8_err_not_initialized | Init not run. |
| Forwarded | codes from the bus seam write. |
Definition at line 294 of file ra8_smbus.c.
References internal_make_addr_byte(), internal_pec_update(), k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_smbus_pec_init, k_ra8_smbus_rw_write, k_smbus_frame_bytes, RA8_CHECK_NULL_PTR, s_state, and s_tag.
|
nodiscard |
Tear the SMBus layer down and release the driver slot.
| k_ra8_ok | Layer released. |
| k_ra8_err_not_initialized | ra8_smbus_init never ran. |
Definition at line 175 of file ra8_smbus.c.
References k_ra8_err_not_initialized, k_ra8_ok, and s_state.
|
nodiscard |
Initialise the SMBus layer over the injected bus seam.
Latches cfg->bus and the policy bits (PEC enable) for later transfers. The bus peripheral behind the seam is initialised by the app before this call – this layer never brings hardware up or down.
| [in] | cfg | Configuration descriptor. |
| k_ra8_ok | SMBus layer ready. |
| k_ra8_err_null_ptr | cfg is NULL. |
| k_ra8_err_invalid_arg | cfg->bus seam incomplete (a NULL op). |
Definition at line 152 of file ra8_smbus.c.
References ra8_smbus_cfg_t::bus, k_ra8_err_invalid_arg, k_ra8_ok, ra8_smbus_cfg_t::pec_enabled, RA8_CHECK_NULL_PTR, ra8_log_error, ra8_i2c_bus_ops_t::read, s_state, s_tag, ra8_i2c_bus_ops_t::transfer, and ra8_i2c_bus_ops_t::write.
Referenced by main().
| uint8_t ra8_smbus_pec | ( | const uint8_t * | data, |
| uint32_t | len ) |
Compute CRC-8/SMBus over a buffer.
Polynomial 0x07, initial value 0x00, no reflection, no XOR-out (SMBus 3.2 section 5.4). Provided as a public symbol so tests can cross-check the framing; production code should not need to call this directly.
| [in] | data | Pointer to bytes (non-NULL when len > 0). |
| [in] | len | Byte count. |
| 0x00 | Either len == 0 or the input bytes happen to hash to zero. |
| other | Computed CRC-8 over data[0..len-1] per SMBus 3.2 section 5.4. |
Definition at line 122 of file ra8_smbus.c.
References internal_pec_update(), and k_ra8_smbus_pec_init.
|
nodiscard |
Read Byte Data: register-indexed byte read (SMBus 3.2 sec 6.5.5).
Wire format with PEC disabled: S | addr_w | cmd | Sr | addr_r | data | P With PEC enabled: S | addr_w | cmd | Sr | addr_r | data | PEC | P
The PEC is computed over addr_w | cmd | addr_r | data.
| [in] | target_7b | 7-bit peripheral address. |
| [in] | cmd | Command / register index byte. |
| [out] | out_data | Destination byte (non-NULL). |
| k_ra8_ok | Byte read (and PEC matched if enabled). |
| k_ra8_err_null_ptr | out_data NULL. |
| k_ra8_err_not_initialized | Init not run. |
| k_ra8_err_crc_mismatch | PEC verification failed. |
| Forwarded | codes from the bus seam write / read. |
Definition at line 259 of file ra8_smbus.c.
References internal_make_addr_byte(), internal_pec_update(), k_ra8_err_crc_mismatch, k_ra8_err_not_initialized, k_ra8_ok, k_ra8_smbus_pec_init, k_ra8_smbus_rw_read, k_ra8_smbus_rw_write, RA8_CHECK_NULL_PTR, ra8_log_error, s_state, and s_tag.
Referenced by bm_read_or_halt(), and sd_read_whoami_or_halt().
|
nodiscard |
Receive Byte transaction (SMBus 3.2 section 6.5.3).
Wire format with PEC disabled: S | (addr<<1)|1 | data | P With PEC enabled: S | (addr<<1)|1 | data | PEC | P
| [in] | target_7b | 7-bit peripheral address. |
| [out] | out_data | Destination byte (non-NULL). |
| k_ra8_ok | Byte received (and PEC matched if enabled). |
| k_ra8_err_null_ptr | out_data is NULL. |
| k_ra8_err_not_initialized | Init not run. |
| k_ra8_err_crc_mismatch | PEC verification failed. |
| Forwarded | codes from the bus seam read. |
Definition at line 210 of file ra8_smbus.c.
References internal_make_addr_byte(), internal_pec_update(), k_ra8_err_crc_mismatch, k_ra8_err_not_initialized, k_ra8_ok, k_ra8_smbus_pec_init, k_ra8_smbus_rw_read, RA8_CHECK_NULL_PTR, ra8_log_error, s_state, and s_tag.
Referenced by sd_read_whoami_or_halt().
|
nodiscard |
Send Byte transaction (SMBus 3.2 section 6.5.2).
Wire format with PEC disabled: S | (addr<<1)|0 | data | P With PEC enabled: S | (addr<<1)|0 | data | PEC | P
The PEC is computed over the address byte and the data byte using CRC-8 polynomial 0x07, init 0 (SMBus 3.2 section 5.4).
| [in] | target_7b | 7-bit peripheral address. |
| [in] | data | Single data byte to transmit. |
| k_ra8_ok | Byte delivered. |
| k_ra8_err_not_initialized | Init not run. |
| Forwarded | codes from the bus seam write. |
Definition at line 191 of file ra8_smbus.c.
References internal_make_addr_byte(), internal_pec_update(), k_ra8_err_not_initialized, k_ra8_smbus_pec_init, k_ra8_smbus_rw_write, and s_state.
Referenced by sd_read_whoami_or_halt().
|
nodiscard |
Write Byte Data: register-indexed byte write (SMBus 3.2 sec 6.5.4).
Wire format with PEC disabled: S | addr_w | cmd | data | P With PEC enabled the PEC is appended before the STOP.
| [in] | target_7b | 7-bit peripheral address. |
| [in] | cmd | Command / register index byte. |
| [in] | data | Data byte to write. |
| k_ra8_ok | Byte written. |
| k_ra8_err_not_initialized | Init not run. |
| Forwarded | codes from the bus seam write. |
Definition at line 240 of file ra8_smbus.c.
References internal_make_addr_byte(), internal_pec_update(), k_ra8_err_not_initialized, k_ra8_smbus_pec_init, k_ra8_smbus_rw_write, and s_state.
|
static |
Singleton driver state.
Definition at line 73 of file ra8_smbus.c.
|
static |
Log tag for this driver.
Definition at line 34 of file ra8_smbus.c.