simfish:

Klipper Firmware

This workflow contains configuration settings, software dependencies, and application notes for building and flashing Klipper firmware on Ender3 V3 SE 3D printer.

cover image

Introduction

The Klipper firmware is designed to run on resource constrained consumer grade 3D printers. The firmware is capable of splitting its workload between the system board and an external hardware.

The local workload consists of running real-time low-level stepper-motor commands and managing sensor data.

The external hardware is expected to handle computationally intensive tasks. Motion planning, kinematics calculations, and other resource hogging tasks are offloaded by the firmware to the external device. Communication between the external device and the Klipper firmware is carried out via USB,UART, or CAN protocols.

Klipper's client-server like firmware architecture opens up possibilities for implementing advanced 3D printing features and squeezing performance out of consumer grade printers. It should be noted, however, the performance gain is still bounded by the printer hardware capabilities.

Requirements

The software and hardware requirements are,

  • A Linux machine running GNU/Guix, git, and LitDoc is expected.
  • A copy of distroconfig project with its root directory added to LITDOC_PATH environment variable.
  • A 3D printer(Ender 3 V3 SE)
  • 4GB - 8GB SD card for flashing the firmware

Installation

First, grab a copy of the Klipper firmware source code,

git clone https://github.com/klipper3d/klipper.git

Switch to the source directory,

cd klipper

And build the firmware by running this workflow(document),

guix ld klipper-firmware

If all goes well, the Klipper firmware should be available under klipper/out directory.

./out
  |_ klipper.bin
  |_ klipper.elf
  |_ ...

klipper.bin is the binary file, which contains a memory mapped image of the firmware.

To flash the klipper.bin file to an SD card, first the card needs to be formatted using FAT32 file format. In general, it is recommended to use a 4GB - 8GB SD card with 32KB cluster size. This can be done using a graphical tool such as gparted or a shell command.

sudo mkfs.fat /dev/[DEVICE NAME] -s 64 -F 32

The device name, [DEVICE NAME], can be identified using lsblk command first without inserting the SD card and after to resolve its name.

Once the device is formatted, copy the klipper.bin file to the SD card.

cp ./out/klipper.bin   /media/[DEVICE-NAME]

To flash the Ender 3 V3 SE board, first turn off the printer and insert the SD card. Leave the printer on for approximately 30 seconds until the firmware is installed. After the wait, turn off the printer again and remove the SD card before powering it back up. If the firmware is successfully installed, on the next power up a blank blue screen should be visible instead of the stock Marlin firmware UI.

Build Instruction

This section details the build instruction used by this workflow.

First clone the Klipper repository as specified in the installation section. Then run the build using litdoc as shown below,

guix ld klipper-firmware

The build command spawns a GNU/Guix container environment, configures the Klipper source for cross-compilation, and finally builds the firmware binaries.

The part that instruct LitDoc to spawn a container is specified using a LitDoc container.opt source block A container.opt is a LitDoc source block, which is used for passing command-line arguments to guix package and guix shell commands.

--container

We also add --emulate-fhs and --writable-root options to the block to enable emulation of a standard Linux file-system structure with write permission. This will ensure build tools that depend on these features behave as expected.

--emulate-fhs
--writable-root

Software packages required by the build process are specified using a manifest block. For the Ender3 V3 SE the required manifest specification is,

(use-modules (guix packages)
             (guix profiles)
             (gnu packages commencement)
             (gnu packages embedded) ;; arm-none-eabi-toolchain
             (gnu packages cross-toolchain) ;; gcc-cross-avr-toolchain
             (gnu packages base)  ;; binutils coreutils make
             (gnu packages version-control) ;; git
             (gnu packages bash) ;; bash
             (gnu packages python));; python-2.7 python-3.10

(packages->manifest (list
        binutils
        coreutils
        gnu-make
        bash
        git
        gcc-toolchain
        gcc-cross-avr-toolchain
        (make-arm-none-eabi-toolchain-7-2018-q2-update)
        (make-newlib-nano-arm-none-eabi-7-2018-q2-update)
        python-2.7
        python-3.10))

To prepare the source code for cross-compilation run

make menuconfig

