EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Inline functions in C (Crossworks)

Started by Miles Gazic August 31, 2004
I am using the Crossworks compiler, and there are a few places where
I'd 
like to call a function (to make the code easier to read and more 
modular), but would like to avoid the overhead of the function call.  In 
C++, Ada, or the latest C standard you can inline a function, but C 
didn't originally have that ability.

Is there a clean and easy way to inline a function in C?  I don't like 
making macros to replace functions more than a half a dozen lines long, 
since it gets rather messy.

Thanks,
Miles

PS: Yes, I know I can make it even faster if I write assembly.

Beginning Microcontrollers with the MSP430

Miles,

> I am using the Crossworks compiler, and there are
a few 
> places where I'd like to call a function (to make the code 
> easier to read and more modular), but would like to avoid the 
> overhead of the function call.  In 
> C++, Ada, or the latest C standard you can inline a function, but C
> didn't originally have that ability.
> 
> Is there a clean and easy way to inline a function in C?  I 
> don't like 
> making macros to replace functions more than a half a dozen 
> lines long, 
> since it gets rather messy.

CrossWorks doesn't yet support the inline qualifier.  We can accept it
and not generate inline code as we're permitted to do, but that's not
really in the spirit or expected behaviour.

From the compilers I've looked at for the MSP430, the inline
implementations are not ideal--they all generate sub-optimal code in
various cases, even simple cases.

At some point I will implement "inline", but don't expect it any
time
soon.

Right now, your best recourse is a C macro or use another macro
processor.  For large projects, I've used noweb and find it useful.

-- Paul.


Paul,

Thanks, I'll continue using macros.

Quick question, can I (when using a MSP430F149) set a conditional 
breakpoint on the SP register (to catch a stack overflow).  If so, 
what's the proper syntax?  Everything I've tried results in the
"?" 
indicating an invalid breakpoint.

Thanks again,
Miles

Paul Curtis wrote:

> Miles,
>
> > I am using the Crossworks compiler, and there are a few
> > places where I'd like to call a function (to make the code
> > easier to read and more modular), but would like to avoid the
> > overhead of the function call.  In
> > C++, Ada, or the latest C standard you can inline a function, but
C
> > didn't originally have that ability.
> >
> > Is there a clean and easy way to inline a function in C?  I
> > don't like
> > making macros to replace functions more than a half a dozen
> > lines long,
> > since it gets rather messy.
>
> CrossWorks doesn't yet support the inline qualifier.  We can accept it
> and not generate inline code as we're permitted to do, but that's
not
> really in the spirit or expected behaviour.
>
> >From the compilers I've looked at for the MSP430, the inline
> implementations are not ideal--they all generate sub-optimal code in
> various cases, even simple cases.
>
> At some point I will implement "inline", but don't expect it
any time
> soon.
>
> Right now, your best recourse is a C macro or use another macro
> processor.  For large projects, I've used noweb and find it useful.
>
> -- Paul.



Miles, 

> Thanks, I'll continue using macros.
> 
> Quick question, can I (when using a MSP430F149) set a 
> conditional breakpoint on the SP register (to catch a stack 
> overflow).  If so, what's the proper syntax?  Everything I've 
> tried results in the "?" 
> indicating an invalid breakpoint.

Unfortunately, the F149's EEM does not support register breakpoints--the
F169 does and is pin compatible, so we recommend you use F169s for
development even if you're deploying on F149s because of the extra
goodies you get.

Regards,

-- Paul.

Paul,

I've got another question for you.  My MSP430F149 has (AFAIK) 2k of 
RAM.  However, when I look at the "Sections" in Symbol Browser, it
shows 
the range of UDATA0 as 242-5ef, and the size as 942, and it shows the 
range of IDATA0 as 200-241, and size as 66.  That's a total of 1008 
bytes, or about half of what I expected it to be.  Heap size is set to 
0, and the only sections I have are CODE, CONST, UDATA0, IDATA0, 
INTVEC.  Is there something else that uses RAM?

