ソースを参照

Merge pull request #10983 from thinkyhead/bf2_xon_xoff_changes

[2.0.x] Serial handshaking fixes / debug
Scott Lahteine 6年前
コミット
ae15c5af88
コミッターのメールアドレスに関連付けられたアカウントが存在しません

+ 282
- 158
Marlin/src/HAL/HAL_AVR/MarlinSerial.cpp ファイルの表示

56
     ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
56
     ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
57
     #if TX_BUFFER_SIZE > 0
57
     #if TX_BUFFER_SIZE > 0
58
       ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
58
       ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
59
-      static bool _written;
60
     #endif
59
     #endif
60
+    static bool _written;
61
   #endif
61
   #endif
62
 
62
 
63
   #if ENABLED(SERIAL_XON_XOFF)
63
   #if ENABLED(SERIAL_XON_XOFF)
64
-    constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80;  // XON / XOFF Character was sent
65
-    constexpr uint8_t XON_XOFF_CHAR_MASK = 0x1F;  // XON / XOFF character to send
64
+    constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80,  // XON / XOFF Character was sent
65
+                      XON_XOFF_CHAR_MASK = 0x1F;  // XON / XOFF character to send
66
     // XON / XOFF character definitions
66
     // XON / XOFF character definitions
67
-    constexpr uint8_t XON_CHAR  = 17;
68
-    constexpr uint8_t XOFF_CHAR = 19;
67
+    constexpr uint8_t XON_CHAR  = 17, XOFF_CHAR = 19;
69
     uint8_t xon_xoff_state = XON_XOFF_CHAR_SENT | XON_CHAR;
68
     uint8_t xon_xoff_state = XON_XOFF_CHAR_SENT | XON_CHAR;
70
   #endif
69
   #endif
71
 
70
 
73
     uint8_t rx_dropped_bytes = 0;
72
     uint8_t rx_dropped_bytes = 0;
74
   #endif
73
   #endif
75
 
74
 
75
+  #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
76
+    uint8_t rx_buffer_overruns = 0;
77
+  #endif
78
+
79
+  #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
80
+    uint8_t rx_framing_errors = 0;
81
+  #endif
82
+
76
   #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
83
   #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
77
     ring_buffer_pos_t rx_max_enqueued = 0;
84
     ring_buffer_pos_t rx_max_enqueued = 0;
78
   #endif
85
   #endif
91
       static EmergencyParser::State emergency_state; // = EP_RESET
98
       static EmergencyParser::State emergency_state; // = EP_RESET
92
     #endif
99
     #endif
93
 
100
 
94
-    const ring_buffer_pos_t h = rx_buffer.head,
95
-                            i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
101
+    // Get the tail - Nothing can alter its value while we are at this ISR
102
+    const ring_buffer_pos_t t = rx_buffer.tail;
103
+
104
+    // Get the head pointer
105
+    ring_buffer_pos_t h = rx_buffer.head;
106
+
107
+    // Get the next element
108
+    ring_buffer_pos_t i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
96
 
109
 
97
-    // Read the character
98
-    const uint8_t c = M_UDRx;
110
+    // This must read the M_UCSRxA register before reading the received byte to detect error causes
111
+    #if ENABLED(SERIAL_STATS_DROPPED_RX)
112
+      if (TEST(M_UCSRxA, M_DORx) && !++rx_dropped_bytes) --rx_dropped_bytes;
113
+    #endif
114
+
115
+    #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
116
+      if (TEST(M_UCSRxA, M_DORx) && !++rx_buffer_overruns) --rx_buffer_overruns;
117
+    #endif
118
+
119
+    #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
120
+      if (TEST(M_UCSRxA, M_FEx) && !++rx_framing_errors) --rx_framing_errors;
121
+    #endif
122
+
123
+    // Read the character from the USART
124
+    uint8_t c = M_UDRx;
125
+
126
+    #if ENABLED(EMERGENCY_PARSER)
127
+      emergency_parser.update(emergency_state, c);
128
+    #endif
99
 
129
 
100
     // If the character is to be stored at the index just before the tail
130
     // If the character is to be stored at the index just before the tail
101
-    // (such that the head would advance to the current tail), the buffer is
102
-    // critical, so don't write the character or advance the head.
103
-    if (i != rx_buffer.tail) {
131
+    // (such that the head would advance to the current tail), the RX FIFO is
132
+    // full, so don't write the character or advance the head.
133
+    if (i != t) {
104
       rx_buffer.buffer[h] = c;
134
       rx_buffer.buffer[h] = c;
105
-      rx_buffer.head = i;
106
-    }
107
-    else {
108
-      #if ENABLED(SERIAL_STATS_DROPPED_RX)
109
-        if (!++rx_dropped_bytes) ++rx_dropped_bytes;
110
-      #endif
135
+      h = i;
111
     }
136
     }
137
+    #if ENABLED(SERIAL_STATS_DROPPED_RX)
138
+      else if (!++rx_dropped_bytes) --rx_dropped_bytes;
139
+    #endif
112
 
140
 
113
     #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
141
     #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
114
-      // calculate count of bytes stored into the RX buffer
115
-      ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(rx_buffer.head - rx_buffer.tail) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
142
+      // Calculate count of bytes stored into the RX buffer
143
+      const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
144
+
116
       // Keep track of the maximum count of enqueued bytes
145
       // Keep track of the maximum count of enqueued bytes
117
       NOLESS(rx_max_enqueued, rx_count);
146
       NOLESS(rx_max_enqueued, rx_count);
118
     #endif
147
     #endif
119
 
148
 
120
     #if ENABLED(SERIAL_XON_XOFF)
149
     #if ENABLED(SERIAL_XON_XOFF)
121
-
122
-      // for high speed transfers, we can use XON/XOFF protocol to do
123
-      // software handshake and avoid overruns.
150
+      // If the last char that was sent was an XON
124
       if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
151
       if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
125
 
152
 
126
-        // calculate count of bytes stored into the RX buffer
127
-        ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(rx_buffer.head - rx_buffer.tail) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
153
+        // Bytes stored into the RX buffer
154
+        const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
128
 
155
 
