pATAq 发表于 2024-2-20 00:21:30

跟思兼学Klipper(28):无接触线刷Klipper固件:千秋万载,一统江湖

### 跟着思兼学习Klipper(28):无接触线刷Klipper固件:千秋万载,一统江湖之Katapult
## 前言

原创文章,转载引用请务必注明链接,水平有限,如有疏漏,欢迎交流指正。

文章如有更新请访问 (https://mc.dfrobot.com.cn/thread-318010-1-1.html?fromuid=725344)及 (https://www.cnblogs.com/sjqlwy/p/Katapult.html),前者内容较全,后者排版及阅读体验更佳。

看过我学习 Klipper 系列文章的,都知道我一直在寻找 ~~油腻的师姐在哪里~~ 一个满意的 Bootloader,期望其有如下特点:

* 占用空间小,避免需要裁剪 Klipper 功能
* 支持无接触线刷,不需要拆开电气舱手动将设备进入烧录模式,全部在上位机上完成。
* 支持多种微控制器芯片
* 简单易用,最好有配置界面而不是修改源码来设置
* 支持多种线刷模式:CanBUS、USB、Serial 等

本文介绍 Katapult(formerly known as Canboot)这一引导程序 (Bootloader),它可以极大方便我们烧录、升级主板 Klipper 固件。既往 Canboot 主要用于 Can 工具板的固件升级,现在也支持 USB 和 Serial 通讯方式的主板升级了。

**我们约定:**上位机指运行 Linux 的 MPU 部分,也称为 host。下位机又称 MCU、控制板。

**名词解释:**

* Bootloader:最主要的作用就是方便咱烧录升级固件,毕竟不是谁家都有串口和 SWD 调试模块的

* 卡刷:传统的使用 编译好的固件拷贝到 SD 卡,插入主板升级固件

* 线刷:使用上位机完成固件烧录,无需 SD 卡,进需要数据线连接即可

* 无接触线刷:使用上位机完成固件编译、烧录、升级,无需打开电气舱,**<u>无需接触打印机主板</u>**

**软硬件环境:**

* RK3399 上位机,Ubuntu 22.04.3 jammy
* MKS Monster8 v1,使用 USB (PA11/PA12) 通讯
* Gokit2 机智云 2 代,使用 UART (PA9/PA10) 通讯

**本文涉及的内容:**

1. 不同 Bootloader 及主板升级方式的对比
2. Katapult 的介绍与使用
3. 使用 RaspberryPi DebugProbe (Pico) + OpenOCD 通过 SWD 接口烧录主板固件
4. 使运行 Klipper 固件的主板进入 Bootloader 模式

## 1、现状

### 1.1 不同的 BootLoader

由于接触 Klipper 固件相对比较早,接触了很多 Marlin 时代设计的主板,以现在常见的 STM32 主控芯片为例,烧录升级主板固件的方法有如下:

1. SD 卡升级 | 基本都支持,将编译好的主板固件拷贝到 SD 卡中,插入主板插槽上电等待烧录、更新完成

2. (https://www.klipper3d.org/SDCard_Updates.html) | 伪线刷,在主板上保留 SD 卡不取出,实现线刷功能

3. 3.3v serial | 主板进入 ISP 烧录模式后,通过 UART 烧录固件

4. USB DFU | STM32F4 等主板进入烧录模式后可以通过 USB 接口烧录固件

5. stm32duino bootloader|8KiB STM32F103,为 F103 芯片带来 DFU USB 烧录功能,dfu-util

6. HID bootloader | 无需驱动, 2KiB 0n STM32F10x,16 KB on STM32F4xx,hid-flash

7. MSC bootloader | STM32F103/STM32F072 | 8KiB or 16KiB ,无需驱动,dfu-util

8. CanBoot/Kataplut bootloader | STM32F103/STM32F0x2

9. mks bootloader | 48KB

10. chitu bootloader | 专有,需要后处理

> 注意 STM32F4 系列引导至少 16KB,H7 系列至少 128KB

### 1.2 常见主板固件更新方式

这两部分我不想赘述,凑合看吧。

1. STM32F103
   1. USB:线刷需要使用第三方引导
   2. UART:使用一个额外的引脚,将主板重置进入烧录模式
   3. 特立独行的 MKS,我们的老熟人又来了,特指之前的 MKS Robin Nano 系列,通讯接口不是 PA9/PA10,无法串口烧录固件,只能卡刷或者伪线刷
2. STM32F4、F0x2、H7
   1. USB DFU
   2. 3.3v serial
   3. Can 工具板,Katapult

## 2、Katapult 介绍与使用

项目主页:https://github.com/Arksine/katapult ,查了下英文意思是弹射器,具体咱也不清楚。

很久之前就听过 Canboot,感觉有点绕就一直没仔细研究,后来发现改名了,并且额外支持 USB 和 UART 模式了,不禁让我想起了之前的 MKS Robin 系列主板。看看它的特点:

- 针对 ARM Cortex-M 系列主控芯片的引导程序
- 支持 CANBUS, USB 以及 UART 通讯接口
- 目前支持 lpc176x, stm32 以及 rp2040 系列主控芯片. CAN 方式目前仅支持 stm32 F 系列和使用 rp2040 芯片的设备。

### 2.1 编译使用 Katapult

和 Klipper 的编译方式很相似,我们编译出 katapult BootLoader,然后使用编程器或者 3.3v serial/USB DFU 等方式 **<u>覆盖原来的引导</u>**(如果有)。

```shell
cd ~
git clone https://github.com/Arksine/katapult
cd ~/katapult
make menuconfig
make
```

![](https://gcore.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/202112151215586.png)

注:上图 USB DFU 模式应该和 3.3v serial 一起。

#### 编译选项介绍:

!(https://s2.loli.net/2024/02/19/v7bRuJhFAL6WSBP.png)

- `Microcontroller Architecture`: 选择主控芯片架构:lpc176x, stm32 and rp2040

- `Processor model`: 选择具体的型号

- `Build Katapult deployment application`: 默认不要改动,无编程器环境下使用原 BootLoader 安装 Katapult

- `Disable SWD at startup`: 兆易创新的 GigaDevice STM32F103 克隆版芯片使用,由于未测试,不保证能用

- `Clock Reference`: 选择正确的晶振

- `Communication interface`: 通讯接口和引脚选择,包括 CAN, USB, 和 UART 等。

- CAN 接口:
    - `CAN bus speed`: 选择合适的 CAN 总线速率
- Serial (USART) 接口:
    - `Baud rate for serial port`: 选择合适的波特率,默认 `250000`。注意,由于 UART 通讯没有 CLK 时钟,所以波特率要保证一致。
- USB 接口:
    - `USB ids`: 可以自定义 USB Vendor ID, Product ID, 建议保持默认。`Serial Number` 可以设置为好记的名字比如 `katapult` ,要求和 klipper 固件的名称不同,代表进入 BootLoader.

- `Application start offset`: Katapult 占用空间大小,注意 **<u>后面编译 Klipper 固件 时和此处保持一致</u>**。

- `Support bootloader entry on rapid double click of reset button`: 启用时,**<u>运行 Klipper 状态下</u>**快速按两下 `reset` 按钮 (500ms内) 可以进入 BootLoader,初始没有烧录固件时也会进入 BootLoader。

- `Enable bootloader entry on button (or gpio) state`: 启用时,使用自定义 GPIO 引脚进入 BootLoader。
- `Button GPIO Pin`: 设置 GPIO 引脚

- `Enable Status Led`: 启用时,指定 LED 显示状态,进入 BootLoader 时指定 LED 灯慢闪。**<u>建议 UART 和 CANBus 模式启用</u>**,因为无法像 USB 那样看到 Katapult 名称确认进入 BootLoader。
- `Status LED GPIO Pin`: LED 状态灯引脚,如 `PC13`,部分需要反转 low 时亮灯,此时填写 `!PC13`.

#### 烧录 Katapult 覆盖原引导

由于我们要安装 Katapult,来覆盖掉原来的bl,所以起始地址为 `0x08000000` 。不同烧录方式如下:

```shell
# 3.3v serial | PA9-TX, PA10-RX
sudo stm32flash -w /home/pi/katapult/out/katapult.bin -v -g 0 /dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0

# USB DFU
sudo dfu-util -a 0 -d 0483:df11 --dfuse-address 0x08000000 -D /home/pi/katapult/out/katapult.bin
```

### 2.2 烧录 Klipper 固件

使用 klipper 或者 kiauh-Advanced-Build Only 编译主板固件,注意选择正确的晶振和 BootLoader offset。

#### 2.2.1 USB 及物理 UART 设备

进入 Katapult BootLoader 后(方法见上)

```shell
~/klippy-env/bin/python flashtool.py -d 串口设备地址 -b 波特率 -f 固件地址
```

注意:

1. 串口设备地址必填
2. 波特率默认 `250000`,需要和编译 Katapult 时保持一致
3. 固件地址默认 `klipper.bin` ,可以指定其他地址或其他固件

#### 2.2.3 CAN 设备

这里可以参考 (https://mellow.klipper.cn/#/advanced/canboot) ,不再赘述。首次烧录还是需要 USB DFU 等方法。

```shell
# 查询 CAN 节点 UUID
~/klippy-env/bin/python ~/katapult/scripts/flashtool.py -i can0 -q

# 烧录 Klipper 固件
~/klippy-env/bin/python ~/katapult/scripts/flashtool.py -i can0 -f ~/klipper/out/klipper.bin -u <uuid>
```

## 3、【番外】使用原主板 BootLoader 烧录 Katapult

这种方式实际就是编译生成一个程序 deployer.bin,原来的引导启动 deployer,之后它会覆盖原来的引导。所以要求编译时它的Bootloader Offset 和原来的引导相一致,才能被启动。第二处 offset 则代表 deployer(kataplut) 覆盖原来的引导后所占用的空间,这个和之后编译 klipper 的 offset 一致,有点绕,对照最初的图就好理解了。

建议首先使用 SWD 编程器/串口模块/ DFU 等方式烧录 Katapult,如果没有的话,再考虑使用原来的 BootLoader 运行 Katapult 并覆盖原有的引导,这种方式要保证编译选项正确,否则无法启动。这种方式就是上面说的 `Build Kata`

`pult deployment application`,建议有条件先备份原引导,或者看看官方有无备份(当然没有其实对于老手来说也没关系)。

!(https://s2.loli.net/2024/02/19/VhvYRyE5GtAnl7j.png)

这种可以用 SD 卡、HID-BootLoader、或者旧版本 Katapult 进行升级。

```shell
# 使用旧版 Katapult 升级,使用上面生成的 deployer.bin,启动后覆盖原引导
~/klippy-env/bin/python ~/katapult/scripts/flashtool.py -d /dev/serial/by-id/usb-katapult_stm32f407xx_katapult-if00 -f ~/katapult/out/deployer.bin
```

## 4、从 Klipper 进入 Katapult

参看 Klipper 官方文档:(https://www.klipper3d.org/Bootloader_Entry.html)

安装 Kataput 后,目前为止仍然需要手动按 `reset` 键两次进入 Katapult BootLoader 才能烧录固件,如果想要实现**<u>无需额外按键升级 Klipper</u>** (上面所说的无接触线刷),可以发送命令让主板上的 Klipper 程序进入 Katapult BootLoader 状态。分述如下:

### 4.1 USB:

```shell
cd ~/klipper/scripts
~/klippy-env/bin/python -c 'import flash_usb as u; u.enter_bootloader("/dev/serial/by-id/usb-Klipper_stm32f407xx_mks-monster8-if00")'
# 如果成功会返回:Entering bootloader on <DEVICE>
# 注意 /dev/serial/by-id/usb-Klipper_stm32f407xx_mks-monster8-if00 改成你的串口设备号
```

### 4.2 Serial:

以下部分为官方文档,实际有问题,原因是我们编译的固件采用 `250000` 波特率,stty 不支持此非标准波特率,所以需要进行修改。

```shell
# 注意第一行不适用我们的场景
stty 115200 < /dev/serial/by-id/usb-Klipper_stm32f407xx_mks-monster8-if00
echo $'~ \x1c Request Serial Bootloader!! ~' >> /dev/serial/by-id/usb-Klipper_stm32f407xx_mks-monster8-if00
```

#### 设置非标准波特率

创建 mysetbaud.py,来源:https://unix.stackexchange.com/questions/327188/how-to-monitor-a-serial-connection-250000-baud

```python
#!/usr/bin/python
# set nonstandard baudrate. http://unix.stackexchange.com/a/327366/119298
import sys,array,fcntl

# from /usr/lib/python2.7/site-packages/serial/serialposix.py
# /usr/include/asm-generic/termbits.h for struct termios2
#c_cflag c_ispeed c_ospeed
def set_special_baudrate(fd, baudrate):
    TCGETS2 = 0x802C542A
    TCSETS2 = 0x402C542B
    BOTHER = 0o010000
    CBAUD = 0o010017
    buf = array.array('i', * 64) # is 44 really
    fcntl.ioctl(fd, TCGETS2, buf)
    buf &= ~CBAUD
    buf |= BOTHER
    buf = buf = baudrate
    assert(fcntl.ioctl(fd, TCSETS2, buf)==0)
    fcntl.ioctl(fd, TCGETS2, buf)
    if buf!=baudrate or buf!=baudrate:
      print("failed. speed is %d %d" % (buf,buf))
      sys.exit(1)

set_special_baudrate(0, int(sys.argv))
```

#### 最终脚本

```shell
# 设置串口波特率 250000
python3 ./mysetbaud.py <> /dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 250000
# 重启下位机进入 Katapult
echo $'~ \x1c Request Serial Bootloader!! ~' >> /dev/serial/by-id/usb-Klipper_stm32f407xx_mks-monster8-if00
```

### 4.3 CAN:

```shell
# 使 CAN 板从运行 Klipper 状态进入 Katapult
~/klippy-env/bin/python ~/katapult/scripts/flashtool.py -i can0 -u <uuid> -r
```

## 5、实战 MKS Robin Nano(UART)

之前的 Robin 主板送人了,Gokit2 为例。

```shell
# make serialflash FLASH_DEVICE=/dev/serial/by-id/usb-Klipper_stm32f407xx_swd-if00

# 编译 deploy.bin
# 使用 SD 卡烧录,注意改名才会被原 Bootloader 识别
# 按reset2进入Katapult,烧录Klipper固件
```

## 6、使用树莓派 Debug Probe + OpenOCD 烧录固件

![图片2.png](https://ws.dfrobot.com.cn/Fu61IIGajIx3EZ-QI3cm_cwQ74Ew)

之所以要这样,原因在于我的 MKS Monster8 v1 主板早期被我刷了 HID-Bootloader 方便线刷,现在进不去 HID,同时 DFU 和 3.3v serial (PA9/PA10) 也没有反应,只能靠 SWD 接口烧录固件。此种方式最少只需要三根线:SWD、SWC、GND。

| PA13 | SW_DIO |
| ---- | ------ |
| PA14 | SW_CLK |

过去会用 STM32Z7 开发板板载的 ST-Link,巧在前段时间买了树莓派的 Debug Probe 套件,支持 CMSIS-DAP 和 OpenOCD,想看看可否为其烧录引导和 Klipper 固件。

之前总以为 RP2040 是个玩具不稳定,但是随着代码越来越完善,PIO 的优势就体现出来了,可以做逻辑分析仪、示波器、JTAG调试器啥的。这里的树莓派 Debug Probe 一体化 USB 调试套件买来还没正常用过。

项目主页:(https://github.com/raspberrypi/debugprobe) ,注意有两个固件分支: debugprobe 和 picoprobe,前者适配 DebugProbe 套件,后者使用树莓派 Pico,两者引脚不一样。DProbe 支持 SWD 和 UART 调试功能,使用 CMSIS-DAP 标准,支持 OpenOCD + GDB 调试。

```shell
# 安装 OpenOCD 和 GDB,注意 OpenOCD 0.11.0 或 0.12.0 才支持 Debug Probe
sudo apt install openocd gdb-multiarch

# 基本命令
openocd -f <接口配置文件> -f <目标芯片配置文件>

# 烧录 BootLoader,起始地址 0x08000000
sudo openocd -f interface/cmsis-dap.cfg -f target/stm32f4x.cfg -c init -c halt -c "flash write_image erase /home/pi/katapult/out/katapult.bin 0x08000000" -c reset -c shutdown

# 烧录 Klipper 固件,起始地址和编译 Katapult 时一致,这里以 16KB 为例
sudo openocd -f interface/cmsis-dap.cfg -f target/stm32f4x.cfg -c init -c halt -c "flash write_image erase /home/pi/klipper/out/klipper.bin 0x08004000" -c reset -c shutdown
```

注意:

1. interface 代表调试器,我们这里选择 `cmsis-dap`
2. target 代表目标开发板,此处为 monster8 主板,采用 stm32f407 主控芯片,选择 `stm32f4x`
3. 更多支持的调试器和开发板可以从以下目录中找到(find 命令搜索得知):
   * /usr/share/openocd/scripts/interface/
   * /usr/share/openocd/scripts/target/

4. 更多信息可以查看 (https://cloud.tencent.com/developer/article/1840792) 以及 OpenOCD 官方文档
页: [1]
查看完整版本: 跟思兼学Klipper(28):无接触线刷Klipper固件:千秋万载,一统江湖