Преглед на файлове

Proper AVR preemptive interrupt handling (#10496)

Also simplify logic on all ARM-based interrupts. Now, it is REQUIRED to properly configure interrupt priority. USART should have highest priority, followed by Stepper, and then all others.
Eduardo José Tagle преди 7 години
родител
ревизия
0c428a66d9

+ 25
- 6
Marlin/src/HAL/HAL_AVR/HAL.h Целия файл

@@ -142,10 +142,11 @@ extern "C" {
142 142
 
143 143
 #define ENABLE_STEPPER_DRIVER_INTERRUPT()  SBI(TIMSK1, OCIE1A)
144 144
 #define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A)
145
-#define STEPPER_ISR_ENABLED() TEST(TIMSK1, OCIE1A)
145
+#define STEPPER_ISR_ENABLED()             TEST(TIMSK1, OCIE1A)
146 146
 
147
-#define ENABLE_TEMPERATURE_INTERRUPT()  SBI(TIMSK0, OCIE0B)
148
-#define DISABLE_TEMPERATURE_INTERRUPT() CBI(TIMSK0, OCIE0B)
147
+#define ENABLE_TEMPERATURE_INTERRUPT()     SBI(TIMSK0, OCIE0B)
148
+#define DISABLE_TEMPERATURE_INTERRUPT()    CBI(TIMSK0, OCIE0B)
149
+#define TEMPERATURE_ISR_ENABLED()         TEST(TIMSK0, OCIE0B)
149 150
 
150 151
 #define HAL_timer_start(timer_num, frequency)
151 152
 
@@ -156,13 +157,31 @@ extern "C" {
156 157
 #define HAL_timer_get_compare(timer) _CAT(TIMER_OCR_, timer)
157 158
 #define HAL_timer_get_count(timer) _CAT(TIMER_COUNTER_, timer)
158 159
 
159
-#define HAL_timer_isr_prologue(timer_num)
160
+/**
161
+ * On AVR there is no hardware prioritization and preemption of
162
+ * interrupts, so this emulates it. The UART has first priority
163
+ * (otherwise, characters will be lost due to UART overflow).
164
+ * Then: Stepper, Endstops, Temperature, and -finally- all others.
165
+ */
166
+#define HAL_timer_isr_prologue_0 do{ DISABLE_TEMPERATURE_INTERRUPT(); sei(); }while(0)
167
+#define HAL_timer_isr_epilogue_0 do{ cli(); ENABLE_TEMPERATURE_INTERRUPT(); }while(0)
168
+
169
+#define HAL_timer_isr_prologue_1 \
170
+  const bool temp_isr_was_enabled = TEMPERATURE_ISR_ENABLED(); \
171
+  do{ \
172
+    DISABLE_TEMPERATURE_INTERRUPT(); \
173
+    DISABLE_STEPPER_DRIVER_INTERRUPT(); \
174
+    sei(); \
175
+  }while(0)
176
+
177
+#define HAL_timer_isr_epilogue_1 do{ cli(); ENABLE_STEPPER_DRIVER_INTERRUPT(); if (temp_isr_was_enabled) ENABLE_TEMPERATURE_INTERRUPT(); }while(0)
178
+
179
+#define HAL_timer_isr_prologue(TIMER_NUM) _CAT(HAL_timer_isr_prologue_, TIMER_NUM)
180
+#define HAL_timer_isr_epilogue(TIMER_NUM) _CAT(HAL_timer_isr_epilogue_, TIMER_NUM)
160 181
 
161 182
 #define HAL_STEP_TIMER_ISR ISR(TIMER1_COMPA_vect)
162 183
 #define HAL_TEMP_TIMER_ISR ISR(TIMER0_COMPB_vect)
163 184
 
164
-#define HAL_ENABLE_ISRs() do { cli(); if (thermalManager.in_temp_isr) DISABLE_TEMPERATURE_INTERRUPT(); else ENABLE_TEMPERATURE_INTERRUPT(); ENABLE_STEPPER_DRIVER_INTERRUPT(); } while(0)
165
-
166 185
 // ADC
167 186
 #ifdef DIDR2
168 187
   #define HAL_ANALOG_SELECT(pin) do{ if (pin < 8) SBI(DIDR0, pin); else SBI(DIDR2, pin & 0x07); }while(0)

+ 3
- 3
Marlin/src/HAL/HAL_DUE/HAL_timers_Due.cpp Целия файл

@@ -61,13 +61,13 @@
61 61
 // --------------------------------------------------------------------------
62 62
 
63 63
 const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
64
-  { TC0, 0, TC0_IRQn,  0}, // 0 - [servo timer5]
64
+  { TC0, 0, TC0_IRQn,  3}, // 0 - [servo timer5]
65 65
   { TC0, 1, TC1_IRQn,  0}, // 1
66 66
   { TC0, 2, TC2_IRQn,  0}, // 2
67 67
   { TC1, 0, TC3_IRQn,  2}, // 3 - stepper
68 68
   { TC1, 1, TC4_IRQn, 15}, // 4 - temperature
69
-  { TC1, 2, TC5_IRQn,  0}, // 5 - [servo timer3]
70
-  { TC2, 0, TC6_IRQn, 15}, // 6 - tone
69
+  { TC1, 2, TC5_IRQn,  3}, // 5 - [servo timer3]
70
+  { TC2, 0, TC6_IRQn, 14}, // 6 - tone
71 71
   { TC2, 1, TC7_IRQn,  0}, // 7
72 72
   { TC2, 2, TC8_IRQn,  0}, // 8
73 73
 };

+ 2
- 2
Marlin/src/HAL/HAL_DUE/HAL_timers_Due.h Целия файл

@@ -62,8 +62,6 @@ typedef uint32_t hal_timer_t;
62 62
 #define ENABLE_TEMPERATURE_INTERRUPT()  HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
63 63
 #define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
64 64
 
65
-#define HAL_ENABLE_ISRs() do { if (thermalManager.in_temp_isr) DISABLE_TEMPERATURE_INTERRUPT(); else ENABLE_TEMPERATURE_INTERRUPT(); ENABLE_STEPPER_DRIVER_INTERRUPT(); } while(0)
66
-
67 65
 #define HAL_STEP_TIMER_ISR  void TC3_Handler()
68 66
 #define HAL_TEMP_TIMER_ISR  void TC4_Handler()
69 67
 #define HAL_TONE_TIMER_ISR  void TC6_Handler()
@@ -127,4 +125,6 @@ FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
127 125
   pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_SR;
128 126
 }
129 127
 
128
+#define HAL_timer_isr_epilogue(TIMER_NUM)
129
+
130 130
 #endif // _HAL_TIMERS_DUE_H

+ 5
- 0
Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.cpp Целия файл

@@ -353,6 +353,11 @@
353 353
     // Install interrupt handler
354 354
     install_isr(HWUART_IRQ, UART_ISR);
355 355
 
356
+    // Configure priority. We need a very high priority to avoid losing characters
357
+    // and we need to be able to preempt the Stepper ISR and everything else!
358
+    // (this could probably be fixed by using DMA with the Serial port)
359
+    NVIC_SetPriority(HWUART_IRQ, 1);
360
+
356 361
     // Enable UART interrupt in NVIC
357 362
     NVIC_EnableIRQ(HWUART_IRQ);
358 363
 

+ 0
- 1
Marlin/src/HAL/HAL_LPC1768/HAL_timers.cpp Целия файл

@@ -90,5 +90,4 @@ void HAL_timer_isr_prologue(const uint8_t timer_num) {
90 90
   }
91 91
 }
