MCU Communication problem - Klipper infinite STARTUP loading

Basic Information: MCU communication problem

Printer Model: Yet to configure
MCU / Printerboard: BTT-SKR-mini-E3-V3
Host / SBC: ORANGEPI ZERO 2W
klippy.log

Hi, I’m new to the mcu/sbc/printer modding, just got my BTT SKR mini e3v3, paired with orangepi zero 2w, followed Stacking Layers “How to install Klipper for beginners” tutorial on YT, everything seems to work fine up to the point where klipper is trying to communicate with mcu - infinite startup loading.

Issue: Klipper reports: STARTUP stuck loading finfinitely,
(flashed mcu multiple times, sbc can see mcu, can see mcu in mainsail devices panel)

I am asking for help and advice as I dont understand klippy logs :folded_hands: :folded_hands:

Starting Klippy…
Args: [‘/home/jabcok/klipper/klippy/klippy.py’, ‘/home/jabcok/printer_data/config/printer.cfg’, ‘-I’, ‘/home/jabcok/printer_data/comms/klippy.serial’, ‘-l’, ‘/home/jabcok/printer_data/logs/klippy.log’, ‘-a’, ‘/home/jabcok/printer_data/comms/klippy.sock’]
Git version: ‘v0.13.0-369-g6a8b823a’
Branch: master
Remote: origin
Tracked URL: 

CPU: 4 core ?
Device: OrangePi Zero 2W
Linux: Linux version 6.12.43-current-sunxi64 (build@armbian) (aarch64-linux-gnu-gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0, GNU ld (GNU Binutils for Ubuntu) 2.42) #1 SMP Wed Aug 20 16:30:58 UTC 2025
Python: ‘3.11.2 (main, Apr 28 2025, 14:11:48) [GCC 12.2.0]’
Start printer at Sat Oct 18 22:30:48 2025 (1760826648.8 2260.2)
===== Config file =====
[virtual_sdcard]
path = ~/printer_data/gcodes
on_error_gcode = CANCEL_PRINT

[pause_resume]

[display_status]

[respond]

[gcode_macro CANCEL_PRINT]
description = Cancel the actual running print
rename_existing = CANCEL_PRINT_BASE
gcode =

{% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %}
{% set allow_park = client.park_at_cancel|default(false)|lower == 'true' %}
{% set retract = client.cancel_retract|default(5.0)|abs %}

{% set park_x = "" if (client.park_at_cancel_x|default(none) is none)
else "X=" ~ client.park_at_cancel_x %}
{% set park_y = "" if (client.park_at_cancel_y|default(none) is none)
else "Y=" ~ client.park_at_cancel_y %}
{% set custom_park = park_x|length > 0 or park_y|length > 0 %}


{% if printer['gcode_macro RESUME'].restore_idle_timeout > 0 %}
SET_IDLE_TIMEOUT TIMEOUT={printer['gcode_macro RESUME'].restore_idle_timeout}
{% endif %}
{% if (custom_park or not printer.pause_resume.is_paused) and allow_park %} _TOOLHEAD_PARK_PAUSE_CANCEL {park_x} {park_y} {% endif %}
_CLIENT_RETRACT LENGTH={retract}
TURN_OFF_HEATERS
M106 S0
{client.user_cancel_macro|default("")}
SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=idle_state VALUE=False

SET_PAUSE_NEXT_LAYER ENABLE=0
SET_PAUSE_AT_LAYER ENABLE=0 LAYER=0
CANCEL_PRINT_BASE

[gcode_macro PAUSE]
description = Pause the actual running print
rename_existing = PAUSE_BASE
gcode =

{% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %}
{% set idle_timeout = client.idle_timeout|default(0) %}
{% set temp = printer[printer.toolhead.extruder].target if printer.toolhead.extruder != '' else 0 %}
{% set restore = False if printer.toolhead.extruder == ''
else True  if params.RESTORE|default(1)|int == 1 else False %}

SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=last_extruder_temp VALUE="{{'restore': restore, 'temp': temp}}"

{% if idle_timeout > 0 %}
SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=restore_idle_timeout VALUE={printer.configfile.settings.idle_timeout.timeout}
SET_IDLE_TIMEOUT TIMEOUT={idle_timeout}
{% endif %}
PAUSE_BASE
{client.user_pause_macro|default("")}
_TOOLHEAD_PARK_PAUSE_CANCEL {rawparams}

