Katapult 源码导读:从 bootentry 到 sched 任务循环,看懂 ARM Bootloader 启动全流程
【免费下载链接】katapultConfigurable bootloader for Klipper项目地址: https://gitcode.com/gh_mirrors/ka/katapult
🎯Katapult(前身为 CanBoot)是一款为Klipper3D 打印机主板设计的可配置 ARM Bootloader(引导加载器),支持 CAN、USB、UART 三种通信接口,覆盖 STM32F0/F1/F4/G0/G4/H7、LPC176x、RP2040/RP2350 等主流 MCU。本文带你从 bootentry.c 到 sched.c 任务循环,用最小代码量看懂 ARM Bootloader 启动全流程。
一、为什么需要 Katapult?
在 3D 打印主控板(如 STM32、RP2040 小板)上刷 Klipper 固件,传统方式需要 ST-Link 等烧录器。Katapult 的做法是:把引导程序常驻在 Flash 起始位置,应用固件(Klipper)放在其后的偏移地址。当需要升级时,电脑端通过 CAN/USB/UART 直接向板子写入新固件——无需任何硬件烧录器。
💡 快速上手:克隆代码后执行
make menuconfig选择芯片和接口,再make即可编译:git clone https://gitcode.com/gh_mirrors/ka/katapult cd katapult make menuconfig make
项目结构一览:
| 目录 | 作用 |
|---|---|
| src/generic/ | 与芯片无关的通用逻辑(命令、串口/CAN 协议栈) |
| src/stm32/ | STM32 各系列的芯片适配代码 |
| src/rp2040/ | RP2040/RP2350 芯片适配代码 |
| src/lpc176x/ | LPC176x 芯片适配代码 |
| lib/ | 芯片头文件库、构建工具(kconfig 等) |
| scripts/ | 构建与烧录脚本,核心是 flashtool.py |
二、启动第一步:ResetHandler 与平台初始化
MCU 上电后,硬件从 Flash 地址 0 取第一条指令。Katapult 位于 Flash 最前端,因此第一个跑起来的 C 函数就是 armcm_boot.c 中的ResetHandler:
- stage_one:关中断、用内联汇编显式设置栈指针(因为此时 C 环境尚未就绪);
- stage_two(
reset_handler_stage_two):清 NVIC 中断、复位中断优先级、把.data段从 Flash 拷贝到 RAM、清零.bss段; - 调用平台相关的
armcm_main(),完成后永远不返回。
以 RP2040 为例,main.c 中的armcm_main做了三件事:
void noinline armcm_main(void) { enable_ram_vectortable(); // 中断向量表搬进 RAM clock_setup(); // 配置 XOSC/PLL,125MHz 主频 sched_main(); // 进入调度主循环 }STM32 各系列(stm32f1.c、stm32f4.c、stm32h7.c 等)结构类似:向量表、时钟、外设复位各不同,但最终都汇聚到同一个入口——sched_main()。
三、核心决策点:bootentry_check 该跑谁?
sched_main在 sched.c 中,它是整个 Bootloader 的"总调度":
void sched_main(void) { timer_setup(); if (!bootentry_check()) // 关键判断:进 Bootloader 还是跳应用? application_jump(); // 有有效应用 → 直接跳转 Klipper ctr_run_initfuncs(); // 执行所有 DECL_INIT 注册函数 for (;;) ctr_run_taskfuncs(); // 死循环,周期性执行所有任务 }判断逻辑全部在 bootentry.c 的bootentry_check()中,满足任一条件就进入 Bootloader:
- 内存中有请求签名(
bootup_code == REQUEST_CANBOOT)——例如 Klipper 收到BOOT命令后通过 armcm_reset.c 写入签名再复位; - Flash 应用区为空或校验失败(
application_check_valid()为假)——所以首次烧录 Katapult 前建议整片擦除,它会自动进入引导模式; - 按钮被按住(配置了
Enable bootloader entry on button时)。
若以上都不满足,还会检查双击 RESET 键(500ms 内连按两次):check_double_reset()会先写入请求签名并延时,如果用户在窗口内再按一次 RESET,签名保留、复位后自然进入 Bootloader。
🔍 应用合法性校验、跳转地址(
application_jump)等实现在各芯片的 flash.c、bootentry 相关的 board/misc.h 中,canboot.h 里定义了魔数签名CANBOOT_SIGNATURE与请求码REQUEST_CANBOOT。
四、零配置注册机制:ctr.h 让模块自动"报到"
Katapult 没有中央init.c来挨个调用初始化函数,而是靠 ctr.h(compile time request,编译期请求)这套精巧机制:
- 模块只需写一行
DECL_INIT(func),宏会把函数名以字符串形式放进.compile_time_request链接段; - 构建时 buildcommands.py 从链接输出中提取这些字符串,自动生成调用代码
out/compile_time_request.c; - 最终
ctr_run_initfuncs()/ctr_run_taskfuncs()就是按序调用所有注册函数。
sched.h 定义了三种注册宏:
| 宏 | 执行时机 | 典型用途 |
|---|---|---|
DECL_INIT | 启动时一次性执行 | 初始化 CAN/USB/UART、LED |
DECL_TASK | 主循环中周期性执行 | 轮询串口、喂狗、状态灯闪烁 |
DECL_SHUTDOWN | 紧急停止时执行 | 安全停机清理 |
这就是为什么每个芯片目录都有同名serial.c、gpio.c:它们各自注册自己的任务,上层逻辑完全无需修改——典型的硬件抽象层(HAL)设计,与 Klipper 本体一脉相承。
五、主循环在忙什么?
进入for(;;) ctr_run_taskfuncs()后,各模块的任务函数依次轮询:
- 协议任务(canbus.c、usb_cdc.c、canserial.c):从接口收帧、拆包,交给 command.c 的
command_dispatch(); - 命令分发:
CMD_CONNECT(握手)、CMD_RX_BLOCK(接收固件块)、CMD_REQ_BLOCK(回读校验)、CMD_RX_EOF(结束)等,帧格式与 CRC16 校验细节见 protocol.md; - Flash 写入:flashcmd.c 配合各芯片 flash.c 完成擦除/写入,写完校验后由 Klipper 请求重启进入应用;
- 唤醒机制:中断里只做
sched_wake_task()置位一个字节,主循环用sched_check_wake()读清——极简的"中断只打标记,任务里干活"模式,避免在中断上下文中做重活。
六、进阶:Deployer 免烧录器升级 Bootloader 本身
Bootloader 坏了还能救吗?Katapult 提供了 deployer.c:通过现有引导程序把新版 Katapult 刷进自己的地址区间。在 menuconfig 中勾选Build Katapult deployment application,烧录生成的deployer.bin,设备重启即完成自举升级。
⚠️ 官方提醒:升级前务必确认新配置正确,并保留 ST-Link/DFU 等备用恢复手段,否则可能变砖。
七、源码导读路线总结
按以下顺序阅读,半天即可吃透核心流程:
- armcm_boot.c —— 复位、建栈、清 bss(100 行内)
- 对应芯片
main.c(如 rp2040/main.c)—— 时钟与向量表 - sched.c + ctr.h —— 调度与注册机制
- bootentry.c —— 三条件判断 + 双击 RESET
- command.c + protocol.md —— 通信协议
- flashcmd.c —— 刷写与校验
整个核心路径代码量极小、无 C 库初始化依赖,是学习裸机 ARM Bootloader 结构(向量表 → 时钟 → 启动判断 → 任务循环 → 协议栈)的绝佳教材。配合 test/configs/ 下现成的芯片配置文件(如 stm32f1.config),动手跑一遍make menuconfig && make,你就能真正"看懂 + 用会" Katapult 这套 ARM Bootloader 启动全流程了。🚀
【免费下载链接】katapultConfigurable bootloader for Klipper项目地址: https://gitcode.com/gh_mirrors/ka/katapult
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考