AVR Libc Home Page | AVR Libc Development Pages | ||||
Main Page | User Manual | Library Reference | FAQ | Alphabetical Index | Example Projects |
00001 /* Copyright (c) 2007, Atmel Corporation 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 /* $Id: fuse.h 2107 2010-03-20 18:00:47Z arcanum $ */ 00032 00033 /* avr/fuse.h - Fuse API */ 00034 00035 #ifndef _AVR_FUSE_H_ 00036 #define _AVR_FUSE_H_ 1 00037 00038 /* This file must be explicitly included by <avr/io.h>. */ 00039 #if !defined(_AVR_IO_H_) 00040 #error "You must #include <avr/io.h> and not <avr/fuse.h> by itself." 00041 #endif 00042 00043 00044 /** \file */ 00045 /** \defgroup avr_fuse <avr/fuse.h>: Fuse Support 00046 00047 \par Introduction 00048 00049 The Fuse API allows a user to specify the fuse settings for the specific 00050 AVR device they are compiling for. These fuse settings will be placed 00051 in a special section in the ELF output file, after linking. 00052 00053 Programming tools can take advantage of the fuse information embedded in 00054 the ELF file, by extracting this information and determining if the fuses 00055 need to be programmed before programming the Flash and EEPROM memories. 00056 This also allows a single ELF file to contain all the 00057 information needed to program an AVR. 00058 00059 To use the Fuse API, include the <avr/io.h> header file, which in turn 00060 automatically includes the individual I/O header file and the <avr/fuse.h> 00061 file. These other two files provides everything necessary to set the AVR 00062 fuses. 00063 00064 \par Fuse API 00065 00066 Each I/O header file must define the FUSE_MEMORY_SIZE macro which is 00067 defined to the number of fuse bytes that exist in the AVR device. 00068 00069 A new type, __fuse_t, is defined as a structure. The number of fields in 00070 this structure are determined by the number of fuse bytes in the 00071 FUSE_MEMORY_SIZE macro. 00072 00073 If FUSE_MEMORY_SIZE == 1, there is only a single field: byte, of type 00074 unsigned char. 00075 00076 If FUSE_MEMORY_SIZE == 2, there are two fields: low, and high, of type 00077 unsigned char. 00078 00079 If FUSE_MEMORY_SIZE == 3, there are three fields: low, high, and extended, 00080 of type unsigned char. 00081 00082 If FUSE_MEMORY_SIZE > 3, there is a single field: byte, which is an array 00083 of unsigned char with the size of the array being FUSE_MEMORY_SIZE. 00084 00085 A convenience macro, FUSEMEM, is defined as a GCC attribute for a 00086 custom-named section of ".fuse". 00087 00088 A convenience macro, FUSES, is defined that declares a variable, __fuse, of 00089 type __fuse_t with the attribute defined by FUSEMEM. This variable 00090 allows the end user to easily set the fuse data. 00091 00092 \note If a device-specific I/O header file has previously defined FUSEMEM, 00093 then FUSEMEM is not redefined. If a device-specific I/O header file has 00094 previously defined FUSES, then FUSES is not redefined. 00095 00096 Each AVR device I/O header file has a set of defined macros which specify the 00097 actual fuse bits available on that device. The AVR fuses have inverted 00098 values, logical 1 for an unprogrammed (disabled) bit and logical 0 for a 00099 programmed (enabled) bit. The defined macros for each individual fuse 00100 bit represent this in their definition by a bit-wise inversion of a mask. 00101 For example, the FUSE_EESAVE fuse in the ATmega128 is defined as: 00102 \code 00103 #define FUSE_EESAVE ~_BV(3) 00104 \endcode 00105 \note The _BV macro creates a bit mask from a bit number. It is then 00106 inverted to represent logical values for a fuse memory byte. 00107 00108 To combine the fuse bits macros together to represent a whole fuse byte, 00109 use the bitwise AND operator, like so: 00110 \code 00111 (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN) 00112 \endcode 00113 00114 Each device I/O header file also defines macros that provide default values 00115 for each fuse byte that is available. LFUSE_DEFAULT is defined for a Low 00116 Fuse byte. HFUSE_DEFAULT is defined for a High Fuse byte. EFUSE_DEFAULT 00117 is defined for an Extended Fuse byte. 00118 00119 If FUSE_MEMORY_SIZE > 3, then the I/O header file defines macros that 00120 provide default values for each fuse byte like so: 00121 FUSE0_DEFAULT 00122 FUSE1_DEFAULT 00123 FUSE2_DEFAULT 00124 FUSE3_DEFAULT 00125 FUSE4_DEFAULT 00126 .... 00127 00128 \par API Usage Example 00129 00130 Putting all of this together is easy. Using C99's designated initializers: 00131 00132 \code 00133 #include <avr/io.h> 00134 00135 FUSES = 00136 { 00137 .low = LFUSE_DEFAULT, 00138 .high = (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN), 00139 .extended = EFUSE_DEFAULT, 00140 }; 00141 00142 int main(void) 00143 { 00144 return 0; 00145 } 00146 \endcode 00147 00148 Or, using the variable directly instead of the FUSES macro, 00149 00150 \code 00151 #include <avr/io.h> 00152 00153 __fuse_t __fuse __attribute__((section (".fuse"))) = 00154 { 00155 .low = LFUSE_DEFAULT, 00156 .high = (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN), 00157 .extended = EFUSE_DEFAULT, 00158 }; 00159 00160 int main(void) 00161 { 00162 return 0; 00163 } 00164 \endcode 00165 00166 If you are compiling in C++, you cannot use the designated intializers so 00167 you must do: 00168 00169 \code 00170 #include <avr/io.h> 00171 00172 FUSES = 00173 { 00174 LFUSE_DEFAULT, // .low 00175 (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN), // .high 00176 EFUSE_DEFAULT, // .extended 00177 }; 00178 00179 int main(void) 00180 { 00181 return 0; 00182 } 00183 \endcode 00184 00185 00186 However there are a number of caveats that you need to be aware of to 00187 use this API properly. 00188 00189 Be sure to include <avr/io.h> to get all of the definitions for the API. 00190 The FUSES macro defines a global variable to store the fuse data. This 00191 variable is assigned to its own linker section. Assign the desired fuse 00192 values immediately in the variable initialization. 00193 00194 The .fuse section in the ELF file will get its values from the initial 00195 variable assignment ONLY. This means that you can NOT assign values to 00196 this variable in functions and the new values will not be put into the 00197 ELF .fuse section. 00198 00199 The global variable is declared in the FUSES macro has two leading 00200 underscores, which means that it is reserved for the "implementation", 00201 meaning the library, so it will not conflict with a user-named variable. 00202 00203 You must initialize ALL fields in the __fuse_t structure. This is because 00204 the fuse bits in all bytes default to a logical 1, meaning unprogrammed. 00205 Normal uninitialized data defaults to all locgial zeros. So it is vital that 00206 all fuse bytes are initialized, even with default data. If they are not, 00207 then the fuse bits may not programmed to the desired settings. 00208 00209 Be sure to have the -mmcu=<em>device</em> flag in your compile command line and 00210 your linker command line to have the correct device selected and to have 00211 the correct I/O header file included when you include <avr/io.h>. 00212 00213 You can print out the contents of the .fuse section in the ELF file by 00214 using this command line: 00215 \code 00216 avr-objdump -s -j .fuse <ELF file> 00217 \endcode 00218 The section contents shows the address on the left, then the data going from 00219 lower address to a higher address, left to right. 00220 00221 */ 00222 00223 #ifndef __ASSEMBLER__ 00224 00225 #ifndef FUSEMEM 00226 #define FUSEMEM __attribute__((section (".fuse"))) 00227 #endif 00228 00229 #if FUSE_MEMORY_SIZE > 3 00230 00231 typedef struct 00232 { 00233 unsigned char byte[FUSE_MEMORY_SIZE]; 00234 } __fuse_t; 00235 00236 00237 #elif FUSE_MEMORY_SIZE == 3 00238 00239 typedef struct 00240 { 00241 unsigned char low; 00242 unsigned char high; 00243 unsigned char extended; 00244 } __fuse_t; 00245 00246 #elif FUSE_MEMORY_SIZE == 2 00247 00248 typedef struct 00249 { 00250 unsigned char low; 00251 unsigned char high; 00252 } __fuse_t; 00253 00254 #elif FUSE_MEMORY_SIZE == 1 00255 00256 typedef struct 00257 { 00258 unsigned char byte; 00259 } __fuse_t; 00260 00261 #endif 00262 00263 #if !defined(FUSES) 00264 #if defined(__AVR_XMEGA__) 00265 #define FUSES NVM_FUSES_t __fuse FUSEMEM 00266 #else 00267 #define FUSES __fuse_t __fuse FUSEMEM 00268 #endif 00269 #endif 00270 00271 00272 #endif /* !__ASSEMBLER__ */ 00273 00274 #endif /* _AVR_FUSE_H_ */