Searching \ for 'Re-entrant vs. Re-cursive (ref: PIC C Compiler, RE' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/languages.htm?key=c
Search entire site for: 'Re-entrant vs. Re-cursive (ref: PIC C Compiler, RE'.

Truncated match.
PICList Thread
'Re-entrant vs. Re-cursive (ref: PIC C Compiler, RE'
1999\03\12@093412 by Lou Calkins

flavicon
face
There has been some discussion on the use of C compilers with re-entrant
routines.  Then mention of heavy stack usage and the word recursive came
up.  Recursive routines (ones that call themselves) obviously must be
re-entrant, but re-entrant routines do not need to be used recursively.
The real heavy stack usage comes with recursive routines.  The one
application that comes to mind for using a recursive routine is printing
out a tree or other data structure.

While I do agree that a recursive routine does tend to gobble up the stack
and is somewhat indeterminant as to how much RAM will be used, the
re-entrant routine may not be as hoggish.  The compiler I use for the
68HC11 (Whitesmiths) has recursive routines and they are a must for me.  If
I am in the middle of a math computation (e.g. divide), and an interrupt
occurs where the ISR needs to perform the same kind of math computation,
the math routine better be re-entrant.  But just because those two routines
are using the math function at the same time does not mean a large amount
of stack space is used.  So re-entrant routines are a must in embedded
applications where interrupts call routines.

Which comes to the bigger subject of using a C compiler for a PIC.  I have
been coding in C for 15 years and most of my code I write daily is in C.  I
would LOVE to write C code for a PIC but cannot get over the feeling that I
am doing the wrong thing.  Believe me, after writing a large application
for a 17C44 in assembly language, I really want to use C.  Compilers
without an available stack tend to use large blocks of RAM and overhead
routines to access them as pseudo stack spaces, and I think this is
wasteful in a PIC.  Most PICs I use have a rather small amount of RAM to
start with.  The day a PIC has an addressable stack will be when everything
changes.  Maybe for simple applications where there is sufficient memory, a
compiler would be great.  But then again, if the application is simple, why
not just code it in assembly language?  My answer to that would be because
I make less mistakes in C and can write code a lot faster.  Any other thoughts?

1999\03\12@111502 by Andy Kunz

flavicon
face
>for a 17C44 in assembly language, I really want to use C.  Compilers
>without an available stack tend to use large blocks of RAM and overhead
>routines to access them as pseudo stack spaces, and I think this is
>wasteful in a PIC.  Most PICs I use have a rather small amount of RAM to

Actually, that's not what happens.

The software stack is to fixed addresses determined by the call graph
during the link phase.  A variable ends up in the same location every time
you call it.  Just where that is would be determined by the RAM used before
deepest call to it.  The linker has everything it needs to know to do this,
as long as the program is not recursive.  Even re-entrant is OK and is
handled properly (by HiTech C at least).

Andy

  \-----------------/
   \     /---\     /
    \    |   |    /          Andy Kunz
     \   /---\   /           Montana Design
/---------+   +---------\     http://www.montanadesign.com
| /  |----|___|----|  \ |
\/___|      *      |___\/     Go fast, turn right,
                              and keep the wet side down!

1999\03\12@125035 by w. v. ooijen / f. hanneman

picon face
> Recursive routines (ones that call themselves) obviously must be
> re-entrant, but re-entrant routines do not need to be used recursively.

> The compiler I use for the
> 68HC11 (Whitesmiths) has recursive routines and they are a must for me.

> I am in the middle of a math computation (e.g. divide), and an interrupt
> occurs where the ISR needs to perform the same kind of math computation,
> the math routine better be re-entrant.  But just because those two
routines
> are using the math function at the same time does not mean a large amount
> of stack space is used.

The PIC (except the high-end ones?) do not have a data stack, so even
the re-entrancy which you mention is difficult to achive. I know, I have
written my own PIC compiler. The best (compact) PIC code uses fixed
addresses for data, allocated pseudo-stack wise. This makes re-entracy
impossible. I think the best a compiler could do is generate separate
code for everything which is used during an interrupt. Lucky that PICs do
not have nested interrupts....

wouter.

1999\03\12@130950 by Gerhard Fiedler

picon face
At 11:12 03/12/99 -0500, Andy Kunz wrote:
>The software stack is to fixed addresses determined by the call graph
>during the link phase.  A variable ends up in the same location every time
>you call it.  Just where that is would be determined by the RAM used before
>deepest call to it.  The linker has everything it needs to know to do this,
>as long as the program is not recursive.  Even re-entrant is OK and is
>handled properly (by HiTech C at least).

are you sure? i remember something about at least a bunch of system
functions not being reentrant.

ge

1999\03\13@084530 by w. v. ooijen / f. hanneman

