瀏覽代碼

🐛 Resolve DUE Servo pulse issue (#24305)

Co-authored-by: sjasonsmith <20053467+sjasonsmith@users.noreply.github.com>
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
InsanityAutomation 2 年之前
父節點
當前提交
757d66e2c5
No account linked to committer's email address

+ 105
- 95
Marlin/src/HAL/AVR/Servo.cpp 查看文件

@@ -67,26 +67,25 @@ static volatile int8_t Channel[_Nbr_16timers];              // counter for the s
67 67
 /************ static functions common to all instances ***********************/
68 68
 
69 69
 static inline void handle_interrupts(const timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
70
-  if (Channel[timer] < 0)
71
-    *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
72
-  else {
73
-    if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
74
-      extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
75
-  }
76
-
77
-  Channel[timer]++;    // increment to the next channel
78
-  if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
79
-    *OCRnA = *TCNTn + SERVO(timer, Channel[timer]).ticks;
80
-    if (SERVO(timer, Channel[timer]).Pin.isActive)    // check if activated
81
-      extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high
70
+  int8_t cho = Channel[timer];                                        // Handle the prior Channel[timer] first
71
+  if (cho < 0)                                                        // Channel -1 indicates the refresh interval completed...
72
+    *TCNTn = 0;                                                       // ...so reset the timer
73
+  else if (SERVO_INDEX(timer, cho) < ServoCount)                      // prior channel handled?
74
+    extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW);                  // pulse the prior channel LOW
75
+
76
+  Channel[timer] = ++cho;                                             // Handle the next channel (or 0)
77
+  if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
78
+    *OCRnA = *TCNTn + SERVO(timer, cho).ticks;                        // set compare to current ticks plus duration
79
+    if (SERVO(timer, cho).Pin.isActive)                               // activated?
80
+      extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH);               // yes: pulse HIGH
82 81
   }
83 82
   else {
84 83
     // finished all channels so wait for the refresh period to expire before starting over
85
-    if (((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL))    // allow a few ticks to ensure the next OCR1A not missed
86
-      *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
87
-    else
88
-      *OCRnA = *TCNTn + 4;  // at least REFRESH_INTERVAL has elapsed
89
-    Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
84
+    const unsigned int cval = ((unsigned)*TCNTn) + 32 / (SERVO_TIMER_PRESCALER), // allow 32 cycles to ensure the next OCR1A not missed
85
+                       ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
86
+    *OCRnA = max(cval, ival);
87
+
88
+    Channel[timer] = -1;                                              // reset the timer counter to 0 on the next call
90 89
   }
91 90
 }
92 91
 
