STM32F4 主板的真正线刷 Klipper 固件方法
前言
原创文章,转载引用请务必注明链接,水平有限,如有疏漏,欢迎交流指正。
我们约定:主板
指 MCU 部分,上位机
指运行 Klippy 的 MPU Linux 部分。
目前大多数基于 STM32F4 主控芯片的 3D 打印机主板,都是使用 SD 卡来更新固件,两个现状使得这一方法非常不方便:
- 主板固定在底部,盖板密封,机器又重
- Klipper 固件开发活跃,更新频繁,甚至会出现大版本更新必须升级固件的情况,想一个版本养老都难
那么有没有办法像基于 mega2560
芯片的主板那样直接线刷升级固件呢?方法总比困难多,官方提供了一种 伪线刷 的方法:SDCard updates ,原理是通过 Klipper 固件接管主板的 SD 卡插槽,将固件传送到主板 SD 卡内,然后重置主板,使其进入正常的固件过程,这需要满足以下条件:
- 只能用于升级,第一次还是要手动烧入 Klipper 固件
- 始终需要插一个 SD 卡在主板上
- 需要 SD 卡槽使用 SPI 协议
而 Fly Gemini 的 SD 卡槽使用 SDIO 协议,Klipper 无法操作,所以也就无法使用这种方法了。但是由于我最近调试该主板,需要经常重刷固件,所以频繁插拔 SD 卡,简直要了懒人的命了,有没有简单的方法么?也是有的,而且该方法通用常见的 STM32F4 主板。
注意:使用 HID-Bootloader 后,原来的 SD 卡刷方式会失效,建议保存原来的 Bootloader 后执行此操作。
请大家在此之前阅读官方文档 Bootlaoders 和我的文章 一、二、三,通读即可,了解下 3.3v serial 烧录。
精简版
0x01 烧录 HID-Bootloader
置高 BOOT0,置低 BOOT1,按下 Reset 键进入 3.3v serial 烧写模式,具体参考之前的 Fly-Gemini 硬件简明使用手册 。也可以使用 Windows 烧写。
# 下载我预编译的 hid-bootloader for Fly-Gemini
wget https://gitee.com/mx-force/STM32_HID_Bootloader/raw/master/bootloader/releases/hid_bootloader_gemini_pb2_wo_led.bin
# 可以使用以下命令确认已进入串口烧写模式
sudo stm32flash /dev/ttyUSB0
# 烧入 hid-bootloader
sudo stm32flash -w hid_bootloader_gemini_pb2_wo_led.bin -v -g 0 [/dev/ttyUSB0]
注意:
- 如果使用 USB-TTL 模块,则设备号为
/dev/ttyUSB0
- 如果使用前文介绍的板载 UART 自烧写,则设备号为
/dev/ttyS1
- 烧录成功后,boot0 置低,按下 reset 键正常运行。
0x02 首次烧录 Klipper 固件
注意使用该 BL 时,编译选项中 Bootloader offset
选择 HID Bootloader
,编译好 Klipper 固件待用。
8位拨码开关的 [3+4] 置于on(使 MPU 与 MCU 通过 USB 相连),置低 BOOT0,置高 BOOT1,按下 Reset 键进入 BL。
# hid-bootloader 使用 hidflash 工具进行操作,先编译之
sudo apt install libusb-1.0 pkg-config
cd ~/klipper/lib/hidflash
make
# 执行首次烧录操作,需要 sudo,否则报错 Segmentation fault
sudo ~/klipper/lib/hidflash/hid-flash ~/klipper/out/klipper.bin
至此首次烧录成功,boot1置低即可,reset 进入 klipper 固件。
0x03 日常升级固件过程
按上图配置编译好固件,此时主板内已经有旧版本的 Klipper,
整个流程和 mega2560
一样,不需要手动进入 bootloader 模式,会自动重置 MCU 并进入。也不需要插入 SD 卡,是不是很方便?
探索版
1、修改移植 HID-Bootloader 并启动失败
我们需要修改 HID-Bootloader 以适配 Fly-Gemini,我们观察其原理图,其中 BOOT1
连接在默认的 PB2
(同时该引脚定义为 X-EN
,即 X 电机的使能引脚,需要注意),然后没有板载 LED 指示灯,再加上 EXP 取消的那几个引脚,可知 Fly-Gemini 资源真的是紧张。
cd ~ && make projs && cd projs
git clone https://gitee.com/mx-force/STM32_HID_Bootloader && cd bootloader/F4/
主要修改定义文件 STM32_HID_Bootloader/bootloader/F4/Inc/mian.h
即可,根据实际情况,在相应位置添加如下内容:
#define BOOT_1_PIN GPIO_PIN_2 //Fly-Gemini, STM32F405RGT6 board (Button PB2, No LED)
#define BOOT_1_PORT GPIOB
#define BOOT_1_ENABLED GPIO_PIN_SET // 置高时手动进入 bootloader
保存并编译,bin 文件位于 biuld
目录内:
make clean && make
使用 3.3v serial 烧入主板,重置后:
系统错误?lib-usb版本错误?编译选项错误?接口连接方式错误(拨码、直连)?以上皆尝试无果,最后找到解决方法:
This build contains no code changes, however the binary is built using the gcc 6.3.1 toolchain. This seems to resolve issues some have with the bootloader not enumerating USB.
我目前的系统是 Armbian Buster,默认 gcc 版本为 gcc-8,需要使用 gcc-6 编译,包含在 Debian 9 stretch
中,不包括在 Debian 10 Buster
软件仓库中。
2、使用 gcc-6 重新编译 HID Bootloader
好在 Raspbian Buster 内置源包括 gcc6,直接安装即可,省去手动下载安装设置环境变量了。但是为了避免和系统已安装的 gcc8 冲突,我们需要使用 update-alternatives
命令来切换 gcc 版本。
# 查看软件仓库中是否包括 gcc6 以及查看当前仓库中 gcc 版本
apt show gcc
apt search gcc-6
# 查看系统已安装 gcc 版本
ls /usr/bin/gcc*
# 安装 gcc-6
sudo apt install gcc-6
# 修改 /usr/bin/gcc 软链接并设置不同版本优先级(60 > 40,数字随便设置)
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 60 --slave /usr/bin/g++ g++ /usr/bin/g++-8
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-6 40
# 切换 gcc 版本,直接回车使用默认,输入数字切换选择
sudo update-alternatives --config gcc
# 验证 gcc 版本
gcc -v
# gcc version 6.5.0 20181026 (Raspbian 6.5.0-1+rpi1+b1)
# 编译完成后,切换回 gcc8
# sudo update-alternatives --config gcc
如此这番,重新编译 BL,烧录后正常使用。Bootloader
模式下显示为 Generic serasidis.gr STM32 HID Bootloader
,普通运行模式下显示为 OpenMoko, Inc.
。
fly@Fly-Gemini:~$ lsusb # Bootloader
...
Bus 003 Device 002: ID 148f:7601 Ralink Technology, Corp. MT7601U Wireless Adapter
Bus 006 Device 003: ID 1209:beba Generic serasidis.gr STM32 HID Bootloader
...
fly@Fly-Gemini:~$ lsusb # Normal
...
Bus 003 Device 002: ID 148f:7601 Ralink Technology, Corp. MT7601U Wireless Adapter
Bus 006 Device 004: ID 1d50:614e OpenMoko, Inc.
参考文档:
3、hidflash 烧录权限问题
直接使用 ~/klipper/lib/hidflash/hid-flash ~/klipper/out/klipper.bin
会报错 Segmentation fault
,这并不是二进制文件格式错误,而是权限不足导致的,除了使用 sudo
之后,还可以添加 udev 规则:
sudo su
cat << _EOF_ > /etc/udev/rules.d/99-stm32_hid_bl.rules
# STM32_HID_bootloader
ATTRS{idProduct}=="beba", ATTRS{idVendor}=="1209", MODE:="666"
_EOF_
# 重启生效,【sudo udevadm control --reload-rules】我这里不管乎
reboot
不过一般使用 kiauh 助手就行了,会自动添加 sudo。