AVR Libc Home Page | AVR Libc Development Pages | ||||
Main Page | User Manual | Library Reference | FAQ | Alphabetical Index | Example Projects |
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: sfr_defs.h 1691 2008-04-28 22:05:42Z arcanum $ */ 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_ */