Do I need to modify the memory map, or will the choice of proper 
processor type in the project be sufficient to allocate all the ram?  I 
looked at the project configuration, and the xml files used are 
msp430f149.xml and section_placement.xml.  Neither one appears to set 
the sections sizes, that I can see.  The ram size is set to 0x800 in 
msp430f149.xml, so I assume it auto-allocates the sections into that 
somehow?

Thanks,
Miles

Paul Curtis wrote:

> Miles,
>
> > I am using the Crossworks compiler, and there are a few
> > places where I'd like to call a function (to make the code
> > easier to read and more modular), but would like to avoid the
> > overhead of the function call.  In
> > C++, Ada, or the latest C standard you can inline a function, but
C
> > didn't originally have that ability.
> >
> > Is there a clean and easy way to inline a function in C?  I
> > don't like
> > making macros to replace functions more than a half a dozen
> > lines long,
> > since it gets rather messy.
>
> CrossWorks doesn't yet support the inline qualifier.  We can accept it
> and not generate inline code as we're permitted to do, but that's
not
> really in the spirit or expected behaviour.
>
> >From the compilers I've looked at for the MSP430, the inline
> implementations are not ideal--they all generate sub-optimal code in
> various cases, even simple cases.
>
> At some point I will implement "inline", but don't expect it
any time
> soon.
>
> Right now, your best recourse is a C macro or use another macro
> processor.  For large projects, I've used noweb and find it useful.
>
> -- Paul.
>
>

Miles, 

> I've got another question for you.  My
MSP430F149 has (AFAIK) 
> 2k of RAM.  However, when I look at the "Sections" in Symbol 
> Browser, it shows the range of UDATA0 as 242-5ef, and the 
> size as 942, and it shows the range of IDATA0 as 200-241, and 
> size as 66.  That's a total of 1008 bytes, or about half of 
> what I expected it to be.  Heap size is set to 0, and the 
> only sections I have are CODE, CONST, UDATA0, IDATA0, INTVEC. 
>  Is there something else that uses RAM?

The symbol browser shows you what your application has used, not what is
available.  The stack pointer is initialised to the end of RAM and grows
down.  Thus, the stack is from the end of UDATA0 and 5ef through to 9ff.
If you add more variables and reference them, you'll see the IDATA0
and/or the UDATA0 section sizes increase.  As soon as you break the 2K
barrier for RAM, the linker will complain that it can't fit all your
data into RAM.

> Do I need to modify the memory map, or will the
choice of 
> proper processor type in the project be sufficient to 
> allocate all the ram?  I looked at the project configuration, 
> and the xml files used are msp430f149.xml and 
> section_placement.xml.  Neither one appears to set the 
> sections sizes, that I can see.  The ram size is set to 0x800 
> in msp430f149.xml, so I assume it auto-allocates the sections 
> into that somehow?

Yes, the section_placement.xml file describes how the linker is to fit
sections into the FLASH and RAM sections.  You don't need to modify it.

-- Paul.

Paul,

 > As soon as you break the 2K barrier for RAM, the linker
 > will complain that it can't fit all your data into RAM.
Is that only for global or static variables?  If so, I've seen that 
error when I try to compile/link my program.  What I am worried about is 
the stack overflowing while I run, from local variables being declared.  
I don't see how the linker would know about that ahead of time (but 
wouldn't mind being corrected).

What I've had in the past, is I will get eratic behavior, and it will be 
corrected when I reduce the size of some buffers.  I had assumed it was 
because I ran out of memory, but until know haven't tried to precisely 
determine when it happens.

Thanks,
Miles

Paul Curtis wrote:

