跳转至

lib/iic/iic.h

I2C (IIC) abstraction layer for CFBD drivers. More...

Classes

Name
struct _CFBD_I2C_Message
struct CFBD_I2COperations
Function table that a backend must implement to drive an I2C bus.
struct _CFBD_I2CHandle
struct CFBD_I2C_IORequestParams
Helper structure used by convenience read/write helpers.

Types

Name
typedef struct _CFBD_I2C_Message CFBD_I2C_Message
typedef void(int status, void *arg) CFBD_I2C_AsyncCallback
Signature for asynchronous I2C transfer completion callbacks.
typedef struct _CFBD_I2CHandle CFBD_I2CHandle
Opaque forward-declared type representing an I2C bus instance.
typedef void * CFBD_I2CPrivateHandle
Opaque pointer for backend-private state stored in the handle.

Defines

Name
I2C_M_RD
Flag indicating a read transfer (slave -> master).
I2C_M_NOSTART
Flag to suppress START condition between messages.

Detailed Description

I2C (IIC) abstraction layer for CFBD drivers.

This header defines a lightweight, backend-pluggable I2C interface used by drivers in the project (for example the OLED driver). The abstraction exposes message-based transfers, device readiness checks, error reporting and optional DMA hooks. Concrete backends implement the [CFBD_I2COperations](Classes/structCFBD__I2COperations.md) table and populate [CFBD_I2CHandle](Classes/structCFBD__I2CHandle.md).

Types Documentation

typedef CFBD_I2C_Message

typedef struct _CFBD_I2C_Message CFBD_I2C_Message;

typedef CFBD_I2C_AsyncCallback

CFBD_I2C_AsyncCallback;

Signature for asynchronous I2C transfer completion callbacks.

Parameters:

  • status Result status code (I2C_OK or negative error code).
  • arg User-provided argument passed through the async API.

Par: Example - Async Transfer with Callback

struct TransferContext {
    uint8_t *data;
    size_t len;
    int error_count;
} ctx;

void transfer_complete_callback(int status, void *arg) {
    struct TransferContext *ctx = (struct TransferContext *)arg;

    if (status != I2C_OK) {
        ctx->error_count++;
        if (status == I2C_ERR_TIMEOUT) {
            // Timeout handling
            schedule_retry();
        }
    } else {
        // Transfer successful
        process_received_data(ctx->data, ctx->len);
    }
}

// Initiate async transfer
ctx.data = buffer;
ctx.len = sizeof(buffer);
CFBD_I2CTransferAsync(bus, msgs, count, transfer_complete_callback, &ctx);

Called when an asynchronous I2C operation completes. Enables interrupt-driven or DMA-based transfers without blocking the main application thread.

typedef CFBD_I2CHandle

typedef struct _CFBD_I2CHandle CFBD_I2CHandle;

Opaque forward-declared type representing an I2C bus instance.

Represents a single I2C bus in the system. The handle combines backend-agnostic operations with platform-specific state.

typedef CFBD_I2CPrivateHandle

CFBD_I2CPrivateHandle;

Opaque pointer for backend-private state stored in the handle.

Backend implementations use this to store any hardware-specific data, such as peripheral base addresses, interrupt handlers, DMA channel info, etc.

Macros Documentation

define I2C_M_RD

#define I2C_M_RD 0x0001 /* read data, from slave to master */

Flag indicating a read transfer (slave -> master).

Par: Example - Combined Write-Read Transfer

// Many I2C devices require: write address, then read data
CFBD_I2C_Message msgs[2];
uint8_t cmd = 0x01;  // Command/register
uint8_t response[8];

// Write command (no I2C_M_RD flag)
msgs[0].addr = 0x50;
msgs[0].flags = 0;
msgs[0].len = 1;
msgs[0].buf = &cmd;

// Read response (with I2C_M_RD flag)
msgs[1].addr = 0x50;
msgs[1].flags = I2C_M_RD;  // Indicates read operation
msgs[1].len = sizeof(response);
msgs[1].buf = response;

CFBD_I2CTransfer(bus, msgs, 2, 1000);

When set in a message's flags field, indicates that the message direction is a read operation (master receives from slave).

define I2C_M_NOSTART