129
-        // if we are above 12.5% of RX buffer capacity, send XOFF before
130
-        // we run out of RX buffer space .. We need 325 bytes @ 250kbits/s to
131
-        // let the host react and stop sending bytes. This translates to 13mS
132
-        // propagation time.
156
+        // If over 12.5% of RX buffer capacity, send XOFF before running out of
157
+        // RX buffer space .. 325 bytes @ 250kbits/s needed to let the host react
158
+        // and stop sending bytes. This translates to 13mS propagation time.
133
         if (rx_count >= (RX_BUFFER_SIZE) / 8) {
159
         if (rx_count >= (RX_BUFFER_SIZE) / 8) {
134
 
160
 
135
-          // If TX interrupts are disabled and data register is empty,
136
-          // just write the byte to the data register and be done. This
137
-          // shortcut helps significantly improve the effective datarate
138
-          // at high (>500kbit/s) bitrates, where interrupt overhead
139
-          // becomes a slowdown.
140
-          if (!TEST(M_UCSRxB, M_UDRIEx) && TEST(M_UCSRxA, M_UDREx)) {
141
-
142
-            // Send an XOFF character
143
-            M_UDRx = XOFF_CHAR;
144
-
145
-            // clear the TXC bit -- "can be cleared by writing a one to its bit
146
-            // location". This makes sure flush() won't return until the bytes
147
-            // actually got written
148
-            SBI(M_UCSRxA, M_TXCx);
149
-
150
-            // And remember it was sent
151
-            xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
161
+          // At this point, definitely no TX interrupt was executing, since the TX isr can't be preempted.
162
+          // Don't enable the TX interrupt here as a means to trigger the XOFF char, because if it happens
163
+          // to be in the middle of trying to disable the RX interrupt in the main program, eventually the
164
+          // enabling of the TX interrupt could be undone. The ONLY reliable thing this can do to ensure
165
+          // the sending of the XOFF char is to send it HERE AND NOW.
166
+
167
+          // About to send the XOFF char
168
+          xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
169
+
170
+          // Wait until the TX register becomes empty and send it - Here there could be a problem
171
+          // - While waiting for the TX register to empty, the RX register could receive a new
172
+          //   character. This must also handle that situation!
173
+          while (!TEST(M_UCSRxA, M_UDREx)) {
174
+
175
+            if (TEST(M_UCSRxA,M_RXCx)) {
176
+              // A char arrived while waiting for the TX buffer to be empty - Receive and process it!
177
+
178
+              i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
179
+
180
+              // Read the character from the USART
181
+              c = M_UDRx;
182
+
183
+              #if ENABLED(EMERGENCY_PARSER)
184
+                emergency_parser.update(emergency_state, c);
185
+              #endif
186
+
187
+              // If the character is to be stored at the index just before the tail
188
+              // (such that the head would advance to the current tail), the FIFO is
189
+              // full, so don't write the character or advance the head.
190
+              if (i != t) {
191
+                rx_buffer.buffer[h] = c;
192
+                h = i;
193
+              }
194
+              #if ENABLED(SERIAL_STATS_DROPPED_RX)
195
+                else if (!++rx_dropped_bytes) --rx_dropped_bytes;
196
+              #endif
197
+            }
198
+            sw_barrier();
152
           }
199
           }
153
-          else {
154
-            // TX interrupts disabled, but buffer still not empty ... or
155
-            // TX interrupts enabled. Reenable TX ints and schedule XOFF
156
-            // character to be sent
157
-            #if TX_BUFFER_SIZE > 0
158
-              SBI(M_UCSRxB, M_UDRIEx);
159
-              xon_xoff_state = XOFF_CHAR;
160
-            #else
161
-              // We are not using TX interrupts, we will have to send this manually
162
-              while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
163
-              M_UDRx = XOFF_CHAR;
164
-
165
-              // clear the TXC bit -- "can be cleared by writing a one to its bit
166
-              // location". This makes sure flush() won't return until the bytes
167
-              // actually got written
168
-              SBI(M_UCSRxA, M_TXCx);
169
-
170
-              // And remember we already sent it
171
-              xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
172
-            #endif
200
+
201
+          M_UDRx = XOFF_CHAR;
202
+
203
+          // Clear the TXC bit -- "can be cleared by writing a one to its bit
204
+          // location". This makes sure flush() won't return until the bytes
205
+          // actually got written
206
+          SBI(M_UCSRxA, M_TXCx);
207
+
208
+          // At this point there could be a race condition between the write() function
209
+          // and this sending of the XOFF char. This interrupt could happen between the
210
+          // wait to be empty TX buffer loop and the actual write of the character. Since
211
+          // the TX buffer is full because it's sending the XOFF char, the only way to be
212
+          // sure the write() function will succeed is to wait for the XOFF char to be
213
+          // completely sent. Since an extra character could be received during the wait
214
+          // it must also be handled!
215
+          while (!TEST(M_UCSRxA, M_UDREx)) {
216
+
217
+            if (TEST(M_UCSRxA,M_RXCx)) {
218
+              // A char arrived while waiting for the TX buffer to be empty - Receive and process it!
219
+
220
+              i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
221
+
222
+              // Read the character from the USART
223
+              c = M_UDRx;
224
+
225
+              #if ENABLED(EMERGENCY_PARSER)
226
+                emergency_parser.update(emergency_state, c);
227
+              #endif
228
+
229
+              // If the character is to be stored at the index just before the tail
230
+              // (such that the head would advance to the current tail), the FIFO is
231
+              // full, so don't write the character or advance the head.
232
+              if (i != t) {
233
+                rx_buffer.buffer[h] = c;
234
+                h = i;
235
+              }
236
+              #if ENABLED(SERIAL_STATS_DROPPED_RX)
237
+                else if (!++rx_dropped_bytes) --rx_dropped_bytes;
238
+              #endif
239
+            }
240
+            sw_barrier();
173
           }
241
           }
242
+
243
+          // At this point everything is ready. The write() function won't
244
+          // have any issues writing to the UART TX register if it needs to!
174
         }
245
         }
175
       }
246
       }
176
     #endif // SERIAL_XON_XOFF
247
     #endif // SERIAL_XON_XOFF
177
 
248
 
178
-    #if ENABLED(EMERGENCY_PARSER)
179
-      emergency_parser.update(emergency_state, c);
180
-    #endif
249
+    // Store the new head value
250
+    rx_buffer.head = h;
181
   }
251
   }
182
 
252
 
183
   #if TX_BUFFER_SIZE > 0
253
   #if TX_BUFFER_SIZE > 0
184
 
254
 
185
     // (called with TX irqs disabled)
255
     // (called with TX irqs disabled)
186
     FORCE_INLINE void _tx_udr_empty_irq(void) {
256
     FORCE_INLINE void _tx_udr_empty_irq(void) {
187
-      // If interrupts are enabled, there must be more data in the output
188
-      // buffer.
257
+
258
+      // Read positions
259
+      uint8_t t = tx_buffer.tail;
260
+      const uint8_t h = tx_buffer.head;
189
 
261
 
190
       #if ENABLED(SERIAL_XON_XOFF)
262
       #if ENABLED(SERIAL_XON_XOFF)
191
-        // Do a priority insertion of an XON/XOFF char, if needed.
192
-        const uint8_t state = xon_xoff_state;
193
-        if (!(state & XON_XOFF_CHAR_SENT)) {
194
-          M_UDRx = state & XON_XOFF_CHAR_MASK;
195
-          xon_xoff_state = state | XON_XOFF_CHAR_SENT;
263
+        // If an XON char is pending to be sent, do it now
264
+        if (xon_xoff_state == XON_CHAR) {
265
+
266
+          // Send the character
267
+          M_UDRx = XON_CHAR;
268
+
269
+          // clear the TXC bit -- "can be cleared by writing a one to its bit
270
+          // location". This makes sure flush() won't return until the bytes
271
+          // actually got written
272
+          SBI(M_UCSRxA, M_TXCx);
273
+
274
+          // Remember we sent it.
275
+          xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
276
+
277
+          // If nothing else to transmit, just disable TX interrupts.
278
+          if (h == t) CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
279
+
280
+          return;
196
         }
281
         }
197
-        else
198
       #endif
282
       #endif
199
-      { // Send the next byte
200
-        const uint8_t t = tx_buffer.tail, c = tx_buffer.buffer[t];
201
-        tx_buffer.tail = (t + 1) & (TX_BUFFER_SIZE - 1);
202
-        M_UDRx = c;
283
+
284
+      // If nothing to transmit, just disable TX interrupts. This could
285
+      // happen as the result of the non atomicity of the disabling of RX
286
+      // interrupts that could end reenabling TX interrupts as a side effect.
287
+      if (h == t) {
288
+        CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
289
+        return;
203
       }
290
       }
204
 
291
 
205
-      // clear the TXC bit -- "can be cleared by writing a one to its bit
206
-      // location". This makes sure flush() won't return until the bytes
207
-      // actually got written
292
+      // There is something to TX, Send the next byte
293
+      const uint8_t c = tx_buffer.buffer[t];
294
+      t = (t + 1) & (TX_BUFFER_SIZE - 1);
295
+      M_UDRx = c;
296
+      tx_buffer.tail = t;
297
+
298
+      // Clear the TXC bit (by writing a one to its bit location).
299
+      // Ensures flush() won't return until the bytes are actually written/
208
       SBI(M_UCSRxA, M_TXCx);
300
       SBI(M_UCSRxA, M_TXCx);
209
 
301
 
210
-      // Disable interrupts if the buffer is empty
211
-      if (tx_buffer.head == tx_buffer.tail)
212
-        CBI(M_UCSRxB, M_UDRIEx);
302
+      // Disable interrupts if there is nothing to transmit following this byte
303
+      if (h == t) CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
213
     }
304
     }
214
 
305
 
215
     #ifdef M_USARTx_UDRE_vect
