1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
/* Copyright (c) 2002, Joerg Wunsch
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */
/* $Id: sfr.dox,v 1.6 2005/08/14 21:44:54 joerg_wunsch Exp $ */
/** \defgroup avr_sfr <avr/sfr_defs.h>: Special function registers
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 (\c in, \c out, \c sbi etc.). The entire IO
address space is also made available as <em>memory-mapped IO</em>,
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 \c outb():
\code
#include <avr/io.h>
outb(PORTA, 0x33);
\endcode
or they can assign a value directly to the symbolic address:
\code
PORTA = 0x33;
\endcode
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
\code
PORTA |= 0x40;
\endcode
the compiler can optimize this into the use of an \c 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:
\code
outb(DDRD, inb(DDRD) & ~LCDBITS);
DDRD &= ~LCDBITS;
\endcode
The generated code is identical for both. Without optimization, the
compiler strictly generates code following the memory-mapped paradigm,
while with optimization turned on, code is generated using the (faster
and smaller) \c 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 \ref faq_16bitio.
\par Porting programs that use sbi/cbi
As described above, access to the AVR single bit set and clear instructions
are provided via the standard C bit manipulation commands. The sbi and cbi
commands are no longer directly supported.
sbi (sfr,bit) can be replaced by sfr |= _BV(bit) .
ie: sbi(PORTB, PB1); is now PORTB |= _BV(PB1);
This actually is more flexible than having sbi directly, as the optimizer
will use a hardware sbi if appropriate, or a read/or/write if not. You do
not need to keep track of which registers sbi/cbi will operate on.
Likewise, cbi (sfr,bit) is now sfr &= ~(_BV(bit));
*/
|