ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches

SMBus 3.2 protocol layer over an injected I2C bus seam. More...

#include <stdint.h>
#include "ra8_err.h"
#include "ra8_i2c_bus_ops.h"
Include dependency graph for ra8_smbus.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ra8_smbus_cfg_t
 Configuration descriptor for ra8_smbus_init. More...

Typedefs

typedef void(* ra8_smbus_alert_fn_t) (void *ctx, uint8_t target_7b, uint8_t status)
 SMBALERT# notification callback.

Enumerations

enum  ra8_smbus_limits_t : uint16_t {
  k_ra8_smbus_block_max = 255U ,
  k_ra8_smbus_frame_max = 258U ,
  k_ra8_smbus_alert_addr_7b = 0x0CU
}
 Spec-mandated buffer ceilings. More...

Functions

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).
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.
uint8_t ra8_smbus_pec (const uint8_t *data, uint32_t len)
 Compute CRC-8/SMBus over a buffer.

Detailed Description

SMBus 3.2 protocol layer over an injected I2C bus seam.

Tag
[Ring 3 / HAL] {World: NS}

Implements the controller-side SMBus 3.2 protocol layer specified in the SMBus 3.2 specification (SBS-IF, December 2018):

  • section 6.5.1 Quick Command (not yet wrapped here – use the bus driver's scan instead)
  • section 6.5.2 Send Byte
  • section 6.5.3 Receive Byte
  • section 6.5.4 Write Byte / Write Word
  • section 6.5.5 Read Byte / Read Word
  • section 6.5.7 Block Write
  • section 6.5.8 Block Read
  • section 6.5.13 Host Notify / SMBALERT# (alert response address 0x0C)
  • section 5.4 Packet Error Code (PEC, CRC-8 polynomial 0x07, init 0)

SMBus is a strict subset of I2C with extra protocol rules:

  1. fixed bus speeds: 10, 100, 400, 1000 kHz
  2. mandatory STOP after every transaction (no bus parking)
  3. PEC byte may be appended to detect single-bit errors end-to-end
  4. block transfers carry a leading byte-count field

This module owns the protocol framing (count byte, PEC, address stuffing for ARA) and delegates raw byte movement to the injected I2C bus seam (ra8_i2c_bus_ops_t) supplied at init – IIC_B in I2C-compat mode today, RIIC on a future board revision. The bus drivers are not modified – SMBus is layered on top, and the app owns bus bring-up/teardown (typically binding the seam via ra8_io_i2c_bus_as_ops()).

Inclusive terminology: "controller" / "peripheral" replaces the legacy controller/peripheral wording in the SMBus spec (the spec itself uses the older terminology).

Definition in file ra8_smbus.h.

Typedef Documentation

◆ ra8_smbus_alert_fn_t

typedef void(* ra8_smbus_alert_fn_t) (void *ctx, uint8_t target_7b, uint8_t status)

SMBALERT# notification callback.

Parameters
[in]ctxCaller-supplied context.
[in]target_7b7-bit address of the peripheral that asserted ALERT, as recovered from the ARA read.
[in]statusStatus byte returned in the ARA payload.

Definition at line 101 of file ra8_smbus.h.

Enumeration Type Documentation

◆ ra8_smbus_limits_t

enum ra8_smbus_limits_t : uint16_t

Spec-mandated buffer ceilings.

SMBus 3.2 section 6.5.7 / 6.5.8 caps a block payload at 255 bytes (the count byte is uint8_t). The on-the-wire frame is therefore at most addr + count + 255 data + PEC = 258 bytes. Callers that stack-allocate scratch buffers should size them with this enum.

Enumerator
k_ra8_smbus_block_max 

Max data bytes per block xfer.

k_ra8_smbus_frame_max 

Max wire bytes incl.

PEC + addr.

k_ra8_smbus_alert_addr_7b 

Alert Response Address (ARA).

Definition at line 72 of file ra8_smbus.h.

Function Documentation

◆ ra8_smbus_alert_dispatch()

ra8_err_t ra8_smbus_alert_dispatch ( void )
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.

Returns
ra8_err_t.
Return values
k_ra8_okDispatch completed (callback fired if registered).
k_ra8_err_not_initializedInit not run.
Forwardedcodes from the bus seam read.
Precondition
ra8_smbus_init previously succeeded.
Postcondition
Bus is released.
Since
0.1.0

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.

◆ ra8_smbus_alert_register_callback()

ra8_err_t ra8_smbus_alert_register_callback ( ra8_smbus_alert_fn_t fn,
void * ctx )
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.

Parameters
[in]fnCallback to fire, or NULL to detach.
[in]ctxContext pointer passed back unchanged.
Returns
ra8_err_t.
Return values
k_ra8_okCallback registered or detached.
k_ra8_err_not_initializedInit not run.
Since
0.1.0

Definition at line 461 of file ra8_smbus.c.

References k_ra8_err_not_initialized, k_ra8_ok, and s_state.

◆ ra8_smbus_block_read()

ra8_err_t ra8_smbus_block_read ( uint8_t target_7b,
uint8_t cmd,
uint8_t * buf,
uint8_t cap,
uint8_t * out_len )
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.

Parameters
[in]target_7b7-bit peripheral address.
[in]cmdCommand / register index byte.
[out]bufDestination buffer (non-NULL, capacity cap).
[in]capCapacity of buf (1..255).
[out]out_lenBytes actually returned by the peripheral (the count field). Always populated on k_ra8_ok and on k_ra8_err_invalid_size.
Returns
ra8_err_t.
Return values
k_ra8_okBlock received and PEC matched if on.
k_ra8_err_null_ptrbuf / out_len NULL.
k_ra8_err_invalid_argcap is 0 or > 255.
k_ra8_err_invalid_sizeReturned count exceeds cap.
k_ra8_err_not_initializedInit not run.
k_ra8_err_crc_mismatchPEC verification failed.
Forwardedcodes from the bus seam write / read.
Precondition
ra8_smbus_init previously succeeded.
Postcondition
STOP is issued regardless of outcome.
Since
0.1.0

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.

◆ ra8_smbus_block_write()

ra8_err_t ra8_smbus_block_write ( uint8_t target_7b,
uint8_t cmd,
const uint8_t * data,
uint8_t len )
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).

