avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [avr-libc-dev] [RFC] Sleeping BOD API


From: Weddington, Eric
Subject: RE: [avr-libc-dev] [RFC] Sleeping BOD API
Date: Fri, 6 Feb 2009 12:00:17 -0700

 

> -----Original Message-----
> From: Krzysztof Kościuszkiewicz [mailto:address@hidden 
> Sent: Friday, February 06, 2009 11:45 AM
> To: Weddington, Eric
> Cc: address@hidden
> Subject: Re: [avr-libc-dev] [RFC] Sleeping BOD API
> 
> On Fri, Feb 06, 2009 at 08:20:49AM -0700, Weddington, Eric wrote:
> 
> > > > +#define sleep_bod_disable()  \
> > > > +(__extension__({             \
> > > > +    __asm__ __volatile__ (   \
> > > > +        "ori  %0,%1" \
> > > > +        : "+d" (MCUCR) \
> > > > +        : "i" (_BV(BODS) | _BV(BODSE)) \
> > > > +    ); \
> > > > +    __asm__ __volatile__ (   \
> > > > +        "andi  %0,%1" \
> > > > +        : "=d" (MCUCR) \
> > > > +        : "i" (~_BV(BODSE)) \
> > > > +    ); \
> > > > +}))
> > 
> > [...]
> >
> > My big question is: Do I have to worry that GCC will 
> somehow select a
> > different register for MCUCR in the second __asm__ 
> statement? I would
> > think that since I am letting gcc select the register in the first
> > __asm__ statement and having gcc do the output, that gcc will know
> > which register that MCUCR lives in and can match that with 
> the second
> > __asm__ statement. From my tests, it seems that it is truly 
> the case;
> > the registers always match so that it generates (pseudocode):
> >
> > in X, 85-32
> > ori  X, 96
> > out  85-32, X
> > andi X, -33
> > out  85-32, X
> > 
> > where "X" is always the same high register ("d" constraint).
> > 
> > This is important to meet the timed sequence needed to 
> disable the BOD
> > before sleeping.
> 
> Is there any disadvantage to including the OUT instructions directly
> instead of breaking up the macro into two asm statements? 

Yes. I would then have to specify the exact register to use. I don't want to do 
that, because I don't really care what register is being used to modify the 
value, as long it meets the constraints for the ORI and ANDI instructions. If I 
had to pick a fixed register, then I won't know if it is being used elsewhere 
in the code and so I would have to ensure that it is PUSHed and POPed. The 
compiler knows which register is free. And in the end, the register is a 
scratch register; I don't need it to be a specific register to do the 
modifications of the value. I do care that the value gets written out to memory 
when I need it to (twice).

> This could
> break unexpectedly - as you said the timing is crucial here.

Well, I didn't say that it could break unexpectedly. I don't know whether it 
could break or not. Perhaps it's perfectly fine code. I freely admit that I'm 
not the world's best gcc inline assembly programmer; but then again, I don't 
know anyone who is. It's definitely an arcane subject. Every time I write the 
stuff I'm constantly referencing the documentation. (Perhaps one of these years 
I'll finally have a clue what everything does and means.)

> I guess this trick would not work if the sfr contents could change
> between OUTs - in the above case compiler assumed (why?) that they
> won't.

The sfr won't change due to user code because the macro generates two __asm__ 
statements back-to-back. No user code can get in between. As long as the macro 
is used in the recommended sequence (described in the documentation part, then 
interrupts will be turned off so it won't interrupt the sequence timing.

I definitely appreciate the review.

Thanks,
Eric




reply via email to

[Prev in Thread] Current Thread [Next in Thread]