Explorar o código

Minimize risk of stepper routine interrupt blocking by reorganizing
the routine to move the G-code line length from the command queue
to the planner queue.

bubnikv %!s(int64=6) %!d(string=hai) anos
pai
achega
9e534c1990
Modificáronse 2 ficheiros con 31 adicións e 9 borrados
  1. 27 9
      Firmware/Marlin_main.cpp
  2. 4 0
      Firmware/cmdqueue.h

+ 27 - 9
Firmware/Marlin_main.cpp

@@ -1409,8 +1409,12 @@ void loop()
     #endif //SDSUPPORT
 
     if (! cmdbuffer_front_already_processed && buflen)
-	  {
-		    cli();
+    {
+      // ptr points to the start of the block currently being processed.
+      // The first character in the block is the block type.      
+      char *ptr = cmdbuffer + bufindr;
+      if (*ptr == CMDBUFFER_CURRENT_TYPE_SDCARD) {
+        // To support power panic, move the lenght of the command on the SD card to a planner buffer.
         union {
           struct {
               char lo;
@@ -1419,14 +1423,28 @@ void loop()
           uint16_t value;
         } sdlen;
         sdlen.value = 0;
-		    if (CMDBUFFER_CURRENT_TYPE == CMDBUFFER_CURRENT_TYPE_SDCARD) {
-			      sdlen.lohi.lo = cmdbuffer[bufindr + 1];
-            sdlen.lohi.hi = cmdbuffer[bufindr + 2];
+        {
+          // This block locks the interrupts globally for 3.25 us,
+          // which corresponds to a maximum repeat frequency of 307.69 kHz.
+          // This blocking is safe in the context of a 10kHz stepper driver interrupt
+          // or a 115200 Bd serial line receive interrupt, which will not trigger faster than 12kHz.
+          cli();
+          // Reset the command to something, which will be ignored by the power panic routine,
+          // so this buffer length will not be counted twice.
+          *ptr ++ = CMDBUFFER_CURRENT_TYPE_TO_BE_REMOVED;
+          // Extract the current buffer length.
+          sdlen.lohi.lo = *ptr ++;
+          sdlen.lohi.hi = *ptr;
+          // and pass it to the planner queue.
+          planner_add_sd_length(sdlen.value);
+          sei();
         }
-	      cmdqueue_pop_front();
-		    planner_add_sd_length(sdlen.value);
-		    sei();
-	  }
+      }
+      // Now it is safe to release the already processed command block. If interrupted by the power panic now,
+      // this block's SD card length will not be counted twice as its command type has been replaced 
+      // by CMDBUFFER_CURRENT_TYPE_TO_BE_REMOVED.
+      cmdqueue_pop_front();
+    }
 	host_keepalive();
   }
 }

+ 4 - 0
Firmware/cmdqueue.h

@@ -18,6 +18,10 @@
 #define CMDBUFFER_CURRENT_TYPE_UI       3
 // Command in cmdbuffer was generated by another G-code.
 #define CMDBUFFER_CURRENT_TYPE_CHAINED  4
+// Command has been processed and its SD card length has been possibly pushed 
+// to the planner queue, but not yet removed from the cmdqueue. 
+// This is a temporary state to reduce stepper interrupt locking time.
+#define CMDBUFFER_CURRENT_TYPE_TO_BE_REMOVED 5
 
 // How much space to reserve for the chained commands
 // of type CMDBUFFER_CURRENT_TYPE_CHAINED,