306
     #ifdef M_USARTx_UDRE_vect
253
     SBI(M_UCSRxB, M_RXCIEx);
344
     SBI(M_UCSRxB, M_RXCIEx);
254
     #if TX_BUFFER_SIZE > 0
345
     #if TX_BUFFER_SIZE > 0
255
       CBI(M_UCSRxB, M_UDRIEx);
346
       CBI(M_UCSRxB, M_UDRIEx);
256
-      _written = false;
257
     #endif
347
     #endif
348
+    _written = false;
258
   }
349
   }
259
 
350
 
260
   void MarlinSerial::end() {
351
   void MarlinSerial::end() {
281
   }
372
   }
282
 
373
 
283
   int MarlinSerial::read(void) {
374
   int MarlinSerial::read(void) {
284
-    int v;
285
 
375
 
286
     #if RX_BUFFER_SIZE > 256
376
     #if RX_BUFFER_SIZE > 256
287
-      // Disable RX interrupts to ensure atomic reads
288
-      const bool isr_enabled = TEST(M_UCSRxB, M_RXCIEx);
377
+      // Disable RX interrupts to ensure atomic reads - This could reenable TX interrupts,
378
+      //  but this situation is explicitly handled at the TX isr, so no problems there
379
+      bool isr_enabled = TEST(M_UCSRxB, M_RXCIEx);
289
       CBI(M_UCSRxB, M_RXCIEx);
380
       CBI(M_UCSRxB, M_RXCIEx);
290
     #endif
381
     #endif
291
 
382
 
298
 
389
 
299
     ring_buffer_pos_t t = rx_buffer.tail;
390
     ring_buffer_pos_t t = rx_buffer.tail;
300
 
391
 
301
-    if (h == t)
302
-      v = -1;
303
-    else {
304
-      v = rx_buffer.buffer[t];
305
-      t = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
306
-
307
-      #if RX_BUFFER_SIZE > 256
308
-        // Disable RX interrupts to ensure atomic write to tail, so
309
-        // the RX isr can't read partially updated values
310
-        const bool isr_enabled = TEST(M_UCSRxB, M_RXCIEx);
311
-        CBI(M_UCSRxB, M_RXCIEx);
312
-      #endif
392
+    // If nothing to read, return now
393
+    if (h == t) return -1;
313
 
394
 
314
-      // Advance tail
315
-      rx_buffer.tail = t;
395
+    // Get the next char
396
+    const int v = rx_buffer.buffer[t];
397
+    t = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
316
 
398
 
317
-      #if RX_BUFFER_SIZE > 256
318
-        // End critical section
319
-        if (isr_enabled) SBI(M_UCSRxB, M_RXCIEx);
320
-      #endif
399
+    #if RX_BUFFER_SIZE > 256
400
+      // Disable RX interrupts to ensure atomic write to tail, so
401
+      // the RX isr can't read partially updated values - This could
402
+      // reenable TX interrupts, but this situation is explicitly
403
+      // handled at the TX isr, so no problems there
404
+      isr_enabled = TEST(M_UCSRxB, M_RXCIEx);
405
+      CBI(M_UCSRxB, M_RXCIEx);
406
+    #endif
321
 
407
 
322
-      #if ENABLED(SERIAL_XON_XOFF)
323
-        if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
408
+    // Advance tail
409
+    rx_buffer.tail = t;
324
 
410
 
325
-          // Get count of bytes in the RX buffer
326
-          ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
411
+    #if RX_BUFFER_SIZE > 256
412
+      // End critical section
413
+      if (isr_enabled) SBI(M_UCSRxB, M_RXCIEx);
414
+    #endif
327
 
415
 
328
-          // When below 10% of RX buffer capacity, send XON before
329
-          // running out of RX buffer bytes
330
-          if (rx_count < (RX_BUFFER_SIZE) / 10) {
416
+    #if ENABLED(SERIAL_XON_XOFF)
417
+      // If the XOFF char was sent, or about to be sent...
418
+      if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
419
+        // Get count of bytes in the RX buffer
420
+        const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
421
+        if (rx_count < (RX_BUFFER_SIZE) / 10) {
422
+          #if TX_BUFFER_SIZE > 0
423
+            // Signal we want an XON character to be sent.
424
+            xon_xoff_state = XON_CHAR;
425
+            // Enable TX isr. Non atomic, but it will eventually enable them
426
+            SBI(M_UCSRxB, M_UDRIEx);
427
+          #else
428
+            // If not using TX interrupts, we must send the XON char now
331
             xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
429
             xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
332
-            write(XON_CHAR);
333
-            return v;
334
-          }
430
+            while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
431
+            M_UDRx = XON_CHAR;
432
+          #endif
335
         }
433
         }
336
-      #endif
337
-    }
434
+      }
435
+    #endif
338
 
436
 
339
     return v;
437
     return v;
340
   }
438
   }
367
     #endif
465
     #endif
368
 
466
 
369
     #if ENABLED(SERIAL_XON_XOFF)
467
     #if ENABLED(SERIAL_XON_XOFF)
468
+      // If the XOFF char was sent, or about to be sent...
370
       if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
469
       if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
371
-        xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
372
-        write(XON_CHAR);
470
+        #if TX_BUFFER_SIZE > 0
471
+          // Signal we want an XON character to be sent.
472
+          xon_xoff_state = XON_CHAR;
473
+          // Enable TX isr. Non atomic, but it will eventually enable it.
474
+          SBI(M_UCSRxB, M_UDRIEx);
475
+        #else
476
+          // If not using TX interrupts, we must send the XON char now
477
+          xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
478
+          while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
479
+          M_UDRx = XON_CHAR;
480
+        #endif
373
       }
481
       }
374
     #endif
482
     #endif
375
   }
483
   }
383
       // be done. This shortcut helps significantly improve the
491
       // be done. This shortcut helps significantly improve the
384
       // effective datarate at high (>500kbit/s) bitrates, where
492
       // effective datarate at high (>500kbit/s) bitrates, where
385
       // interrupt overhead becomes a slowdown.
493
       // interrupt overhead becomes a slowdown.
494
+      // Yes, there is a race condition between the sending of the
495
+      // XOFF char at the RX isr, but it is properly handled there
386
       if (!TEST(M_UCSRxB, M_UDRIEx) && TEST(M_UCSRxA, M_UDREx)) {
496
       if (!TEST(M_UCSRxB, M_UDRIEx) && TEST(M_UCSRxA, M_UDREx)) {
387
         M_UDRx = c;
497
         M_UDRx = c;
388
 
498
 
395
 
505
 
396
       const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
506
       const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
397
 
507
 
398
-      // If the output buffer is full, there's nothing for it other than to
399
-      // wait for the interrupt handler to empty it a bit
400
-      while (i == tx_buffer.tail) {
401
-        if (!ISRS_ENABLED()) {
402
-          // Interrupts are disabled, so we'll have to poll the data
403
-          // register empty flag ourselves. If it is set, pretend an
404
-          // interrupt has happened and call the handler to free up
405
-          // space for us.
406
-          if (TEST(M_UCSRxA, M_UDREx))
407
-            _tx_udr_empty_irq();
408
-        }
409
-        // (else , the interrupt handler will free up space for us)
508
+      // If global interrupts are disabled (as the result of being called from an ISR)...
509
+      if (!ISRS_ENABLED()) {
510
+
511
+        // Make room by polling if it is possible to transmit, and do so!
512
+        while (i == tx_buffer.tail) {
513
+
514
+          // If we can transmit another byte, do it.
515
+          if (TEST(M_UCSRxA, M_UDREx)) _tx_udr_empty_irq();
410
 
516
 
411
-        // Make sure compiler rereads tx_buffer.tail
412
-        sw_barrier();
517
+          // Make sure compiler rereads tx_buffer.tail
518
+          sw_barrier();
519
+        }
520
+      }
521
+      else {
522
+        // Interrupts are enabled, just wait until there is space
523
+        while (i == tx_buffer.tail) { sw_barrier(); }
413
       }
524
       }
414
 
525
 
415
       // Store new char. head is always safe to move
526
       // Store new char. head is always safe to move
416
       tx_buffer.buffer[tx_buffer.head] = c;
527
       tx_buffer.buffer[tx_buffer.head] = c;
417
       tx_buffer.head = i;
528
       tx_buffer.head = i;
418
 
529
 
419
-      // Enable TX isr
530
+      // Enable TX isr - Non atomic, but it will eventually enable TX isr
420
       SBI(M_UCSRxB, M_UDRIEx);
531
       SBI(M_UCSRxB, M_UDRIEx);
421
-      return;
422
     }
532
     }
