|
@@ -40,8 +40,8 @@
|
40
|
40
|
*
|
41
|
41
|
* Also, there are two support functions that can be called from a developer's C code.
|
42
|
42
|
*
|
43
|
|
- * uint16_t check_for_free_memory_corruption(char * const ptr);
|
44
|
|
- * void M100_dump_routine( char *title, char *start, char *end);
|
|
43
|
+ * uint16_t check_for_free_memory_corruption(const char * const ptr);
|
|
44
|
+ * void M100_dump_routine(const char * const title, const char *start, const char *end);
|
45
|
45
|
*
|
46
|
46
|
* Initial version by Roxy-3D
|
47
|
47
|
*/
|
|
@@ -68,7 +68,7 @@ extern char __bss_end;
|
68
|
68
|
//
|
69
|
69
|
|
70
|
70
|
#define END_OF_HEAP() (__brkval ? __brkval : &__bss_end)
|
71
|
|
-int check_for_free_memory_corruption(char *title);
|
|
71
|
+int check_for_free_memory_corruption(const char * const title);
|
72
|
72
|
|
73
|
73
|
// Location of a variable on its stack frame. Returns a value above
|
74
|
74
|
// the stack (once the function returns to the caller).
|
|
@@ -100,7 +100,7 @@ int16_t count_test_bytes(const uint8_t * const ptr) {
|
100
|
100
|
* the block. If so, it may indicate memory corruption due to a bad pointer.
|
101
|
101
|
* Unexpected bytes are flagged in the right column.
|
102
|
102
|
*/
|
103
|
|
- void dump_free_memory(uint8_t *ptr, uint8_t *sp) {
|
|
103
|
+ void dump_free_memory(const uint8_t *ptr, const uint8_t *sp) {
|
104
|
104
|
//
|
105
|
105
|
// Start and end the dump on a nice 16 byte boundary
|
106
|
106
|
// (even though the values are not 16-byte aligned).
|
|
@@ -120,17 +120,13 @@ int16_t count_test_bytes(const uint8_t * const ptr) {
|
120
|
120
|
safe_delay(25);
|
121
|
121
|
SERIAL_CHAR('|'); // Point out non test bytes
|
122
|
122
|
for (uint8_t i = 0; i < 16; i++) {
|
123
|
|
- char ccc;
|
124
|
|
- ccc = (char) ptr[i];
|
125
|
|
- if ( &ptr[i]>=&command_queue[0][0] && &ptr[i]<&command_queue[BUFSIZE][MAX_CMD_SIZE]) { // Print out ASCII in the command
|
126
|
|
- if ( ccc<' ' || ccc>0x7e) // buffer area
|
127
|
|
- ccc = ' ';
|
128
|
|
- }
|
129
|
|
- else
|
130
|
|
- if (ccc != TEST_BYTE) // If not display data in the command buffer
|
131
|
|
- ccc = '?'; // area, we flag bytes that don't match the test byte
|
132
|
|
- else
|
133
|
|
- ccc = ' ';
|
|
123
|
+ char ccc = (char)ptr[i]; // cast to char before automatically casting to char on assignment, in case the compiler is broken
|
|
124
|
+ if (&ptr[i] >= command_queue && &ptr[i] < &command_queue[BUFSIZE][MAX_CMD_SIZE]) { // Print out ASCII in the command buffer area
|
|
125
|
+ if (!WITHIN(ccc, ' ', 0x7E)) ccc = ' ';
|
|
126
|
+ }
|
|
127
|
+ else { // If not in the command buffer area, flag bytes that don't match the test byte
|
|
128
|
+ ccc = (ccc == TEST_BYTE) ? ' ' : '?';
|
|
129
|
+ }
|
134
|
130
|
SERIAL_CHAR(ccc);
|
135
|
131
|
}
|
136
|
132
|
SERIAL_EOL;
|
|
@@ -140,19 +136,16 @@ int16_t count_test_bytes(const uint8_t * const ptr) {
|
140
|
136
|
}
|
141
|
137
|
}
|
142
|
138
|
|
143
|
|
-void M100_dump_routine( char *title, char *start, char *end) {
|
144
|
|
-unsigned char c;
|
145
|
|
-int i;
|
146
|
|
-
|
147
|
|
-//
|
148
|
|
-// Round the start and end locations to produce full lines of output
|
149
|
|
-//
|
150
|
|
- start = (char*) ((uint16_t) start & 0xfff0);
|
151
|
|
- end = (char*) ((uint16_t) end | 0x000f);
|
152
|
|
-
|
153
|
|
- SERIAL_ECHOLN(title);
|
154
|
|
- dump_free_memory( start, end );
|
|
139
|
+void M100_dump_routine(const char * const title, const char *start, const char *end) {
|
|
140
|
+ SERIAL_ECHOLN(title);
|
|
141
|
+ //
|
|
142
|
+ // Round the start and end locations to produce full lines of output
|
|
143
|
+ //
|
|
144
|
+ start = (char*)((uint16_t) start & 0xfff0);
|
|
145
|
+ end = (char*)((uint16_t) end | 0x000f);
|
|
146
|
+ dump_free_memory(start, end);
|
155
|
147
|
}
|
|
148
|
+
|
156
|
149
|
#endif // M100_FREE_MEMORY_DUMPER
|
157
|
150
|
|
158
|
151
|
/**
|
|
@@ -233,10 +226,10 @@ void init_free_memory(uint8_t *ptr, int16_t size) {
|
233
|
226
|
SERIAL_ECHOLNPGM(" bytes of memory initialized.\n");
|
234
|
227
|
|
235
|
228
|
for (uint16_t i = 0; i < size; i++) {
|
236
|
|
- if (((char) ptr[i]) != TEST_BYTE) {
|
|
229
|
+ if ((char)ptr[i] != TEST_BYTE) {
|
237
|
230
|
SERIAL_ECHOPAIR("? address : ", hex_address(ptr + i));
|
238
|
|
- SERIAL_ECHOPAIR("=", hex_byte(ptr[i]));
|
239
|
|
- SERIAL_EOL; SERIAL_EOL;
|
|
231
|
+ SERIAL_ECHOLNPAIR("=", hex_byte(ptr[i]));
|
|
232
|
+ SERIAL_EOL;
|
240
|
233
|
}
|
241
|
234
|
}
|
242
|
235
|
}
|
|
@@ -276,68 +269,66 @@ void gcode_M100() {
|
276
|
269
|
#endif
|
277
|
270
|
}
|
278
|
271
|
|
279
|
|
-int check_for_free_memory_corruption(char *title) {
|
280
|
|
- char *sp, *ptr;
|
281
|
|
- int block_cnt = 0, i, j, n;
|
282
|
|
-
|
283
|
|
- SERIAL_ECHO(title);
|
284
|
|
-
|
285
|
|
- ptr = __brkval ? __brkval : &__bss_end;
|
286
|
|
- sp = top_of_stack();
|
287
|
|
-
|
288
|
|
- n = sp - ptr;
|
289
|
|
- SERIAL_ECHOPAIR("\nfmc() n=", n);
|
290
|
|
- SERIAL_ECHOPAIR("\n&__brkval: ", hex_address(&__brkval));
|
291
|
|
- SERIAL_ECHOPAIR("=", hex_address(__brkval));
|
292
|
|
- SERIAL_ECHOPAIR("\n__bss_end: ", hex_address(&__bss_end));
|
293
|
|
- SERIAL_ECHOPAIR(" sp=", hex_word(sp));
|
294
|
|
-
|
295
|
|
- if (sp < ptr) {
|
296
|
|
- SERIAL_ECHOPGM(" sp < Heap ");
|
297
|
|
-// SET_INPUT_PULLUP(63); // if the developer has a switch wired up to their controller board
|
298
|
|
-// safe_delay(5); // this code can be enabled to pause the display as soon as the
|
299
|
|
-// while ( READ(63)) // malfunction is detected. It is currently defaulting to a switch
|
300
|
|
-// idle(); // being on pin-63 which is unassigend and available on most controller
|
301
|
|
-// safe_delay(20); // boards.
|
302
|
|
-// while ( !READ(63))
|
303
|
|
-// idle();
|
304
|
|
- safe_delay(20);
|
305
|
|
- #ifdef M100_FREE_MEMORY_DUMPER
|
306
|
|
- M100_dump_routine( " Memory corruption detected with sp<Heap\n", (char *)0x1b80, 0x21ff );
|
307
|
|
- #endif
|
308
|
|
- }
|
|
272
|
+int check_for_free_memory_corruption(const char * const title) {
|
|
273
|
+ SERIAL_ECHO(title);
|
|
274
|
+
|
|
275
|
+ char *ptr = END_OF_HEAP(), *sp = top_of_stack();
|
|
276
|
+ int n = sp - ptr;
|
|
277
|
+
|
|
278
|
+ SERIAL_ECHOPAIR("\nfmc() n=", n);
|
|
279
|
+ SERIAL_ECHOPAIR("\n&__brkval: ", hex_address(&__brkval));
|
|
280
|
+ SERIAL_ECHOPAIR("=", hex_address(__brkval));
|
|
281
|
+ SERIAL_ECHOPAIR("\n__bss_end: ", hex_address(&__bss_end));
|
|
282
|
+ SERIAL_ECHOPAIR(" sp=", hex_address(sp));
|
|
283
|
+
|
|
284
|
+ if (sp < ptr) {
|
|
285
|
+ SERIAL_ECHOPGM(" sp < Heap ");
|
|
286
|
+ // SET_INPUT_PULLUP(63); // if the developer has a switch wired up to their controller board
|
|
287
|
+ // safe_delay(5); // this code can be enabled to pause the display as soon as the
|
|
288
|
+ // while ( READ(63)) // malfunction is detected. It is currently defaulting to a switch
|
|
289
|
+ // idle(); // being on pin-63 which is unassigend and available on most controller
|
|
290
|
+ // safe_delay(20); // boards.
|
|
291
|
+ // while ( !READ(63))
|
|
292
|
+ // idle();
|
|
293
|
+ safe_delay(20);
|
|
294
|
+ #ifdef M100_FREE_MEMORY_DUMPER
|
|
295
|
+ M100_dump_routine(" Memory corruption detected with sp<Heap\n", (char*)0x1B80, 0x21FF);
|
|
296
|
+ #endif
|
|
297
|
+ }
|
309
|
298
|
|
310
|
|
- // Scan through the range looking for the biggest block of 0xE5's we can find
|
311
|
|
- for (i = 0; i < n; i++) {
|
312
|
|
- if (*(ptr + i) == (char)0xe5) {
|
313
|
|
- j = count_test_bytes(ptr + i);
|
314
|
|
- if (j > 8) {
|
315
|
|
-// SERIAL_ECHOPAIR("Found ", j);
|
316
|
|
-// SERIAL_ECHOLNPAIR(" bytes free at 0x", hex_word((uint16_t)(ptr + i)));
|
317
|
|
-
|
318
|
|
- i += j;
|
319
|
|
- block_cnt++;
|
320
|
|
- SERIAL_ECHOPAIR(" (", block_cnt);
|
321
|
|
- SERIAL_ECHOPAIR(") found=", j);
|
322
|
|
- SERIAL_ECHOPGM(" ");
|
323
|
|
- }
|
|
299
|
+ // Scan through the range looking for the biggest block of 0xE5's we can find
|
|
300
|
+ int block_cnt = 0;
|
|
301
|
+ for (int i = 0; i < n; i++) {
|
|
302
|
+ if (ptr[i] == TEST_BYTE) {
|
|
303
|
+ int16_t j = count_test_bytes(ptr + i);
|
|
304
|
+ if (j > 8) {
|
|
305
|
+ // SERIAL_ECHOPAIR("Found ", j);
|
|
306
|
+ // SERIAL_ECHOLNPAIR(" bytes free at ", hex_address(ptr + i));
|
|
307
|
+ i += j;
|
|
308
|
+ block_cnt++;
|
|
309
|
+ SERIAL_ECHOPAIR(" (", block_cnt);
|
|
310
|
+ SERIAL_ECHOPAIR(") found=", j);
|
|
311
|
+ SERIAL_ECHOPGM(" ");
|
324
|
312
|
}
|
325
|
313
|
}
|
326
|
|
- SERIAL_ECHOPAIR(" block_found=", block_cnt);
|
|
314
|
+ }
|
|
315
|
+ SERIAL_ECHOPAIR(" block_found=", block_cnt);
|
327
|
316
|
|
328
|
|
- if ((block_cnt!=1) || (__brkval != 0x0000))
|
329
|
|
- SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area.");
|
|
317
|
+ if (block_cnt != 1 || __brkval != 0x0000)
|
|
318
|
+ SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area.");
|
330
|
319
|
|
331
|
|
- if ((block_cnt==0)) // Make sure the special case of no free blocks shows up as an
|
332
|
|
- block_cnt = -1; // error to the calling code!
|
|
320
|
+ if (block_cnt == 0) // Make sure the special case of no free blocks shows up as an
|
|
321
|
+ block_cnt = -1; // error to the calling code!
|
333
|
322
|
|
334
|
|
- if (block_cnt==1) {
|
335
|
|
- SERIAL_ECHOPGM(" return=0\n"); // if the block_cnt is 1, nothing has broken up the free memory
|
336
|
|
- return 0; // area and it is appropriate to say 'no corruption'.
|
337
|
|
- }
|
338
|
|
- SERIAL_ECHOPGM(" return=true\n");
|
339
|
|
- return block_cnt;
|
|
323
|
+ SERIAL_ECHOPGM(" return=");
|
|
324
|
+ if (block_cnt == 1) {
|
|
325
|
+ SERIAL_CHAR('0'); // if the block_cnt is 1, nothing has broken up the free memory
|
|
326
|
+ SERIAL_EOL; // area and it is appropriate to say 'no corruption'.
|
|
327
|
+ return 0;
|
340
|
328
|
}
|
|
329
|
+ SERIAL_ECHOLNPGM("true");
|
|
330
|
+ return block_cnt;
|
|
331
|
+}
|
341
|
332
|
|
342
|
333
|
#endif // M100_FREE_MEMORY_WATCHER
|
343
|
334
|
|