misc tidying, added watchdog stuff, moved things around a bit
This commit is contained in:
parent
65c237cff6
commit
7326e17560
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
PROGRAM = mendel
|
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
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# #
|
# #
|
||||||
|
|
|
||||||
40
mendel/dda.c
40
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) {
|
void dda_step(DDA *dda) {
|
||||||
|
// called from interrupt context! keep it as simple as possible
|
||||||
uint8_t step_option = 0;
|
uint8_t step_option = 0;
|
||||||
#define X_CAN_STEP 1
|
#define X_CAN_STEP 1
|
||||||
#define Y_CAN_STEP 2
|
#define Y_CAN_STEP 2
|
||||||
|
|
@ -284,12 +285,11 @@ void dda_step(DDA *dda) {
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
serial_writechar('!');
|
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(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(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(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.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.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;
|
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) {
|
if (step_option & F_CAN_STEP) {
|
||||||
dda->f_counter -= dda->f_delta;
|
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
|
// 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) {
|
while (dda->f_counter < 0) {
|
||||||
|
|
||||||
dda->f_counter += dda->total_steps;
|
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)
|
if (step_option & REAL_MOVE)
|
||||||
// we stepped, reset timeout
|
// we stepped, reset timeout
|
||||||
steptimeout = 0;
|
steptimeout = 0;
|
||||||
|
|
@ -409,13 +398,8 @@ void dda_step(DDA *dda) {
|
||||||
|
|
||||||
// if we could do anything at all, we're still running
|
// if we could do anything at all, we're still running
|
||||||
// otherwise, must have finished
|
// otherwise, must have finished
|
||||||
else if (step_option == 0) {
|
else if (step_option == 0)
|
||||||
dda->live = 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
|
// 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
|
// if not, too bad. or insert a (very!) small delay here, or fire up a spare timer or something
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "dda_queue.h"
|
#include "dda_queue.h"
|
||||||
#include "dda.h"
|
#include "dda.h"
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
|
#include "watchdog.h"
|
||||||
|
|
||||||
uint8_t option_bitfield;
|
uint8_t option_bitfield;
|
||||||
#define OPTION_COMMENT 128
|
#define OPTION_COMMENT 128
|
||||||
|
|
@ -267,7 +268,7 @@ void scan_char(uint8_t c) {
|
||||||
// if (DEBUG)
|
// if (DEBUG)
|
||||||
serial_writechar(c);
|
serial_writechar(c);
|
||||||
// process
|
// process
|
||||||
// if (next_target.seen_G || next_target.seen_M) {
|
if (next_target.seen_G || next_target.seen_M) {
|
||||||
process_gcode_command(&next_target);
|
process_gcode_command(&next_target);
|
||||||
|
|
||||||
// reset 'seen comment'
|
// reset 'seen comment'
|
||||||
|
|
@ -281,7 +282,7 @@ void scan_char(uint8_t c) {
|
||||||
read_digit.exponent = 0;
|
read_digit.exponent = 0;
|
||||||
|
|
||||||
serial_writestr_P(PSTR("OK\n"));
|
serial_writestr_P(PSTR("OK\n"));
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -434,6 +435,9 @@ void process_gcode_command(GCODE_COMMAND *gcmd) {
|
||||||
void clock_250ms(void);
|
void clock_250ms(void);
|
||||||
clock_250ms();
|
clock_250ms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset watchdog
|
||||||
|
wd_reset();
|
||||||
}
|
}
|
||||||
SpecialMoveE(E_STARTSTOP_STEPS, FEEDRATE_FAST_E);
|
SpecialMoveE(E_STARTSTOP_STEPS, FEEDRATE_FAST_E);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,18 @@
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "temp.h"
|
#include "temp.h"
|
||||||
#include "sermsg.h"
|
#include "sermsg.h"
|
||||||
|
#include "watchdog.h"
|
||||||
|
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline void io_init(void) {
|
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_STEP_PIN, 0); SET_OUTPUT(X_STEP_PIN);
|
||||||
WRITE(X_DIR_PIN, 0); SET_OUTPUT(X_DIR_PIN);
|
WRITE(X_DIR_PIN, 0); SET_OUTPUT(X_DIR_PIN);
|
||||||
WRITE(X_MIN_PIN, 1); SET_INPUT(X_MIN_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);
|
WRITE(SS, 1); SET_OUTPUT(SS);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void init(void);
|
inline void init(void) {
|
||||||
inline void init() {
|
|
||||||
|
// set up watchdog
|
||||||
|
wd_init();
|
||||||
|
|
||||||
// set up serial
|
// set up serial
|
||||||
serial_init();
|
serial_init();
|
||||||
|
|
||||||
|
|
@ -86,10 +95,12 @@ inline void init() {
|
||||||
|
|
||||||
// say hi to host
|
// say hi to host
|
||||||
serial_writestr_P(PSTR("Start\n"));
|
serial_writestr_P(PSTR("Start\n"));
|
||||||
|
|
||||||
|
// reset watchdog
|
||||||
|
wd_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clock_250ms(void);
|
void clock_250ms(void) {
|
||||||
void clock_250ms() {
|
|
||||||
temp_tick();
|
temp_tick();
|
||||||
|
|
||||||
if (steptimeout > (30 * 4)) {
|
if (steptimeout > (30 * 4)) {
|
||||||
|
|
@ -159,5 +170,8 @@ int main (void)
|
||||||
ifclock(CLOCK_FLAG_250MS) {
|
ifclock(CLOCK_FLAG_250MS) {
|
||||||
clock_250ms();
|
clock_250ms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset watchdog
|
||||||
|
wd_reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,9 +93,8 @@ ISR(USART_UDRE_vect)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (buf_canread(tx)) {
|
if (buf_canread(tx))
|
||||||
buf_pop(tx, UDR0);
|
buf_pop(tx, UDR0);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
UCSR0B &= ~MASK(UDRIE0);
|
UCSR0B &= ~MASK(UDRIE0);
|
||||||
}
|
}
|
||||||
|
|
@ -112,6 +111,7 @@ uint8_t serial_rxchars()
|
||||||
uint8_t serial_popchar()
|
uint8_t serial_popchar()
|
||||||
{
|
{
|
||||||
uint8_t c = 0;
|
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))
|
if (buf_canread(rx))
|
||||||
buf_pop(rx, c);
|
buf_pop(rx, c);
|
||||||
return c;
|
return c;
|
||||||
|
|
@ -130,16 +130,15 @@ void serial_writechar(uint8_t data)
|
||||||
{
|
{
|
||||||
// check if interrupts are enabled
|
// check if interrupts are enabled
|
||||||
if (SREG & MASK(SREG_I)) {
|
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;);
|
for (;buf_canwrite(tx) == 0;);
|
||||||
buf_push(tx, data);
|
buf_push(tx, data);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// interrupts are disabled- maybe we're in one?
|
// interrupts are disabled- maybe we're in one?
|
||||||
// anyway, instead of blocking, only write if we have room
|
// anyway, instead of blocking, only write if we have room
|
||||||
if (buf_canwrite(tx)) {
|
if (buf_canwrite(tx))
|
||||||
buf_push(tx, data);
|
buf_push(tx, data);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// enable TX interrupt so we can send this character
|
// enable TX interrupt so we can send this character
|
||||||
UCSR0B |= MASK(UDRIE0);
|
UCSR0B |= MASK(UDRIE0);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "watchdog.h"
|
||||||
|
|
||||||
|
#include <avr/wdt.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 */
|
||||||
Loading…
Reference in New Issue