92 92
 
93
-
94 93
 #endif // TARGET_LPC1768

+ 1
- 2
Marlin/src/HAL/HAL_LPC1768/HAL_timers.h Целия файл

@@ -65,8 +65,6 @@ typedef uint32_t hal_timer_t;
65 65
 #define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
66 66
 #define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
67 67
 
68
-#define HAL_ENABLE_ISRs() do { if (thermalManager.in_temp_isr) DISABLE_TEMPERATURE_INTERRUPT(); else ENABLE_TEMPERATURE_INTERRUPT(); ENABLE_STEPPER_DRIVER_INTERRUPT(); } while(0)
69
-
70 68
 #define HAL_STEP_TIMER_ISR  extern "C" void TIMER0_IRQHandler(void)
71 69
 #define HAL_TEMP_TIMER_ISR  extern "C" void TIMER1_IRQHandler(void)
72 70
 
@@ -129,5 +127,6 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num);
129 127
 void HAL_timer_disable_interrupt(const uint8_t timer_num);
130 128
 bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
131 129
 void HAL_timer_isr_prologue(const uint8_t timer_num);
130
+#define HAL_timer_isr_epilogue(TIMER_NUM)
132 131
 
133 132
 #endif // _HAL_TIMERS_DUE_H

+ 2
- 1
Marlin/src/HAL/HAL_STM32F1/HAL_timers_Stm32f1.h Целия файл

