Support for Debug Codes - Dnnn (#19225)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
This commit is contained in:
Victor Oliveira 2020-10-09 08:25:23 -03:00 committed by Scott Lahteine
parent 0b13608bad
commit 2553a18f40
20 changed files with 269 additions and 38 deletions

View file

@ -120,6 +120,8 @@ void HAL_init();
inline void HAL_clear_reset_source() { MCUSR = 0; } inline void HAL_clear_reset_source() { MCUSR = 0; }
inline uint8_t HAL_get_reset_source() { return MCUSR; } inline uint8_t HAL_get_reset_source() { return MCUSR; }
inline void HAL_reboot() {} // reboot the board or restart the bootloader
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-function"
extern "C" { extern "C" {

View file

@ -105,6 +105,8 @@ void sei(); // Enable interrupts
void HAL_clear_reset_source(); // clear reset reason void HAL_clear_reset_source(); // clear reset reason
uint8_t HAL_get_reset_source(); // get reset reason uint8_t HAL_get_reset_source(); // get reset reason
inline void HAL_reboot() {} // reboot the board or restart the bootloader
// //
// ADC // ADC
// //

View file

@ -96,6 +96,8 @@ void HAL_clear_reset_source();
// reset reason // reset reason
uint8_t HAL_get_reset_source(); uint8_t HAL_get_reset_source();
inline void HAL_reboot() {} // reboot the board or restart the bootloader
void _delay_ms(int delay); void _delay_ms(int delay);
#pragma GCC diagnostic push #pragma GCC diagnostic push

View file

@ -101,6 +101,8 @@ uint16_t HAL_adc_get_result();
inline void HAL_clear_reset_source(void) {} inline void HAL_clear_reset_source(void) {}
inline uint8_t HAL_get_reset_source(void) { return RST_POWER_ON; } inline uint8_t HAL_get_reset_source(void) { return RST_POWER_ON; }
inline void HAL_reboot() {} // reboot the board or restart the bootloader
/* ---------------- Delay in cycles */ /* ---------------- Delay in cycles */
FORCE_INLINE static void DELAY_CYCLES(uint64_t x) { FORCE_INLINE static void DELAY_CYCLES(uint64_t x) {
Clock::delayCycles(x); Clock::delayCycles(x);

View file

@ -200,6 +200,8 @@ void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255,
void HAL_clear_reset_source(void); void HAL_clear_reset_source(void);
uint8_t HAL_get_reset_source(void); uint8_t HAL_get_reset_source(void);
inline void HAL_reboot() {} // reboot the board or restart the bootloader
// Add strcmp_P if missing // Add strcmp_P if missing
#ifndef strcmp_P #ifndef strcmp_P
#define strcmp_P(a, b) strcmp((a), (b)) #define strcmp_P(a, b) strcmp((a), (b))

View file

@ -88,6 +88,8 @@ typedef int8_t pin_t;
void HAL_clear_reset_source(); // clear reset reason void HAL_clear_reset_source(); // clear reset reason
uint8_t HAL_get_reset_source(); // get reset reason uint8_t HAL_get_reset_source(); // get reset reason
inline void HAL_reboot() {} // reboot the board or restart the bootloader
// //
// ADC // ADC
// //

View file

@ -134,6 +134,8 @@ void HAL_clear_reset_source();
// Reset reason // Reset reason
uint8_t HAL_get_reset_source(); uint8_t HAL_get_reset_source();
inline void HAL_reboot() {} // reboot the board or restart the bootloader
void _delay_ms(const int delay); void _delay_ms(const int delay);
extern "C" char* _sbrk(int incr); extern "C" char* _sbrk(int incr);

View file

@ -185,6 +185,8 @@ void HAL_clear_reset_source();
// Reset reason // Reset reason
uint8_t HAL_get_reset_source(); uint8_t HAL_get_reset_source();
inline void HAL_reboot() {} // reboot the board or restart the bootloader
void _delay_ms(const int delay); void _delay_ms(const int delay);
#pragma GCC diagnostic push #pragma GCC diagnostic push

View file

@ -142,6 +142,8 @@ void HAL_clear_reset_source();
// Reset reason // Reset reason
uint8_t HAL_get_reset_source(); uint8_t HAL_get_reset_source();
inline void HAL_reboot() {} // reboot the board or restart the bootloader
void _delay_ms(const int delay); void _delay_ms(const int delay);
/* /*

View file

@ -93,6 +93,8 @@ void HAL_clear_reset_source();
// Get the reason for the reset // Get the reason for the reset
uint8_t HAL_get_reset_source(); uint8_t HAL_get_reset_source();
inline void HAL_reboot() {} // reboot the board or restart the bootloader
FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); } FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); }
#pragma GCC diagnostic push #pragma GCC diagnostic push

View file

@ -99,6 +99,8 @@ void HAL_clear_reset_source();
// Reset reason // Reset reason
uint8_t HAL_get_reset_source(); uint8_t HAL_get_reset_source();
inline void HAL_reboot() {} // reboot the board or restart the bootloader
FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); } FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); }
#pragma GCC diagnostic push #pragma GCC diagnostic push

View file

@ -215,6 +215,7 @@
#define WITHIN(N,L,H) ((N) >= (L) && (N) <= (H)) #define WITHIN(N,L,H) ((N) >= (L) && (N) <= (H))
#define NUMERIC(a) WITHIN(a, '0', '9') #define NUMERIC(a) WITHIN(a, '0', '9')
#define DECIMAL(a) (NUMERIC(a) || a == '.') #define DECIMAL(a) (NUMERIC(a) || a == '.')
#define HEXCHR(a) (NUMERIC(a) ? (a) - '0' : WITHIN(a, 'a', 'f') ? ((a) - 'a' + 10) : WITHIN(a, 'A', 'F') ? ((a) - 'A' + 10) : -1)
#define NUMERIC_SIGNED(a) (NUMERIC(a) || (a) == '-' || (a) == '+') #define NUMERIC_SIGNED(a) (NUMERIC(a) || (a) == '-' || (a) == '+')
#define DECIMAL_SIGNED(a) (DECIMAL(a) || (a) == '-' || (a) == '+') #define DECIMAL_SIGNED(a) (DECIMAL(a) || (a) == '-' || (a) == '+')
#define COUNT(a) (sizeof(a)/sizeof(*a)) #define COUNT(a) (sizeof(a)/sizeof(*a))

View file

@ -88,10 +88,8 @@ public:
case EP_N: case EP_N:
switch (c) { switch (c) {
case '0': case '1': case '2': case '0' ... '9':
case '3': case '4': case '5': case '-': case ' ': break;
case '6': case '7': case '8':
case '9': case '-': case ' ': break;
case 'M': state = EP_M; break; case 'M': state = EP_M; break;
default: state = EP_IGNORE; default: state = EP_IGNORE;
} }
@ -153,10 +151,7 @@ public:
case EP_M876S: case EP_M876S:
switch (c) { switch (c) {
case ' ': break; case ' ': break;
case '0': case '1': case '2': case '0' ... '9':
case '3': case '4': case '5':
case '6': case '7': case '8':
case '9':
state = EP_M876SN; state = EP_M876SN;
M876_reason = (uint8_t)(c - '0'); M876_reason = (uint8_t)(c - '0');
break; break;

View file

@ -46,7 +46,7 @@
* Tx Same as T?, but nozzle doesn't have to be preheated. Tc requires a preheated nozzle to finish filament load. * Tx Same as T?, but nozzle doesn't have to be preheated. Tc requires a preheated nozzle to finish filament load.
* Tc Load to nozzle after filament was prepared by Tc and nozzle is already heated. * Tc Load to nozzle after filament was prepared by Tc and nozzle is already heated.
*/ */
void GcodeSuite::T(const uint8_t tool_index) { void GcodeSuite::T(const int8_t tool_index) {
DEBUG_SECTION(log_T, "T", DEBUGGING(LEVELING)); DEBUG_SECTION(log_T, "T", DEBUGGING(LEVELING));
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("...(", tool_index, ")"); if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("...(", tool_index, ")");

View file

@ -923,6 +923,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 'T': T(parser.codenum); break; // Tn: Tool Change case 'T': T(parser.codenum); break; // Tn: Tool Change
#if ENABLED(MARLIN_DEV_MODE)
case 'D': D(parser.codenum); break; // Dn: Debug codes
#endif
default: default:
#if ENABLED(WIFI_CUSTOM_COMMAND) #if ENABLED(WIFI_CUSTOM_COMMAND)
if (wifi_custom_command(parser.command_ptr)) break; if (wifi_custom_command(parser.command_ptr)) break;

View file

@ -285,6 +285,7 @@
* M995 - Touch screen calibration for TFT display * M995 - Touch screen calibration for TFT display
* M997 - Perform in-application firmware update * M997 - Perform in-application firmware update
* M999 - Restart after being stopped by error * M999 - Restart after being stopped by error
* D... - Custom Development G-code. Add hooks to 'gcode_D.cpp' for developers to test features. (Requires MARLIN_DEV_MODE)
* *
* "T" Codes * "T" Codes
* *
@ -408,6 +409,8 @@ public:
private: private:
TERN_(MARLIN_DEV_MODE, static void D(const int16_t dcode));
static void G0_G1(TERN_(HAS_FAST_MOVES, const bool fast_move=false)); static void G0_G1(TERN_(HAS_FAST_MOVES, const bool fast_move=false));
TERN_(ARC_SUPPORT, static void G2_G3(const bool clockwise)); TERN_(ARC_SUPPORT, static void G2_G3(const bool clockwise));
@ -882,7 +885,7 @@ private:
TERN_(CONTROLLER_FAN_EDITABLE, static void M710()); TERN_(CONTROLLER_FAN_EDITABLE, static void M710());
static void T(const uint8_t tool_index); static void T(const int8_t tool_index);
}; };

View file

@ -0,0 +1,173 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../inc/MarlinConfigPre.h"
#if ENABLED(MARLIN_DEV_MODE)
#include "gcode.h"
#include "../module/settings.h"
#include "../libs/hex_print.h"
#include "../HAL/shared/eeprom_if.h"
/**
* Dn: G-code for development and testing
*
* See https://reprap.org/wiki/G-code#D:_Debug_codes
*
* Put whatever else you need here to test ongoing development.
*/
void GcodeSuite::D(const int16_t dcode) {
switch (dcode) {
case -1:
for (;;); // forever
case 0:
HAL_reboot();
break;
case 1: {
// Zero or pattern-fill the EEPROM data
#if ENABLED(EEPROM_SETTINGS)
persistentStore.access_start();
size_t total = persistentStore.capacity();
int pos = 0;
const uint8_t value = 0x0;
while(total--) {
persistentStore.write_data(pos, &value, 1);
}
persistentStore.access_finish();
#else
settings.reset();
settings.save();
#endif
HAL_reboot();
} break;
case 2: { // D2 Read / Write SRAM
#define SRAM_SIZE 8192
uint8_t *pointer = parser.hex_adr_val('A');
uint16_t len = parser.ushortval('C', 1);
uintptr_t addr = (uintptr_t)pointer;
NOMORE(addr, (size_t)(SRAM_SIZE - 1));
NOMORE(len, SRAM_SIZE - addr);
if (parser.seenval('X')) {
// Write the hex bytes after the X
uint16_t val = parser.hex_val('X');
while (len--) {
*pointer = val;
pointer++;
}
}
else {
while (len--) print_hex_byte(*(pointer++));
SERIAL_EOL();
}
} break;
case 3: { // D3 Read / Write EEPROM
uint8_t *pointer = parser.hex_adr_val('A');
uint16_t len = parser.ushortval('C', 1);
uintptr_t addr = (uintptr_t)pointer;
#ifndef MARLIN_EEPROM_SIZE
#define MARLIN_EEPROM_SIZE size_t(E2END + 1)
#endif
NOMORE(addr, (size_t)(MARLIN_EEPROM_SIZE - 1));
NOMORE(len, MARLIN_EEPROM_SIZE - addr);
if (parser.seenval('X')) {
uint16_t val = parser.hex_val('X');
#if ENABLED(EEPROM_SETTINGS)
persistentStore.access_start();
while(len--) {
int pos = 0;
persistentStore.write_data(pos, (uint8_t *)&val, sizeof(val));
}
SERIAL_EOL();
persistentStore.access_finish();
#else
SERIAL_ECHOLN("NO EEPROM");
#endif
}
else {
while (len--) {
// Read bytes from EEPROM
#if ENABLED(EEPROM_SETTINGS)
persistentStore.access_start();
uint8_t val;
while(len--) {
int pos = 0;
if (!persistentStore.read_data(pos, (uint8_t *)&val, sizeof(val))) {
print_hex_byte(val);
}
}
SERIAL_EOL();
persistentStore.access_finish();
#else
SERIAL_ECHOLN("NO EEPROM");
#endif
}
SERIAL_EOL();
}
} break;
case 4: { // D4 Read / Write PIN
// const uint8_t pin = parser.byteval('P');
// const bool is_out = parser.boolval('F'),
// val = parser.byteval('V', LOW);
if (parser.seenval('X')) {
// TODO: Write the hex bytes after the X
//while (len--) {
//}
}
else {
// while (len--) {
// TODO: Read bytes from EEPROM
// print_hex_byte(eeprom_read_byte(*(adr++));
// }
SERIAL_EOL();
}
} break;
case 5: { // D4 Read / Write onboard Flash
#define FLASH_SIZE 1024
uint8_t *pointer = parser.hex_adr_val('A');
uint16_t len = parser.ushortval('C', 1);
uintptr_t addr = (uintptr_t)pointer;
NOMORE(addr, (size_t)(FLASH_SIZE - 1));
NOMORE(len, FLASH_SIZE - addr);
if (parser.seenval('X')) {
// TODO: Write the hex bytes after the X
//while (len--) {
//}
}
else {
// while (len--) {
// TODO: Read bytes from EEPROM
// print_hex_byte(eeprom_read_byte(adr++));
// }
SERIAL_EOL();
}
} break;
}
}
#endif

View file

@ -147,22 +147,15 @@ void GCodeParser::parse(char *p) {
starpos[1] = '\0'; starpos[1] = '\0';
} }
#if ENABLED(GCODE_MOTION_MODES) #if ANY(MARLIN_DEV_MODE, SWITCHING_TOOLHEAD, MAGNETIC_SWITCHING_TOOLHEAD, ELECTROMAGNETIC_SWITCHING_TOOLHEAD)
#if ENABLED(ARC_SUPPORT) #define SIGNED_CODENUM 1
#define GTOP 3
#else
#define GTOP 1
#endif
#endif #endif
// Bail if the letter is not G, M, or T // Bail if the letter is not G, M, or T
// (or a valid parameter for the current motion mode) // (or a valid parameter for the current motion mode)
switch (letter) { switch (letter) {
case 'G': case 'M': case 'T': case 'G': case 'M': case 'T': TERN_(MARLIN_DEV_MODE, case 'D':)
#if ENABLED(CANCEL_OBJECTS)
case 'O':
#endif
// Skip spaces to get the numeric part // Skip spaces to get the numeric part
while (*p == ' ') p++; while (*p == ' ') p++;
@ -178,22 +171,33 @@ void GCodeParser::parse(char *p) {
#endif #endif
// Bail if there's no command code number // Bail if there's no command code number
if (!NUMERIC(*p)) return; if (!TERN(SIGNED_CODENUM, NUMERIC_SIGNED(*p), NUMERIC(*p))) return;
// Save the command letter at this point // Save the command letter at this point
// A '?' signifies an unknown command // A '?' signifies an unknown command
command_letter = letter; command_letter = letter;
{
#if ENABLED(SIGNED_CODENUM)
int sign = 1; // Allow for a negative code like D-1 or T-1
if (*p == '-') { sign = -1; ++p; }
#endif
// Get the code number - integer digits only // Get the code number - integer digits only
codenum = 0; codenum = 0;
do { codenum *= 10, codenum += *p++ - '0'; } while (NUMERIC(*p));
do { codenum = codenum * 10 + *p++ - '0'; } while (NUMERIC(*p));
// Apply the sign, if any
TERN_(SIGNED_CODENUM, codenum *= sign);
}
// Allow for decimal point in command // Allow for decimal point in command
#if ENABLED(USE_GCODE_SUBCODES) #if ENABLED(USE_GCODE_SUBCODES)
if (*p == '.') { if (*p == '.') {
p++; p++;
while (NUMERIC(*p)) while (NUMERIC(*p))
subcode *= 10, subcode += *p++ - '0'; subcode = subcode * 10 + *p++ - '0';
} }
#endif #endif
@ -201,11 +205,8 @@ void GCodeParser::parse(char *p) {
while (*p == ' ') p++; while (*p == ' ') p++;
#if ENABLED(GCODE_MOTION_MODES) #if ENABLED(GCODE_MOTION_MODES)
if (letter == 'G' && (codenum <= GTOP || codenum == 5 if (letter == 'G'
#if ENABLED(G38_PROBE_TARGET) && (codenum <= TERN(ARC_SUPPORT, 3, 1) || codenum == 5 || TERN0(G38_PROBE_TARGET, codenum == 38))
|| codenum == 38
#endif
)
) { ) {
motion_mode_codenum = codenum; motion_mode_codenum = codenum;
TERN_(USE_GCODE_SUBCODES, motion_mode_subcode = subcode); TERN_(USE_GCODE_SUBCODES, motion_mode_subcode = subcode);
@ -216,12 +217,12 @@ void GCodeParser::parse(char *p) {
#if ENABLED(GCODE_MOTION_MODES) #if ENABLED(GCODE_MOTION_MODES)
#if ENABLED(ARC_SUPPORT) #if ENABLED(ARC_SUPPORT)
case 'I': case 'J': case 'R': case 'I' ... 'J': case 'R':
if (motion_mode_codenum != 2 && motion_mode_codenum != 3) return; if (motion_mode_codenum != 2 && motion_mode_codenum != 3) return;
#endif #endif
case 'P': case 'Q': case 'P' ... 'Q':
if (motion_mode_codenum != 5) return; if (motion_mode_codenum != 5) return;
case 'X': case 'Y': case 'Z': case 'E': case 'F': case 'X' ... 'Z': case 'E' ... 'F':
if (motion_mode_codenum < 0) return; if (motion_mode_codenum < 0) return;
command_letter = 'G'; command_letter = 'G';
codenum = motion_mode_codenum; codenum = motion_mode_codenum;
@ -247,7 +248,7 @@ void GCodeParser::parse(char *p) {
#if ENABLED(EXPECTED_PRINTER_CHECK) #if ENABLED(EXPECTED_PRINTER_CHECK)
case 16: case 16:
#endif #endif
case 23: case 28: case 30: case 33: case 117: case 118: case 928: case 23: case 28: case 30: case 117 ... 118: case 928:
string_arg = unescape_string(p); string_arg = unescape_string(p);
return; return;
default: break; default: break;

View file

@ -114,6 +114,11 @@ public:
return valid_signless(p) || ((p[0] == '-' || p[0] == '+') && valid_signless(&p[1])); // [-+]?.?[0-9] return valid_signless(p) || ((p[0] == '-' || p[0] == '+') && valid_signless(&p[1])); // [-+]?.?[0-9]
} }
FORCE_INLINE static bool valid_number(const char * const p) {
// TODO: With MARLIN_DEV_MODE allow HEX values starting with "x"
return valid_float(p);
}
#if ENABLED(FASTER_GCODE_PARSER) #if ENABLED(FASTER_GCODE_PARSER)
FORCE_INLINE static bool valid_int(const char * const p) { FORCE_INLINE static bool valid_int(const char * const p) {
@ -142,8 +147,12 @@ public:
if (ind >= COUNT(param)) return false; // Only A-Z if (ind >= COUNT(param)) return false; // Only A-Z
const bool b = TEST32(codebits, ind); const bool b = TEST32(codebits, ind);
if (b) { if (b) {
if (param[ind]) {
char * const ptr = command_ptr + param[ind]; char * const ptr = command_ptr + param[ind];
value_ptr = param[ind] && valid_float(ptr) ? ptr : nullptr; value_ptr = valid_number(ptr) ? ptr : nullptr;
}
else
value_ptr = nullptr;
} }
return b; return b;
} }
@ -198,7 +207,7 @@ public:
static inline bool seen(const char c) { static inline bool seen(const char c) {
char *p = strgchr(command_args, c); char *p = strgchr(command_args, c);
const bool b = !!p; const bool b = !!p;
if (b) value_ptr = valid_float(&p[1]) ? &p[1] : nullptr; if (b) value_ptr = valid_number(&p[1]) ? &p[1] : nullptr;
return b; return b;
} }
@ -401,6 +410,25 @@ public:
static inline float linearval(const char c, const float dval=0) { return seenval(c) ? value_linear_units() : dval; } static inline float linearval(const char c, const float dval=0) { return seenval(c) ? value_linear_units() : dval; }
static inline float celsiusval(const char c, const float dval=0) { return seenval(c) ? value_celsius() : dval; } static inline float celsiusval(const char c, const float dval=0) { return seenval(c) ? value_celsius() : dval; }
#if ENABLED(MARLIN_DEV_MODE)
static inline uint8_t* hex_adr_val(const char c, uint8_t * const dval=nullptr) {
if (!seen(c) || *value_ptr != 'x') return dval;
uint8_t *out = nullptr;
for (char *vp = value_ptr + 1; HEXCHR(*vp) >= 0; vp++)
out = (uint8_t*)((uintptr_t(out) << 8) | HEXCHR(*vp));
return out;
}
static inline uint16_t hex_val(const char c, uint16_t const dval=0) {
if (!seen(c) || *value_ptr != 'x') return dval;
uint16_t out = 0;
for (char *vp = value_ptr + 1; HEXCHR(*vp) >= 0; vp++)
out = ((out) << 8) | HEXCHR(*vp);
return out;
}
#endif
}; };
extern GCodeParser parser; extern GCodeParser parser;

View file

@ -123,11 +123,15 @@ constexpr uint8_t epps = ENCODER_PULSES_PER_STEP;
#include "lcdprint.h" #include "lcdprint.h"
#include "../sd/cardreader.h" #include "../sd/cardreader.h"
#include "../module/settings.h"
#include "../module/temperature.h" #include "../module/temperature.h"
#include "../module/planner.h" #include "../module/planner.h"
#include "../module/motion.h" #include "../module/motion.h"
#if HAS_LCD_MENU
#include "../module/settings.h"
#endif
#if ENABLED(AUTO_BED_LEVELING_UBL) #if ENABLED(AUTO_BED_LEVELING_UBL)
#include "../feature/bedlevel/bedlevel.h" #include "../feature/bedlevel/bedlevel.h"
#endif #endif