Parameters
[in]target_7b7-bit peripheral address.
[in]cmdCommand / register index byte.
[in]dataPayload buffer (non-NULL when len > 0).
[in]lenNumber of bytes (1..255).
Returns
ra8_err_t.
Return values
k_ra8_okBlock written.
k_ra8_err_null_ptrdata NULL with non-zero len.
k_ra8_err_invalid_arglen is 0 or > 255.
k_ra8_err_not_initializedInit not run.
Forwardedcodes from the bus seam write.
Precondition
ra8_smbus_init previously succeeded.
Postcondition
STOP is issued.
Since
0.1.0

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.

◆ ra8_smbus_deinit()

ra8_err_t ra8_smbus_deinit ( void )
nodiscard

Tear the SMBus layer down and release the driver slot.

Returns
ra8_err_t.
Return values
k_ra8_okLayer released.
k_ra8_err_not_initializedra8_smbus_init never ran.
Precondition
Caller is not in the middle of a transaction.
Postcondition
The layer rejects transactions until the next init; the app keeps owning the bus peripheral behind the injected seam.
Since
0.1.0

Definition at line 175 of file ra8_smbus.c.

References k_ra8_err_not_initialized, k_ra8_ok, and s_state.

◆ ra8_smbus_init()

ra8_err_t ra8_smbus_init ( const ra8_smbus_cfg_t * cfg)
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.