[gcode_macro RESUME]
description = Resume the actual running print
rename_existing = RESUME_BASE
variable_last_extruder_temp = {‘restore’: False, ‘temp’: 0}
variable_restore_idle_timeout = 0
variable_idle_state = False
gcode =

{% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %}
{% set velocity = printer.configfile.settings.pause_resume.recover_velocity %}
{% set sp_move = client.speed_move|default(velocity) %}
{% set runout_resume = True if client.runout_sensor|default("") == ""
else True if not printer[client.runout_sensor].enabled
else printer[client.runout_sensor].filament_detected %}
{% set can_extrude = True if printer.toolhead.extruder == ''
else printer[printer.toolhead.extruder].can_extrude %}
{% set do_resume = False %}
{% set prompt_txt = [] %}


{% if printer.idle_timeout.state|upper == "IDLE" or idle_state %}
SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=idle_state VALUE=False
{% if last_extruder_temp.restore %}

RESPOND TYPE=echo MSG='{"Restoring \"%s\" temperature to %3.1f\u00B0C, this may take some time" % (printer.toolhead.extruder, last_extruder_temp.temp) }'
M109 S{last_extruder_temp.temp}
{% set do_resume = True %}
{% elif can_extrude %}
{% set do_resume = True %}
{% else %}
RESPOND TYPE=error MSG='{"Resume aborted !!! \"%s\" not hot enough, please heat up again and press RESUME" % printer.toolhead.extruder}'
{% set _d = prompt_txt.append("\"%s\" not hot enough, please heat up again and press RESUME" % printer.toolhead.extruder) %}
{% endif %}

{% elif can_extrude %}
{% set do_resume = True %}
{% else %}
RESPOND TYPE=error MSG='{"Resume aborted !!! \"%s\" not hot enough, please heat up again and press RESUME" % printer.toolhead.extruder}'
{% set _d = prompt_txt.append("\"%s\" not hot enough, please heat up again and press RESUME" % printer.toolhead.extruder) %}
{% endif %}
{% if runout_resume %}
{% if do_resume %}
{% if restore_idle_timeout > 0 %} SET_IDLE_TIMEOUT TIMEOUT={restore_idle_timeout} {% endif %}
{client.user_resume_macro|default("")}
_CLIENT_EXTRUDE
RESUME_BASE VELOCITY={params.VELOCITY|default(sp_move)}
{% endif %}
{% else %}
RESPOND TYPE=error MSG='{"Resume aborted !!! \"%s\" detects no filament, please load filament and press RESUME" % (client.runout_sensor.split(" "))[1]}'
{% set _d = prompt_txt.append("\"%s\" detects no filament, please load filament and press RESUME" % (client.runout_sensor.split(" "))[1]) %}
{% endif %}

{% if not (runout_resume and do_resume) %}
RESPOND TYPE=command MSG="action:prompt_begin RESUME aborted !!!"
{% for element in prompt_txt %}
RESPOND TYPE=command MSG='{"action:prompt_text %s" % element}'
{% endfor %}
RESPOND TYPE=command MSG="action:prompt_footer_button Ok|RESPOND TYPE=command MSG=action:prompt_end|info"
RESPOND TYPE=command MSG="action:prompt_show"
{% endif %}

[gcode_macro SET_PAUSE_NEXT_LAYER]
description = Enable a pause if the next layer is reached
gcode =
{% set pause_next_layer = printer[‘gcode_macro SET_PRINT_STATS_INFO’].pause_next_layer %}
{% set ENABLE = params.ENABLE|default(1)|int != 0 %}
{% set MACRO = params.MACRO|default(pause_next_layer.call, True) %}
SET_GCODE_VARIABLE MACRO=SET_PRINT_STATS_INFO VARIABLE=pause_next_layer VALUE=“{{ ‘enable’: ENABLE, ‘call’: MACRO }}”