423
 
533
 
424
     void MarlinSerial::flushTX(void) {
534
     void MarlinSerial::flushTX(void) {
425
-      // TX
426
-      // If we have never written a byte, no need to flush. This special
427
-      // case is needed since there is no way to force the TXC (transmit
428
-      // complete) bit to 1 during initialization
429
-      if (!_written)
430
-        return;
535
+      // No bytes written, no need to flush. This special case is needed since there's
536
+      // no way to force the TXC (transmit complete) bit to 1 during initialization.
537
+      if (!_written) return;
538
+
539
+      // If global interrupts are disabled (as the result of being called from an ISR)...
540
+      if (!ISRS_ENABLED()) {
541
+
542
+        // Wait until everything was transmitted - We must do polling, as interrupts are disabled
543
+        while (tx_buffer.head != tx_buffer.tail || !TEST(M_UCSRxA, M_TXCx)) {
431
 
544
 
432
-      while (TEST(M_UCSRxB, M_UDRIEx) || !TEST(M_UCSRxA, M_TXCx)) {
433
-        if (!ISRS_ENABLED()) {
434
-          // Interrupts are globally disabled, but the DR empty
435
-          // interrupt should be enabled, so poll the DR empty flag to
436
-          // prevent deadlock
545
+          // If there is more space, send an extra character
437
           if (TEST(M_UCSRxA, M_UDREx))
546
           if (TEST(M_UCSRxA, M_UDREx))
438
             _tx_udr_empty_irq();
547
             _tx_udr_empty_irq();
548
+
549
+          sw_barrier();
439
         }
550
         }
440
-        sw_barrier();
551
+
441
       }
552
       }
442
-      // If we get here, nothing is queued anymore (DRIE is disabled) and
553
+      else {
554
+        // Wait until everything was transmitted
555
+        while (tx_buffer.head != tx_buffer.tail || !TEST(M_UCSRxA, M_TXCx)) sw_barrier();
556
+      }
557
+
558
+      // At this point nothing is queued anymore (DRIE is disabled) and
443
       // the hardware finished transmission (TXC is set).
559
       // the hardware finished transmission (TXC is set).
444
     }
560
     }
445
 
561
 
446
   #else // TX_BUFFER_SIZE == 0
562
   #else // TX_BUFFER_SIZE == 0
447
 
563
 
448
     void MarlinSerial::write(const uint8_t c) {
564
     void MarlinSerial::write(const uint8_t c) {
565
+      _written = true;
449
       while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
566
       while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
450
       M_UDRx = c;
567
       M_UDRx = c;
451
     }
568
     }
452
 
569
 
570
+    void MarlinSerial::flushTX(void) {
571
+      // No bytes written, no need to flush. This special case is needed since there's
572
+      // no way to force the TXC (transmit complete) bit to 1 during initialization.
573
+      if (!_written) return;
574
+
575
+      // Wait until everything was transmitted
576
+      while (!TEST(M_UCSRxA, M_TXCx)) sw_barrier();
577
+
578
+      // At this point nothing is queued anymore (DRIE is disabled) and
579
+      // the hardware finished transmission (TXC is set).
580
+    }
453
   #endif // TX_BUFFER_SIZE == 0
581
   #endif // TX_BUFFER_SIZE == 0
454
 
582
 