picon face
> The software stack is to fixed addresses determined by the call graph
> during the link phase.  A variable ends up in the same location every
time
> you call it.  Just where that is would be determined by the RAM used
before
> deepest call to it.  The linker has everything it needs to know to do
this,
> as long as the program is not recursive.  Even re-entrant is OK and is
> handled properly (by HiTech C at least).

How is re-entrancy handled when all variables have a fixed address?

Wouter.

1999\03\13@110026 by Andy Kunz

flavicon
face
>How is re-entrancy handled when all variables have a fixed address?

The linker also knows which libaray routines are called within the ISR
which are also used by the application.

It adds a module of code to save the variables from these dual-use routines
somewhere in RAM, then proceeds to use the same addresses for the other.
This provides "true" re-entrancy.

Or, it could have a second copy of the library routine which uses different
RAM addresses.  This provides "functional" re-entrancy.

In an ideal world, the programmer should be able to select which method to
use each shared function.

Personally, I like to keep the ISR to a minimum and set flags telling the
application level what to do with the data collected during the ISR.

Andy

1999\03\13@111936 by Marc

flavicon
face
> It adds a module of code to save the variables from these dual-use routines
> somewhere in RAM, then proceeds to use the same addresses for the other.
> This provides "true" re-entrancy.

I wouldn't call this "true re-entrancy". It's more of a "re-entrancy
with last-enter first-exit requirement"

It will fail, for example, in a preemptive task scheduling environment.
Several tasks can enter the function, and be preempted at any time.

The task scheduler would have to know which task currently uses which
function to know which RAM locations it has to backup for later restore.
That would be way of an overhead, so basically it would have to be
implemented by swaping the _whole_ used RAM space for each task.

..that somehow reminds me of Windows and multitasking :-)


Creating vars on a stack is a more elegant solution to this
problem, and it _really_ provides true re-entrancy.

1999\03\13@180416 by Clyde Smith-Stubbs

flavicon
face
On Fri, Mar 12, 1999 at 10:05:42AM -0800, Gerhard Fiedler wrote:

> are you sure? i remember something about at least a bunch of system
> functions not being reentrant.

The intrinsic library routines (e.g. multiply, divide) are re-entrant in the
sense that they can be called from an interrupt function, and no problems will
occur if they're already executing, but this is achieved by saving the
necessary RAM areas in the interrupt routine (the compiler saves only what appea
rs
to be necessary). User functions are generally speaking not re-entrant.

With respect to the original question about practicality of C on a PIC, the
amount of RAM used by a C program should not be any larger than that used
by an equivalent assembler program; data is data and occupies the same space
irrespective of the language used.

ROM usage for C is comparable to assembler in most cases; I have seen plenty of
examples of C compiled code that came out smaller than hand-written assembler;
OTOH a clever assembler programmer will always be able to equal or better
the compiler, but the time invested will be much greater.

Regards, Clyde

--
Clyde Smith-Stubbs               |            HI-TECH Software
Email: spam_OUTclydeTakeThisOuTspamhtsoft.com          |          Phone            Fax
WWW:   http://www.htsoft.com/    | USA: (408) 490 2885  (408) 490 2885
PGP:   finger .....clydeKILLspamspam@spam@htsoft.com   | AUS: +61 7 3355 8333 +61 7 3355 8334
---------------------------------------------------------------------------
HI-TECH C: compiling the real world.

1999\03\13@183816 by Gerhard Fiedler

picon face
At 09:01 03/14/99 +1000, Clyde Smith-Stubbs wrote:
>The intrinsic library routines (e.g. multiply, divide) are re-entrant in the
>sense that they can be called from an interrupt function, and no problems will
>occur if they're already executing, but this is achieved by saving the
>necessary RAM areas in the interrupt routine (the compiler saves only what
>appears
>to be necessary). User functions are generally speaking not re-entrant.

thanks for the clarification. makes sense.


>With respect to the original question about practicality of C on a PIC, the
>amount of RAM used by a C program should not be any larger than that used
>by an equivalent assembler program; data is data and occupies the same space
>irrespective of the language used.

as a matter of fact, due to the "smart" handling of local variables it
might even be that a compiler uses less ram than a not fully optimized
assembler program. (and who has the time to fully optimize everything? :)

ge

1999\03\13@210620 by Andy Kunz

flavicon
face
>I wouldn't call this "true re-entrancy". It's more of a "re-entrancy
>with last-enter first-exit requirement"

Agreed.

>It will fail, for example, in a preemptive task scheduling environment.
>Several tasks can enter the function, and be preempted at any time.

However, we are talking PICs here, not real processors <G>.  So we have
only two tasks available - ISR and Application.

>The task scheduler would have to know which task currently uses which
>function to know which RAM locations it has to backup for later restore.
>That would be way of an overhead, so basically it would have to be
>implemented by swaping the _whole_ used RAM space for each task.
>
>..that somehow reminds me of Windows and multitasking :-)

