From 7326e175606aa3b84827453a3c07641f18984e52 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Wed, 10 Feb 2010 12:56:26 +1100 Subject: [PATCH] misc tidying, added watchdog stuff, moved things around a bit --- mendel/Makefile | 2 +- mendel/dda.c | 40 ++++++++++++---------------------------- mendel/gcode.c | 8 ++++++-- mendel/mendel.c | 22 ++++++++++++++++++---- mendel/serial.c | 9 ++++----- mendel/watchdog.c | 27 +++++++++++++++++++++++++++ mendel/watchdog.h | 12 ++++++++++++ 7 files changed, 80 insertions(+), 40 deletions(-) create mode 100644 mendel/watchdog.c create mode 100644 mendel/watchdog.h diff --git a/mendel/Makefile b/mendel/Makefile index 3463382..ccd1c89 100644 --- a/mendel/Makefile +++ b/mendel/Makefile @@ -14,7 +14,7 @@ PROGRAM = mendel -SOURCES = $(PROGRAM).c serial.c dda.c gcode.c timer.c clock.c temp.c sermsg.c dda_queue.c +SOURCES = $(PROGRAM).c serial.c dda.c gcode.c timer.c clock.c temp.c sermsg.c dda_queue.c watchdog.c ############################################################################## # # diff --git a/mendel/dda.c b/mendel/dda.c index 42238fb..70981d5 100644 --- a/mendel/dda.c +++ b/mendel/dda.c @@ -272,6 +272,7 @@ uint8_t can_step(uint8_t min, uint8_t max, int32_t current, int32_t target, uint */ void dda_step(DDA *dda) { + // called from interrupt context! keep it as simple as possible uint8_t step_option = 0; #define X_CAN_STEP 1 #define Y_CAN_STEP 2 @@ -284,12 +285,11 @@ void dda_step(DDA *dda) { if (DEBUG) serial_writechar('!'); - step_option &= ~(X_CAN_STEP | Y_CAN_STEP | Z_CAN_STEP | E_CAN_STEP | F_CAN_STEP); // step_option |= can_step(x_min(), x_max(), current_position.X, dda->endpoint.X, dda->x_direction) & X_CAN_STEP; -// step_option |= can_step(y_min(), y_max(), current_position.Y, dda->endpoint.Y, dda->y_direction) & Y_CAN_STEP; -// step_option |= can_step(z_min(), z_max(), current_position.Z, dda->endpoint.Z, dda->z_direction) & Z_CAN_STEP; step_option |= can_step(0 , 0 , current_position.X, dda->endpoint.X, dda->x_direction) & X_CAN_STEP; +// step_option |= can_step(y_min(), y_max(), current_position.Y, dda->endpoint.Y, dda->y_direction) & Y_CAN_STEP; step_option |= can_step(0 , 0 , current_position.Y, dda->endpoint.Y, dda->y_direction) & Y_CAN_STEP; +// step_option |= can_step(z_min(), z_max(), current_position.Z, dda->endpoint.Z, dda->z_direction) & Z_CAN_STEP; step_option |= can_step(0 , 0 , current_position.Z, dda->endpoint.Z, dda->z_direction) & Z_CAN_STEP; step_option |= can_step(0 , 0 , current_position.E, dda->endpoint.E, dda->e_direction) & E_CAN_STEP; step_option |= can_step(0 , 0 , current_position.F, dda->endpoint.F, dda->f_direction) & F_CAN_STEP; @@ -354,9 +354,17 @@ void dda_step(DDA *dda) { } } + #if STEP_INTERRUPT_INTERRUPTIBLE + // since we have sent steps to all the motors that will be stepping and the rest of this function isn't so time critical, + // this interrupt can now be interruptible + disableTimerInterrupt(); + sei(); + #endif + if (step_option & F_CAN_STEP) { dda->f_counter -= dda->f_delta; // since we don't allow total_steps to be defined by F, we may need to step multiple times if f_delta is greater than total_steps + // loops in interrupt context are a bad idea, but this is the best way to do this that I've come up with so far while (dda->f_counter < 0) { dda->f_counter += dda->total_steps; @@ -376,25 +384,6 @@ void dda_step(DDA *dda) { } } - #if STEP_INTERRUPT_INTERRUPTIBLE - // this interrupt can now be interruptible - disableTimerInterrupt(); - sei(); - #endif - - // this generates too much debug output for all but the slowest step rates - if (0 && DEBUG) { - serial_writechar('['); - serwrite_hex8(step_option); - serial_writechar(':'); - serwrite_int32(current_position.F); - serial_writechar('/'); - serwrite_int32(dda->endpoint.F); - serial_writechar('#'); - serwrite_uint32(dda->move_duration); - serial_writechar(']'); - } - if (step_option & REAL_MOVE) // we stepped, reset timeout steptimeout = 0; @@ -409,13 +398,8 @@ void dda_step(DDA *dda) { // if we could do anything at all, we're still running // otherwise, must have finished - else if (step_option == 0) { + else if (step_option == 0) dda->live = 0; - #ifdef STUPIDLY_HIDE_BUGS - // this magically makes bugs disappear after each move, probably a bad idea - memcpy(¤t_position, &(dda->endpoint), sizeof(TARGET)); - #endif - } // turn off step outputs, hopefully they've been on long enough by now to register with the drivers // if not, too bad. or insert a (very!) small delay here, or fire up a spare timer or something diff --git a/mendel/gcode.c b/mendel/gcode.c index 8e26da9..ae33ec1 100644 --- a/mendel/gcode.c +++ b/mendel/gcode.c @@ -10,6 +10,7 @@ #include "dda_queue.h" #include "dda.h" #include "clock.h" +#include "watchdog.h" uint8_t option_bitfield; #define OPTION_COMMENT 128 @@ -267,7 +268,7 @@ void scan_char(uint8_t c) { // if (DEBUG) serial_writechar(c); // process -// if (next_target.seen_G || next_target.seen_M) { + if (next_target.seen_G || next_target.seen_M) { process_gcode_command(&next_target); // reset 'seen comment' @@ -281,7 +282,7 @@ void scan_char(uint8_t c) { read_digit.exponent = 0; serial_writestr_P(PSTR("OK\n")); -// } + } } } @@ -434,6 +435,9 @@ void process_gcode_command(GCODE_COMMAND *gcmd) { void clock_250ms(void); clock_250ms(); } + + // reset watchdog + wd_reset(); } SpecialMoveE(E_STARTSTOP_STEPS, FEEDRATE_FAST_E); break; diff --git a/mendel/mendel.c b/mendel/mendel.c index ebf383f..af17651 100644 --- a/mendel/mendel.c +++ b/mendel/mendel.c @@ -15,12 +15,18 @@ #include "clock.h" #include "temp.h" #include "sermsg.h" +#include "watchdog.h" #ifndef DEBUG #define DEBUG 0 #endif inline void io_init(void) { + // disable modules we don't use + PRR = MASK(PRTWI) | MASK(PRTIM2) | MASK(PRADC); + ACSR = MASK(ACD); + + // setup I/O pins WRITE(X_STEP_PIN, 0); SET_OUTPUT(X_STEP_PIN); WRITE(X_DIR_PIN, 0); SET_OUTPUT(X_DIR_PIN); WRITE(X_MIN_PIN, 1); SET_INPUT(X_MIN_PIN); @@ -62,8 +68,11 @@ inline void io_init(void) { WRITE(SS, 1); SET_OUTPUT(SS); } -inline void init(void); -inline void init() { +inline void init(void) { + + // set up watchdog + wd_init(); + // set up serial serial_init(); @@ -86,10 +95,12 @@ inline void init() { // say hi to host serial_writestr_P(PSTR("Start\n")); + + // reset watchdog + wd_reset(); } -void clock_250ms(void); -void clock_250ms() { +void clock_250ms(void) { temp_tick(); if (steptimeout > (30 * 4)) { @@ -159,5 +170,8 @@ int main (void) ifclock(CLOCK_FLAG_250MS) { clock_250ms(); } + + // reset watchdog + wd_reset(); } } diff --git a/mendel/serial.c b/mendel/serial.c index 0a0462c..ac1626b 100644 --- a/mendel/serial.c +++ b/mendel/serial.c @@ -93,9 +93,8 @@ ISR(USART_UDRE_vect) } else #endif - if (buf_canread(tx)) { + if (buf_canread(tx)) buf_pop(tx, UDR0); - } else UCSR0B &= ~MASK(UDRIE0); } @@ -112,6 +111,7 @@ uint8_t serial_rxchars() uint8_t serial_popchar() { uint8_t c = 0; + // it's imperative that we check, because if the buffer is empty and we pop, we'll go through the whole buffer again if (buf_canread(rx)) buf_pop(rx, c); return c; @@ -130,16 +130,15 @@ void serial_writechar(uint8_t data) { // check if interrupts are enabled if (SREG & MASK(SREG_I)) { - // if they are, we should be ok to block + // if they are, we should be ok to block since the tx buffer is emptied from an interrupt for (;buf_canwrite(tx) == 0;); buf_push(tx, data); } else { // interrupts are disabled- maybe we're in one? // anyway, instead of blocking, only write if we have room - if (buf_canwrite(tx)) { + if (buf_canwrite(tx)) buf_push(tx, data); - } } // enable TX interrupt so we can send this character UCSR0B |= MASK(UDRIE0); diff --git a/mendel/watchdog.c b/mendel/watchdog.c new file mode 100644 index 0000000..2a109a0 --- /dev/null +++ b/mendel/watchdog.c @@ -0,0 +1,27 @@ +#include "watchdog.h" + +#include +#include + +#include "arduino.h" + +volatile uint8_t wd_flag = 0; + +ISR(WDT_vect) { + // watchdog has tripped- no main loop activity for 0.25s, probably a bad thing + wd_flag |= 1; +} + +void wd_init() { + // 0.25s timeout, interrupt and system reset + wdt_enable(WDTO_250MS); + WDTCSR |= MASK(WDIE); +} + +void wd_reset() { + wdt_reset(); + if (wd_flag) { + WDTCSR |= MASK(WDIE); + wd_flag &= ~1; + } +} diff --git a/mendel/watchdog.h b/mendel/watchdog.h new file mode 100644 index 0000000..afd0d83 --- /dev/null +++ b/mendel/watchdog.h @@ -0,0 +1,12 @@ +#ifndef _WATCHDOG_H +#define _WATCHDOG_H + +// initialize +void wd_init(void); + +// reset timeout- must be called periodically or we reboot +void wd_reset(void); + +// notable lack of disable function + +#endif /* _WATCHDOG_H */