Fix M100 Free Memory Checker
M100 had numerious changes and quit working. Part of the problem is the overloading of the SERIAL_PROTOCOL functions. Also, some of the address arithmatic was changed to use char *ptr and passing ptr into the SERIAL_PROTOCOL functions caused them to try to print a string instead of a number. M100 is working again. Let's keep it that way! M100 has been expanded to now have a function int free_memory_is_corrupted() that can be called from other code to see if the free space is still contiguous. It may make sense to add a flag to control its verbose nature but right now, the extra chit chat is very helpful to know int free_memory_is_corrupted() is doing the right thing and what it found at various points when it was called. A 'Show & Tell' is coming up with int free_memory_is_corrupted().
This commit is contained in:
parent
3b82db5fe9
commit
ba85faabc0
|
@ -55,7 +55,8 @@ extern char __bss_end;
|
||||||
|
|
||||||
char* top_of_stack();
|
char* top_of_stack();
|
||||||
int how_many_E5s_are_here(char*);
|
int how_many_E5s_are_here(char*);
|
||||||
|
int free_memory_is_corrupted(); // int not bool!!!! it will tell us how many blocks of
|
||||||
|
// free memory it found.
|
||||||
void gcode_M100() {
|
void gcode_M100() {
|
||||||
static bool m100_not_initialized = true;
|
static bool m100_not_initialized = true;
|
||||||
char* sp, *ptr;
|
char* sp, *ptr;
|
||||||
|
@ -69,18 +70,26 @@ void gcode_M100() {
|
||||||
// probably caused by bad pointers. Any unexpected values will be flagged in
|
// probably caused by bad pointers. Any unexpected values will be flagged in
|
||||||
// the right hand column to help spotting them.
|
// the right hand column to help spotting them.
|
||||||
//
|
//
|
||||||
|
SERIAL_ECHOPAIR("\n__brkval : 0x", hex_word((uint16_t)__brkval) );
|
||||||
|
SERIAL_ECHOPAIR("\n__bss_end : 0x", hex_word((uint16_t)&__bss_end));
|
||||||
|
//
|
||||||
|
// With out malloc() we need to be smart and use &__bss_end
|
||||||
|
//
|
||||||
|
ptr = __brkval ? __brkval : &__bss_end;
|
||||||
|
SERIAL_ECHOPAIR("\nstart of free space : 0x", hex_word((uint16_t)ptr));
|
||||||
|
|
||||||
|
sp = top_of_stack();
|
||||||
|
SERIAL_ECHOLNPAIR("\nStack Pointer : 0x", hex_word((uint16_t)sp));
|
||||||
|
|
||||||
#if ENABLED(M100_FREE_MEMORY_DUMPER) // Disable to remove Dump sub-command
|
#if ENABLED(M100_FREE_MEMORY_DUMPER) // Disable to remove Dump sub-command
|
||||||
if (code_seen('D')) {
|
if (code_seen('D')) {
|
||||||
ptr = __brkval ? __brkval : &__bss_end;
|
|
||||||
//
|
//
|
||||||
// We want to start and end the dump on a nice 16 byte boundry even though
|
// We want to start and end the dump on a nice 16 byte boundry even though
|
||||||
// the values we are using are not 16 byte aligned.
|
// the values we are using are not 16 byte aligned.
|
||||||
//
|
//
|
||||||
SERIAL_ECHOPAIR("\nbss_end : 0x", hex_word((uint16_t)ptr));
|
ptr = (char*) ((uint16_t) ptr & 0xfff0);
|
||||||
ptr = (char*)((uint32_t)ptr & 0xfff0);
|
sp = (char*) ((uint16_t) sp | 0x000f);
|
||||||
sp = top_of_stack();
|
|
||||||
SERIAL_ECHOLNPAIR("\nStack Pointer : 0x", hex_word((uint16_t)sp));
|
|
||||||
sp = (char*)((uint32_t)sp | 0x000f);
|
|
||||||
n = sp - ptr;
|
n = sp - ptr;
|
||||||
//
|
//
|
||||||
// This is the main loop of the Dump command.
|
// This is the main loop of the Dump command.
|
||||||
|
@ -89,6 +98,8 @@ void gcode_M100() {
|
||||||
print_hex_word((uint16_t)ptr); // Print the address
|
print_hex_word((uint16_t)ptr); // Print the address
|
||||||
SERIAL_CHAR(':');
|
SERIAL_CHAR(':');
|
||||||
for (i = 0; i < 16; i++) { // and 16 data bytes
|
for (i = 0; i < 16; i++) { // and 16 data bytes
|
||||||
|
if (i==8)
|
||||||
|
SERIAL_CHAR('-');
|
||||||
print_hex_byte(*(ptr + i));
|
print_hex_byte(*(ptr + i));
|
||||||
SERIAL_CHAR(' ');
|
SERIAL_CHAR(' ');
|
||||||
}
|
}
|
||||||
|
@ -97,6 +108,7 @@ void gcode_M100() {
|
||||||
SERIAL_CHAR((*(ptr + i) == (char)0xe5) ? ' ' : '?');
|
SERIAL_CHAR((*(ptr + i) == (char)0xe5) ? ' ' : '?');
|
||||||
SERIAL_EOL;
|
SERIAL_EOL;
|
||||||
ptr += 16;
|
ptr += 16;
|
||||||
|
idle();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -106,11 +118,8 @@ void gcode_M100() {
|
||||||
// other vital statistics that define the memory pool.
|
// other vital statistics that define the memory pool.
|
||||||
//
|
//
|
||||||
if (code_seen('F')) {
|
if (code_seen('F')) {
|
||||||
#if 0
|
int max_cnt = -1, block_cnt = 0;
|
||||||
int max_addr = (int) __brkval ? __brkval : &__bss_end;
|
uint16_t max_addr=0;
|
||||||
int max_cnt = 0;
|
|
||||||
#endif
|
|
||||||
int block_cnt = 0;
|
|
||||||
ptr = __brkval ? __brkval : &__bss_end;
|
ptr = __brkval ? __brkval : &__bss_end;
|
||||||
sp = top_of_stack();
|
sp = top_of_stack();
|
||||||
n = sp - ptr;
|
n = sp - ptr;
|
||||||
|
@ -121,19 +130,21 @@ void gcode_M100() {
|
||||||
if (j > 8) {
|
if (j > 8) {
|
||||||
SERIAL_ECHOPAIR("Found ", j);
|
SERIAL_ECHOPAIR("Found ", j);
|
||||||
SERIAL_ECHOLNPAIR(" bytes free at 0x", hex_word((uint16_t)(ptr + i)));
|
SERIAL_ECHOLNPAIR(" bytes free at 0x", hex_word((uint16_t)(ptr + i)));
|
||||||
|
if (j > max_cnt) {
|
||||||
|
max_cnt = j;
|
||||||
|
max_addr = (uint16_t) ptr + i;
|
||||||
|
}
|
||||||
i += j;
|
i += j;
|
||||||
block_cnt++;
|
block_cnt++;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
if (j > max_cnt) { // We don't do anything with this information yet
|
|
||||||
max_cnt = j; // but we do know where the biggest free memory block is.
|
|
||||||
max_addr = (int) ptr + i;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (block_cnt > 1)
|
if (block_cnt > 1) {
|
||||||
SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area.");
|
SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area.");
|
||||||
|
SERIAL_ECHOPAIR("\nLargest free block is ", max_cnt);
|
||||||
|
SERIAL_ECHOLNPAIR(" bytes big at 0x", hex_word(max_addr));
|
||||||
|
}
|
||||||
|
SERIAL_ECHOLNPAIR("free_memory_is_corrupted() = ", free_memory_is_corrupted());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
@ -144,13 +155,9 @@ void gcode_M100() {
|
||||||
if (code_seen('C')) {
|
if (code_seen('C')) {
|
||||||
int x = code_value_int(); // x gets the # of locations to corrupt within the memory pool
|
int x = code_value_int(); // x gets the # of locations to corrupt within the memory pool
|
||||||
SERIAL_ECHOLNPGM("Corrupting free memory block.\n");
|
SERIAL_ECHOLNPGM("Corrupting free memory block.\n");
|
||||||
ptr = __brkval ? __brkval : &__bss_end;
|
|
||||||
SERIAL_ECHOPAIR("\nbss_end : ", ptr);
|
|
||||||
ptr += 8;
|
ptr += 8;
|
||||||
sp = top_of_stack();
|
sp = top_of_stack();
|
||||||
SERIAL_ECHOPAIR("\nStack Pointer : ", sp);
|
n = sp - ptr - 250; // -250 just to keep us from finding interrupt activity that
|
||||||
SERIAL_ECHOLNPGM("\n");
|
|
||||||
n = sp - ptr - 64; // -64 just to keep us from finding interrupt activity that
|
|
||||||
// has altered the stack.
|
// has altered the stack.
|
||||||
j = n / (x + 1);
|
j = n / (x + 1);
|
||||||
for (i = 1; i <= x; i++) {
|
for (i = 1; i <= x; i++) {
|
||||||
|
@ -167,13 +174,11 @@ void gcode_M100() {
|
||||||
//
|
//
|
||||||
if (m100_not_initialized || code_seen('I')) { // If no sub-command is specified, the first time
|
if (m100_not_initialized || code_seen('I')) { // If no sub-command is specified, the first time
|
||||||
SERIAL_ECHOLNPGM("Initializing free memory block.\n"); // this happens, it will Initialize.
|
SERIAL_ECHOLNPGM("Initializing free memory block.\n"); // this happens, it will Initialize.
|
||||||
ptr = __brkval ? __brkval : &__bss_end; // Repeated M100 with no sub-command will not destroy the
|
// Repeated M100 with no sub-command will not destroy the
|
||||||
SERIAL_ECHOPAIR("\nbss_end : ", ptr); // state of the initialized free memory pool.
|
// state of the initialized free memory pool.
|
||||||
ptr += 8;
|
ptr += 8;
|
||||||
sp = top_of_stack();
|
|
||||||
SERIAL_ECHOPAIR("\nStack Pointer : ", sp);
|
|
||||||
SERIAL_ECHOLNPGM("\n");
|
SERIAL_ECHOLNPGM("\n");
|
||||||
n = sp - ptr - 64; // -64 just to keep us from finding interrupt activity that
|
n = sp - ptr - 250; // -250 just to keep us from finding interrupt activity that
|
||||||
// has altered the stack.
|
// has altered the stack.
|
||||||
SERIAL_ECHO(n);
|
SERIAL_ECHO(n);
|
||||||
SERIAL_ECHOLNPGM(" bytes of memory initialized.\n");
|
SERIAL_ECHOLNPGM(" bytes of memory initialized.\n");
|
||||||
|
@ -181,8 +186,8 @@ void gcode_M100() {
|
||||||
*(ptr + i) = (char)0xe5;
|
*(ptr + i) = (char)0xe5;
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
if (*(ptr + i) != (char)0xe5) {
|
if (*(ptr + i) != (char)0xe5) {
|
||||||
SERIAL_ECHOPAIR("? address : ", ptr + i);
|
SERIAL_ECHOPAIR("? address : ", hex_word(ptr+i) );
|
||||||
SERIAL_ECHOPAIR("=", *(ptr + i));
|
SERIAL_ECHOPAIR("=", hex_byte(*(ptr + i)) );
|
||||||
SERIAL_ECHOLNPGM("\n");
|
SERIAL_ECHOLNPGM("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,5 +217,36 @@ int how_many_E5s_are_here(char* p) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int free_memory_is_corrupted() {
|
||||||
|
char *sp, *ptr;
|
||||||
|
int block_cnt = 0, i, j, n;
|
||||||
|
|
||||||
|
ptr = __brkval ? __brkval : &__bss_end;
|
||||||
|
sp = top_of_stack();
|
||||||
|
|
||||||
|
n = sp - ptr;
|
||||||
|
|
||||||
|
// Scan through the range looking for the biggest block of 0xE5's we can find
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (*(ptr + i) == (char)0xe5) {
|
||||||
|
j = how_many_E5s_are_here(ptr + i);
|
||||||
|
if (j > 8) {
|
||||||
|
// SERIAL_ECHOPAIR("Found ", j);
|
||||||
|
// SERIAL_ECHOLNPAIR(" bytes free at 0x", hex_word((uint16_t)(ptr + i)));
|
||||||
|
|
||||||
|
i += j;
|
||||||
|
block_cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (block_cnt > 1) {
|
||||||
|
// SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area.");
|
||||||
|
// SERIAL_ECHOLNPAIR("\nLargest free block is ", max_cnt);
|
||||||
|
// }
|
||||||
|
return block_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue