Just when I sorted out the multiplication problem (buggy avr-gcc version), I'm stumped by another problem in the software or hardware...
When I implement a simple data repeater at the start of my project, it works fine. However, if I add a single Serial.println line before the repeater, the data gets corrupted. The data I'm sending using a terminal program is simple ASCII data, but it gets very soon corrupted with binary portions interspersed.
It probably has something to do with the size of the project, as if I implement the exact same without the rest project, it works fine. The control never leaves the loop, so it cannot have any direct affect.
The project compiles to about 8-9kB and consists of several files and header files. I'm using an iDuino with an ATmega168 via the USB connection at 9600bps (but varying the speed has not fixed the problem). The compiler avr-gcc 4.3.2 and avr-libc 1.6.2.cvs20080610 on XUbuntu Intrepid.
Any suggestions as to the cause of the problems would be highly appreciated. Thanks.
void setup() {
Serial.begin(9600);
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
Serial.println("DEBUG Starting setup"); // With this line the data is corrupted
while (true) {
int c = Serial.read();
if (c < 0) {
delay(100);
} else {
Serial.print(c,BYTE);
}
}
// Rest of the code...
Could the rest of your sketch be using up all of the 1024 bytes of RAM? If that happens then the overflow will spill over and do very bad things. This becomes the most likely case when you can remove code that isn't currently running and suddenly the sketch runs properly.
What memory section do literal strings within the code go to? I have quite a lot of communication messages and debugging in the program (sendline("SETSERVO %hd\n", angle), debug("DEBUG Read: ...") etc., implemented using vsnprintf, a fixed-size buffer and Serial.print). These strings are not modified by any part of the program, so they could be stored in the code section, but if they are not they might be filling up the memory.
Other that that, I can't imagine the code taking up more than around 300 bytes of RAM (including the message buffer and all global variables).
I'm not using any memory-reserving functions, so couldn't the compiler warn if the RAM is filling up with variables?
I think AdderD is probably on to something. Even constant strings are stored in RAM. It is VERY easy to experience and overflow and flaky behavior when you have a bunch of strings like that.
I counted the length of the strings and with the other variables they add up very close to 1kB, so I guess this is the problem.
The avr-libc page on data storage gives an example of storing and retrieving an array of strings in program memory (avr-libc: Data in Program Space), but could somebody please give an example of storing and retrieving just one string? I couldn't quite deduce that from the page, and having an array of the pointers stored in program space seems a bit overkill for my needs.
A few suggestions though: Why doesn't avr-gcc warn when the RAM is filling up? All of the space used is defined at compile-time (except if Serial.begin allocates space), so couldn't the compiler warn when, say, 90% of the available RAM is used? Also, couldn't the compiler automatically store long literal strings in program memory and generate code to retrieve them onto the stack when necessary? (This is a space/speed trade-off that might not be desired in all cases, but the option of doing so could ease programming a lot.)
Thanks for the help. After removing the debugging text and shrinking a read buffer from 200 to 100 bytes the problems have disappeared. I was quite surprised that removing just the strings was not enough, and even with them avr-gcc didn't complain or warn anything about memory potentially running out.
The page you linked to is effectively the same that I posted, but I figured out how to store only one string:
prog_char mystring[] PROGMEM = "My string!";
...
strcpy_P(buffer, mystring);
Thanks again for the help, after a bit of further debugging the software now is functioning as desired.
Why doesn't avr-gcc warn when the RAM is filling up?
The most the compiler could do is warn how much static memory (heap) is being used.
A significant part of RAM utilization is determined at runtime, and it is frequently dependent on the actual input data, so it can change between program executions. The compiler has no way of knowing what data you will feed the program, and only the vaguest guess at how functions will be called. Automatic variables and saved registers consume RAM on the stack when functions are called. Functions don't get called at compile time, they get called at runtime.
You can also add a linker switch to produce the map file.
In my makefile I have this switch for gcc --
Can you tell me where the Makefile is located to add this to? There are several under C:\Program Files\Arduino... on my drive & it's not obvious which one GCC will pick up and use? :o
My modified Makefile is for a project that I do without the Arduino tools. I just
use avr-gcc. Also I am on a linux box and I do not install using the default paths.