# U-Boot-Smart210 **Repository Path**: thecasttim/u-boot-smart210 ## Basic Information - **Project Name**: U-Boot-Smart210 - **Description**: 移植U-Boot(2026.10-rc3)到Smart210开发板 - **Primary Language**: Unknown - **License**: GPL-2.0 - **Default Branch**: smart210-port - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-12 - **Last Updated**: 2026-10-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Smart210(S5PV210)U-Boot 移植教程 —— 从零复现到 P5(SD 卡 + ENV 持久化) > 本教程是**复现面**:按执行顺序把「环境准备 → 改动就位 → 构建 → 卡布局 → 烧写 → 上电验收 → ENV 持久化 → 故障自救」 > 走一遍。走完 = Smart210 上跑起 SD 卡启动的 U-Boot(引导加载程序,见 §1.4),能读写卡、ENV(U-Boot 环境变量区,见 §8.1)能跨断电保存。 > > - **给谁**:没参与过本项目的人(或数月后的你自己);不预设 ARM / U-Boot / Linux 构建经验。 > - **到哪**:**只到 P5 为止**。P6 网络 / P7 USB / P8 内核引导不写步骤(更新落点见附录 D)。 > - **事实来源**:本文每条命令、数值、输出都能回指既有文档(实测日志 / 判据 / 机检记录)——逐节映射见附录 D。 > - **叙述基线**:P5 终态唯一主线;历史迭代(1 GiB 口径、`[xx]` 打点、旧 banner)只作「为什么 / 坑」材料,均带「历史」字样。 > - **行数口径**:本教程引用的源码/文档行数一律为 `wc -l` 现测值。 > - **配套文档**:`port-plan.md`(设计与论证)、`bringup-test.md`(实测日志与用例)——深读入口见附录 E。 ## 第 1 章 导览与术语 (本章只读、不动手:建立全局观、备齐物料、把术语查好。) ### 1.1 教程定位与范围 - **给谁**:没参与过本项目的人(或数月后的你自己)——不预设 ARM / U-Boot / Linux 构建经验; 能照命令敲、会用串口终端即可,遇到不认识的名词回 §1.4 查。 - **到哪**:**到 P5 为止**——环境准备 → 改动就位 → 构建 → 卡布局 → 烧写 → 上电验收 → ENV 持久化 → 故障自救。 走完的标志:串口打出 `Smart210 # ` 提示符(第 7 章),`mmc` / 文件读写 / 校验和命令全绿(§7.4), ENV 改一次、断电重上电后值还在(第 8 章)。 - **不写什么**:P6 网络 / P7 USB / P8 内核引导 / NAND / 1GHz / 冷启动恢复——都不写步骤。 后续批次补入时的更新落点已排好(附录 D)。 - **本文档不是设计文档**:为什么这样选型、有没有别的做法——论证过程在 `port-plan.md`(深读入口见附录 E)。 - **事实纪律**:每条命令、数值、输出都有出处(附录 D 逐条列出)。 ### 1.2 物料清单 (动手前逐项备齐;各项说明见备注列。) | # | 物料 | 要求 / 本项目实测值 | 备注 | |---|---|---|---| | 1 | 开发板 | Smart210(S5PV210;**512 MB DDR2**;板上**无 eMMC** 颗粒) | 本文一律用 SD 卡启动 | | 2 | SD 卡 | 容量 ≥ 64 MB(示例卡 1.92 GB) | 布局操作会清空卡上数据(§5.5) | | 3 | USB-TTL 串口线 | **3.3 V 电平** | 接 UART0:`TXD0` / `RXD0` / `GND`,**勿接 VCC**(§2.4);终端软件 = MobaXterm(§2.4) | | 4 | 读卡器 | USB 接口 | 两条路线:WSL 直插(§6.2)或 Windows 原生(§6.6,`sd-fusing-win.py`) | | 5 | PC | Windows + WSL2(Ubuntu) | 环境准备见第 2 章 | | 6 | 交叉工具链与工具 | `gcc-arm-linux-gnueabihf`、`u-boot-tools`、`dosfstools`、`python3` | 安装与自检见 §2.2 / §2.6 | | 7 | usbipd-win 安装包 | 工作区 `refer/tools/usbipd-win_5.3.0_x64.msi` | 用途与核对见 §2.5 | | 8 | 源码树 | 含本移植全部改动(59 个文件,附录 A) | 进 WSL 的做法见 §2.3 | | 9 | 板侧开关 | **S2** 拨到 `SDBOOT` 侧(另一侧 = NAND 启动) | 本项目实测丝印 `SDBOOT` / `NAND`;细节见 §7.1 | ### 1.3 十步地图 先扫一遍再动手:每步对应一章,通过标志即该步的判据。 | 步 | 做什么 | 章 | 通过标志 | |---|---|---|---| | 1 | 备料与通读 | 第 1 章 | 上表物料齐;术语能回查 | | 2 | 环境准备 | 第 2 章 | 自检清单(§2.6)全绿 | | 3 | 改动就位与核验 | 第 3 章 | 59 件全量清单见附录 A;P5 面 27 件卡片核验(§3.2 / §3.3)逐条命中 | | 4 | 构建 | 第 4 章 | 四件产物:`u-boot.bin` / `u-boot-spl.bin` / `u-boot-bl1.bin` / `u-boot.dtb` | | 5 | 卡布局 | 第 5 章 | 分区起点 4096 扇区、类型 0x0c、尾 = 卡尾、卷标 `SMART210` | | 6 | 烧写 | 第 6 章 | 脚本收尾输出 `Commit ok:` + `Done.` | | 7 | 上电验收 | 第 7 章 | 启动日志到 `Smart210 # `;命令面全绿 | | 8 | ENV 使用与持久化 | 第 8 章 | `saveenv` 后拔电重上电,值仍在 | | 9 | 故障排查 | 第 9 章 | (随查)症状 → 原因 → 对策 | | 10 | 附录与维护 | 第 10 章 | 指纹核对 / 命令速查 / 更新落点 | ### 1.4 术语表 全文首现的术语都在这里;正文首现处另有短解释。查不到的名词按括号里的指针去对应章节看上下文。 | 术语 | 一句话解释 | 指针 | |---|---|---| | **U-Boot** | 运行在操作系统之前的引导加载程序(bootloader);本移植的最终产物就是它 | 第 7 章 | | **S5PV210 / S5PC110** | 同一颗芯片的两个商用名;本项目的 SoC | §3.1 | | **iROM** | 芯片片内固化 ROM:上电首先执行,从 SD 扇区 1 把 BL1 读进来 | §3.1 / §6.1 | | **BL1** | iROM 装载的第一级镜像 = 16 字节头 + SPL 代码;烧在 SD 扇区 1 | §4.2 / §6.1 | | **SPL** | 二级程序装载器(Second Program Loader)= BL1 的代码部分:初始化时钟/DDR,把主程序读进来 | §3.1 | | **U-Boot 主程序(proper)** | SPL 装载的完整 U-Boot(DM + 设备树 + shell);与 SPL 相对 | §7.1 | | **mkbl1** | 打包小工具 `tools/mkbl1.py`:给 SPL 加 16 字节头,产出 `u-boot-bl1.bin` | §4.2 | | **累加和(checksum)** | 代码逐字节求和取低 32 位;iROM 与烧写脚本用它验证 BL1 完整 | §4.2 | | **设备树(DTS / DTB)** | 描述硬件的源文件(`.dts`)与其编译产物(`.dtb`);主程序靠它认识板子 | §3.3 卡 9 | | **DM(驱动模型)/ uclass** | U-Boot 的现代驱动框架:设备与驱动自动匹配 | §3.3 卡 16 | | **SDHCI** | SD 主机控制器的标准编程接口;本项目用 `s5p_sdhci` 驱动 | §3.3 卡 16 | | **SDMMC0** | 芯片内 MMC 控制器 0 号通道——本项目 SD 槽挂它 | §6.1 / §7.4 | | **LBA** | 逻辑块地址(扇区号);1 扇区 = 512 字节 | §5.1 | | **MBR** | 主引导记录:扇区 0 里的分区表 | §5.1 | | **分区表** | 扇区 0 中描述各分区起点/类型/终点的表(MBR 格式) | §5.1 | | **FAT32** | 数据分区使用的文件系统;U-Boot 用 `ls mmc 0:1` 读它 | §5.1 | | **ENV** | U-Boot 环境变量区:存在 SD `0x100000` 起 16 KiB;`saveenv` 写这里 | §8.1 | | **TEXT_BASE** | 主程序链接/加载地址 `0x34800000`;SPL 把 `u-boot.bin` 读到它 | §3.1 / §6.1 | | **重定位** | 主程序起步时把自身整镜像搬到 RAM 高位(避开自己的加载区)再继续跑 | §3.3 卡 5 | | **UBRDIV / UDIVSLOT** | 串口波特率分频寄存器:固定值 `34` / `0xdfdd`,只在配套时钟下等于 115200 | §3.3 卡 5 | | **FIFO** | 串口的收发缓冲队列;TX FIFO 满则写方等待(SPL 输出不丢字的原因) | §3.3 卡 5 | | **usbipd** | Windows 端工具:把 USB 设备(读卡器)转发进 WSL | §2.5 / §6.2 | | **dd** | 逐块读写工具;烧写脚本用 `dd` 写扇区 1 / 扇区 49 | §6.1 / §6.3 | | **O_DIRECT** | 「绕过页缓存」直接读设备的方式(`dd iflag=direct`);读到的是卡上实况 | §6.4 | | **页缓存** | 内核缓存磁盘内容的内存区;普通读写默认先经过它 | §6.4 | | **交叉工具链** | 在 x86 主机上编译 ARM 程序的编译器(`arm-linux-gnueabihf-` 前缀) | §2.2 | | **WSL2** | Windows 上的 Linux 子系统(本项目构建/烧写都在它里面) | 第 2 章 | | **115200-8N1** | 串口参数:波特率 115200、8 数据位、无校验、1 停止位 | §2.4 | | **`sync` / `blockdev --flushbufs`** | 把内核缓冲与设备缓存刷到介质的命令(烧写提交语义) | §6.4 | | **diskpart / parted** | Windows / Linux 的分区工具(卡布局的两条路线) | 第 5 章 | | **boot mode switch** | 板上选择启动介质的开关:**S2**,拨到 `SDBOOT` 侧 = SD 卡启动(另一侧 = NAND) | §7.1 | ### 1.5 路径与约定 | 名称 | 本项目实测值 | 说明 | |---|---|---| | Windows 工作区 | `C:\Projects\Application\U-Boot_Smart210` | 内含 `u-boot/`(源码副本)、`build-smart210/`(产物)、`refer/`(参考资料);你的路径不同就用占位符替代 | | WSL 源码树 | `~/ub210/u-boot` | 构建在这里进行(§2.3) | | WSL 构建树 | `~/ub210/build-smart210` | `make O=` 指向(§4.1) | - **占位符规则**(W3):须替换的内容用尖括号——`<你的工作区>`、`/dev/sdX`(WSL 里读卡器整盘设备,如 `/dev/sdb`)、 `<盘号>`(Windows 里的磁盘号,如 `2`)、``(usbipd 列出的设备号);同一变量首现处给语义。 - **命令在哪跑**:文中命令块默认按标注执行——「WSL」的进 WSL 跑,「Windows」的在 Windows 跑(需管理员的会写明)。 - **命令块可直接复制**:除注释外不含说明文字;需要改的地方就是尖括号占位符。 ## 第 2 章 环境准备 (读本章:把 PC 配齐。每节末尾一条判据,全绿再进下一步。) ### 2.1 WSL2 与 Ubuntu **为什么需要 WSL2**: - U-Boot 构建系统与交叉工具链(`arm-linux-gnueabihf-` 前缀)是 Linux 工具链——Windows 原生环境没有它们; 构建与烧写脚本都在 Linux 侧跑(`port-plan.md §7`)。 - WSL2 在 Windows 内跑真 Linux 内核:既能访问 Windows 文件(`/mnt/c/…`),又能接 USB 设备(通行做法)—— 本项目烧写路线(读卡器经 usbipd 转发进 WSL,§6.2)就依赖这条通道。 **如何安装**(下述通用操作属通行做法——非本项目实测): ```text wsl --install -d Ubuntu # Windows 管理员 PowerShell ``` - 前置条件:Windows 开启虚拟化(通行做法)。 - 装完首次启动会要求设置 UNIX 用户名与密码(通行做法);发行版名按需替换(本项目实测 = `Ubuntu` 26.04 LTS、WSL 版本 2)。 - 磁盘预留(`port-plan.md §7`):Ubuntu 基础系统约 3 GB + 交叉工具链约 0.5 GB + 源码与构建产物约 1 GB ≈ 4.5 GB 起步; 建议 WSL 虚拟盘 16 GB(下限 8 GB)。 判据:`wsl -l -v` → 你的发行版(本项目 = `Ubuntu`)`VERSION` 列 = `2`。 **如何使用**: - 启动 / 退出:Windows 终端输入 `wsl` 进入 Ubuntu,`exit` 退出(通行做法)。 - 访问 Windows 文件:Windows 盘符挂在 `/mnt/` 下——`/mnt/c/…` 即 Windows 的 `C:\…`(通行做法)。 - 两棵树分工:Windows 工作区 = 编辑面、WSL `~/ub210/…` = 构建面(§2.3)——本项目实测工作流 (记录见 `batch-01-memory-512m.md §5.2`)。 - 空闲关停注意(本项目实测):WSL 空闲关停会把 usbipd 挂上的读卡器一并摘掉(坑④)——烧写期间保持 会话活跃(保活);被关停后重新 `wsl` 进入、重挂读卡器(§6.2)。 判据:`wsl` 进入后 `ls /mnt/c/` 列出 Windows C 盘内容(文件互访在位)。 ### 2.2 交叉工具链与依赖 ```bash sudo apt update sudo apt install gcc-arm-linux-gnueabihf bison flex libssl-dev u-boot-tools dosfstools python3 ``` - 每个包的用途:`gcc-arm-linux-gnueabihf` = 交叉编译器;`bison` / `flex` / `libssl-dev` = 构建依赖; `u-boot-tools` = `mkimage`;`dosfstools` = `mkfs.vfat`(布局路线 B(§5.3)格式化用);`python3` = 跑 `tools/mkbl1.py`。 判据:三条 `--version` 命令(输出为本项目实测值): - `arm-linux-gnueabihf-gcc --version | head -1` → `arm-linux-gnueabihf-gcc (Ubuntu 15.2.0-16ubuntu1) 15.2.0` - `mkimage --version` → `mkimage version 2025.10` - `python3 --version` → `Python 3.14.4` - 补充一条(布局路线 B(§5.3)会用到):`mkfs.vfat --help | head -1` → `mkfs.fat 4.2 (2021-01-31)`。 ### 2.3 源码进 WSL(教程约定) - 推荐把源码树放进 WSL(ext4 上构建)。两种做法,任选其一: 1. **整树放进 WSL**(推荐): ```bash mkdir -p ~/ub210 cp -a <你的工作区>/u-boot ~/ub210/u-boot ``` 2. **双树工作流**:Windows 工作区为编辑面、WSL 树为构建面;每次改动后同步并逐对核对 (本项目实测工作流,记录见 `batch-01-memory-512m.md §5.2`): ```bash cp <你的工作区>/u-boot/configs/smart210_defconfig ~/ub210/u-boot/configs/ md5sum <你的工作区>/u-boot/configs/smart210_defconfig ~/ub210/u-boot/configs/smart210_defconfig ``` - 约定:本文其余章节均假定源码树 = `~/ub210/u-boot`(教程约定,非实测记录);你的路径不同就整体替换。 判据:`ls ~/ub210/u-boot/board/samsung/smart210/` 列出 `Kconfig`、`MAINTAINERS`、`Makefile`、`smart210.c`、 `lowlevel_init.S`、`spl_sd.c`、`sd_fusing.sh`(另含 Windows 工装三件,见 §6.6);**最终验证 = 第 4 章构建成功**。 - 踩坑提示:双树不同步会让「改了代码但构建行为不变」——排查入口 = 第 9 章坑⑨。 ### 2.4 串口终端 - 接线:USB-TTL 串口线(**3.3 V 电平**)接开发板 UART0——`TXD0`、`RXD0`、`GND` 三根;**勿接 VCC**。 - 参数:`115200-8N1`。 - 终端软件(本项目实测 = **MobaXterm**),配置要点:`Session` → `Serial`;`Serial port` 选你的 COM 口 (设备管理器里 USB-TTL 线对应的口);波特率 `115200`;其余 = 8N1(8 数据位、无校验、1 停止位); `Flow control` = `None`。 - 其它串口终端(PuTTY / Tera Term / Xshell…)可自选,参数同上;串口线与模块的具体接法以你的线材说明为准。 - 为什么:SPL 与主程序的所有日志都从 UART0 输出——串口是观察启动过程的唯一窗口 (SPL 直写串口、主程序走设备树 `stdout-path`,机制见 §7.1)。 判据:按上述参数打开终端;上电后能看到输出(完整对照见第 7 章;无输出先查第 9 章坑⑪)。 ### 2.5 usbipd-win 安装 - 用途:把读卡器从 Windows 转发进 WSL2(命令与用法在 §6.2)。为什么不用 `wsl --mount`:它不适用于 USB 读卡器(见第 9 章坑②)。 - 安装包:工作区已备 `refer/tools/usbipd-win_5.3.0_x64.msi`; sha256 = `1c984914aec944de19b64eff232421439629699f8138e3ddc29301175bc6d938`(2026-09-14 复核)。 - 官方来源:`dorssel/usbipd-win`(GitHub 上的官方项目)。 - 步骤:双击 msi 安装(Windows)。 判据:`usbipd --version` → 打印版本号(本安装包 = `5.3.0`)。核对安装包:WSL 内 `sha256sum` 该文件 (或 Windows `certutil -hashfile usbipd-win_5.3.0_x64.msi SHA256`),与上值一致。 ### 2.6 环境自检清单 | 项目 | 命令 | 期望 | |---|---|---| | WSL 发行版 | `wsl -l -v` | 发行版行 `VERSION` 列 = `2` | | 交叉工具链 | `arm-linux-gnueabihf-gcc --version \| head -1` | 打印版本号(本项目 15.2.0) | | mkimage | `mkimage --version` | `mkimage version 2025.10` | | Python | `python3 --version` | `Python 3.14.4`(本项目实测) | | dosfstools | `mkfs.vfat --help \| head -1` | `mkfs.fat 4.2 (2021-01-31)` | | 源码树 | `ls ~/ub210/u-boot/board/samsung/smart210/` | 七个板级文件在场(§2.3;另含 Windows 工装三件,见 §6.6) | | usbipd(Windows) | `usbipd --version` | 打印版本号(§2.5) | | 串口线 | (硬件)接到 UART0 | 第 7 章上电有输出 | 判据:逐条跑全绿再进第 3 章。 ## 第 3 章 源码结构与改动总览 (读本章:建立启动链心智模型;改动就位后逐卡核对。改动以「片段 + 就位核验」呈现,完整源码以树内文件为准—— 本仓是唯一权威源,正文只给关键片段。) ### 3.1 启动链总图 ```text 上电 → iROM(芯片片内固化 ROM) → 从 SD 卡扇区 1 读 BL1(16 字节头 + SPL 代码,代码 ≤ 16 KiB − 16 B)到 IRAM(片内 RAM)`0xD0020010`,校验通过后执行 → BL1 = U-Boot SPL(非 DM、无设备树;本构建约 5 KB): ① 时钟初始化(APLL 800 MHz / MPLL 667 MHz / EPLL 96 MHz / VPLL 54 MHz——四路锁相环 PLL) ② DMC0(DDR 控制器 0)单控制器 DDR2 初始化 → 512 MiB @ 0x20000000 ③ 调 iROM 读卡接口:从扇区 49 起按 1 MiB 窗口把 u-boot.bin 读到 0x34800000 ④ 跳转 0x34800000 → U-Boot 主程序(DM + 设备树,TEXT_BASE = 0x34800000)→ `Smart210 # ` shell ``` | 级 | 介质 / 位置 | 载入地址 | 谁写进去 / 谁读它 | |---|---|---|---| | BL1(16B 头 + SPL 代码) | SD 扇区 1 | IRAM `0xD0020010` | 写:烧写脚本;读:iROM | | 主程序 `u-boot.bin` | SD 扇区 49 起(1 MiB 窗口) | `0x34800000` | 写:烧写脚本;读:SPL | | 内核装载区(P8 才用) | — | `0x20008000` | 本教程不展开(`SYS_LOAD_ADDR`) | - 为什么扇区 1 存 BL1:iROM 固定从 SD 卡扇区 1 读第一级镜像,并校验它的 16 字节头。 - 为什么主程序从扇区 49 起:本移植选定的固定位置——与烧写脚本、1 MiB 引导区、SPL 的 1 MiB 读窗口同一口径(第 5 / 6 章)。 - 为什么 BL1 限制 16 KiB:iROM 的装载窗口是 16 KiB,减 16 字节头 = 代码上限 16368 字节。 - 冷启动现状(`port-plan.md §4.3`):当前为**诊断版 bring-up**——保留看门狗关闭、时钟初始化、DRAM 初始化、 UART 初始化与 banner、CPU id 设置;其余(EVT 异步桥、ABB 禁用、SROMC BW 清零、VIC 关中断、internal_ram_init、 唤醒清除、IO 保留域释放)不在本构建内,后续按需逐项恢复。 - 就位核验:`grep -n 'DMC1\|0x40E00323' board/samsung/smart210/lowlevel_init.S` → 无命中(历史 DMC1 段已删); `grep -n '0xD0037F98\|SPL_SD_START_SECTOR' board/samsung/smart210/spl_sd.c` → 命中(iROM 接口地址、扇区 49)。 ### 3.2 改动文件总表 **新增 11 / 修改 16 / 删除 0**(P5 面;行数为 P5 期 as-of 值,现测以附录 A 为准;其后批次增补的完整清单与逐文件行数见附录 A;9 个共享文件的守卫逐处位置与机检见 `batch-06-boot-banner.md §2.7`)。 | 类别 | 文件 | 行数 | 一句话作用 | |---|---|---|---| | 板级·新增 | `board/samsung/smart210/Kconfig` | 22 | 板级 defaults + 移植版本号定义(单一定义处) | | 板级·新增 | `board/samsung/smart210/MAINTAINERS` | 6 | 板级归档信息 | | 板级·新增 | `board/samsung/smart210/Makefile` | 8 | 编 `smart210.o` / `lowlevel_init.o`;SPL 另编 `spl_sd.o` | | 板级·新增 | `board/samsung/smart210/smart210.c` | 318 | `board_init()`:机器号 / boot_params、DM9000(P6 用)、MMC 引脚复用 | | 板级·新增 | `board/samsung/smart210/lowlevel_init.S` | 263 | SPL 时钟 + DDR2(DMC0)初始化 + UART 输出模块 | | 板级·新增 | `board/samsung/smart210/spl_sd.c` | 162 | SPL 装载器:经 iROM 接口从 SD 读主程序并跳转 | | 板级·新增 | `board/samsung/smart210/sd_fusing.sh` | 311 | 烧写脚本:写入前校验(含卡布局 C1–C4)+ 写后提交/回读(W1–W3) | | 工具·新增 | `tools/mkbl1.py` | 41 | BL1 打包:16B 头(加载长度 + 累加和) | | 配置·新增 | `configs/smart210_defconfig` | 42 | 全量配置(内存 / MMC / ENV / SPL) | | 设备树·新增 | `arch/arm/dts/s5pc1xx-smart210.dts` | 65 | SoC 节点 + 板级外设(serial / sdhci×2 / dm9000 / usb / pinctrl) | | 头文件·新增 | `include/configs/smart210.h` | 29 | DRAM 布局(512 MiB 单 bank) | | 平台·修改 | `arch/arm/mach-s5pc1xx/Kconfig` | 31 | `TARGET_SMART210` 选项(`select OF_CONTROL` / `SUPPORT_SPL`) | | 平台·修改 | `arch/arm/mach-s5pc1xx/pinmux.c` | 37 | `pinmux_decode_periph_id()` 桩 → 实读 `samsung,periph-id` | | 驱动·修改 | `drivers/mmc/s5p_sdhci.c` | 244 | `of_match` 增 `samsung,s5pv210-sdhci`(+1 行) | | 构建系统·修改 | `arch/arm/dts/Makefile` | 1181 | 增 `dtb-$(CONFIG_TARGET_SMART210) += s5pc1xx-smart210.dtb` | | 构建系统·修改 | `arch/arm/cpu/armv7/s5p-common/Makefile` | 19 | s5pc1xx SPL 下补编 `timer.o` / `sromc.o` | | 构建系统·修改 | `scripts/Makefile.xpl` | 632 | `mkexynosspl` 规则仅限 exynos(其定长格式与 S5PV210 16B 头不符) | | 共享·修改 | `common/version.c` | 26 | 守卫覆盖 `U_BOOT_VERSION_STRING`(仅主程序 banner 消费) | | 共享·修改 | `common/board_f.c` | 1162 | 守卫:banner 打印点换板级函数 + 跳过 `DRAM:` 前缀/值(G01–G03) | | 共享·修改 | `common/board_r.c` | 837 | 守卫:`Core:` 8 列 + `MMC:`/`Net:` 板级打印挂点、Net 行前移(G06–G09) | | 共享·修改 | `common/board_info.c` | 81 | 守卫:跳过 `Model:` 回退打印(G05;DT `model` 属性不动) | | 共享·修改 | `common/console.c` | 1310 | 守卫:`In:/Out:/Err:` 8 列 + `@` 截断显示(G15) | | 共享·修改 | `arch/arm/cpu/armv7/s5p-common/cpu_info.c` | 58 | 守卫:`CPU:` 标签 8 列(G04) | | 共享·修改 | `drivers/mmc/mmc.c` | 3374 | 守卫:跳过启动时 `print_mmc_devices`(G10;`mmc list` 命令面不动) | | 共享·修改 | `env/env.c` | 404 | 守卫:ENV 行 `Env:` 前缀(8 列)+ `OK` 收尾(G11/G12) | | 共享·修改 | `env/mmc.c` | 584 | 守卫:`Reading from MMC(n) ...` 空格口径(G13) | | 共享·修改 | `net/eth-uclass.c` | 672 | 守卫:设备清单打印抑制(G14;`Net:` 行由板级打印) | ### 3.3 逐文件卡片(18 张) (每卡:作用 → 为什么 → 关键片段(≤15 行)→ 就位核验(命令 + 期望)。逐卡过,核验命令逐条跑。) #### 卡 1 · `board/samsung/smart210/Kconfig`(新增,22 行) - 作用:告诉构建系统这块板的 `SYS_BOARD` / `SYS_SOC` 等 defaults;定义移植版本号 `CONFIG_SMART210_PORT_VERSION`(默认 `v0.1`)。 - 为什么版本号放这里:单一定义处——消费面 = 仅主程序 banner(SPL 自 batch-06 起不再打印版本,见 `port-plan.md §4.11`)。 - 关键片段: ```kconfig if TARGET_SMART210 config SYS_BOARD default "smart210" config SYS_SOC default "s5pc1xx" config SMART210_PORT_VERSION string "Smart210 port version string" default "v0.1" endif ``` - 就位核验:`grep -n 'SMART210_PORT_VERSION' board/samsung/smart210/Kconfig` → 命中 1 行(定义处)。 #### 卡 2 · `board/samsung/smart210/MAINTAINERS`(新增,6 行) - 作用:板级归档(维护者 / 状态 / 文件域)。 - 为什么:主线加板的规范动作——板目录与配置进维护清单。 - 关键片段(全文 6 行): ```text SMART210 BOARD M: Local port (ThinCoder session) S: Maintained F: board/samsung/smart210/ F: include/configs/smart210.h F: configs/smart210_defconfig ``` - 就位核验:`grep -c '^F:' board/samsung/smart210/MAINTAINERS` → `3`。 #### 卡 3 · `board/samsung/smart210/Makefile`(新增,8 行) - 作用:编译入口——`smart210.o` + `lowlevel_init.o` 常编;`spl_sd.o` 只在 SPL 构建时编。 - 为什么 `lowlevel_init` 常编:主程序启动时也从它过一遍(它按 PC 段判断直接返回,见卡 5)。 - 关键片段: ```makefile obj-y = smart210.o obj-y += lowlevel_init.o obj-$(CONFIG_SPL_BUILD) += spl_sd.o ``` - 就位核验:`grep -n 'spl_sd' board/samsung/smart210/Makefile` → 命中 1 行(`CONFIG_SPL_BUILD` 条件)。 #### 卡 4 · `board/samsung/smart210/smart210.c`(新增,318 行) - 作用:`board_init()`——机器号 2458 / boot_params、DM9000(以太网控制器)时序与片选(P6 用)、SDMMC0/SDMMC2 引脚复用; `dram_init()` / `dram_init_banksize()` 单 bank 512 MiB。 - 为什么引脚复用放 `board_init()`:DM 驱动模型下 MMC 设备由 uclass 自己探测,板级只需在探测前把引脚 mux 好; 时序上 `board_init()` 早于 MMC 探测(`port-plan.md §4.6.1`)。 - 关键片段: ```c #ifdef CONFIG_MMC /* * SDMMC0 (SD card slot) on GPG0[0:6], SDMMC2 on GPG2[0:6]. Both * channels are muxed; whichever carries media shows up. */ smart210_mmc_pinmux(S5PC110_GPIO_G00, 7); smart210_mmc_pinmux(S5PC110_GPIO_G20, 7); #endif ``` - 就位核验:`grep -n 'smart210_mmc_pinmux' board/samsung/smart210/smart210.c` → 定义 1 处 + `board_init()` 内调用 2 处; `grep -c 'board_mmc_init' board/samsung/smart210/smart210.c` → `0`(死路径已删)。 #### 卡 5 · `board/samsung/smart210/lowlevel_init.S`(新增,263 行) - 作用:SPL 的时钟(APLL 800 / MPLL 667 / EPLL 96 / VPLL 54 MHz)、DDR2 DMC0 初始化(512 MiB @ `0x20000000`)、 UART0 直写输出模块(六行 SPL 块中的前两行);主程序路径按 PC 段判断直接返回。 - 为什么有「PC 段判断」:同一文件被 SPL(IRAM)与主程序(DRAM)共用——从 DRAM 进来即说明时钟/DRAM 已就绪,直接返回。 - 为什么 UBRDIV 固定:串口分频写死 `34` / `0xdfdd`,只有与上面这套时钟配套才等于 115200 (历史坑:时钟未初始化时输出全乱码——固定分频必须与确定时钟源配套)。 - 关键片段: ```asm /* Disable watchdog */ ldr r0, =S5PC110_WATCHDOG_BASE str r5, [r0] bl system_clock_init bl mem_ctrl_asm_init bl uart_asm_init ldr r0, =msg_dram_ready bl uart_puts ``` - 就位核验:`grep -n 'system_clock_init\|mem_ctrl_asm_init' board/samsung/smart210/lowlevel_init.S` → 定义与调用均在位; `grep -n 'DMC1\|0x40E00323' board/samsung/smart210/lowlevel_init.S` → 无命中(历史 DMC1 段已删)。 #### 卡 6 · `board/samsung/smart210/spl_sd.c`(新增,162 行) - 作用:SPL 装载器——取 iROM 的 SD 读接口函数指针,按 128 扇区/批 × 16 批,把扇区 49 起的 1 MiB 读到 `0x34800000`; 并提供 SPL 直写串口的行日志与探针(DMC0 基部、重定位目标区顶部)。 - 为什么用 iROM 接口:SPL 里还没有 MMC 驱动——用芯片固化的读卡函数是最短路径。 - 为什么读满 1 MiB 窗口:SPL 固定读 2048 扇区(`SPL_SD_COPY_SECTORS`)——所以 `u-boot.bin` 必须 ≤ 1 MiB(§6.4 C1/C2)。 - 关键片段: ```c spl_uart_puts("SPL: Boot source: SD/MMC (sector "); spl_uart_putdec(start); spl_uart_puts(")\r\n"); for (off = 0; off < SPL_SD_COPY_SECTORS; off += 128) { if (!copy(0, start + off, 128, (u32 *)(dest + off * 512), 0)) { spl_uart_puts("SPL: load failed (sector "); spl_uart_putdec(start + off); spl_uart_puts(")\r\n"); return -EIO; } } spl_uart_puts("SPL: Jump to U-Boot @ 0x"); spl_uart_puthex(dest); spl_uart_puts("\r\n"); ``` - 就位核验:`grep -n '0xD0037F98\|SPL_SD_START_SECTOR' board/samsung/smart210/spl_sd.c` → 命中(iROM 接口地址、扇区 49)。 - 历史遗留注释:文件头注释含「SD/eMMC」字样,`spl_boot_device()` 注释含「eMMC boot follows…」—— 均为历史遗留文字(板上无 eMMC、实板早已验证)。 #### 卡 7 · `board/samsung/smart210/sd_fusing.sh`(新增,311 行) - 作用:烧写脚本——写入前校验(BL1 头自洽 + 与同目录 `u-boot-spl.bin` 交叉核对 + 1 MiB 窗口 + 卡布局 C1–C4 + 设备为整盘), 两处 `dd` 写扇区 1 / 49,写后提交(W1)与 O_DIRECT 回读(W2),只有全过才打印 `Done.`(W3)。 - 为什么校验这么重:写卡是「不可逆 + 目标盘可能选错」的操作——脚本 fail-closed,让「烧错/烧半」不可能静默发生(第 6 章)。 - 关键片段(文件头布局注释): ```sh # Layout (S5PV210 iROM + card layout of port-plan.md section 4.12.1): # sector 1 : BL1 = SPL + 16-byte checksum header (mkbl1.py output) # sector 49 : u-boot.bin (loaded by SPL to 0x34800000) # 0x100000 : environment area (CONFIG_ENV_OFFSET, 16 KiB) - never # written by this script # 2 MiB (LBA 4096): FAT32 data partition, i.e. after the environment area ``` - 就位核验:`sh -n board/samsung/smart210/sd_fusing.sh` → 无输出(语法零错);`grep -c 'ABORT:' board/samsung/smart210/sd_fusing.sh` → 多条命中(各校验失败路径)。 #### 卡 8 · `configs/smart210_defconfig`(新增,42 行) - 作用:全量配置——内存(单 bank 512 MiB / `TEXT_BASE`)、ENV(MMC 落点 `0x100000` + 16 KiB)、 MMC/SDHCI 与命令面(`CMD_MMC` / `CMD_FAT` / `CMD_FS_GENERIC`)、SPL 布局(IRAM 地址 / 栈 / BSS)。 - 为什么 `CONFIG_SYS_MONITOR_LEN` 用十进制:Kconfig 的 int 型符号不接受 `0x` 前缀——写了 `0x80000` 会被判非法并回退为 0(坑⑧)。 - 关键片段: ```text CONFIG_TEXT_BASE=0x34800000 CONFIG_SYS_MONITOR_LEN=524288 CONFIG_NR_DRAM_BANKS=1 CONFIG_ENV_IS_IN_MMC=y CONFIG_ENV_OFFSET=0x100000 CONFIG_ENV_SIZE=0x4000 CONFIG_MMC=y CONFIG_CMD_MMC=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y ``` - 就位核验:`grep -n 'CONFIG_ENV_OFFSET\|CONFIG_ENV_SIZE\|CONFIG_NR_DRAM_BANKS\|CONFIG_SYS_MONITOR_LEN' configs/smart210_defconfig` → 四值如左; `grep -c '0x80000\|CONFIG_ENV_IS_NOWHERE' configs/smart210_defconfig` → `0`。 #### 卡 9 · `arch/arm/dts/s5pc1xx-smart210.dts`(新增,65 行) - 作用:描述板子——`serial0`(UART0 + `stdout-path`)、`sdhci0` / `sdhci2` 两个 SDHCI 控制器节点(SD 槽 = SDMMC0)、 DM9000、USB OTG、pinctrl;`aliases` 增 `mmc0 = &sdhci0;` / `mmc1 = &sdhci2;` 定序。 - 为什么 SDHCI 节点带 `samsung,periph-id`:驱动靠它判断「这是第几号控制器」;用自定义属性而非中断号载体, 与「全树无中断控制器」的实况相容(`port-plan.md §4.6.1`)。 - 关键片段: ```dts sdhci0: sdhci@eb000000 { compatible = "samsung,s5pv210-sdhci"; reg = <0xeb000000 0x1000>; bus-width = <4>; samsung,periph-id = <75>; }; ``` - 就位核验:`grep -n 'samsung,s5pv210-sdhci\|samsung,periph-id\|mmc0 = ' arch/arm/dts/s5pc1xx-smart210.dts` → 两节点 + 两 periph-id + 两别名命中。 #### 卡 10 · `include/configs/smart210.h`(新增,29 行) - 作用:C 侧 DRAM 布局——`PHYS_SDRAM_1` = `0x20000000`、`PHYS_SDRAM_1_SIZE` = 512 MiB。 文件政策:能进 defconfig / 设备树的都不放这里。 - 为什么单 bank:板上只有 DMC0 挂颗粒(历史 1 GiB 双控制器口径已作废)。 - 关键片段: ```c #define CFG_SYS_SDRAM_BASE 0x20000000 /* Smart210: 512 MiB DDR2, DMC0 single controller @ 0x20000000 */ #define PHYS_SDRAM_1 0x20000000 #define PHYS_SDRAM_1_SIZE (512 << 20) ``` - 就位核验:`grep -n 'PHYS_SDRAM' include/configs/smart210.h` → 仅 `_1` 两条;`grep -c 'PHYS_SDRAM_2' include/configs/smart210.h` → `0`。 #### 卡 11 · `tools/mkbl1.py`(新增,41 行) - 作用:把 `u-boot-spl.bin` 打包成 BL1(16B 头 + 代码):头 `[0:4]` = 总长(代码 + 16,小端)、 `[8:12]` = 代码字节累加和(低 32 位)。 - 为什么:iROM 就是按这个格式校验并装载的(格式与出厂移植一致)。 - 关键片段: ```python header = bytearray(16) header[0:4] = (len(code) + 16).to_bytes(4, "little") header[8:12] = (sum(code) & 0xFFFFFFFF).to_bytes(4, "little") with open(sys.argv[2], "wb") as f: f.write(header + code) ``` - 就位核验:`grep -n 'BL1_CODE_MAX\|header\[0:4\]\|header\[8:12\]' tools/mkbl1.py` → 多处命中(上限常量与头字段写入);运行判据在第 4 章。 #### 卡 12 · `arch/arm/mach-s5pc1xx/Kconfig`(修改,31 行) - 作用:增 `TARGET_SMART210` 选项:`select OF_CONTROL`(设备树)与 `select SUPPORT_SPL`;并 source 板级 Kconfig。 - 为什么 select:新板要显式声明「我用设备树、我有 SPL」——这是 defconfig 里 `CONFIG_SPL=y` 能成立的前提。 - 关键片段: ```kconfig config TARGET_SMART210 bool "Smart210 board (S5PV210)" select OF_CONTROL select SUPPORT_SPL ``` - 就位核验:`grep -n -A3 'config TARGET_SMART210' arch/arm/mach-s5pc1xx/Kconfig` → 选项与两个 select 在位; `grep -n 'smart210/Kconfig' arch/arm/mach-s5pc1xx/Kconfig` → source 行在位。 #### 卡 13 · `arch/arm/dts/Makefile`(修改,1181 行) - 作用:把 `s5pc1xx-smart210.dtb` 加进构建(依赖 `CONFIG_TARGET_SMART210`)。 - 关键片段: ```makefile dtb-$(CONFIG_TARGET_SMART210) += s5pc1xx-smart210.dtb ``` - 就位核验:`grep -n 'smart210' arch/arm/dts/Makefile` → 恰 1 行。 #### 卡 14 · `arch/arm/cpu/armv7/s5p-common/Makefile`(修改,19 行) - 作用:s5pc1xx 的 SPL 构建下补编 `timer.o` / `sromc.o`(SPL 框架需要 legacy timer)。 - 为什么:SPL 框架会调 `timer_init()`——不补编就链接失败。 - 关键片段: ```makefile ifeq ($(filter s5pc1xx,$(SOC)),s5pc1xx) # s5pc1xx SPL needs the legacy timer (common/spl calls timer_init) obj-y += timer.o obj-y += sromc.o ``` - 就位核验:`grep -n -A3 's5pc1xx SPL needs' arch/arm/cpu/armv7/s5p-common/Makefile` → 该块在位。 #### 卡 15 · `scripts/Makefile.xpl`(修改,632 行) - 作用:`mkexynosspl` 规则只对 exynos 生效——S5PV210 用自带的 16B 头格式(`tools/mkbl1.py`), 不走 exynos4412 的定长格式。 - 为什么:S5PV210 若也走 `mkexynosspl`,产出的 SPL 包装格式与 iROM 期望不符。 - 关键片段: ```makefile # s5pc1xx (S5PV210) uses the 16-byte-header BL1 format of the board's own # packer (tools/mkbl1.py); mkexynosspl's exynos4412 fixed-size layout does # not match, so only exynos takes this rule. ifneq ($(CONFIG_ARCH_EXYNOS),) INPUTS-y += $(obj)/$(BOARD)-spl.bin endif ``` - 就位核验:`grep -n 'only exynos takes this rule' scripts/Makefile.xpl` → 2 处命中(两段同注记)。 #### 卡 16 · `drivers/mmc/s5p_sdhci.c`(修改,244 行) - 作用:SDHCI 驱动加一条 `of_match`——`samsung,s5pv210-sdhci`,让设备树节点能绑上驱动(全文件仅 +1 行)。 - 为什么能这么小:驱动主体在主线里已存在;缺的只是「认这块板的相容串」。 - 关键片段: ```c static const struct udevice_id s5p_sdhci_ids[] = { { .compatible = "samsung,exynos4412-sdhci"}, { .compatible = "samsung,exynos4210-sdhci"}, { .compatible = "samsung,s5pv210-sdhci"}, { } }; ``` - 就位核验:`grep -n 's5pv210-sdhci' drivers/mmc/s5p_sdhci.c` → 恰 1 行。 #### 卡 17 · `arch/arm/mach-s5pc1xx/pinmux.c`(修改,37 行) - 作用:`pinmux_decode_periph_id()` 由桩改实读 `samsung,periph-id`(单 cell;缺属性/长度不足 → `PERIPH_ID_NONE`); `exynos_pinmux_config()` 保持返回 0 的桩(引脚复用归板级)。 - 为什么:SDHCI 驱动探测时按 periph id 判断「SDMMC0 还是 SDMMC2」——桩恒返回 0 会让探测以 `-EINVAL` 失败(历史停报的根因)。 - 关键片段: ```c int pinmux_decode_periph_id(const void *blob, int node) { int err; u32 cell; err = fdtdec_get_int_array(blob, node, "samsung,periph-id", &cell, 1); if (err) { debug("invalid peripheral id\n"); return PERIPH_ID_NONE; } return cell; } ``` - 就位核验:`grep -n 'samsung,periph-id' arch/arm/mach-s5pc1xx/pinmux.c` → 命中; `grep -c '"interrupts"' arch/arm/mach-s5pc1xx/pinmux.c` → `0`(无旧载体残留)。 #### 卡 18 · `common/version.c`(修改,26 行) - 作用:smart210 构建下用守卫覆盖 `U_BOOT_VERSION_STRING`——主程序 banner 标识三行的第 2 行(版本行)变成 `U-Boot-Smart210 v0.1 (<日期> - <时间> <时区>)`;非 smart210 路径逐字保留原定义。 - 为什么用守卫而不是改公共定义:其他板零影响(零行为变化)。 - 关键片段: ```c #ifdef CONFIG_TARGET_SMART210 #define U_BOOT_VERSION_STRING "U-Boot-Smart210 " CONFIG_SMART210_PORT_VERSION \ " (" U_BOOT_DATE " - " U_BOOT_TIME " " U_BOOT_TZ ")" #else #define U_BOOT_VERSION_STRING U_BOOT_VERSION " (" U_BOOT_DATE " - " \ U_BOOT_TIME " " U_BOOT_TZ ")" CONFIG_IDENT_STRING #endif ``` - 就位核验:`grep -n 'U-Boot-Smart210\|CONFIG_TARGET_SMART210' common/version.c` → 守卫与覆盖串在位; **运行判据 = 主程序 banner 标识三行的第 2 行(版本行)**(第 7 章)。 ### 3.4 改动组织方式 + 延伸阅读 - **组织方式**(为什么落这些层): - 板级专属(设备、引脚、机器号、烧写脚本)→ `board/samsung/smart210/`; - SoC/平台面(Kconfig 选项、periph id 解码)→ `arch/arm/mach-s5pc1xx/`; - 驱动面尽量小:`drivers/mmc/s5p_sdhci.c` 只 +1 行相容串; - 构建系统面(dtb 规则、SPL 依赖、mkexynosspl 收窄)在各自 Makefile; - 版本面用 `common/version.c` 的守卫覆盖。 - 总原则:**不删任何现有板级**;Smart210 与 goni 并存,未用能力靠 defconfig 不启用(`port-plan.md §5.3`)。 - **延伸阅读**(选型论证,另见 `port-plan.md`):`port-plan.md §4.6`(MMC 走 DM 路径的证据与方案选型)、 `§4.11`(banner 版本串机制与备选否决)、`§4.12.4`(ENV 落点方案选型)、`§4.3`(内存模型与时钟)。 - 就位核验(整批):把 §3.3 各卡的核验命令逐条跑一遍,全部命中即可进第 4 章。 ## 第 4 章 构建 (读本章:产出四件产物并自查。命令全部在 WSL 源码树里跑。) ### 4.1 defconfig 与构建命令 ```bash cd ~/ub210/u-boot make O=../build-smart210 smart210_defconfig CROSS_COMPILE=arm-linux-gnueabihf- make -j6 O=../build-smart210 CROSS_COMPILE=arm-linux-gnueabihf- ``` - 逐句解释:`O=../build-smart210` = 构建树放源码树外(产出到 `~/ub210/build-smart210`;源码目录保持干净); `smart210_defconfig` = 套用本板配置;`CROSS_COMPILE=arm-linux-gnueabihf-` = 用交叉工具链编译;`-j6` = 并行(数字按你的核数)。 - 为什么两条分开:先配置、后编译——配置阶段把 defconfig 落成 `.config` 与生成头。 判据:两条命令退出码均 0;构建输出里没有 `warning:` 行(本项目 P5 终版构建 = 零警告); 四件产物存在(§4.3)。若报 `symbol value '0x80000' invalid` → 第 9 章坑⑧。 ### 4.2 BL1 打包 ```bash python3 tools/mkbl1.py ../build-smart210/spl/u-boot-spl.bin ../build-smart210/u-boot-bl1.bin ``` - 为什么:iROM 要求 BL1 = 16 字节头 + 代码;头里存加载长度与 32 位累加和(工具见 §3.3 卡 11)。 - 为什么每次重编都要重新打包:工具从当次 `u-boot-spl.bin` 生成;bl1 与 spl 必须同源(坑⑥)。 判据:输出形如 `../build-smart210/u-boot-bl1.bin: 5136 bytes (code 5120, checksum 0x00084a5e)` 且退出码 0 (本项目 P5 实测:code 5120、checksum `0x00084a5e`;你的数值随构建变化,格式一致)。 ### 4.3 产物清单与自检 | 产物 | 路径 | P5 实测大小 | 说明 | |---|---|---|---| | `u-boot.bin` | `~/ub210/build-smart210/u-boot.bin` | 411272 B | 主程序(SPL 的装载对象) | | `u-boot-spl.bin` | `~/ub210/build-smart210/spl/u-boot-spl.bin` | 5120 B | SPL(在 `spl/` 子目录里) | | `u-boot-bl1.bin` | `~/ub210/build-smart210/u-boot-bl1.bin` | 5136 B | BL1 = 头 16B + 5120B 代码 | | `u-boot.dtb` | `~/ub210/build-smart210/u-boot.dtb` | 3552 B | 设备树(含两 sdhci 节点) | - bl1 ↔ spl 交叉核对(两层):① 打包输出 `(code N, …)` 的 N 必须等于 spl 文件尺寸; ② 烧写前脚本自动核对(BL1 内嵌 SPL 的长度 + 累加和与同目录 `u-boot-spl.bin` 一致),失败即 `ABORT: … does not embed …`(坑⑥)。 - 为什么必须核对:bl1 与 spl 出自不同构建时「头自洽 ≠ 版本一致」——板子行为会与源码不符(坑⑥)。 - 指纹登记指针:四件的大小 / sha256 登记于 `bringup-test.md §7`(登记纪律与对照说明见附录 B)。 判据:`ls -l` 四件在场;`wc -c` 尺寸为同量级(对照上表;你的哈希/尺寸随构建变化,量级一致即可); §4.2 的 `(code N, …)` 中 N = spl 文件尺寸。 ### 4.4 构建常见问题 - `make smart210_defconfig` 报 `symbol value '0x80000' invalid`,`.config` 里 `CONFIG_SYS_MONITOR_LEN=0`: defconfig 的 int 型符号不能写 `0x` 前缀(坑⑧)。 - 改了代码/配置但构建行为不变,或 WSL 树与工作区两侧不一致:双树同步问题(坑⑨)。 判据:按上述两条对照;仍不通 → 按 §9.3 收集求助材料。 ## 第 5 章 卡布局 (读本章:把卡做成正确布局;首次或要重置卡时执行一次。布局会清空卡上数据。) ### 5.1 扇区级布局表 | 区域 | LBA | 字节范围 | 大小 | 内容 / 写入者 | |---|---|---|---|---| | 引导区 | 0..2047 | 0x00000000–0x000FFFFF | 1 MiB | 扇区 0 = MBR(布局操作写);扇区 1 = BL1、扇区 49 起 = `u-boot.bin`(烧写脚本写);其余不动 | | ENV 区 | 2048..2079 | 0x00100000–0x00103FFF | 16 KiB | U-Boot 环境(`saveenv` 写;`CONFIG_ENV_OFFSET` / `CONFIG_ENV_SIZE`) | | B 槽 | 2080..4095 | 0x00104000–0x001FFFFF | ≈1 MiB − 16 KiB | batch-05 B 段:试用镜像(`fwupdate` 写;标志有效且 slot=1 时 SPL 自 2080 启动;机制详述 = `port-plan.md §4.13.2`) | | 数据分区(FAT32) | 4096..卡尾 | 0x00200000–卡尾 | ≈1.9 GB | 用户数据;卷标 `SMART210`;MBR 类型 0x0c | - **两个「1 MiB」不可混**:① 引导区 = 扇区 0..2047(写镜像的上限);② SPL 读窗口 = 扇区 49 起 2048 扇区 (只读操作,不写卡)。 - 为什么这样分:镜像只占扇区 1 / 49 起的小块;ENV 固定于 `0x100000`(在镜像覆盖区之外,重烧固件不丢它); 数据分区从 2 MiB 起(与 ENV 区之间留 ≈1 MiB 间隔)。 判据:布局操作完成后的四项核对见 §5.4;烧写脚本 C1–C4 即按本表数值判定(§6.4)。 ### 5.2 路线 A:Windows `diskpart`(本项目实测执行) ```text diskpart DISKPART> list disk ← 核对盘号与容量(≈1.92 GB;选错盘即毁盘) DISKPART> select disk <盘号> DISKPART> detail disk ← 二次核对(输出 = 磁盘属性与卷列表) DISKPART> clean ← 只清分区结构(引导镜像随后由烧写重建) DISKPART> create partition primary offset=2048 ← 偏移单位 = KB:2048 KB = 2 MiB = LBA 4096(关键步) DISKPART> format fs=fat32 quick label=SMART210 DISKPART> assign ← 仅为拷测试文件方便(可省) DISKPART> exit ``` - 每步安全性:`list disk` / `detail disk` 是核对步;`clean` 不可撤销但只作用于选中的那张盘,且随后烧写会重建引导负载; `offset=2048` 的 KB 语义是把分区推离 ENV 区的唯一参数;`format` 只写分区范围内。 - **不要用「磁盘管理」GUI 新建分区**——GUI 默认起点 1 MiB(LBA 2048)会压到 ENV 区(坑①)。 判据:`DISKPART> list partition` 的 `Offset` 列 = `4096`(或 PowerShell `Get-Partition -DiskNumber <盘号>`,输出含 Offset)。 ### 5.3 路线 B:WSL `parted` + `mkfs.vfat`(备选,本项目未实测该路线) (语境注:第 5 章「路线 A/B」= **布局**路线(A = §5.2 Windows `diskpart`、B = 本节 WSL `parted`); 第 6 章「烧写路线 A/B」字母↔系统映射相反,勿混。) ```bash lsblk # 核对:整盘、容量 ≈1.92GB、无挂载点 DEV=/dev/sdb # ← 换成整盘(不是分区) sudo parted -s "$DEV" mklabel msdos sudo parted -s "$DEV" mkpart primary fat32 2MiB 100% sudo partprobe "$DEV" # 或 sudo blockdev --rereadpt "$DEV" sudo mkfs.vfat -F 32 -n SMART210 "${DEV}1" ``` - 每步安全性:`lsblk` 核对步;`mklabel msdos` 重写扇区 0;`mkpart … 2MiB 100%` 起点 2 MiB = LBA 4096、尾 = 卡尾; `mkfs.vfat` 只写分区内。 - 备选说明:**本路线为设计面给出、本项目未实测**——实测路线是路线 A(`diskpart`,逐项核对后执行)。 判据:`sudo parted -s "$DEV" unit s print` → 分区 1 的 `Start` = `4096s`。 ### 5.4 布局后四项核对 | 核对项 | 期望 | 命令(路线 A / B) | |---|---|---| | 分区起点 | 4096 扇区(2 MiB) | A:`diskpart list partition`(Offset 列)或 `Get-Partition -DiskNumber <盘号>`;B:`sudo parted -s "$DEV" unit s print` | | 分区类型 | 0x0c(FAT32 LBA) | 同上 | | 分区尾 | 卡尾最后一扇区 | 同上 | | 文件系统 | FAT32、卷标 `SMART210` | A:`dir <新盘符>:`;B:`sudo file -s "${DEV}1"` | - 注意(2026-09-13 修订口径):路线 A 的偏移核对用「能列出偏移的命令」——`list partition` 的 Offset 列或 `Get-Partition`; `detail disk` 不含分区偏移,仅作盘身份核对。 判据:四项全过再进第 6 章(任何一项不过 → 重新布局;烧写脚本 C3 也会把不合规的卡拦下)。 ### 5.5 时序纪律 - **布局必须在烧写之前**:布局要重写扇区 0 并格式化数据分区,且不保证保留扇区 1 / 49 的既有内容。 先布局、再烧写,终态即「新分区表 + 新镜像」;反过来(先烧后重分区)会丢掉刚写的镜像。 - 重做布局 = 按新卡对待:ENV 区与数据分区一起被重置(§8.4)。 判据:动手前确认顺序——本章(第 5 章)在 §6.3 烧写之前完成。 ## 第 6 章 烧写 (读本章:写入 BL1 + 主程序;理解校验与「完成」语义。警告:写卡不可逆,先做对第 5 章的布局。 本章两条烧写路线:路线 A(WSL `sd_fusing.sh`,§6.2–§6.5)/ 路线 B(Windows 原生 `sd-fusing-win.py`,§6.6); 与第 5 章「布局路线 A/B」为不同语境。) ### 6.1 烧写原理 - 扇区 1 ← `u-boot-bl1.bin`(SPL + 16B 头);扇区 49 起 ← `u-boot.bin`。 - iROM 读扇区 1(校验 16B 头);SPL 读扇区 49 起(1 MiB 窗口)。 - 脚本**不写** MBR(扇区 0,属布局操作)与 ENV 区(属 `saveenv`)——三者各管各的区域。 判据:与脚本校验同口径——镜像末端 ≤ 2048×512(1 MiB 引导区,C1)且 ≤ `CONFIG_ENV_OFFSET`(C2)。 ### 6.2 读卡器接入 WSL ```bash # Windows(PowerShell / cmd) usbipd list # 找到读卡器条目,记下 BUSID usbipd bind --busid # 把设备交给 usbipd(首次需要) usbipd attach --wsl --busid # 挂进 WSL ``` - 三要点(本项目实测):① attach 前若 Windows 已给卡挂卷,先 `mountvol <盘符>: /p` 卸载; ② WSL 空闲关停会把卡从 WSL 摘除——attach 后保持会话活跃(保活);③ 报 `Device in error state` → 拔插读卡器重试(仍不行 → 烧写路线 B,见 §6.6)。 - 为什么不用 `wsl --mount`:它不适用于 USB 读卡器(实测报 `0x8007000f`;坑②)。 判据:WSL 内 `lsblk` → 出现整盘设备(如 `/dev/sdb`,容量 ≈1.92 GB、无挂载点)。 ### 6.3 烧写命令 ```bash cd ~/ub210/u-boot/board/samsung/smart210 ./sd_fusing.sh /dev/sdX ~/ub210/build-smart210/u-boot.bin ~/ub210/build-smart210/u-boot-bl1.bin ``` - 参数语义:第 1 个 = 读卡器整盘(**不是分区**,如 `/dev/sdb` 而非 `/dev/sdb1`);第 2 个 = 主程序;第 3 个 = BL1。 判据:结尾输出 `Commit ok:` 行 + `Done. …` 行,退出码 0(看到 `Done.` 才表示「已提交且已核验」)。 ### 6.4 校验语义逐条 + ABORT 处置 写入前校验(全部在任何 `dd` 之前;任一中止 = 未写设备): | # | 判据句 | 失败提示要点 | |---|---|---| | C1 引导区占用 | `49×512 + u-boot.bin 尺寸 ≤ 2048×512`(1 MiB) | 镜像超出 1 MiB 引导区 | | C2 镜像不触 ENV 区 | `49×512 + u-boot.bin 尺寸 ≤ CONFIG_ENV_OFFSET` | 镜像末端越过 ENV 偏移 | | C3 ENV 区不与数据分区重叠 | 设备扇区 0 有 MBR(`55aa`)且分区 1 起点(字节)≥ 2 MiB(`0x200000`,扇区 4096) | 无分区表 → 提示先做布局;起点 < 2 MiB(压 ENV 区或 B 槽)→ 提示重布局 | | C4 ENV 区在设备内 | `CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE ≤ 设备字节数` | ENV 区超出设备容量 | (既有校验保持不变:BL1 头自洽 + 与同目录 `u-boot-spl.bin` 交叉核对、BL1 ≤ 16 KiB、`u-boot.bin` ≤ 1 MiB 读窗口、设备为整盘且容量足够。 C1/C2/C4 的数值单源 = `configs/smart210_defconfig`;C3 阈 = `port-plan.md §4.12.3`(分区 1 起点 ≥ 2 MiB)。) 写入后提交与回读(W1–W3): | # | 判据句 | 失败提示要点 | |---|---|---| | W1 提交 | 两处 `dd` 后执行 `sync` + `blockdev --flushbufs "$DEV"`,通过方可继续 | 命令失败 → 非零退出(不得报成功) | | W2 回读校验 | 以 `dd iflag=direct`(O_DIRECT,绕过页缓存)回读并逐字节比对两区域:扇区 1 的 BL1、扇区 49 起的 `u-boot.bin` | 任何不一致 → `ABORT: …` + 非零退出(fail-closed) | | W3 完成语义 | 「完成」= 已提交(W1)且已核验通过(W2)——`Commit ok:` 行与收尾 `Done.` 行仅在两者通过后出现 | 未通过即不打印成功行(其缺席 = 未完成) | - 失败语义:写入前中止 = 未写;出现在 `Writing …` 之后 = 卡可能已被写入 → **重跑脚本**(不得按「未写设备」处置)。 - 为什么回读要绕页缓存:普通读可能读到内存里的缓存副本而不是卡上实况——那样校验证明不了介质内容(历史教训见坑⑤)。 判据:脚本输出与上表逐条对应;出现 `ABORT` 时按「失败语义」两分行处置。 ### 6.5 烧写后操作与首启判读 - 写完后:先 `sync`、再安全移除/断开读卡器更稳;上电前等待数秒让卡完成内部提交。 - 首启判读:烧写后的**首次**上电若出现个别命令缺失(`Unknown command`)等异常,**先断电重上电再判读**—— 不得直接判为固件缺陷(坑⑤)。 判据:拔卡/上电前完成等待;首启异常先重上电一次再下结论。 ### 6.6 路线 B:Windows 原生(`sd-fusing-win.py`) **何时用**:读卡器挂不进 WSL(§6.2 ③ 报 `Device in error state` 且拔插重试仍不行),或手上没有 Linux 环境—— 全程在 Windows 上完成烧写,不依赖 usbipd / WSL。 **与路线 A 的关系**:同布局(第 5 章先做布局)、同校验口径(写前 C1–C4 与写后提交/回读 W1–W3, 判据表 = §6.4,不重述);本路线 2026-09-16/17 实板实测走通。 **前置条件**: - 管理员 PowerShell(写物理盘需要提权;缺权会明示错误码并退出); - Windows 原生 Python 3(工具仅用标准库 + `ctypes`,无第三方依赖); - 工具位置 = 源码树 `board/samsung/smart210/sd-fusing-win.py`(与 `sd_fusing.sh` 同目录)。 **认卡(`--scan`,只读,不写盘)**: ```text cd <你的工作区>\u-boot\board\samsung\smart210 python sd-fusing-win.py --scan ``` 输出逐条列出物理盘(容量 / MBR 有无 / 分区 1 类型与起点 LBA);认准容量 `≈1.9 GB`、`MBR=有`、 分区 1 类型 `0x0c`、起点 `LBA 4096` 的那张卡——该行末尾带 `← 疑似 SMART210 卡` 标记(三重特征匹配)。 **烧写**: ```text python sd-fusing-win.py --target [--spl ] ``` - `` = 认卡步骤里的盘号(工具内部转成 `\\.\PhysicalDriveN`);镜像 = 当次构建产物(§4.3; 需要身份核对时按 `bringup-test.md §7` 指纹表)。 - 写前检查全过 → 提示输入 `YES` 确认;`--yes` 可跳过确认(脚本化用)。 **输出与「完成」语义**:写前检查 → 写入 → 提交 → 回读核验;看到 `Commit ok:` + `Done.` = 已提交且已核验 (与 §6.4 同口径)。失败两分处置同 §6.4:写前中止 = 未写;`写入 …` 行之后失败 = 卡可能已被写入 → 重跑。 **注意事项**: - 写物理盘必须用**管理员** PowerShell; - 插卡后 Windows 弹「需要格式化」→ **一律取消**(否则会破坏引导区); - 先关掉可能占用该卡的程序(资源管理器窗口 / 杀毒扫描); - 盘号务必二次核对——写卡不可逆,选错盘即毁盘。 **自测与诊断**: - `python sd-fusing-win-selftest.py`——离线镜像演练自测(7 项;免管理员、不碰物理盘); - `python no-buffer-diag.py [目标文件]`——回读 `NO_BUFFERING` 报错时的只读排障件(默认自建测试镜像)。 **旧 dd 裸写(历史)**:`bringup-test.md §3`(dd for Windows 直写方案的存档,保留备查)。 ## 第 7 章 上电验收 (读本章:上电、逐行对照、跑命令。) ### 7.1 上电与输出结构 ```text # 上电前(板侧): 1. S2 开关拨到 SDBOOT 侧(另一侧 = NAND 启动) 2. 卡插入 SD 槽 3. 接好串口(UART0,115200-8N1)后上电 ``` - 开关说明(本项目实测):板上启动开关 = **S2**,丝印 `SDBOOT` / `NAND`——上电前拨到 `SDBOOT` 侧; 另一侧 `NAND` = NAND 启动(本教程不涉及)。 - 输出结构:从 `SPL: UART0 @ 115200-8N1` 到 `SPL: Jump to U-Boot @ 0x34800000` 是 SPL 直写串口的输出; 自 ASCII 块(75 `*` 上框线行)起是主程序(DM 串口)输出。首行前的个别 `0x00` 是 UART 初始化毛刺,无害。 判据:上电后第一行输出 `SPL: UART0 @ 115200-8N1`(无输出 → 第 9 章坑⑪)。 ### 7.2 期望日志逐行对照 ```text SPL: UART0 @ 115200-8N1 SPL: S5PV210 @ 800MHz, DDR2 512MiB SPL: DDR self-test ......... OK SPL: Reloc test ............ OK SPL: Boot source: SD/MMC (sector 49) SPL: fwflag invalid -> slot A SPL: Jump to U-Boot @ 0x34800000 *************************************************************************** ____ __ ___ _ __ /\ _`\ /\ \__ /'___`\ /' \ /'__`\ \ \,\L\_\ ___ ___ __ _ __\ \ ,_\ /\_\ /\ \ /\_, \/\ \/\ \ \/_\__ \ /' __` __`\ /'__`\ /\`'__\ \ \/ \/_/// /__\/_/\ \ \ \ \ \ /\ \L\ \/\ \/\ \/\ \/\ \L\.\_\ \ \/ \ \ \_ // /_\ \ \ \ \ \ \_\ \ \ `\____\ \_\ \_\ \_\ \__/.\_\\ \_\ \ \__\ /\______/ \ \_\ \____/ \/_____/\/_/\/_/\/_/\/__/\/_/ \/_/ \/__/ \/_____/ \/_/\/___/ *************************************************************************** FriendlyARM Smart210 / S5PV210 U-Boot-Smart210 v0.1 (…) https://gitee.com/thecasttim CPU: S5PC110 @ 800 MHz Board: Smart210 (512MiB DDR2) Core: devices, uclasses, devicetree: separate Boot: SD/MMC (SDHCI0) MMC: SDHCI0 (1.9 GiB SDHC), SDHCI1 (none) Env: Reading from MMC(0) ... OK Net: dm9000 @ 0x88000000, 02:12:34:56:78:9a In: serial Out: serial Err: serial Smart210 # ``` 逐行对照: | 行 | 含义 / 证明了什么 | |---|---| | `SPL: UART0 @ 115200-8N1` | SPL 直写串口第一行——时钟 + UART 初始化成功(配置值 115200-8N1) | | `SPL: S5PV210 @ 800MHz, DDR2 512MiB` | 配置值:APLL 800MHz + DDR2 512MiB 就绪(SPL 段第 2 行) | | `SPL: DDR self-test ......... OK` | DMC0 基部窗口读写探针通过(`OK`/`FAIL` 为真实自检结果) | | `SPL: Reloc test ............ OK` | 重定位目标区顶部读写通过(512 MiB 内存模型的关键证据) | | `SPL: Boot source: SD/MMC (sector )` | 启动源(`0xD0037488` 通道寄存器解码)+ 实际起扇区(A 槽 49 / 试用 B 槽 2080) | | `SPL: fwflag …` | 标志扇区判决——常态 `invalid -> slot A`;试用态 `valid -> slot B`(batch-05 B 段新增行;未烧 B 段时为六行) | | `SPL: Jump to U-Boot @ 0x34800000` | 主程序已读到 TEXT_BASE,准备跳转 | | ASCII 块(上/下框线各 75 `*` + 艺术字 7 行 + 标识三行) | 主 banner(batch-06 逐字节规格 = `batch-06-boot-banner.md §2.5`);版本行 = `version_string` | | `CPU: S5PC110 @ 800 MHz` | 主程序读到的 CPU 与时钟 | | `Board: Smart210 (512MiB DDR2)` | 板名 + 容量(内存信息并入本行;旧 `Model:`/`DRAM:` 行已删) | | `Core: devices, uclasses, devicetree: separate` | DM 设备计数(数值随配置变化,判读不依赖) | | `Boot: SD/MMC (SDHCI0)` | 启动通道(`0xD0037488` 解码;本卡 = SDHCI0) | | `MMC: SDHCI0 (1.9 GiB SDHC), SDHCI1 (none)` | DM 枚举的 MMC 控制器(每控制器一行内;无卡 = `(none)`) | | `Env: Reading from MMC(0) ... OK` | ENV 从 SD 的 `0x100000` 装载(首启无 `OK`,见注 1) | | `Net: dm9000 @ 0x88000000, ` | 网络已启用(P6-A):驱动名 / IO 基址 / MAC(`ethaddr` 值) | | `In:/Out:/Err: serial` | 控制台 = UART0(`@` 截断显示) | | `Smart210 #` | 到达 shell——主流程成功 | - 注 1:ENV 行末尾的 `OK`——首次上电(ENV 区还没写过)不出现 `OK`(正常回落,见 §8.4);`saveenv` 后各次上电均出现。 - 注 2:判读以 `Env: Reading from MMC(0) ... OK` 整行出现为准;首启空白 ENV 时该行无 `OK`(正常,见 §8.4)。 - 注 3:`SPL: fwflag …` 行文本/落位与 `SPL: Boot source: …` 的 `` 口径 = `batch-06-boot-banner.md §2.8`(与 batch-05 B 段一次协调)。 - 注 4:`Net:` 行 = P6-A 起形态(`dm9000 @ 0x88000000, `);未设 `ethaddr` 时 = `Net: (none)` + 上游错误行;网络联调/升级用例 = `bringup-test.md §10`。 - 注 5(历史):若你翻阅 `bringup-test.md §4.1/§4.2` 的早期日志,会看到 `[D8]` / `[AC]` / `[M]` 等 `[xx]` 打点与 `DRAM: 1 GiB`、旧 banner 字样—— 那是 bring-up 期的历史记录(打点已移除、内存口径已更正),不是现行形态;本文给的是最终形态的日志。 判据:从第一行逐行对照到 `Smart210 #`;偏离的行走 §7.3 定位。 ### 7.3 按最后可见行定位 | 停在 | 故障方向 | |---|---| | `SPL: UART0 @ 115200-8N1` 之前(无任何输出) | 时钟/UART 初始化;串口线序/电平/COM 口(坑⑪) | | `SPL: S5PV210 @ 800MHz, DDR2 512MiB` 之前 | DMC0 初始化未完成(PHYSTATUS DLL 锁定等待) | | `SPL: DDR self-test .........` / `SPL: Reloc test ............` 之后无 `OK/FAIL` | 该窗口读挂在总线上——地址无映射 | | `SPL: … FAIL`(含明细行 `SPL: @0x… read …, expected …`) | 该窗口读写失败(DMC0 参数与颗粒不符) | | `SPL: Boot source: …` 之后无 `SPL: Jump …` | iROM API / 起扇区内容(`SPL: load failed (sector )` 明示扇区;§9.2) | | `SPL: Jump to U-Boot …` 之后无主程序 banner | 跳转后主程序未跑起来(DRAM 数据通路 / TEXT_BASE) | | 主程序 banner 后止步(信息区未出全) | 重定位目标越界(历史机制见 §9.2;先核对单 bank 配置) | | `MMC:` 行为空 / `mmc info` 报无卡 | MMC 路径三对应位(DTS 节点 / periph id 解码 / 板级引脚复用,`port-plan.md §4.6`) | | `Env: Reading from MMC(0) ...` 后无 `OK` | ENV 区空白(首次上电,正常)或读取失败——先看 `mmc dev 0` + `mmc info` 能否识别卡 | 判据:用「最后可见行」对照本表定位方向;细则与处置见第 9 章。 ### 7.4 验收命令表 (在 `Smart210 # ` 提示符下逐条执行;输出为本项目实测。) | # | 命令 | 期望输出 / 结果 | |---|---|---| | 1 | `mmc list` | 卡挂控制器 0(`SAMSUNG SDHCI: 0 (SD)`);控制器 1 无卡(`SAMSUNG SDHCI: 1`) | | 2 | `mmc dev 0`;`mmc info` | `Device: SAMSUNG SDHCI`、`Capacity:` 1.9 GiB 量级、`Bus Width: 4-bit`、SD 版本行 | | 3 | `md 0xd0037488 1` | `eb000000`(iROM 启动通道 = SDMMC0 的实板实证) | | 4 | `ls mmc 0:1` | 列表含 `TEST.TXT`(数据分区可读) | | 5 | `load mmc 0:1 ${loadaddr} TEST.TXT`;`crc32 ${loadaddr} ${filesize}` | `crc32 … ==> 85ec2194`——与主机侧预计算一致(逐位正确) | - 第 5 条的「主机侧预计算」(WSL):`python3 -c "import zlib,pathlib;print('%08x'%zlib.crc32(pathlib.Path('TEST.TXT').read_bytes()))"`。 - 为什么 `md 0xd0037488 1` 能证明 SD 槽:iROM 把启动通道号记在这个地址——`eb000000` = SDMMC0(`0xEB000000`)。 判据:五条输出与上表一致(逐条记录)。 ### 7.5 P5 通过判据 - 三条一起看:① 启动关键行——`MMC: SDHCI0 (…)`/`SDHCI1 (none)` 与 `Env: Reading from MMC(0) ...`(首启无 `OK` 属预期);② 命令面全绿(§7.4 五条); ③ ENV 持久化(第 8 章:`saveenv` → 断电重上电 → 值仍在)。 - 用例口径:本项目验收按 T1–T12 用例表执行(定义见 `bringup-test.md §9`)——本文 §7.4 覆盖 T1–T5, §8.2 / §8.3 覆盖 T7–T9;机检面(T10–T11)与文档一致面(T12)由项目侧执行(定义见 `bringup-test.md §9`)。 判据:三段全绿 = P5 通过;任一不绿 → 第 9 章。 ### 7.6 网络应用(P6 应用面:TFTP 服务器 / 网络升级 / 传输运行 / 网络测试) (本节 = P6 应用面用法速查(板端命令在 `Smart210 # ` 提示符下执行);P6 移植与联调细节不属本教程范围—— 判据与用例 = `bringup-test.md §10`,设计论证 = `port-plan.md §4.7` / `§4.13`。 实板建议操作序 ① → ③ → ④ → ②:② 会替换在板件,放最后做。) **① 主机 TFTP 服务器**(`board/samsung/smart210/tftp-gui.py`;纯 Python 标准库、免安装、只读服务): 1. **运行**:在 `board/samsung/smart210/` 下 `python tftp-gui.py`(免控制台窗口可用 `pythonw tftp-gui.py`);可选自检 = `python tftp-gui-selftest.py`。 2. **选根目录**:把要下发的文件放进去(测试资产 `TEST1M.BIN`;升级用新构建的 `u-boot.bin`)。 3. **启动**:默认监听 `0.0.0.0:69`;**Windows 侧双条(实测口径)**:① 以太网「网络类别」改**专用**(Windows 设置 → 网络和 Internet → 以太网); ② 防火墙放行 Python / UDP 69(首次运行弹窗勾「专用网络」允许即可)。**公用档下板端 UDP 首包被静默丢弃**—— 命令行补放行规则(端口级 / 程序级 / 组合)均无效,实测真解 = 改「专用」(改后防火墙开着即通)。 端口被占用时:GUI 侧换端口(如 `1069`)+ 板端 `setenv tftpdstp 1069` 对齐——端口只经该环境变量传递 (`net/tftp.c:928-930`);`tftpboot` 的文件名参数只接受 `[hostIPaddr:]file`(`cmd/net.c:62-64`),不带端口。 板端取件与校验(联调主路线): ```text tftpboot 0x21000000 TEST1M.BIN crc32 0x21000000 ${filesize} ``` 判据:`filesize = 0x100000`;`crc32` = `04d0e435`(与主机侧预计算逐位一致)。TFTP 不通 → 备选 `wget` / HTTP。 **② 网络升级 U-Boot**(双槽机制:试用 → 提交 / 回滚;详 = `port-plan.md §4.13`): 前置:ENV 里 `fwupdate` / `fwcommit` / `fwrollback` 三脚本在位(缺则按 `batch-05-net-fw.md §2.4.5` 用 `fw-scripts.env` 录入)。 ```text setenv fwfile u-boot.bin setenv fwsize 0x<新件字节数(十六进制)> run fwupdate # 下载 → 写 B 槽(试用态)→ 置标志;reset 后 SPL 走 slot B run fwcommit # 试用满意:写 A 槽 + 清标志;reset 后 slot A run fwrollback # 不满意:清标志;reset 回 slot A ``` - 任一 `FWUPDATE-FAIL` / `FWCOMMIT-FAIL` = 保护生效(**A 槽零写入**);按报错字处置(尺寸不符 → 重设 `fwsize` 重跑)。 - 边界:BL1(扇区 1)**不提供网络升级**——写坏只能按第 6 章卡刷恢复。 **③ 传输程序并运行**(`tftpboot` → `crc32` → `go`;P8 内核加载的铺路用法): - **载荷址纪律**:推荐 `0x21000000`(本教程与双槽脚本的下载缓冲);**禁** `0x40000000` 及以上(DMC0 无映射区); **避** `0x24000000` 起帧缓冲段、`0x33000000` early 栈、`0x34800000` 镜像区与重定位区(≈`0x3F9xxxxx` 起)、SPL / ENV 面。 - 样例载荷 `board/samsung/smart210/payload-hello.S`(构建 = WSL 单行): ```text arm-linux-gnueabihf-as -o payload-hello.o payload-hello.S && arm-linux-gnueabihf-ld -Ttext=0x21000000 -o payload-hello.elf payload-hello.o && arm-linux-gnueabihf-objcopy -O binary payload-hello.elf payload-hello.bin ``` - 板端:`tftpboot 0x21000000 payload-hello.bin` → `crc32 0x21000000 ${filesize}` → `go 0x21000000` → 串口出 `SMART210 PAYLOAD OK`,随后 `## Application terminated, rc = 0x0` 回到提示符。 - 换成自备件同理(自家载荷 / 内核 uImage 换文件名);**内核引导本体 = P8,不在本教程。** **④ 网络测试**(脚本载荷:`mkimage -T script` 打包 → `source` 执行): ```text mkimage -T script -C none -n smart210-net-selftest -d net-selftest.txt net-selftest.img tftpboot 0x21000000 net-selftest.img source 0x21000000 ``` 判据 = 串口 `NETTEST PASS` 行;脚本正文 = `board/samsung/smart210/net-selftest.txt` (`dhcp` → `ping ${serverip}` → `tftpboot` → `crc32` 比对 `04d0e435`,`if/then/fi` 分支出 PASS / FAIL 行)。 ### 7.7 内核引导(P8:DT + uImage + 内置 initramfs → shell) (本节 = P8 应用面速查;板端命令在 `Smart210 # ` 提示符下执行。前置 = P6 链路(§7.6 ①:TFTP 服务器 + 网络类别「专用」); 构建链全文(DT 清单 / 构建命令)= `port-plan.md §22`;判据 J1–J5 与失败面 F1–F4 = `bringup-test.md §18`——实板执行与结论回填 = 该节; 内核显示面(batch-25)机制 = `port-plan.md §24`、用例与实测 = `bringup-test.md §19`。) **① 构建件**(WSL 产出;当次指纹登记 = `bringup-test.md §7`): | 产物 | 大小(B) | 备注 | |---|---|---| | `uImage-r2` | 5,951,032 | `bootm` 载荷——`mkimage -A arm -O linux -T kernel -C none`(Load/Entry = `0x20008000`;batch-25 命名 = `-r2` 后缀,旧件并存) | | `s5pv210-smart210.dtb` | 24,116 | 板级 DT(自有派生件,direct-dtc 编译;batch-25 = `&fimd` + panel 面) | | `zImage-r2` | 5,950,968 | 内核本体(mainline 6.18.51;构建时已内置 initramfs) | | `initramfs-r2.cpio` | 1,638,912 | busybox 静态 + `/init`(唯构建期消费——`INITRAMFS_SOURCE`) | (**batch-25 内核显示面终态值**(`-r2` 件 + dtb);尺寸沿革与 sha256 全表 = `bringup-test.md §7`。) **② 装载链(TFTP 优先;`bootm` 三段式)**: ```text setenv bootargs 'console=tty0 console=ttySAC0,115200n8 root=/dev/ram0 rw rdinit=/init'; saveenv tftpboot 0x20008000 uImage-r2 tftpboot 0x28000000 s5pv210-smart210.dtb bootm 0x20008000 - 0x28000000 ``` - 两件落地:把 `uImage-r2`(① 表)与 `s5pv210-smart210.dtb` 放进 TFTP 根目录(服务端 = §7.6 ①);文件名按落位实际名与命令对齐(R6 实链 = 卡上 `uImage` 名承载该件)。 - **fatload 备路**(SD-FAT;TFTP 不可用时):`fatload mmc 0:1 0x20008000 uImage-r2` → `fatload mmc 0:1 0x28000000 s5pv210-smart210.dtb` → `bootm 0x20008000 - 0x28000000`(R6 实链;crc32 双中 `3814c7e5` / `3779559c`)。 - 地址纪律(同 §7.6 ③):内核 `0x20008000`(`SYS_LOAD_ADDR`)、DT `0x28000000`;**禁** `0x40000000` 及以上、避 FB 段 `0x24000000` / 早期栈 / 镜像与重定位区。 - bootargs 字面 = **两处同文**(DT `chosen` / U-Boot env;内核面以引导器传入为准)——env 写一次即持久;`bootm` 出现的 FDT 重定位行 = 预期(不判)。 **③ 判据(J1–J5;逐级)**:J1 `Linux version 6.18.51`(内核 banner)→ J2 `Kernel command line: console=tty0 console=ttySAC0,115200n8 root=/dev/ram0 rw rdinit=/init`(bootargs 生效;字面 = ② 命令块)→ J3 `Run /init as init process`(辅助不判)→ J4 `SMART210-P8: initramfs init OK`(自造标记,主判)→ J5 提示符 `/ $ ` + 交互(`echo P8-SHELL-OK` 有回显 / `uname -r` = `6.18.51`)。 失败面 F1–F4(预注册判读表:看到什么 ⇒ 判 ⇒ 下一步)与留证格式 = `bringup-test.md §18`;**内核显示面判据(J-D1–J-D4)与失败面 F-D1–F-D5 = `bringup-test.md §19`**。 **④ 完成面(batch-24:墙②定因与修后——J1–J5 全中 · 到 shell;batch-25:内核显示面——J-D1–J-D4 全中)**: - **实板结果(2026-10-10,R4 回归轮)= J1–J5 全中(判据字面见 ③)**:J1–J4 逐行命中(内核 banner → cmdline → `Run /init as init process` → 主判标记 `SMART210-P8: initramfs init OK`);J5 提示符可达且可交互(`uname -r` → `6.18.51`;`echo P8-SHELL-OK` 有回显;`ls /` 完整)。本轮实际装载链 = `fatload` 两件 + `bootm`(② 同址命令块)。判据全文与失败面 = `bringup-test.md §18`。 - **墙②(内核串口面挂死)定因**:uart0 取钟接线 / 取钟语义——`dtsi` 基座取钟形与驱动取钟 / divslot 语义互斥(`UCON[10]` 切至 SCLK 路径后 TX 停摆);三点互证 = E1-A(PCLK 面重放无害)+ E1-B(SCLK 切换致乱)+ E2(`&uart0` 三槽锁 `CLK_UART0` 即通)。 - **修案(as-built)**:① `&uart0` 三槽锁 `CLK_UART0`(A2);② `/init` 控制台接线(devtmpfs + `/dev/console` 兜底 + `exec sh &1` 重定向序)→ 修法定案(`sh -i` + 内层 `exec 2>&1`)。 - **R6(20:0x)复验**:`bound f8000000.fimd (ops fimd_component_ops)` → `Console: switching to colour frame buffer device 100x30` → `fb0: exynosdrmfb` → `/ $ ` 交互(`uname -r` → `6.18.51`)——屏面 = 用户目视确认、串口留证 `tmp-b25/ser-r6-*.txt`。 - 观察项 4 条(非致命)= `port-plan.md §24.6`。 - 定因与修案全文(含 E1–E3 轮读数与留证)= `port-plan.md §23`。 ### 7.8 NAND 命令面(batch-26 · 1A:S5PV210 NFC 驱动 + `nand` 命令族;启动链 = 1B 待做) (本节 = NAND 应用面速查;板端命令在 `Smart210 # ` 提示符下执行。1A = 从 SD 启动后 `nand` 命令族可用(识别 / 读写 / 擦除 / 坏块 / ECC 注入);**NAND 冷启动链(1B)= 未开工**——闸门 = §4 批准 → 探针 → v-2 关闭。机制与布局 = `port-plan.md §25`;判据与实板用例 = `bringup-test.md §20`。) **① 识别**: ```text nand info ``` ⇒ `Device 0: nand0, sector size 128 KiB` + 页 2048 B / OOB 64 B / 擦除块 131072 B / ecc strength 1 bits / ecc step 2048 B; 启动行 `NAND: 1024 MiB`(K9K8G08U0E = 1 GiB = 8 Gbit;实读 ID `EC D3`)。 **② 读 / 擦 / 写**(测试区 = 空闲区块 18 起——块 0 只读): ```text nand erase 0x240000 0x20000 mw.l 0x21000000 0xA5A5A5A5 0x200 nand write 0x21000000 0x240000 0x800 nand read 0x22000000 0x240000 0x800 cmp.b 0x21000000 0x22000000 0x800 ``` 判据 = `Total of 2048 byte(s) were the same`(实板块 18 = `NAND-RW-OK`;8 块抽样 + 末块读出全绿 = `bringup-test.md §20`)。 **③ 坏块 / ECC / 拒绝面**: - `nand bad`:坏块扫描(实板全片零坏块)。 - `nand biterr `:ECC 注入——1 bit ⇒ 读时打印 `S5PV210 NAND: 1 bit error at byte 0 corrected` 且数据复原;2 bit ⇒ `ECC uncorrectable error`。 - 非页对齐偏移 / 越界写 = 命令面拒绝(`Attempt to write non page-aligned data` / `Offset exceeds device limit`)。 **④ 边界**:NAND 冷启动链(iROM → BL1 → U-Boot 全链)= **1B 面(未开工)**;Linux 侧 NAND(MTD 驱动)= 后续段另批。 ## 第 8 章 ENV 使用与持久化 (读本章:把 ENV 用起来,并验证它跨断电、跨重烧都在。) ### 8.1 ENV 是什么、存在哪 - ENV = U-Boot 的环境变量区:一串「名字 = 值」的配置。 - **存在哪**:SD 卡 `0x100000` 起 16 KiB(`CONFIG_ENV_OFFSET` / `CONFIG_ENV_SIZE`)——在镜像覆盖区之外(§5.1), 所以重烧固件(只跑烧写脚本)不碰它。 - 谁读谁写:启动时 `Env: Reading from MMC(0) ...` 装载(batch-06 起形态);`saveenv` 写回同一位置。 - 为什么用固定偏移:不依赖文件系统,布局/重烧操作天然不丢;代价 = ENV 区与数据分区之间留 ≈1 MiB 间隔(现为 B 槽——§5.1;布局详表 = `port-plan.md §4.12.1`)。 判据:`saveenv` 输出含 `Writing to MMC(0)...`(写入面生效);落点核对 = §5.1 布局表。 ### 8.2 命令面 ```text Smart210 # setenv p5test v1 Smart210 # saveenv Saving Environment to MMC... Writing to MMC(0)... OK Smart210 # printenv p5test p5test=v1 ``` - 三个命令的分工:`setenv` 只改内存里的值;`saveenv` 才落盘;`printenv` 查看。 判据:`saveenv` 输出 `Saving Environment to MMC... Writing to MMC(0)... OK`。 ### 8.3 持久化验证 - 断电重上电 ×3:每次 `printenv p5test` = `v1`,且 ENV 行有 `OK`。 - 重烧验证:只跑一遍 `sd_fusing.sh`(**不重做布局**)→ 上电 → 值仍在(ENV 区在镜像区外)。 - 为什么这样验:ENV 的两大风险——断电丢(没落盘)、重烧丢(落点被镜像覆盖)——两个用例各自覆盖。 判据:断电重上电后 `printenv p5test` = `v1`;重烧(只烧不重布局)后仍在。 ### 8.4 首启空白 ENV - 全新卡(或刚重做布局)的首次上电:ENV 区为空白 → `Env: Reading from MMC(0) ...` 后**没有 `OK`**——这是正常回落, 不是故障(坑⑩)。 - `saveenv` 之后,各次上电都会出现 `OK`。 - 重做布局 = 按新卡对待:ENV 区与数据分区一起回到空白状态。 判据:首启无 `OK` 不处理;`saveenv` 后复测出现 `OK` 与值保留。 ### 8.5 P8 边界解除(内核引导) - P8(内核引导)已落(batch-23):构建件与装载链 = §7.7;判据 J1–J5 与失败面 F1–F4 = `bringup-test.md §18`(实板执行与结论回填 = 该节)。 - 口径:**bootargs 单串两处同文**(DT `chosen/bootargs` / U-Boot env;内核面以引导器传入为准),字面 = §7.7 命令块; 引导命令面 = **手动 env**(`setenv bootargs …; saveenv` + 逐条装载命令)——U-Boot 侧仍 **defconfig 零改动**(不设 `CONFIG_BOOTCOMMAND`;P8 红线)。 - 为什么保持手动:auto-boot(`bootcmd` 固化)属边界外(`port-plan.md §22` 边界句);手动 = 判据单一、可复现。 判据:`grep -n 'BOOTCOMMAND' configs/smart210_defconfig` → 无命中(U-Boot 侧零改动;引导命令面在手动 env 与 §7.7 命令块)。 ## 第 9 章 故障排查 (读本章:出问题按症状自救。本章是全文唯一的完整坑表;正文现场提示只留操作指令,机制都指回这里。) ### 9.1 坑清单(11 条) | # | 症状 | 原因 | 对策 | 出处 | |---|---|---|---|---| | 1 | `sd_fusing.sh` 中止:分区起点 < 2 MiB(C3);绕过照用则 ENV 区或 B 槽被文件系统覆盖 | Windows 磁盘管理 GUI 默认分区起点 1 MiB(LBA 2048)= ENV 区起点 | `diskpart` 用 `offset=2048`(KB = 2 MiB)或 `parted` `mkpart … 2MiB 100%`;不用 GUI 建分区 | `port-plan.md §4.12.2/§4.12.3`(C3 负例 N4) | | 2 | `wsl --mount` 报 `0x8007000f` | `--mount` 不适用于 USB 读卡器类设备 | 改用 usbipd-win(`bind` / `attach --wsl`) | `bringup-test.md §2.2`(实测) | | 3 | usbipd `attach` 后 WSL 里没有 `/dev/sdX`(或 attach 报错) | Windows 已给卡挂卷,卷被占用 | `mountvol <盘符>: /p` 卸载卷后再 attach | `bringup-test.md §2.2` ① | | 4 | 布局/烧写进行中设备突然消失 | WSL 空闲关停会 detach 已接入的 USB 设备 | 保持 WSL 会话活跃(保活);重新 attach;布局 + 烧写一气呵成 | `bringup-test.md §2.2` ② | | 5 | 烧写后**首次**上电个别命令缺失(`Unknown command`:`md` / `crc32` / `printenv` / `ls`) | 根因未定论(设备级提交滞后 / 卡内状态与时序,两假设并列) | **先断电重上电再判读**——不得直接判为固件缺陷;脚本已带 W1–W3 提交与回读校验 | `port-plan.md §4.12.5`(复现 2/2;W1–W3 落地后 1/1 未复现) | | 6 | 烧写中止 `ABORT: … does not embed …`(BL1 交叉核对失败);若绕过则板子行为与源码不符 | bl1 与 spl 出自不同构建(头自洽 ≠ 版本一致) | 用当次 `u-boot-spl.bin` 重跑 `mkbl1.py` 打包;烧写前按 `bringup-test.md §7` 指纹表二次核对 | `port-plan.md §10`;`bringup-test.md §7` 纪律 3;`batch-01 §1.4` E8 | | 7 | 4K 逻辑扇区读卡器上回读校验不一致 / 脚本中止 | 脚本按 512 B 逻辑扇区口径建模(`skip=1` / `skip=49` 等),4Kn 设备口径不合 | 保持 fail-closed(中止即失败);换 512 B 逻辑扇区读卡器;不得以「重试」绕过 | `batch-03 §6.3`(决策)、`§5.9.2`(探针) | | 8 | `make smart210_defconfig` 警告 `symbol value '0x80000' invalid`,`.config` 中 `CONFIG_SYS_MONITOR_LEN=0` | Kconfig int 型符号不接受 `0x` 前缀 | defconfig 以十进制书写(`524288`) | `port-plan.md §4.4`(实跑证据);`batch-01 §2.8` | | 9 | 改了代码/配置但构建行为不变;或 WSL 树与工作区两侧不一致 | 双树工作流(Windows 工作区 ↔ WSL 构建树)未同步 | 构建前同步 + `diff`/md5 核对(或只维持一棵树) | `batch-01 §5.2/§5.3`、`batch-02 §5.3`(记录) | | 10 | 首次上电 `Env: Reading from MMC(0) ...` 后无 `OK` | ENV 区空白——全新卡首启的正常回落,非故障 | 不处理;`saveenv` 后各次上电均出现 `OK` | `bringup-test.md §4`(batch-06 注)、`§9`(T9) | | 11 | 完全无输出 / 输出乱码 | 线序电平(TXD0/RXD0/GND、3.3V)/ COM 口/驱动;或时钟与固定 UBRDIV 不配套(乱码);劣质卡 iROM 读不出 | 查接线与电平 → 换终端/线 → 确认 S2 拨在 `SDBOOT` 侧 → 换卡重烧;乱码先核时钟初始化 | `bringup-test.md §5.1`;`port-plan.md §4.3/§10` | ### 9.2 分阶段故障树 按启动链顺序二分定位(**一次只改一个变量**): 1. **完全无输出**:串口线序/电平/COM 口 → 换终端确认 → 换一张卡重烧(劣质卡 iROM 读不出是常见坑)→ 确认 S2 拨在 `SDBOOT` 侧、卡插在 SD 槽。 2. **有输出但无 `SPL: S5PV210 @ 800MHz, DDR2 512MiB`**:DRAM(DMC0)初始化未完成——对照 `port-plan.md §4.3` 参数表逐项核对颗粒手册。 3. **SPL 段出现但无主程序 banner**:SPL 搬运或跳转失败(`SPL: load failed (sector )` = 拷贝失败、明示扇区)。检查扇区 49 是否烧了 `u-boot.bin`(而不是 bl1)、卡容量是否 >1MiB+512 扇区;用 `dd if=/dev/sdX skip=49 count=2 | xxd` 看开头是否为合法 ARM 跳转向量(`ea0000…`)。 4. **有 banner 但很快死**:DM/DT 阶段问题,把 banner 后最后一行日志发出来定位。 5. **主程序 banner 后止步(信息区未出全)**:重定位目标越界。历史机制:1GiB 双控制器口径下 `ram_top=0x60000000` → relocaddr 落 0x40000000+ 无映射区,重定位写被静默丢弃(历史记录;512 MiB 修正后该现象消失)。 若仍止步:先核对 `NR_DRAM_BANKS=1`、`dram_init` 单 bank 与 `Board: Smart210 (512MiB DDR2)`(或 SPL 段第 2 行)显示是否就位。 ### 9.3 求助材料 收集三样再提问: 1. 串口日志(**最后可见行**,最好全段复制); 2. 产物指纹:四件的大小 / sha256(`bringup-test.md §7` 登记行)+ 主程序 banner 的时间戳; 3. 卡布局核对输出(§5.4 四项)——以及你跑过的命令与输出。 - 为什么:这三样把问题域砍到最小——镜像版本 / 卡状态 / 代码路径各占一面。 ## 第 10 章 附录 (读本章:核对、速查、维护。) ### 附录 A 改动文件与行数 (行数 = `wc -l` 现测;**新增 30 / 修改 29 / 删除 0**,共 59 件。口径 = 代码/工具/配置类(非文档类——`docs/**`、`README.md`、`minidfu-readme.md` 不计)。P5 面各文件的作用与就位核验见 §3.2 / §3.3。) **新增(30)**: `board/samsung/smart210/Kconfig`(22)· `board/samsung/smart210/MAINTAINERS`(6)· `board/samsung/smart210/Makefile`(11)· `board/samsung/smart210/smart210.c`(446)· `board/samsung/smart210/smart210_info.c`(118)· `board/samsung/smart210/lowlevel_init.S`(263)· `board/samsung/smart210/spl_sd.c`(221)· `board/samsung/smart210/lcd_bootinfo.c`(307)· `board/samsung/smart210/s702_backlight.c`(356)· `board/samsung/smart210/sd_fusing.sh`(312)· `board/samsung/smart210/sd-fusing-win.py`(346)· `board/samsung/smart210/sd-fusing-win-selftest.py`(184)· `board/samsung/smart210/no-buffer-diag.py`(109)· `board/samsung/smart210/fw-scripts.env`(3)· `board/samsung/smart210/dfu_core.py`(465)· `board/samsung/smart210/minidfu.py`(354)· `board/samsung/smart210/minidfu_gui.py`(481)· `board/samsung/smart210/minidfu_ops.py`(414)· `board/samsung/smart210/minidfu-selftest.py`(497)· `board/samsung/smart210/requirements.txt`(3)· `tools/mkbl1.py`(41)· `configs/smart210_defconfig`(74)· `arch/arm/dts/s5pc1xx-smart210.dts`(91)· `include/configs/smart210.h`(52)· `drivers/usb/host/ehci-s5p.c`(105)· `drivers/video/s5p_fimd.c`(396)· `board/samsung/smart210/tftp-gui.py`(360)· `board/samsung/smart210/tftp-gui-selftest.py`(127)· `board/samsung/smart210/payload-hello.S`(43)· `board/samsung/smart210/net-selftest.txt`(25) **修改(29)**: `arch/arm/mach-s5pc1xx/Kconfig`(31)· `arch/arm/mach-s5pc1xx/pinmux.c`(37)· `drivers/mmc/s5p_sdhci.c`(244)· `drivers/mmc/mmc.c`(3374)· `arch/arm/dts/Makefile`(1181)· `arch/arm/cpu/armv7/s5p-common/Makefile`(19)· `arch/arm/cpu/armv7/s5p-common/cpu_info.c`(58)· `scripts/Makefile.xpl`(632)· `common/version.c`(26)· `common/board_f.c`(1162)· `common/board_r.c`(855)· `common/board_info.c`(81)· `common/console.c`(1310)· `env/env.c`(404)· `env/mmc.c`(584)· `net/eth-uclass.c`(672)· `drivers/usb/common/dwc2_core.c`(133)· `drivers/usb/gadget/dwc2_udc_otg.c`(1236)· `drivers/usb/host/Kconfig`(476)· `drivers/usb/host/Makefile`(61)· `drivers/video/Kconfig`(1438)· `drivers/video/Makefile`(97)· `drivers/video/console_normal.c`(421;上游例外)· `drivers/video/vidconsole-uclass.c`(848;上游例外)· `fs/exfat/exfat.h`(265;上游例外)· `fs/exfat/time.c`(175;上游例外)· `fs/exfat/io.c`(1039;上游例外)· `fs/exfat/mount.c`(381;上游例外)· `fs/exfat/node.c`(1246;上游例外) (注:`fs/exfat/` 5 件 = **上游例外**(用户裁定)——2 件(`exfat.h` / `time.c`)登记与消解期 = `batch-13-usb-input-media.md §2.7`; 第 3 件 `fs/exfat/io.c` = **合并登记**(该文件改动处数 1 → 2):batch-14 第 1 处(`:415` 加宽;用户 2026-09-26 裁定;消解路径 = 上游提报 / 到期条件 = 上游合并或升级回收)= `batch-14-exfat-large-vol.md §2.3-⑤`; batch-16 第 2 处(`mode` 传导 / ENV 开关 `exfat_rw` / 写入口 4 处只读拒绝(A′3)/ `` + `#undef le32_to_cpu`(宏冲突消解 = 实施轮发现,1 行);用户 2026-09-26 裁定 = `batch-16-exfat-ro.md §4.1`;登记 / 消解路径 / 到期条件 = `batch-16-exfat-ro.md §2.8-K5`); 第 4 / 第 5 件 `fs/exfat/mount.c` / `fs/exfat/node.c` 为 batch-15 扩面(用户 2026-09-26 裁定;登记 / 消解路径 / 到期条件 = `batch-15-usb-align.md §2.8-K4`);其余上游面改动 = 0。 (batch-17(R9)上游例外 4 件 = `drivers/video/s5p_fimd.c`(新写驱动)+ `drivers/video/Kconfig` / `drivers/video/Makefile`(两登记面)+ `board/samsung/smart210/lcd_bootinfo.c`(板级件);登记 / 消解路径(上游提报 / 上游合并或升级回收)/ 到期条件(上游出现 `samsung,s5pv210-fimd` 匹配件)= `batch-17-lcd-display.md §2.9` / §2.12-K9。 扩展轮(1-wire 背光握手)**不新增例外件**:`drivers/video/s5p_fimd.c` = 例外件 1 的减行;板级例外件 4 扩为两件(`lcd_bootinfo.c` + `s702_backlight.c`);登记 = `batch-17-lcd-display.md §2.18.2`。 修正轮 2(USB 读盘回归定因闭环 + 显示门控退场)**不新增例外件**、并**回收例外件 5**:`drivers/usb/host/ehci-hcd.c` 还原至 HEAD 形态(`git diff` 面为空 ⇒ 撤出改动面);板级例外件 4 回落两件(`lcd_bootinfo.c` + `s702_backlight.c`;`usb_display_gate.c` 随退场删除)。 batch-18 修正轮(滚动失稳修复)**新增上游例外件 2 件** = `drivers/video/console_normal.c` + `drivers/video/vidconsole-uclass.c`(免整段 FB 读的滚动:屏面文本影子 + 唯写重绘 + 清屏经驱动路由;消解路径 = 上游提报 / 上游合并或升级回收;到期条件 = 上游采用等价机制或本仓升级回收)= `batch-18-lcd-vidconsole.md §2.19`。) ### 附录 B 产物指纹 当次构建(batch-18(R9-B)装配前移轮:P1/P2 两段装配 + 挂点前移——早段 `board_early_init_r()` 探测 + 白底填充 + 行 1–17 绘制(全部入屏外控制台帧、不可见)、晚段 `console_init_r()` 后行 18–23 续画 + 强制刷屏 + 换帧 + 背光 ⇒ 亮起即完整板块(T31 = AC16‴ 提案); 终态与上一轮同形:屏面板块 23 行 + 其后控制台追加 2 行(背光行 + `LCD:` 几何行); banner 时间戳 `Oct 01 2026 - 17:49:40 +0800`——已登记于 `bringup-test.md §7` 当次行)——烧前核对用: | 产物 | 大小(B) | sha256(当次构建) | |---|---|---| | `u-boot.bin` | 584936 | `1e285771205e41db114386e7bcfa70900d7629273b2e639f12e615a869aa2f07` | | `u-boot-spl.bin` | 7008 | `156e0e3c445b347c13555b4c94fb5a0506c81b01b633046046d3a1c95ac73332` | | `u-boot-bl1.bin` | 7024 | `c08d43345f29a523e48d91e0181f15644d67b65715c3d32b60be398f584d1e3a` | | `u-boot.dtb` | 3928 | `1df21367df3f5c29a92cc184062cf15da11362e7a6ad53571ca106a225e3594b` | - **你的构建哈希会不同**:`u-boot.bin` 内嵌构建时间戳(banner 里的 `(<日期> - <时间> <时区>)`)——每次重编哈希都变。 跨构建比对以「尺寸 + bl1↔spl 交叉核对 + `bringup-test.md §7` 当次登记行」为准。 - 烧前二次核对(人工):对照 `bringup-test.md §7` 的当次行;`sha256sum u-boot.bin u-boot-spl.bin u-boot-bl1.bin`。 ### 附录 C 命令速查 (从各章汇总,无新事实。) - **环境**(第 2 章):`wsl --install -d Ubuntu`;`sudo apt install gcc-arm-linux-gnueabihf bison flex libssl-dev u-boot-tools dosfstools python3`; 自检 = §2.6 清单(`wsl -l -v` / `arm-linux-gnueabihf-gcc --version` / `mkimage --version` / `python3 --version` / `mkfs.vfat --help` / `usbipd --version`)。 - **构建**(第 4 章):`make O=../build-smart210 smart210_defconfig CROSS_COMPILE=arm-linux-gnueabihf-`; `make -j6 O=../build-smart210 CROSS_COMPILE=arm-linux-gnueabihf-`; `python3 tools/mkbl1.py ../build-smart210/spl/u-boot-spl.bin ../build-smart210/u-boot-bl1.bin`。 - **卡布局**(第 5 章):路线 A = `diskpart` 流程(§5.2);路线 B = `parted` + `mkfs.vfat` 流程(§5.3); 核对 = §5.4 四项(`list partition` / `Get-Partition` / `parted unit s print` / `file -s`)。 - **烧写**(第 6 章):`usbipd list` → `usbipd bind --busid ` → `usbipd attach --wsl --busid `; `cd ~/ub210/u-boot/board/samsung/smart210 && ./sd_fusing.sh /dev/sdX ~/ub210/build-smart210/u-boot.bin ~/ub210/build-smart210/u-boot-bl1.bin`; 烧写路线 B(§6.6):`python sd-fusing-win.py --scan` / `python sd-fusing-win.py --target u-boot.bin u-boot-bl1.bin`(管理员)。 - **验收**(第 7 章):`mmc list`;`mmc dev 0`;`mmc info`;`md 0xd0037488 1`;`ls mmc 0:1`; `load mmc 0:1 ${loadaddr} TEST.TXT`;`crc32 ${loadaddr} ${filesize}`。 - **ENV**(第 8 章):`printenv`;`setenv <名> <值>`;`saveenv`。 - **网络**(P6-A,batch-05):`setenv ethaddr …`;`dhcp`;`ping `;`tftpboot 0x21000000 <文件>`;`crc32 0x21000000 ${filesize}`(联调步骤与用例 = `bringup-test.md §10`)。 - **网络应用**(P6 应用面;batch-21):`python tftp-gui.py`(主机 TFTP 服务;自检 = `tftp-gui-selftest.py`);`go 0x21000000`(网络载荷运行); `mkimage -T script -C none …` + `source 0x21000000`(脚本载荷测试,判据 `NETTEST PASS`);`run fwupdate` / `run fwcommit` / `run fwrollback`(网络升级 / 回滚)——三步与判据 = §7.6。 - **USB**(P7;batch-09/12/13):`usb start`;`usb reset`;`usb tree`;`usb info`;`ls usb 0:1`;`load usb 0:1 ${loadaddr} <文件>`; `fatload usb 0:1 …`(FAT 盘;exFAT 用 `load`);`crc32 ${loadaddr} ${filesize}`; 键盘接入 = `setenv stdin serial,usbkbd` + `saveenv`(插键盘后 `usb start`)——**顺序不可颠倒**(先 `setenv`/`saveenv`,再插键盘): 存量 ENV 卡无 `stdin` 时先枚举键盘 → `common/usb_kbd.c:630` `strstr(stdinname,…)` 无 NULL 防护(K6 上报项;`batch-13-usb-input-media.md §2.9`)。 - **非对齐 DMA 打印归零**(P7 补面;batch-15):exFAT 读路径族 4 处缓冲改走 `malloc_cache_aligned`(`fs/exfat/mount.c` / `fs/exfat/node.c`)⇒ 块层 DMA 目标缓冲 64 字节对齐,`usb reset` / `ls usb 0:1` 不再打 `CACHE: Misaligned operation`; `invalidate` 侧维护恢复执行(非对齐时被跳过——`arch/arm/cpu/armv7/cache_v7.c:44-55`;`flush` 侧不受影响);实板判据与用例 = `bringup-test.md §15`。 - **exFAT 大容量卷**(P7 补面;batch-14):`ls usb 0:1`;`load usb 0:1 ${loadaddr} <文件> [bytes [pos]]`(可选后两参 = 读窗口字节数 / 文件内起始偏移); `crc32 ${loadaddr} `(读闭环 = `crc32` 对主机侧 `zlib.crc32`;用例 = `bringup-test.md §14`)。 **32 位解析上界注句**:`bytes` / `pos` 经 `hextoul`(`ulong`,32 位;`lib/strto.c`,无溢出检测)解析 ⇒ 命令行起点上界 = 4 GiB−1(`0xFFFFFFFF`); > 4 GiB 的**文件偏移**不可表达——> 4 GiB 面以**跨 4 GiB 线切片**覆盖(起点 `0xFFFFF000` + 窗口 `0x100000`:尾部 1020 KiB ≥ 4 GiB)。 - **exFAT 只读语义**(P7 补面;batch-16):exFAT 默认**只读**挂载(挂载选项 `"ro"`)——`ls` / `load` 全程不写卷(卸载不写超级块、读路径不标 atime 脏); 放行写面 = `setenv exfat_rw 1`(非零即放行;未设 / `""` / 非数值 / `0` ⇒ 只读;每次命令重读、免重启);默认态 `save` / `rm` / `mkdir` / `mv` 四命令立即拒绝(`-EROFS`)。 `exfat_rw` 为普通 ENV ⇒ `saveenv` 后跨重启生效(**核验轮勿 `saveenv`**);写入面前置 = `setenv exfat_rw 1`(用例 = `bringup-test.md §14` / §16);判据 = `batch-16-exfat-ro.md §2`。 - **LCD 上屏**(batch-17 A 段;行序 = batch-18 甲形信息区轮现行口径):A 段不改 `stdout` ⇒ 上电屏面刷一屏**板块**(23 行:三色块(红/绿/蓝,最顶)→ 75 `*` 规则线 → banner art → 75 `*` 规则线(两线夹 logo)→ `FriendlyARM…` / 版本 / URL / `CPU:` / `Board:` / `Core:` / `Boot:` / `MMC:` / `Env:` / `Net:` / `In:` / `Out:` / `Err:`),其后控制台追加 2 行(背光行 + `LCD:` 几何行);串口面除背光行与 `LCD:` 两行外逐行不变; 寄存器抽检 = `md.l 0xf8000000 9`(VIDCON0/1 · VIDTCON0/1/2 · WINCON0 + 3 填充)· `md.l 0xf8000040 3`(VIDOSD0A/B/C)· `md.l 0xf80000a0 1` / `md.l 0xf80000d0 1` / `md.l 0xf8000100 1`(FB 起址 / 末址 / 行距)· `md.l 0xf8000034 1`(SHADOWCON)· `md.l 0xe0107008 1`(路由); 用例与期望值 = `bringup-test.md §17`。 - **LCD 实时日志**(batch-18(R9-B)段):板级三路 env 钉住(`smart210_console_setup()`,`console_init_r` 之前调用)⇒ `stdout` = `vidconsole,serial`(屏 + 串口双路)、`stderr` = `serial`、`stdin` = `serial,usbkbd`——**上电即生效、无需 `setenv` 前置**(`printenv stdout stderr` 复核); 早段行(banner / `Board:` / `Boot:` / `MMC:` / `Net:`)作为输出流 = **串口专有**(预控制台回放已退役——`PRE_CONSOLE_BUFFER` 三项移除);其内容由屏侧独立渲染进入板块(复现 / 捕获,非回放搬运);屏面 = 板块 23 行 + 控制台 2 行 → 其后日志与提示符 `Smart210 #`;用例与期望值 = `bringup-test.md §17`(T6 / T18–T25);判据 = `batch-18-lcd-vidconsole.md §2`。 - **LCD 滚动失稳修复**(batch-18 B 段修正轮;2026-09-30):旧滚动 = 行移搬运帧缓冲像素(对 FB 的整段「读」= 失稳元凶:屏面花屏 + 串口卡死)⇒ 修复 = **免整段 FB 读的滚动**:`console_normal.c` 维护屏面文本影子(4096 格 × 3 B)、滚动 = 影子行腾挪 + 唯写重绘(对 FB 只写);清屏(`cls` / `[2J`)经驱动逐行 `set_row` 路由(`vidconsole_clear_screen()`),防「影子与屏面失配」(清屏后旧文本重现); 实板判据 = 连续滚动 ≥60 行不花屏 / 不死机 / 末行完整 + 滚动后三色块保色 + `cls` 后无旧文本重现(用例 = `bringup-test.md §17` T26–T28);判据全文 = `batch-18-lcd-vidconsole.md §2.18 / §2.19`。 - **LCD 版面块**(batch-18 版面块重排轮 + 甲形信息区轮;2026-09-30;**装配前移轮 2026-10-01**):屏面板块 **23 行 = 色块行 → 星号线 → LOGO → 星号线 → `FriendlyARM…` / 版本 / URL / `CPU:` / `Board:` / `Core:` / `Boot:` / `MMC:` / `Env:` / `Net:` / `In:` / `Out:` / `Err:`**——色块行在最顶(两星号线之外)、两星号线夹住 logo; 信息行 = 串口同款行集,屏侧独立渲染(复现 12 行 + 捕获 1 行;`DRAM:` / `Storage:` 撤——串口无此二行); 控制台追加 2 行(背光行 + `LCD:` 几何行,屏面 `LCD:` 恰 2 条);**装配两段**(装配前移轮)= 早段(`board_early_init_r()`:探测 + 白底填充 + 行 1–17)→ 晚段(`console_init_r()` 后:行 18–23 续画)→ 强制刷屏 → **换帧**(`s5p_fimd_present_frame()`,帧边界原子)→ **背光** ⇒ 亮起即完整板块 (判据 = T31 / AC16‴ 提案;判据全文 = `batch-18-lcd-vidconsole.md §2.26`;前轮 = T31 修正(`NO_FB_CLEAR` + 绘制前白底回填 / §2.23)+ 绘制原子化(屏外起始帧 + VSYNC 原子换帧 / §2.24)); 早段日志回放退役(`configs/smart210_defconfig` 去 3 项:`PRE_CONSOLE_BUFFER` / `_SZ` / `_ADDR`); 实板判据 = 行序 / 无回放无重复 / `LCD:` ×2 / 亮起即完整画面(AC16‴ 提案)(用例 = `bringup-test.md §17` T29′ / T30′ / T32 / T31);判据全文 = `batch-18-lcd-vidconsole.md §2.21`(+ §2.20 / §2.26)。 - **USB 读盘回归修复**(batch-17 修正轮 2;2026-09-29):元凶 = FIMD 引脚复用步的 pad 驱动强度笔 `gpio_set_drv(gpio, S5P_GPIO_DRV_4X)`(写 4x 即复现、清 0 即恢复)⇒ 已整笔删除(`drivers/video/s5p_fimd.c`);「扫屏争用」假设与显示门控修法**作废**、门控件已退场(`ehci-hcd.c` 还原至 HEAD); 判读 = USB 操作期间屏面**保持点亮**;回归判据 = `usb reset` → `usb start` → `ls usb 0:1` = 零 `EHCI timed out on TD` + 5 file(s) / 10 dir(s)(用例 = `bringup-test.md §17` T17)。 - **背光握手**(batch-17 扩展轮):S702 背光不经 SoC GPIO/PWM——模组 STM8 经 `GPH1[2]` 1-wire(9600 bps)管理,U-Boot 启动时发 `0x7F` 使能; 串口新增一条(每次启动只出现其一):成功 = `LCD: backlight on (0x7F ok, type=…, … tries)`;失败 = `LCD: backlight handshake failed (…), screen dark`; 抽检 = `md.l 0xe02000a0 3`(`GPD0[1]` 已释放 = 输入 / 无上下拉)· `md.l 0xe2500000 2`(`TCFG0` / `TCFG1` 逐位不变——timer4 心跳)· `md.l 0xe2500008 1`(`TCON` bit16 = 0,timer3 已停机);用例 = `bringup-test.md §17` T5 / T14–T16。 - **内核引导**(P8):`setenv bootargs 'console=tty0 console=ttySAC0,115200n8 root=/dev/ram0 rw rdinit=/init'; saveenv`; `tftpboot 0x20008000 uImage-r2` → `tftpboot 0x28000000 s5pv210-smart210.dtb` → `bootm 0x20008000 - 0x28000000`(fatload 备路同址); 判据 J1–J5(到 `/ $ ` shell)与失败面 F1–F4 = §7.7 / `bringup-test.md §18`;**内核显示面**(batch-25:日志上屏 + `/ $ ` + 双 console)= §7.7 ④ / `port-plan.md §24` / `bringup-test.md §19`。 - **NAND**(batch-26 · 1A):`nand info`(识别:`NAND: 1024 MiB` / 页 2048+64 B / 擦除块 128 KiB / ecc 1 bit)· `nand read/write/erase`(测试区块 18 起;块 0 只读)· `nand bad`(坏块扫描)· `nand biterr `(ECC 注入:1 bit 纠正 / 2 bit 报错); 非页对齐 / 越界写 = 拒绝;判据与用例 = §7.8 / `bringup-test.md §20`;设计 = `port-plan.md §25`;**NAND 启动链(1B)= 待做**。 - **寄存器重放**(P8 墙② 判别面;batch-24):`md.l ` · `mw.l ` · `mw.b `(宽度后缀显式)——U-Boot 活参照上重放内核 UART 配方 / 取钟位(E1 命令块与判读 = `port-plan.md §23` / `bringup-test.md §18` T11)。 - **故障**(第 9 章):无命令——按症状查 §9.1 坑表 / §9.2 故障树。 ### 附录 D 来源映射 + P6–P8 更新落点 **D.1 来源映射**(每节事实 → 出处;来源清单 = `batch-04-port-tutorial.md §2.4`,共 54 行): | 教程落点 | 事实内容 | 来源(文件:节) | 状态 | |---|---|---|---| | §1.1 | 范围到 P5 止;本教程 = 复现面(设计论证另存 `port-plan.md`) | `batch-04-port-tutorial.md §1.1/§1.5/§1.6` | 判据 | | §1.2 | 物料:板(512MB DDR2、无 eMMC)/ SD 卡 ≥64MB / USB-TTL 3.3V / 读卡器 / PC / 板侧开关 S2(SDBOOT/NAND) | `port-plan.md §3`、`bringup-test.md §1`;板侧开关 = 用户实测(2026-09-14 复核反馈) | 判据+实测 | | §1.3 | 十步地图(步 ↔ 章 ↔ 产物) | `batch-04-port-tutorial.md §2.3` | 判据 | | §1.4 | 术语表覆盖全文首现术语 | `port-plan.md §2/§4` 各节 + 教程内定义 | 判据 | | §1.5 | 路径约定(工作区 / WSL 树 `~/ub210/u-boot` / 构建树 `~/ub210/build-smart210`) | `batch-01 §1.4.1`(环境注)、`batch-02 §5.3`(同步记录) | 记录 | | §2.1–§2.2 | WSL2:为什么 + 安装/使用要点(通用操作 = 通行做法;实测环境 Ubuntu 26.04);依赖包(gcc-arm-linux-gnueabihf 15.2 / mkimage 2025.10 / dosfstools / python3) | `port-plan.md §7/§10`、`§4.12.2`(dosfstools);通用操作 = 通行做法(无文档出处) | 判据+记录+通行做法 | | §2.3 | 源码进 WSL 做法(教程约定) | K2(`batch-04-port-tutorial.md §2.6`);同步工作流 `batch-01 §5.2/§5.3` | 约定+记录 | | §2.4 | 串口参数/接线(115200-8N1、UART0、3.3V、勿接 VCC)+ 终端软件 MobaXterm 与配置要点 | `bringup-test.md §1`、`port-plan.md §3` 行 1;MobaXterm = 用户实测(2026-09-14 复核反馈) | 实测 | | §2.5 | usbipd 安装包 + sha256 + 官方来源 | `refer/tools/usbipd-win_5.3.0_x64.msi`(sha256 `1c984914…6d938`;2026-09-14 复核一致) | 实测 | | §2.6 | 环境自检项 | `port-plan.md §7/§10` | 判据 | | §3.1 | 启动链总图(iROM → BL1(SPL) → U-Boot;介质/扇区/地址) | `port-plan.md §4.1` | 实测+判据 | | §3.2 | BL1 格式(16B 头 = 加载长度 + 32 位字节累加和;代码 ≤16368B) | `port-plan.md §3`(iROM 事实)、`tools/mkbl1.py` | 实读+实测 | | §3.2 | SPL 搬运(iROM `0xD0037F98` 通道 0、扇区 49、`0x34800000`、128 扇区/次 ×16 次) | `board/samsung/smart210/spl_sd.c`(`spl_s5pc1xx_load_image`)、`port-plan.md §4.1` | 实读+实测 | | §3.2 | 文件总表:新增 11 / 修改 16 / 删除 0 | `port-plan.md §5.1/§5.2/§5.3`、`§10`、`batch-03 §6.5`、`batch-06-boot-banner.md §2.11` | 实读 | | §3.3·卡 | 板级 7 件(Kconfig / MAINTAINERS / Makefile / smart210.c / lowlevel_init.S / spl_sd.c / sd_fusing.sh) | 对应文件实读;`port-plan.md §4.3/§4.6.1/§4.7/§4.12.3` | 实读 | | §3.3·卡 | 构建与配置 3 件(configs/smart210_defconfig / include/configs/smart210.h / tools/mkbl1.py) | 对应文件实读;`port-plan.md §4.4/§4.5` | 实读 | | §3.3·卡 | 设备树 2 件(arch/arm/dts/s5pc1xx-smart210.dts / arch/arm/dts/Makefile) | 对应文件实读;`port-plan.md §4.2/§4.6.1/§4.7/§4.8` | 实读+机检 | | §3.3·卡 | 平台 3 件(mach-s5pc1xx/Kconfig、pinmux.c、drivers/mmc/s5p_sdhci.c) | 对应文件实读;`port-plan.md §4.6.1` | 实读+机检 | | §3.3·卡 | SPL 接线 2 件(arch/arm/cpu/armv7/s5p-common/Makefile、scripts/Makefile.xpl) | 对应文件实读;`port-plan.md §5.2/§10` | 实读 | | §3.3·卡 | 版本 1 件(common/version.c;版本号单一定义 `SMART210_PORT_VERSION`) | `common/version.c`、`port-plan.md §4.11` | 实读+实测 | | §3.4 | 选型论证指针(不复制论证) | `port-plan.md §4.6/§4.11/§4.12.4` | 判据 | | §4.1 | 构建命令(`O=` 构建树)+ 零警告判据 | `bringup-test.md` 头注、`batch-03 §5.3/§5.4` | 实测+机检 | | §4.2 | BL1 打包命令与输出(`(code N, checksum 0x…)`) | `bringup-test.md` 头注、`tools/mkbl1.py` | 实测 | | §4.3 | 四件产物 + 量级 + bl1↔spl 交叉核对 | `bringup-test.md §7`(P5 行)、`batch-03 §6.6`、`sd_fusing.sh`(cross-check 段) | 实测+机检 | | §5.1 | 扇区级布局表(1 MiB / 16 KiB @ `0x100000` / 2 MiB = LBA 4096) | `port-plan.md §4.12.1` | 判据 | | §5.2 | 路线 A `diskpart` 逐行 + 每步安全性 + `offset=2048` KB 语义 + GUI 警告(坑①) | `port-plan.md §4.12.2`;执行记录 `batch-03 §4.4`、`bringup-test.md §4.4` | 实测+判据 | | §5.3 | 路线 B(`parted` + `mkfs.vfat`) | `port-plan.md §4.12.2` | 判据(未实测) | | §5.4 | 布局后四项核对(起点/类型/尾/文件系统) | `port-plan.md §4.12.2`(含 2026-09-13 修订:`list partition`/`Get-Partition`) | 实测+判据 | | §5.5 | 布局先于烧写(为什么) | `port-plan.md §4.12.2` | 判据 | | §6.1 | 烧写原理(扇区 1/49;脚本不写 MBR 与 ENV 区) | `sd_fusing.sh`(头注布局段) | 实读+判据 | | §6.2 | usbipd 接入三要点(`--mount` `0x8007000f` / `mountvol /p` / 保活 / error state) | `bringup-test.md §2.2` | 实测 | | §6.3 | 烧写命令 | `bringup-test.md §2.2`、`sd_fusing.sh`(用法段) | 实测 | | §6.4 | 写入前校验清单(BL1 头/交叉核对/1 MiB 窗口/C1–C4/整盘;C1/C2/C4 值取自 defconfig 单源、C3 阈 = `port-plan.md §4.12.3`(分区 1 起点 ≥ 2 MiB)) | `sd_fusing.sh`(校验段)、`port-plan.md §4.12.3` | 实读+机检 | | §6.4 | W1–W3 与「完成」语义(提交 + O_DIRECT 回读;`Commit ok:` + `Done.`) | `sd_fusing.sh`(W1–W3 段)、`port-plan.md §4.12.3` | 实读+机检 | | §6.4 | ABORT 处置(写入前 = 未写;写入后 = 可能已写 → 重跑) | `port-plan.md §4.12.3`(注) | 判据 | | §6.5 | 烧后等待/安全移除 + 首启判读纪律(先断电重上电) | `bringup-test.md §2.2/§3`、`port-plan.md §4.12.5` | 实测 | | §6.6 | 烧写路线 B = Windows 原生闪写器(`sd-fusing-win.py` 三件;C1–C4/W1–W3 同口径;实板实测走通) | 工具三件 + `batch-07 §2` | 实测+判据 | | §7.1 | 上电步骤(S2 拨 `SDBOOT`)+ 日志结构(SPL 直写 / DM 串口;`0x00` 毛刺) | `bringup-test.md §4`(说明段);S2 = 用户实测(2026-09-14 复核反馈) | 实测 | | §7.2 | 期望日志逐行对照(P5 终态) | `bringup-test.md §4`、`§4.4` | 实测 | | §7.3 | 按最后可见行定位 | `bringup-test.md §4`(定位表) | 实测+判据 | | §7.4 | 验收命令与输出(T1–T5) | `bringup-test.md §4.4/§9` | 实测 | | §7.5 | P5 通过判据(T1–T12 汇总) | `batch-03 §6.2`、`bringup-test.md §9` | 实测 | | §7.6 | 网络应用(P6 应用面:TFTP 服务器 / 网络升级 / 传输运行 / 网络测试) | `batch-21-port-p6-network.md §2.1`、`batch-05-net-fw.md §2`、`bringup-test.md §10` | 判据+实测 | | §7.7 | 内核引导(P8:mainline 6.18.51 DT + uImage + 内置 initramfs → shell) | `batch-23-port-p8-kernel.md §2.1`;墙② 定因/修 = `port-plan.md §23` + `batch-24-kernel-serial.md §2.1`;构建件指纹 = `bringup-test.md §7`;用例/判据 = `bringup-test.md §18`;设计节 = `port-plan.md §22` | 机检 + 实板全过(**J1–J5 到 shell**) | | §8.1 | ENV 落点(MMC / `0x100000` / `0x4000`;镜像区外) | `port-plan.md §4.6.3/§4.12.1` | 判据+实读 | | §8.2 | ENV 命令与输出面(`Writing to MMC(0)...`) | `port-plan.md §4.6.3`、`bringup-test.md §4.4` | 实测 | | §8.3 | 持久化(断电 ×3 + 重烧保留,不重布局) | `bringup-test.md §9`(T7–T9)、`§4.4` | 实测 | | §8.4 | 首启空白 ENV 无 `OK`(正常) | `bringup-test.md §4`(P5 注)、`§9`(T9) | 实测 | | §8.5 | P8 边界(`bootcmd`/`bootargs` 不展开;defconfig 未设 `CONFIG_BOOTCOMMAND`) | `port-plan.md §4.9/§4.10`;`configs/smart210_defconfig` 实读 | 实读 | | §9.1 | 坑清单 11 条 | `batch-04-port-tutorial.md §2.5`(逐条出处) | 实测/机检/记录 | | §9.2 | 分阶段故障树 | `bringup-test.md §4/§5` | 实测+判据 | | §10.A | 文件与行数(`wc -l` 现测) | O1(`batch-04-port-tutorial.md §2.6`);`batch-03 §6.5`(前值参考) | 机检 | | §10.B | 产物指纹(引用当次行) | `bringup-test.md §7` | 实测 | | §10.C | 命令速查 | 各章命令块(无新事实) | — | | §10.D | 来源映射 + P6–P8 更新落点 | `batch-04-port-tutorial.md §2.4`;`port-plan.md §6`(阶段表) | 判据 | | §10.E | 设计档指针索引 | `port-plan.md` / `bringup-test.md` / `baremetal-ref.md` / 批次档(batch-01/02/03) | 判据 | **D.2 后续更新落点**(P6–P8 完成或缺口项补登后,按下表更新本文——分段更新即可,其余节不动): | 事项 | 更新落点 | 动作 | |---|---|---| | P6 网络(SROMC + DM9000) | §7.2 `Net:` 行;附录 A / 附录 C;§7.6(应用面) | `Net:` 行形态更新 + 网络命令入速查——**已落(2026-09-17 文档轮)**;附录 A 行数重测与指纹重登——**已落(batch-13)**;**应用面四件套**(TFTP 服务器 / 网络升级 / 传输运行 / 网络测试)= §7.6 + 附录 C 应用行 + 附录 A 计数随动——**已落(batch-21)** | | P7 USB(dwc2 OTG host / gadget / EHCI 主机口) | 附录 A(新增 `ehci-s5p.c`);附录 B / 附录 C | 文件表与命令表增项——**已落(batch-13)**(附录 A 全量重测 / 附录 B 指纹刷新 / 附录 C 增 USB 行;键盘/介质收尾 = `batch-13-usb-input-media.md`) | | 需求池 R6(大容量 exFAT 面)(P7 补面:> 4 GiB exFAT 卷寻址) | 附录 A / 附录 B / 附录 C | 文件表与指纹刷新 + exFAT 行(`load … [bytes [pos]]` 用法与 32 位解析上界注句)——**已落(batch-14)**;判据与用例 = `batch-14-exfat-large-vol.md` / `bringup-test.md §14` | | 需求池 R7(USB 扫描面非对齐 DMA)(P7 补面:exFAT 读路径族缓冲非 64 字节对齐 ⇒ `CACHE: Misaligned operation` 打印 + `invalidate` 维护跳过) | 附录 A / 附录 B / 附录 C | 文件表与指纹刷新 + 非对齐 DMA 注行(4 处 `malloc` → `malloc_cache_aligned`)——**已落(batch-15)**;判据与用例 = `batch-15-usb-align.md` / `bringup-test.md §15` | | 需求池 R8(exFAT 只读语义)(P7 补面:exFAT 卸载写盘——只读访问亦触碰用户盘) | 附录 A / 附录 B / 附录 C | 文件表与指纹刷新 + 只读语义注行(默认只读 + `exfat_rw` 开关 + `saveenv` 持久化注)——**已落(batch-16)**;判据与用例 = `batch-16-exfat-ro.md` / `bringup-test.md §16` | | 需求池 R9(显示面)A 段(FIMD 驱动 + 静态启动屏) | 附录 A(新增 `s5p_fimd.c` / `lcd_bootinfo.c`;计数 47 → 51)/ 附录 B / 附录 C | 文件表(含 `drivers/video/Kconfig` / `Makefile` 两新登记面)与指纹刷新 + LCD 上屏注行(`md.l` 抽检组)——**已落(batch-17 A 段)**;判据与用例 = `batch-17-lcd-display.md` / `bringup-test.md §17`;B 段(vidconsole 实时日志)= 已落(batch-18) | | 需求池 R9(显示面)扩展轮(1-wire 背光握手) | 附录 A(新增 `s702_backlight.c`;计数 51 → 52)/ 附录 B / 附录 C | 文件表与指纹刷新 + 背光握手注行(`GPD0[1]` 释放 + timer 面抽检组)——**已落(batch-17 扩展轮)**;判据与用例 = `batch-17-lcd-display.md §2.18` / `bringup-test.md §17`(T5 / T14–T16) | | 需求池 R9(显示面)修正轮 2(USB 读盘回归:定因 = FIMD 引脚复用里的 `gpio_set_drv` 笔;显示门控退场) | 附录 A(`usb_display_gate.c` 删、`ehci-hcd.c` 撤出;计数 54 → **52**)/ 附录 B / 附录 C | 文件表与指纹刷新 + 修复注行(定因链 + 修复形态 + 屏面保持点亮)——**已落(batch-17 修正轮 2)**;判据 = `batch-17-lcd-display.md §2.20` / §2.21 / `bringup-test.md §17`(T17) | | 需求池 R9(显示面)B 段(vidconsole 实时日志:三路 env 钉住 + 预控制台回放) | 附录 A(四件行数刷新;计数 52 不变)/ 附录 B / 附录 C | 文件表行数与指纹刷新 + 实时日志注行(钉住口径 + 回放 + 无 `setenv` 前置)——**已落(batch-18)**;判据与用例 = `batch-18-lcd-vidconsole.md` / `bringup-test.md §17`(T6 / T18–T25) | | 需求池 R9(显示面)B 段修正轮(滚动失稳:旧滚动 = 对 FB 整段「读」⇒ 花屏 + 串口卡死;修复 = 免整段 FB 读的滚动) | 附录 A(两件行数 357 / 848;修改 27 → 29;计数 52 → 54)/ 附录 B / 附录 C | 文件表与指纹刷新 + 滚动修复注行(屏面文本影子 + 唯写重绘 + 清屏路由)——**已落(batch-18 B 段修正轮)**;判据与用例 = `batch-18-lcd-vidconsole.md §2.18 / §2.19` / `bringup-test.md §17`(T26–T28) | | 需求池 R9(显示面)版面块重排轮(行序重排 + `CPU:` 行;回放退役;首亮无闪) | 附录 A(`lcd_bootinfo.c` 145 → 164;`defconfig` 76 → 73;`console_normal.c` 357 → 421 回填)/ 附录 B / 附录 C | 行数 / 指纹刷新 + 版面块重排注行(行序 + `CPU:` 行 + 绘制→强刷→背光 + 回放退役)——**已落(batch-18)**;判据与用例 = `batch-18-lcd-vidconsole.md §2.20` / `bringup-test.md §17`(T29–T31) | | 需求池 R9(显示面)甲形信息区轮(屏面信息区 = 串口同款行集;新件 `smart210_info.c`) | 附录 A(新增 26;计 55;`lcd_bootinfo.c` 209;`smart210.c` 440;`smart210.h` 47;`board_r.c` 851)/ 附录 B / 附录 C | 文件表 / 指纹刷新 + 甲形注行(行序 23 行 + `LCD:` ×2)——**已落(batch-18)**;判据 = `batch-18-lcd-vidconsole.md §2.21` / `bringup-test.md §17`(T29′/T30′/T32) | | 需求池 R9(显示面)T31 修正轮(首亮空白白窗消除:`NO_FB_CLEAR` + 绘制前白底回填) | 附录 A(`defconfig` 73 → 74;`lcd_bootinfo.c` 209 → 217)/ 附录 B / 附录 C | 行数 / 指纹刷新 + T31 修正注行(AC16′ 口径②:SoC 参与后无中间可见态;首个 SoC 可控可见帧 = 完整板块)——**已落(batch-18 T31 修正轮)**;判据 = `batch-18-lcd-vidconsole.md §2.23` / `bringup-test.md §17`(T31 / AC16′) | | 需求池 R9(显示面)绘制 / 填充提速·原子化轮(屏外起始帧 + VSYNC 原子换帧) | 附录 A(`s5p_fimd.c` 345 → 396;`lcd_bootinfo.c` 217 → 227;`smart210.h` 47 → 50)/ 附录 B(附录 C 核而不改:无新命令) | 行数 / 指纹刷新 + 绘制原子化注行(双帧模型:A 控制台帧 / B 起始扫描帧;换帧 = SHADOWCON 保护窗;首亮 ≤1 帧)——**已落(batch-18 绘制原子化轮)**;判据 = `batch-18-lcd-vidconsole.md §2.24` / `bringup-test.md §17`(T31 / AC16″) | | 需求池 R9(显示面)装配前移轮(P1/P2 两段装配 + 挂点前移:早段挂 `board_early_init_r`、晚段挂 `console_init_r` 后 ⇒ 亮起即完整画面) | 附录 A(`lcd_bootinfo.c` 227 → 307;`smart210.c` 440 → 446;`board_r.c` 851 → 855;`smart210.h` 50 → 52)/ 附录 B / 附录 C | 行数 / 指纹刷新 + 装配前移注行(两段装配 + 挂点 + `board_late_init` 空心化;早段失败 ⇒ 晚段退化单段绘制)——**已落(batch-18 装配前移轮)**;判据 = `batch-18-lcd-vidconsole.md §2.26` / `bringup-test.md §17`(T31 / AC16‴ 提案) | | P8 内核引导(**DT 引导**:板级 DTS + uImage + **内置 initramfs**) | §7.7(新增);§8.5(边界解除);附录 C | 引导命令与判据(J1–J5 / F1–F4)补入 + 构建件入册(`bringup-test.md §7`)+ 用例(同档 §18)——**已落(batch-23)** | | NAND 段 1(batch-26 · 1A:S5PV210 NFC 驱动 + `nand` 命令族;启动链 = 1B) | §7.8(新增);附录 C | NAND 命令族与识别行补入 + 命令速查行 + 判据(`bringup-test.md §20`)——**已落(batch-26 1A)**;NAND 启动链(1B)= 未开工、随轮再落 | | K1 串口终端软件 | §2.4(软件与打开方式) | **已落定**(2026-09-14) | | K4 板侧开关/跳线细节 | §1.2 / §7.1 | **已落定**(2026-09-14) | | O5 `spl_sd.c` 陈旧注释处置(触发 = 下个触及该文件的批次) | §3.3 卡 6 的引用行 | 注释更新后同步引用 | | 卡布局路线 B 若被实测 | §5.3 的「未实测」标注 | 实测后升级为实测口径 | ### 附录 E 设计档指针索引 - `port-plan.md`(设计文档):§2 现状盘点 · §3 硬件参数 · §4.1 启动流程 · §4.3 DRAM 与时钟 · §4.4 defconfig 关键项 · §4.5 内存布局 · §4.6 MMC 与 ENV · §4.11 版本标识 · §4.12 卡布局与 ENV 落点 · §6 实施阶段 · §7 构建环境 · §10 实施状态。 - `bringup-test.md`(测试文档):§1 准备 · §2 布局与烧写 · §3 Windows 路线 · §4 期望日志与定位(§4.4 P5 实测)· §5 故障树 · §7 指纹登记 · §9 P5 用例表(T1–T12)。 - 批次档(实施记录):`batch-01-memory-512m.md`(内存模型更正)· `batch-02-banner-version.md`(版本标识)· `batch-03-mmc-env.md`(P5 实施与验收)· `batch-04-port-tutorial.md`(本文档批次)· `batch-05-net-fw.md`(网络基线 + 双槽安全固件升级)· `batch-06-boot-banner.md`(启动输出美化)· `batch-07-win-fusing.md`(Windows 原生闪写器入库 + 教程「路线 B」)。 - `baremetal-ref.md`(参考档):友善之臂裸机示例的硬件与初始化对照——外设矩阵、与本项目 20 项差异、 P6–P8 可借鉴点、13 条 `unverified`(含 DDR 引脚驱动强度缺项的登记与触发条件)。 - 深读建议:先 `port-plan.md §4.6/§4.12`(P5 两条主线机制),再 `bringup-test.md §9`(验收口径), 需要证据链时按附录 D 逐行回到对应批次档。