455
   /**
583
   /**
473
   }
601
   }
474
 
602
 
475
   void MarlinSerial::print(long n, int base) {
603
   void MarlinSerial::print(long n, int base) {
476
-    if (base == 0)
477
-      write(n);
604
+    if (base == 0) write(n);
478
     else if (base == 10) {
605
     else if (base == 10) {
479
-      if (n < 0) {
480
-        print('-');
481
-        n = -n;
482
-      }
606
+      if (n < 0) { print('-'); n = -n; }
483
       printNumber(n, 10);
607
       printNumber(n, 10);
484
     }
608
     }
485
     else
609
     else

+ 25
- 7
Marlin/src/HAL/HAL_AVR/MarlinSerial.h ファイルの表示

62
 #define M_TXCx             SERIAL_REGNAME(TXC,SERIAL_PORT,)
62
 #define M_TXCx             SERIAL_REGNAME(TXC,SERIAL_PORT,)
63
 #define M_RXCIEx           SERIAL_REGNAME(RXCIE,SERIAL_PORT,)
63
 #define M_RXCIEx           SERIAL_REGNAME(RXCIE,SERIAL_PORT,)
64
 #define M_UDREx            SERIAL_REGNAME(UDRE,SERIAL_PORT,)
64
 #define M_UDREx            SERIAL_REGNAME(UDRE,SERIAL_PORT,)
65
+#define M_FEx              SERIAL_REGNAME(FE,SERIAL_PORT,)
66
+#define M_DORx             SERIAL_REGNAME(DOR,SERIAL_PORT,)
67
+#define M_UPEx             SERIAL_REGNAME(UPE,SERIAL_PORT,)
65
 #define M_UDRIEx           SERIAL_REGNAME(UDRIE,SERIAL_PORT,)
68
 #define M_UDRIEx           SERIAL_REGNAME(UDRIE,SERIAL_PORT,)
66
 #define M_UDRx             SERIAL_REGNAME(UDR,SERIAL_PORT,)
69
 #define M_UDRx             SERIAL_REGNAME(UDR,SERIAL_PORT,)
67
 #define M_UBRRxH           SERIAL_REGNAME(UBRR,SERIAL_PORT,H)
70
 #define M_UBRRxH           SERIAL_REGNAME(UBRR,SERIAL_PORT,H)
75
 #define HEX 16
78
 #define HEX 16
76
 #define OCT 8
79
 #define OCT 8
77
 #define BIN 2
80
 #define BIN 2
81
+#define BYTE 0
78
 
82
 
79
 #ifndef USBCON
83
 #ifndef USBCON
80
   // We're using a ring buffer (I think), in which rx_buffer_head is the index of the
84
   // We're using a ring buffer (I think), in which rx_buffer_head is the index of the
90
     extern uint8_t rx_dropped_bytes;
94
     extern uint8_t rx_dropped_bytes;
91
   #endif
95
   #endif
92
 
96
 
97
+  #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
98
+    extern uint8_t rx_buffer_overruns;
99
+  #endif
100
+
101
+  #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
102
+    extern uint8_t rx_framing_errors;
103
+  #endif
104
+
93
   #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
105
   #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
94
     extern ring_buffer_pos_t rx_max_enqueued;
106
     extern ring_buffer_pos_t rx_max_enqueued;
95
   #endif
107
   #endif
105
       static void flush(void);
117
       static void flush(void);
106
       static ring_buffer_pos_t available(void);
118
       static ring_buffer_pos_t available(void);
107
       static void write(const uint8_t c);
119
       static void write(const uint8_t c);
108
-      #if TX_BUFFER_SIZE > 0
109
-        static void flushTX(void);
110
-      #endif
120
+      static void flushTX(void);
111
 
121
 
112
       #if ENABLED(SERIAL_STATS_DROPPED_RX)
122
       #if ENABLED(SERIAL_STATS_DROPPED_RX)
113
         FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }
123
         FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }
114
       #endif
124
       #endif
115
 
125
 
126
+      #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
127
+        FORCE_INLINE static uint32_t buffer_overruns() { return rx_buffer_overruns; }
128
+      #endif
129
+
130
+      #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
131
+        FORCE_INLINE static uint32_t framing_errors() { return rx_framing_errors; }
132
+      #endif
133
+
116
       #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
134
       #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
117
         FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return rx_max_enqueued; }
135
         FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return rx_max_enqueued; }
118
       #endif
136
       #endif
122
       FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
140
       FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
123
       FORCE_INLINE static void print(const char* str) { write(str); }
141
       FORCE_INLINE static void print(const char* str) { write(str); }
124
 
142
 
125
-      static void print(char, int = 0);
126
-      static void print(unsigned char, int = 0);
143
+      static void print(char, int = BYTE);
144
+      static void print(unsigned char, int = BYTE);
127
       static void print(int, int = DEC);
145
       static void print(int, int = DEC);
128
       static void print(unsigned int, int = DEC);
146
       static void print(unsigned int, int = DEC);
129
       static void print(long, int = DEC);
147
       static void print(long, int = DEC);
132
 
150
 
133
       static void println(const String& s);
151
       static void println(const String& s);
134
       static void println(const char[]);
152
       static void println(const char[]);
135
-      static void println(char, int = 0);
136
-      static void println(unsigned char, int = 0);
153
+      static void println(char, int = BYTE);
154
+      static void println(unsigned char, int = BYTE);
137
       static void println(int, int = DEC);
155
       static void println(int, int = DEC);
138
       static void println(unsigned int, int = DEC);
156
       static void println(unsigned int, int = DEC);
139
       static void println(long, int = DEC);
157
       static void println(long, int = DEC);

+ 274
- 147
Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.cpp ファイルの表示

74
   ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
74
   ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
75
   #if TX_BUFFER_SIZE > 0
75
   #if TX_BUFFER_SIZE > 0
76
     ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
76
     ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
77
-    static bool _written;
78
   #endif
77
   #endif
78
+  static bool _written;
79
 
79
 
80
   #if ENABLED(SERIAL_XON_XOFF)
80
   #if ENABLED(SERIAL_XON_XOFF)
81
-    constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80;  // XON / XOFF Character was sent
82
-    constexpr uint8_t XON_XOFF_CHAR_MASK = 0x1F;  // XON / XOFF character to send
81
+    constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80,  // XON / XOFF Character was sent
82
+                      XON_XOFF_CHAR_MASK = 0x1F;  // XON / XOFF character to send
83
     // XON / XOFF character definitions
83
     // XON / XOFF character definitions
84
-    constexpr uint8_t XON_CHAR  = 17;
85
-    constexpr uint8_t XOFF_CHAR = 19;
84
+    constexpr uint8_t XON_CHAR  = 17, XOFF_CHAR = 19;
86
     uint8_t xon_xoff_state = XON_XOFF_CHAR_SENT | XON_CHAR;
85
     uint8_t xon_xoff_state = XON_XOFF_CHAR_SENT | XON_CHAR;
87
 
86
 
88
     // Validate that RX buffer size is at least 4096 bytes- According to several experiments, on
87
     // Validate that RX buffer size is at least 4096 bytes- According to several experiments, on
99
     uint8_t rx_dropped_bytes = 0;
98
     uint8_t rx_dropped_bytes = 0;
100
   #endif
99
   #endif
101
 
100
 
101
+  #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
102
+    uint8_t rx_buffer_overruns = 0;
103
+  #endif
104
+
105
+  #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
106
+    uint8_t rx_framing_errors = 0;
107
+  #endif
108
+
102
   #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
109
   #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
103
     ring_buffer_pos_t rx_max_enqueued = 0;
110
     ring_buffer_pos_t rx_max_enqueued = 0;
104
   #endif
111
   #endif
110
     #include "../../feature/emergency_parser.h"
117
     #include "../../feature/emergency_parser.h"
111
   #endif
118
   #endif
112
 
119
 
120
+  // (called with RX interrupts disabled)
113
   FORCE_INLINE void store_rxd_char() {
121
   FORCE_INLINE void store_rxd_char() {
114
 
122
 
115
     #if ENABLED(EMERGENCY_PARSER)
123
     #if ENABLED(EMERGENCY_PARSER)
116
       static EmergencyParser::State emergency_state; // = EP_RESET
124
       static EmergencyParser::State emergency_state; // = EP_RESET
117
     #endif
125
     #endif
118
 
126
 
119
-    const ring_buffer_pos_t h = rx_buffer.head,
120
-                            i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
127
+    // Get the tail - Nothing can alter its value while we are at this ISR
128
+    const ring_buffer_pos_t t = rx_buffer.tail;
129
+
130
+    // Get the head pointer
131
+    ring_buffer_pos_t h = rx_buffer.head;
121
 
132
 
122
-      // Read the character
123
-    const uint8_t c = HWUART->UART_RHR;
133
+    // Get the next element
134
+    ring_buffer_pos_t i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
135
+
136
+    // Read the character from the USART
137
+    uint8_t c = HWUART->UART_RHR;
138
+
139
+    #if ENABLED(EMERGENCY_PARSER)
140
+      emergency_parser.update(emergency_state, c);
141
+    #endif
124
 
142
 
125
     // If the character is to be stored at the index just before the tail
143
     // If the character is to be stored at the index just before the tail
126
-    // (such that the head would advance to the current tail), the buffer is
127
-    // critical, so don't write the character or advance the head.
128
-    if (i != rx_buffer.tail) {
144
+    // (such that the head would advance to the current tail), the RX FIFO is
145
+    // full, so don't write the character or advance the head.
146
+    if (i != t) {
129
       rx_buffer.buffer[h] = c;
147
       rx_buffer.buffer[h] = c;
130
-      rx_buffer.head = i;
148
+      h = i;
131
     }
149
     }
132
     #if ENABLED(SERIAL_STATS_DROPPED_RX)
150
     #if ENABLED(SERIAL_STATS_DROPPED_RX)
133
-      else if (!++rx_dropped_bytes) ++rx_dropped_bytes;
151
+      else if (!++rx_dropped_bytes) --rx_dropped_bytes;
134
     #endif
152
     #endif
135
 
153
 
136
     #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
154
     #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
137
-      // calculate count of bytes stored into the RX buffer
138
-      ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(rx_buffer.head - rx_buffer.tail) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
155
+      const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
156
+      // Calculate count of bytes stored into the RX buffer
157
+
139
       // Keep track of the maximum count of enqueued bytes
158
       // Keep track of the maximum count of enqueued bytes
140
       NOLESS(rx_max_enqueued, rx_count);
159
       NOLESS(rx_max_enqueued, rx_count);
141
     #endif
160
     #endif
142
 
161
 
143
     #if ENABLED(SERIAL_XON_XOFF)
162
     #if ENABLED(SERIAL_XON_XOFF)
144
-
145
-      // for high speed transfers, we can use XON/XOFF protocol to do
146
-      // software handshake and avoid overruns.
163
+      // If the last char that was sent was an XON
147
       if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
164
       if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
148
 
165
 
149
-        // calculate count of bytes stored into the RX buffer
150
-        ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(rx_buffer.head - rx_buffer.tail) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
166
+        // Bytes stored into the RX buffer
167
+        const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
151
 
168
 
152
-        // if we are above 12.5% of RX buffer capacity, send XOFF before
153
-        // we run out of RX buffer space .. We need 325 bytes @ 250kbits/s to
154
-        // let the host react and stop sending bytes. This translates to 13mS
155
-        // propagation time.
169
+        // If over 12.5% of RX buffer capacity, send XOFF before running out of
170
+        // RX buffer space .. 325 bytes @ 250kbits/s needed to let the host react
171
+        // and stop sending bytes. This translates to 13mS propagation time.
156
         if (rx_count >= (RX_BUFFER_SIZE) / 8) {
172
         if (rx_count >= (RX_BUFFER_SIZE) / 8) {
157
-          
158
-          // If TX interrupts are disabled and data register is empty,
159
-          // just write the byte to the data register and be done. This
160
-          // shortcut helps significantly improve the effective datarate
161
-          // at high (>500kbit/s) bitrates, where interrupt overhead
162
-          // becomes a slowdown.
163
-          if (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) {
164
-            
165
-            // Send an XOFF character
166
-            HWUART->UART_THR = XOFF_CHAR;
167
-
168
-            // And remember it was sent
169
-            xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
173
+
174
+          // At this point, definitely no TX interrupt was executing, since the TX isr can't be preempted.
175
+          // Don't enable the TX interrupt here as a means to trigger the XOFF char, because if it happens
176
+          // to be in the middle of trying to disable the RX interrupt in the main program, eventually the
177
+          // enabling of the TX interrupt could be undone. The ONLY reliable thing this can do to ensure
178
+          // the sending of the XOFF char is to send it HERE AND NOW.
179
+
180
+          // About to send the XOFF char
181
+          xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
182
+
183
+          // Wait until the TX register becomes empty and send it - Here there could be a problem
184
+          // - While waiting for the TX register to empty, the RX register could receive a new
185
+          //   character. This must also handle that situation!
186
+          uint32_t status;
187
+          while (!((status = HWUART->UART_SR) & UART_SR_TXRDY)) {
188
+
189
+            if (status & UART_SR_RXRDY) {
190
+              // We received a char while waiting for the TX buffer to be empty - Receive and process it!
191
+
192
+              i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
193
+
194
+              // Read the character from the USART
195
+              c = HWUART->UART_RHR;
196
+
197
+              #if ENABLED(EMERGENCY_PARSER)
198
+                emergency_parser.update(emergency_state, c);
199
+              #endif
200
+
201
+              // If the character is to be stored at the index just before the tail
202
+              // (such that the head would advance to the current tail), the FIFO is
203
+              // full, so don't write the character or advance the head.
204
+              if (i != t) {
205
+                rx_buffer.buffer[h] = c;
206
+                h = i;
207
+              }
208
+              #if ENABLED(SERIAL_STATS_DROPPED_RX)
209
+                else if (!++rx_dropped_bytes) --rx_dropped_bytes;
210
+              #endif
211
+            }
212
+            sw_barrier();
170
           }
213
           }
171
-          else {
172
-            // TX interrupts disabled, but buffer still not empty ... or
173
-            // TX interrupts enabled. Reenable TX ints and schedule XOFF
174
-            // character to be sent
175
-            #if TX_BUFFER_SIZE > 0
176
-              HWUART->UART_IER = UART_IER_TXRDY;
177
-              xon_xoff_state = XOFF_CHAR;
178
-            #else
179
-              // We are not using TX interrupts, we will have to send this manually
180
-              while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
181
-              HWUART->UART_THR = XOFF_CHAR;
182
-              
183
-              // And remember we already sent it
184
-              xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
185
-            #endif
214
+
215
+          HWUART->UART_THR = XOFF_CHAR;
216
+
217
+          // At this point there could be a race condition between the write() function
218
+          // and this sending of the XOFF char. This interrupt could happen between the
219
+          // wait to be empty TX buffer loop and the actual write of the character. Since
220
+          // the TX buffer is full because it's sending the XOFF char, the only way to be
221
+          // sure the write() function will succeed is to wait for the XOFF char to be
222
+          // completely sent. Since an extra character could be received during the wait
223
+          // it must also be handled!
224
+          while (!((status = HWUART->UART_SR) & UART_SR_TXRDY)) {
225
+
226
+            if (status & UART_SR_RXRDY) {
227
+              // A char arrived while waiting for the TX buffer to be empty - Receive and process it!
228
+
229
+              i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
230
+
231
+              // Read the character from the USART
232
+              c = HWUART->UART_RHR;
233
+
234
+              #if ENABLED(EMERGENCY_PARSER)
235
+                emergency_parser.update(emergency_state, c);
236
+              #endif
237
+
238
+              // If the character is to be stored at the index just before the tail
239
+              // (such that the head would advance to the current tail), the FIFO is
240
+              // full, so don't write the character or advance the head.
241
+              if (i != t) {
242
+                rx_buffer.buffer[h] = c;
243
+                h = i;
244
+              }
245
+              #if ENABLED(SERIAL_STATS_DROPPED_RX)
246
+                else if (!++rx_dropped_bytes) --rx_dropped_bytes;
247
+              #endif
248
+            }
249
+            sw_barrier();
186
           }
250
           }
251
+
252
+          // At this point everything is ready. The write() function won't
253
+          // have any issues writing to the UART TX register if it needs to!
187
         }
254
         }
188
       }
255
       }
189
     #endif // SERIAL_XON_XOFF
256
     #endif // SERIAL_XON_XOFF
190
 
257
 
191
-    #if ENABLED(EMERGENCY_PARSER)
192
-      emergency_parser.update(emergency_state, c);
193
-    #endif
258
+    // Store the new head value
259
+    rx_buffer.head = h;
194
   }
260
   }
195
 
261
 
196
   #if TX_BUFFER_SIZE > 0
262
   #if TX_BUFFER_SIZE > 0
197
 
263
 
198
     FORCE_INLINE void _tx_thr_empty_irq(void) {
264
     FORCE_INLINE void _tx_thr_empty_irq(void) {
199
-      // If interrupts are enabled, there must be more data in the output
200
-      // buffer.
265
+      // Read positions
266
+      uint8_t t = tx_buffer.tail;
267
+      const uint8_t h = tx_buffer.head;
201
 
268
 
202
       #if ENABLED(SERIAL_XON_XOFF)
269
       #if ENABLED(SERIAL_XON_XOFF)
203
-        // Do a priority insertion of an XON/XOFF char, if needed.
204
-        const uint8_t state = xon_xoff_state;
205
-        if (!(state & XON_XOFF_CHAR_SENT)) {
206
-          HWUART->UART_THR = state & XON_XOFF_CHAR_MASK;
207
-          xon_xoff_state = state | XON_XOFF_CHAR_SENT;
270
+        // If an XON char is pending to be sent, do it now
271
+        if (xon_xoff_state == XON_CHAR) {
272
+
273
+          // Send the character
274
+          HWUART->UART_THR = XON_CHAR;
275
+
276
+          // Remember we sent it.
277
+          xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
278
+
279
+          // If nothing else to transmit, just disable TX interrupts.
280
+          if (h == t) HWUART->UART_IDR = UART_IDR_TXRDY;
281
+
282
+          return;
208
         }
283
         }
209
-        else
210
       #endif
284
       #endif
211
-        { // Send the next byte
212
-          const uint8_t t = tx_buffer.tail, c = tx_buffer.buffer[t];
213
-          tx_buffer.tail = (t + 1) & (TX_BUFFER_SIZE - 1);
214
-          HWUART->UART_THR = c;
215
-        }
216
 
285
 
217
-      // Disable interrupts if the buffer is empty
218
-      if (tx_buffer.head == tx_buffer.tail)
286
+      // If nothing to transmit, just disable TX interrupts. This could
287
+      // happen as the result of the non atomicity of the disabling of RX
288
+      // interrupts that could end reenabling TX interrupts as a side effect.
289
+      if (h == t) {
219
         HWUART->UART_IDR = UART_IDR_TXRDY;
290
         HWUART->UART_IDR = UART_IDR_TXRDY;
291
+        return;
292
+      }
293
+
294
+      // There is something to TX, Send the next byte
295
+      const uint8_t c = tx_buffer.buffer[t];
296
+      t = (t + 1) & (TX_BUFFER_SIZE - 1);
297
+      HWUART->UART_THR = c;
298
+      tx_buffer.tail = t;
299
+
300
+      // Disable interrupts if there is nothing to transmit following this byte
301
+      if (h == t) HWUART->UART_IDR = UART_IDR_TXRDY;
220
     }
302
     }
221
 
303
 
222
   #endif // TX_BUFFER_SIZE > 0
304
   #endif // TX_BUFFER_SIZE > 0
223
 
305
 
224
   static void UART_ISR(void) {
306
   static void UART_ISR(void) {
225
-    uint32_t status = HWUART->UART_SR;
307
+    const uint32_t status = HWUART->UART_SR;
226
 
308
 
227
-    // Did we receive data?
228
-    if (status & UART_SR_RXRDY)
229
-      store_rxd_char();
309
+    // Data received?
310
+    if (status & UART_SR_RXRDY) store_rxd_char();
230
 
311
 
231
     #if TX_BUFFER_SIZE > 0
312
     #if TX_BUFFER_SIZE > 0
232
-      // Do we have something to send, and TX interrupts are enabled (meaning something to send) ?
233
-      if ((status & UART_SR_TXRDY) && (HWUART->UART_IMR & UART_IMR_TXRDY))
234
-        _tx_thr_empty_irq();
313
+      // Something to send, and TX interrupts are enabled (meaning something to send)?
314
+      if ((status & UART_SR_TXRDY) && (HWUART->UART_IMR & UART_IMR_TXRDY)) _tx_thr_empty_irq();
235
     #endif
315
     #endif
236
 
316
 
237
     // Acknowledge errors
317
     // Acknowledge errors
238
     if ((status & UART_SR_OVRE) || (status & UART_SR_FRAME)) {
318
     if ((status & UART_SR_OVRE) || (status & UART_SR_FRAME)) {
319
+
320
+      #if ENABLED(SERIAL_STATS_DROPPED_RX)
321
+        if (status & UART_SR_OVRE && !++rx_dropped_bytes) --rx_dropped_bytes;
322
+      #endif
323
+
324
+      #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
325
+        if (status & UART_SR_OVRE && !++rx_buffer_overruns) --rx_buffer_overruns;
326
+      #endif
327
+
328
+      #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
329
+        if (status & UART_SR_FRAME && !++rx_framing_errors) --rx_framing_errors;
330
+      #endif
331
+
239
       // TODO: error reporting outside ISR
332
       // TODO: error reporting outside ISR
240
       HWUART->UART_CR = UART_CR_RSTSTA;
333
       HWUART->UART_CR = UART_CR_RSTSTA;
241
     }
334
     }
312
   }
405
   }
313
 
406
 
314
   int MarlinSerial::read(void) {
407
   int MarlinSerial::read(void) {
315
-    int v;
316
-    
408
+
317
     const ring_buffer_pos_t h = rx_buffer.head;
409
     const ring_buffer_pos_t h = rx_buffer.head;
318
     ring_buffer_pos_t t = rx_buffer.tail;
410
     ring_buffer_pos_t t = rx_buffer.tail;
319
-    
320
-    if (h == t)
321
-      v = -1;
322
-    else {
323
-      v = rx_buffer.buffer[t];
324
-      t = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
325
-      
326
-      // Advance tail
327
-      rx_buffer.tail = t;
328
 
411
 
329
-      #if ENABLED(SERIAL_XON_XOFF)
330
-        if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
331
-          
332
-          // Get count of bytes in the RX buffer
333
-          ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
334
-          
335
-          // When below 10% of RX buffer capacity, send XON before
336
-          // running out of RX buffer bytes
337
-          if (rx_count < (RX_BUFFER_SIZE) / 10) {
412
+    if (h == t) return -1;
413
+
414
+    int v = rx_buffer.buffer[t];
415
+    t = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
416
+
417
+    // Advance tail
418
+    rx_buffer.tail = t;
419
+
420
+    #if ENABLED(SERIAL_XON_XOFF)
421
+      // If the XOFF char was sent, or about to be sent...
422
+      if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
423
+        // Get count of bytes in the RX buffer
424
+        const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
425
+        // When below 10% of RX buffer capacity, send XON before running out of RX buffer bytes
426
+        if (rx_count < (RX_BUFFER_SIZE) / 10) {
427
+          #if TX_BUFFER_SIZE > 0
428
+            // Signal we want an XON character to be sent.
429
+            xon_xoff_state = XON_CHAR;
430
+            // Enable TX isr.
431
+            HWUART->UART_IER = UART_IER_TXRDY;
432
+          #else
433
+            // If not using TX interrupts, we must send the XON char now
338
             xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
434
             xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
339
-            write(XON_CHAR);
340
-            return v;
341
-          }
435
+            while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
436
+            HWUART->UART_THR = XON_CHAR;
437
+          #endif
342
         }
438
         }
343
-      #endif
344
-    }
439
+      }
440
+    #endif
441
+
345
     return v;
442
     return v;
346
   }
443
   }
347
 
444
 
355
 
452
 
356
     #if ENABLED(SERIAL_XON_XOFF)
453
     #if ENABLED(SERIAL_XON_XOFF)
357
       if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
454
       if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
358
-        xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
359
-        write(XON_CHAR);
455
+        #if TX_BUFFER_SIZE > 0
456
+          // Signal we want an XON character to be sent.
457
+          xon_xoff_state = XON_CHAR;
458
+          // Enable TX isr.
459
+          HWUART->UART_IER = UART_IER_TXRDY;
460
+        #else
461
+          // If not using TX interrupts, we must send the XON char now
462
+          xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
463
+          while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
464
+          HWUART->UART_THR = XON_CHAR;
465
+        #endif
360
       }
466
       }
361
     #endif
467
     #endif
362
   }
468
   }
364
   #if TX_BUFFER_SIZE > 0
470
   #if TX_BUFFER_SIZE > 0
365
     void MarlinSerial::write(const uint8_t c) {
471
     void MarlinSerial::write(const uint8_t c) {
366
       _written = true;
472
       _written = true;
367
-      
368
-      // If the TX interrupts are disabled and the data register 
369
-      // is empty, just write the byte to the data register and 
370
-      // be done. This shortcut helps significantly improve the 
371
-      // effective datarate at high (>500kbit/s) bitrates, where 
473
+
474
+      // If the TX interrupts are disabled and the data register
475
+      // is empty, just write the byte to the data register and
476
+      // be done. This shortcut helps significantly improve the
477
+      // effective datarate at high (>500kbit/s) bitrates, where
372
       // interrupt overhead becomes a slowdown.
478
       // interrupt overhead becomes a slowdown.
479
+      // Yes, there is a race condition between the sending of the
480
+      // XOFF char at the RX isr, but it is properly handled there
373
       if (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) {
481
       if (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) {
374
         HWUART->UART_THR = c;
482
         HWUART->UART_THR = c;
375
         return;
483
         return;
376
       }
484
       }
377
-      
485
+
378
       const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
486
       const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
379
 
487
 
380
-      // If the output buffer is full, there's nothing for it other than to
381
-      // wait for the interrupt handler to empty it a bit
382
-      while (i == tx_buffer.tail) {
383
-        if (!ISRS_ENABLED()) {
384
-          // Interrupts are disabled, so we'll have to poll the data
385
-          // register empty flag ourselves. If it is set, pretend an
386
-          // interrupt has happened and call the handler to free up
387
-          // space for us.
388
-          if (HWUART->UART_SR & UART_SR_TXRDY)
389
-            _tx_thr_empty_irq();
488
+      // If global interrupts are disabled (as the result of being called from an ISR)...
489
+      if (!ISRS_ENABLED()) {
490
+
491
+        // Make room by polling if it is possible to transmit, and do so!
492
+        while (i == tx_buffer.tail) {
493
+          // If we can transmit another byte, do it.
494
+          if (HWUART->UART_SR & UART_SR_TXRDY) _tx_thr_empty_irq();
495
+          // Make sure compiler rereads tx_buffer.tail
496
+          sw_barrier();
390
         }
497
         }
391
-        // (else , the interrupt handler will free up space for us)
392
-        
393
-        // Make sure compiler rereads tx_buffer.tail
394
-        sw_barrier();
498
+      }
499
+      else {
500
+        // Interrupts are enabled, just wait until there is space
501
+        while (i == tx_buffer.tail) sw_barrier();
395
       }
502
       }
396
 
503
 
504
+      // Store new char. head is always safe to move
397
       tx_buffer.buffer[tx_buffer.head] = c;
505
       tx_buffer.buffer[tx_buffer.head] = c;
398
       tx_buffer.head = i;
506
       tx_buffer.head = i;
399
-      
400
-      // Enable TX isr
507
+
508
+      // Enable TX isr - Non atomic, but it will eventually enable TX isr
401
       HWUART->UART_IER = UART_IER_TXRDY;
509
       HWUART->UART_IER = UART_IER_TXRDY;
402
-      return;
403
     }
510
     }
404
 
511
 
405
     void MarlinSerial::flushTX(void) {
512
     void MarlinSerial::flushTX(void) {
406
       // TX
513
       // TX
407
-      // If we have never written a byte, no need to flush.
514
+
515
+      // If we have never written a byte, no need to flush. This special
516
+      // case is needed since there is no way to force the TXC (transmit
517
+      // complete) bit to 1 during initialization
408
       if (!_written) return;
518
       if (!_written) return;
409
 
519
 
410
-      while ((HWUART->UART_IMR & UART_IMR_TXRDY) || !(HWUART->UART_SR & UART_SR_TXEMPTY)) {
411
-        if (!ISRS_ENABLED()) {
412
-          if (HWUART->UART_SR & UART_SR_TXRDY)
413
-            _tx_thr_empty_irq();
520
+      // If global interrupts are disabled (as the result of being called from an ISR)...
521
+      if (!ISRS_ENABLED()) {
522
+
523
+        // Wait until everything was transmitted - We must do polling, as interrupts are disabled
524
+        while (tx_buffer.head != tx_buffer.tail || !(HWUART->UART_SR & UART_SR_TXEMPTY)) {
525
+          // If there is more space, send an extra character
526
+          if (HWUART->UART_SR & UART_SR_TXRDY) _tx_thr_empty_irq();
527
+          sw_barrier();
414
         }
528
         }
415
-        sw_barrier();
529
+
530
+      }
531
+      else {
532
+        // Wait until everything was transmitted
533
+        while (tx_buffer.head != tx_buffer.tail || !(HWUART->UART_SR & UART_SR_TXEMPTY)) sw_barrier();
416
       }
534
       }
417
-      // If we get here, nothing is queued anymore (TX interrupts are disabled) and
418
-      // the hardware finished tranmission (TXEMPTY is set).
535
+
536
+      // At this point nothing is queued anymore (DRIE is disabled) and
537
+      // the hardware finished transmission (TXC is set).
419
     }
538
     }
420
 
539
 
421
   #else // TX_BUFFER_SIZE == 0
540
   #else // TX_BUFFER_SIZE == 0
422
 
541
 
423
     void MarlinSerial::write(const uint8_t c) {
542
     void MarlinSerial::write(const uint8_t c) {
543
+      _written = true;
424
       while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
544
       while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
425
       HWUART->UART_THR = c;
545
       HWUART->UART_THR = c;
426
     }
546
     }
427
 
547
 
548
+    void MarlinSerial::flushTX(void) {
549
+      // TX
550
+
551
+      // No bytes written, no need to flush. This special case is needed since there's
552
+      // no way to force the TXC (transmit complete) bit to 1 during initialization.
553
+      if (!_written) return;
554
+
555
+      // Wait until everything was transmitted
556
+      while (!(HWUART->UART_SR & UART_SR_TXEMPTY)) sw_barrier();
557
+
558
+      // At this point nothing is queued anymore (DRIE is disabled) and
559
+      // the hardware finished transmission (TXC is set).
560
+    }
428
   #endif // TX_BUFFER_SIZE == 0
561
   #endif // TX_BUFFER_SIZE == 0
429
 
562
 
430
   /**
563
   /**
431
-  * Imports from print.h
432
-  */
564
+   * Imports from print.h
565
+   */
433
 
