My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

gcode_d.cpp 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #include "../inc/MarlinConfigPre.h"
  23. #if ENABLED(MARLIN_DEV_MODE)
  24. #include "gcode.h"
  25. #if ENABLED(BUFFER_MONITORING)
  26. #include "queue.h"
  27. #endif
  28. #include "../module/settings.h"
  29. #include "../module/temperature.h"
  30. #include "../libs/hex_print.h"
  31. #include "../HAL/shared/eeprom_if.h"
  32. #include "../HAL/shared/Delay.h"
  33. #include "../sd/cardreader.h"
  34. #include "../MarlinCore.h" // for kill
  35. void dump_delay_accuracy_check();
  36. /**
  37. * Dn: G-code for development and testing
  38. *
  39. * See https://reprap.org/wiki/G-code#D:_Debug_codes
  40. *
  41. * Put whatever else you need here to test ongoing development.
  42. */
  43. void GcodeSuite::D(const int16_t dcode) {
  44. switch (dcode) {
  45. case -1:
  46. for (;;) { /* loop forever (watchdog reset) */ }
  47. case 0:
  48. hal.reboot();
  49. break;
  50. case 10:
  51. kill(F("D10"), F("KILL TEST"), parser.seen_test('P'));
  52. break;
  53. case 1: {
  54. // Zero or pattern-fill the EEPROM data
  55. #if ENABLED(EEPROM_SETTINGS)
  56. persistentStore.access_start();
  57. size_t total = persistentStore.capacity();
  58. int pos = 0;
  59. const uint8_t value = 0x0;
  60. while (total--) persistentStore.write_data(pos, &value, 1);
  61. persistentStore.access_finish();
  62. #else
  63. settings.reset();
  64. settings.save();
  65. #endif
  66. hal.reboot();
  67. } break;
  68. case 2: { // D2 Read / Write SRAM
  69. #define SRAM_SIZE 8192
  70. uint8_t *pointer = parser.hex_adr_val('A');
  71. uint16_t len = parser.ushortval('C', 1);
  72. uintptr_t addr = (uintptr_t)pointer;
  73. NOMORE(addr, size_t(SRAM_SIZE - 1));
  74. NOMORE(len, SRAM_SIZE - addr);
  75. if (parser.seenval('X')) {
  76. // Write the hex bytes after the X
  77. uint16_t val = parser.hex_val('X');
  78. while (len--) {
  79. *pointer = val;
  80. pointer++;
  81. }
  82. }
  83. else {
  84. while (len--) print_hex_byte(*(pointer++));
  85. SERIAL_EOL();
  86. }
  87. } break;
  88. #if ENABLED(EEPROM_SETTINGS)
  89. case 3: { // D3 Read / Write EEPROM
  90. uint8_t *pointer = parser.hex_adr_val('A');
  91. uint16_t len = parser.ushortval('C', 1);
  92. uintptr_t addr = (uintptr_t)pointer;
  93. NOMORE(addr, size_t(persistentStore.capacity() - 1));
  94. NOMORE(len, persistentStore.capacity() - addr);
  95. if (parser.seenval('X')) {
  96. uint16_t val = parser.hex_val('X');
  97. #if ENABLED(EEPROM_SETTINGS)
  98. persistentStore.access_start();
  99. while (len--) {
  100. int pos = 0;
  101. persistentStore.write_data(pos, (uint8_t *)&val, sizeof(val));
  102. }
  103. SERIAL_EOL();
  104. persistentStore.access_finish();
  105. #else
  106. SERIAL_ECHOLNPGM("NO EEPROM");
  107. #endif
  108. }
  109. else {
  110. // Read bytes from EEPROM
  111. #if ENABLED(EEPROM_SETTINGS)
  112. persistentStore.access_start();
  113. int pos = 0;
  114. uint8_t val;
  115. while (len--) if (!persistentStore.read_data(pos, &val, 1)) print_hex_byte(val);
  116. SERIAL_EOL();
  117. persistentStore.access_finish();
  118. #else
  119. SERIAL_ECHOLNPGM("NO EEPROM");
  120. len = 0;
  121. #endif
  122. SERIAL_EOL();
  123. }
  124. } break;
  125. #endif
  126. case 4: { // D4 Read / Write PIN
  127. //const bool is_out = parser.boolval('F');
  128. //const uint8_t pin = parser.byteval('P'),
  129. // val = parser.byteval('V', LOW);
  130. if (parser.seenval('X')) {
  131. // TODO: Write the hex bytes after the X
  132. //while (len--) {
  133. //}
  134. }
  135. else {
  136. //while (len--) {
  137. //// TODO: Read bytes from EEPROM
  138. // print_hex_byte(eeprom_read_byte(adr++));
  139. //}
  140. SERIAL_EOL();
  141. }
  142. } break;
  143. case 5: { // D5 Read / Write onboard Flash
  144. #define FLASH_SIZE 1024
  145. uint8_t *pointer = parser.hex_adr_val('A');
  146. uint16_t len = parser.ushortval('C', 1);
  147. uintptr_t addr = (uintptr_t)pointer;
  148. NOMORE(addr, size_t(FLASH_SIZE - 1));
  149. NOMORE(len, FLASH_SIZE - addr);
  150. if (parser.seenval('X')) {
  151. // TODO: Write the hex bytes after the X
  152. //while (len--) {}
  153. }
  154. else {
  155. //while (len--) {
  156. //// TODO: Read bytes from EEPROM
  157. // print_hex_byte(eeprom_read_byte(adr++));
  158. //}
  159. SERIAL_EOL();
  160. }
  161. } break;
  162. case 6: // D6 Check delay loop accuracy
  163. dump_delay_accuracy_check();
  164. break;
  165. case 7: // D7 dump the current serial port type (hence configuration)
  166. SERIAL_ECHOLNPGM("Current serial configuration RX_BS:", RX_BUFFER_SIZE, ", TX_BS:", TX_BUFFER_SIZE);
  167. SERIAL_ECHOLN(gtn(&SERIAL_IMPL));
  168. break;
  169. case 100: { // D100 Disable heaters and attempt a hard hang (Watchdog Test)
  170. SERIAL_ECHOLNPGM("Disabling heaters and attempting to trigger Watchdog");
  171. SERIAL_ECHOLNPGM("(USE_WATCHDOG " TERN(USE_WATCHDOG, "ENABLED", "DISABLED") ")");
  172. thermalManager.disable_all_heaters();
  173. delay(1000); // Allow time to print
  174. hal.isr_off();
  175. // Use a low-level delay that does not rely on interrupts to function
  176. // Do not spin forever, to avoid thermal risks if heaters are enabled and
  177. // watchdog does not work.
  178. for (int i = 10000; i--;) DELAY_US(1000UL);
  179. hal.isr_on();
  180. SERIAL_ECHOLNPGM("FAILURE: Watchdog did not trigger board reset.");
  181. } break;
  182. #if ENABLED(SDSUPPORT)
  183. case 101: { // D101 Test SD Write
  184. card.openFileWrite("test.gco");
  185. if (!card.isFileOpen()) {
  186. SERIAL_ECHOLNPGM("Failed to open test.gco to write.");
  187. return;
  188. }
  189. __attribute__((aligned(sizeof(size_t)))) uint8_t buf[512];
  190. uint16_t c;
  191. for (c = 0; c < COUNT(buf); c++)
  192. buf[c] = 'A' + (c % ('Z' - 'A'));
  193. c = 1024 * 4;
  194. while (c--) {
  195. hal.watchdog_refresh();
  196. card.write(buf, COUNT(buf));
  197. }
  198. SERIAL_ECHOLNPGM(" done");
  199. card.closefile();
  200. } break;
  201. case 102: { // D102 Test SD Read
  202. char testfile[] = "test.gco";
  203. card.openFileRead(testfile);
  204. if (!card.isFileOpen()) {
  205. SERIAL_ECHOLNPGM("Failed to open test.gco to read.");
  206. return;
  207. }
  208. __attribute__((aligned(sizeof(size_t)))) uint8_t buf[512];
  209. uint16_t c = 1024 * 4;
  210. while (c--) {
  211. hal.watchdog_refresh();
  212. card.read(buf, COUNT(buf));
  213. bool error = false;
  214. for (uint16_t i = 0; i < COUNT(buf); i++) {
  215. if (buf[i] != ('A' + (i % ('Z' - 'A')))) {
  216. error = true;
  217. break;
  218. }
  219. }
  220. if (error) {
  221. SERIAL_ECHOLNPGM(" Read error!");
  222. break;
  223. }
  224. }
  225. SERIAL_ECHOLNPGM(" done");
  226. card.closefile();
  227. } break;
  228. #endif // SDSUPPORT
  229. #if ENABLED(POSTMORTEM_DEBUGGING)
  230. case 451: { // Trigger all kind of faults to test exception catcher
  231. SERIAL_ECHOLNPGM("Disabling heaters");
  232. thermalManager.disable_all_heaters();
  233. delay(1000); // Allow time to print
  234. volatile uint8_t type[5] = { parser.byteval('T', 1) };
  235. // The code below is obviously wrong and it's full of quirks to fool the compiler from optimizing away the code
  236. switch (type[0]) {
  237. case 1: default: *(int*)0 = 451; break; // Write at bad address
  238. case 2: { volatile int a = 0; volatile int b = 452 / a; *(int*)&a = b; } break; // Divide by zero (some CPUs accept this, like ARM)
  239. case 3: { *(uint32_t*)&type[1] = 453; volatile int a = *(int*)&type[1]; type[0] = a / 255; } break; // Unaligned access (some CPUs accept this)
  240. case 4: { volatile void (*func)() = (volatile void (*)()) 0xE0000000; func(); } break; // Invalid instruction
  241. }
  242. break;
  243. }
  244. #endif
  245. #if ENABLED(BUFFER_MONITORING)
  246. /**
  247. * D576: Return buffer stats or set the auto-report interval.
  248. * Usage: D576 [S<seconds>]
  249. *
  250. * With no parameters emits the following output:
  251. * "D576 P<nn> B<nn> PU<nn> PD<nn> BU<nn> BD<nn>"
  252. * Where:
  253. * P : Planner buffers free
  254. * B : Command buffers free
  255. * PU: Planner buffer underruns (since the last report)
  256. * PD: Longest duration (ms) the planner buffer was empty (since the last report)
  257. * BU: Command buffer underruns (since the last report)
  258. * BD: Longest duration (ms) command buffer was empty (since the last report)
  259. */
  260. case 576: {
  261. if (parser.seenval('S'))
  262. queue.set_auto_report_interval((uint8_t)parser.value_byte());
  263. else
  264. queue.report_buffer_statistics();
  265. break;
  266. }
  267. #endif // BUFFER_MONITORING
  268. }
  269. }
  270. #endif // MARLIN_DEV_MODE