相关仓库: - 网关产品仓:https://github.com/ffffxxxjjj/gateway - 参考仓 h743-hello:https://github.com/ffffxxxjjj/h743-hello - 签名打包服务 sign:https://github.com/ffffxxxjjj/sign
本文件是网关仓 H743 板级支撑的唯一说明。板子是模组星球 STM32H743VIT6 双网口板(卖家原理图)。以后开发调试全部在 gateway 仓里弄,h743-hello 不再开发、只作参考。
| 内容 | 位置 | 说明 |
|---|---|---|
| 引脚定义 | boards/h743/src/pins.rs |
全套引脚表(见第 2 节),W5500/存储/CAN/USB 只列定义 |
| 芯片唯一号 | boards/h743/src/uid.rs |
H7 地址 0x1FF1E800,网卡地址与随机种子由此派生 |
| 串口初始化 | boards/h743/src/uart.rs |
调试 USART1、485 UART7、485 UART8(阻塞模式,115200 8N1) |
| 内网口带起 | boards/h743/src/net.rs |
PC0 复位 + MDIO 扫芯片 + RMII + embassy-net(DHCPv4)+ Runner 任务 |
| 应用骨架 | app/src/main.rs |
时钟 + 串口 + 内网口带起 + 链路/IP 变化日志 + 心跳(无应用逻辑) |
| 构建配置 | boards/h743/、app/ 各自的 Cargo.toml、.cargo/config.toml |
见第 4 节 |
| 内存布局 | app/memory.x |
应用 FLASH 在 bank2 0x08100000,RAM 用 AXI SRAM 0x24000000 512K |
| 打包脚本 | app/package.sh、app/tools/stamp_version.py |
编 → 转 bin → 打版本块(格式 2,bin 偏移 0x1000)→ 放 dist/ |
| 链接脚本 | app/link.x |
基于 cortex-m-rt 0.7 link.x.in,插入 .version_block 在 Flash+0x1000 |
| 信号 | MCU 引脚 |
|---|---|
| RMII_REF_CLK | PA1(PHY 的 REFCLKO 输出 50MHz,PHY 自带 25MHz 晶振) |
| RMII_CRS_DV | PA7 |
| RMII_RXD0 | PC4 |
| RMII_RXD1 | PC5 |
| RMII_TX_EN | PB11 |
| RMII_TXD0 | PB12 |
| RMII_TXD1 | PB13 |
| ETH_MDIO | PA2 |
| ETH_MDC | PC1 |
| PHY 复位 nRST | PC0 |
| 信号 | MCU 引脚 |
|---|---|
| SPI4_SCK | PE12 |
| SPI4_MISO | PE13 |
| SPI4_MOSI | PE14 |
| SPI4_NSS(片选) | PE11 |
| W5500_RST | PE15 |
| W5500_INT | PB1 |
W5500 自带 25MHz 晶振。W5500 先不弄(用户定暂缓),现阶段 LAN8720 单网口(Modbus 轮询与 MQTT 上云都走 LAN8720,因为 内网口已能上外网)。
| 接口 | TX | RX | 备注 |
|---|---|---|---|
| USART1 | PA9 | PA10 | DAPLink 调试串口插座(卖家确认) |
| UART7 | PE8 | PE7 | 接 485 收发器(以芯片功能为准:PE8=TX、PE7=RX) |
| UART8 | PE1 | PE0 | 接 485 收发器(PE1=TX、PE0=RX) |
| 接口 | TX | RX | 备注 |
|---|---|---|---|
| USART2 | PD5 | PD6 | 板上标 ESP(TXD/RXD) |
| USART3 | PD8 | PD9 | 板上标 232(hello 里曾用 PB10/PB11,与引脚表不一致,网关不用它) |
| USART6 | PC6 | PC7 | hello 六路全撒网的候选之一,网关不用 |
| UART4 | PA0 | PA1 | hello 六路全撒网的候选之一,网关不用(PA1 与内网口 RMII 参考时钟冲突) |
0x1FF1E800(系统区,2026-10-22 真板实证定版)。0x1FFF7A10,更不是错用过的 F4/L4/G0 地址
0x1FFF7590(H7 上根本不存在该区域,读它会 FAULT)。0x02(本地管理位 + 单播位固定),
其余字节取 UID 混合(见 uid.rs 的 mac_from_uid)。((uid[0] as u64) << 32) | (uid[1] as u64) ^ (uid[2] as u64).rotate_left(17))。
注意:先转 u64 再 rotate_left(17),是 64 位循环左移,不是 32 位
(64 位移位的高位会或进种子高半部分,不要把它当 bug“修正”掉)。板卡其他引脚(LED/按键/SWD/DCMI,pins.rs 未定义)见
docs/pinmap-h743.md 附录(同目录有 HTML 版)。
gateway/
├── bootloader/ # 启动加载器(已验完,第一批不动它)
├── boards/
│ └── h743/ # H743 板级支撑库(本批新增,包名 h743-board)
│ ├── Cargo.toml
│ ├── .cargo/config.toml
│ └── src/ # lib.rs、pins.rs、uid.rs、uart.rs、net.rs
├── app/ # 网关应用骨架(本批新增,包名 gateway-app)
│ ├── Cargo.toml
│ ├── .cargo/config.toml
│ ├── memory.x # 应用内存布局(bank2)
│ ├── link.x # 自定义链接脚本(版本块留位)
│ ├── build.rs # 拷 memory.x + link.x 到 OUT_DIR
│ ├── package.sh # 打包脚本(编 → 转 bin → 打版本块 → dist/)
│ ├── tools/
│ │ └── stamp_version.py
│ └── src/
│ └── main.rs
└── docs/
├── board-h743.md # 本文件
└── firmware-version-block.md
板级支撑放成干净的 H743 板级模块(boards/h743/ 下),
不要把 H743 专属代码散在应用根目录(以后要加别的平台)。
两个新 crate 是独立 crate(不是虚拟工作区成员),
应用用路径依赖引用板级库(h743-board = { path = "../boards/h743" }),
与 bootloader 的独立 crate 做法一致(bootloader 不是工作区成员,
是独立 crate;本批不改 bootloader,不动它的结构)。
thumbv7em-none-eabihf。-Tlink.x -Tdefmt.x(应用的 link.x 是自定义的,
见第 5 节;板级库的 link.x 用 cortex-m-rt 默认的)。probe-rs run --chip STM32H743VI。[env] DEFMT_LOG = "info"(铁律,两个新 crate 的
.cargo/config.toml 里都有)。.cargo/config.toml 区别:
板级库故意不设 [build] target(与 bootloader 相同做法);
应用设了 [build] target = "thumbv7em-none-eabihf"(应用只编
芯片固件,无主机测试,设默认目标方便)。
注意:板级库是硬件 crate(依赖 embassy-executor arch-cortex-m、
embassy-stm32,含 ARM 汇编与芯片外设类型),主机 cargo test
编不过(embassy-executor 的 sev 指令在 x86 主机上是非法助记符)
——这不是板级库代码的问题,是硬件 crate 本来就只能编芯片目标。
纯函数(uid.rs 的网卡地址/种子派生)不用 cargo test,改用单文件测
(见第 6 节);芯片构建用 --target thumbv7em-none-eabihf 验。[profile.release]
opt-level = "s"
lto = true
codegen-units = 1
panic = "abort"
debug = false
overflow-checks = false
[profile.release.package.embassy-stm32]
opt-level = 0
这是 2026-10-24 已验证配方:全局 "s" + embassy-stm32 单库
opt-level=0。hello 里 opt 2/3/"s" 单独用都死于时钟初始化同一行;
现行两个仓只有全局 "s" 的偏离版绝不用。
出货那一发必须真板冒烟(发哪一发、测哪一发)。
0x08100000(按网关分区),
绝不用 hello 的独立镜像 0x08000000(那是 hello 单独跑的布局,
网关应用要与 bootloader 分区配合)。0x24000000 512K。应用的链接脚本(app/link.x,基于 cortex-m-rt 0.7 link.x.in 改)
在 Flash 布局里给版本块留了固定位置(其余逐字照抄):
0x1000 处(即 bin 偏移 0x1000),
长度 228 字节,由应用源码里的占位静态变量
(#[link_section = ".version_block"],#[used])占据;.text)从版本块之后开始,不与版本块重叠;
向量表到版本块之间的空隙(约 3.3KB)在 bin 里为零填充,
未用 Flash,无害。.version_block 地址必须等于 Flash + 0x1000,
长度必须恰好 228 字节,.text 必须在版本块之后;
任一不满足,链接直接失败(不要绕过)。打包脚本(app/package.sh)流程:编 → 转 bin → 打版本块 →
放 dist/ 带版本号命名。版本块格式见
docs/firmware-version-block.md(格式 2,bin 偏移 0x1000,
228 字节;型号 stm32h743vi,固件名 gateway,版本取
app/Cargo.toml,构建日期/时间取打包时的 UTC 时间)。
打戳安全规则:目标区域全零才写;已等于要写的版本块则幂等跳过;
目标区域是其他内容(代码/数据,说明链接器没有留位)则失败退出,
绝不覆盖代码。hello 的打包脚本没有打版本块这步(hello 的 bin
不需要被 sign-tool 打包);网关应用的打包脚本必须补这步,
否则 sign-tool pack 读不到身份,无法打包。
前置:装 Rust(rustup)+ thumbv7em-none-eabihf 目标 + probe-rs (烧录用)+ Python 3(打版本块用,标准库即可)。
# 1. 拉仓(gateway 仓,main 分支)
# (按用户本地已有流程拉取,本批不改拉取方式)
# 2. 编板级库(芯片目标,显式带 --target;板级库不设默认目标)
cd boards/h743
cargo build --target thumbv7em-none-eabihf
# 3. 纯函数单文件测试(主机上跑,不用 cargo test)
rustc --test boards/h743/src/uid.rs -o /tmp/uid_test && /tmp/uid_test
# 预期:3 passed(网卡地址、种子精确值、种子确定性/敏感性)
# 4. 编应用(debug;应用设了默认目标,不带 --target 也往芯片编,
# 但显式带 --target 更清楚)
cd app
cargo build --target thumbv7em-none-eabihf
# 5. 编应用(release,发布版用已验证配方)
cargo build --target thumbv7em-none-eabihf --release
# 6. 打包(编 → 转 bin → 打版本块 → dist/,默认 debug)
./package.sh
# release 打包:
./package.sh release
# 产物:dist/gateway-app-v0.1.0.bin(debug)
# dist/gateway-app-v0.1.0-release.bin(release)
# 7. 烧录(DAPLink,芯片型号 STM32H743VI)
# 注意:本批只给命令,烧录由用户操作(板上验证由用户跑日志)。
probe-rs run --chip STM32H743VI target/thumbv7em-none-eabihf/debug/gateway-app
# release:
probe-rs run --chip STM32H743VI target/thumbv7em-none-eabihf/release/gateway-app
接线:DAPLink 调试串口(USART1,PA9 TX / PA10 RX)接电脑串口 (115200 8N1);内网口(RJ45-1,LAN8720)接交换机/路由器 (能 DHCP 分配地址);485 口本批只初始化、不收发,不用接线。
上电后,调试串口(USART1)应先出现一行横幅(应用写出):
gateway-app skeleton: board up, USART1 OK
随后 defmt RTT 日志(probe-rs run 的输出)应依次出现:
gateway-app skeleton: board up
485 UART7 init OK (PE8 TX / PE7 RX)
485 UART8 init OK (PE1 TX / PE0 RX)
UID 0x........ 0x........ 0x........(本板芯片唯一号,每块板不同)
MAC 02:..:..:..:..:..(由唯一号派生,首字节固定 02)
PHY found at MDIO addr ..: id 0x........(LAN8720 芯片编号)
LAN up: PHY 0x........, MAC 02:..:..:..:..:..
link UP
DHCP IP ...(由路由器分配的地址)
heartbeat(每 10 秒一次,证明板子活着)
probe-rs list 看不到探针:换 USB 口或线再试(探针先用 USB
接上电脑、板子上电)。485 UARTx init failed:查对应引脚接线(UART7:PE8/PE7;
UART8:PE1/PE0),或先不管(本批 485 只初始化、不收发,
不影响内网口验证)。PHY not found on any MDIO addr 0..32(随后 LAN init failed,
板子保持活着、每 5 秒打 alive, no network):
查 PC0 复位脚、PA2(MDIO)/PC1(MDC)接线、内网口网线、
交换机端口;贴回完整日志(含 UID、MAC 行)。link DOWN 一直不 UP:查网线、交换机端口、路由器 DHCP 是否开。DHCP IP 一直不出:查路由器 DHCP、网线、交换机;
链路 UP 但拿不到 IP,多半是 DHCP 服务端问题,不是板子问题。boards/h743/.cargo/config.toml 与 app/.cargo/config.toml
里 [env] DEFMT_LOG = "info" 是否还在(删了会零输出:defmt 1.x
未设此变量时默认只编译 error 级,info! 不生成代码)。nm 看 __DEFMT_MARKER_INFO_START/END 区间是否为空
(为空说明日志调用点根本没编译进去)。板上验证结果(日志)贴回后,再定下一步(Modbus/MQTT/应用逻辑 是后续批次,本批不做)。
新增:
boards/h743/Cargo.toml、.cargo/config.toml、
src/lib.rs、src/pins.rs、src/uid.rs、src/uart.rs、src/net.rsapp/Cargo.toml、.cargo/config.toml、memory.x、link.x、
build.rs、package.sh、tools/stamp_version.py、src/main.rsdocs/board-h743.md(本文件)、docs/firmware-version-block.md改动:
README.md(加板级支撑章节与现状,见正文).github/workflows/build.yml(加芯片目标构建任务与纯函数单文件测试)未动:
bootloader/(那批已验完,第一批只新增,不改它)