Quellcode durchsuchen

Fix BLTouch PWM reliability in HAL/STM32 (#18702)

Jason Smith vor 3 Jahren
Ursprung
Commit
12bc63913c
Es ist kein Account mit der E-Mail-Adresse des Committers verbunden

+ 1
- 1
Marlin/src/HAL/STM32/HAL.cpp Datei anzeigen

@@ -79,7 +79,7 @@ void HAL_init() {
79 79
     while (!LL_PWR_IsActiveFlag_BRR());   // Wait until backup regulator is initialized
80 80
   #endif
81 81
 
82
-  SetSoftwareSerialTimerInterruptPriority();
82
+  SetTimerInterruptPriorities();
83 83
 
84 84
   TERN_(EMERGENCY_PARSER, USB_Hook_init());
85 85
 }

+ 22
- 2
Marlin/src/HAL/STM32/Servo.cpp Datei anzeigen

@@ -33,6 +33,18 @@ static libServo *servos[NUM_SERVOS] = {0};
33 33
 constexpr millis_t servoDelay[] = SERVO_DELAY;
34 34
 static_assert(COUNT(servoDelay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
35 35
 
36
+// Initialize to the default timer priority. This will be overridden by a call from timers.cpp.
37
+// This allows all timer interrupt priorities to be managed from a single location in the HAL.
38
+static uint32_t servo_interrupt_priority = NVIC_EncodePriority(NVIC_GetPriorityGrouping(), TIM_IRQ_PRIO, TIM_IRQ_SUBPRIO);
39
+
40
+// This must be called after the STM32 Servo class has intialized the timer.
41
+// It may only be needed after the first call to attach(), but it is possible
42
+// that is is necessary after every detach() call. To be safe this is currently
43
+// called after every call to attach().
44
+static void fixServoTimerInterruptPriority() {
45
+  NVIC_SetPriority(getTimerUpIrq(TIMER_SERVO), servo_interrupt_priority);
46
+}
47
+
36 48
 libServo::libServo()
37 49
 : delay(servoDelay[servoCount]),
38 50
   was_attached_before_pause(false),
@@ -44,13 +56,17 @@ libServo::libServo()
44 56
 int8_t libServo::attach(const int pin) {
45 57
   if (servoCount >= MAX_SERVOS) return -1;
46 58
   if (pin > 0) servo_pin = pin;
47
-  return stm32_servo.attach(servo_pin);
59
+  auto result = stm32_servo.attach(servo_pin);
60
+  fixServoTimerInterruptPriority();
61
+  return result;
48 62
 }
49 63
 
50 64
 int8_t libServo::attach(const int pin, const int min, const int max) {
51 65
   if (servoCount >= MAX_SERVOS) return -1;
52 66
   if (pin > 0) servo_pin = pin;
53
-  return stm32_servo.attach(servo_pin, min, max);
67
+  auto result = stm32_servo.attach(servo_pin, min, max);
68
+  fixServoTimerInterruptPriority();
69
+  return result;
54 70
 }
55 71
 
56 72
 void libServo::move(const int value) {
@@ -86,5 +102,9 @@ void libServo::resume_all_servos() {
86 102
     if (servo) servo->resume();
87 103
 }
88 104
 
105
+void libServo::setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority) {
106
+  servo_interrupt_priority = NVIC_EncodePriority(NVIC_GetPriorityGrouping(), preemptPriority, subPriority);
107
+}
108
+
89 109
 #endif // HAS_SERVOS
90 110
 #endif // ARDUINO_ARCH_STM32 && !STM32GENERIC

+ 1
- 0
Marlin/src/HAL/STM32/Servo.h Datei anzeigen

@@ -41,6 +41,7 @@ class libServo {
41 41
 
42 42
     static void pause_all_servos();
43 43
     static void resume_all_servos();
44
+    static void setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority);
44 45
 
45 46
   private:
46 47
     Servo stm32_servo;

+ 30
- 14
Marlin/src/HAL/STM32/timers.cpp Datei anzeigen

@@ -29,26 +29,41 @@
29 29
 
30 30
 #define NUM_HARDWARE_TIMERS 2
31 31
 
32
+// Default timer priorities. Override by specifying alternate priorities in the board pins file.
33
+// The TONE timer is not present here, as it currently cannot be set programmatically. It is set
34
+// by defining TIM_IRQ_PRIO in the variant.h or platformio.ini file, which adjusts the default
35
+// priority for STM32 HardwareTimer objects.
36
+#define SWSERIAL_TIMER_IRQ_PRIO_DEFAULT  1 // Requires tight bit timing to communicate reliably with TMC drivers
37
+#define SERVO_TIMER_IRQ_PRIO_DEFAULT     1 // Requires tight PWM timing to control a BLTouch reliably
38
+#define STEP_TIMER_IRQ_PRIO_DEFAULT      2
39
+#define TEMP_TIMER_IRQ_PRIO_DEFAULT     14 // Low priority avoids interference with other hardware and timers
40
+
32 41
 #ifndef STEP_TIMER_IRQ_PRIO
33
-  #define STEP_TIMER_IRQ_PRIO 2
42
+  #define STEP_TIMER_IRQ_PRIO STEP_TIMER_IRQ_PRIO_DEFAULT
34 43
 #endif
35 44
 #ifndef TEMP_TIMER_IRQ_PRIO
36
-  #define TEMP_TIMER_IRQ_PRIO 14   // 14 = after hardware ISRs
37
-#endif
38
-
39
-// Ensure the default timer priority is somewhere between the STEP and TEMP priorities.
40
-// The STM32 framework defaults to interrupt 14 for all timers. This should be increased so that
41
-// timing-sensitive operations such as speaker output are note impacted by the long-running
42
-// temperature ISR. This must be defined in the platformio.ini file or the board's variant.h,
43
-// so that it will be consumed by framework code.
44
-#if !(TIM_IRQ_PRIO > STEP_TIMER_IRQ_PRIO && TIM_IRQ_PRIO < TEMP_TIMER_IRQ_PRIO)
45
-  #error "Default timer interrupt priority is unspecified or set to a value which may degrade performance."
45
+  #define TEMP_TIMER_IRQ_PRIO TEMP_TIMER_IRQ_PRIO_DEFAULT
46 46
 #endif
47
-
48 47
 #if HAS_TMC_SW_SERIAL
49 48
   #include <SoftwareSerial.h>
50 49
   #ifndef SWSERIAL_TIMER_IRQ_PRIO
51
-    #define SWSERIAL_TIMER_IRQ_PRIO 1
50
+    #define SWSERIAL_TIMER_IRQ_PRIO SWSERIAL_TIMER_IRQ_PRIO_DEFAULT
51
+  #endif
52
+#endif
53
+#if HAS_SERVOS
54
+  #include "Servo.h"
55
+  #ifndef SERVO_TIMER_IRQ_PRIO
56
+    #define SERVO_TIMER_IRQ_PRIO SERVO_TIMER_IRQ_PRIO_DEFAULT
57
+  #endif
58
+#endif
59
+#if ENABLED(SPEAKER)
60
+  // Ensure the default timer priority is somewhere between the STEP and TEMP priorities.
61
+  // The STM32 framework defaults to interrupt 14 for all timers. This should be increased so that
62
+  // timing-sensitive operations such as speaker output are not impacted by the long-running
63
+  // temperature ISR. This must be defined in the platformio.ini file or the board's variant.h,
64
+  // so that it will be consumed by framework code.
65
+  #if !(TIM_IRQ_PRIO > STEP_TIMER_IRQ_PRIO && TIM_IRQ_PRIO < TEMP_TIMER_IRQ_PRIO)
66
+    #error "Default timer interrupt priority is unspecified or set to a value which may degrade performance."
52 67
   #endif
53 68
 #endif
54 69
 
@@ -189,8 +204,9 @@ TIM_TypeDef * HAL_timer_device(const uint8_t timer_num) {
189 204
   return nullptr;
190 205
 }
191 206
 
192
-void SetSoftwareSerialTimerInterruptPriority() {
207
+void SetTimerInterruptPriorities() {
193 208
   TERN_(HAS_TMC_SW_SERIAL, SoftwareSerial::setInterruptPriority(SWSERIAL_TIMER_IRQ_PRIO, 0));
209
+  TERN_(HAS_SERVOS, libServo::setInterruptPriority(SERVO_TIMER_IRQ_PRIO, 0));
194 210
 }
195 211
 
196 212
 #endif // ARDUINO_ARCH_STM32 && !STM32GENERIC

+ 2
- 1
Marlin/src/HAL/STM32/timers.h Datei anzeigen

@@ -86,8 +86,9 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num);
86 86
 void HAL_timer_disable_interrupt(const uint8_t timer_num);
87 87
 bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
88 88
 
89
+// Configure timer priorities for peripherals such as Software Serial or Servos.
89 90
 // Exposed here to allow all timer priority information to reside in timers.cpp
90
-void SetSoftwareSerialTimerInterruptPriority();
91
+void SetTimerInterruptPriorities();
91 92
 
92 93
 //TIM_TypeDef* HAL_timer_device(const uint8_t timer_num); no need to be public for now. not public = not used externally
93 94
 

Laden…
Abbrechen
Speichern