I3C协议介绍

下面我从"协议本身"出发 ,把 I³C(Improved Inter-Integrated Circuit)协议 做一次偏规范级、但仍然偏工程实现 的完整拆解。

我会尽量按 "你如果要写驱动 / 看协议 / 调 I3C 外设" 的思路来讲。


一、I³C 协议的设计目标(为什么会有 I³C)

I³C 不是单纯"更快的 I²C",而是为了解决 I²C 的系统级问题

I²C 痛点 I³C 对应解决方案
速度慢 SDR / HDR 高速
上拉功耗高 推挽驱动
地址冲突 动态地址分配(DAA)
从机不能主动通信 IBI
无即插即用 Hot-Join
扩展性差 CCC 命令体系

二、I³C 总线基础结构

1️⃣ 总线角色

Master / Slave(Controller / Target)

术语 旧称
Controller Master
Target Slave

I³C 官方文档中逐步使用 Controller / Target


支持的角色能力

角色 能力
Primary Controller 负责 DAA、总线管理
Secondary Controller 可接管总线
Target 响应访问 / 发送 IBI

2️⃣ 设备类型

设备类型 说明
I³C Target 原生 I³C 设备
I²C Target 兼容旧设备
Mixed Bus I²C + I³C 共存

📌 I³C 总线必须能容忍 I²C 设备存在


三、I³C 的地址体系(核心)

1️⃣ 静态地址(Static Address)

  • 与 I²C 类似
  • 可选
  • 主要用于兼容 / 简化

2️⃣ 动态地址(Dynamic Address)⭐⭐⭐

🔹 核心思想

I³C 设备出厂时没有地址

主机在上电后统一分配


🔹 分配流程(DAA)

text 复制代码
1. 上电
2. 主机发送 ENTDAA CCC
3. 从设备依次发送唯一ID
4. 主机分配动态地址

🔹 唯一 ID(PID / BCR / DCR)

字段 含义
PID Provisional ID(厂商+设备唯一)
BCR Bus Characteristic Register
DCR Device Characteristic Register

📌 类似 USB 枚举 + MAC 地址


3️⃣ 地址优先级

地址类型 优先级
动态地址
静态地址

四、CCC(Common Command Codes)------I³C 的"灵魂"

CCC 是 I³C 协议最核心的扩展点


1️⃣ CCC 分类

🔹 Broadcast CCC(广播)

  • 地址:0x7E
  • 所有设备接收
命令 作用
ENTDAA 进入动态地址分配
RSTDAA 重置动态地址
SETMWL 设置最大写长度
SETMRL 设置最大读长度

🔹 Directed CCC(定向)

  • 指定设备
命令 作用
GETPID 读取设备 ID
GETBCR 查询能力
GETSTATUS 状态获取
ENEC / DISEC 中断使能

2️⃣ CCC 在驱动中的意义

驱动初始化 = 一堆 CCC 命令

text 复制代码
RSTDAA
ENTDAA
GETPID
GETBCR
SETMWL / SETMRL

📌 I³C 驱动 ≈ 小型协议栈


五、数据传输模式

1️⃣ SDR(Single Data Rate)

  • 默认模式
  • 最高 12.5 Mbps
  • 最常用

2️⃣ HDR(High Data Rate)

模式 特点
HDR-DDR 双边沿
HDR-TSP 三态
HDR-TSL 低摆幅

📌 HDR 通常用于 高速 sensor / camera 辅助链路


3️⃣ 私有传输(Private Transfer)

  • 类似 I²C 普通读写
  • 不走 CCC
  • 日常数据主要靠它

六、IBI(In-Band Interrupt)⭐⭐⭐

1️⃣ IBI 是什么?

从设备在 SDA/SCL 上直接"打断"主机

不需要 GPIO 中断线。


2️⃣ IBI 触发流程

text 复制代码
Target 拉低 SDA → 仲裁 → 主机响应 → IBI 数据

3️⃣ IBI 类型

类型 用途
Interrupt 事件通知
Hot-Join 设备动态加入
Master Request 请求主控切换

4️⃣ 软件意义

  • 事件驱动
  • 极低功耗
  • 非轮询

📌 I³C 非常适合 RTOS + sensor hub


七、热插拔(Hot-Join)

工作流程

text 复制代码
新设备上电
↓
发送 Hot-Join IBI
↓
主机 ENTDAA
↓
分配地址

📌 I²C 做不到


八、多主与主控切换

特性 I²C I³C
多主支持 理论支持 规范化
主切换 Master Handoff

九、时序与仲裁机制

1️⃣ 仲裁规则

  • SDA 线仲裁
  • 低电平优先
  • 推挽阶段避免冲突

2️⃣ 起始/停止条件

与 I²C 类似,但:

  • 起始阶段为开漏
  • 数据阶段为推挽

十、错误检测与可靠性

功能 I³C
ACK/NACK
CRC
超时检测
设备复位 CCC

十一、I³C 驱动实现视角(非常关键)

