Anyone who has written a sketch beyond blinking a LED, has likely encountered the problem of running out of SRam.
There is alot written about storing strings into FLASH, but not a lot about other variables and the best way to optimize their use of SRam.
Consider the following statement:
if (i == 5){ ....
I was really confused about how the 5 was stored... in SRam or Flash
Also, consider
const int i = 5;
SRam or Flash?
Below is an experiment that I used to help answer some of these questions.
[font=Verdana]
#include <SPI.h>
#define DZ 5
bool first = true;
// Step 1 : Execute the sketch as-is with everything commented
// int a = 5; // Step 2 : Uncomment here and Step2 below
// int z = 5; // Step 3 : Uncomment (Also below)
// const int z = 5; // Step 4 : Comment Step3 and Uncomment this
void setup(){
Serial.begin(9600);
delay(1500);
Serial.println (F(""));
Serial.println (F("SRam test..."));
Serial.print (F("Beginning SRAM = "));
Serial.println (freeRam());
// const int z = 5; // Step 5: comment Step4 and uncomment this
// const int z = 4; // step 8: Comment Step5 and uncomment this
// int z = 5; // Step 9: Comment Step8 and uncomment this
// if (a == z) Serial.println (F("A = Z")); // Step 3: Uncomment and leave it uncommented until Step6
// if (a == DZ) Serial.println (F("A = Z")); // Step 6: Comment Step3 above and uncomment this
// if (a == z){ // Step 7: Comment Step6, Step2 below and Uncomment the block below
// Serial.println (F("A = Z"));
// int i = 5;
// a = i;
// }
// a = 0; // Step 2: Uncomment here.. This is here to ensure int a is not optimized out of the compile
Serial.print (F("Ending SRAM = "));
Serial.println (freeRam());
}
void loop(){
if (first){
Serial.print (F("Loop SRAM = "));
Serial.println (freeRam());
first = false;
}
}
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
[/font]
Here are my results:
| Step -- | Flash -- | SRam -- | Desc -- |
|---|---|---|---|
| 1 | 2858 | 1901 | No Variables Declared |
| 2 | 2868 | 1899 | int a Declared Globally |
| 3 | 2910 | 1897 | int z Declared Globally |
| 4 | 2898 | 1899 | const int z Declared Globally |
| 5 | 2898 | 1899 | const int z Declared Locally |
| 6 | 2898 | 1899 | #define is used in if statement |
| 7 | 2908 | 1897 | int i Declared Local and Conditionally |
| 8 | 2838 | 1899 | int i not Declared Conditionally |
| 9 | 2928 | 1897 | int z Declared Locally and int i Declared Conditionally |
Many of the steps are obvious and the results are expected. However, there are a couple that have me a bit puzzled.
Not so obvious (at least to me) results:
- using "#define" and "const int" are equivalent (Step 4 and Step 6)
- declarations inside a conditional block are only declared if the condition is true (Step 7 and Step 8)
- declaring a "const int" requires 12 fewer bytes in Flash than declaring "int" (Step 3 and Step 4)
Here are my questions:
-
Look at Step 9. Variable z is declared locally as a regular int and assigned a value that will satisfy the conditional to declare variable i as an int. However, there are only 4 bytes consumed from SRam. I was expecting that 6 bytes be consumed (2 bytes each for variables a, i, z). Why only 4?
-
Consider Step 7. Both calls to the FreeRam routine in Setup() returned 1897 bytes free. I would have expected the FreeRam call at the beginning of Setup() to return 1899 and the last FreeRam call to return 1897. How did the first FreeRam routine know it was going to need the Ram space before the conditional was evaluated? Perhaps, is z going out of scope (and then freed) since it isn't used any more in the routine?
Thanks.