avr-gcc-list
[Top][All Lists]
Advanced

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

Re: [avr-gcc-list] What Happened to the sbi() and cbi() Macros????


From: Ned Konz
Subject: Re: [avr-gcc-list] What Happened to the sbi() and cbi() Macros????
Date: Mon, 31 Jan 2005 15:33:59 -0800
User-agent: KMail/1.7.2

On Monday 31 January 2005 9:09 am, E. Weddington wrote:
> Which way did Ned describe? Is it with a bit field?

Yes, at least in part. I also like inline functions to do higher-level things, 
but I didn't talk about those on the list.

> If so, there are several portability issues with using bitfields. 

The portability issues aren't relevant here, because my headers are 
machine-generated from the text from the Atmel databooks (copy table from 
PDF, paste into text file, generate headers directly) and so moving to 
another compiler only requires re-generating the headers. Anyway, I intend to 
stay with GCC. And it's likely that other compilers will also pack bits more 
or less the same way for the AVR target, and I could generate the headers 
with conditionals for bitfield ordering, if there were any demand from a user 
of another free compiler whose authors hadn't for some reason created 
headers.

> Also, if you use a bit field you cannot operate on non-continguous bits 
simultaneously such as:
>  PORTA |= (_BV(0) | _BV(6));

That's quite right, and that's why my headers also allow for this idiom.

For each SFR, there is a union declared, containing:

- both byte- or word- wise (just as the current avr-libc headers)
- bit-wise
- multi-bit fields where possible

So for, say the ATmega16's SFIOR register, I have:


/* SFIOR ($50) (page 55,86,133,199,219) */
typedef union SFIOR_t {
  uint8_t asByte;
  struct {
    uint8_t bPSR10 :1;
    uint8_t bPSR2 :1;
    uint8_t bPUD :1;
    uint8_t bACME :1;
    uint8_t bReserved4 :1;
    uint8_t bADTS0 :1;
    uint8_t bADTS1 :1;
    uint8_t bADTS2 :1;
  } b;
  struct {
    uint8_t :1; /* PSR10 */
    uint8_t :1; /* PSR2 */
    uint8_t :1; /* PUD */
    uint8_t :1; /* ACME */
    uint8_t :1; /* Reserved4 */
    uint8_t fADTS :3;
  } f;
} SFIOR_t;
#define SFIOR_sfr (*(volatile SFIOR_t *) (0x50))
#define SFIOR SFIOR_sfr.asByte /* entire register */
#define PSR10 SFIOR_sfr.b.bPSR10
#define PSR2 SFIOR_sfr.b.bPSR2
#define PUD SFIOR_sfr.b.bPUD
#define ACME SFIOR_sfr.b.bACME
#define ADTS0 SFIOR_sfr.b.bADTS0
#define ADTS1 SFIOR_sfr.b.bADTS1
#define ADTS2 SFIOR_sfr.b.bADTS2
#define ADTS SFIOR_sfr.f.fADTS


Now, with this I can still go:

SFIOR |= 0xE1;

to set both ADTS and PSR10 at once.

Or I can do this:

        SFIOR_sfr = (SFIOR_t) { .b.bPUD = 1, .b.bPSR10 = 1 };
  96:   85 e0           ldi     r24, 0x05       ; 5
  98:   80 bf           out     0x30, r24       ; 48

Note that combining .f.fADTS and .b.bPSR10 would not work right, though:

        SFIOR_sfr = (SFIOR_t) { .f.fADTS = 7, .b.bPSR10 = 1 };
  9a:   81 e0           ldi     r24, 0x01       ; 1
  9c:   80 bf           out     0x30, r24       ; 48

Naturally, since SFIOR is declared as volatile, successive assignments won't 
be combined:

        ADTS = 7;
  b2:   80 b7           in      r24, 0x30       ; 48
  b4:   80 6e           ori     r24, 0xE0       ; 224
  b6:   80 bf           out     0x30, r24       ; 48
        PSR10 = 1;
  b8:   80 b7           in      r24, 0x30       ; 48
  ba:   81 60           ori     r24, 0x01       ; 1
  bc:   80 bf           out     0x30, r24       ; 48

Perhaps a hybrid scheme like this that also adds bit *numbers* for a BIT() 
macro would be useful:

#define bitPSR10 0
#define bitPSR2  1
#define bitPUD  2

etc. (the names could probably be chosen better).

and then, given appropriate macros like:

#define bit(bitNum) (1<<(bitNum))
#define bit_set(reg, bits) reg |= (uint8_t)(bits);
#define bit_clear(reg, bits) reg &= ~(uint8_t)(bits);

we could do things the way we're used to if necessary:

        bit_set(SFIOR, bit(bitPSR10) | bit(bitPSR2) | bit(bitPUD));
  be:   80 b7           in      r24, 0x30       ; 48
  c0:   87 60           ori     r24, 0x07       ; 7
  c2:   80 bf           out     0x30, r24       ; 48

-- 
Ned Konz
http://bike-nomad.com



reply via email to

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