@@ -88,7 +88,6 @@ timer_dev* get_timer_dev(int number);
88 88
 
89 89
 #define HAL_timer_get_count(timer_num) timer_get_count(TIMER_DEV(timer_num))
90 90
 
91
-#define HAL_ENABLE_ISRs() do { if (thermalManager.in_temp_isr)DISABLE_TEMPERATURE_INTERRUPT(); else ENABLE_TEMPERATURE_INTERRUPT(); ENABLE_STEPPER_DRIVER_INTERRUPT(); } while(0)
92 91
 // TODO change this
93 92
 
94 93
 
@@ -175,4 +174,6 @@ FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
175 174
   }
176 175
 }
177 176
 
177
+#define HAL_timer_isr_epilogue(TIMER_NUM)
178
+
178 179
 #endif // _HAL_TIMERS_STM32F1_H

+ 1
- 1
Marlin/src/HAL/HAL_STM32F4/HAL_timers_STM32F4.h Целия файл

@@ -61,7 +61,6 @@
61 61
 #define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
62 62
 #define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
63 63
 
64
-#define HAL_ENABLE_ISRs() do { if (thermalManager.in_temp_isr)DISABLE_TEMPERATURE_INTERRUPT(); else ENABLE_TEMPERATURE_INTERRUPT(); ENABLE_STEPPER_DRIVER_INTERRUPT(); } while(0)
65 64
 // TODO change this
66 65
 
67 66
 
@@ -101,5 +100,6 @@ uint32_t HAL_timer_get_count(const uint8_t timer_num);
101 100
 void HAL_timer_restrain(const uint8_t timer_num, const uint16_t interval_ticks);
102 101
 
103 102
 void HAL_timer_isr_prologue(const uint8_t timer_num);
103
+#define HAL_timer_isr_epilogue(TIMER_NUM)
104 104
 
105 105
 #endif // _HAL_TIMERS_STM32F4_H

+ 1
- 1
Marlin/src/HAL/HAL_STM32F7/HAL_timers_STM32F7.h Целия файл

@@ -60,7 +60,6 @@
60 60
 #define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
61 61
 #define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
62 62
 
63
-#define HAL_ENABLE_ISRs() do { if (thermalManager.in_temp_isr)DISABLE_TEMPERATURE_INTERRUPT(); else ENABLE_TEMPERATURE_INTERRUPT(); ENABLE_STEPPER_DRIVER_INTERRUPT(); } while(0)
64 63
 // TODO change this
65 64
 
66 65
 
@@ -99,5 +98,6 @@ uint32_t HAL_timer_get_count(const uint8_t timer_num);
99 98
 void HAL_timer_restrain(const uint8_t timer_num, const uint16_t interval_ticks);
100 99
 
101 100
 void HAL_timer_isr_prologue(const uint8_t timer_num);
101
+#define HAL_timer_isr_epilogue(TIMER_NUM)
102 102
 
103 103
 #endif // _HAL_TIMERS_STM32F7_H

+ 1
- 2
Marlin/src/HAL/HAL_TEENSY35_36/HAL_timers_Teensy.h Целия файл

@@ -78,8 +78,6 @@ typedef uint32_t hal_timer_t;
78 78
 #define HAL_STEP_TIMER_ISR  extern "C" void ftm0_isr(void) //void TC3_Handler()
79 79
 #define HAL_TEMP_TIMER_ISR  extern "C" void ftm1_isr(void) //void TC4_Handler()
80 80
 
81
-#define HAL_ENABLE_ISRs() do { if (thermalManager.in_temp_isr) DISABLE_TEMPERATURE_INTERRUPT(); else ENABLE_TEMPERATURE_INTERRUPT(); ENABLE_STEPPER_DRIVER_INTERRUPT(); } while(0)
82
-
83 81
 void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
