From 5e9726530ff21d3bc62beaa6ac1b9437c276130a Mon Sep 17 00:00:00 2001 From: Roxy-3D Date: Sat, 15 Apr 2017 19:14:40 -0500 Subject: [PATCH] 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). --- Marlin/M100_Free_Mem_Chk.cpp | 28 +++++-- Marlin/Marlin_main.cpp | 9 ++ Marlin/configuration_store.cpp | 20 +++-- Marlin/ubl_G29.cpp | 145 +++++++++++++++++---------------- 4 files changed, 117 insertions(+), 85 deletions(-) diff --git a/Marlin/M100_Free_Mem_Chk.cpp b/Marlin/M100_Free_Mem_Chk.cpp index 08236ff95..5387a71ed 100644 --- a/Marlin/M100_Free_Mem_Chk.cpp +++ b/Marlin/M100_Free_Mem_Chk.cpp @@ -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 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));