This is an interactive configmenu based script. The script is used to generate printer board specific hardware configuration settings. For the Ender3 V3 SE printer the configuration menu collects the following parameters,

Configuration Key Configuration Value
Micro-controller Architecture STMicroelectronics STM32
Processor Model STM32F103
Bootloader Offset 28KiB
Communication Interface Serial (on USART1 PA10/PA09)

The collected information is used to generate a firmware build configuration file shown below,

CONFIG_LOW_LEVEL_OPTIONS=y
# CONFIG_MACH_AVR is not set
# CONFIG_MACH_ATSAM is not set
# CONFIG_MACH_ATSAMD is not set
# CONFIG_MACH_LPC176X is not set
CONFIG_MACH_STM32=y
# CONFIG_MACH_HC32F460 is not set
# CONFIG_MACH_RPXXXX is not set
# CONFIG_MACH_PRU is not set
# CONFIG_MACH_AR100 is not set
# CONFIG_MACH_LINUX is not set
# CONFIG_MACH_SIMU is not set
CONFIG_BOARD_DIRECTORY="stm32"
CONFIG_MCU="stm32f103xe"
CONFIG_CLOCK_FREQ=72000000
CONFIG_SERIAL=y
CONFIG_FLASH_SIZE=0x10000
CONFIG_FLASH_BOOT_ADDRESS=0x8000000
CONFIG_RAM_START=0x20000000
CONFIG_RAM_SIZE=0x5000
CONFIG_STACK_SIZE=512
CONFIG_FLASH_APPLICATION_ADDRESS=0x8007000
CONFIG_STM32_SELECT=y
CONFIG_MACH_STM32F103=y
# CONFIG_MACH_STM32F207 is not set
# CONFIG_MACH_STM32F401 is not set
# CONFIG_MACH_STM32F405 is not set
# CONFIG_MACH_STM32F407 is not set
# CONFIG_MACH_STM32F429 is not set
# CONFIG_MACH_STM32F446 is not set
# CONFIG_MACH_STM32F765 is not set
# CONFIG_MACH_STM32F031 is not set
# CONFIG_MACH_STM32F042 is not set
# CONFIG_MACH_STM32F070 is not set
# CONFIG_MACH_STM32F072 is not set
# CONFIG_MACH_STM32G070 is not set
# CONFIG_MACH_STM32G071 is not set
# CONFIG_MACH_STM32G0B0 is not set
# CONFIG_MACH_STM32G0B1 is not set
# CONFIG_MACH_STM32G431 is not set
# CONFIG_MACH_STM32G474 is not set
# CONFIG_MACH_STM32H723 is not set
# CONFIG_MACH_STM32H743 is not set
# CONFIG_MACH_STM32H750 is not set
# CONFIG_MACH_STM32L412 is not set
# CONFIG_MACH_N32G452 is not set
# CONFIG_MACH_N32G455 is not set
# CONFIG_MACH_STM32F103x6 is not set
CONFIG_MACH_STM32F1=y
CONFIG_HAVE_STM32_USBFS=y
CONFIG_HAVE_STM32_CANBUS=y
# CONFIG_STM32F103GD_DISABLE_SWD is not set
CONFIG_STM32_DFU_ROM_ADDRESS=0
# CONFIG_STM32_FLASH_START_2000 is not set
# CONFIG_STM32_FLASH_START_5000 is not set
CONFIG_STM32_FLASH_START_7000=y
# CONFIG_STM32_FLASH_START_8000 is not set
# CONFIG_STM32_FLASH_START_8800 is not set
# CONFIG_STM32_FLASH_START_9000 is not set
# CONFIG_STM32_FLASH_START_10000 is not set
# CONFIG_STM32_FLASH_START_800 is not set
# CONFIG_STM32_FLASH_START_1000 is not set
# CONFIG_STM32_FLASH_START_4000 is not set
# CONFIG_STM32_FLASH_START_0000 is not set
CONFIG_STM32_CLOCK_REF_8M=y
# CONFIG_STM32_CLOCK_REF_12M is not set
# CONFIG_STM32_CLOCK_REF_16M is not set
# CONFIG_STM32_CLOCK_REF_20M is not set
# CONFIG_STM32_CLOCK_REF_24M is not set
# CONFIG_STM32_CLOCK_REF_25M is not set
# CONFIG_STM32_CLOCK_REF_INTERNAL is not set
CONFIG_CLOCK_REF_FREQ=8000000
CONFIG_STM32F0_TRIM=16
# CONFIG_STM32_USB_PA11_PA12 is not set
CONFIG_STM32_SERIAL_USART1=y
# CONFIG_STM32_SERIAL_USART1_ALT_PB7_PB6 is not set
# CONFIG_STM32_SERIAL_USART2 is not set
# CONFIG_STM32_SERIAL_USART2_ALT_PD6_PD5 is not set
# CONFIG_STM32_SERIAL_USART3 is not set
# CONFIG_STM32_SERIAL_USART3_ALT_PD9_PD8 is not set
# CONFIG_STM32_CANBUS_PA11_PA12 is not set
# CONFIG_STM32_CANBUS_PA11_PB9 is not set
# CONFIG_STM32_MMENU_CANBUS_PB8_PB9 is not set
# CONFIG_STM32_MMENU_CANBUS_PD0_PD1 is not set
CONFIG_SERIAL_BAUD=250000
CONFIG_USB_VENDOR_ID=0x1d50
CONFIG_USB_DEVICE_ID=0x614e
CONFIG_USB_SERIAL_NUMBER="12345"
CONFIG_WANT_ADC=y
CONFIG_WANT_SPI=y
CONFIG_WANT_SOFTWARE_SPI=y
CONFIG_WANT_I2C=y
CONFIG_WANT_SOFTWARE_I2C=y
CONFIG_WANT_HARD_PWM=y
CONFIG_WANT_BUTTONS=y
CONFIG_WANT_TMCUART=y
CONFIG_WANT_NEOPIXEL=y
CONFIG_WANT_PULSE_COUNTER=y
CONFIG_WANT_ST7920=y
CONFIG_WANT_HD44780=y
CONFIG_WANT_ADXL345=y
CONFIG_WANT_LIS2DW=y
CONFIG_WANT_MPU9250=y
CONFIG_WANT_ICM20948=y
CONFIG_WANT_THERMOCOUPLE=y
CONFIG_WANT_HX71X=y
CONFIG_WANT_ADS1220=y
CONFIG_WANT_LDC1612=y
CONFIG_WANT_SENSOR_ANGLE=y
CONFIG_NEED_SENSOR_BULK=y
CONFIG_CANBUS_FREQUENCY=1000000
CONFIG_INLINE_STEPPER_HACK=y
CONFIG_HAVE_STEPPER_OPTIMIZED_BOTH_EDGE=y
CONFIG_WANT_STEPPER_OPTIMIZED_BOTH_EDGE=y
CONFIG_INITIAL_PINS=""
CONFIG_HAVE_GPIO=y
CONFIG_HAVE_GPIO_ADC=y
CONFIG_HAVE_GPIO_SPI=y
CONFIG_HAVE_GPIO_I2C=y
CONFIG_HAVE_GPIO_HARD_PWM=y
CONFIG_HAVE_STRICT_TIMING=y
CONFIG_HAVE_CHIPID=y
CONFIG_HAVE_BOOTLOADER_REQUEST=y

Notice, the generated configuration is independent of the hardware/software the build is running on. The configuration can be reused for subsequent builds. This is especially useful when generating build configurations non-interactively. Therefore, save the build configuration for future reference to a file. For example, ${LITDOC_CACHE_DIR}/klipper-firmware/etc/e3v3se.config

To reuse the configuration make sure the file can be accessed within the build container. This is done by adding to container.opt block a file --expose option.

--expose=${LITDOC_CACHEDIR}/klipper-firmware/etc/e3v3se.config=/opt/klipper-firmware/config/e3v3se.config

Any subsequent build that does not introduce a hardware change can now be configured using,

#!/usr/bin/env sh

make clean
make distclean
cp "/opt/klipper-firmware/config/e3v3se.config"  .config
make olddefconfig

Once the source code is configured for cross-compilation the firmware can be built by running make.

make V=1

If all is good, the build should generate the Klipper firmware binary for the Ender3 V3 SE. A copy of the firmware binary file should be available under the output directory, ./out.

References