> Miles,
>
> > I've got another question for you.  My MSP430F149 has (AFAIK)
> > 2k of RAM.  However, when I look at the "Sections" in Symbol
> > Browser, it shows the range of UDATA0 as 242-5ef, and the
> > size as 942, and it shows the range of IDATA0 as 200-241, and
> > size as 66.  That's a total of 1008 bytes, or about half of
> > what I expected it to be.  Heap size is set to 0, and the
> > only sections I have are CODE, CONST, UDATA0, IDATA0, INTVEC.
> >  Is there something else that uses RAM?
>
> The symbol browser shows you what your application has used, not what is
> available.  The stack pointer is initialised to the end of RAM and grows
> down.  Thus, the stack is from the end of UDATA0 and 5ef through to 9ff.
> If you add more variables and reference them, you'll see the IDATA0
> and/or the UDATA0 section sizes increase.  As soon as you break the 2K
> barrier for RAM, the linker will complain that it can't fit all your
> data into RAM.
>
> > Do I need to modify the memory map, or will the choice of
> > proper processor type in the project be sufficient to
> > allocate all the ram?  I looked at the project configuration,
> > and the xml files used are msp430f149.xml and
> > section_placement.xml.  Neither one appears to set the
> > sections sizes, that I can see.  The ram size is set to 0x800
> > in msp430f149.xml, so I assume it auto-allocates the sections
> > into that somehow?
>
> Yes, the section_placement.xml file describes how the linker is to fit
> sections into the FLASH and RAM sections.  You don't need to modify
it.
>
> -- Paul.



Miles, 

>  > As soon as you break the 2K barrier for RAM,
the linker  > 
> will complain that it can't fit all your data into RAM.
> Is that only for global or static variables?

Global and static variables are exactly the same thing: they are
allocated at fixed addresses in MSP430 memory, the static/extern is
simply the linkage of the symbol (file-local for static, globally known
for extern).

>  If so, I've 
> seen that error when I try to compile/link my program.

That's bad.  It means that you have lots of data that can't fit into
2K.