@@ -123,91 +122,102 @@ static inline void handle_interrupts(const timer16_Sequence_t timer, volatile ui
123 122
 
124 123
 /****************** end of static functions ******************************/
125 124
 
126
-void initISR(timer16_Sequence_t timer) {
127
-  #ifdef _useTimer1
128
-    if (timer == _timer1) {
129
-      TCCR1A = 0;             // normal counting mode
130
-      TCCR1B = _BV(CS11);     // set prescaler of 8
131
-      TCNT1 = 0;              // clear the timer count
132
-      #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
133
-        SBI(TIFR, OCF1A);      // clear any pending interrupts;
134
-        SBI(TIMSK, OCIE1A);    // enable the output compare interrupt
135
-      #else
136
-        // here if not ATmega8 or ATmega128
137
-        SBI(TIFR1, OCF1A);     // clear any pending interrupts;
138
-        SBI(TIMSK1, OCIE1A);   // enable the output compare interrupt
139
-      #endif
140
-      #ifdef WIRING
141
-        timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
142
-      #endif
143
-    }
144
-  #endif
145
-
146
-  #ifdef _useTimer3
147
-    if (timer == _timer3) {
148
-      TCCR3A = 0;             // normal counting mode
149
-      TCCR3B = _BV(CS31);     // set prescaler of 8
150
-      TCNT3 = 0;              // clear the timer count
151
-      #ifdef __AVR_ATmega128__
152
-        SBI(TIFR, OCF3A);     // clear any pending interrupts;
153
-        SBI(ETIMSK, OCIE3A);  // enable the output compare interrupt
154
-      #else
155
-        SBI(TIFR3, OCF3A);   // clear any pending interrupts;
156
-        SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
157
-      #endif
158
-      #ifdef WIRING
159
-        timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service);  // for Wiring platform only
160
-      #endif
161
-    }
162
-  #endif
163
-
164
-  #ifdef _useTimer4
165
-    if (timer == _timer4) {
166
-      TCCR4A = 0;             // normal counting mode
167
-      TCCR4B = _BV(CS41);     // set prescaler of 8
168
-      TCNT4 = 0;              // clear the timer count
169
-      TIFR4 = _BV(OCF4A);     // clear any pending interrupts;
170
-      TIMSK4 = _BV(OCIE4A);   // enable the output compare interrupt
171
-    }
172
-  #endif
173
-
174
-  #ifdef _useTimer5
175
-    if (timer == _timer5) {
176
-      TCCR5A = 0;             // normal counting mode
177
-      TCCR5B = _BV(CS51);     // set prescaler of 8
178
-      TCNT5 = 0;              // clear the timer count
179
-      TIFR5 = _BV(OCF5A);     // clear any pending interrupts;
180
-      TIMSK5 = _BV(OCIE5A);   // enable the output compare interrupt
181
-    }
182
-  #endif
183
-}
184
-
185
-void finISR(timer16_Sequence_t timer) {
186
-  // Disable use of the given timer
187
-  #ifdef WIRING
188
-    if (timer == _timer1) {
189
-      CBI(
190
-        #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
191
-          TIMSK1
125
+void initISR(const timer16_Sequence_t timer_index) {
126
+  switch (timer_index) {
127
+    default: break;
128
+
129
+    #ifdef _useTimer1
130
+      case _timer1:
131
+        TCCR1A = 0;             // normal counting mode
132
+        TCCR1B = _BV(CS11);     // set prescaler of 8
133
+        TCNT1 = 0;              // clear the timer count
134
+        #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
135
+          SBI(TIFR, OCF1A);      // clear any pending interrupts;
136
+          SBI(TIMSK, OCIE1A);    // enable the output compare interrupt
192 137
         #else
193
-          TIMSK
138
+          // here if not ATmega8 or ATmega128
139
+          SBI(TIFR1, OCF1A);     // clear any pending interrupts;
140
+          SBI(TIMSK1, OCIE1A);   // enable the output compare interrupt
194 141
         #endif
195
-          , OCIE1A);    // disable timer 1 output compare interrupt
196
-      timerDetach(TIMER1OUTCOMPAREA_INT);
197
-    }
198
-    else if (timer == _timer3) {
199
-      CBI(
200
-        #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
201
-          TIMSK3
142
+        #ifdef WIRING
143
+          timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
144
+        #endif
145
+        break;
146
+    #endif
147
+
148
+    #ifdef _useTimer3
149
+      case _timer3:
150
+        TCCR3A = 0;             // normal counting mode
151
+        TCCR3B = _BV(CS31);     // set prescaler of 8
152
+        TCNT3 = 0;              // clear the timer count
153
+        #ifdef __AVR_ATmega128__
154
+          SBI(TIFR, OCF3A);     // clear any pending interrupts;
155
+          SBI(ETIMSK, OCIE3A);  // enable the output compare interrupt
202 156
         #else
203
-          ETIMSK
157
+          SBI(TIFR3, OCF3A);   // clear any pending interrupts;
158
+          SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
159
+        #endif
160
+        #ifdef WIRING
161
+          timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service);  // for Wiring platform only
204 162
         #endif
205
-          , OCIE3A);    // disable the timer3 output compare A interrupt
206
-      timerDetach(TIMER3OUTCOMPAREA_INT);
163
+        break;
164
+    #endif
165
+
166
+    #ifdef _useTimer4
167
+      case _timer4:
168
+        TCCR4A = 0;             // normal counting mode
169
+        TCCR4B = _BV(CS41);     // set prescaler of 8
170
+        TCNT4 = 0;              // clear the timer count
171
+        TIFR4 = _BV(OCF4A);     // clear any pending interrupts;
172
+        TIMSK4 = _BV(OCIE4A);   // enable the output compare interrupt
173
+        break;
174
+    #endif
175
+
176
+    #ifdef _useTimer5
177
+      case _timer5:
178
+        TCCR5A = 0;             // normal counting mode
179
+        TCCR5B = _BV(CS51);     // set prescaler of 8
180
+        TCNT5 = 0;              // clear the timer count
181
+        TIFR5 = _BV(OCF5A);     // clear any pending interrupts;
182
+        TIMSK5 = _BV(OCIE5A);   // enable the output compare interrupt
183
+        break;
184
+    #endif
185
+  }
186
+}
187
+
188
+void finISR(const timer16_Sequence_t timer_index) {
189
+  // Disable use of the given timer
190
+  #ifdef WIRING
191
+    switch (timer_index) {
192
+      default: break;
193
+
194
+      case _timer1:
195
+        CBI(
196
+          #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
197
+            TIMSK1
198
+          #else
199
+            TIMSK
200
+          #endif
201
+          , OCIE1A    // disable timer 1 output compare interrupt
202
+        );
203
+        timerDetach(TIMER1OUTCOMPAREA_INT);
204
+        break;
205
+
206
+      case _timer3:
207
+        CBI(
208
+          #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
209
+            TIMSK3
210
+          #else
211
+            ETIMSK
212
+          #endif
213
+          , OCIE3A    // disable the timer3 output compare A interrupt
214
+        );
215
+        timerDetach(TIMER3OUTCOMPAREA_INT);
216
+        break;
207 217
     }
208 218
   #else // !WIRING
209 219
     // For arduino - in future: call here to a currently undefined function to reset the timer
210
-    UNUSED(timer);
220
+    UNUSED(timer_index);
211 221
   #endif
212 222
 }
213 223
 

+ 69
- 60
Marlin/src/HAL/DUE/Servo.cpp 查看文件

@@ -47,7 +47,7 @@
47 47
 #include "../shared/servo.h"
48 48
 #include "../shared/servo_private.h"
49 49
 
50
-static volatile int8_t Channel[_Nbr_16timers];              // counter for the servo being pulsed for each timer (or -1 if refresh interval)
50
+static Flags<_Nbr_16timers> DisablePending; // ISR should disable the timer at the next timer reset
51 51
 
52 52
 // ------------------------
53 53
 /// Interrupt handler for the TC0 channel 1.
@@ -71,82 +71,91 @@ void Servo_Handler(const timer16_Sequence_t, Tc*, const uint8_t);
71 71
 #endif
72 72
 
73 73
 void Servo_Handler(const timer16_Sequence_t timer, Tc *tc, const uint8_t channel) {
74
-  // clear interrupt
75
-  tc->TC_CHANNEL[channel].TC_SR;
76
-  if (Channel[timer] < 0)
77
-    tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // channel set to -1 indicated that refresh interval completed so reset the timer
78
-  else if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
79
-    extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
80
-
81
-  Channel[timer]++;    // increment to the next channel
82
-  if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
83
-    tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer,Channel[timer]).ticks;
84
-    if (SERVO(timer,Channel[timer]).Pin.isActive)    // check if activated
85
-      extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // its an active channel so pulse it high
74
+  static int8_t Channel[_Nbr_16timers];                               // Servo counters to pulse (or -1 for refresh interval)
75
+  int8_t cho = Channel[timer];                                        // Handle the prior Channel[timer] first
76
+  if (cho < 0) {                                                      // Channel -1 indicates the refresh interval completed...
77
+    tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG;                   // ...so reset the timer
78
+    if (DisablePending[timer]) {
79
+      // Disabling only after the full servo period expires prevents
80
+      // pulses being too close together if immediately re-enabled.
81
+      DisablePending.clear(timer);
82
+      TC_Stop(tc, channel);
83
+      tc->TC_CHANNEL[channel].TC_SR;                                  // clear interrupt
84
+      return;
85
+    }
86
+  }
87
+  else if (SERVO_INDEX(timer, cho) < ServoCount)                      // prior channel handled?
88
+    extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW);                  // pulse the prior channel LOW
89
+
90
+  Channel[timer] = ++cho;                                             // go to the next channel (or 0)
91
+  if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
92
+    tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer, cho).ticks;
93
+    if (SERVO(timer, cho).Pin.isActive)                               // activated?
94
+      extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH);               // yes: pulse HIGH
86 95
   }
