Setup to find data corruption and general clean up

This data corruption problem is very difficult.  Just changing the code
a little bit changes whether the problem even happens and what is
affected.  I need these changes in the main branch so I can operate with
the extra debug code always available and turned on.

Everything is setup such that if M100 is turned off or DEBUG(ECHO) is
turned off, the code is not affected.   M100 has been made a little bit
more inteligent so it can display the serial command buffers in a more
meaningful way (because the data corruption seems to often times end up
in that area).
master
Roxy-3D 7 years ago committed by Roxy-3D
parent e519e95953
commit 5e9726530f

@ -41,7 +41,7 @@
* Also, there are two support functions that can be called from a developer's C code.
*
* uint16_t check_for_free_memory_corruption(char * const ptr);
* void M100_dump_free_memory(char *ptr, char *sp);
* void M100_dump_routine( char *title, char *start, char *end);
*
* Initial version by Roxy-3D
*/
@ -52,7 +52,9 @@
#if ENABLED(M100_FREE_MEMORY_WATCHER)
#define TEST_BYTE ((uint8_t) 0xE5)
#define TEST_BYTE ((char) 0xE5)
extern char command_queue[BUFSIZE][MAX_CMD_SIZE];
extern char* __brkval;
extern size_t __heap_start, __heap_end, __flp;
@ -78,7 +80,7 @@ char* top_of_stack() {
// Count the number of test bytes at the specified location.
int16_t count_test_bytes(const uint8_t * const ptr) {
for (uint16_t i = 0; i < 32000; i++)
if (ptr[i] != TEST_BYTE)
if (((char) ptr[i]) != TEST_BYTE)
return i - 1;
return -1;
@ -118,8 +120,20 @@ int16_t count_test_bytes(const uint8_t * const ptr) {
}
safe_delay(25);
SERIAL_CHAR('|'); // Point out non test bytes
for (uint8_t i = 0; i < 16; i++)
SERIAL_CHAR(ptr[i] == TEST_BYTE ? ' ' : '?');
for (uint8_t i = 0; i < 16; i++) {
char ccc;
ccc = (char) ptr[i];
if ( &ptr[i]>=&command_queue[0][0] && &ptr[i]<&command_queue[BUFSIZE][MAX_CMD_SIZE]) { // Print out ASCII in the command
if ( ccc<' ' || ccc>0x7e) // buffer area
ccc = ' ';
}
else
if (ccc != TEST_BYTE) // If not display data in the command buffer
ccc = '?'; // area, we flag bytes that don't match the test byte
else
ccc = ' ';
SERIAL_CHAR(ccc);
}
SERIAL_EOL;
ptr += 16;
safe_delay(25);
@ -220,7 +234,7 @@ void init_free_memory(uint8_t *ptr, int16_t size) {
SERIAL_ECHOLNPGM(" bytes of memory initialized.\n");
for (uint16_t i = 0; i < size; i++) {
if (ptr[i] != TEST_BYTE) {
if (((char) ptr[i]) != TEST_BYTE) {
SERIAL_ECHOPAIR("? address : 0x", hex_word((uint16_t)ptr + i));
SERIAL_ECHOLNPAIR("=", hex_byte(ptr[i]));
}
@ -288,7 +302,9 @@ int check_for_free_memory_corruption(char *title) {
// while ( !READ(63))
// idle();
safe_delay(20);
#ifdef M100_FREE_MEMORY_DUMPER
M100_dump_routine( " Memory corruption detected with sp<Heap\n", (char *)0x1b80, 0x21ff );
#endif
}
// Scan through the range looking for the biggest block of 0xE5's we can find

@ -284,6 +284,7 @@
#if ENABLED(M100_FREE_MEMORY_WATCHER)
void gcode_M100();
void M100_dump_routine( char *title, char *start, char *end);
#endif
#if ENABLED(SDSUPPORT)
@ -359,7 +360,11 @@ static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
uint8_t commands_in_queue = 0; // Count of commands in the queue
static uint8_t cmd_queue_index_r = 0, // Ring buffer read position
cmd_queue_index_w = 0; // Ring buffer write position
#if ENABLED(M100_FREE_MEMORY_WATCHER)
char command_queue[BUFSIZE][MAX_CMD_SIZE]; // Necessary so M100 Free Memory Dumper can show us the commands and any corruption
#else // This can be collapsed back to the way it was soon.
static char command_queue[BUFSIZE][MAX_CMD_SIZE];
#endif
/**
* Current GCode Command
@ -9561,6 +9566,10 @@ void process_next_command() {
if (DEBUGGING(ECHO)) {
SERIAL_ECHO_START;
SERIAL_ECHOLN(current_command);
#if ENABLED(M100_FREE_MEMORY_WATCHER)
SERIAL_ECHOPAIR("slot:", cmd_queue_index_r);
M100_dump_routine( " Command Queue:", &command_queue[0][0], &command_queue[BUFSIZE][MAX_CMD_SIZE] );
#endif
}
// Sanitize the current command:

@ -1330,17 +1330,21 @@ void MarlinSettings::reset() {
SERIAL_ECHOPAIR("EEPROM can hold ", (int)((UBL_LAST_EEPROM_INDEX - ubl.eeprom_start) / sizeof(ubl.z_values)));
SERIAL_ECHOLNPGM(" meshes.\n");
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_X " STRINGIFY(GRID_MAX_POINTS_X));
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_Y " STRINGIFY(GRID_MAX_POINTS_Y));
SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_X ", GRID_MAX_POINTS_X);
SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_Y ", GRID_MAX_POINTS_Y);
SERIAL_ECHOLNPGM("UBL_MESH_MIN_X " STRINGIFY(UBL_MESH_MIN_X));
SERIAL_ECHOLNPGM("UBL_MESH_MIN_Y " STRINGIFY(UBL_MESH_MIN_Y));
SERIAL_ECHOPGM("UBL_MESH_MIN_X " STRINGIFY(UBL_MESH_MIN_X));
SERIAL_ECHOLNPAIR("=", UBL_MESH_MIN_X );
SERIAL_ECHOPGM("UBL_MESH_MIN_Y " STRINGIFY(UBL_MESH_MIN_Y));
SERIAL_ECHOLNPAIR("=", UBL_MESH_MIN_Y );
SERIAL_ECHOLNPGM("UBL_MESH_MAX_X " STRINGIFY(UBL_MESH_MAX_X));
SERIAL_ECHOLNPGM("UBL_MESH_MAX_Y " STRINGIFY(UBL_MESH_MAX_Y));
SERIAL_ECHOPGM("UBL_MESH_MAX_X " STRINGIFY(UBL_MESH_MAX_X));
SERIAL_ECHOLNPAIR("=", UBL_MESH_MAX_X);
SERIAL_ECHOPGM("UBL_MESH_MAX_Y " STRINGIFY(UBL_MESH_MAX_Y));
SERIAL_ECHOLNPAIR("=", UBL_MESH_MAX_Y);
SERIAL_ECHOLNPAIR("MESH_X_DIST ", MESH_X_DIST);
SERIAL_ECHOLNPAIR("MESH_Y_DIST ", MESH_Y_DIST);
SERIAL_ECHOLNPAIR("MESH_X_DIST ", MESH_X_DIST);
SERIAL_ECHOLNPAIR("MESH_Y_DIST ", MESH_Y_DIST);
SERIAL_EOL;
}

@ -102,8 +102,6 @@
* specified height, no correction is applied and natural printer kenimatics take over. If no
* number is specified for the command, 10mm is assumed to be reasonable.
*
* G # Grid * Perform a Grid Based Leveling of the current Mesh using a grid with n points on a side.
*
* H # Height Specify the Height to raise the nozzle after each manual probe of the bed. The
* default is 5mm.
*
@ -117,6 +115,10 @@
* the bed and use this feature to select the center of the area (or cell) you want to
* invalidate.
*
* J # Grid * Perform a Grid Based Leveling of the current Mesh using a grid with n points on a side.
*
* j EEPROM Dump This function probably goes away after debug is complete.
*
* K # Kompare Kompare current Mesh with stored Mesh # replacing current Mesh with the result. This
* command literally performs a diff between two Meshes.
*
@ -303,7 +305,7 @@
// The simple parameter flags and values are 'static' so parameter parsing can be in a support routine.
static int g29_verbose_level, phase_value = -1, repetition_cnt,
storage_slot = 0, map_type, grid_size_G ; //unlevel_value = -1;
storage_slot=0, map_type, grid_size;
static bool repeat_flag, c_flag, x_flag, y_flag;
static float x_pos, y_pos, measured_z, card_thickness = 0.0, ubl_constant = 0.0;
@ -378,24 +380,9 @@
}
}
/*
if (code_seen('U')) {
unlevel_value = code_value_int();
//if (!WITHIN(unlevel_value, 0, 7)) {
// SERIAL_PROTOCOLLNPGM("Invalid Unlevel value. (0-4)\n");
// return;
//}
}
*/
if (code_seen('G')) {
uint8_t grid_size_G = code_has_value() ? code_value_int() : 3;
if (grid_size_G < 2) {
SERIAL_PROTOCOLLNPGM("ERROR - grid size must be 2 or more");
return;
}
if (grid_size_G > GRID_MAX_POINTS_X || grid_size_G > GRID_MAX_POINTS_Y) {
SERIAL_PROTOCOLLNPGM("ERROR - grid size can NOT exceed GRID_MAX_POINTS_X nor GRID_MAX_POINTS_Y");
if (code_seen('J')) {
if (grid_size<2 || grid_size>5) {
SERIAL_PROTOCOLLNPGM("ERROR - grid size must be between 2 and 5");
return;
}
tilt_mesh_based_on_probed_grid(code_seen('O') || code_seen('M'));
@ -567,7 +554,7 @@
// When we are fully debugged, the EEPROM dump command will get deleted also. But
// right now, it is good to have the extra information. Soon... we prune this.
//
if (code_seen('J')) g29_eeprom_dump(); // EEPROM Dump
if (code_seen('j')) g29_eeprom_dump(); // EEPROM Dump
//
// When we are fully debugged, this may go away. But there are some valid
@ -692,11 +679,9 @@
LEAVE:
#if ENABLED(ULTRA_LCD)
lcd_reset_alert_level();
LCD_MESSAGEPGM("");
lcd_quick_feedback();
#endif
lcd_reset_alert_level();
LCD_MESSAGEPGM("");
lcd_quick_feedback();
ubl.has_control_of_lcd_panel = false;
}
@ -997,18 +982,26 @@
}
bool g29_parameter_parsing() {
#if ENABLED(ULTRA_LCD)
bool err_flag = false;
LCD_MESSAGEPGM("Doing G29 UBL!");
lcd_quick_feedback();
#endif
x_flag = code_seen('X') && code_has_value();
y_flag = code_seen('Y') && code_has_value();
x_pos = x_flag ? code_value_float() : current_position[X_AXIS];
y_flag = code_seen('Y') && code_has_value();
y_pos = y_flag ? code_value_float() : current_position[Y_AXIS];
repeat_flag = code_seen('R') ? code_value_bool() : false;
bool err_flag = false;
repetition_cnt = 0;
repeat_flag = code_seen('R');
if (repeat_flag) {
repetition_cnt = code_has_value() ? code_value_int() : GRID_MAX_POINTS_X*GRID_MAX_POINTS_Y;
if (repetition_cnt < 1) {
SERIAL_PROTOCOLLNPGM("Invalid Repetition count.\n");
return UBL_ERR;
}
}
g29_verbose_level = code_seen('V') ? code_value_int() : 0;
if (!WITHIN(g29_verbose_level, 0, 4)) {
@ -1017,8 +1010,8 @@
}
if (code_seen('G')) {
grid_size_G = code_has_value() ? code_value_int() : 3;
if (!WITHIN(grid_size_G, 2, 10)) {
grid_size = code_has_value() ? code_value_int() : 3;
if (!WITHIN(grid_size, 2, 5)) {
SERIAL_PROTOCOLLNPGM("Invalid grid probe points specified.\n");
err_flag = true;
}
@ -1032,11 +1025,27 @@
if (!WITHIN(RAW_X_POSITION(x_pos), X_MIN_POS, X_MAX_POS)) {
SERIAL_PROTOCOLLNPGM("Invalid X location specified.\n");
err_flag = true;
SERIAL_PROTOCOLPAIR("\nx_flag = ", x_flag); // These print blocks are only useful because sometimes the
SERIAL_PROTOCOLPAIR("\nx_pos = ", x_pos ); // data corruption causes x_pos and y_pos to be crazy. This gets deleted soon.
SERIAL_PROTOCOLPAIR("\ncurrent[] = ", current_position[X_AXIS]);
SERIAL_PROTOCOLPAIR("\nX_MIN_POS = ", X_MIN_POS);
SERIAL_PROTOCOLPAIR("\nX_MAX_POS = ", X_MAX_POS);
SERIAL_PROTOCOLPAIR("\nRAW_X_POSITION() = ", RAW_X_POSITION(x_pos));
SERIAL_PROTOCOLPAIR("\nwithin() = ", WITHIN(RAW_X_POSITION(x_pos), X_MIN_POS, X_MAX_POS));
SERIAL_PROTOCOL("\n");
}
if (!WITHIN(RAW_Y_POSITION(y_pos), Y_MIN_POS, Y_MAX_POS)) {
SERIAL_PROTOCOLLNPGM("Invalid Y location specified.\n");
err_flag = true;
SERIAL_PROTOCOLPAIR("\ny_flag = ", y_flag); // These print blocks are only useful because sometimes the
SERIAL_PROTOCOLPAIR("\ny_pos = ", y_pos ); // data corruption causes x_pos and y_pos to be crazy. This gets deleted soon.
SERIAL_PROTOCOLPAIR("\ncurrent[] = ", current_position[Y_AXIS]);
SERIAL_PROTOCOLPAIR("\nY_MIN_POS = ", Y_MIN_POS);
SERIAL_PROTOCOLPAIR("\nY_MAX_POS = ", Y_MAX_POS);
SERIAL_PROTOCOLPAIR("\nRAW_Y_POSITION() = ", RAW_Y_POSITION(y_pos));
SERIAL_PROTOCOLPAIR("\nwithin() = ", WITHIN(RAW_Y_POSITION(y_pos), Y_MIN_POS, Y_MAX_POS));
SERIAL_PROTOCOL("\n");
}
if (err_flag) return UBL_ERR;
@ -1068,11 +1077,6 @@
}
#endif
repetition_cnt = repeat_flag ? (code_has_value() ? code_value_int() : 9999) : 1;
if (repetition_cnt < 1) {
SERIAL_PROTOCOLLNPGM("Invalid Repetition count.\n");
return UBL_ERR;
}
map_type = code_seen('O') && code_has_value() ? code_value_int() : 0;
if (!WITHIN(map_type, 0, 1)) {
@ -1365,9 +1369,8 @@
}
void fine_tune_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map) {
// do all mesh points unless R option has a value of 1 or more
repetition_cnt = code_seen('R') && code_has_value() ? code_value_byte() : GRID_MAX_POINTS_X * GRID_MAX_POINTS_Y;
if (repetition_cnt == 0) repetition_cnt = GRID_MAX_POINTS_X * GRID_MAX_POINTS_Y;
if (!code_seen('R')) // fine_tune_mesh() is special. If no repetion count flag is specified
repetition_cnt = 1; // we know to do exactly one mesh location. Otherwise we use what the parser decided.
mesh_index_pair location;
uint16_t not_done[16];
@ -1448,7 +1451,7 @@
lcd_implementation_clear();
} while (location.x_index >= 0 && location.y_index >= 0 && --repetition_cnt);
} while (location.x_index >= 0 && location.y_index >= 0 && (--repetition_cnt>0));
FINE_TUNE_EXIT:
@ -1466,16 +1469,16 @@
}
void tilt_mesh_based_on_probed_grid(const bool do_ubl_mesh_map) {
int8_t grid_G_index_to_xpos[grid_size_G], // UBL MESH X index to be probed
grid_G_index_to_ypos[grid_size_G], // UBL MESH Y index to be probed
i, j ,k, xCount, yCount, G_X_index, G_Y_index; // counter variables
float z_values_G[grid_size_G][grid_size_G];
int8_t grid_G_index_to_xpos[grid_size], // UBL MESH X index to be probed
grid_G_index_to_ypos[grid_size], // UBL MESH Y index to be probed
i, j ,k, xCount, yCount, xi, yi; // counter variables
float z_values_G[grid_size][grid_size];
linear_fit *results;
for (G_Y_index = 0; G_Y_index < grid_size_G; G_Y_index++)
for (G_X_index = 0; G_X_index < grid_size_G; G_X_index++)
z_values_G[G_X_index][G_Y_index] = NAN;
for (yi = 0; yi < grid_size; yi++)
for (xi = 0; xi < grid_size; xi++)
z_values_G[xi][yi] = NAN;
uint8_t x_min = GRID_MAX_POINTS_X - 1,
x_max = 0,
@ -1494,26 +1497,26 @@
}
}
if (x_max - x_min + 1 < grid_size_G || y_max - y_min + 1 < grid_size_G) {
if (x_max - x_min + 1 < grid_size || y_max - y_min + 1 < grid_size) {
SERIAL_ECHOPAIR("ERROR - probeable UBL MESH smaller than grid - X points: ", x_max - x_min + 1);
SERIAL_ECHOPAIR(" Y points: ", y_max - y_min + 1);
SERIAL_ECHOLNPAIR(" grid: ", grid_size_G);
SERIAL_ECHOLNPAIR(" grid: ", grid_size);
return;
}
// populate X matrix
for (G_X_index = 0; G_X_index < grid_size_G; G_X_index++) {
grid_G_index_to_xpos[G_X_index] = x_min + G_X_index * (x_max - x_min) / (grid_size_G - 1);
if (G_X_index > 0 && grid_G_index_to_xpos[G_X_index - 1] == grid_G_index_to_xpos[G_X_index]) {
grid_G_index_to_xpos[G_X_index] = grid_G_index_to_xpos[G_X_index - 1] + 1;
for (xi = 0; xi < grid_size; xi++) {
grid_G_index_to_xpos[xi] = x_min + xi * (x_max - x_min) / (grid_size - 1);
if (xi > 0 && grid_G_index_to_xpos[xi - 1] == grid_G_index_to_xpos[xi]) {
grid_G_index_to_xpos[xi] = grid_G_index_to_xpos[xi - 1] + 1;
}
}
// populate Y matrix
for (G_Y_index = 0; G_Y_index < grid_size_G; G_Y_index++) {
grid_G_index_to_ypos[G_Y_index] = y_min + G_Y_index * (y_max - y_min) / (grid_size_G - 1);
if (G_Y_index > 0 && grid_G_index_to_ypos[G_Y_index - 1] == grid_G_index_to_ypos[G_Y_index]) {
grid_G_index_to_ypos[G_Y_index] = grid_G_index_to_ypos[G_Y_index - 1] + 1;
for (yi = 0; yi < grid_size; yi++) {
grid_G_index_to_ypos[yi] = y_min + yi * (y_max - y_min) / (grid_size - 1);
if (yi > 0 && grid_G_index_to_ypos[yi - 1] == grid_G_index_to_ypos[yi]) {
grid_G_index_to_ypos[yi] = grid_G_index_to_ypos[yi - 1] + 1;
}
}
@ -1526,14 +1529,14 @@
#undef PROBE_Y_FIRST
#if ENABLED(PROBE_Y_FIRST)
#define PR_OUTER_VAR xCount
#define PR_OUTER_NUM grid_size_G
#define PR_OUTER_NUM grid_size
#define PR_INNER_VAR yCount
#define PR_INNER_NUM grid_size_G
#define PR_INNER_NUM grid_size
#else
#define PR_OUTER_VAR yCount
#define PR_OUTER_NUM grid_size_G
#define PR_OUTER_NUM grid_size
#define PR_INNER_VAR xCount
#define PR_INNER_NUM grid_size_G
#define PR_INNER_NUM grid_size
#endif
bool zig = PR_OUTER_NUM & 1; // Always end at RIGHT and BACK_PROBE_BED_POSITION
@ -1601,9 +1604,9 @@
//do_blocking_move_to_xy(ubl.mesh_index_to_xpos[grid_G_index_to_xpos[0]], ubl.mesh_index_to_ypos[grid_G_index_to_ypos[0]]);
// least squares code
double xxx9[] = { 0,50,100,150,200, 20,70,120,165,195, 0,50,100,150,200, 0,55,100,150,200, 0,65,100,150,205 },
yyy9[] = { 0, 1, 2, 3, 4, 50, 51, 52, 53, 54, 100, 101,102,103,104, 150,151,152,153,154, 200,201,202,203,204 },
zzz9[] = { 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.012,0.01},
double xxx5[] = { 0,50,100,150,200, 20,70,120,165,195, 0,50,100,150,200, 0,55,100,150,200, 0,65,100,150,205 },
yyy5[] = { 0, 1, 2, 3, 4, 50, 51, 52, 53, 54, 100, 101,102,103,104, 150,151,152,153,154, 200,201,202,203,204 },
zzz5[] = { 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.012,0.01},
xxx0[] = { 0.0, 0.0, 1.0 }, // Expect [0,0,0.1,0]
yyy0[] = { 0.0, 1.0, 0.0 },
zzz0[] = { 0.1, 0.1, 0.1 },
@ -1611,10 +1614,10 @@
yyy[] = { 0.0, 1.0, 0.0, 1.0 },
zzz[] = { 0.05, 0.05, 0.15, 0.15 };
results = lsf_linear_fit(xxx9, yyy9, zzz9, COUNT(xxx9));
SERIAL_ECHOPAIR("\nxxx9->A =", results->A);
SERIAL_ECHOPAIR("\nxxx9->B =", results->B);
SERIAL_ECHOPAIR("\nxxx9->D =", results->D);
results = lsf_linear_fit(xxx5, yyy5, zzz5, COUNT(xxx5));
SERIAL_ECHOPAIR("\nxxx5->A =", results->A);
SERIAL_ECHOPAIR("\nxxx5->B =", results->B);
SERIAL_ECHOPAIR("\nxxx5->D =", results->D);
SERIAL_EOL;
results = lsf_linear_fit(xxx0, yyy0, zzz0, COUNT(xxx0));

Loading…
Cancel
Save