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 15:17:48 -0700

 

> -----Original Message-----
> From: Krzysztof Kościuszkiewicz [mailto:address@hidden 
> Sent: Friday, February 06, 2009 2:34 PM
> To: Weddington, Eric
> Cc: address@hidden
> Subject: Re: [avr-libc-dev] [RFC] Sleeping BOD API
> 
> Then why not use temporary variable:
> 
> #define sleep_bod_disable()                     \
>     do {                                        \
>         unsigned char tmp = MCUCR;              \
>         __asm__ __volatile__ (                  \
>             "ori  %0,%1"  "\n\t"                \
>             "out  %3,%0"  "\n\t"                \
>             "andi %0,%2"  "\n\t"                \
>             "out  %3,%0"  "\n\t"                \
>             : "+d" (tmp)                        \
>             : "i" (_BV(BODS) | _BV(BODSE)),     \
>               "i" (~_BV(BODSE)),                \
>               "I" (_SFR_IO_ADDR(MCUCR))         \
>         );                                      \
>     } while (0)
> 
> > 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.
> 
> You are right, but the compiler will not be able to figure that out.
> Correct me if I'm wrong, but I believe gcc *should* generate 
> two INs and
> two OUTs for the macro above, ie. treat MCUCR as volatile.

Well, the macro above works. I disagree with your last paragraph above: gcc 
does not generate two INs and OUTs. We are explicitly generating the OUTs. GCC 
does generate the IN instruction before the __asm__ statement.

Ok so the above works, but now a question about some theoretical aspects of 
this. In practice, the MCUCR register is in the I/O space, therefore it can be 
accessed with IN/OUT instructions. The macro above works, but it *explicitly* 
specifies the OUT instruction. But what if there were an AVR device where MCUCR 
were *not* in the I/O space? (A real world example is the Watchdog API, wdt.h, 
where we have two sets of macros, one that uses the OUT instruction and the 
other uses the STS instruction, based on the device type and where the watchdog 
control register is located.) Could my first macro implementation work with 
either definition?....

After some initial testing, indeed it does generate different code, and correct 
code, if the I/O register in question is outside of the I/O space. This has a 
very distinct advantage for use within avr-libc. If I don't have to specify the 
exact instruction to move the value out to an I/O register, but let gcc 
generate the correct instruction based on the address of the I/O register, then 
I can write a single macro and it will cover practically all AVR devices and be 
somewhat "future-proof" if Atmel decides to relocate the register to a 
different part of the address map. This would open up new possibilities for 
rewriting the other APIs that need this feature (watchdog).

Eric




reply via email to

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