#define I2C_M_NOSTART 0x4000 /* no start between messages (rare) */

Flag to suppress START condition between messages.

When set, prevents generation of a START condition before this message. Used in specialized scenarios (rare) where messages should be combined without intermediate START conditions.

Source code

#pragma once
#include <stddef.h>
#include <stdint.h>

#include "iic_error.h"

#define I2C_M_RD 0x0001 /* read data, from slave to master */

#define I2C_M_NOSTART 0x4000 /* no start between messages (rare) */

typedef struct _CFBD_I2C_Message
{
    uint16_t addr;  
    uint16_t flags; 
    uint16_t len;   
    uint8_t* buf;   
} CFBD_I2C_Message;

/* Async Callbacks */
typedef void CFBD_I2C_AsyncCallback(int status, void* arg);

typedef struct _CFBD_I2CHandle CFBD_I2CHandle;

typedef struct
{
    int (*init)(CFBD_I2CHandle* handle);

    int (*deinit)(CFBD_I2CHandle* handle);

    int (*transfer)(CFBD_I2CHandle* bus, CFBD_I2C_Message* msgs, int num, uint32_t timeout_ms);

    int (*is_device_ready)(CFBD_I2CHandle* bus,
                           uint16_t addr,
                           uint32_t trials,
                           uint32_t timeout_ms);

    int (*recover_bus)(CFBD_I2CHandle* bus);

    int (*get_error)(CFBD_I2CHandle* bus);

    /* optional DMA hooks */
    int (*tx_dma_start)(CFBD_I2CHandle* bus, const uint8_t* buf, size_t len);

    int (*rx_dma_start)(CFBD_I2CHandle* bus, uint8_t* buf, size_t len);
} CFBD_I2COperations;

typedef void* CFBD_I2CPrivateHandle;

typedef struct _CFBD_I2CHandle
{
    const CFBD_I2COperations* ops;        
    CFBD_I2CPrivateHandle private_handle; 
} CFBD_I2CHandle;

/* --------- inline wrappers  ---------- */
static inline int CFBD_I2CInit(CFBD_I2CHandle* bus)
{
    if (!bus || !bus->ops || !bus->ops->init)
        return I2C_ERR_INVAL;
    return bus->ops->init(bus);
}

static inline int CFBD_I2CDeInit(CFBD_I2CHandle* bus)
{
    if (!bus || !bus->ops || !bus->ops->deinit)
        return I2C_ERR_INVAL;
    return bus->ops->deinit(bus);
}

static inline int
CFBD_I2CTransfer(CFBD_I2CHandle* bus, CFBD_I2C_Message* msgs, int num, uint32_t timeout_ms)
{
    if (!bus || !bus->ops || !bus->ops->transfer)
        return I2C_ERR_INVAL;
    return bus->ops->transfer(bus, msgs, num, timeout_ms);
}

static inline int CFBD_I2CTransferIsDeviceReady(CFBD_I2CHandle* bus,
                                                uint16_t addr,
                                                uint32_t trials,
                                                uint32_t timeout_ms)
{
    if (!bus || !bus->ops || !bus->ops->is_device_ready)
        return I2C_ERR_INVAL;
    return bus->ops->is_device_ready(bus, addr, trials, timeout_ms);
}

static inline int CFBD_I2CRecoverBus(CFBD_I2CHandle* bus)
{
    if (!bus || !bus->ops || !bus->ops->recover_bus)
        return I2C_ERR_INVAL;
    return bus->ops->recover_bus(bus);
}

typedef struct
{
    uint16_t addr7;        
    uint32_t mem_addr;     
    uint8_t mem_addr_size; 
    uint8_t* data;         
    uint16_t len;          
    uint32_t timeout_ms;   
} CFBD_I2C_IORequestParams;

int CFBD_I2CRead(CFBD_I2CHandle* handle, CFBD_I2C_IORequestParams* r);

int CFBD_I2CWrite(CFBD_I2CHandle* handle, CFBD_I2C_IORequestParams* r);

#include "lib_settings.h"
#if defined(CFBD_IS_ST)
#include "backend/i2c_stm_impl.h"
#else
#error "No supports chips"
#endif

Updated on 2026-02-03 at 13:21:55 +0000