I don't know aboutWith the code related to the __arm__ implementation aside, but for the code related to the AVR one, it is incompleteincomplete for handling the corner case when the program does not use the malloc() function. If your program never uses malloc(), the formula used in freeMemory() will produce the wrong result. A simple corrected version for AVR that I used is here:
extern unsigned int __heap_start;
extern char *__brkval;
int freeMemory() {
char top_of_stack;
if (__brkval == 0) {
Serial.println(((int)&top_of_stack - (int)&__heap_start));
} else {
Serial.println((int)&top_of_stack - (int)__brkval);
}
}
extern unsigned int __heap_start;
extern char *__brkval;
int freeMemory() {
char top_of_stack;
if (__brkval == 0) {
Serial.println(((int)&top_of_stack - (int)&__heap_start));
} else {
Serial.println((int)&top_of_stack - (int)__brkval);
}
}
#define PSTR(s) ((const PROGMEM char *)(s))
#define PSTR(s) ((const PROGMEM char *)(s))
It looks a little bit intimidating, but it is actually quite simple. It not only tells the avr-gcc that the string literal s should be kept in program memory (i.e., flash memory in the case of Arduino), but it allows the program to convert it into a const char *s PROGMEM variablepointer, so that it can be pass around into some PROGMEM-aware functions as a parameter.
// This is a PROGMEM-aware function in C
printMsg_P(const char* str) {
char buf[strlen_P(str)+1];
strcpy_P(buf, str);
puts(buf);
}
// This handles the normal string array function
printMsg(const char* str) {
puts(str);
}
// This is a PROGMEM-aware function in C
printMsg_P(const char* str) {
char buf[strlen_P(str)+1];
strcpy_P(buf, str);
puts(buf);
}
// This handles the normal string array function
printMsg(const char* str) {
puts(str);
}
class __FlashStringHelper;
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
class __FlashStringHelper;
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
This has to do with C++'s function overload. Function overload is a feature of C++ where multiple methods could have the same function name, but each with different parameters. Within all the Serial.print() methods, there is a method Serial.print(const char* str) that will take in a string literal and print it to serial monitor, but it is not PROGMEM-aware. If you pass in a PROGMEM string literal Serial.print(PSTR("string literal"));, the same overloaded method we just mentioned will accept what you pass in because it meet the type checking (remember PSTR is actually const char*), but it will not print out the correct string for PSTR("string literal"), because it simply expecting a normal string.
Serial.print(const __FlashStringHelper *ifsh)
Serial.print(const __FlashStringHelper *ifsh)
Serial.print((__FlashStringHelper*)PSTR("test"));
Serial.print((__FlashStringHelper*)PSTR("test"));
#define PGM_P const char *
#define PGM_P const char *
const char *const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};
const char *const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};
PGM_P const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};
PGM_P const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};