84 82
 
85 83
 FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
@@ -115,5 +113,6 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num);
115 113
 bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
116 114
 
117 115
 void HAL_timer_isr_prologue(const uint8_t timer_num);
116
+#define HAL_timer_isr_epilogue(TIMER_NUM)
118 117
 
119 118
 #endif // _HAL_TIMERS_TEENSY_H

+ 3
- 23
Marlin/src/module/stepper.cpp Целия файл

@@ -1144,11 +1144,14 @@ void Stepper::set_directions() {
1144 1144
 
1145 1145
 HAL_STEP_TIMER_ISR {
1146 1146
   HAL_timer_isr_prologue(STEP_TIMER_NUM);
1147
+
1147 1148
   #if ENABLED(LIN_ADVANCE)
1148 1149
     Stepper::advance_isr_scheduler();
1149 1150
   #else
1150 1151
     Stepper::isr();
1151 1152
   #endif
1153
+
1154
+  HAL_timer_isr_epilogue(STEP_TIMER_NUM);
1152 1155
 }
1153 1156
 
1154 1157
 void Stepper::isr() {
@@ -1156,15 +1159,6 @@ void Stepper::isr() {
1156 1159
   #define ENDSTOP_NOMINAL_OCR_VAL 1500 * HAL_TICKS_PER_US // Check endstops every 1.5ms to guarantee two stepper ISRs within 5ms for BLTouch
1157 1160
   #define OCR_VAL_TOLERANCE        500 * HAL_TICKS_PER_US // First max delay is 2.0ms, last min delay is 0.5ms, all others 1.5ms
1158 1161
 
1159
-  #if DISABLED(LIN_ADVANCE)
1160
-    // Disable Timer0 ISRs and enable global ISR again to capture UART events (incoming chars)
1161
-    DISABLE_TEMPERATURE_INTERRUPT(); // Temperature ISR
1162
-    DISABLE_STEPPER_DRIVER_INTERRUPT();
1163
-    #ifndef CPU_32_BIT
1164
-      sei();
1165
-    #endif
1166
-  #endif
1167
-
1168 1162
   hal_timer_t ocr_val;
1169 1163
   static uint32_t step_remaining = 0;  // SPLIT function always runs.  This allows 16 bit timers to be
1170 1164
                                        // used to generate the stepper ISR.
@@ -1191,7 +1185,6 @@ void Stepper::isr() {
1191 1185
 
1192 1186
     #if DISABLED(LIN_ADVANCE)
1193 1187
       HAL_timer_restrain(STEP_TIMER_NUM, STEP_TIMER_MIN_INTERVAL * HAL_TICKS_PER_US);
1194
-      HAL_ENABLE_ISRs();
1195 1188
     #endif
1196 1189
 
1197 1190
     return;
@@ -1215,7 +1208,6 @@ void Stepper::isr() {
1215 1208
     }
1216 1209
     current_block = NULL;                       // Prep to get a new block after cleaning
1217 1210
     _NEXT_ISR(HAL_STEPPER_TIMER_RATE / 10000);  // Run at max speed - 10 KHz
1218
-    HAL_ENABLE_ISRs();
1219 1211
     return;
1220 1212
   }
1221 1213
 
@@ -1291,7 +1283,6 @@ void Stepper::isr() {
1291 1283
         if (current_block->steps[Z_AXIS] > 0) {
1292 1284
           enable_Z();
1293 1285
           _NEXT_ISR(HAL_STEPPER_TIMER_RATE / 1000); // Run at slow speed - 1 KHz
1294
-          HAL_ENABLE_ISRs();
1295 1286
           return;
1296 1287
         }
1297 1288
       #endif
@@ -1299,7 +1290,6 @@ void Stepper::isr() {
1299 1290
     else {
1300 1291
       // If no more queued moves, postpone next check for 1mS
1301 1292
       _NEXT_ISR(HAL_STEPPER_TIMER_RATE / 1000); // Run at slow speed - 1 KHz
1302
-      HAL_ENABLE_ISRs();
1303 1293
       return;
1304 1294
     }
1305 1295
   }
@@ -1631,9 +1621,6 @@ void Stepper::isr() {
1631 1621
     current_block = NULL;
1632 1622
     planner.discard_current_block();
1633 1623
   }
1634
-  #if DISABLED(LIN_ADVANCE)
1635
-    HAL_ENABLE_ISRs();
1636
-  #endif
1637 1624
 }
1638 1625
 
1639 1626
 #if ENABLED(LIN_ADVANCE)
@@ -1755,10 +1742,6 @@ void Stepper::isr() {
1755 1742
   }
1756 1743
 
1757 1744
   void Stepper::advance_isr_scheduler() {
1758
-    // Disable Timer0 ISRs and enable global ISR again to capture UART events (incoming chars)
1759
-    DISABLE_TEMPERATURE_INTERRUPT(); // Temperature ISR
1760
-    DISABLE_STEPPER_DRIVER_INTERRUPT();
1761
-    sei();
1762 1745
 
1763 1746
     // Run main stepping ISR if flagged
1764 1747
     if (!nextMainISR) isr();
@@ -1787,9 +1770,6 @@ void Stepper::isr() {
1787 1770
 
1788 1771
     // Make sure stepper ISR doesn't monopolize the CPU
1789 1772
     HAL_timer_restrain(STEP_TIMER_NUM, STEP_TIMER_MIN_INTERVAL * HAL_TICKS_PER_US);
1790
-
1791
-    // Restore original ISR settings
1792
-    HAL_ENABLE_ISRs();
1793 1773
   }
1794 1774
 
1795 1775
 #endif // LIN_ADVANCE

+ 4
- 20
Marlin/src/module/temperature.cpp Целия файл

@@ -1219,11 +1219,10 @@ void Temperature::init() {
1219 1219
     // Use timer0 for temperature measurement
1220 1220
     // Interleave temperature interrupt with millies interrupt
1221 1221
     OCR0B = 128;
1222
-    SBI(TIMSK0, OCIE0B);
1223 1222
   #else
1224 1223
     HAL_timer_start(TEMP_TIMER_NUM, TEMP_TIMER_FREQUENCY);
1225
-    HAL_timer_enable_interrupt(TEMP_TIMER_NUM);
1226 1224
   #endif
1225
+  ENABLE_TEMPERATURE_INTERRUPT();
1227 1226
 
1228 1227
   #if HAS_AUTO_FAN_0
1229 1228
     #if E0_AUTO_FAN_PIN == FAN1_PIN
@@ -1716,22 +1715,13 @@ void Temperature::set_current_temp_raw() {
1716 1715
  */
1717 1716
 HAL_TEMP_TIMER_ISR {
1718 1717
   HAL_timer_isr_prologue(TEMP_TIMER_NUM);
1718
+
1719 1719
   Temperature::isr();
1720
-}
1721 1720
 
1722
-volatile bool Temperature::in_temp_isr = false;
1721
+  HAL_timer_isr_epilogue(TEMP_TIMER_NUM);
1722
+}
1723 1723
 
1724 1724
 void Temperature::isr() {
1725
-  // The stepper ISR can interrupt this ISR. When it does it re-enables this ISR
1726
-  // at the end of its run, potentially causing re-entry. This flag prevents it.
1727
-  if (in_temp_isr) return;
1728
-  in_temp_isr = true;
1729
-
1730
-  // Allow UART and stepper ISRs
1731
-  DISABLE_TEMPERATURE_INTERRUPT(); //Disable Temperature ISR
1732
-  #ifndef CPU_32_BIT
1733
-    sei();
1734
-  #endif
1735 1725
 
1736 1726
   static int8_t temp_count = -1;
1737 1727
   static ADCSensorState adc_sensor_state = StartupDelay;
@@ -2255,12 +2245,6 @@ void Temperature::isr() {
2255 2245
       e_hit--;
2256 2246
     }
2257 2247
   #endif
2258
-
2259
-  #ifndef CPU_32_BIT
2260
-    cli();
2261
-  #endif
2262
-  in_temp_isr = false;
2263
-  ENABLE_TEMPERATURE_INTERRUPT(); //re-enable Temperature ISR
2264 2248
 }
2265 2249
 
2266 2250
 #if HAS_TEMP_SENSOR

Loading…
Отказ
Запис