From db985065ff2eec2006e5023f8c2390266b21f6fe Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 12 Jan 2018 20:15:59 +0100 Subject: [PATCH 1/3] WRITE_NC macro for non-critical (non-synchronized) access to slow ports. The WRITE macro stores the CPU bits on the stack first, then locks the interupts, reads the port, sets a bit, writes the port and then finally reverts the CPU bits. The WRITE_NC does not lock the interrupts, therefore it may only be used where it cannot be interrupted. --- Firmware/fastio.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Firmware/fastio.h b/Firmware/fastio.h index c20a6b70..e4f25ed8 100644 --- a/Firmware/fastio.h +++ b/Firmware/fastio.h @@ -66,6 +66,11 @@ #define READ(IO) _READ(IO) /// Write to a pin wrapper #define WRITE(IO, v) _WRITE(IO, v) +/// Write to a pin wrapper, non critical. +/// This macro is cheaper than WRITE(IO,v) on ports H,I,J,K,L, as _WRITE_C disables / enables interrupts +/// and stores the old CPU flags on the stack. +/// This macro should only be called, where it cannot be interrupted. +#define WRITE_NC(IO, v) _WRITE_NC(IO, v) /// toggle a pin wrapper #define TOGGLE(IO) _TOGGLE(IO) From 26747d7236d16081ab25b52b69b8606f899b2524 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 12 Jan 2018 20:18:20 +0100 Subject: [PATCH 2/3] Definition of 8 pins on the Einsy 0.4 board connected to pin headers to be monitored by an 8 channel logic analyzer, for example the Saleae. --- Firmware/pins_Einy_0_4.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Firmware/pins_Einy_0_4.h b/Firmware/pins_Einy_0_4.h index b41ead82..1c408d45 100644 --- a/Firmware/pins_Einy_0_4.h +++ b/Firmware/pins_Einy_0_4.h @@ -126,3 +126,27 @@ #endif //NEWPANEL #endif //ULTRA_LCD + +// Support for an 8 bit logic analyzer, for example the Saleae. +// Channels 0-2 are fast, they could generate 2.667Mhz waveform with a software loop. +#define LOGIC_ANALYZER_CH0 X_MIN_PIN // PB6 +#define LOGIC_ANALYZER_CH1 Y_MIN_PIN // PB5 +#define LOGIC_ANALYZER_CH2 53 // PB0 (PROC_nCS) +// Channels 3-7 are slow, they could generate +// 0.889Mhz waveform with a software loop and interrupt locking, +// 1.333MHz waveform without interrupt locking. +#define LOGIC_ANALYZER_CH3 73 // PJ3 +// PK0 has no Arduino digital pin assigned, so we set it directly. +#define WRITE_LOGIC_ANALYZER_CH4(value) if (value) PORTK |= (1 << 0); else PORTK &= ~(1 << 0) // PK0 +#define LOGIC_ANALYZER_CH5 16 // PH0 (RXD2) +#define LOGIC_ANALYZER_CH6 17 // PH1 (TXD2) +#define LOGIC_ANALYZER_CH7 76 // PJ5 + +#define LOGIC_ANALYZER_CH0_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH0) +#define LOGIC_ANALYZER_CH1_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH1) +#define LOGIC_ANALYZER_CH2_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH2) +#define LOGIC_ANALYZER_CH3_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH3) +#define LOGIC_ANALYZER_CH4_ENABLE do { DDRK |= 1 << 0; } while (0) +#define LOGIC_ANALYZER_CH5_ENABLE do { cbi(UCSR2B, TXEN2); cbi(UCSR2B, RXEN2); cbi(UCSR2B, RXCIE2); SET_OUTPUT(LOGIC_ANALYZER_CH5); } while (0) +#define LOGIC_ANALYZER_CH6_ENABLE do { cbi(UCSR2B, TXEN2); cbi(UCSR2B, RXEN2); cbi(UCSR2B, RXCIE2); SET_OUTPUT(LOGIC_ANALYZER_CH6); } while (0) +#define LOGIC_ANALYZER_CH7_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH7) From 3e6d853364981c82c3e79b9fabc38f354985869c Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 12 Jan 2018 20:51:14 +0100 Subject: [PATCH 3/3] Debugging of the stepper timer routine. When enabled through DEBUG_STEPPER_TIMER_MISSED, the printer is halted on stepper timer overflow and an error message is displayed. --- Firmware/Configuration_prusa.h | 1 + Firmware/language_all.cpp | 5 +++++ Firmware/language_all.h | 2 ++ Firmware/language_en.h | 1 + Firmware/stepper.cpp | 14 ++++++++++++++ Firmware/ultralcd.cpp | 16 ++++++++++++++++ 6 files changed, 39 insertions(+) diff --git a/Firmware/Configuration_prusa.h b/Firmware/Configuration_prusa.h index 488ce8c9..4d7faaa7 100644 --- a/Firmware/Configuration_prusa.h +++ b/Firmware/Configuration_prusa.h @@ -127,6 +127,7 @@ const bool Z_MIN_ENDSTOP_INVERTING = false; // set to true to invert the logic o //#define DEBUG_DISABLE_FANCHECK //disable fan check (no ISR INT7, check disabled) //#define DEBUG_DISABLE_FSENSORCHECK //disable fsensor check (no ISR INT7, check disabled) #define DEBUG_DUMP_TO_2ND_SERIAL //dump received characters to 2nd serial line +//#define DEBUG_STEPPER_TIMER_MISSED // Stop on stepper timer overflow, beep and display a message. #endif diff --git a/Firmware/language_all.cpp b/Firmware/language_all.cpp index f6241bea..59d69d88 100644 --- a/Firmware/language_all.cpp +++ b/Firmware/language_all.cpp @@ -2039,6 +2039,11 @@ const char * const MSG_STEEL_SHEET_CHECK_LANG_TABLE[LANG_NUM] PROGMEM = { MSG_STEEL_SHEET_CHECK_CZ }; +const char MSG_STEPPER_TIMER_OVERFLOW_ERROR_EN[] PROGMEM = "Error - stepper timer overflow"; +const char * const MSG_STEPPER_TIMER_OVERFLOW_ERROR_LANG_TABLE[1] PROGMEM = { + MSG_STEPPER_TIMER_OVERFLOW_ERROR_EN +}; + const char MSG_STEPPER_TOO_HIGH_EN[] PROGMEM = "Steprate too high: "; const char * const MSG_STEPPER_TOO_HIGH_LANG_TABLE[1] PROGMEM = { MSG_STEPPER_TOO_HIGH_EN diff --git a/Firmware/language_all.h b/Firmware/language_all.h index e4d23036..0d40242e 100644 --- a/Firmware/language_all.h +++ b/Firmware/language_all.h @@ -672,6 +672,8 @@ extern const char* const MSG_STATS_TOTALPRINTTIME_LANG_TABLE[LANG_NUM]; #define MSG_STATS_TOTALPRINTTIME LANG_TABLE_SELECT(MSG_STATS_TOTALPRINTTIME_LANG_TABLE) extern const char* const MSG_STEEL_SHEET_CHECK_LANG_TABLE[LANG_NUM]; #define MSG_STEEL_SHEET_CHECK LANG_TABLE_SELECT(MSG_STEEL_SHEET_CHECK_LANG_TABLE) +extern const char* const MSG_STEPPER_TIMER_OVERFLOW_ERROR_LANG_TABLE[1]; +#define MSG_STEPPER_TIMER_OVERFLOW_ERROR LANG_TABLE_SELECT_EXPLICIT(MSG_STEPPER_TIMER_OVERFLOW_ERROR_LANG_TABLE, 0) extern const char* const MSG_STEPPER_TOO_HIGH_LANG_TABLE[1]; #define MSG_STEPPER_TOO_HIGH LANG_TABLE_SELECT_EXPLICIT(MSG_STEPPER_TOO_HIGH_LANG_TABLE, 0) extern const char* const MSG_STOPPED_LANG_TABLE[1]; diff --git a/Firmware/language_en.h b/Firmware/language_en.h index 9cc91a00..22225d29 100644 --- a/Firmware/language_en.h +++ b/Firmware/language_en.h @@ -261,6 +261,7 @@ #define(length=20, lines=4) MSG_FIL_ADJUSTING "Adjusting filaments. Please wait." #define(length=20,lines=8) MSG_CONFIRM_NOZZLE_CLEAN_FIL_ADJ "Filaments are now adjusted. Please clean the nozzle for calibration. Click when done." #define(length=20, lines=4) MSG_STACK_ERROR "Error - static memory has been overwritten" +#define(length=20, lines=4) MSG_STEPPER_TIMER_OVERFLOW_ERROR "Error - stepper timer overflow" #define(length=20, lines=1) MSG_CALIBRATE_E "Calibrate E" //#define(length=20, lines=1) MSG_RESET_CALIBRATE_E "Reset E Cal." #define(length=20, lines=8) MSG_E_CAL_KNOB "Rotate knob until mark reaches extruder body. Click when done." diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index ae8081bd..352f243c 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -126,6 +126,10 @@ uint8_t LastStepMask = 0; #define _NEXT_ISR(T) OCR1A = T #endif +#ifdef DEBUG_STEPPER_TIMER_MISSED +extern bool stepper_timer_overflow_state; +#endif /* DEBUG_STEPPER_TIMER_MISSED */ + //=========================================================================== //=============================functions ============================ //=========================================================================== @@ -842,6 +846,16 @@ void isr() { #ifdef TMC2130 tmc2130_st_isr(LastStepMask); #endif //TMC2130 +#ifdef DEBUG_STEPPER_TIMER_MISSED + // Verify whether the next planned timer interrupt has not been missed already. + // This debugging test takes < 1.125us + // This skews the profiling slightly as the fastest stepper timer + // interrupt repeats at a 100us rate (10kHz). + if (OCR1A < TCNT1) { + stepper_timer_overflow_state = true; + WRITE(BEEPER, HIGH); + } +#endif } #ifdef LIN_ADVANCE diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 6e984bfd..00ad001b 100644 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -5109,6 +5109,19 @@ void stack_error() { while (1) delay_keep_alive(1000); } +#ifdef DEBUG_STEPPER_TIMER_MISSED +bool stepper_timer_overflow_state = false; +void stepper_timer_overflow() { + SET_OUTPUT(BEEPER); + WRITE(BEEPER, HIGH); + delay(1000); + WRITE(BEEPER, LOW); + lcd_display_message_fullscreen_P(MSG_STEPPER_TIMER_OVERFLOW_ERROR); + //err_triggered = 1; + while (1) delay_keep_alive(1000); +} +#endif /* DEBUG_STEPPER_TIMER_MISSED */ + #ifdef SDSUPPORT static void lcd_autostart_sd() { @@ -6779,6 +6792,9 @@ void lcd_update(uint8_t lcdDrawUpdateOverride) lcd_next_update_millis = millis() + LCD_UPDATE_INTERVAL; } if (!SdFatUtil::test_stack_integrity()) stack_error(); +#ifdef DEBUG_STEPPER_TIMER_MISSED + if (stepper_timer_overflow_state) stepper_timer_overflow(); +#endif /* DEBUG_STEPPER_TIMER_MISSED */ lcd_ping(); //check that we have received ping command if we are in farm mode if (lcd_commands_type == LCD_COMMAND_V2_CAL) lcd_commands(); }