Use util/atomic.h, Small stepper interrupt speed improvement, Code cleanup, Pass...
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Wed, 20 Nov 2019 00:05:52 +0000 (16:05 -0800)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Wed, 20 Nov 2019 00:05:52 +0000 (16:05 -0800)
14 files changed:
src/avr/src/axis.c
src/avr/src/config.h
src/avr/src/drv8711.c
src/avr/src/exec.c
src/avr/src/huanyang.c
src/avr/src/motor.c
src/avr/src/pwm.c
src/avr/src/pwm.h
src/avr/src/ringbuf.def
src/avr/src/spindle.c
src/avr/src/spindle.h
src/avr/src/stepper.c
src/avr/src/usart.c
src/avr/src/vfd_spindle.c

index d85c002f8d85104a97f43479cadfb116b5dd7108..1f891f5cdcbb013daed467e348a3109ef6065b78 100644 (file)
@@ -95,23 +95,7 @@ void axis_map_motors() {
   void set_##NAME(int axis, TYPE value) {axes[axis].NAME = value;}
 
 
-#define AXIS_GET(NAME, TYPE, DEFAULT)                   \
-  TYPE axis_get_##NAME(int axis) {                      \
-    int motor = axis_get_motor(axis);                   \
-    return motor == -1 ? DEFAULT : axes[motor].NAME;    \
-  }                                                     \
-  AXIS_VAR_GET(NAME, TYPE)
-
-
-#define AXIS_SET(NAME, TYPE)                            \
-  void axis_set_##NAME(int axis, TYPE value) {          \
-    int motor = axis_get_motor(axis);                   \
-    if (motor != -1) axes[motor].NAME = value;          \
-  }                                                     \
-  AXIS_VAR_SET(NAME, TYPE)
-
-
-/// Velocity is scaled by 1,000.
+/// Velocity is scaled by 1,000
 float axis_get_velocity_max(int axis) {
   int motor = axis_get_motor(axis);
   return motor == -1 ? 0 : axes[motor].velocity_max * VELOCITY_MULTIPLIER;
@@ -119,7 +103,7 @@ float axis_get_velocity_max(int axis) {
 AXIS_VAR_GET(velocity_max, float)
 
 
-/// Acceleration is scaled by 1,000.
+/// Acceleration is scaled by 1,000
 float axis_get_accel_max(int axis) {
   int motor = axis_get_motor(axis);
   return motor == -1 ? 0 : axes[motor].accel_max * ACCEL_MULTIPLIER;
@@ -127,7 +111,7 @@ float axis_get_accel_max(int axis) {
 AXIS_VAR_GET(accel_max, float)
 
 
-/// Jerk is scaled by 1,000,000.
+/// Jerk is scaled by 1,000,000
 float axis_get_jerk_max(int axis) {
   int motor = axis_get_motor(axis);
   return motor == -1 ? 0 : axes[motor].jerk_max * JERK_MULTIPLIER;
index 68df3849cbc7a1a2f04b37f42b48ef8993f26c35..a224b4d793484587c481c30f18a7ace54f09c05b 100644 (file)
@@ -112,12 +112,15 @@ enum {
 
 /* Interrupt usage:
  *
- *    HI    Stepper timers                       (set in stepper.h)
- *    LO    Segment execution SW interrupt       (set in stepper.h)
- *   MED    Serial RX                            (set in usart.c)
- *   MED    Serial TX                            (set in usart.c) (* see note)
- *   MED    I2C Slave                            (set in i2c.c)
- *    LO    Real time clock interrupt            (set in rtc.h)
+ *    HI    Step timers                          stepper.c
+ *    HI    Serial RX                            usart.c
+ *   MED    Serial TX                            usart.c (* see note)
+ *   MED    Modbus serial interrupts             modbus.c
+ *    LO    Segment execution SW interrupt       stepper.c
+ *    LO    I2C Slave                            i2c.c
+ *    LO    Real-time clock interrupt            rtc.c
+ *    LO    DRV8711 SPI                          drv8711.c
+ *    LO    A2D interrupts                       analog.c
  *
  *    (*) The TX cannot run at LO level or exception reports and other prints
  *        called from a LO interrupt (as in prep_line()) will kill the system
@@ -125,19 +128,16 @@ enum {
  */
 
 // Timer assignments
-// NOTE, TCC1 free
+// NOTE, TCC1 is unused
 #define TIMER_STEP               TCC0 // Step timer (see stepper.h)
 #define TIMER_PWM                TCD1 // PWM timer  (see pwm.c)
 
 
 // Timer setup for stepper and dwells
-#define STEP_TIMER_ENABLE        TC_CLKSEL_DIV8_gc
 #define STEP_TIMER_DIV           8
 #define STEP_TIMER_FREQ          (F_CPU / STEP_TIMER_DIV)
 #define STEP_TIMER_POLL          ((uint16_t)(STEP_TIMER_FREQ * 0.001)) // 1ms
-#define STEP_TIMER_WGMODE        TC_WGMODE_NORMAL_gc // count to TOP & rollover
 #define STEP_TIMER_ISR           TCC0_OVF_vect
-#define STEP_TIMER_INTLVL        TC_OVFINTLVL_HI_gc
 #define STEP_LOW_LEVEL_ISR       ADCB_CH0_vect
 #define STEP_PULSE_WIDTH         (F_CPU * 0.000002 / 2) // 2uS w/ clk/2
 #define SEGMENT_MS               4
index ca7a8f635af08d277722c0aa2efa306032d16235..dbc4de3514fb72101af1950e3e4b38c92d17ea58 100644 (file)
@@ -322,7 +322,7 @@ static void _motor_fault_switch_cb(switch_id_t sw, bool active) {
 
 void drv8711_init() {
   // Setup pins
-  // Must set the SS pin either in/high or any/output for master mode to work
+  // Must set the SS pin either in/high or out/any for master mode to work
   // Note, this pin is also used by the USART as the CTS line
   DIRSET_PIN(SPI_SS_PIN);   // Output
   OUTSET_PIN(SPI_CLK_PIN);  // High
index c8f93147da7873120767793953ad220bdee64467..e5f6fe03dc54bebb4f0e9d0d382f50603278c8ff 100644 (file)
@@ -300,6 +300,7 @@ void command_set_axis_exec(void *data) {
   ex.position[cmd->axis] = cmd->position;
 
   // Update motors
-  int motor = axis_get_motor(cmd->axis);
-  if (0 <= motor) motor_set_position(motor, cmd->position);
+  for (int motor = 0; motor < MOTORS; motor++)
+    if (motor_get_axis(motor) == cmd->axis)
+      motor_set_position(motor, cmd->position);
 }
index 8986702f5aa4e972420b65567df795f18b2497ba..26481e1e30e925901dc5b8bc2f3417bca4e929ff 100644 (file)
@@ -30,6 +30,8 @@
 #include "modbus.h"
 #include "estop.h"
 
+#include <util/atomic.h>
+
 #include <string.h>
 #include <math.h>
 
@@ -279,12 +281,11 @@ void huanyang_deinit(deinit_cb_t cb) {
 
 
 void huanyang_set(float power) {
-  cli();
-  if (hy.power != power && !hy.shutdown) {
-    hy.power = power;
-    hy.changed = true;
-  }
-  sei();
+  if (hy.power != power && !hy.shutdown)
+    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+      hy.power = power;
+      hy.changed = true;
+    }
 }
 
 
index 2edc42c98592b4d01b07bda9ed65d19a45e3201f..cee1e9c8a1a67791c9fa3ec3f836b3abc960f47f 100644 (file)
@@ -224,59 +224,59 @@ void motor_emulate_steps(int motor) {
 
 
 void motor_end_move(int motor) {
-  motor_t *m = &motors[motor];
+  motor_t &m = motors[motor];
 
-  if (!m->timer->CTRLA) return;
+  if (!m.timer->CTRLA) return;
 
   // Stop clock
-  m->timer->CTRLA = 0;
+  m.timer->CTRLA = 0;
 
   // Wait for pending DMA transfers
-  while (m->dma->CTRLB & DMA_CH_CHPEND_bm) continue;
+  while (m.dma->CTRLB & DMA_CH_CHPEND_bm) continue;
 
   // Get actual step count from DMA channel
-  const int32_t steps = 0xffff - m->dma->TRFCNT;
+  const int32_t steps = 0xffff - m.dma->TRFCNT;
 
   // Accumulate encoder & compute error
-  m->encoder += m->last_negative ? -steps : steps;
-  m->error = m->commanded - m->encoder;
+  m.encoder += m.last_negative ? -steps : steps;
+  m.error = m.commanded - m.encoder;
 }
 
 
 void motor_load_move(int motor) {
-  motor_t *m = &motors[motor];
+  motor_t &m = motors[motor];
 
   // Clear move
-  ESTOP_ASSERT(m->prepped, STAT_MOTOR_NOT_PREPPED);
-  m->prepped = false;
+  ESTOP_ASSERT(m.prepped, STAT_MOTOR_NOT_PREPPED);
+  m.prepped = false;
 
   motor_end_move(motor);
 
-  if (!m->timer_period) return; // Leave clock stopped
+  if (!m.timer_period) return; // Leave clock stopped
 
   // Set direction, compensating for polarity but only when moving
-  const bool dir = m->negative ^ m->reverse;
-  if (dir != IN_PIN(m->dir_pin)) {
-    SET_PIN(m->dir_pin, dir);
+  const bool dir = m.negative ^ m.reverse;
+  if (dir != IN_PIN(m.dir_pin)) {
+    SET_PIN(m.dir_pin, dir);
 
     // We need at least 200ns between direction change and next step.
-    if (m->timer->CCA < m->timer->CNT) m->timer->CNT = m->timer->CCA + 1;
+    if (m.timer->CCA < m.timer->CNT) m.timer->CNT = m.timer->CCA + 1;
   }
 
   // Reset DMA step counter
-  m->dma->CTRLA &= ~DMA_CH_ENABLE_bm;
-  m->dma->TRFCNT = 0xffff;
-  m->dma->CTRLA |= DMA_CH_ENABLE_bm;
+  m.dma->CTRLA &= ~DMA_CH_ENABLE_bm;
+  m.dma->TRFCNT = 0xffff;
+  m.dma->CTRLA |= DMA_CH_ENABLE_bm;
 
   // To avoid causing couter wrap around, it is important to start the clock
   // before setting PERBUF.  If PERBUF is set before the clock is started PER
   // updates immediately and possibly mid step.
 
   // Set clock and period
-  m->timer->CTRLA  = m->clock;         // Start clock
-  m->timer->PERBUF = m->timer_period;  // Set next frequency
-  m->last_negative = m->negative;
-  m->commanded     = m->position;
+  m.timer->CTRLA  = m.clock;         // Start clock
+  m.timer->PERBUF = m.timer_period;  // Set next frequency
+  m.last_negative = m.negative;
+  m.commanded     = m.position;
 }
 
 
@@ -285,27 +285,27 @@ void motor_prep_move(int motor, float target) {
   ESTOP_ASSERT(0 <= motor && motor < MOTORS, STAT_MOTOR_ID_INVALID);
   ESTOP_ASSERT(isfinite(target), STAT_BAD_FLOAT);
 
-  motor_t *m = &motors[motor];
-  ESTOP_ASSERT(!m->prepped, STAT_MOTOR_NOT_READY);
+  motor_t &m = motors[motor];
+  ESTOP_ASSERT(!m.prepped, STAT_MOTOR_NOT_READY);
 
   // Travel in steps
   int32_t position = _position_to_steps(motor, target);
-  int24_t steps = position - m->position;
-  m->position = position;
+  int24_t steps = position - m.position;
+  m.position = position;
 
   // Error correction
-  int16_t correction = abs(m->error);
+  int16_t correction = abs(m.error);
   if (MIN_STEP_CORRECTION <= correction) {
     // Dampen correction oscillation
     correction >>= 1;
 
     // Make correction
-    steps += m->error < 0 ? -correction : correction;
+    steps += m.error < 0 ? -correction : correction;
   }
 
   // Positive steps from here on
-  m->negative = steps < 0;
-  if (m->negative) steps = -steps;
+  m.negative = steps < 0;
+  if (m.negative) steps = -steps;
 
   // Start with clock / 2
   const float seg_clocks = SEGMENT_TIME * (F_CPU * 60 / 2);
@@ -321,27 +321,27 @@ void motor_prep_move(int motor, float target) {
   // Use faster clock with faster step rates for increased resolution.
   if (ticks_per_step < 0x7fff) {
     ticks_per_step *= 2;
-    m->clock = TC_CLKSEL_DIV1_gc;
+    m.clock = TC_CLKSEL_DIV1_gc;
 
-  } else m->clock = TC_CLKSEL_DIV2_gc;
+  } else m.clock = TC_CLKSEL_DIV2_gc;
 
   // Disable clock if too slow
   if (0xffff <= ticks_per_step) ticks_per_step = 0;
 
-  m->timer_period = steps ? round(ticks_per_step) : 0;
+  m.timer_period = steps ? round(ticks_per_step) : 0;
 
   // Power motor
-  if (!m->enabled) {
-    m->timer_period = 0;
-    m->encoder = m->commanded = m->position;
-    m->error = 0;
+  if (!m.enabled) {
+    m.timer_period = 0;
+    m.encoder = m.commanded = m.position;
+    m.error = 0;
 
-  } else if (m->timer_period) // Motor is moving so reset power timeout
-    m->power_timeout = rtc_get_time() + MOTOR_IDLE_TIMEOUT * 1000;
+  } else if (m.timer_period) // Motor is moving so reset power timeout
+    m.power_timeout = rtc_get_time() + MOTOR_IDLE_TIMEOUT * 1000;
   _update_power(motor);
 
   // Queue move
-  m->prepped = true;
+  m.prepped = true;
 }
 
 
index 524a4a3203ba12cd15b6f859d1661633dd1fcd8f..165996439546cd6a896c0a2f01895ef88e07e8e4 100644 (file)
@@ -173,7 +173,7 @@ power_update_t pwm_get_update(float power) {
 
 
 // Called from hi-priority stepper interrupt, must be very fast
-void pwm_update(power_update_t update) {
+void pwm_update(const power_update_t &update) {
   if (!pwm.initialized || update.state == POWER_IGNORE) return;
   _update_clock(update.period);
   if (update.period) _set_dir(update.state == POWER_FORWARD);
index 044d811195477d0c1a326f6b90b0731df9db2fde..23c723b394709a6dcf31e2ac778e9b521392054b 100644 (file)
@@ -34,4 +34,4 @@ void pwm_init();
 float pwm_get();
 void pwm_deinit(deinit_cb_t cb);
 power_update_t pwm_get_update(float power);
-void pwm_update(power_update_t update);
+void pwm_update(const power_update_t &update);
index 9fff9641b718f6b9da932e404e4dec75c6156154..1f4bad908c14545eccf6b835ec9b22ebdc8f4056 100644 (file)
@@ -122,17 +122,13 @@ RING_BUF_FUNC void CONCAT(RING_BUF_NAME, _init)() {
   }
 
 
-#define _RING_BUF_ATOMIC_WRITE_INDEX(INDEX, TARGET)                     \
+#define RING_BUF_ATOMIC_WRITE_INDEX(INDEX)                              \
   RING_BUF_FUNC void CONCAT(RING_BUF_NAME, _write_##INDEX)              \
-  (RING_BUF_INDEX_TYPE value) {                                         \
-    RING_BUF_ATOMIC_COPY(TARGET, value);                                \
+    (RING_BUF_INDEX_TYPE value) {                                       \
+    RING_BUF_ATOMIC_COPY(RING_BUF.INDEX, value);                        \
   }
 
 
-#define RING_BUF_ATOMIC_WRITE_INDEX(INDEX)                              \
-  _RING_BUF_ATOMIC_WRITE_INDEX(INDEX, RING_BUF.INDEX)
-
-
 RING_BUF_ATOMIC_READ_INDEX(head);
 RING_BUF_ATOMIC_READ_INDEX(tail);
 RING_BUF_ATOMIC_WRITE_INDEX(head);
index 6b2566d8c8442b8c5b17b6a708b0b4a0d42029d2..cd39a8855fdebe40896467cc84ba12ea6d1b377f 100644 (file)
@@ -189,7 +189,7 @@ void spindle_load_power_updates(power_update_t updates[], float minD,
 
 
 // Called from hi-priority stepper interrupt
-void spindle_update(power_update_t update) {pwm_update(update);}
+void spindle_update(const power_update_t &update) {pwm_update(update);}
 void spindle_update_speed() {_set_speed(spindle.speed);}
 
 
index b3f83953754a0d036043977b8942eed20b143028..556a512610e8ef801a12a14cd861716b9e3a5e50 100644 (file)
@@ -67,6 +67,6 @@ void spindle_stop();
 void spindle_estop();
 void spindle_load_power_updates(power_update_t updates[], float minD,
                                 float maxD);
-void spindle_update(power_update_t update);
+void spindle_update(const power_update_t &update);
 void spindle_update_speed();
 void spindle_idle();
index 21feec0767de0893b346318cb8ec8d92bffe5f15..68453f76dcefd1fa083f56191f63321c63fd215a 100644 (file)
@@ -36,6 +36,8 @@
 #include "exec.h"
 #include "drv8711.h"
 
+#include <util/atomic.h>
+
 #include <string.h>
 #include <stdio.h>
 
@@ -45,14 +47,16 @@ typedef struct {
   bool busy;
   bool requesting;
   float dwell;
+  uint8_t power_buf;
   uint8_t power_index;
-  power_update_t powers[POWER_MAX_UPDATES];
 
   // Move prep
   bool move_ready;  // Prepped move ready for loader
   bool move_queued; // Prepped move queued
   float prep_dwell;
-  power_update_t prep_powers[POWER_MAX_UPDATES];
+  int8_t power_next;
+
+  power_update_t powers[2][POWER_MAX_UPDATES];
 
   uint32_t underrun;
 } stepper_t;
@@ -63,10 +67,10 @@ static stepper_t st = {0};
 
 void stepper_init() {
   // Setup step timer
-  TIMER_STEP.CTRLB    = STEP_TIMER_WGMODE; // Waveform mode
-  TIMER_STEP.INTCTRLA = STEP_TIMER_INTLVL; // Interrupt mode
-  TIMER_STEP.PER      = STEP_TIMER_POLL;   // Timer rate
-  TIMER_STEP.CTRLA    = STEP_TIMER_ENABLE; // Start step timer
+  TIMER_STEP.CTRLB    = TC_WGMODE_NORMAL_gc; // Count to TOP & rollover
+  TIMER_STEP.INTCTRLA = TC_OVFINTLVL_HI_gc;  // Interrupt level
+  TIMER_STEP.PER      = STEP_TIMER_POLL;     // Timer rate
+  TIMER_STEP.CTRLA    = TC_CLKSEL_DIV8_gc;   // Start step timer
 }
 
 
@@ -141,7 +145,7 @@ static void _request_exec_move() {
 
 static void _update_power() {
   if (st.power_index < POWER_MAX_UPDATES)
-    spindle_update(st.powers[st.power_index++]);
+    spindle_update(st.powers[st.power_buf][st.power_index++]);
 }
 
 
@@ -189,10 +193,12 @@ ISR(STEP_TIMER_ISR) {
   }
 
   // Handle power updates
-  st.power_index = 0;
-  memcpy(st.powers, st.prep_powers, sizeof(st.powers));
-  memset(st.prep_powers, 0, sizeof(st.prep_powers));
-  _update_power();
+  if (st.power_next != -1) {
+    st.power_index = 0;
+    st.power_buf = st.power_next;
+    st.power_next = -1;
+    _update_power();
+  }
 
   st.busy = true;        // Executing move so mark busy
   st.move_ready = false; // We are done with this move, flip the flag back
@@ -201,7 +207,9 @@ ISR(STEP_TIMER_ISR) {
 
 void st_prep_power(const power_update_t powers[]) {
   ESTOP_ASSERT(!st.move_ready, STAT_STEPPER_NOT_READY);
-  memcpy(st.prep_powers, powers, sizeof(st.prep_powers));
+  st.power_next = !st.power_buf;
+  memcpy(st.powers[st.power_next], powers,
+         sizeof(power_update_t) * POWER_MAX_UPDATES);
 }
 
 
@@ -221,7 +229,8 @@ void st_prep_line(const float target[]) {
 void st_prep_dwell(float seconds) {
   ESTOP_ASSERT(!st.move_ready, STAT_STEPPER_NOT_READY);
   if (seconds <= 1e-4) seconds = 1e-4; // Min dwell
-  spindle_load_power_updates(st.prep_powers, 0, 0);
+  st.power_next = !st.power_buf;
+  spindle_load_power_updates(st.powers[st.power_next], 0, 0);
   st.prep_dwell = seconds;
   st.move_queued = true; // signal prep buffer ready
 }
@@ -233,8 +242,6 @@ uint32_t get_underrun() {return st.underrun;}
 
 float get_dwell_time() {
   float dwell;
-  cli();
-  dwell = st.dwell;
-  sei();
+  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) dwell = st.dwell;
   return dwell;
 }
index f36433244b91d644e8c79c722bfb1845c5fac3ab..d035c0e6ad9e7dea023fe888acc7eb4c3ce20e88 100644 (file)
@@ -84,12 +84,10 @@ ISR(SERIAL_DRE_vect) {
 // Data received interrupt vector
 ISR(SERIAL_RXC_vect) {
   if (rx_buf_full()) _set_rxc_interrupt(false); // Disable interrupt
+  else rx_buf_push(SERIAL_PORT.DATA);
 
-  else {
-    rx_buf_push(SERIAL_PORT.DATA);
-    if (rx_buf_space() < SERIAL_CTS_THRESH)
-      OUTSET_PIN(SERIAL_CTS_PIN); // CTS Hi (disable)
-  }
+  if (rx_buf_space() < SERIAL_CTS_THRESH)
+    OUTSET_PIN(SERIAL_CTS_PIN); // CTS Hi (disable)
 }
 
 
index 7c9530c23dfeed312276a1f92cfffb513ac7f689..40cdf4aeca3215a496ee0df678e507906f33f552 100644 (file)
@@ -32,6 +32,8 @@
 #include "estop.h"
 #include "pgmspace.h"
 
+#include <util/atomic.h>
+
 #include <string.h>
 #include <math.h>
 #include <stdint.h>
@@ -383,12 +385,11 @@ void vfd_spindle_deinit(deinit_cb_t cb) {
 
 
 void vfd_spindle_set(float power) {
-  cli();
-  if (vfd.power != power) {
-    vfd.power = power;
-    vfd.changed = true;
-  }
-  sei();
+  if (vfd.power != power)
+    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+      vfd.power = power;
+      vfd.changed = true;
+    }
 }