566
 
434
   void MarlinSerial::print(char c, int base) {
567
   void MarlinSerial::print(char c, int base) {
435
     print((long)c, base);
568
     print((long)c, base);
448
   }
581
   }
449
 
582
 
450
   void MarlinSerial::print(long n, int base) {
583
   void MarlinSerial::print(long n, int base) {
451
-    if (base == 0)
452
-      write(n);
584
+    if (base == 0) write(n);
453
     else if (base == 10) {
585
     else if (base == 10) {
454
-      if (n < 0) {
455
-        print('-');
456
-        n = -n;
457
-      }
586
+      if (n < 0) { print('-'); n = -n; }
458
       printNumber(n, 10);
587
       printNumber(n, 10);
459
     }
588
     }
460
     else
589
     else
546
 
675
 
547
     // Round correctly so that print(1.999, 2) prints as "2.00"
676
     // Round correctly so that print(1.999, 2) prints as "2.00"
548
     double rounding = 0.5;
677
     double rounding = 0.5;
549
-    for (uint8_t i = 0; i < digits; ++i)
550
-      rounding *= 0.1;
551
-
678
+    for (uint8_t i = 0; i < digits; ++i) rounding *= 0.1;
552
     number += rounding;
679
     number += rounding;
553
 
680
 
554
     // Extract the integer part of the number and print it
681
     // Extract the integer part of the number and print it

+ 17
- 3
Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.h ファイルの表示

70
   extern uint8_t rx_dropped_bytes;
70
   extern uint8_t rx_dropped_bytes;
71
 #endif
71
 #endif
72
 
72
 
73
+#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
74
+  extern uint8_t rx_buffer_overruns;
75
+#endif
76
+
77
+#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
78
+  extern uint8_t rx_framing_errors;
79
+#endif
80
+
73
 #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
81
 #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
74
   extern ring_buffer_pos_t rx_max_enqueued;
82
   extern ring_buffer_pos_t rx_max_enqueued;
75
 #endif
83
 #endif
85
   static void flush(void);
93
   static void flush(void);
86
   static ring_buffer_pos_t available(void);
94
   static ring_buffer_pos_t available(void);
87
   static void write(const uint8_t c);
95
   static void write(const uint8_t c);
88
-  #if TX_BUFFER_SIZE > 0
89
-    static void flushTX(void);
90
-  #endif
96
+  static void flushTX(void);
91
 
97
 
92
   #if ENABLED(SERIAL_STATS_DROPPED_RX)
98
   #if ENABLED(SERIAL_STATS_DROPPED_RX)
93
     FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }
99
     FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }
