# micropython_I3C **Repository Path**: wth_iw0/micropython_i3c ## Basic Information - **Project Name**: micropython_I3C - **Description**: mpy史上的第一个I3C功能分支,基于mpy1.29,目前已经支持通用的软件I3C和rp2040/2350的PIO模拟I3C,PIO模拟引擎修改于I3CBlaster,支持SDR模式HDR(未测试),使用PIO模拟,测试freq可达12_500_000。Github:https://github.com/iw0-wth/micropython_i3c - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2026-07-06 - **Last Updated**: 2026-07-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MicroPython I3C — an I3C fork of MicroPython This is a fork of [MicroPython](https://github.com/micropython/micropython) that adds **I3C** support, structured like the built-in `machine.I2C`: a generic framework in `extmod/` plus thin per-port adapters. It currently ships: - **`machine.I3C`** — a PIO-based I3C controller for **RP2040 / RP2350**, with full I3C SDR, dynamic address assignment, CCC, IBI, HDR-DDR, legacy-I2C compatibility and dual-bus (PIO0/PIO1). The PIO engine is ported from [I3CBlaster](https://github.com/xyphro/I3CBlaster) (MIT, Kai Gossner / xyphro). - **`machine.SoftI3C`** — a **generic, GPIO bit-banged** I3C SDR controller that runs on any port (no port code needed), for bring-up and MCUs without an I3C peripheral. > ⚠️ **SoftI3C speed is not yet characterised.** It is verified *functional* on > RP2040 (scan / RSTDAA / ENTDAA / SDR read-write / legacy-I2C), but its maximum > reliable clock has **not been measured** — treat it as low-speed. Verified on RP2040 with a mixed bus of **2× P3T1755 (I3C temperature sensors) + BMP180 (I2C pressure sensor)**. ## Documentation | Doc | What | |-----|------| | [`machine.I3C` API](ports/rp2/i3c/API.md) | Full API of the PIO I3C class (RP2 port) | | [Technical report](ports/rp2/i3c/TECH_REPORT.md) | Design, port of I3CBlaster, stability fixes | | [RP2 I3C overview + build](ports/rp2/i3c/README.md) | rp2 engine overview & build recipe | | [`machine.SoftI3C` doc](extmod/SOFTI3C.md) | The generic GPIO bit-bang I3C (SDR) | | [Porting guide](extmod/machine_i3c_PORTING.md) | How to add `machine.I3C` to a new port | ## Demo (measured, RP2040) One bus, multiple devices (I3C + legacy I2C together). **`machine.I3C` (PIO):** | SETDASA assign (12.5 MHz) | ENTDAA assign (12.5 MHz) | I2C compat (multi-device) | |---|---|---| | ![setdasa](images/一挂多setdasa测试_12.5M.png) | ![entdaa](images/一挂多entdaa测试_12.5M.png) | ![i2c](images/一挂多I2C兼容测试.png) | **`machine.SoftI3C` (generic GPIO bit-bang):** | SETDASA assign | ENTDAA assign | I2C compat (multi-device) | |---|---|---| | ![s-setdasa](images/软件I3C的satdasa测试.png) | ![s-entdaa](images/软件I3C的entdaa测试.png) | ![s-i2c](images/软件I3C一挂多I2C兼容测试.png) | > 🔌 **SoftI3C: do NOT add external pull-ups.** The bit-bang engine drives SDA > push-pull for I3C SDR data; an external pull-up fights that and corrupts reads. > It enables the internal pull-up itself for the open-drain phases. (`machine.I3C` > on PIO is different — it can use external pull-ups for higher-speed open-drain.) ## Quick start ```python from machine import Pin, I3C # scl must be sda + 1 (the PIO engine uses SDA as the base pin) i3c = I3C(scl=Pin(17), sda=Pin(16), freq=8_000_000) # id omitted → first free PIO # assign a dynamic address: by static address (SETDASA) or discovery (ENTDAA) i3c.rstdaa() i3c.setdasa(0x48, 0x30) # static 0x48 → dynamic 0x30 # or: for a in i3c.entdaa_all(0x30): ... # enroll every DAA-capable device print([hex(a) for a in i3c.scan()]) # e.g. [0x30, 0x7e] raw = i3c.readfrom_mem(0x30, 0x00, 2) # read a register (P3T1755 temperature) temp = ((raw[0] << 8 | raw[1]) >> 4) * 0.0625 print("temp:", temp, "C") ``` For a portable software bus, swap `I3C` for `SoftI3C` (low speed — see the note above and [SoftI3C doc](extmod/SOFTI3C.md)). ## Firmware Pre-built UF2 in [`firmware/`](firmware/): - `micropython_i3c_rp2040.uf2` — Raspberry Pi Pico (RP2040) - `micropython_i3c_rp2350.uf2` — Raspberry Pi Pico 2 (RP2350) Hold **BOOTSEL**, plug in USB, drop the UF2 onto the drive. ## Building from source This repo is a **sparse overlay** — it contains only the files that this fork adds or changes, *not* a full MicroPython tree. To build: 1. Get a clean **MicroPython v1.29.0** checkout and its submodules (`pico-sdk`, `tinyusb`, `mbedtls`, ...). 2. Overlay these files on top (they include one generic build fix, `py/makeqstrpp.py` + `py/mkrules.cmake`, needed for native Windows builds). 3. Build `mpy-cross`, then CMake+Ninja the `ports/rp2` target with the ARM toolchain. For RP2350 use `-DMICROPY_BOARD=RPI_PICO2`. Full, verified recipe (Windows + MSYS2): see [ports/rp2/i3c/README.md](ports/rp2/i3c/README.md). ## Credits & licence The low-level PIO I3C engine is ported from [I3CBlaster](https://github.com/xyphro/I3CBlaster) (MIT, Kai Gossner / xyphro); its copyright header is retained in `ports/rp2/i3c/i3c_hl.c/.h` and `i3c.pio`. Everything else follows MicroPython's MIT licence. ---
中文说明(点击展开) ## 这是什么 这是 [MicroPython](https://github.com/micropython/micropython) 的一个 **I3C 分支**, 参照内置的 `machine.I2C` 架构:`extmod/` 里放通用框架,各 port 写薄适配器。目前提供: - **`machine.I3C`** —— 基于 PIO 的 I3C 控制器,支持 **RP2040 / RP2350**,含完整 I3C SDR、动态地址分配、CCC、IBI、HDR-DDR、传统 I2C 兼容、双总线(PIO0/PIO1)。 底层 PIO 引擎移植自 [I3CBlaster](https://github.com/xyphro/I3CBlaster)(MIT)。 - **`machine.SoftI3C`** —— **通用的 GPIO 位模拟** I3C SDR 控制器,任何 port 都能用 (无需 port 代码),用于调试和没有 I3C 外设的 MCU。 > ⚠️ **软件 I3C(SoftI3C)目前尚未测速。** 已在 RP2040 上验证**功能可用** > (scan / RSTDAA / ENTDAA / SDR 读写 / 传统 I2C),但**最高可靠时钟未测**,请当作 > 低速使用。 已在 RP2040 上以 **2×P3T1755(I3C 温度传感器)+ BMP180(I2C 气压传感器)混合总线**验证。 ## 文档 | 文档 | 内容 | |------|------| | [`machine.I3C` API](ports/rp2/i3c/API.md) | PIO I3C 类完整 API(RP2 端口) | | [技术报告](ports/rp2/i3c/TECH_REPORT.md) | 设计、I3CBlaster 移植、稳定性修复 | | [RP2 I3C 总览与编译](ports/rp2/i3c/README.md) | rp2 引擎总览与编译配方 | | [`machine.SoftI3C` 文档](extmod/SOFTI3C.md) | 通用 GPIO 位模拟 I3C(SDR) | | [移植指南](extmod/machine_i3c_PORTING.md) | 如何给新 port 添加 `machine.I3C` | ## 演示(实测,RP2040) 一条总线挂多个器件(I3C 与传统 I2C 共存)。 **`machine.I3C`(PIO):** | SETDASA 分配 (12.5MHz) | ENTDAA 分配 (12.5MHz) | I2C 兼容 (一挂多) | |---|---|---| | ![setdasa](images/一挂多setdasa测试_12.5M.png) | ![entdaa](images/一挂多entdaa测试_12.5M.png) | ![i2c](images/一挂多I2C兼容测试.png) | **`machine.SoftI3C`(通用 GPIO 位模拟):** | SETDASA 分配 | ENTDAA 分配 | I2C 兼容 (一挂多) | |---|---|---| | ![s-setdasa](images/软件I3C的satdasa测试.png) | ![s-entdaa](images/软件I3C的entdaa测试.png) | ![s-i2c](images/软件I3C一挂多I2C兼容测试.png) | > 🔌 **SoftI3C:请勿加外部上拉。** 位模拟引擎在 I3C SDR 数据相位以推挽驱动 SDA, > 外部上拉会与之冲突、导致读取出错;开漏相位所需的上拉由内部上拉自动提供。 > (`machine.I3C`(PIO)不同——它可用外部上拉以支持更高速的开漏相位。) ## 快速上手 ```python from machine import Pin, I3C # scl 必须 == sda + 1(PIO 引擎以 SDA 为基引脚) i3c = I3C(scl=Pin(17), sda=Pin(16), freq=8_000_000) # 省略 id → 自动选空闲 PIO # 分配动态地址:静态地址法(SETDASA) 或 动态发现(ENTDAA) i3c.rstdaa() i3c.setdasa(0x48, 0x30) # 静态 0x48 → 动态 0x30 # 或: for a in i3c.entdaa_all(0x30): ... # 登记所有支持 DAA 的器件 print([hex(a) for a in i3c.scan()]) # 如 [0x30, 0x7e] raw = i3c.readfrom_mem(0x30, 0x00, 2) # 读寄存器(P3T1755 温度) temp = ((raw[0] << 8 | raw[1]) >> 4) * 0.0625 print("温度:", temp, "C") ``` 需要可移植的软件总线时,把 `I3C` 换成 `SoftI3C`(低速,见上方提示与 [SoftI3C 文档](extmod/SOFTI3C.md))。 ## 从源码编译 本仓库是**稀疏 overlay** —— 只含本 fork 新增/修改的文件,**不是**完整 MicroPython 树。编译步骤: 1. 取一份干净的 **MicroPython v1.29.0** 源码及其子模块(`pico-sdk`、`tinyusb`、 `mbedtls` 等)。 2. 把本仓库文件覆盖上去(含一个通用构建修复 `py/makeqstrpp.py` + `py/mkrules.cmake`, Windows 原生编译所需)。 3. 先 build `mpy-cross`,再用 ARM 工具链 CMake+Ninja 编 `ports/rp2`。RP2350 用 `-DMICROPY_BOARD=RPI_PICO2`。 完整、已验证的配方(Windows + MSYS2)见 [ports/rp2/i3c/README.md](ports/rp2/i3c/README.md)。 ## 固件 预编译 UF2 见 [`firmware/`](firmware/): - `micropython_i3c_rp2040.uf2` —— 树莓派 Pico(RP2040) - `micropython_i3c_rp2350.uf2` —— 树莓派 Pico 2(RP2350) 按住 **BOOTSEL** 插 USB,把 UF2 拖到出现的 U 盘即可。 ## 致谢与许可 底层 PIO I3C 引擎移植自 [I3CBlaster](https://github.com/xyphro/I3CBlaster)(MIT, Kai Gossner / xyphro),版权头保留于 `ports/rp2/i3c/i3c_hl.c/.h` 与 `i3c.pio`。 其余部分遵循 MicroPython 的 MIT 许可。