Yes, but considering we are now down to 2 "programs" (ISR & App) we only
need to backup the data for those routines which are common to both.  And
as Clyde pointed out, he already took care of that for us.

>Creating vars on a stack is a more elegant solution to this
>problem, and it _really_ provides true re-entrancy.

Agreed.  But then, we don't have one in a PIC, do we?!

Andy

1999\03\14@133731 by w. v. ooijen / f. hanneman

picon face
> >How is re-entrancy handled when all variables have a fixed address?
>
> It adds a module of code to save the variables from these dual-use
routines
> somewhere in RAM, then proceeds to use the same addresses for the other.
> This provides "true" re-entrancy.
That could take quite some time, which is not very practical in an
interrupt.

> Or, it could have a second copy of the library routine which uses
different
> RAM addresses.  This provides "functional" re-entrancy.
That is how I plan to do it.

Thanks!
Wouter.

1999\03\14@133733 by w. v. ooijen / f. hanneman

picon face
Your objections are theoretically correct, but not relevant on a PIC
with just one interrupt vector and no options to manipulate the stack.
Or to put it in a nother way: there is no way for a user to notice the
difference.
An simulating a stack is A solution, but costs a lot of code.

> > It adds a module of code to save the variables from these dual-use
routines
> > somewhere in RAM, then proceeds to use the same addresses for the
other.
{Quote hidden}

1999\03\15@065638 by Marc

flavicon
face
> Your objections are theoretically correct, but not relevant on a PIC
> with just one interrupt vector and no options to manipulate the stack.
> Or to put it in a nother way: there is no way for a user to notice the
> difference.

I would not think so..  What I described is exactly what I do with IAR-C
on an AVR chip (about 350 code words for the whole multitasker).  I know
that the PIC has some limitations regarding the stack, but I would have
expected a compiler to hide them from me. Why else should I want to use
one than to hide the architecture?

Well, until now I have considered the low end PICs to be a valuable
thing to have, and those I programmed in Asm anyway because of their
limitedness.  Probably I just stick with that..

1999\03\15@104941 by Gerhard Fiedler

picon face
At 12:44 03/15/99 +0100, Marc wrote:
>I would not think so..  What I described is exactly what I do with IAR-C
>on an AVR chip (about 350 code words for the whole multitasker).  I know
>that the PIC has some limitations regarding the stack, but I would have
>expected a compiler to hide them from me. Why else should I want to use
>one than to hide the architecture?

i don't know... when i switch from a dos compiler to a windows 9x compiler
to a unix compiler, i =do= expect some differences. or when i switch from a
pic compiler to a 80186 to a powerpc compiler, i do expect some
differences, too... :)

but if you take the limitations of the compiler in account (ie., in most
pic compiler no re-entrant user functions), then the compiler does "hide"
the architecture. you don't have to know why the limitation is there if you
don't want to, you just have to read your compiler's manual and know that
it is there.

BTW, is your task switcher preemptive (ie. an interrupt may lead
immediately to a task switch)? if it is, i don't know how you would
implement that on a pic, even in assembler (and therefore shouldn't expect
it to be possible in c, neither). if it is not, you don't need reentrant
functions for that. state machine-based "task switcher" can be implemented
on a pic, and of course with a c compiler, too. (basically you can say that
all you can do with assembler on a pic you can do with c. i guess that's as
far as you can get in terms of "hiding the architecture"... you can't
expect a compiler do things that are not possible on the target hardware,
can you?)

ge

1999\03\15@142326 by w. v. ooijen / f. hanneman

picon face
> > Your objections are theoretically correct, but not relevant on a PIC
> > with just one interrupt vector and no options to manipulate the stack.
> > Or to put it in a nother way: there is no way for a user to notice the
> > difference.
>
> I would not think so..  What I described is exactly what I do with IAR-C
> on an AVR chip (about 350 code words for the whole multitasker).  I know
> that the PIC has some limitations regarding the stack, but I would have
> expected a compiler to hide them from me. Why else should I want to use
> one than to hide the architecture?
>
> Well, until now I have considered the low end PICs to be a valuable
> thing to have, and those I programmed in Asm anyway because of their
> limitedness.  Probably I just stick with that..

In assembler or otherwise you won't be able to make an interrupt-based
multitasker because you can not manipulate the stack... You would have
the same problem on a 90S1200.

1999\03\15@172136 by Marc

flavicon
face
> BTW, is your task switcher preemptive (ie. an interrupt may lead
> immediately to a task switch)?

Yes :-) (round-robbin with aging) But it is not realtime, a task
can Forbid() anytime it wants.

More... (looser matching)
- Last day of these posts
- In 1999 , 2000 only
- Today
- New search...