It does not make since to me but adding a simple case greatly increased the SRAM usage.
I am using the IRLIB2 in an effort to decode as many different IR remotes as possible. I am decoding the IR signal and then sending text to the serial port indicating the value decoded. I am using a large switch to translate the decoded value to the text.
The problem is that adding cases increased SRAM usage for no know reason. The code is currently several hundred lines in length. I also combine several statement on a line. It is a lot of code.
Here is a segment of the code
When I compile it get:
Sketch uses 17080 bytes (52%) of program storage space. Maximum is 32256 bytes.
Global variables use 1574 bytes (76%) of dynamic memory, leaving 474 bytes for local variables. Maximum is 2048 bytes.
When I compile it get:
Sketch uses 17092 bytes (52%) of program storage space. Maximum is 32256 bytes.
Global variables use 1574 bytes (76%) of dynamic memory, leaving 474 bytes for local variables. Maximum is 2048 bytes.
Adding a "case" made a sketch size increase by 12 bytes (reasonable) and no change in the "Global variable" use (expected).
When I compile it get:
Sketch uses 17072 bytes (52%) of program storage space. Maximum is 32256 bytes.
Global variables use 2082 bytes (101%) of dynamic memory, leaving -34 bytes for local variables. Maximum is 2048 bytes.
Adding another "case" made a sketch size decrease by 20 bytes (unexpected) and increase in the "Global variable" use by 508 bytes (VERY unexpected).
Ah, didn't see them when I was viewing on the phone.
As mentioned, compiler does some optimizing, possibly things were getting cut out when smaller to make you think the smaller was your default prog size.
Delta_G:
What's in those extern arrays? You know if you don't use one it doesn't get linked in. So if you add a case that suddenly uses one that wasn't previously referenced then your code should grow by the size of the array.
The complete variable definition is in the code block. The arrays are single character strings.
INTP:
Ah, didn't see them when I was viewing on the phone.
As mentioned, compiler does some optimizing, possibly things were getting cut out when smaller to make you think the smaller was your default prog size.
Program size does not seem to be the problem. The problem is RAM (Global Variable) usage. Code is added that uses no new variables and usage jumps (a lot).
Do you know why this would cause the observed behavior?
Delta_G:
Aha. The odd formatting caused me not to see the initializations. What's the purpose of an array if it only has one element? Something seems fishy between that and them being extern.
This is just part of the code. Other definitions hold strings like "Power", "Channel Up" and "Input".
Is there something about short strings using more RAM than long strings?
Is there something about short strings using more RAM than long strings?
A string uses one byte per character, regardless of the length of the string.
A String, on the other hand, wastes proportionately more space for short strings than for long strings. The key is "proportionately". A String wastes the same amount of memory for every String in addition to what is required to hold the string.
PaulS:
A string uses one byte per character, regardless of the length of the string.
A String, on the other hand, wastes proportionately more space for short strings than for long strings. The key is "proportionately". A String wastes the same amount of memory for every String in addition to what is required to hold the string.
It was not by accident that I indicate that it was a "string" and not a "String". Also the definition is clearly a character array and not a String object.
Not to split hairs, but a string also includes a NULL terminator. Therefore, the string "1" is a 2 byte character array.
This is all interesting. But does not explain what is happening.
RandallR:
Do you know why this would cause the observed behavior?
I think I do. When you go from two entries to three it sees that you are setting the same pointer to different addresses based on the value of a byte. I suspect it is creating a table of 256 addresses and just indexes into the table. That would add 512 bytes but saves a few over the previous incarnation for the net gain is 508.
Try changing the 0xFF to 0x07. That should allow the compiler to generate an 8-entry table (16 bytes) instead of a 256-entry table.
johnwasser:
I think I do. When you go from two entries to three it sees that you are setting the same pointer to different addresses based on the value of a byte. I suspect it is creating a table of 256 addresses and just indexes into the table. That would add 512 bytes but saves a few over the previous incarnation for the net gain is 508.
Try changing the 0xFF to 0x07. That should allow the compiler to generate an 8-entry table (16 bytes) instead of a 256-entry table.
Exactly the same results.
This is some what comforting. Since a switch could have hundreds of cases. To build the jump table in RAM would eat a lot of memory.
You need to either make the whole sketch available, or duplicate the memory usage situation in a smaller sketch (one that actually compiles, and demonstrates the problem.) (or, you could publish the .elf file, I guess, if you feel the source is sensitive.)
This is a problem that ought to be analyzable by poking at the object files with tools like avr-nm and avr-objdump, but ... I'd need to have the object files... (source code, however big, is probably smaller than two .elf files )
Which section? I tried to change the below part as shown
#ifdef IRLIB_PROTOCOL_13_H
if (My_Decoder.protocolNum == RQ) {
switch (My_Decoder.value) {
case 0B00000001: F_Cmd = F_Mode; break;
case 0B00000011: F_Cmd = F_Menu; break;
case 0B00000101: F_Cmd = F_Stop; break;
case 0B00000100: F_Cmd = F_Power; break;
#if 0
And it does not make a difference. Arduino Uno, IDE 1.6.6
Sketch uses 17,802 bytes (55%) of program storage space. Maximum is 32,256 bytes.
Global variables use 1,034 bytes (50%) of dynamic memory, leaving 1,014 bytes for local variables. Maximum is 2,048 bytes.
avr-nm -SC --size-sort *.elf | grep " [dDbB] "
:
00800726 0000002f B My_Decoder
0080044a 00000050 d VTT for IRdecode
008003c8 00000082 d vtable for IRdecode
008004a6 000000c8 b IRBuffer
0080064b 000000db B recvGlobal
0080056e 000000dd B Serial
[color=red]00800104 000001f2 d CSWTCH.234[/color]
So, yeah. It looks like for certain case statements, avr-gcc will put a big jump table in RAM.
Appears to be a longstanding avr-gcc bug that they've given up trying to fix https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49857
I suggest constructing your own table in pgmspace, and searching it in a loop. You can make the search relatively fancy if you need speed (but you probably don't.)