Skip to content

Commit a438bb0

Browse files
rogerlzKevinOConnorCirromuluspedrolamas
authored
stm32: Add STM32H723 520MHz support (#800)
* stm32: Add optimized stm32h7_gpio.c Add optimized gpio functions for stm32h7 - caching the ODR register can notably improve the performance of the gpio_out_toggle() code. Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * docs: Update benchmarks for stm32h7 Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * output_pin: Introduce new helper to facilitate queuing of gcode requests * servo: Use GCodeRequestQueue to queue updates * output_pin: Improve GCodeRequestQueue timing on duplicate requests The GCodeRequestQueue code handles duplicate requests by detecting a repeat of the last command. If a duplicate is found, no scheduling is performed. However, in this case, the flush_notification() code should continue looking for requests to schedule. Update the GCodeRequestQueue code to use "discard" and "delay" actions to indicate what steps the _flush_notification() callback should take. This simplifies the code and allows for future uses. Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * output_pin: Add send_async_request() support to GCodeRequestQueue Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * fan: Use GCodeRequestQueue to queue updates This is similar to 7940a6a, but using gcrq.send_async_request() for requests that could be asynchronous. Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * fan: Wait full kick_start_time even if request is for full speed Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * mcu: Add new min_schedule_time() and max_nominal_duration() helpers Add a function that returns the minimum amount of time the host needs to reserve for messages to be sent from host to micro-controller. Add a function that returns the maximum amount of time (in seconds) that all micro-controllers should be able to schedule future timers at. Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * output_pin: Use mcu.min_schedule_time() and mcu.max_nominal_duration() Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * pwm_cycle_time: Use mcu.min_schedule_time() and mcu.max_nominal_duration() Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * led: Use mcu.min_schedule_time() and mcu.max_nominal_duration() Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * pwm_tool: Use mcu.min_schedule_time() and mcu.max_nominal_duration() Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * heaters: Confirm heater setting in mcu every 3 seconds instead of 5 Increase the confirmation rate of heater enable settings. This allows the mcu to utilize faster internal speeds. Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * mcu: Decrease mcu.max_nominal_duration() to 3 seconds from 5 This allows the mcu to utilize faster internal speeds. Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * stm32h7: Always clear AHB1ENR at startup on stm32h7 * stm32: Use enable_pclock() in stm32h7 clock_setup() * stm32: Avoid read-modify-write register updates in stm32h7 clock_setup() Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * stm32: Set the PLL frequency equal to CONFIG_CLOCK_FREQ on stm32h723 * stm32: Don't try to set incorrect PWR->CR3 register on stm32h7 * stm32: Enable VOS0 power mode on stm32h723 if frequency above 400Mhz * stm32: Use CONFIG_STM32_CLOCK_REF_25M for pll_base in stm32g4.c Update stm32g4.c to use the same Kconfig-based approach as stm32h7.c for determining pll_base, replacing the compile-time preprocessor check. This maintains 25MHz crystal support from Kalico #623 while using the cleaner upstream approach from #6909. Signed-off-by: Rogério Gonçalves <rogerlz@gmail.com> * stm32: Use 12Mhz nominal internal clock in stm32f0_i2c.c * stm32: Support over 400Mhz main clock in stm32h7_adc.c * stm32: Run stm32h723 at 520Mhz * docs: Update stm32h723 benchmarks now that it runs at 520Mhz * MCU: Fail early if clock speed is too high to support max nominal duration (#7122) This adds a dedicated check for that case to be able to find the root cause of a misconfiguration earlier. Also, replace occurrences of hardcoded max tick count. Signed-off-by: Pascal Pieper <accounts@pascalpieper.de> * heaters: Increase time before clearing the temperature of an inactive heater The get_temp() code will stop reporting the last temperature of the heater if there hasn't been any recent temperature updates. However, on a full mcu communication loss this can cause the verify_heater code to report a heating error prior to the mcu code reporting the communication failure. Increase the heater timeout from 5 to 7 seconds to make it more likely the mcu failure is reported first. Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * heaters: Reduce next_pwm_time window * timer_irq: Remove TIMER_IDLE_REPEAT_TICKS special case * armcm_timer: Use a static instruction count for TIMER_MIN_TRY_TICKS * serialqueue: Tune MIN_REQTIME_DELTA timing * reactor: Prevent update_timer() from running a single timer multiple times * display: Check for redraw_request_pending at end of screen_update_event() * mcu: Fix incorrect reqclock during endstop homing For correct operation the trsync system must be programmed prior to the start of endstop checking. This means the desired "reqclock" for the trsync configuration messages need to use the same "clock" that the endstop start message uses - even though the actual deadline for these messages is later. Signed-off-by: Kevin O'Connor <kevin@koconnor.net> (cherry picked from commit 8e6e467ebc16f93ab01ed63c55d24af52b020b54) * serialqueue: Make 31-bit clock overflow check a little more robust Allow reqclock to be slightly less than the transmitted messages's deadline. That is, delay messages with a reqclock far in the future to slightly past (1<<31) ticks from its deadline. Use (3<<29) instead, which gives an additional (1<<29) grace period to avoid clock overflow issues. Signed-off-by: Kevin O'Connor <kevin@koconnor.net> (cherry picked from commit 867d73f0b8988a8df79abb3223018132c11448ab) * led: Generalize template evaluation so it is not dependent on LEDs Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * output_pin: Move template evaluation code from led.py to output_pin.py Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * output_pin: Support setting a TEMPLATE on SET_PIN commands Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * fan: Support calling set_speed() without a print_time Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * fan_generic: Support setting a TEMPLATE on SET_FAN_SPEED commands Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * fan_generic: fixes missing logging import Signed-off-by: Pedro Lamas <pedrolamas@gmail.com> * output_pin: Fix handling of template rendering errors Make sure to assign 'value' on a rendering error to avoid an internal error. Signed-off-by: Kevin O'Connor <kevin@koconnor.net> * fan_generic: Fix handling of template rendering errors Make sure to assign 'value' on a rendering error to avoid an internal error. Signed-off-by: Kevin O'Connor <kevin@koconnor.net> --------- Signed-off-by: Kevin O'Connor <kevin@koconnor.net> Signed-off-by: Rogério Gonçalves <rogerlz@gmail.com> Signed-off-by: Pascal Pieper <accounts@pascalpieper.de> Signed-off-by: Pedro Lamas <pedrolamas@gmail.com> Co-authored-by: Kevin O'Connor <kevin@koconnor.net> Co-authored-by: Pascal <accounts@pascalpieper.de> Co-authored-by: Pedro Lamas <pedrolamas@gmail.com>
1 parent b42dd20 commit a438bb0

35 files changed

Lines changed: 729 additions & 418 deletions

docs/Benchmarks.md

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -250,23 +250,22 @@ results were obtained by running an STM32F407 binary on an STM32F446
250250

251251
### STM32H7 step rate benchmark
252252

253-
The following configuration sequence is used on a STM32H743VIT6:
253+
The following configuration sequence is used on STM32H723:
254254
```
255255
allocate_oids count=3
256-
config_stepper oid=0 step_pin=PD4 dir_pin=PD3 invert_step=-1 step_pulse_ticks=0
257-
config_stepper oid=1 step_pin=PA15 dir_pin=PA8 invert_step=-1 step_pulse_ticks=0
258-
config_stepper oid=2 step_pin=PE2 dir_pin=PE3 invert_step=-1 step_pulse_ticks=0
256+
config_stepper oid=0 step_pin=PA13 dir_pin=PB5 invert_step=-1 step_pulse_ticks=52
257+
config_stepper oid=1 step_pin=PB2 dir_pin=PB6 invert_step=-1 step_pulse_ticks=52
258+
config_stepper oid=2 step_pin=PB3 dir_pin=PB7 invert_step=-1 step_pulse_ticks=52
259259
finalize_config crc=0
260260
```
261261

262-
The test was last run on commit `00191b5c` with gcc version
263-
`arm-none-eabi-gcc (15:8-2019-q3-1+b1) 8.3.1 20190703 (release)
264-
[gcc-8-branch revision 273027]`.
262+
The test was last run on commit `554ae78d` with gcc version
263+
`arm-none-eabi-gcc (Fedora 14.1.0-1.fc40) 14.1.0`.
265264

266-
| stm32h7 | ticks |
265+
| stm32h723 | ticks |
267266
| -------------------- | ----- |
268-
| 1 stepper | 44 |
269-
| 3 stepper | 198 |
267+
| 1 stepper | 70 |
268+
| 3 stepper | 181 |
270269

271270
### STM32G0B1 step rate benchmark
272271

docs/Config_Changes.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ All dates in this document are approximate.
1212
takes a time in seconds to debounce the state of the button before any action
1313
is taken. It defaults to 0 which causes it to act as if there is no debouncing.
1414

15+
20250425: The maximum `cycle_time` for pwm `[output_pin]`,
16+
`[pwm_cycle_time]`, `[pwm_tool]`, and similar config sections is now 3
17+
seconds (reduced from 5 seconds). The `maximum_mcu_duration` in
18+
`[pwm_tool]` is now also 3 seconds.
19+
1520
20250816: The filament_switch_sensor adds a new option `debounce_delay` that
1621
takes a time in seconds to debounce the state of the switch before any action
1722
is taken. It defaults to 0 which causes it to act as if there is no debouncing.
@@ -47,6 +52,19 @@ default config values anymore, a [`RESET_RETRACTION`](./G-Codes.md#reset_retract
4752
command was added to achieve this. Automatic resetting behavior on
4853
events was removed.
4954

55+
20240912: `SET_PIN`, `SET_SERVO`, `SET_FAN_SPEED`, `M106`, and `M107`
56+
commands are now collated. Previously, if many updates to the same
57+
object were issued faster than the minimum scheduling time (typically
58+
100ms) then actual updates could be queued far into the future. Now if
59+
many updates are issued in rapid succession then it is possible that
60+
only the latest request will be applied. If the previous behavior is
61+
required then consider adding explicit `G4` delay commands between
62+
updates.
63+
64+
20240912: Support for `maximum_mcu_duration` and `static_value`
65+
parameters in `[output_pin]` config sections have been removed. These
66+
options have been deprecated since 20240123.
67+
5068
20240430: The `adc_ignore_limits` parameter in the `[danger_options]`
5169
config section has been renamed to `temp_ignore_limits` and it now
5270
covers all possible temperature sensors.

docs/Features.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ represent total number of steps per second on the micro-controller.
192192
| RP2040 | 4000K | 2571K |
193193
| RP2350 | 4167K | 2663K |
194194
| SAME70 | 6667K | 4737K |
195-
| STM32H743 | 9091K | 6061K |
195+
| STM32H723 | 7429K | 8619K |
196196

197197
If unsure of the micro-controller on a particular board, find the
198198
appropriate [config file](../config/), and look for the

docs/G-Codes.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,20 @@ enabled.
620620
`SET_FAN_SPEED FAN=config_name SPEED=<speed>` This command sets the
621621
speed of a fan. "speed" must be between 0.0 and 1.0.
622622

623+
`SET_FAN_SPEED PIN=config_name TEMPLATE=<template_name>
624+
[<param_x>=<literal>]`: If `TEMPLATE` is specified then it assigns a
625+
[display_template](Config_Reference.md#display_template) to the given
626+
fan. For example, if one defined a `[display_template
627+
my_fan_template]` config section then one could assign
628+
`TEMPLATE=my_fan_template` here. The display_template should produce a
629+
string containing a floating point number with the desired value. The
630+
template will be continuously evaluated and the fan will be
631+
automatically set to the resulting speed. One may set display_template
632+
parameters to use during template evaluation (parameters will be
633+
parsed as Python literals). If TEMPLATE is an empty string then this
634+
command will clear any previous template assigned to the pin (one can
635+
then use `SET_FAN_SPEED` commands to manage the values directly).
636+
623637
### [filament_switch_sensor]
624638

625639
The following command is available when a
@@ -1131,6 +1145,20 @@ output `VALUE`. VALUE should be 0 or 1 for "digital" output pins. For
11311145
PWM pins, set to a value between 0.0 and 1.0, or between 0.0 and
11321146
`scale` if a scale is configured in the output_pin config section.
11331147

1148+
`SET_PIN PIN=config_name TEMPLATE=<template_name> [<param_x>=<literal>]`:
1149+
If `TEMPLATE` is specified then it assigns a
1150+
[display_template](Config_Reference.md#display_template) to the given
1151+
pin. For example, if one defined a `[display_template
1152+
my_pin_template]` config section then one could assign
1153+
`TEMPLATE=my_pin_template` here. The display_template should produce a
1154+
string containing a floating point number with the desired value. The
1155+
template will be continuously evaluated and the pin will be
1156+
automatically set to the resulting value. One may set display_template
1157+
parameters to use during template evaluation (parameters will be
1158+
parsed as Python literals). If TEMPLATE is an empty string then this
1159+
command will clear any previous template assigned to the pin (one can
1160+
then use `SET_PIN` commands to manage the values directly).
1161+
11341162
### [palette2]
11351163

11361164
The following commands are available when the

klippy/chelper/serialqueue.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ struct serialqueue {
9191
#define MIN_RTO 0.025
9292
#define MAX_RTO 5.000
9393
#define MAX_PENDING_BLOCKS 12
94-
#define MIN_REQTIME_DELTA 0.250
94+
#define MIN_REQTIME_DELTA 0.100
9595
#define MIN_BACKGROUND_DELTA 0.005
9696
#define IDLE_QUERY_TIME 1.0
9797

@@ -793,9 +793,10 @@ serialqueue_send_batch(struct serialqueue *sq, struct command_queue *cq
793793
int len = 0;
794794
struct queue_message *qm;
795795
list_for_each_entry(qm, msgs, node) {
796-
if (qm->min_clock + (1LL<<31) < qm->req_clock
796+
if (qm->min_clock + (3LL<<29) < qm->req_clock
797797
&& qm->req_clock != BACKGROUND_PRIORITY_CLOCK)
798-
qm->min_clock = qm->req_clock - (1LL<<31);
798+
// Avoid mcu clock comparison 31-bit overflow issues
799+
qm->min_clock = qm->req_clock - (3LL<<29);
799800
len += qm->len;
800801
}
801802
if (! len)

klippy/extras/controller_fan.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,7 @@ def callback(self, eventtime):
7373
self.last_on += 1
7474
if speed != self.last_speed:
7575
self.last_speed = speed
76-
curtime = self.printer.get_reactor().monotonic()
77-
print_time = self.fan.get_mcu().estimated_print_time(curtime)
78-
self.fan.set_speed(print_time + PIN_MIN_TIME, speed)
76+
self.fan.set_speed(speed)
7977
return eventtime + 1.0
8078

8179

klippy/extras/display/display.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ def screen_update_event(self, eventtime):
289289
except:
290290
logging.exception("Error during display screen update")
291291
self.lcd_chip.flush()
292+
if self.redraw_request_pending:
293+
return self.redraw_time
292294
return eventtime + REDRAW_TIME
293295

294296
def request_redraw(self):

klippy/extras/dotstar.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Support for "dotstar" leds
22
#
3-
# Copyright (C) 2019-2022 Kevin O'Connor <kevin@koconnor.net>
3+
# Copyright (C) 2019-2024 Kevin O'Connor <kevin@koconnor.net>
44
#
55
# This file may be distributed under the terms of the GNU GPLv3 license.
6-
from . import bus
6+
from . import bus, led
77

88
BACKGROUND_PRIORITY_CLOCK = 0x7FFFFFFF00000000
99

@@ -26,8 +26,7 @@ def __init__(self, config):
2626
self.spi = bus.MCU_SPI(mcu, None, None, 0, 500000, sw_spi_pins)
2727
# Initialize color data
2828
self.chain_count = config.getint("chain_count", 1, minval=1)
29-
pled = printer.load_object(config, "led")
30-
self.led_helper = pled.setup_helper(
29+
self.led_helper = led.LEDHelper(
3130
config, self.update_leds, self.chain_count
3231
)
3332
self.prev_data = None

klippy/extras/fan.py

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,13 @@
33
# Copyright (C) 2016-2020 Kevin O'Connor <kevin@koconnor.net>
44
#
55
# This file may be distributed under the terms of the GNU GPLv3 license.
6-
from . import pulse_counter
7-
8-
FAN_MIN_TIME = 0.100
6+
from . import output_pin, pulse_counter
97

108

119
class Fan:
1210
def __init__(self, config, default_shutdown_speed=0.0):
1311
self.printer = config.get_printer()
14-
self.last_fan_value = 0.0
15-
self.last_fan_time = 0.0
12+
self.last_fan_value = self.last_req_value = 0.0
1613
self.last_pwm_value = 0.0
1714
# Read config
1815
self.kick_start_time = config.getfloat(
@@ -79,6 +76,11 @@ def __init__(self, config, default_shutdown_speed=0.0):
7976
self.enable_pin = ppins.setup_pin("digital_out", enable_pin)
8077
self.enable_pin.setup_max_duration(0.0)
8178

79+
# Create gcode request queue
80+
self.gcrq = output_pin.GCodeRequestQueue(
81+
config, self.mcu_fan.get_mcu(), self._apply_speed
82+
)
83+
8284
# Setup tachometer
8385
self.tachometer = FanTachometer(config)
8486

@@ -91,18 +93,17 @@ def __init__(self, config, default_shutdown_speed=0.0):
9193
def get_mcu(self):
9294
return self.mcu_fan.get_mcu()
9395

94-
def set_speed(self, print_time, value):
96+
def _apply_speed(self, print_time, value):
9597
if value == self.last_fan_value:
96-
return
98+
return "discard", 0.0
9799
if value > 0:
98100
# Scale value between min_power and max_power
99101
value = min(value, 1.0)
100102
pwm_value = (
101103
value * (self.max_power - self.min_power) + self.min_power
102104
)
103105
else:
104-
pwm_value = 0
105-
print_time = max(self.last_fan_time + FAN_MIN_TIME, print_time)
106+
pwm_value = 0.0
106107
if self.enable_pin:
107108
if value > 0 and self.last_fan_value == 0:
108109
self.enable_pin.set_digital(print_time, 1)
@@ -115,21 +116,23 @@ def set_speed(self, print_time, value):
115116
and (not self.last_fan_value or value - self.last_fan_value > 0.5)
116117
):
117118
# Run fan at full speed for specified kick_start_time
119+
self.last_req_value = value
120+
self.last_fan_value = value
121+
self.last_pwm_value = self.max_power
118122
self.mcu_fan.set_pwm(print_time, self.max_power)
119-
print_time += self.kick_start_time
120-
self.mcu_fan.set_pwm(print_time, pwm_value)
123+
return "delay", self.kick_start_time
124+
self.last_fan_value = self.last_req_value = value
121125
self.last_pwm_value = pwm_value
122-
self.last_fan_time = print_time
123-
self.last_fan_value = value
126+
self.mcu_fan.set_pwm(print_time, pwm_value)
127+
128+
def set_speed(self, value, print_time=None):
129+
self.gcrq.send_async_request(value, print_time)
124130

125131
def set_speed_from_command(self, value):
126-
toolhead = self.printer.lookup_object("toolhead")
127-
toolhead.register_lookahead_callback(
128-
(lambda pt: self.set_speed(pt, value))
129-
)
132+
self.gcrq.queue_gcode_request(value)
130133

131134
def _handle_request_restart(self, print_time):
132-
self.set_speed(print_time, 0.0)
135+
self.set_speed(0.0, print_time)
133136

134137
def _handle_ready(self):
135138
if self.initial_speed:

klippy/extras/fan_generic.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# Support fans that are controlled by gcode
22
#
3-
# Copyright (C) 2016-2020 Kevin O'Connor <kevin@koconnor.net>
3+
# Copyright (C) 2016-2024 Kevin O'Connor <kevin@koconnor.net>
44
#
55
# This file may be distributed under the terms of the GNU GPLv3 license.
6-
from . import fan
6+
import logging
7+
8+
from . import fan, output_pin
79

810

911
class PrinterFanGeneric:
@@ -14,6 +16,9 @@ def __init__(self, config):
1416
self.fan = fan.Fan(config, default_shutdown_speed=0.0)
1517
self.fan_name = config.get_name().split()[-1]
1618

19+
# Template handling
20+
self.template_eval = output_pin.lookup_template_eval(config)
21+
1722
gcode = self.printer.lookup_object("gcode")
1823
gcode.register_mux_command(
1924
"SET_FAN_SPEED",
@@ -26,8 +31,23 @@ def __init__(self, config):
2631
def get_status(self, eventtime):
2732
return self.fan.get_status(eventtime)
2833

34+
def _template_update(self, text):
35+
try:
36+
value = float(text)
37+
except ValueError as e:
38+
logging.exception("fan_generic template render error")
39+
value = 0.0
40+
self.fan.set_speed(value)
41+
2942
def cmd_SET_FAN_SPEED(self, gcmd):
30-
speed = gcmd.get_float("SPEED", 0.0)
43+
speed = gcmd.get_float("SPEED", None, 0.0)
44+
template = gcmd.get("TEMPLATE", None)
45+
if (speed is None) == (template is None):
46+
raise gcmd.error("SET_FAN_SPEED must specify SPEED or TEMPLATE")
47+
# Check for template setting
48+
if template is not None:
49+
self.template_eval.set_template(gcmd, self._template_update)
50+
return
3151
self.fan.set_speed_from_command(speed)
3252

3353

0 commit comments

Comments
 (0)