
Katapult 源码导读从 bootentry 到 sched 任务循环看懂 ARM Bootloader 启动全流程【免费下载链接】katapultConfigurable bootloader for Klipper项目地址: https://gitcode.com/gh_mirrors/ka/katapultKatapult前身为 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 中的ResetHandlerstage_one关中断、用内联汇编显式设置栈指针因为此时 C 环境尚未就绪stage_tworeset_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/PLL125MHz 主频 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.hcompile 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、LEDDECL_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.mdFlash 写入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 —— 复位、建栈、清 bss100 行内对应芯片main.c如 rp2040/main.c—— 时钟与向量表sched.c ctr.h —— 调度与注册机制bootentry.c —— 三条件判断 双击 RESETcommand.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),仅供参考