87 96
   else {
88 97
     // finished all channels so wait for the refresh period to expire before starting over
89
-    tc->TC_CHANNEL[channel].TC_RA =
90
-      tc->TC_CHANNEL[channel].TC_CV < usToTicks(REFRESH_INTERVAL) - 4
91
-        ? (unsigned int)usToTicks(REFRESH_INTERVAL) // allow a few ticks to ensure the next OCR1A not missed
92
-        : tc->TC_CHANNEL[channel].TC_CV + 4;        // at least REFRESH_INTERVAL has elapsed
93
-    Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
98
+    const unsigned int cval = tc->TC_CHANNEL[channel].TC_CV + 128 / (SERVO_TIMER_PRESCALER), // allow 128 cycles to ensure the next CV not missed
99
+                       ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
100
+    tc->TC_CHANNEL[channel].TC_RA = max(cval, ival);
101
+
102
+    Channel[timer] = -1;                                              // reset the timer CCR on the next call
94 103
   }
104
+
105
+  tc->TC_CHANNEL[channel].TC_SR;                                      // clear interrupt
95 106
 }
96 107
 
97 108
 static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn) {
98 109
   pmc_enable_periph_clk(id);
99 110
   TC_Configure(tc, channel,
100
-    TC_CMR_TCCLKS_TIMER_CLOCK3 | // MCK/32
101
-    TC_CMR_WAVE |                // Waveform mode
102
-    TC_CMR_WAVSEL_UP_RC );       // Counter running up and reset when equals to RC
103
-
104
-  /* 84MHz, MCK/32, for 1.5ms: 3937 */
105
-  TC_SetRA(tc, channel, 2625); // 1ms
106
-
107
-  /* Configure and enable interrupt */
111
+      TC_CMR_WAVE                   // Waveform mode
112
+    | TC_CMR_WAVSEL_UP_RC           // Counter running up and reset when equal to RC
113
+    | (SERVO_TIMER_PRESCALER ==   2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0) // MCK/2
114
+    | (SERVO_TIMER_PRESCALER ==   8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0) // MCK/8
115
+    | (SERVO_TIMER_PRESCALER ==  32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0) // MCK/32
116
+    | (SERVO_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0) // MCK/128
117
+  );
118
+
119
+  // Wait 1ms before the first ISR
120
+  TC_SetRA(tc, channel, (F_CPU) / (SERVO_TIMER_PRESCALER) / 1000UL); // 1ms
121
+
122
+  // Configure and enable interrupt
108 123
   NVIC_EnableIRQ(irqn);