> What I am worried about is the stack overflowing
while I run,
> from local variables being declared.  
> I don't see how the linker would know about that ahead of 
> time (but wouldn't mind being corrected).

The linker could have a good guess, but in general it can't know
(consider interrupts, recursive functions, and function pointers).

> What I've had in the past, is I will get
eratic behavior, and 
> it will be corrected when I reduce the size of some buffers.  
> I had assumed it was because I ran out of memory, but until 
> know haven't tried to precisely determine when it happens.

Sounds like your stack could be overwriting your variables.  Note that
the FET has a RAM Fill Value (0xCD by default) which will fill RAM when
the program is run.  You can therefore monitor the stack usage by
examining memory to see how far down the stack the MSP430 has gone (i.e.
all non-0xCD values have been written to).

I'd suggest using an F169 if you can with a register write breakpoint
which will nail exactly when this thing goes bad.

-- Paul.


 > Global and static variables are exactly the same thing:

That's exactly what I meant, that global and static are allocated 
beforehand, and local variables are put on the stack at runtime, so the 
linker will only tell me if my global+static variables exceed 2k.

I am a bit confused about the SP.  I set a breakpoint to look at it at 
the start (just after stopping the watchdog), and the value was 9fe, 
while UDATA0 goes to 0x0693.  The SP does decrease, I saw it in the 
800's at a break point farther down.

I appears to me that if the SP is at 9fe right after the watchdog, and 
UDATA0 and IDATA0 go from 200 to 693, then I only have (9fe-693)5 
bytes of RAM.

Is something wrong, or am I interpreting something incorrectly?  The 
chip is correctly identified as a MSP430F149, and the ram size value was 
indeed 2k in the config file, I did not modify the heap size (it's 0), 
or mess with any of the uml files.

Thanks,
Miles


Paul Curtis wrote:

> Miles,
>
> >  > As soon as you break the 2K barrier for RAM, the linker  >
> > will complain that it can't fit all your data into RAM.
> > Is that only for global or static variables?
>
> Global and static variables are exactly the same thing: they are
> allocated at fixed addresses in MSP430 memory, the static/extern is
> simply the linkage of the symbol (file-local for static, globally known
> for extern).
>
> >  If so, I've
> > seen that error when I try to compile/link my program.
>
> That's bad.  It means that you have lots of data that can't fit
into 2K.
>
> > What I am worried about is the stack overflowing while I run,
> > from local variables being declared. 
> > I don't see how the linker would know about that ahead of
> > time (but wouldn't mind being corrected).
>
> The linker could have a good guess, but in general it can't know
> (consider interrupts, recursive functions, and function pointers).
>
> > What I've had in the past, is I will get eratic behavior, and
> > it will be corrected when I reduce the size of some buffers. 
> > I had assumed it was because I ran out of memory, but until
> > know haven't tried to precisely determine when it happens.
>
> Sounds like your stack could be overwriting your variables.  Note that
> the FET has a RAM Fill Value (0xCD by default) which will fill RAM when
> the program is run.  You can therefore monitor the stack usage by
> examining memory to see how far down the stack the MSP430 has gone (i.e.
> all non-0xCD values have been written to).
>
> I'd suggest using an F169 if you can with a register write breakpoint
> which will nail exactly when this thing goes bad.
>
> -- Paul.
>


Sorry for that, I was actually *very* confused.  Obviously if I use 
(693-200)75 bytes for globals and static, then there will be around 
875 left for the stack.

(Wish there was an 'undo' button for the forum, to delete dumb posts)

Miles Gazic wrote:

> > Global and static variables are exactly the
same thing:
>
> That's exactly what I meant, that global and static are allocated
> beforehand, and local variables are put on the stack at runtime, so the
> linker will only tell me if my global+static variables exceed 2k.
>
> I am a bit confused about the SP.  I set a breakpoint to look at it at
> the start (just after stopping the watchdog), and the value was 9fe,
> while UDATA0 goes to 0x0693.  The SP does decrease, I saw it in the
> 800's at a break point farther down.
>
> I appears to me that if the SP is at 9fe right after the watchdog, and
> UDATA0 and IDATA0 go from 200 to 693, then I only have (9fe-693)5
> bytes of RAM.
>
> Is something wrong, or am I interpreting something incorrectly?  The
> chip is correctly identified as a MSP430F149, and the ram size value was
> indeed 2k in the config file, I did not modify the heap size (it's 0),
> or mess with any of the uml files.
>
> Thanks,
> Miles
>
>
> Paul Curtis wrote:
>
> > Miles,
> >
> > >  > As soon as you break the 2K barrier for RAM, the linker 
>
> > > will complain that it can't fit all your data into RAM.
> > > Is that only for global or static variables?
> >
> > Global and static variables are exactly the same thing: they are
> > allocated at fixed addresses in MSP430 memory, the static/extern is
> > simply the linkage of the symbol (file-local for static, globally
known
> > for extern).
> >
> > >  If so, I've
> > > seen that error when I try to compile/link my program.
> >
> > That's bad.  It means that you have lots of data that can't
fit into 2K.
> >
> > > What I am worried about is the stack overflowing while I run,
> > > from local variables being declared.
> > > I don't see how the linker would know about that ahead of
> > > time (but wouldn't mind being corrected).
> >
> > The linker could have a good guess, but in general it can't know
> > (consider interrupts, recursive functions, and function pointers).
> >
> > > What I've had in the past, is I will get eratic behavior,
and
> > > it will be corrected when I reduce the size of some buffers.
> > > I had assumed it was because I ran out of memory, but until
> > > know haven't tried to precisely determine when it happens.
> >
> > Sounds like your stack could be overwriting your variables.  Note that
> > the FET has a RAM Fill Value (0xCD by default) which will fill RAM
when
> > the program is run.  You can therefore monitor the stack usage by
> > examining memory to see how far down the stack the MSP430 has gone
(i.e.
> > all non-0xCD values have been written to).
> >
> > I'd suggest using an F169 if you can with a register write
breakpoint
> > which will nail exactly when this thing goes bad.
> >
> > -- Paul.
> >
>



Memfault Beyond the Launch