Skip to content

第三十周工作总结

概述

在完成设计文档与实现计划后,本周实现了 K3 RT24 rcpu1 极简固件的全部代码——从 CCU 时钟链、PXA-UART 驱动、pinmux 配置到 Chip/TimerChip trait 实现,以及独立的 K3 app crate 与构建脚本。同时完成了一次重要的 platform 层重构:用 Chip::board_init() 替代了对外暴露的 extern "C" _board_init 弱符号模式,使 chip 初始化成为标准 trait 方法。全部改动已通过编译+符号验证,合并入 main 分支。

20 个文件、+1580/-62 行,产物:k3-minimal bin——编译出 ELF(entry=0x100804000),经 objcopy 即可生成刷板固件。

1. chip-k3-rt24 完整实现

1.1 硬件初始化序列(7 步,main.c 已验证)

操作对应文件
1SPL 握手回写 write32(0xc088007c, 1) (如果不和spl握手,其会忙等一段时间)clock.rs
2上游 ruart_14 DDN gateclock.rs
3UART0 末端 gate + mux 选择clock.rs
4pinmux:GPIO_122/123 → MUX_MODE4clock.rs
5波特率/帧格式(8N1, 115200)uart.rs
6UUE 单元使能(PXA 专属,最易漏)uart.rs
7put_str 轮询 THRuart.rs

这 7 步在 clock::early_init() + uart::init() 中完成,经 _board_initChip::board_init() 链在用户 main 之前执行。

clock.rs 中的寄存器常量(ruart_14 gate num/den、uart0 mux/div)均与 ESOS 源码 ccu-spacemit-k3.c 逐项交叉验证。

2. Platform 层重构:Chip::board_init()

2.1 问题

初版设计用 link.x PROVIDE + #[no_mangle] extern "C" fn _board_init() 作为 chip 钩子机制:

  • arch crate 提供 _default_board_init(空),link.x PROVIDE(_board_init = _default_board_init)
  • chip crate 用强 _board_init 覆盖

这虽然可行,但 _board_init 是一个脱离 trait 体系的裸 extern "C" 函数——调用方(platform)和实现方(chip)之间没有 Rust 类型约束,也没有文档化的接口契约。

2.2 方案

Chip trait 中增加 board_init() 方法(带默认空实现),platform 通过 ChipImpl::board_init() 调用。chip crate 在 impl Chip for K3Rt24 中重写该方法即可。

优势

  • Rust trait 提供编译期类型检查,实现方不匹配即编译失败
  • 所有 chip 初始化统一走 Chip trait,新 chip crate 只需 impl Chip,无需理解 link.x 弱符号机制
  • 调用方代码 ChipImpl::board_init() 自文档化

3. 独立 K3 app crate 与构建链

3.1 架构隔离

新建 apps/rt-async-k3 crate,与 QEMU apps/rt-async-app 完全隔离:

  • 各自 memory.x(K3: 0x100804000,QEMU: 0x80200000
  • 各自 target triple(共用 riscv64imac-unknown-none-elf
  • K3 app bin 通过 #[used] static 引用 chip_k3_rt24::K3Rt24,确保 chip rlib 被链接器拉入

3.2 xtask 统一命名

xtask build 统一 bin 命名为 <platform>-<bin>(如 qemu-demok3-minimal),K3 构建产物为 ELF 而非 bin(objcopy 留给脚本,因需刷板前确认)。

4. 刷板验证(7/5 完成)

4.1 真板上成功启动

周五(7/5)成功将 k3-minimal 固件刷入 K3 实体板,R_UART0 输出启动日志:

I am alive! Hello from rt-async on K3 RT24!

:rcpu1 的固件加载由 SPL 通过 rproc_load/rproc_start 完成,esos.itbrcpu1-fw 节点的 load/entry 0x1_804000 是 RT24 SRAM 内的硬编码地址,不可改动。

5 刷写自动化工具链(scripts/flash/)

为缩短迭代周期,创建了一套完整的一键刷写自动化工具链,覆盖编译→打包→刷写的全流程:

scripts/flash/
├── k3-flash.sh                  # 主编排:一键编译+打包+刷写(7 步串联)
├── k3-pack-itb.sh               # itb 打包(自包含,不依赖 esos 仓库)
├── k3-console.py                # pyserial 串口交互(ensure-uboot / run / fastboot)
├── flash.conf                   # 串口配置(编辑一次即可)
├── esos_k3_com260_ifx.its       # 精简 ITS 模板(仅 com260_ifx 板型,5 节点)
├── payloads/                    # 固定 payload(入库)
│   ├── rt24_os0_rcpu.elf        #   rcpu0 esos 固件(固定复用)
│   ├── k3_rt240_com260_ifx.dtb  #   rcpu0 设备树
│   ├── k3_rt241_com260_ifx.dtb  #   rcpu1 设备树
│   └── null.spacemit            #   AP 交互 blob
└── README.md

k3-flash.sh 编排以下 7 步:

▶ build k3-minimal              # cargo xtask build k3-minimal
▶ pack esos.itb                 # cp ELF + lzo + mkimage(自包含)
▶ ensure board at U-Boot prompt # reset + 抓 autoboot 窗口 → =>
▶ enter fastboot                # 板端 fastboot usb 0,主机轮询 devices
▶ fastboot stage                # 主机 stage 传输 itb → Ctrl-C 退出 fastboot
▶ mtd erase / write             # 写 flash
▶ ensure-uboot                  # reset 停在 =>,新固件已就绪

一键运行./scripts/flash/k3-flash.sh

6 其他改动

  • README.md 更新:修正构建步骤顺序(子模块 → xtask setup → xtask build → rootfs → install → run),补充 Musl 工具链从 setup-musl 预编译包安装的说明
  • rt-async 子模块更新:同步平台重构(Chip::board_init() 替代弱符号)和相关文档

7. 本周在 K3 迁移中的位置

对应 项目计划-20260528 K3 适配第一阶段,与上周(二十九周)"下周计划"及本周补充工作对齐:

上周/本周计划项本周状态
定位 UART 输入乱码根因🟡 疑似硬件问题(CH340),待新硬件到货对照
实现 PXA-UART Chip::put_str + CCU 时钟使能✅ 完成(clock.rs + uart.rs,7 步初始化)
刷板验证:R_UART0 看到 rt-async 启动日志真板上成功输出!
刷写自动化工具链scripts/flash/ 一键刷写
替代路线调研(软复位/JTAG)✅ 两条路线均否决,选自动化 itb+mtd 路线

里程碑达成:从代码编译到真板运行的全链路已打通。

8. 下周计划

  1. 替换 StarryOS 为周雨同学版本:用 tgoskits 仓库中的 StarryOS 替换当前版本,适配 K3 真板
  2. AMP 双系统通信调试
    • 在真板上跑通 StarryOS(X100 大核)与 rt-async(RT24 小核)的共享内存 + IPI 通信
    • 移植现有 ov-channels / ov-rpc 到真板拓扑
  3. TimerChip 真实现:研究 rtimer0 寄存器映射,实现 set_alarm / enable_timer_irq,让调度器时钟跑起来
  4. 目标:RT24 上跑通完整的 rt-async 调度循环(定时器中断 → 任务切换)