109
-  // TC_IER_CPAS: RA Compare
110
-  tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS;
124
+  tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS; // TC_IER_CPAS: RA Compare
111 125
 
112 126
   // Enables the timer clock and performs a software reset to start the counting
113 127
   TC_Start(tc, channel);
114 128
 }
115 129
 
116
-void initISR(const timer16_Sequence_t timer) {
117
-  #ifdef _useTimer1
118
-    if (timer == _timer1) _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
119
-  #endif
120
-  #ifdef _useTimer2
121
-    if (timer == _timer2) _initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
122
-  #endif
123
-  #ifdef _useTimer3
124
-    if (timer == _timer3) _initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
125
-  #endif
126
-  #ifdef _useTimer4
127
-    if (timer == _timer4) _initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
128
-  #endif
129
-  #ifdef _useTimer5
130
-    if (timer == _timer5) _initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
131
-  #endif
130
+void initISR(const timer16_Sequence_t timer_index) {
131
+  CRITICAL_SECTION_START();
132
+  const bool disable_soon = DisablePending[timer_index];
133
+  DisablePending.clear(timer_index);
134
+  CRITICAL_SECTION_END();
135
+
136
+  if (!disable_soon) switch (timer_index) {
137
+    default: break;
138
+    #ifdef _useTimer1
139
+      case _timer1: return _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
140
+    #endif
141
+    #ifdef _useTimer2
142
+      case _timer2: return _initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
143
+    #endif
144
+    #ifdef _useTimer3
145
+      case _timer3: return _initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
146
+    #endif
147
+    #ifdef _useTimer4
148
+      case _timer4: return _initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
149
+    #endif
150
+    #ifdef _useTimer5
151
+      case _timer5: return _initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
152
+    #endif
153
+  }
132 154
 }
133 155
 
134
-void finISR(timer16_Sequence_t) {
135
-  #ifdef _useTimer1
136
-    TC_Stop(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1);
137
-  #endif
138
-  #ifdef _useTimer2
139
-    TC_Stop(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2);
140
-  #endif
141
-  #ifdef _useTimer3
142
-    TC_Stop(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3);
143
-  #endif
144
-  #ifdef _useTimer4
145
-    TC_Stop(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4);
146
-  #endif
147
-  #ifdef _useTimer5
148
-    TC_Stop(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5);
149
-  #endif
156
+void finISR(const timer16_Sequence_t timer_index) {
157
+  // Timer is disabled from the ISR, to ensure proper final pulse length.
158
+  DisablePending.set(timer_index);
150 159
 }
151 160
 
152 161
 #endif // HAS_SERVOS

+ 1
- 1
Marlin/src/HAL/DUE/ServoTimers.h 查看文件

@@ -37,7 +37,7 @@
37 37
 #define _useTimer5
38 38
 
39 39
 #define TRIM_DURATION             2   // compensation ticks to trim adjust for digitalWrite delays
40
-#define SERVO_TIMER_PRESCALER     32  // timer prescaler
40
+#define SERVO_TIMER_PRESCALER     2   // timer prescaler
41 41
 
42 42
 /*
43 43
   TC0, chan 0 => TC0_Handler

+ 9
- 2
Marlin/src/HAL/DUE/timers.cpp 查看文件

@@ -89,10 +89,17 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
89 89
   NVIC_SetPriority(irq, timer_config[timer_num].priority);
90 90
 
91 91
   // wave mode, reset counter on match with RC,
92
-  TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1);
92
+  TC_Configure(tc, channel,
93
+      TC_CMR_WAVE
94
+    | TC_CMR_WAVSEL_UP_RC
95
+    | (HAL_TIMER_PRESCALER ==   2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0)
96
+    | (HAL_TIMER_PRESCALER ==   8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0)
97
+    | (HAL_TIMER_PRESCALER ==  32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0)
98
+    | (HAL_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0)
99
+  );
93 100
 
94 101
   // Set compare value
95
-  TC_SetRC(tc, channel, VARIANT_MCK / 2 / frequency);
102
+  TC_SetRC(tc, channel, VARIANT_MCK / (HAL_TIMER_PRESCALER) / frequency);
96 103
 
97 104
   // And start timer
98 105
   TC_Start(tc, channel);

+ 2
- 1
Marlin/src/HAL/DUE/timers.h 查看文件

@@ -35,7 +35,8 @@
35 35
 typedef uint32_t hal_timer_t;
36 36
 #define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
37 37
 
38
-#define HAL_TIMER_RATE         ((F_CPU) / 2)    // frequency of timers peripherals
38
+#define HAL_TIMER_PRESCALER    2
39
+#define HAL_TIMER_RATE         ((F_CPU) / (HAL_TIMER_PRESCALER))  // frequency of timers peripherals
39 40
 
40 41
 #ifndef MF_TIMER_STEP
41 42
   #define MF_TIMER_STEP         2  // Timer Index for Stepper

+ 18
- 25
Marlin/src/HAL/SAMD51/Servo.cpp 查看文件

@@ -77,7 +77,8 @@ HAL_SERVO_TIMER_ISR() {
77 77
   ;
78 78
   const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
79 79
 
80
-  if (currentServoIndex[timer] < 0) {
80
+  int8_t cho = currentServoIndex[timer];                // Handle the prior servo first
81
+  if (cho < 0) {                                        // Servo -1 indicates the refresh interval completed...
81 82
     #if defined(_useTimer1) && defined(_useTimer2)
82 83
       if (currentServoIndex[timer ^ 1] >= 0) {
83 84
         // Wait for both channels
@@ -86,41 +87,33 @@ HAL_SERVO_TIMER_ISR() {
86 87
         return;
87 88
       }
88 89
     #endif
89
-    tc->COUNT16.COUNT.reg = TC_COUNTER_START_VAL;
90
+    tc->COUNT16.COUNT.reg = TC_COUNTER_START_VAL;       // ...so reset the timer
90 91
     SYNC(tc->COUNT16.SYNCBUSY.bit.COUNT);
91 92
   }
92
-  else if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && SERVO(timer, currentServoIndex[timer]).Pin.isActive)
93
-    digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, LOW);      // pulse this channel low if activated
94
-
95
-  // Select the next servo controlled by this timer
96
-  currentServoIndex[timer]++;
93
+  else if (SERVO_INDEX(timer, cho) < ServoCount)        // prior channel handled?
94
+    digitalWrite(SERVO(timer, cho).Pin.nbr, LOW);       // pulse the prior channel LOW
97 95
 
98
-  if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && currentServoIndex[timer] < SERVOS_PER_TIMER) {
99
-    if (SERVO(timer, currentServoIndex[timer]).Pin.isActive)                // check if activated
100
-      digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, HIGH);   // it's an active channel so pulse it high
96
+  currentServoIndex[timer] = ++cho;                     // go to the next channel (or 0)
97
+  if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
98
+    if (SERVO(timer, cho).Pin.isActive)                 // activated?
99
+      digitalWrite(SERVO(timer, cho).Pin.nbr, HIGH);    // yes: pulse HIGH
101 100
 
102
-    tc->COUNT16.CC[tcChannel].reg = getTimerCount() - (uint16_t)SERVO(timer, currentServoIndex[timer]).ticks;
101
+    tc->COUNT16.CC[tcChannel].reg = getTimerCount() - (uint16_t)SERVO(timer, cho).ticks;
103 102
   }
104 103
   else {
105 104
     // finished all channels so wait for the refresh period to expire before starting over
106
-    currentServoIndex[timer] = -1;   // this will get incremented at the end of the refresh period to start again at the first channel
107
-
108
-    const uint16_t tcCounterValue = getTimerCount();
109
-
110
-    if ((TC_COUNTER_START_VAL - tcCounterValue) + 4UL < usToTicks(REFRESH_INTERVAL))  // allow a few ticks to ensure the next OCR1A not missed
111
-      tc->COUNT16.CC[tcChannel].reg = TC_COUNTER_START_VAL - (uint16_t)usToTicks(REFRESH_INTERVAL);
112
-    else
113
-      tc->COUNT16.CC[tcChannel].reg = (uint16_t)(tcCounterValue - 4UL);               // at least REFRESH_INTERVAL has elapsed
105
+    currentServoIndex[timer] = -1;                                          // reset the timer COUNT.reg on the next call
106
+    const uint16_t cval = getTimerCount() - 256 / (SERVO_TIMER_PRESCALER),  // allow 256 cycles to ensure the next CV not missed
107
+                   ival = (TC_COUNTER_START_VAL) - (uint16_t)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
108
+    tc->COUNT16.CC[tcChannel].reg = min(cval, ival);
114 109
   }
115 110
   if (tcChannel == 0) {
116 111
     SYNC(tc->COUNT16.SYNCBUSY.bit.CC0);
117
-    // Clear the interrupt
118
-    tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0;
112
+    tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0; // Clear the interrupt
119 113
   }
120 114
   else {
121 115
     SYNC(tc->COUNT16.SYNCBUSY.bit.CC1);
122
-    // Clear the interrupt
123
-    tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC1;
116
+    tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC1; // Clear the interrupt
124 117
   }
125 118
 }
126 119
 
@@ -201,9 +194,9 @@ void initISR(const timer16_Sequence_t timer) {
201 194
   }
202 195
 }
203 196
 
204
-void finISR(const timer16_Sequence_t timer) {
197
+void finISR(const timer16_Sequence_t timer_index) {
205 198
   Tc * const tc = timer_config[SERVO_TC].pTc;
206
-  const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
199
+  const uint8_t tcChannel = TIMER_TCCHANNEL(timer_index);
207 200
 
208 201
   // Disable the match channel interrupt request
209 202
   tc->COUNT16.INTENCLR.reg = (tcChannel == 0) ? TC_INTENCLR_MC0 : TC_INTENCLR_MC1;

+ 2
- 2
Marlin/src/HAL/shared/servo_private.h 查看文件

@@ -94,5 +94,5 @@ extern ServoInfo_t servo_info[MAX_SERVOS];
94 94
 
95 95
 // Public functions
96 96
 
97
-extern void initISR(const timer16_Sequence_t timer);
98
-extern void finISR(const timer16_Sequence_t timer);
97
+void initISR(const timer16_Sequence_t timer_index);
98
+void finISR(const timer16_Sequence_t timer_index);

+ 2
- 2
Marlin/src/core/serial.cpp 查看文件

@@ -72,8 +72,8 @@ void serial_print_P(PGM_P str) {
72 72
   while (const char c = pgm_read_byte(str++)) SERIAL_CHAR(c);
73 73
 }
74 74
 
75
-void serial_echo_start()  { static PGMSTR(echomagic, "echo:"); serial_print_P(echomagic); }
76
-void serial_error_start() { static PGMSTR(errormagic, "Error:"); serial_print_P(errormagic); }
75
+void serial_echo_start()  { serial_print(F("echo:")); }
76
+void serial_error_start() { serial_print(F("Error:")); }
77 77
 
78 78
 void serial_spaces(uint8_t count) { count *= (PROPORTIONAL_FONT_RATIO); while (count--) SERIAL_CHAR(' '); }
79 79
 

+ 4
- 4
Marlin/src/core/types.h 查看文件

@@ -99,8 +99,8 @@ struct Flags {
99 99
   void set(const int n)                    { b |=  (bits_t)_BV(n); }
100 100
   void clear(const int n)                  { b &= ~(bits_t)_BV(n); }
101 101
   bool test(const int n) const             { return TEST(b, n); }
102
-  bool operator[](const int n)             { return test(n); }
103
-  bool operator[](const int n) const       { return test(n); }
102
+  const bool operator[](const int n)       { return test(n); }
103
+  const bool operator[](const int n) const { return test(n); }
104 104
   int size() const                         { return sizeof(b); }
105 105
 };
106 106
 
@@ -113,8 +113,8 @@ struct Flags<1> {
113 113
   void set(const int)                     { b = true; }
114 114
   void clear(const int)                   { b = false; }
115 115
   bool test(const int) const              { return b; }
116
-  bool operator[](const int)              { return b; }
117
-  bool operator[](const int) const        { return b; }
116
+  bool& operator[](const int)             { return b; }
117
+  bool  operator[](const int) const       { return b; }
118 118
   int size() const                        { return sizeof(b); }
119 119
 };
120 120
 

Loading…
取消
儲存