[gcode_macro SET_PAUSE_AT_LAYER]
description = Enable/disable a pause if a given layer number is reached
gcode =
{% set pause_at_layer = printer[‘gcode_macro SET_PRINT_STATS_INFO’].pause_at_layer %}
{% set ENABLE = params.ENABLE|int != 0 if params.ENABLE is defined
else params.LAYER is defined %}
{% set LAYER = params.LAYER|default(pause_at_layer.layer)|int %}
{% set MACRO = params.MACRO|default(pause_at_layer.call, True) %}
SET_GCODE_VARIABLE MACRO=SET_PRINT_STATS_INFO VARIABLE=pause_at_layer VALUE=“{{ ‘enable’: ENABLE, ‘layer’: LAYER, ‘call’: MACRO }}”

[gcode_macro SET_PRINT_STATS_INFO]
rename_existing = SET_PRINT_STATS_INFO_BASE
description = Overwrite, to get pause_next_layer and pause_at_layer feature
variable_pause_next_layer = { ‘enable’: False, ‘call’: “PAUSE” }
variable_pause_at_layer = { ‘enable’: False, ‘layer’: 0, ‘call’: “PAUSE” }
gcode =
{% if pause_next_layer.enable %}
RESPOND TYPE=echo MSG=‘{“%s, forced by pause_next_layer” % pause_next_layer.call}’
{pause_next_layer.call}
SET_PAUSE_NEXT_LAYER ENABLE=0
{% elif pause_at_layer.enable and params.CURRENT_LAYER is defined and params.CURRENT_LAYER|int == pause_at_layer.layer %}
RESPOND TYPE=echo MSG=‘{“%s, forced by pause_at_layer [%d]” % (pause_at_layer.call, pause_at_layer.layer)}’
{pause_at_layer.call}
SET_PAUSE_AT_LAYER ENABLE=0
{% endif %}
SET_PRINT_STATS_INFO_BASE {rawparams}

[gcode_macro _TOOLHEAD_PARK_PAUSE_CANCEL]
description = Helper: park toolhead used in PAUSE and CANCEL_PRINT
gcode =

{% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %}
{% set velocity = printer.configfile.settings.pause_resume.recover_velocity %}
{% set use_custom     = client.use_custom_pos|default(false)|lower == 'true' %}
{% set custom_park_x  = client.custom_park_x|default(0.0) %}
{% set custom_park_y  = client.custom_park_y|default(0.0) %}
{% set park_dz        = client.custom_park_dz|default(2.0)|abs %}
{% set sp_hop         = client.speed_hop|default(15) * 60 %}
{% set sp_move        = client.speed_move|default(velocity) * 60 %}

{% set origin    = printer.gcode_move.homing_origin %}
{% set act       = printer.gcode_move.gcode_position %}
{% set max       = printer.toolhead.axis_maximum %}
{% set cone      = printer.toolhead.cone_start_z|default(max.z) %}
{% set round_bed = True if printer.configfile.settings.printer.kinematics is in ['delta','polar','rotary_delta','winch']
else False %}

{% set z_min = params.Z_MIN|default(0)|float %}
{% set z_park = [[(act.z + park_dz), z_min]|max, (max.z - origin.z)]|min %}
{% set x_park = params.X       if params.X is defined
else custom_park_x  if use_custom
else 0.0            if round_bed
else (max.x - 5.0) %}
{% set y_park = params.Y       if params.Y is defined
else custom_park_y  if use_custom
else (max.y - 5.0)  if round_bed and z_park < cone
else 0.0            if round_bed
else (max.y - 5.0) %}

_CLIENT_RETRACT
{% if "xyz" in printer.toolhead.homed_axes %}
G90
G1 Z{z_park} F{sp_hop}
G1 X{x_park} Y{y_park} F{sp_move}
{% if not printer.gcode_move.absolute_coordinates %} G91 {% endif %}
{% else %}
RESPOND TYPE=echo MSG='Printer not homed'
{% endif %}

[gcode_macro _CLIENT_EXTRUDE]
description = Extrudes, if the extruder is hot enough
gcode =

{% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %}
{% set use_fw_retract = (client.use_fw_retract|default(false)|lower == 'true') and (printer.firmware_retraction is defined) %}
{% set length = params.LENGTH|default(client.unretract)|default(1.0)|float %}
{% set speed = params.SPEED|default(client.speed_unretract)|default(35) %}
{% set absolute_extrude = printer.gcode_move.absolute_extrude %}

