[Openec] 8051 reentrancy

pgf at laptop.org pgf at laptop.org
Thu Jul 31 11:01:09 EDT 2008


[ beware -- list-crosspost ]

hi -- i started this conversation privately with frieder the
other day, and he correctly pointed out that it would be better
taken to the openec or sdcc lists.  so here i am.  frieder has
already addressed some of my issues, but i'll include my original
mail here, for background, and down below, his initial response.

i'm working on EC firmware for the XO laptop (from OLPC). 
specifically, i'm in the middle of porting the code from the Keil
compiler to sdcc.

it seems that at least some of the instability that i've been
seeing is that the interrupt routines (and/or some of the
routines they call) weren't reentrant, when i thought they would
be.  annoyingly, some of the non-reentrant code was debugging
code that i had added to make the problems more visible.
for instance, i found that code that i added to blink an LED
every 1024 times the routine was called was using __modsint,
which has a register overflow argument.  when i eliminated that
call (by changing "(count % 1024)" to "(count & 0x3ff)"), things
got much better.  (frieder has since pointed out that if my
counter had been unsigned, this wouldn't have been an issue.)

i'm now in the position of ensuring that all of the remaining
code that might be called during an interrupt is safe.  since all
of my ISR routines are in a single file, and there aren't that many
to audit, it's not that bad.

but i'm not completely sure what i'm looking for:  if my routines
don't call subroutines, and there are no references to internal
support routines (e.g., the math code) that have foo_PARM
references, am i safe?  or are there other code generation issues
that i might be subject to if i don't use --stack-auto
and #pragma reentrant?

(most of the interrupt service routines simply set a flag and
return, but a few are more complicated than that.  but they're
still just logic and variables, no function calls.)

any comments/advice appreciated...

paul
-------------------------------

and frieder's response (posted with his permission), with minor edits:

 > Date:    Tue, 29 Jul 2008 20:27:04 +0200
 > To:      pgf at laptop.org,....
 > From:    Frieder Ferlemann <frieder.ferlemann at web.de>
 > Subject: Re: 8051 reentrancy
 > In-Reply-To: <3591.1217333486 at foxharp.boston.ma.us>
 > 
 > pgf at laptop.org schrieb:
 .....
 > 
 > > i'm now in the position of ensuring that all of the remaining
 > > code that might be called during an interrupt is safe.  since all
 > > of my ISR routines are in a single file, and there aren't that many
 > > to audit, it's not that bad.
 > 
 > thats a good situation: you can f.e. grep over the assembler source like:
 > "grep call xo_sample_interrupt.asm"
 > 
 > I'm appending the C file. (you'll find that &0x3ff and %1024 are equivalent
 > there and irq_routine10 and irq_routine11 giving the most compact code)
 > 
 > > but i'm not completely sure what i'm looking for:  if my routines
 > > don't call subroutines, and there are no references to internal support
 > 
 > You can look for lcall with the grep above. Or have a look into the
 > register pushing in the preamble for the IRQ.
 > In the example given you see the complete register bank being pushed
 > for irq_routine13. This makes irq_routine13 suspicious.
 > 
 > > routines (e.g., the math code) that have foo_PARM references, am
 > > i safe?  or are there other code generation issues that i might
 > > be subject to if i don't use --stack-auto and #pragma reentrant?
 > 
 > If you'd call routines that need local storage (for local variables
 > but also for SLOC) you are in trouble. Also if you call functions
 > that need arguments that are not passed via a,b,dpl,dph.
 > 
 > If you need to call a function foo() which is not reentrant it might
 > make sense to declare a function foo_IRQ() which is an exact copy
 > of foo() but only called within IRQ. (or disable IRQ within that function)
 > 
 > Note if you do not use Interrupt priorities (I hope you don't have to)
 > then you only need one foo_IRQ() even if it's used within different
 > IRQ routines.
 > 
 > > (most of the interrupt service routines simply set a flag and return,
 > > but a few are more complicated than that.  but they're still just
 > > logic and variables, no function calls.)
 > 
 > You should be safe then. I may be overlooking something though.
 > Some extra problems might be global >=16 bit variables (or global 8 bit
 > variables in xdata) which used by both IRQ and non-IRQ routines...
 > (also see http://sdcc.sourceforge.net/doc/sdccman.html/node66.html
 > (not a permanent link))
 > 
 ....
 > 
 > Greetings,
 > Frieder
 > 
 > 
 > 
 > static volatile unsigned int irq_count;
 > static volatile          int irq_tmp;
 > 
 > 
 > void irq_routine10(void) __interrupt (10)
 > {
 >   irq_count++;
 >   irq_count %= 1024;
 > }
 > 
 > void irq_routine11(void) __interrupt (11)
 > {
 >   irq_count++;
 >   irq_count &= 0x3ff;
 > }
 > 
 > void irq_routine12(void) __interrupt (12)
 > {
 >   irq_count = irq_count + 1;
 >   irq_count = (irq_count % 1024);
 > }
 > 
 > void irq_routine13(void) __interrupt (13)
 > {
 >   irq_tmp++;
 >   irq_tmp %= 1024;  // <--
 > }
 > 
 > 
 > void main(void)
 > {
 > }



=---------------------
 paul fox, pgf at laptop.org


More information about the Openec mailing list