EmbeddedRelated.com
Forums

IAR for MSP430F2013 and subroutines with more than 4 arguments

Started by jappelino March 17, 2009
I had a subroutine with six arguments of type unsigned char.

The two last ones were put on the stack and the first four in registers by the IAR C compiler.

When the routine returned the stack was not corrected and I ended up in a stack overflow.

I temporarely solved this by using two global variables, is there any box under options I need to tick to get this to work the normal way?

Beginning Microcontrollers with the MSP430

I am curious about something:
Does a "single" call overflow the stack or several subsequent calls?

The IAR compiler does a speed optimization when sequential calls to the same function are made. It doesn't pop old parameters off of the stack until all the calls are made, and then it does one big explosive "pop". (At least that's how I interpretted it.)

There was another thread about this some time ago.

There is a compiler switch somewhere to change this setting.

Stuart
--- In m..., "jappelino" wrote:
>
> I had a subroutine with six arguments of type unsigned char.
>
> The two last ones were put on the stack and the first four in registers by the IAR C compiler.
>
> When the routine returned the stack was not corrected and I ended up in a stack overflow.
>
> I temporarely solved this by using two global variables, is there any box under options I need to tick to get this to work the normal way?
>

That sounds strange. Any C compiler should handle this properly. Is your
debug set up properly ?

One thing you might want to consider if you're concerned with code
size/execution :
If you don't need bytes per se, consider passing shorts to your function
(16 bits). Else the compiled code will faithfully work with 8 bit unsigned
chars and is therefore obliged to constantly mask off the upper byte of the
registers, in case there is a carry or a mod 256 operation result. This
will yield unnecessary code increase, and you can't blame the compiler for
it.

B rgds
Kris

On Tue, 17 Mar 2009 06:53:08 -0000, "jappelino"
wrote:
> I had a subroutine with six arguments of type unsigned char.
>
> The two last ones were put on the stack and the first four in registers
by
> the IAR C compiler.
>
> When the routine returned the stack was not corrected and I ended up in a
> stack overflow.
>
> I temporarely solved this by using two global variables, is there any box
> under options I need to tick to get this to work the normal way?
>
You are rigth I found this:
Yes, that is an optimization, where we generate somewhat smaller and
faster code at the expense of stack space. Of course, this waste of
stack space doesn't continue forever, when the stack has grown over a
certain threshold we clean the stack. For the applications where this is
not enought there is a command line option, --reduce_stack_usage, that
ensures that the stack doesn't grow in this manner, at the expense of
more code.

Hope this helps!

-- Anders Lindgren

I guess I have to use the command or find another solution.

jappelino wrote:
> I had a subroutine with six arguments of type unsigned char.
>
> The two last ones were put on the stack and the first four in registers
> by the IAR C compiler.
>
> When the routine returned the stack was not corrected and I ended up in
> a stack overflow.
>
> I temporarely solved this by using two global variables, is there any
> box under options I need to tick to get this to work the normal way?
>

Passing this many arguments to a routine usually indicates that you should put
them in a structure and pass a structure pointer to the routine.

Best regards,

Greg
jappelino wrote:
> I had a subroutine with six arguments of type unsigned char.
>
> The two last ones were put on the stack and the first four in registers
> by the IAR C compiler.
>
> When the routine returned the stack was not corrected and I ended up in
> a stack overflow.

Could you explain what happened and what you expected to happen.

The basic idea is that when the function returns, the stack pointer
should be the same as when it was called. It is the responsibility of
the caller to remove the parameter that it has pushed on the stack.

-- Anders Lindgren, IAR Systems
--
Disclaimer: Opinions expressed in this posting are strictly my own and
not necessarily those of my employer.

What happened was that the caller did not remove what was pushed on to the stack.

This is from what I understand a part of your optimization if a subroutine is called several times in a row.
Only in this case the stack grow into an area with parameters which I still wanted to use (outside defined stack area).

--- In m..., Anders Lindgren wrote:
>
> jappelino wrote:
> > I had a subroutine with six arguments of type unsigned char.
> >
> > The two last ones were put on the stack and the first four in registers
> > by the IAR C compiler.
> >
> > When the routine returned the stack was not corrected and I ended up in
> > a stack overflow.
>
> Could you explain what happened and what you expected to happen.
>
> The basic idea is that when the function returns, the stack pointer
> should be the same as when it was called. It is the responsibility of
> the caller to remove the parameter that it has pushed on the stack.
>
> -- Anders Lindgren, IAR Systems
> --
> Disclaimer: Opinions expressed in this posting are strictly my own and
> not necessarily those of my employer.
>

jappelino wrote:
> What happened was that the caller did not remove what was pushed on to
> the stack.
>
> This is from what I understand a part of your optimization if a
> subroutine is called several times in a row.
> Only in this case the stack grow into an area with parameters which I
> still wanted to use (outside defined stack area).

In what way did it grow into that area?

Did it stumble a few bytes into the neighboring area -- in that case
your stack is simply too small.

Or did it run amok and overwrite a large amount of data? In that case
something is seriously wrong.

In neither case, I don't think that it caused by our delayed stack
cleanup. Besides, it's easy to test, the command-line option
"--reduce_stack_usage" disables it. If your problem remains, the problem
must be elsewhere.

My money is still on an interrupt running amok...

-- Anders Lindgren, IAR Systems
--
Disclaimer: Opinions expressed in this posting are strictly my own and
not necessarily those of my employer.

it stumbled a few bytes into the neighboring area, but is it my responsibility to check this and not the compilers?

The stack was set to the normal 50 bytes, this is a small cpu with only 128 bytes of RAM.

I will try the "--reduce_stack_usage" way shortly.

--- In m..., Anders Lindgren wrote:
>
> jappelino wrote:
> > What happened was that the caller did not remove what was pushed on to
> > the stack.
> >
> > This is from what I understand a part of your optimization if a
> > subroutine is called several times in a row.
> > Only in this case the stack grow into an area with parameters which I
> > still wanted to use (outside defined stack area).
>
> In what way did it grow into that area?
>
> Did it stumble a few bytes into the neighboring area -- in that case
> your stack is simply too small.
>
> Or did it run amok and overwrite a large amount of data? In that case
> something is seriously wrong.
>
> In neither case, I don't think that it caused by our delayed stack
> cleanup. Besides, it's easy to test, the command-line option
> "--reduce_stack_usage" disables it. If your problem remains, the problem
> must be elsewhere.
>
> My money is still on an interrupt running amok...
>
> -- Anders Lindgren, IAR Systems
> --
> Disclaimer: Opinions expressed in this posting are strictly my own and
> not necessarily those of my employer.
>

2009/3/18 jappelino

> it stumbled a few bytes into the neighboring area, but is it my
> responsibility to check this and not the compilers?
>

I would say that it is your responsibility to check this. In the absence of
any recursive function calls or interrupts, the tools can make an attempt at
calculating the maximum stack usage. The only way, in real systems, to
check for stack usage problems is to run the code for a suitably long period
and see where the high water mark is. IAR 4.20 can do this. The problem
then comes as to how long is "suitably long".

Ian