{% if printer.toolhead.extruder != '' %}
{% if printer[printer.toolhead.extruder].can_extrude %}
{% if use_fw_retract %}
{% if length < 0 %}
G10
{% else %}
G11
{% endif %}
{% else %}
M83
G1 E{length} F{(speed|float|abs) * 60}
{% if absolute_extrude %}
M82
{% endif %}
{% endif %}
{% else %}
RESPOND TYPE=echo MSG='{"\"%s\" not hot enough" % printer.toolhead.extruder}'
{% endif %}
{% endif %}

[gcode_macro _CLIENT_RETRACT]
description = Retracts, if the extruder is hot enough
gcode =
{% set client = printer[‘gcode_macro _CLIENT_VARIABLE’]|default({}) %}
{% set length = params.LENGTH|default(client.retract)|default(1.0)|float %}
{% set speed = params.SPEED|default(client.speed_retract)|default(35) %}

_CLIENT_EXTRUDE LENGTH=-{length|float|abs} SPEED={speed|float|abs}

[gcode_macro _CLIENT_LINEAR_MOVE]
description = Linear move with save and restore of the gcode state
gcode =
{% set x_move = “X” ~ params.X if params.X is defined else “” %}
{% set y_move = “Y” ~ params.Y if params.Y is defined else “” %}
{% set z_move = “Z” ~ params.Z if params.Z is defined else “” %}
{% set e_move = “E” ~ params.E if params.E is defined else “” %}
{% set rate = “F” ~ params.F if params.F is defined else “” %}
{% set ABSOLUTE = params.ABSOLUTE | default(0) | int != 0 %}
{% set ABSOLUTE_E = params.ABSOLUTE_E | default(0) | int != 0 %}
SAVE_GCODE_STATE NAME=_client_movement
{% if x_move or y_move or z_move %}
G9{ 0 if ABSOLUTE else 1 }
{% endif %}
{% if e_move %}
M8{ 2 if ABSOLUTE_E else 3 }
{% endif %}
G1 { x_move } { y_move } { z_move } { e_move } { rate }
RESTORE_GCODE_STATE NAME=_client_movement

[stepper_x]
step_pin = PB13
dir_pin = !PB12
enable_pin = !PB14
microsteps = 16
rotation_distance = 40
endstop_pin = ^PC0
position_endstop = 0
position_max = 235
homing_speed = 50

[tmc2209 stepper_x]
uart_pin = PC11
tx_pin = PC10
uart_address = 0
run_current = 0.580
stealthchop_threshold = 999999

[stepper_y]
step_pin = PB10
dir_pin = !PB2
enable_pin = !PB11
microsteps = 16
rotation_distance = 40
endstop_pin = ^PC1
position_endstop = 0
position_max = 235
homing_speed = 50

[tmc2209 stepper_y]
uart_pin = PC11
tx_pin = PC10
uart_address = 2
run_current = 0.580
stealthchop_threshold = 999999

[stepper_z]
step_pin = PB0
dir_pin = PC5
enable_pin = !PB1
microsteps = 16
rotation_distance = 8
endstop_pin = ^PC2
position_endstop = 0.0
position_max = 250

[tmc2209 stepper_z]
uart_pin = PC11
tx_pin = PC10
uart_address = 1
run_current = 0.580
stealthchop_threshold = 999999

[extruder]
step_pin = PB3
dir_pin = !PB4
enable_pin = !PD1
microsteps = 16
rotation_distance = 33.500
nozzle_diameter = 0.400
filament_diameter = 1.750
heater_pin = PC8
sensor_type = EPCOS 100K B57560G104F
sensor_pin = PA0
control = pid
pid_kp = 21.527
pid_ki = 1.063
pid_kd = 108.982
min_temp = 0
max_temp = 250

[tmc2209 extruder]
uart_pin = PC11
tx_pin = PC10
uart_address = 3
run_current = 0.650

[heater_bed]
heater_pin = PC9
sensor_type = EPCOS 100K B57560G104F
sensor_pin = PC4
control = pid
pid_kp = 54.027
pid_ki = 0.770
pid_kd = 948.182
min_temp = 0
max_temp = 130

[heater_fan heatbreak_cooling_fan]
pin = PC7