1️⃣ 驱动分层

text 复制代码
应用层
 └─ I3C API
     └─ CCC 管理
         └─ Transfer Engine
             └─ I3C 外设寄存器

2️⃣ 初始化流程(典型)

c 复制代码
i3c_init();
send_ccc(RSTDAA);
send_ccc(ENTDAA);
foreach(target)
{
    get_pid();
    get_bcr();
    set_mrl_mwl();
}

3️⃣ RTOS 下重点

  • IBI → ISR → 消息队列
  • CCC 状态机
  • 锁与总线仲裁

十二、与 SPI 的工程对比(很多人误解)

项目 SPI I³C
速度 更快
引脚
中断 额外线 IBI
地址 自动
拓扑 点对点 总线

📌 I³C 是 I²C + SPI 的折中升级方案


十三、真实工程选型建议(给你)

结合你嵌入式 + SoC + RTOS背景:

  • ✔ 多传感器 → I³C
  • ✔ 低功耗 → I³C
  • ✔ 老设备多 → I²C
  • ✔ 摄像头数据主通道 → SPI / MIPI

最后一段总结(工程师视角)

I³C ≠ 简单外设接口
I³C ≈ 一条"轻量级系统总线"

它的复杂度,已经接近:

  • USB 枚举
  • PCIe 设备发现(简化版)

如果你愿意,下一步我可以:

  • 🧩 结合 STM32 / GD32 的 I3C 外设寄存器讲驱动
  • 📐 画 DAA / IBI 时序图
  • 🧠 I3C 协议栈拆分成状态机
  • 🔧 分析 Linux I3C 子系统(i3c core)

你想从 "硬件 / 裸机 / RTOS / Linux" 哪个角度继续深入?




太好了,这一问正中 I³C 的工程核心 🔥

下面我就完全站在「MCU 裸机驱动 I3C」的角度 ,一步一步把 驱动工作流程、状态机、关键细节、坑点 讲清楚。

你可以把这篇当成:"写 I3C 裸机驱动前的设计文档"


一、MCU 裸机 I³C 驱动的整体视角

先给你一个总览框架,避免一上来被 CCC / DAA 吓到。

1️⃣ 裸机 I3C 驱动的本质

I3C 裸机驱动 = 外设驱动 + 协议状态机

text 复制代码
I3C 外设寄存器
   ↓
传输引擎(TX/RX FIFO / DMA)
   ↓
CCC 管理层(协议)
   ↓
设备管理(地址 / 能力)
   ↓
应用层 API

📌 重点

I²C 裸机 ≈ "发地址 + 发数据"

I³C 裸机 ≈ "枚举设备 + 管理设备 + 传输数据"


二、I3C 裸机驱动的生命周期(全流程)

阶段划分(非常重要)

text 复制代码
① 硬件初始化
② 总线初始化
③ 设备枚举(DAA)
④ 设备能力识别
⑤ 正常数据通信
⑥ IBI / Hot-Join 处理

三、① 硬件初始化(外设层)

1️⃣ GPIO / 时钟 / 复位

c 复制代码
i3c_clk_enable();
i3c_reset();
i3c_gpio_init(SDA, SCL);

注意点(⚠️):

  • SDA/SCL 必须支持:

    • 开漏
    • 推挽
  • 不能强拉上拉(除非混接 I2C)


2️⃣ I3C 控制器基础配置

关键配置项(不同 MCU 名字不同):

配置 说明
Role Primary Controller
Mode I3C
Open-Drain 起始阶段
Push-Pull 数据阶段
Clock 8~12.5MHz
c 复制代码
I3C->CTRL = MASTER | I3C_MODE;
I3C->CLKDIV = calc_div(12_500_000);

📌 这一步只是"能发波形",还不能通信


四、② 总线初始化(协议准备)

1️⃣ 总线空闲检测

c 复制代码
while (!bus_idle());
  • SDA = 1
  • SCL = 1

2️⃣ 清空状态

c 复制代码
clear_fifo();
clear_interrupt();

五、③ 设备枚举(DAA)⭐⭐⭐(核心)

1️⃣ 为什么裸机 DAA 是最难的?

  • 多设备竞争
  • 位级仲裁
  • 状态机复杂
  • 错一步,全盘崩

👉 好消息
MCU 的 I3C 外设通常"硬件实现 DAA"


2️⃣ DAA 裸机流程(逻辑)

text 复制代码
发送 ENTDAA (Broadcast CCC)
↓
设备按优先级发送 PID
↓
主机逐个分配动态地址
↓
DAA 完成

3️⃣ 裸机代码结构(伪代码)

c 复制代码
send_ccc(CCC_ENTDAA);

while (i3c_daa_in_progress())
{
    if (device_found())
    {
        pid = read_pid();
        assign_dynamic_addr(next_addr++);
        save_device(pid, addr);
    }
}

4️⃣ 你需要维护的数据结构

