At the moment we are using C51 + a realtime CMX kernel. We are evaluating the ARM platform and are looking how this new platform reacts to parts our existing (little modified) programs in therms of code size and speed. We modified a little existing CMX program to transmit a string.
With our first atempt we already run into trouble.
Problem is unknown amount of stack for sprintf with vars without warning. Next example has 3 parts. 1st part runs fine. 2nd part seems to run fine (but at the moment it looks like it corrupts the stack) 3nd part crashes as soon as os_tsk_self(); is called from within SendBlockTimed(,,) crash result => os_error (with err_code=1) How can this happen (al vars are int)?
for (Counter = 0; Counter <250; Counter++) { NumChars = sprintf(ConsoleBuffer, "Console. 00000"); if (NumChars == 14) { OK_Count++; SendBlockTimed(ConsoleBuffer, strlen(ConsoleBuffer), CONSOLE_SEND_TIMEOUT); } else { Error_Count++; } } for (Counter = 0; Counter <250; Counter++) { NumChars = sprintf(ConsoleBuffer, "Console. %05u",Counter); if (NumChars == 14) { OK_Count++; } else { Error_Count++; } } for (Counter = 0; Counter <250; Counter++) { NumChars = sprintf(ConsoleBuffer, "Console. %05u",Counter); if (NumChars == 14) { OK_Count++; SendBlockTimed(ConsoleBuffer, strlen(ConsoleBuffer), CONSOLE_SEND_TIMEOUT); } else { Error_Count++; } }
.
You have selected ARM as architecture, but C51 in your text. So what is it?
The first sprintf() doesn't do any parameter expansion - it just copies data.
The second two sprintf() needs to call one or more internal functions to convert an integer to string format, when processing the %5u parameter. This should be an obvious reason why these calls requires more stack space.
Stack overflow is seldom a problem, until you need the contents that gets overwritten. This means that you don't get an obligatory failure after a stack overflow - you may be able to continue to a different part of your application before the failure.
That is why you, as developer, must always make sure your stack is big enough. You may attempt to catch the maximum stack size needed by using analysis reports from the compiler. But they don't help for recursive functions and some RTL functions don't have known, fixed requirements either.
And depending on processor, interrupts will add their needs on top of the normal stack requirements. And while testing, it's very hard to get the worst interrupts conditions while being at the part of the execution tree where you already needed max stack.
When an exact answer can't be found, you may have to try different parameter ranges etc to try to get a rough guestimate for the unknown parts of the code. Then add a bit of safety margin, and finally add stack testing code that catches stack overflows - for example if magic markers have been overwritten.
Remember that a compiler/linker can help, but in the end, it's a task for the developer to decide on used stack size.
He said they are currently using C51, but looking to move to ARM.
As I read it, the question relates to some code that has been "ported" to ARM...
The danger of writing the answer an hour after having read the original post.
All is clear after reading the reply of Per Westermark
One way or another i mixed two things up (allocating memory an stack usage). I thougth the sprintf() routine allocated memory and corrupted stack and memory beacause of that and didn't free up all memory on exit, making the next part of the program crash.
But the answer is very simple it's stack usage and a stack must always be large enough. This was the same on a 8051 platform and will be the same on an ARM platform We did all the calculation and testing for routines on the 8051 and "just" forgot and didn't think about it on the ARM.
Now we can continue to evaluate the controller with development platform.