[heater_fan controller_fan]
pin = PB15

[fan]
pin = PC6

[mcu]
serial = /dev/serial/by-id/usb-Klipper_stm32g0b1xx_2800150007504E5238363120-if00

[printer]
kinematics = cartesian
max_velocity = 300
max_accel = 3000
max_z_velocity = 5
max_z_accel = 100

[board_pins]
aliases =

EXP1_1=PB5,  EXP1_3=PA9,   EXP1_5=PA10, EXP1_7=PB8, EXP1_9=<GND>,
EXP1_2=PA15, EXP1_4=<RST>, EXP1_6=PB9,  EXP1_8=PD6, EXP1_10=<5V>

=======================
Extruder max_extrude_ratio=0.266081
mcu ‘mcu’: Starting serial connect
webhooks client 281473040608784: New connection
webhooks client 281473040608784: Client info {‘program’: ‘Moonraker’, ‘version’: ‘v0.9.3-122-g3eb575d’}
Loaded MCU ‘mcu’ 132 commands (v0.13.0-369-g6a8b823a / gcc: (15:12.2.rel1-1) 12.2.1 20221205 binutils: (2.40-2+18+b1) 2.40)
MCU ‘mcu’ config: ADC_MAX=4095 BUS_PINS_i2c1_PA9_PA10=PA9,PA10 BUS_PINS_i2c1_PB6_PB7=PB6,PB7 BUS_PINS_i2c1_PB8_PB9=PB8,PB9 BUS_PINS_i2c2_PA7_PA6=PA7,PA6 BUS_PINS_i2c2_PB10_PB11=PB10,PB11 BUS_PINS_i2c2_PB13_PB14=PB13,PB14 BUS_PINS_i2c3_PA7_PA6=PA7,PA6 BUS_PINS_i2c3_PB3_PB4=PB3,PB4 BUS_PINS_i2c3_PC0_PC1=PC0,PC1 BUS_PINS_spi1=PA6,PA7,PA5 BUS_PINS_spi1_PA6_PA7_PA5=PA6,PA7,PA5 BUS_PINS_spi1_PB4_PB5_PB3=PB4,PB5,PB3 BUS_PINS_spi1a=PB4,PB5,PB3 BUS_PINS_spi2=PB14,PB15,PB13 BUS_PINS_spi2_PB14_PB15_PB13=PB14,PB15,PB13 BUS_PINS_spi2_PB2_PB11_PB10=PB2,PB11,PB10 BUS_PINS_spi2_PB6_PB7_PB8=PB6,PB7,PB8 BUS_PINS_spi2_PC2_PC3_PB10=PC2,PC3,PB10 BUS_PINS_spi2a=PC2,PC3,PB10 BUS_PINS_spi3=PB4,PB5,PB3 BUS_PINS_spi3_PB4_PB5_PB3=PB4,PB5,PB3 BUS_PINS_spi3_PC11_PC12_PC10=PC11,PC12,PC10 CLOCK_FREQ=64000000 INITIAL_PINS=!PA14 MCU=stm32g0b1xx PWM_MAX=257 RESERVE_PINS_USB=PA11,PA12 RESERVE_PINS_crystal=PF0,PF1 STATS_SUMSQ_BASE=256 STEPPER_OPTIMIZED_EDGE=8 STEPPER_STEP_BOTH_EDGE=1
Sending MCU ‘mcu’ printer configuration…

klippy (5).log (14.5 KB)

cd ~/klipper
git checkout 7a036a6ba
sudo systemctl restart klipper

Something is broken in my changes, in some weird way (Serialqueue lock rework by nefelim4ag · Pull Request #7055 · Klipper3d/klipper · GitHub).
That causes the serial queue to hang in an infinite loop.
(So, messages to the MCU is not sent, responses are not received and well, everything stuck).
Alas, until there is either a fix or a revert, this is all you can do (use the previous revision).

Thanks.

1 Like

Thank you for the fast response, explanation and fix :folded_hands: all seems to work for now, will have to finish setting up tomorrow.

Thanks!

Changes are reverted for now: serialqueue: Revert recent serialqueue locking changes · Klipper3d/klipper@7a723bd · GitHub
So, the latest master should work.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.