系列导读
本系列三篇文章对 Arduino 官方 10BASE-T1S 库进行完整的软件架构分析,目标是为后续移植到竞品 T1S 芯片提供技术基线:
10BASE-T1S 技术背景
10BASE-T1S 是 IEEE 802.3cg-2019 定义的单对线以太网标准,核心特性:
| 特性 | 10BASE-T1S | 传统 100BASE-TX |
|---|---|---|
| 线对数 | 1 对 | 2 对 |
| 速率 | 10 Mbps | 100 Mbps |
| 拓扑 | 多点总线(multi-drop) | 点对点 |
| 最大节点数 | 8(PLCA 模式) | 2 |
| 线缆长度 | 25m(mixing segment) | 100m |
| 碰撞处理 | PLCA 确定性轮询 | N/A(全双工) |
关键 trade-off:牺牲速率换取布线简化和多点接入能力,适合汽车/工业传感器网络场景,一根双绞线串联多个节点。
PLCA(Physical Layer Collision Avoidance)是 10BASE-T1S 的核心机制:Node ID 0 作为协调器,按固定顺序给每个节点分配发送时隙,避免 CSMA/CD 的随机退避延迟。
项目概览
| 属性 | 值 |
|---|---|
| 名称 | Arduino_10BASE_T1S |
| 版本 | 0.1.1 |
| 维护者 | Arduino (Alexander Entinger) |
| 许可证 | MPL-2.0(顶层) |
| 仓库 | https://github.com/arduino-libraries/Arduino_10BASE_T1S |
| 目标芯片 | Microchip LAN8650 / LAN8651 MAC-PHY |
| 分类 | Communication |
这是 Arduino 官方维护的库,通过 Arduino Library Manager 分发,提供从 SPI 驱动到 UDP socket 的完整协议栈。
软件架构分层
graph TB
subgraph "Application Layer"
A1["Arduino Sketch (UDP_Client / UDP_Server)"]
A2["Arduino_10BASE_T1S_UDP"]
end
subgraph "Network Layer"
B1["lwIP TCP/IP Stack"]
B2["UDP PCB / ARP / ICMP / IPv4"]
end
subgraph "Protocol Layer"
C1["libtc6 v3.1.3"]
C2["OA TC6 SPI Protocol"]
C3["Credit Mgmt / Chunk Framing"]
end
subgraph "HAL Layer"
D1["TC6_Io"]
D2["SPI + GPIO (CS/RESET/IRQ)"]
end
subgraph "Hardware"
E1["LAN8650/8651 MAC-PHY"]
E2["10BASE-T1S PHY Twisted Pair"]
end
A1 --> A2
A2 --> B1
B1 --> B2
B2 --> C1
C1 --> C2
C2 --> C3
C3 --> D1
D1 --> D2
D2 --> E1
E1 --> E2
各层职责
Application Layer — 用户代码接口,继承 Arduino 标准 UDP 基类,提供 beginPacket() / write() / endPacket() / parsePacket() 标准 API。
Network Layer — 完整的 lwIP 嵌入式 TCP/IP 协议栈,处理 ARP、ICMP、IPv4 路由、UDP 多路复用。MTU 设为 1536 字节。
Protocol Layer — Microchip 提供的 libtc6 库,实现 Open Alliance TC6 SPI 协议:将以太网帧拆分为 64 字节 chunk,附加 4 字节 header/footer,通过 SPI 全双工传输,管理 TX/RX credit 流控。
HAL Layer — TC6_Io 类封装 Arduino SPI 接口,配置 24MHz 时钟、Mode 0、MSB-first,控制 CS/RESET/IRQ 三根 GPIO。
类关系
classDiagram
class Arduino_10BASE_T1S_PHY_Interface {
<<abstract>>
+begin()
+service()
+getPlcaStatus()
+enablePlca()
}
class TC6_Arduino_10BASE_T1S {
-TC6_Io& io
-netif lwip_netif
+begin(ip, mask, gw, mac, plca, mac_settings)
+service()
+digitalWrite(dio, val)
}
class TC6_Io {
-HardwareSPI& spi
-int cs_pin, reset_pin, irq_pin
+begin()
+spiTransaction(pTx, pRx, len)
+onInterrupt()
}
class Arduino_10BASE_T1S_UDP {
-udp_pcb* pcb
-list~UdpRxPacket~ rx_pkt_list
+begin(port)
+beginPacket(ip, port)
+write(buf, len)
+endPacket()
+parsePacket()
+read(buf, len)
}
Arduino_10BASE_T1S_PHY_Interface <|-- TC6_Arduino_10BASE_T1S
TC6_Arduino_10BASE_T1S --> TC6_Io
Arduino_10BASE_T1S_UDP --> TC6_Arduino_10BASE_T1S
典型使用代码
1 | // 实例化 PHY(宏展开为 TC6_Io + TC6_Arduino_10BASE_T1S 对象) |
编译平台与 CI 矩阵
支持的架构
库声明支持 5 种 Arduino 架构:samd, renesas_uno, renesas_portenta, mbed_giga, mbed_portenta
CI 构建矩阵(7 块板卡)
| FQBN | 架构 | MCU |
|---|---|---|
arduino:samd:arduino_zero_native |
SAMD | ATSAMD21G18 (Cortex-M0+) |
arduino:samd:arduino_zero_edbg |
SAMD | ATSAMD21G18 (Cortex-M0+) |
arduino:renesas_uno:minima |
Renesas UNO | RA4M1 (Cortex-M4) |
arduino:renesas_uno:unor4wifi |
Renesas UNO | RA4M1 (Cortex-M4) |
arduino:renesas_portenta:portenta_c33 |
Renesas Portenta | RA6M5 (Cortex-M33) |
arduino:mbed_giga:giga |
Mbed GIGA | STM32H747 (Cortex-M7) |
arduino:mbed_portenta:envie_m7 |
Mbed Portenta | STM32H747 (Cortex-M7) |
板卡引脚映射
1 | // Arduino Zero / UNO R4 系列(Uno form factor) |
编译命令
1 | arduino-cli compile -b arduino:renesas_uno:unor4wifi -v examples/UDP_Client -u -p /dev/ttyACM0 |
开源状态分析
这个库并非完全开源,由三个不同许可证的组件构成:
| 组件 | 许可证 | 是否开源 | 移植影响 |
|---|---|---|---|
| Arduino 封装层 | MPL-2.0 | ✅ 完全开源,可修改分发 | 可自由修改复用 |
| Microchip libtc6 | Microchip 专有许可 | ⚠️ 源码可见,专利受限 | 需评估专利风险 |
| lwIP 协议栈 | BSD (3-clause) | ✅ 完全开源 | 可自由复用 |
| Linux 内核驱动 | GPL-2.0+ | ✅ 完全开源 | 仅限 Linux 环境 |
Microchip libtc6 的许可证关键条款:
“No license or other rights, whether express or implied, are granted under any patent or other intellectual property rights of Microchip or any third party.”
这意味着:源码可以阅读和学习,但如果竞品芯片也需要实现 OA TC6 协议,直接复用 Microchip 的 libtc6 二进制可能存在专利风险。如果竞品芯片自身提供 TC6 协议实现,或者根据 Open Alliance 规范独立实现,则不受此限制。
测试方法分析
现有测试手段
| 测试类型 | 是否具备 | 说明 |
|---|---|---|
| 单元测试 | ❌ | 无任何 test 目录或测试框架 |
| 集成测试 | ❌ | 无自动化集成测试 |
| HIL(硬件在环) | ❌ | 无自动化硬件测试 |
| CI 编译验证 | ✅ | 7 块板卡 × 全部 example 编译通过 |
| Arduino Lint | ✅ | 库结构和代码规范检查 |
| Spell Check | ✅ | codespell 拼写检查 |
实际验证方案
项目依赖手动硬件测试,典型测试拓扑:
graph LR
A["Arduino UNO R4 WiFi\n(UDP Client, Node 1)"] -->|"单对双绞线\n10BASE-T1S"| B["Multi-drop Bus"]
C["Arduino UNO R4 WiFi\n(UDP Server, Node 0)"] -->|"单对双绞线"| B
D["EVB-LAN8670-USB\n(Linux Host, Node 0)"] -->|"单对双绞线"| B
- Arduino 侧:运行 UDP_Client / UDP_Server example,通过 Serial 观察收发日志
- Linux 侧:EVB-LAN8670-USB 加载内核模块,配置 IP,用
tcpdump抓包验证 - PLCA 状态监控:代码中每秒读取 PLCA status 寄存器,检测是否回退到 CSMA/CD
测试覆盖的局限性
- 无回归测试保障 — 修改代码后只能确认编译通过,无法确认功能正确
- 无性能基线 — 无吞吐量/延迟的自动化测量
- PLCA 多节点场景 — CI 无法验证实际多节点竞争行为
- 错误恢复路径 — 未自动验证 SPI 错误、线缆断开等异常场景
这对移植工作意味着:移植后的验证完全依赖手动硬件测试,需要自建 UDP echo 测试环境。
小结
Arduino 10BASE-T1S 库是一个架构清晰的四层设计,核心依赖 Microchip libtc6 实现 OA TC6 SPI 协议。对于移植到竞品芯片:
- lwIP 和 Arduino UDP 封装层可直接复用
- HAL 层(TC6_Io)需要适配新的 SPI 接口
- 协议层是否可复用取决于竞品是否兼容 OA TC6
- 测试需要自建,因为原项目无自动化测试基础设施
下一篇将深入 OA TC6 SPI 协议的帧结构和数据流实现细节。