Special function registers


Detailed Description

When working with microcontrollers, many of the tasks usually consist of controlling the peripherals that are connected to the device, respectively programming the subsystems that are contained in the controller (which by itself communicate with the circuitry connected to the controller).

The AVR series of microcontrollers offers two different paradigms to perform this task. There's a separate IO address space available (as it is known from some high-level CISC CPUs) that can be addressed with specific IO instructions that are applicable to some or all of the IO address space (in, out, sbi etc.). The entire IO address space is also made available as memory-mapped IO, i. e. it can be accessed using all the MCU instructions that are applicable to normal data memory. The IO register space is mapped into the data memory address space with an offset of 0x20 since the bottom of this space is reserved for direct access to the MCU registers. (Actual SRAM is available only behind the IO register area, starting at either address 0x60, or 0x100 depending on the device.)

AVR Libc supports both these paradigms. While by default, the implementation uses memory-mapped IO access, this is hidden from the programmer. So the programmer can access IO registers either with a special function like outb():

        #include <avr/io.h>

        outb(PORTA, 0x33);

or they can assign a value directly to the symbolic address:

        PORTA = 0x33;

The compiler's choice of which method to use when actually accessing the IO port is completely independent of the way the programmer chooses to write the code. So even if the programmer uses the memory-mapped paradigm and writes

        PORTA |= 0x40;

the compiler can optimize this into the use of an sbi instruction (of course, provided the target address is within the allowable range for this instruction, and the right-hand side of the expression is a constant value known at compile-time).

The advantage of using the memory-mapped paradigm in C programs is that it makes the programs more portable to other C compilers for the AVR platform. Some people might also feel that this is more readable. For example, the following two statements would be equivalent:

        outb(DDRD, inb(DDRD) & ~LCDBITS);
        DDRD &= ~LCDBITS;

The generated code is identical for both. Whitout optimization, the compiler strictly generates code following the memory-mapped paradigm, while with optimization turned on, code is generated using the (faster and smaller) in/out MCU instructions.

Note that special care must be taken when accessing some of the 16-bit timer IO registers where access from both the main program and within an interrupt context can happen. See Why do some 16-bit timer registers sometimes get trashed?.


Modules

Additional notes from <avr/sfr_defs.h>

Bit manipulation

#define _BV(bit)   (1 << (bit))

IO register bit manipulation

#define bit_is_set(sfr, bit)   (sfr & _BV(bit))
#define bit_is_clear(sfr, bit)   (!(sfr & _BV(bit)))
#define loop_until_bit_is_set(sfr, bit)   do { } while (bit_is_clear(sfr, bit))
#define loop_until_bit_is_clear(sfr, bit)   do { } while (bit_is_set(sfr, bit))

Deprecated Macros

#define cbi(sfr, bit)   (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit)   (_SFR_BYTE(sfr) |= _BV(bit))
#define inb(sfr)   _SFR_BYTE(sfr)
#define outb(sfr, val)   (_SFR_BYTE(sfr) = (val))
#define inw(sfr)   _SFR_WORD(sfr)
#define outw(sfr, val)   (_SFR_WORD(sfr) = (val))
#define outp(val, sfr)   outb(sfr, val)
#define inp(sfr)   inb(sfr)
#define BV(bit)   _BV(bit)
#define _SFR_BYTE(sfr)   _MMIO_BYTE(_SFR_ADDR(sfr))
#define _SFR_WORD(sfr)   _MMIO_WORD(_SFR_ADDR(sfr))


Define Documentation

no no integer part ORI _BV bit   )     (1 << (bit))
 

 #include <avr/io.h>

Converts a bit number into a byte value.

Note:
The bit shift is performed by the compiler which then inserts the result into the code. Thus, there is no run-time overhead when using _BV().

#define bit_is_clear sfr,
bit   )     (!(sfr & _BV(bit)))
 

 #include <avr/io.h>

Test whether bit bit in IO register sfr is clear. This will return non-zero if the bit is clear, and a 0 if the bit is set.

#define bit_is_set sfr,
bit   )     (sfr & _BV(bit))
 

 #include <avr/io.h>

Test whether bit bit in IO register sfr is set. This will return a 0 if the bit is clear, and non-zero if the bit is set.

#define BV bit   )     _BV(bit)
 

Deprecated:
For backwards compatibility only. This macro will eventually be removed.
Use _BV() in new programs.

#define cbi sfr,
bit   )     (_SFR_BYTE(sfr) &= ~_BV(bit))
 

Deprecated:
 #include <avr/io.h>
For backwards compatibility only. This macro will eventually be removed.
Clear bit bit in IO register sfr.

#define inb sfr   )     _SFR_BYTE(sfr)
 

Deprecated:
 #include <avr/io.h>
For backwards compatibility only. This macro will eventually be removed.
Use direct access in new programs.

#define inp sfr   )     inb(sfr)
 

Deprecated:
For backwards compatibility only. This macro will eventually be removed.
Use direct access in new programs.

#define inw sfr   )     _SFR_WORD(sfr)
 

Deprecated:
 #include <avr/io.h>
For backwards compatibility only. This macro will eventually be removed.
Read a 16-bit word from IO register pair sfr.

Use direct access in new programs.

#define loop_until_bit_is_clear sfr,
bit   )     do { } while (bit_is_set(sfr, bit))
 

 #include <avr/io.h>

Wait until bit bit in IO register sfr is clear.

#define loop_until_bit_is_set sfr,
bit   )     do { } while (bit_is_clear(sfr, bit))
 

 #include <avr/io.h>

Wait until bit bit in IO register sfr is set.

#define outb sfr,
val   )     (_SFR_BYTE(sfr) = (val))
 

Deprecated:
 #include <avr/io.h>
For backwards compatibility only. This macro will eventually be removed.

Use direct access in new programs.
Note:
The order of the arguments was switched in older versions of avr-libc (versions <= 20020203).

#define outp val,
sfr   )     outb(sfr, val)
 

Deprecated:
For backwards compatibility only. This macro will eventually be removed.
Use direct access in new programs.

#define outw sfr,
val   )     (_SFR_WORD(sfr) = (val))
 

Deprecated:
 #include <avr/io.h>
For backwards compatibility only. This macro will eventually be removed.
Write the 16-bit value val to IO register pair sfr. Care will be taken to write the lower register first. When used to update 16-bit registers where the timing is critical and the operation can be interrupted, the programmer is the responsible for disabling interrupts before accessing the register pair.

Use direct access in new programs.
Note:
The order of the arguments was switched in older versions of avr-libc (versions <= 20020203).

#define sbi sfr,
bit   )     (_SFR_BYTE(sfr) |= _BV(bit))
 

Deprecated:
 #include <avr/io.h>
For backwards compatibility only. This macro will eventually be removed.
Set bit bit in IO register sfr.


Automatically generated by Doxygen 1.3.3 on 8 Oct 2003.