소스 검색

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

Jason Smith 3 년 전
부모
커밋
12bc63913c
No account linked to committer's email address
5개의 변경된 파일56개의 추가작업 그리고 18개의 파일을 삭제
  1. 1
    1
      Marlin/src/HAL/STM32/HAL.cpp
  2. 22
    2
      Marlin/src/HAL/STM32/Servo.cpp
  3. 1
    0
      Marlin/src/HAL/STM32/Servo.h
  4. 30
    14
      Marlin/src/HAL/STM32/timers.cpp
  5. 2
    1
      Marlin/src/HAL/STM32/timers.h

+ 1
- 1
Marlin/src/HAL/STM32/HAL.cpp 파일 보기

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

+ 22
- 2
Marlin/src/HAL/STM32/Servo.cpp 파일 보기

33
 constexpr millis_t servoDelay[] = SERVO_DELAY;
33
 constexpr millis_t servoDelay[] = SERVO_DELAY;
34
 static_assert(COUNT(servoDelay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
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
 libServo::libServo()
48
 libServo::libServo()
37
 : delay(servoDelay[servoCount]),
49
 : delay(servoDelay[servoCount]),
38
   was_attached_before_pause(false),
50
   was_attached_before_pause(false),
44
 int8_t libServo::attach(const int pin) {
56
 int8_t libServo::attach(const int pin) {
45
   if (servoCount >= MAX_SERVOS) return -1;
57
   if (servoCount >= MAX_SERVOS) return -1;
46
   if (pin > 0) servo_pin = pin;
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
 int8_t libServo::attach(const int pin, const int min, const int max) {
64
 int8_t libServo::attach(const int pin, const int min, const int max) {
51
   if (servoCount >= MAX_SERVOS) return -1;
65
   if (servoCount >= MAX_SERVOS) return -1;
52
   if (pin > 0) servo_pin = pin;
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
 void libServo::move(const int value) {
72
 void libServo::move(const int value) {
86
     if (servo) servo->resume();
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
 #endif // HAS_SERVOS
109
 #endif // HAS_SERVOS
90
 #endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
110
 #endif // ARDUINO_ARCH_STM32 && !STM32GENERIC

+ 1
- 0
Marlin/src/HAL/STM32/Servo.h 파일 보기

41
 
41
 
42
     static void pause_all_servos();
42
     static void pause_all_servos();
43
     static void resume_all_servos();
43
     static void resume_all_servos();
44
+    static void setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority);
44
 
45
 
45
   private:
46
   private:
46
     Servo stm32_servo;
47
     Servo stm32_servo;

+ 30
- 14
Marlin/src/HAL/STM32/timers.cpp 파일 보기

29
 
29
 
30
 #define NUM_HARDWARE_TIMERS 2
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
 #ifndef STEP_TIMER_IRQ_PRIO
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
 #endif
43
 #endif
35
 #ifndef TEMP_TIMER_IRQ_PRIO
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
 #endif
46
 #endif
47
-
48
 #if HAS_TMC_SW_SERIAL
47
 #if HAS_TMC_SW_SERIAL
49
   #include <SoftwareSerial.h>
48
   #include <SoftwareSerial.h>
50
   #ifndef SWSERIAL_TIMER_IRQ_PRIO
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
   #endif
67
   #endif
53
 #endif
68
 #endif
54
 
69
 
189
   return nullptr;
204
   return nullptr;
190
 }
205
 }
191
 
206
 
192
-void SetSoftwareSerialTimerInterruptPriority() {
207
+void SetTimerInterruptPriorities() {
193
   TERN_(HAS_TMC_SW_SERIAL, SoftwareSerial::setInterruptPriority(SWSERIAL_TIMER_IRQ_PRIO, 0));
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
 #endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
212
 #endif // ARDUINO_ARCH_STM32 && !STM32GENERIC

+ 2
- 1
Marlin/src/HAL/STM32/timers.h 파일 보기

86
 void HAL_timer_disable_interrupt(const uint8_t timer_num);
86
 void HAL_timer_disable_interrupt(const uint8_t timer_num);
87
 bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
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
 // Exposed here to allow all timer priority information to reside in timers.cpp
90
 // Exposed here to allow all timer priority information to reside in timers.cpp
90
-void SetSoftwareSerialTimerInterruptPriority();
91
+void SetTimerInterruptPriorities();
91
 
92
 
92
 //TIM_TypeDef* HAL_timer_device(const uint8_t timer_num); no need to be public for now. not public = not used externally
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
 

Loading…
취소
저장