记录 ebf_qm6m5 板卡(R7FA6M5BH3CFC)在 Zephyr 4.4 下驱动板载以太网(LAN8720A,RMII) 并实现 DHCP 自动获取 IP 的完整过程与踩坑。最终效果:app/lcd_demo 上板后 DHCP 获取 IP 并显示在 LCD 上。本文按"结论速查 → 移植配置 → 四个坑 → 调试方法"组织。
结论速查
| PHY 芯片 | LAN8720AI-CP-TR(U16),PHY ID 0x0007c0f1 |
| PHY MDIO 地址 | 0x0(PHYAD0 实际为下拉,不是原理图推断的 0x1) |
| RMII 时钟 | PHY 侧 25MHz 晶振,REFCLKO 输出 50MHz → MCU P701(输入) |
| PHY 复位 | P802 低有效,线上有 10uF 电容,dts 必须给足复位时序 |
| MAC 地址 | dts local-mac-address = [02 00 5e 10 20 30](本地管理地址) |
| IDAU 分区 | 一次性操作,用 RFP 在 boot 模式写入 zephyr.rpd,否则 EDMAC 报 ADE |
| DHCP 启动 | Zephyr 不会自动启动,应用必须调 net_dhcpv4_start() |
RMII/MDIO 引脚(与 EK-RA6M5 不同,不能照抄 EK 的 pinctrl):
| TXD0 | P700 | RXD0 | P702 |
| TXD1 | P406 | RXD1 | P703 |
| TXEN | P405 | RXER | P704 |
| REF50CK | P701 | CRS_DV | P705 |
| MDC | P214 | MDIO | P211 |
移植配置(最终生效版本)
板卡 dts(boards/ebf/ebf_qm6m5/ebf_qm6m5.dts)
使能 &ioport7、&ioport8(P7xx 数据脚与复位脚 P802 所在端口);
ð:local-mac-address + status = "okay" + phy-handle = <&phy>;
&mdio:pinctrl 挂在 mdio 节点上(Zephyr RA 驱动设计如此),PHY 子节点:
phy: ethernet-phy@0 {
compatible = "ethernet-phy";
reg = <0>; /* PHYAD0 下拉,实测地址 0 应答 */
reset-gpios = <&ioport8 2 GPIO_ACTIVE_LOW>; /* P802 */
reset-assert-duration-us = <10000>; /* 缺省为 0,必须显式给! */
reset-deassertion-timeout-ms = <100>; /* 缺省为 0,必须显式给! */
status = "okay";
};pinctrl(ebf_qm6m5-pinctrl.dtsi)
ether_default 组,10 个引脚全部用 RA_PSEL(RA_PSEL_ETH_RMII, port, pin),drive-strength = "high"。
应用配置(app/lcd_demo/prj.conf)
CONFIG_NETWORKING=y CONFIG_NET_L2_ETHERNET=y CONFIG_NET_IPV4=y CONFIG_NET_IPV6=n CONFIG_NET_ARP=y CONFIG_NET_UDP=y CONFIG_NET_DHCPV4=y CONFIG_NET_MGMT=y CONFIG_NET_MGMT_EVENT=y CONFIG_NET_SHELL=y # 调试期建议保留(net iface / net ipv4)
CONFIG_ETH_RENESAS_RA、CONFIG_PHY_GENERIC_MII、CONFIG_MDIO 随 dts 节点自动开启。
应用代码要点(app/lcd_demo/src/main.c)
net_mgmt_init_event_callback(&cb, handler, NET_EVENT_IPV4_ADDR_ADD) 注册地址事件;
net_dhcpv4_start(net_if_get_default()) 显式启动 DHCP;
事件回调里只做 net_addr_ntop() 存字符串 + 置标志位,LVGL 标签在主循环里更新(net 事件线程直接碰 LVGL 不安全)。
坑 1:PHY 地址不是原理图推断的 0x1,而是 0x0
docs/启明6M5开发板_引脚分配.md 最初根据"PHYAD0 上拉"推断地址 0x1, 结果 phy_mii: No PHY found at address 1。
定位方法:在 main() 里加一段临时 MDIO 扫描(mdio_read() 遍历地址 0~31 读寄存器 2/3 的 PHY ID),实测只有地址 0 应答,ID 0x0007c0f1(LAN8720A 的 OUI)。 教训:PHY strap 电阻的实际贴装以上板扫描为准,文档已更正为 0x0。
坑 2:通用 PHY 驱动的复位时序缺省值是 0
phy_mii.c 中 reset-assert-duration-us / reset-deassertion-timeout-ms用 DT_INST_PROP_OR(..., 0) 取值——dts 不写就是零宽度复位脉冲 + 零等待。 本板 ENET_NRST 线上还有 10uF 延时电容,PHY 复位释放后要完成内部 POR 和 strap 采样才响应 MDIO。必须显式给时序(本次取 10ms / 100ms)。
坑 3:DHCP 客户端不会自动启动
打开 CONFIG_NET_DHCPV4=y 后 net iface 显示 DHCPv4 state : disabled, 永远拿不到地址。Zephyr 的设计是:应用(或 CONFIG_NET_CONFIG_SETTINGS)必须显式调用net_dhcpv4_start(iface);CONFIG_NET_DHCPV4_RESTART_ON_IF_UP 只对已启动的 客户端做"重启"(dhcpv4.c 中接口不在已启动列表则直接返回)。官方示例samples/net/dhcpv4_client/src/main.c 也是手动启动的。
坑 4(最大的坑):EDMAC 报 ADE —— 必须先做 IDAU 分区
现象:PHY/链路/中断/MDIO 全部正常,DHCP 已启动,但 TX/RX 数据通路完全卡死:
TX:4 个发送描述符全部卡死(TACT 不清),之后 R_ETHER_Write 报err=4003(FSP_ERR_ETHER_ERROR_TRANSMIT_BUFFER_FULL);
RX:回调事件 event=4(ETHER_EVENT_RX_MESSAGE_LOST)、event=8(ETHER_EVENT_ERR_GLOBAL),EDRRR=0(接收停摆);
EESR 寄存器反复置 ADE 位(bit 23,Address Error)。
原因:RA6M5 的以太网 DMA(EDMAC)是非安全(NS)总线主机。Zephyr 链接脚本 (soc/renesas/ra/ra6m5/linker.ld)把以太网描述符/缓冲区放在 SRAM 顶部 (.ns_buffer 段,本芯片为顶部 16KB),但这块区域必须用 Renesas Flash Programmer 把 IDAU 分区配置烧进 option-setting memory 才真正成为 NS 区。 未分区的芯片全部 SRAM 都是安全区,EDMAC 一访问就被 TrustZone 拦截 → ADE。 Zephyr 官方文档写在 boards/renesas/ek_ra6m5/doc/index.rst 的 note 里。
一次性分区操作(本板实测步骤)
MD 跳线 J17 拨到 2-3(SCI/USB boot 模式);
执行(J-Link 接 J4,rpd 文件构建时自动生成):
rfp-cli -device RA -tool jlink -fo boundary-file build/lcd_demo/zephyr/zephyr.rpd -p
本机 rfp-cli:C:\Program Files (x86)\Renesas Electronics\Programming Tools\Renesas Flash Programmer V3.24\rfp-cli.exe
关键:必须在 boot 模式下执行。RFP 会自动选 "2 wire UART" 接口 (经 J4 的 TDI/TDO 即 P109/P110 与 boot ROM 通信)。正常模式(J17 在 1-2) 下该命令连不上目标;-if swd 能连上但报This device does not support Flash options(SWD 不支持该芯片的 flash options 操作);-tool usb 报 does not support USB Direct。
Operation successful 后 J17 拨回 1-2,复位。配置写入 option-setting flash,永久生效,无需重复。
zephyr.rpd 内容含义:SRAM 0x20000000~0x2007BFFF(496KB)为安全区, 顶部 16KB 为非安全区(与链接脚本 .ns_buffer 位置一致)。
调试方法备忘(分层定位)
本次按"PHY → 链路 → 协议栈 → DMA"逐层排障,每层一个手段:
PHY 应答:应用层临时 MDIO 扫描(mdio_read 遍历 0~31)→ 定地址;
链路:phy_mii 日志 Link speed 100 Mb, full duplex;
协议栈:shell 命令 net iface / net ipv4(看出 DHCPv4 state : disabled); 调试日志开关注意:net 子系统没有 *_LOG_LEVEL_DBG 选项,要直接写CONFIG_NET_DHCPV4_LOG_LEVEL=4(驱动层才有 CONFIG_ETHERNET_LOG_LEVEL_DBG 等);
DMA:FSP 发送是否成功只看描述符 TACT 位(EDMAC 硬件发完才清),不依赖中断, 所以 buffer full + 零接收 = 数据通路本身问题;在驱动 ISR/回调里打印 EESR(0x40114028)确认 ADE 位。
其他有用事实:
Zephyr 内存报告 RAM: 512KB / 512KB 100.00% 是误导:.ns_buffer 段从 bss 末尾拉到 RAM 顶部,中间 ~370KB 填充区被统计为已用,实际占用约 152KB(30%);
DHCP 首次 Discover 前有 0~10s 随机延迟(NET_DHCPV4_INITIAL_DELAY_MAX), 上电后要多等几秒再下结论;
net iface 里 oper=UP, admin=UP, carrier=ON 三者齐备只说明接口状态正常, 不代表 DHCP 在跑。

我要赚赏金