c 复制代码
typedef struct {
    uint64_t pid;
    uint8_t  dyn_addr;
    uint8_t  bcr;
    uint8_t  dcr;
} i3c_dev_t;

i3c_dev_t dev_table[MAX_I3C_DEV];

📌 这一步相当于 USB 枚举


六、④ 设备能力识别(CCC 查询)

DAA 完成 ≠ 可用

你还不知道设备能干嘛!


1️⃣ 必做的 CCC 查询

CCC 目的
GETPID 验证
GETBCR 是否支持 IBI
GETDCR 设备类型
GETMRL 最大读
GETMWL 最大写

2️⃣ 裸机执行方式

c 复制代码
send_direct_ccc(dev->addr, CCC_GETBCR, &bcr);
send_direct_ccc(dev->addr, CCC_GETMRL, &mrl);

3️⃣ 建立"设备能力表"

c 复制代码
dev->ibi_supported = bcr & BCR_IBI;
dev->max_rd_len    = mrl;

📌 驱动后续逻辑全靠它


七、⑤ 正常数据通信(Private Transfer)

1️⃣ I3C 裸机最常用 API

c 复制代码
i3c_write(dev, buf, len);
i3c_read(dev, buf, len);

2️⃣ 实际底层流程

text 复制代码
START
→ 动态地址 + R/W
→ 数据(推挽)
→ ACK
→ STOP

3️⃣ 裸机实现方式

方式一:轮询(最简单)

c 复制代码
while (!tx_fifo_empty());
write_data();

方式二:中断(推荐)

c 复制代码
ISR:
  if (TX_TH)
    fill_fifo();

4️⃣ 错误处理(必须)

错误 处理
NACK 重试
Timeout 复位控制器
Arbitration Lost 重来

八、⑥ IBI(In-Band Interrupt)处理 ⭐⭐⭐

1️⃣ IBI 在裸机中的地位

I3C 裸机真正"高级"的地方


2️⃣ IBI 裸机处理流程

text 复制代码
设备拉低 SDA
↓
I3C 中断
↓
识别 IBI
↓
读 IBI 数据
↓
回 ACK

3️⃣ ISR 结构示例

c 复制代码
void I3C_IRQHandler(void)
{
    if (IBI_PENDING)
    {
        addr = get_ibi_src();
        read_ibi_payload();
        set_event_flag(addr);
    }
}

📌 ISR 只做事件上报,别做复杂逻辑


九、⑦ Hot-Join(动态插拔)

裸机处理思路

text 复制代码
收到 Hot-Join IBI
↓
重新 ENTDAA
↓
新增设备入表

十、状态机设计(关键设计点)

推荐状态机

text 复制代码
RESET
 → INIT
 → DAA
 → ENUM_DONE
 → RUN
    → IBI
    → ERROR

十一、裸机常见"坑点总结"(非常重要)

❌ 把 I3C 当 I2C 用

❌ 只写 read/write

✅ 必须做枚举


❌ 忽略 CCC 返回值

CCC 失败 ≠ 总线失败

可能设备不支持


❌ IBI 放主循环处理

IBI = 中断级事件
一定进 ISR


❌ 不做设备表

多设备必炸


十二、裸机 vs RTOS 的差异

项目 裸机
IBI ISR + flag
设备管理 静态表
互斥 关中断
复杂度

十三、一句话总结(工程师版)

MCU 裸机 I3C 驱动 = I2C 驱动 + USB 枚举思想 + 中断事件机制


如果你下一步愿意,我可以继续帮你:

  • 🧠 给你画一个 I3C 裸机状态机图
  • 🔧 结合 STM32 / GD32 的 I3C 寄存器写示例
  • 🧩 拆一个最小可跑的 I3C 裸机框架
  • 🚀 讲 IBI 在低功耗系统里的用法

你更想 "看代码结构" 还是 "看具体寄存器/时序"

相关推荐
代码游侠16 分钟前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
xuxg20052 小时前
4G 模组 AT 命令解析框架课程正式发布
stm32·嵌入式·at命令解析框架
CODECOLLECT4 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen5 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制
万法若空6 小时前
8086/8088实模式的内存布局
汇编
全栈游侠7 小时前
STM32F103XX 02-电源与备份寄存器
stm32·单片机·嵌入式硬件
深圳市九鼎创展科技10 小时前
瑞芯微 RK3399 开发板 X3399 评测:高性能 ARM 平台的多面手
linux·arm开发·人工智能·单片机·嵌入式硬件·边缘计算
辰哥单片机设计10 小时前
STM32项目分享:车辆防盗报警系统
stm32·单片机·嵌入式硬件
風清掦11 小时前
【江科大STM32学习笔记-05】EXTI外部中断11
笔记·stm32·学习
小龙报11 小时前
【51单片机】从 0 到 1 玩转 51 蜂鸣器:分清有源无源,轻松驱动它奏响新年旋律
c语言·数据结构·c++·stm32·单片机·嵌入式硬件·51单片机