Parameters
[in]cfgConfiguration descriptor.
Returns
ra8_err_t.
Return values
k_ra8_okSMBus layer ready.
k_ra8_err_null_ptrcfg is NULL.
k_ra8_err_invalid_argcfg->bus seam incomplete (a NULL op).
Precondition
IRQs masked or single-threaded init context.
The bus peripheral behind cfg->bus is initialised.
Postcondition
On success the layer accepts SMBus transactions.
Note
Thread safety: not thread-safe.
See also
ra8_i2c_bus_ops_t
Since
0.1.0

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().

◆ ra8_smbus_pec()

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.

Parameters
[in]dataPointer to bytes (non-NULL when len > 0).
[in]lenByte count.
Returns
Computed CRC-8 value.
Return values
0x00Either len == 0 or the input bytes happen to hash to zero.
otherComputed CRC-8 over data[0..len-1] per SMBus 3.2 section 5.4.
Precondition
data != NULL when len > 0.
len reflects the true buffer size (no aliasing past len).
Postcondition
Function is pure – no firmware state mutated.
Result depends only on data and len.
Note
Thread-safe: pure function with no shared state.
Since
0.1.0

Definition at line 122 of file ra8_smbus.c.

References internal_pec_update(), and k_ra8_smbus_pec_init.

◆ ra8_smbus_read_byte_data()

ra8_err_t ra8_smbus_read_byte_data ( uint8_t target_7b,
uint8_t cmd,
uint8_t * out_data )
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.

Parameters
[in]target_7b7-bit peripheral address.
[in]cmdCommand / register index byte.
[out]out_dataDestination byte (non-NULL).
Returns
ra8_err_t.
Return values
k_ra8_okByte read (and PEC matched if enabled).
k_ra8_err_null_ptrout_data NULL.
k_ra8_err_not_initializedInit not run.
k_ra8_err_crc_mismatchPEC verification failed.
Forwardedcodes from the bus seam write / read.
Precondition
ra8_smbus_init previously succeeded.
Postcondition
STOP is issued.
Since
0.1.0

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().

◆ ra8_smbus_receive_byte()

ra8_err_t ra8_smbus_receive_byte ( uint8_t target_7b,
uint8_t * out_data )
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

Parameters
[in]target_7b7-bit peripheral address.
[out]out_dataDestination byte (non-NULL).
Returns
ra8_err_t.
Return values
k_ra8_okByte received (and PEC matched if enabled).
k_ra8_err_null_ptrout_data is NULL.
k_ra8_err_not_initializedInit not run.
k_ra8_err_crc_mismatchPEC verification failed.
Forwardedcodes from the bus seam read.
Precondition
ra8_smbus_init previously succeeded.
Postcondition
STOP is issued, bus is released.
Since
0.1.0

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().

◆ ra8_smbus_send_byte()

ra8_err_t ra8_smbus_send_byte ( uint8_t target_7b,
uint8_t data )
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).

Parameters
[in]target_7b7-bit peripheral address.
[in]dataSingle data byte to transmit.
Returns
ra8_err_t.
Return values
k_ra8_okByte delivered.
k_ra8_err_not_initializedInit not run.
Forwardedcodes from the bus seam write.
Precondition
ra8_smbus_init previously succeeded.
Postcondition
STOP is issued, bus is released.
Since
0.1.0

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().

◆ ra8_smbus_write_byte_data()

ra8_err_t ra8_smbus_write_byte_data ( uint8_t target_7b,
uint8_t cmd,
uint8_t data )
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.

Parameters
[in]target_7b7-bit peripheral address.
[in]cmdCommand / register index byte.
[in]dataData byte to write.
Returns
ra8_err_t.
Return values
k_ra8_okByte written.
k_ra8_err_not_initializedInit not run.
Forwardedcodes from the bus seam write.
Precondition
ra8_smbus_init previously succeeded.
Postcondition
STOP is issued.
Since
0.1.0

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.