94
   #endif
100
   #endif
95
 
101
 
102
+  #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
103
+    FORCE_INLINE static uint32_t buffer_overruns() { return rx_buffer_overruns; }
104
+  #endif
105
+
106
+  #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
107
+    FORCE_INLINE static uint32_t framing_errors() { return rx_framing_errors; }
108
+  #endif
109
+
96
   #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
110
   #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
97
     FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return rx_max_enqueued; }
111
     FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return rx_max_enqueued; }
98
   #endif
112
   #endif

+ 17
- 0
Marlin/src/gcode/control/M111.cpp ファイルの表示

58
   }
58
   }
59
   else {
59
   else {
60
     SERIAL_ECHOPGM(MSG_DEBUG_OFF);
60
     SERIAL_ECHOPGM(MSG_DEBUG_OFF);
61
+    #if !defined(__AVR__) || !defined(USBCON)
62
+      #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
63
+        SERIAL_ECHOLNPAIR("Buffer Overruns: ", customizedSerial.buffer_overruns());
64
+      #endif
65
+
66
+      #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
67
+        SERIAL_ECHOLNPAIR("Framing Errors: ", customizedSerial.framing_errors());
68
+      #endif
69
+
70
+      #if ENABLED(SERIAL_STATS_DROPPED_RX)
71
+        SERIAL_ECHOLNPAIR("Dropped bytes: ", customizedSerial.dropped());
72
+      #endif
73
+
74
+      #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
75
+        SERIAL_ECHOLNPAIR("Max RX Queue Size: ", customizedSerial.rxMaxEnqueued());
76
+      #endif
77
+    #endif //  !defined(__AVR__) || !defined(USBCON)
61
   }
78
   }
62
   SERIAL_EOL();
79
   SERIAL_EOL();
63
 }
80
 }

読み込み中…
キャンセル
保存