I am facing a low memory available problem in arduino. I am compiling a big sketch for arduino mega 2560.
Analysing a .elf file, the avr-size tool gives:
text data bss dec hex filename
68524 4392 2560 75476 126d4 C:\Users\LEAN...
And the avr-nm (avr-nm doc) shows only variables with t, T, b, d and B. The following is how the command is executed (the output is being saved in a file called test.txt).
avr-nm -a -td -C -l --size-sort -r x.elf >> test.txt
Then, I perform a sum to confirm the avr-size result using this Python script:
f = open("test.txt", "r")
lines = f.readlines()
f.close()
su = 0
dsum = 0
bsum = 0
tsum = 0
gsum = 0
for line in lines:
#print(line, end="")
s = line.split()
try:
val = int(s[0])
su = su + val
if(s[1].lower() == 'b'):
bsum = bsum + val
if(s[1].lower() == 'd'):
print(line)
dsum = dsum + val
if(s[1].lower() == 't'):
tsum = tsum + val
if(s[1].lower() == 'g'):
gsum = gsum + val
except:
print("ERR: ",s[0])
print("\n\nSIZE: ", su)
print("SIZE d/D: ", dsum)
print("SIZE b/B: ", bsum)
print("SIZE t/T: ", tsum)
print("SIZE g/G: ", gsum)
and the sum result of each var type is:
SIZE: 71015
SIZE d/D: 135
SIZE b/B: 2560
SIZE t/T: 68320
SIZE g/G: 0
The question: Here d/D sums is 135 bytes. So, why the data segment reported by avr-size is 4392 bytes? how to find out what is occupying this space?
Best Regards.
EDIT
It must be a Joke!
I have a lot of like this in the code:
Serial.print("QTDE REG: ");
Just changing for this:
Serial.print(F("QTDE REG: "));
I have reduced by 10 the .data size!
So, in this way Serial.print("QTDE REG: ");
"QTDE REG: " is stored as a global variable?? I thought the compiler would save locally.
EDIT 2
I have an advance running avr-objdump -s -j .data x.elf
as suggested by Edgar below. Now I see that all my string literals are in data! For example:
void myFunction(){
...
sprintf(buf, "{\"name\":\"Intervalo de Registros\",\"value\":\"%d\", \"unit\":\"C\"},", (int)settings.treg);
...
}
avr-objdump -s -j .data x.elf
shows:
800660 2c007b22 6e616d65 223a2249 6e746572 ,.{"name":"Inter
800670 76616c6f 20646520 52656769 7374726f valo de Registro
800680 73222c22 76616c75 65223a22 2564222c s","value":"%d",
800690 2022756e 6974223a 2243227d 2c007b22 "unit":"C"},.{"
EDIT 3
As commented, all string literals are saved in the (SRAM). So, the problem is, I have a lot of strings literals spread across different functions. How to save this amount of SRAM? Note that using F() for sprintf gives compilation error.
Is there any way to put the literal in stack (release memory when function returns) and not in the global area? Is F() the only solution?
============ SOLUTION ============
For now, I have found this solution: use sprintf_P
with PSTR(...)
in the same way of F(...)
:
sprintf_P(buf, PSTR("{\"name\":\"Intervalo de Registros\",\"value\":\"%d\", \"unit\":\"C\"},"), (int)settings.treg);
I will test more...
Thanks for all clarification!
Best Regards!