编译与运行
这一页说明怎样编译 Zephyr 程序,并用三种方式把它放到 YuzukiNeko 上运行:
| 方式 | 程序放在哪 | 断电后 | 需要 | 适合 |
|---|---|---|---|---|
| 方式一:下载到 RAM 运行 | PSRAM | 丢失 | FEL + xfel | 开发调试,改一次跑一次 |
| 方式二:xfel 直接写 NOR | SPI NOR | 保留,上电自动运行 | NOR 里有加载器;每次进 FEL + xfel | 固定一个程序,不想装 UF2 下载器 |
| 方式三:UF2 拖放下载 | SPI NOR | 保留,上电自动运行 | NOR 里有加载器和 UF2 下载器;只需要 USB 线 | 日常下载的通用方式 |
三种方式用的是同一个 zephyr.bin,不需要分别编译。方式二和方式三都要先在 NOR 里装好加载器,见 NOR 启动的共同基础。
开始前请先完成 配置开发环境 和 获取 Zephyr 代码,并安装好 xfel(见 FEL 下载模式与工具)。
. ~/f101-zephyr/env.shcd ~/f101-zephyrwest build -b yuzukineko -d build/hello zephyr/samples/hello_world| 参数 | 含义 |
|---|---|
-b yuzukineko | 板级。评估板用 f101_evb |
-d build/hello | 构建目录,不同程序用不同目录,互不覆盖 |
zephyr/samples/hello_world | 要编译的应用,换成别的示例路径即可 |
产物在 build/hello/zephyr/ 下:
| 文件 | 说明 |
|---|---|
zephyr.bin | 裸二进制,下载到板子的就是它 |
zephyr.elf | 带符号的 ELF,调试和看内存布局用 |
镜像的链接地址和入口都是 0x40000000(PSRAM 的起点附近)。工具链是玄铁 900 的 newlib GCC,通过 ZEPHYR_TOOLCHAIN_VARIANT=cross-compile 接入,由 env.sh 设置。
重新编译同一个目录用 west build -d build/hello;换了板级或想从头来,加 -p always。
yuzukineko 的控制台是 UART1,PB00(TX)/ PB01(RX),115200 8N1。把 USB 转串口的 RX 接 PB00、TX 接 PB01,并共地,然后用任意串口终端打开,例如:
picocom -b 115200 /dev/ttyUSB0没有输出时,先判断是哪一环出了问题:接线和终端参数、程序有没有真正执行、还是 Zephyr 自身。一个有效的办法是先载入一个裸机小程序(链接在 0x40000000,轮询 UART 并写发送寄存器)证明这条路径是通的。
方式一:下载到 RAM 运行
Section titled “方式一:下载到 RAM 运行”主机通过 USB 把 zephyr.bin 写进 PSRAM 再跳转过去运行,不动 Flash。
-
让板子进入 FEL:按住 FEL 键,接上 USB 数据线,松开(详见 FEL 下载模式与工具)。
-
确认连接:
终端窗口 xfel version输出里应有
AWUSBFEX ID=0x00193700(F101)。 -
初始化内存、载入、运行:
终端窗口 xfel ddr f101-s3xfel write 0x40000000 build/hello/zephyr/zephyr.binxfel exec 0x40000000
此时控制台应开始输出。hello_world 会打印 Hello World! yuzukineko/sun252i_f101。
| 命令 | 作用 |
|---|---|
xfel ddr f101-s3 | 初始化 PSRAM。这个辅助程序同时配好 UART 时钟和引脚复用,缺了它控制台没有输出 |
xfel write 0x40000000 … | 把镜像写到链接地址 |
xfel exec 0x40000000 | 跳到入口开始运行 |
要点:
- 每次下载都要重新上电进入 FEL。
exec之后 CPU 已离开 BROM,FEL 不再可用。 - 这条路径跳过了 boot0 和 u-boot,SoC 早期初始化(CPU CSR、控制台时钟)由 Zephyr 自己负责。
exec之后不要再用xfel read32、hexdump查看状态,USB 链路已断。要查状态只能在exec之前。exec之后看到usb bulk send/recv error,说明 CPU 已经在跑你的代码,属正常现象,但不代表 Zephyr 本身运行正常,以控制台输出为准。
NOR 启动的共同基础
Section titled “NOR 启动的共同基础”方式二和方式三都把程序写进板载的 16 MiB SPI NOR,由 Flash 里的加载器在上电时取出来运行。这一节说明它是怎么工作的,以及怎样装加载器。
| 内容 | NOR 偏移 | 说明 |
|---|---|---|
| 加载器(三份) | 0x000000 / 0x010000 / 0x020000 | SyterKit flash-boot |
| 已保存的 Flash 采样点 | 0x02f000 | 加载器自己维护,不要覆盖 |
| UF2 下载器(系统程序) | 0x030000 | 头页 + 镜像,最大 0x1CF000 字节;只有方式三需要 |
| 应用(你的 Zephyr 程序) | 0x200000 | 头页 + 镜像,最大 0x9F0000 字节 |
上电后 BROM 把加载器读进 SRAM,加载器初始化 PSRAM 和 Flash 控制器,然后二选一:
- PD5 上的按键没有按住,且应用头页有效:把应用复制到 PSRAM 并运行。
- 否则:运行 UF2 下载器,板子在 USB 口上显示为盘
F101BOOT,等待拖入.uf2。
应用和方式一一样在 PSRAM 里运行,不是在 Flash 里就地执行,所以用的是同一个 zephyr.bin。每个程序前有一个 4 KiB 的头页,记录镜像载入的 PSRAM 地址(默认 0x40000000)和大小。头页由 mkuf2.py 自动加上,不需要手写。
mkuf2.py 在 zephyr-components 仓库里,是只依赖标准库的 Python 脚本,不用装额外的包。仓库的作用见 获取 zephyr-components;已经克隆过的,跳过下面的 git clone:
cd ~/f101-zephyrgit clone https://github.com/YuzukiHD/zephyr-components.git# 默认使用最新的 main。下面这行会固定到本文最初验证时的旧提交(2026-10-10),# 它早于 gbsp/ 和 nekobox/,除非确实需要那个版本,否则保持注释掉。# git -C zephyr-components checkout 282361ce5883bd65c228da584758e4796bf439e7mkdir -p outcd ~/f101-zephyrgit clone https://github.com/YuzukiHD/SyterKit.gitcd SyterKitgit checkout 6ef3f27abd547439cb2de4e455e40a2cbfbebff8export CROSS=$HOME/f101-zephyr/toolchains/Xuantie-900-gcc-elf-newlib-x86_64-V3.2.0/bin/riscv64-unknown-elf-make O=../out/syterkit CROSS_COMPILE=$CROSS yuzukineko_rv32_sram_defconfigmake O=../out/syterkit CROSS_COMPILE=$CROSS olddefconfigmake -j8 O=../out/syterkit CROSS_COMPILE=$CROSS flash-bootcd ..产物是 out/syterkit/build/yuzukineko/app_sram/flash-boot/flash-boot_spi.bin(32 KiB)。
进入 FEL,先备份整片 Flash,再把加载器写三份:
xfel versionxfel spinor read 0x0 0x1000000 neko-backup.bin
L=out/syterkit/build/yuzukineko/app_sram/flash-boot/flash-boot_spi.binxfel spinor write 0x000000 $Lxfel spinor write 0x010000 $Lxfel spinor write 0x020000 $Lxfel spinor write 会自动擦除需要的扇区。写 Flash 不需要执行 xfel ddr。
接着按你用的方式继续:方式二写入应用,方式三写入 UF2 下载器。
生成带头页的镜像
Section titled “生成带头页的镜像”mkuf2.py 把 zephyr.bin 加上头页。--raw 输出 Flash 原始镜像,供 xfel spinor write 用;不加 --raw 输出 .uf2 文件。
python3 zephyr-components/uf2-downloader/tools/mkuf2.py app build/hello/zephyr/zephyr.bin --raw -o out/app.img输出类似 out/app.img: 2096208 bytes at 0x200000。镜像大于应用区(0x9F0000 字节)时脚本会报错退出。默认载入地址是 0x40000000,和 Zephyr 的链接地址一致;镜像链接在别处时用 --load 指定。
方式二:xfel 直接写 NOR
Section titled “方式二:xfel 直接写 NOR”不装 UF2 下载器,每次都用 xfel 把应用写到 NOR 的 0x200000。适合只想固定跑一个程序的场景。
前提:已按上面的 NOR 启动的共同基础 把加载器写进 NOR。
1. 生成应用镜像
python3 zephyr-components/uf2-downloader/tools/mkuf2.py app build/hello/zephyr/zephyr.bin --raw -o out/app.img2. 进入 FEL 并写入
按住 FEL 键上电,然后:
xfel versionxfel spinor write 0x200000 out/app.imgxfel reset3. 观察控制台
加载器会先打印自己的日志,再运行你的程序:
PSRAM: … MiB initializedSPI NOR: flash id 0x…, … KiBSPI NOR: image 0x00201000 -> 0x40000000 (… KiB)starting at 0x40000000 (id 0)之后每次改代码:重新编译 → mkuf2.py app … --raw → 按住 FEL 键上电 → xfel spinor write 0x200000 → xfel reset。
方式三:UF2 拖放下载
Section titled “方式三:UF2 拖放下载”这是通用的日常下载方式。xfel 只在最开始用一次,把 UF2 下载器装进 NOR;以后把应用做成 .uf2 文件,拖进板子显示的 USB 盘即可,不再需要 FEL 和 xfel。
第一步:安装 UF2 下载器(只做一次)
Section titled “第一步:安装 UF2 下载器(只做一次)”前提:已按 NOR 启动的共同基础 把加载器写进 NOR。
1. 编译 UF2 下载器并加头页
west build -b yuzukineko -d build/uf2 zephyr-components/uf2-downloaderpython3 zephyr-components/uf2-downloader/tools/mkuf2.py system build/uf2/zephyr/zephyr.bin --raw -o out/sys.img2. 进入 FEL 并写入
按住 FEL 键上电,然后:
xfel versionxfel spinor write 0x030000 out/sys.imgxfel reset这里不写应用。Flash 里没有有效应用时,加载器会直接运行下载器。
3. 确认 UF2 盘出现
复位后,用 USB 数据线连接电脑,板子应显示为 USB 盘 F101BOOT。看到这个盘,安装就完成了。
第二步:用 UF2 下载应用(日常流程)
Section titled “第二步:用 UF2 下载应用(日常流程)”把 zephyr.bin 做成 .uf2:
python3 zephyr-components/uf2-downloader/tools/mkuf2.py app build/hello/zephyr/zephyr.bin -o out/app.uf2输出类似 out/app.uf2: 2096208 bytes at 0x200000, 8189 UF2 blocks。.uf2 文件大小约是 zephyr.bin 的两倍,因为每个块只携带 256 字节数据。
然后:
- 让板子进入 UF2 下载器:按住 PD5 上的按键,再上电(或复位)。Flash 里没有有效应用时不用按键,自动进入。
- 板子显示为
F101BOOT盘。 - 把
out/app.uf2拷进这个盘。 - 拷完后板子自动重启,加载器运行新的应用,控制台开始输出。
之后每次改代码:重新编译 → mkuf2.py app … → 按住按键上电 → 拷贝。
三种 uf2 文件
Section titled “三种 uf2 文件”| 文件类型 | 命令 | 写入位置 | 能写的范围 |
|---|---|---|---|
| 应用 | mkuf2.py app zephyr.bin -o x.uf2 | 0x200000 | 只能写应用区 |
| 下载器本身 | mkuf2.py system zephyr.bin -o x.uf2 | 0x030000 | 任意位置 |
| 加载器 | mkuf2.py loader flash-boot_spi.bin -o x.uf2 | 0x000000 | 任意位置 |
更多关于 UF2 的细节见 UF2 拖放烧录。
方式一:exec 后控制台没有输出:先确认控制台接线和参数,确认 xfel ddr f101-s3 已经执行。仍然没有,用前面「控制台」一节说的裸机小程序区分问题在哪一环。
mkuf2.py 报 … bytes, the limit is 10420224:应用超过了 0x9F0000 字节的应用区。减小程序,或去掉不需要的功能。
没有出现 F101BOOT 盘:确认用的是带数据线的 USB-C 线,接在下载口上;确认已按住 PD5 的按键再上电。仍然没有,说明加载器或下载器没装好,按住 FEL 键上电,重新写入。
拷贝或写入后板子重启,但没有输出:先用方式一把同一个 zephyr.bin 载入内存运行,看程序本身是否正常,再排查 NOR 里的镜像。
板子上电什么都没有:加载器被覆盖或写坏。按住 FEL 键上电,重新写加载器,或者用备份恢复:xfel spinor write 0x0 neko-backup.bin。