From 87c5703200c1d85c4196130a7a2fd434bb1de644 Mon Sep 17 00:00:00 2001 From: Sonny Jeon Date: Sun, 6 Jul 2014 19:05:12 -0600 Subject: [PATCH] Isolate atomic bit flag for execution. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Denoted bit_true_atomic only for sys.execute bit settings. All other bit_true type calls are for local variables only and don’t need atomic access. Still looking into other ways of setting these flags without requiring atomic access, but this is a patch for now. --- gcode.c | 4 ++-- limits.c | 10 +++++----- motion_control.c | 10 +++++----- nuts_bolts.h | 8 +++++--- protocol.c | 14 +++++++------- serial.c | 6 +++--- stepper.c | 2 +- 7 files changed, 28 insertions(+), 26 deletions(-) diff --git a/gcode.c b/gcode.c index 97a97b3..a68373e 100644 --- a/gcode.c +++ b/gcode.c @@ -264,7 +264,7 @@ uint8_t gc_execute_line(char *line) // Check for more than one command per modal group violations in the current block // NOTE: Variable 'word_bit' is always assigned, if the command is valid. if ( bit_istrue(command_words,bit(word_bit)) ) { FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); } - bit_true(command_words,bit(word_bit)); + command_words |= bit(word_bit); break; case 'M': @@ -307,7 +307,7 @@ uint8_t gc_execute_line(char *line) // Check for more than one command per modal group violations in the current block // NOTE: Variable 'word_bit' is always assigned, if the command is valid. if ( bit_istrue(command_words,bit(word_bit)) ) { FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); } - bit_true(command_words,bit(word_bit)); + command_words |= bit(word_bit); break; // NOTE: All remaining letters assign values. diff --git a/limits.c b/limits.c index f6e5f01..030438e 100644 --- a/limits.c +++ b/limits.c @@ -86,7 +86,7 @@ ISR(LIMIT_INT_vect) // DEFAULT: Limit pin change interrupt process. if (sys.state != STATE_ALARM) { if (bit_isfalse(sys.execute,EXEC_ALARM)) { mc_reset(); // Initiate system kill. - bit_true(sys.execute, (EXEC_ALARM | EXEC_CRIT_EVENT)); // Indicate hard limit critical event + bit_true_atomic(sys.execute, (EXEC_ALARM | EXEC_CRIT_EVENT)); // Indicate hard limit critical event } } } @@ -103,7 +103,7 @@ ISR(WDT_vect) // Watchdog timer ISR if (bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { bits ^= LIMIT_MASK; } if (bits & LIMIT_MASK) { mc_reset(); // Initiate system kill. - bit_true(sys.execute, (EXEC_ALARM | EXEC_CRIT_EVENT)); // Indicate hard limit critical event + bit_true_atomic(sys.execute, (EXEC_ALARM | EXEC_CRIT_EVENT)); // Indicate hard limit critical event } } } @@ -238,7 +238,7 @@ void limits_go_home(uint8_t cycle_mask) // Initiate pull-off using main motion control routines. // TODO : Clean up state routines so that this motion still shows homing state. sys.state = STATE_QUEUED; - bit_true(sys.execute, EXEC_CYCLE_START); + bit_true_atomic(sys.execute, EXEC_CYCLE_START); protocol_execute_runtime(); protocol_buffer_synchronize(); // Complete pull-off motion. @@ -259,7 +259,7 @@ void limits_soft_check(float *target) // workspace volume so just come to a controlled stop so position is not lost. When complete // enter alarm mode. if (sys.state == STATE_CYCLE) { - bit_true(sys.execute, EXEC_FEED_HOLD); + bit_true_atomic(sys.execute, EXEC_FEED_HOLD); do { protocol_execute_runtime(); if (sys.abort) { return; } @@ -267,7 +267,7 @@ void limits_soft_check(float *target) } mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown. - bit_true(sys.execute, (EXEC_ALARM | EXEC_CRIT_EVENT)); // Indicate soft limit critical event + bit_true_atomic(sys.execute, (EXEC_ALARM | EXEC_CRIT_EVENT)); // Indicate soft limit critical event protocol_execute_runtime(); // Execute to enter critical event loop and system abort return; diff --git a/motion_control.c b/motion_control.c index c57dfea..f3c8b2d 100644 --- a/motion_control.c +++ b/motion_control.c @@ -288,13 +288,13 @@ void mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate) // NOTE: Parser error-checking ensures the probe isn't already closed/triggered. sys.probe_state = PROBE_ACTIVE; - bit_true(sys.execute, EXEC_CYCLE_START); + bit_true_atomic(sys.execute, EXEC_CYCLE_START); do { protocol_execute_runtime(); if (sys.abort) { return; } // Check for system abort } while ((sys.state != STATE_IDLE) && (sys.state != STATE_QUEUED)); - if (sys.probe_state == PROBE_ACTIVE) { bit_true(sys.execute, EXEC_CRIT_EVENT); } + if (sys.probe_state == PROBE_ACTIVE) { bit_true_atomic(sys.execute, EXEC_CRIT_EVENT); } protocol_execute_runtime(); // Check and execute run-time commands if (sys.abort) { return; } // Check for system abort @@ -316,7 +316,7 @@ void mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate) mc_line(target, feed_rate, invert_feed_rate); // Bypass mc_line(). Directly plan homing motion. #endif - bit_true(sys.execute, EXEC_CYCLE_START); + bit_true_atomic(sys.execute, EXEC_CYCLE_START); protocol_buffer_synchronize(); // Complete pull-off motion. if (sys.abort) { return; } // Did not complete. Alarm state set by mc_alarm. @@ -337,7 +337,7 @@ void mc_reset() { // Only this function can set the system reset. Helps prevent multiple kill calls. if (bit_isfalse(sys.execute, EXEC_RESET)) { - bit_true(sys.execute, EXEC_RESET); + bit_true_atomic(sys.execute, EXEC_RESET); // Kill spindle and coolant. spindle_stop(); @@ -348,7 +348,7 @@ void mc_reset() // the steppers enabled by avoiding the go_idle call altogether, unless the motion state is // violated, by which, all bets are off. if (sys.state & (STATE_CYCLE | STATE_HOLD | STATE_HOMING)) { - bit_true(sys.execute, EXEC_ALARM); // Flag main program to execute alarm state. + bit_true_atomic(sys.execute, EXEC_ALARM); // Flag main program to execute alarm state. st_go_idle(); // Force kill steppers. Position has likely been lost. } } diff --git a/nuts_bolts.h b/nuts_bolts.h index 5cab6f4..1417fa9 100644 --- a/nuts_bolts.h +++ b/nuts_bolts.h @@ -44,9 +44,11 @@ // Bit field and masking macros #define bit(n) (1 << n) -#define bit_true(x,mask) {uint8_t sreg = SREG; cli(); (x) |= (mask); SREG = sreg; } -#define bit_false(x,mask) {uint8_t sreg = SREG; cli(); (x) &= ~(mask); SREG = sreg; } -#define bit_toggle(x,mask) {uint8_t sreg = SREG; cli(); (x) ^= (mask); SREG = sreg; } +#define bit_true_atomic(x,mask) {uint8_t sreg = SREG; cli(); (x) |= (mask); SREG = sreg; } +#define bit_false_atomic(x,mask) {uint8_t sreg = SREG; cli(); (x) &= ~(mask); SREG = sreg; } +#define bit_toggle_atomic(x,mask) {uint8_t sreg = SREG; cli(); (x) ^= (mask); SREG = sreg; } +#define bit_true(x,mask) (x) |= (mask) +#define bit_false(x,mask) (x) &= ~(mask) #define bit_istrue(x,mask) ((x & mask) != 0) #define bit_isfalse(x,mask) ((x & mask) == 0) diff --git a/protocol.c b/protocol.c index 45f6c27..9507ca8 100644 --- a/protocol.c +++ b/protocol.c @@ -192,7 +192,7 @@ void protocol_execute_runtime() if (rt_exec & EXEC_ALARM) { report_alarm_message(ALARM_LIMIT_ERROR); } else { report_alarm_message(ALARM_PROBE_FAIL); } report_feedback_message(MESSAGE_CRITICAL_EVENT); - bit_false(sys.execute,EXEC_RESET); // Disable any existing reset + bit_false_atomic(sys.execute,EXEC_RESET); // Disable any existing reset do { // Nothing. Block EVERYTHING until user issues reset or power cycles. Hard limits // typically occur while unattended or not paying attention. Gives the user time @@ -208,7 +208,7 @@ void protocol_execute_runtime() // to indicate the possible severity of the problem. report_alarm_message(ALARM_ABORT_CYCLE); } - bit_false(sys.execute,(EXEC_ALARM | EXEC_CRIT_EVENT)); + bit_false_atomic(sys.execute,(EXEC_ALARM | EXEC_CRIT_EVENT)); } // Execute system abort. @@ -220,7 +220,7 @@ void protocol_execute_runtime() // Execute and serial print status if (rt_exec & EXEC_STATUS_REPORT) { report_realtime_status(); - bit_false(sys.execute,EXEC_STATUS_REPORT); + bit_false_atomic(sys.execute,EXEC_STATUS_REPORT); } // Execute a feed hold with deceleration, only during cycle. @@ -233,7 +233,7 @@ void protocol_execute_runtime() st_prep_buffer(); sys.auto_start = false; // Disable planner auto start upon feed hold. } - bit_false(sys.execute,EXEC_FEED_HOLD); + bit_false_atomic(sys.execute,EXEC_FEED_HOLD); } // Execute a cycle start by starting the stepper interrupt begin executing the blocks in queue. @@ -248,7 +248,7 @@ void protocol_execute_runtime() sys.auto_start = false; // Reset auto start per settings. } } - bit_false(sys.execute,EXEC_CYCLE_START); + bit_false_atomic(sys.execute,EXEC_CYCLE_START); } // Reinitializes the cycle plan and stepper system after a feed hold for a resume. Called by @@ -259,7 +259,7 @@ void protocol_execute_runtime() if (rt_exec & EXEC_CYCLE_STOP) { if ( plan_get_current_block() ) { sys.state = STATE_QUEUED; } else { sys.state = STATE_IDLE; } - bit_false(sys.execute,EXEC_CYCLE_STOP); + bit_false_atomic(sys.execute,EXEC_CYCLE_STOP); } } @@ -296,4 +296,4 @@ void protocol_buffer_synchronize() // NOTE: This function is called from the main loop and mc_line() only and executes when one of // two conditions exist respectively: There are no more blocks sent (i.e. streaming is finished, // single commands), or the planner buffer is full and ready to go. -void protocol_auto_cycle_start() { if (sys.auto_start) { bit_true(sys.execute, EXEC_CYCLE_START); } } +void protocol_auto_cycle_start() { if (sys.auto_start) { bit_true_atomic(sys.execute, EXEC_CYCLE_START); } } diff --git a/serial.c b/serial.c index bcbffaa..9f352f5 100644 --- a/serial.c +++ b/serial.c @@ -157,9 +157,9 @@ ISR(SERIAL_RX) // Pick off runtime command characters directly from the serial stream. These characters are // not passed into the buffer, but these set system state flag bits for runtime execution. switch (data) { - case CMD_STATUS_REPORT: bit_true(sys.execute, EXEC_STATUS_REPORT); break; // Set as true - case CMD_CYCLE_START: bit_true(sys.execute, EXEC_CYCLE_START); break; // Set as true - case CMD_FEED_HOLD: bit_true(sys.execute, EXEC_FEED_HOLD); break; // Set as true + case CMD_STATUS_REPORT: bit_true_atomic(sys.execute, EXEC_STATUS_REPORT); break; // Set as true + case CMD_CYCLE_START: bit_true_atomic(sys.execute, EXEC_CYCLE_START); break; // Set as true + case CMD_FEED_HOLD: bit_true_atomic(sys.execute, EXEC_FEED_HOLD); break; // Set as true case CMD_RESET: mc_reset(); break; // Call motion control reset routine. default: // Write character to buffer next_head = rx_buffer_head + 1; diff --git a/stepper.c b/stepper.c index 496f916..b6f6fe0 100644 --- a/stepper.c +++ b/stepper.c @@ -342,7 +342,7 @@ ISR(TIMER1_COMPA_vect) } else { // Segment buffer empty. Shutdown. st_go_idle(); - bit_true(sys.execute,EXEC_CYCLE_STOP); // Flag main program for cycle end + bit_true_atomic(sys.execute,EXEC_CYCLE_STOP); // Flag main program for cycle end return; // Nothing to do but exit. } }