I'll answer some of your questions in this post (partly as an aide-memoire for me!) and will get around to updating the tutorial as soon as I can. But it will save you having to re-read the tutorial to try to spot the answers.
Is there a way to store more stuff in ROM to save more RAM, or vice-versa?
The biggest candidate is any string constants. So for example if you keep logging with something like:
rprintf("Sonar distance=%d\n",sonarValue)
Then the string "Sonar distance=%d\n" never changes so you can use some macros to store the string in Flash (Program memory) rather than in RAM which is where it will go by default. So your program is bigger but needs less RAM at runtime. Will give a fuller explanation in the tutorial.
Why aren't recursive functions allowed on an mcu - is it just a RAM limitation?
The problem is that the Stack must be stored in RAM and an mcu doesn't have much. Each level of recursion will need more memory for the stack. However: recursion is allowed - but you just have to keep it small. So for example: this should print the numbers one to ten:-
void one2ten(int num){
rprintf("Num=%d",num);
if(num <= 10){
one2ten(num+1);
}
}
void main(){
one2ten(1);
}
If you don't know how many levels deep your recursion will go then you are in danger of running out of stack space and the code going beserk.
And how do recursive functions affect optimization?
They don't. The compiler just optimises individual methods and individual lines of code. The compiler may be completely unaware that any of your code is recursive.
Perhaps add a description of memory leaks?
Memory leaks are caused by dynamically allocating memory and then forgetting to release it once you have finished with it. The tutorial alrerady discusses how gcc only allows short lived dynamic memory allocation and automatically frees up the memory at the end of the method that allocated it. So, in theory, I can't think how it would be possible to have a memory leak with gcc.
How does optimizing code affects its readability for a programmer?
If you are optimising the code by using the compiler -O settings then your source code doesn't change - so readability is compromised. However: you can sometimes help the compiler when evaluating complex expressions. For example:-
double d = (x * sin(theta)) + (y * sin(theta))
Calculating sin(theta) is a time consuming operation and its done twice. Depending on the optimisation settings of your makefile, and the capability of the compiler, it 'may' notice that its done twice and reinterpret your equation as:
double d = (x + y) * sin(theta)
Alternatively you could change the source code yourself to hand optimise the equation. You may even store partial results within temporary variables so that they aren't recalculated. Obviously your decision to change the source code may mean that it is less legible - but this could be a necessary evil in the quest for better speed.
How many stacks an mcu has vs computers? 1 vs many, right?
mcus are normally run in a single threaded environment so there is only one stack. Whereas your computer may be running lots of programs at the same time and so each program needs its own stack. Luckily computers have a lot of RAM so this is possible. But an mcu has limited memory so it is more difficult. Multi-tasking environments do exist for mcus but normally require you to set a maximum stack size for each thread. So if you say use 100 bytes and you have 3 threads then it will allocate 300 bytes for the stacks. When it switches threads it will change the stack pointer to point to the 100 bytes that are solely used by that thread.
So if a variable is not initialized, its stored in a different location? gcc says it initializes all variables to 0 if the user doesn't assign value.
The unitialised variables in the BSS segment (immediately after the end of your initialised variables) are all zapped to zeroes just before your 'main' is called. This means that numeric variables are all set to zero and strings are of a zero length.
can you draw up a graphical diagram
Will do