$treeview $search $mathjax $extrastylesheet
avr-libc  2.0.0
$projectbrief
$projectbrief
$searchbox

AVR Libc Home Page

AVRs

AVR Libc Development Pages

Main Page

User Manual

Library Reference

FAQ

Example Projects

sfr_defs.h

00001 /* Copyright (c) 2002, Marek Michalkiewicz <marekm@amelek.gda.pl>
00002    All rights reserved.
00003 
00004    Redistribution and use in source and binary forms, with or without
00005    modification, are permitted provided that the following conditions are met:
00006 
00007    * Redistributions of source code must retain the above copyright
00008      notice, this list of conditions and the following disclaimer.
00009 
00010    * Redistributions in binary form must reproduce the above copyright
00011      notice, this list of conditions and the following disclaimer in
00012      the documentation and/or other materials provided with the
00013      distribution.
00014 
00015    * Neither the name of the copyright holders nor the names of
00016      contributors may be used to endorse or promote products derived
00017      from this software without specific prior written permission.
00018 
00019    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00023    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00024    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00025    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00026    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00027    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00028    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029    POSSIBILITY OF SUCH DAMAGE.  */
00030 
00031 /* avr/sfr_defs.h - macros for accessing AVR special function registers */
00032 
00033 /* $Id$ */
00034 
00035 #ifndef _AVR_SFR_DEFS_H_
00036 #define _AVR_SFR_DEFS_H_ 1
00037 
00038 /** \defgroup avr_sfr_notes Additional notes from <avr/sfr_defs.h>
00039     \ingroup avr_sfr
00040 
00041    The \c <avr/sfr_defs.h> file is included by all of the \c <avr/ioXXXX.h>
00042    files, which use macros defined here to make the special function register
00043    definitions look like C variables or simple constants, depending on the
00044    <tt>_SFR_ASM_COMPAT</tt> define.  Some examples from \c <avr/iocanxx.h> to
00045    show how to define such macros:
00046 
00047 \code
00048 #define PORTA   _SFR_IO8(0x02)
00049 #define EEAR    _SFR_IO16(0x21)
00050 #define UDR0    _SFR_MEM8(0xC6)
00051 #define TCNT3   _SFR_MEM16(0x94)
00052 #define CANIDT  _SFR_MEM32(0xF0)
00053 \endcode
00054 
00055    If \c _SFR_ASM_COMPAT is not defined, C programs can use names like
00056    <tt>PORTA</tt> directly in C expressions (also on the left side of
00057    assignment operators) and GCC will do the right thing (use short I/O
00058    instructions if possible).  The \c __SFR_OFFSET definition is not used in
00059    any way in this case.
00060 
00061    Define \c _SFR_ASM_COMPAT as 1 to make these names work as simple constants
00062    (addresses of the I/O registers).  This is necessary when included in
00063    preprocessed assembler (*.S) source files, so it is done automatically if
00064    \c __ASSEMBLER__ is defined.  By default, all addresses are defined as if
00065    they were memory addresses (used in \c lds/sts instructions).  To use these
00066    addresses in \c in/out instructions, you must subtract 0x20 from them.
00067 
00068    For more backwards compatibility, insert the following at the start of your
00069    old assembler source file:
00070 
00071 \code
00072 #define __SFR_OFFSET 0
00073 \endcode
00074 
00075    This automatically subtracts 0x20 from I/O space addresses, but it's a
00076    hack, so it is recommended to change your source: wrap such addresses in
00077    macros defined here, as shown below.  After this is done, the
00078    <tt>__SFR_OFFSET</tt> definition is no longer necessary and can be removed.
00079 
00080    Real example - this code could be used in a boot loader that is portable
00081    between devices with \c SPMCR at different addresses.
00082 
00083 \verbatim
00084 <avr/iom163.h>: #define SPMCR _SFR_IO8(0x37)
00085 <avr/iom128.h>: #define SPMCR _SFR_MEM8(0x68)
00086 \endverbatim
00087 
00088 \code
00089 #if _SFR_IO_REG_P(SPMCR)
00090     out _SFR_IO_ADDR(SPMCR), r24
00091 #else
00092     sts _SFR_MEM_ADDR(SPMCR), r24
00093 #endif
00094 \endcode
00095 
00096    You can use the \c in/out/cbi/sbi/sbic/sbis instructions, without the
00097    <tt>_SFR_IO_REG_P</tt> test, if you know that the register is in the I/O
00098    space (as with \c SREG, for example).  If it isn't, the assembler will
00099    complain (I/O address out of range 0...0x3f), so this should be fairly
00100    safe.
00101 
00102    If you do not define \c __SFR_OFFSET (so it will be 0x20 by default), all
00103    special register addresses are defined as memory addresses (so \c SREG is
00104    0x5f), and (if code size and speed are not important, and you don't like
00105    the ugly \#if above) you can always use lds/sts to access them.  But, this
00106    will not work if <tt>__SFR_OFFSET</tt> != 0x20, so use a different macro
00107    (defined only if <tt>__SFR_OFFSET</tt> == 0x20) for safety:
00108 
00109 \code
00110     sts _SFR_ADDR(SPMCR), r24
00111 \endcode
00112 
00113    In C programs, all 3 combinations of \c _SFR_ASM_COMPAT and
00114    <tt>__SFR_OFFSET</tt> are supported - the \c _SFR_ADDR(SPMCR) macro can be
00115    used to get the address of the \c SPMCR register (0x57 or 0x68 depending on
00116    device). */
00117 
00118 #ifdef __ASSEMBLER__
00119 #define _SFR_ASM_COMPAT 1
00120 #elif !defined(_SFR_ASM_COMPAT)
00121 #define _SFR_ASM_COMPAT 0
00122 #endif
00123 
00124 #ifndef __ASSEMBLER__
00125 /* These only work in C programs.  */
00126 #include <inttypes.h>
00127 
00128 #define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
00129 #define _MMIO_WORD(mem_addr) (*(volatile uint16_t *)(mem_addr))
00130 #define _MMIO_DWORD(mem_addr) (*(volatile uint32_t *)(mem_addr))
00131 #endif
00132 
00133 #if _SFR_ASM_COMPAT
00134 
00135 #ifndef __SFR_OFFSET
00136 /* Define as 0 before including this file for compatibility with old asm
00137    sources that don't subtract __SFR_OFFSET from symbolic I/O addresses.  */
00138 #  if __AVR_ARCH__ >= 100
00139 #    define __SFR_OFFSET 0x00
00140 #  else
00141 #    define __SFR_OFFSET 0x20
00142 #  endif
00143 #endif
00144 
00145 #if (__SFR_OFFSET != 0) && (__SFR_OFFSET != 0x20)
00146 #error "__SFR_OFFSET must be 0 or 0x20"
00147 #endif
00148 
00149 #define _SFR_MEM8(mem_addr) (mem_addr)
00150 #define _SFR_MEM16(mem_addr) (mem_addr)
00151 #define _SFR_MEM32(mem_addr) (mem_addr)
00152 #define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)
00153 #define _SFR_IO16(io_addr) ((io_addr) + __SFR_OFFSET)
00154 
00155 #define _SFR_IO_ADDR(sfr) ((sfr) - __SFR_OFFSET)
00156 #define _SFR_MEM_ADDR(sfr) (sfr)
00157 #define _SFR_IO_REG_P(sfr) ((sfr) < 0x40 + __SFR_OFFSET)
00158 
00159 #if (__SFR_OFFSET == 0x20)
00160 /* No need to use ?: operator, so works in assembler too.  */
00161 #define _SFR_ADDR(sfr) _SFR_MEM_ADDR(sfr)
00162 #elif !defined(__ASSEMBLER__)
00163 #define _SFR_ADDR(sfr) (_SFR_IO_REG_P(sfr) ? (_SFR_IO_ADDR(sfr) + 0x20) : _SFR_MEM_ADDR(sfr))
00164 #endif
00165 
00166 #else  /* !_SFR_ASM_COMPAT */
00167 
00168 #ifndef __SFR_OFFSET
00169 #  if __AVR_ARCH__ >= 100
00170 #    define __SFR_OFFSET 0x00
00171 #  else
00172 #    define __SFR_OFFSET 0x20
00173 #  endif
00174 #endif
00175 
00176 #define _SFR_MEM8(mem_addr) _MMIO_BYTE(mem_addr)
00177 #define _SFR_MEM16(mem_addr) _MMIO_WORD(mem_addr)
00178 #define _SFR_MEM32(mem_addr) _MMIO_DWORD(mem_addr)
00179 #define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)
00180 #define _SFR_IO16(io_addr) _MMIO_WORD((io_addr) + __SFR_OFFSET)
00181 
00182 #define _SFR_MEM_ADDR(sfr) ((uint16_t) &(sfr))
00183 #define _SFR_IO_ADDR(sfr) (_SFR_MEM_ADDR(sfr) - __SFR_OFFSET)
00184 #define _SFR_IO_REG_P(sfr) (_SFR_MEM_ADDR(sfr) < 0x40 + __SFR_OFFSET)
00185 
00186 #define _SFR_ADDR(sfr) _SFR_MEM_ADDR(sfr)
00187 
00188 #endif /* !_SFR_ASM_COMPAT */
00189 
00190 #define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr))
00191 #define _SFR_WORD(sfr) _MMIO_WORD(_SFR_ADDR(sfr))
00192 #define _SFR_DWORD(sfr) _MMIO_DWORD(_SFR_ADDR(sfr))
00193 
00194 /** \name Bit manipulation */
00195 
00196 /*@{*/
00197 /** \def _BV
00198     \ingroup avr_sfr
00199 
00200     \code #include <avr/io.h>\endcode
00201 
00202     Converts a bit number into a byte value.
00203 
00204     \note The bit shift is performed by the compiler which then inserts the
00205     result into the code. Thus, there is no run-time overhead when using
00206     _BV(). */
00207     
00208 #define _BV(bit) (1 << (bit))
00209 
00210 /*@}*/
00211 
00212 #ifndef _VECTOR
00213 #define _VECTOR(N) __vector_ ## N
00214 #endif
00215 
00216 #ifndef __ASSEMBLER__
00217 
00218 
00219 /** \name IO register bit manipulation */
00220 
00221 /*@{*/
00222 
00223 
00224 
00225 /** \def bit_is_set
00226     \ingroup avr_sfr
00227 
00228     \code #include <avr/io.h>\endcode
00229 
00230     Test whether bit \c bit in IO register \c sfr is set. 
00231     This will return a 0 if the bit is clear, and non-zero
00232     if the bit is set. */
00233 
00234 #define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit))
00235 
00236 /** \def bit_is_clear
00237     \ingroup avr_sfr
00238 
00239     \code #include <avr/io.h>\endcode
00240 
00241     Test whether bit \c bit in IO register \c sfr is clear. 
00242     This will return non-zero if the bit is clear, and a 0
00243     if the bit is set. */
00244 
00245 #define bit_is_clear(sfr, bit) (!(_SFR_BYTE(sfr) & _BV(bit)))
00246 
00247 /** \def loop_until_bit_is_set
00248     \ingroup avr_sfr
00249 
00250     \code #include <avr/io.h>\endcode
00251 
00252     Wait until bit \c bit in IO register \c sfr is set. */
00253 
00254 #define loop_until_bit_is_set(sfr, bit) do { } while (bit_is_clear(sfr, bit))
00255 
00256 /** \def loop_until_bit_is_clear
00257     \ingroup avr_sfr
00258 
00259     \code #include <avr/io.h>\endcode
00260 
00261     Wait until bit \c bit in IO register \c sfr is clear. */
00262 
00263 #define loop_until_bit_is_clear(sfr, bit) do { } while (bit_is_set(sfr, bit))
00264 
00265 /*@}*/
00266 
00267 #endif /* !__ASSEMBLER__ */
00268 
00269 #endif  /* _SFR_DEFS_H_ */
 All Data Structures Files Functions Variables Typedefs Enumerations Defines