summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/avr/avr/fuse.h
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/cpu/avr/avr/fuse.h')
-rw-r--r--cpukit/score/cpu/avr/avr/fuse.h269
1 files changed, 269 insertions, 0 deletions
diff --git a/cpukit/score/cpu/avr/avr/fuse.h b/cpukit/score/cpu/avr/avr/fuse.h
new file mode 100644
index 0000000000..7aa4f92a18
--- /dev/null
+++ b/cpukit/score/cpu/avr/avr/fuse.h
@@ -0,0 +1,269 @@
+/* Copyright (c) 2007, Atmel Corporation
+ 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.
+
+ * Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ 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$ */
+
+/* avr/fuse.h - Fuse API */
+
+#ifndef _AVR_FUSE_H_
+#define _AVR_FUSE_H_ 1
+
+/* This file must be explicitly included by <avr/io.h>. */
+#if !defined(_AVR_IO_H_)
+#error "You must #include <avr/io.h> and not <avr/fuse.h> by itself."
+#endif
+
+
+/** \file */
+/** \defgroup avr_fuse <avr/fuse.h>: Fuse Support
+
+ \par Introduction
+
+ The Fuse API allows a user to specify the fuse settings for the specific
+ AVR device they are compiling for. These fuse settings will be placed
+ in a special section in the ELF output file, after linking.
+
+ Programming tools can take advantage of the fuse information embedded in
+ the ELF file, by extracting this information and determining if the fuses
+ need to be programmed before programming the Flash and EEPROM memories.
+ This also allows a single ELF file to contain all the
+ information needed to program an AVR.
+
+ To use the Fuse API, include the <avr/io.h> header file, which in turn
+ automatically includes the individual I/O header file and the <avr/fuse.h>
+ file. These other two files provides everything necessary to set the AVR
+ fuses.
+
+ \par Fuse API
+
+ Each I/O header file must define the FUSE_MEMORY_SIZE macro which is
+ defined to the number of fuse bytes that exist in the AVR device.
+
+ A new type, __fuse_t, is defined as a structure. The number of fields in
+ this structure are determined by the number of fuse bytes in the
+ FUSE_MEMORY_SIZE macro.
+
+ If FUSE_MEMORY_SIZE == 1, there is only a single field: byte, of type
+ unsigned char.
+
+ If FUSE_MEMORY_SIZE == 2, there are two fields: low, and high, of type
+ unsigned char.
+
+ If FUSE_MEMORY_SIZE == 3, there are three fields: low, high, and extended,
+ of type unsigned char.
+
+ If FUSE_MEMORY_SIZE > 3, there is a single field: byte, which is an array
+ of unsigned char with the size of the array being FUSE_MEMORY_SIZE.
+
+ A convenience macro, FUSEMEM, is defined as a GCC attribute for a
+ custom-named section of ".fuse".
+
+ A convenience macro, FUSES, is defined that declares a variable, __fuse, of
+ type __fuse_t with the attribute defined by FUSEMEM. This variable
+ allows the end user to easily set the fuse data.
+
+ \note If a device-specific I/O header file has previously defined FUSEMEM,
+ then FUSEMEM is not redefined. If a device-specific I/O header file has
+ previously defined FUSES, then FUSES is not redefined.
+
+ Each AVR device I/O header file has a set of defined macros which specify the
+ actual fuse bits available on that device. The AVR fuses have inverted
+ values, logical 1 for an unprogrammed (disabled) bit and logical 0 for a
+ programmed (enabled) bit. The defined macros for each individual fuse
+ bit represent this in their definition by a bit-wise inversion of a mask.
+ For example, the FUSE_EESAVE fuse in the ATmega128 is defined as:
+ \code
+ #define FUSE_EESAVE ~_BV(3)
+ \endcode
+ \note The _BV macro creates a bit mask from a bit number. It is then
+ inverted to represent logical values for a fuse memory byte.
+
+ To combine the fuse bits macros together to represent a whole fuse byte,
+ use the bitwise AND operator, like so:
+ \code
+ (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN)
+ \endcode
+
+ Each device I/O header file also defines macros that provide default values
+ for each fuse byte that is available. LFUSE_DEFAULT is defined for a Low
+ Fuse byte. HFUSE_DEFAULT is defined for a High Fuse byte. EFUSE_DEFAULT
+ is defined for an Extended Fuse byte.
+
+ If FUSE_MEMORY_SIZE > 3, then the I/O header file defines macros that
+ provide default values for each fuse byte like so:
+ FUSE0_DEFAULT
+ FUSE1_DEFAULT
+ FUSE2_DEFAULT
+ FUSE3_DEFAULT
+ FUSE4_DEFAULT
+ ....
+
+ \par API Usage Example
+
+ Putting all of this together is easy. Using C99's designated initializers:
+
+ \code
+ #include <avr/io.h>
+
+ FUSES =
+ {
+ .low = LFUSE_DEFAULT,
+ .high = (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN),
+ .extended = EFUSE_DEFAULT,
+ };
+
+ int main(void)
+ {
+ return 0;
+ }
+ \endcode
+
+ Or, using the variable directly instead of the FUSES macro,
+
+ \code
+ #include <avr/io.h>
+
+ __fuse_t __fuse __attribute__((section (".fuse"))) =
+ {
+ .low = LFUSE_DEFAULT,
+ .high = (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN),
+ .extended = EFUSE_DEFAULT,
+ };
+
+ int main(void)
+ {
+ return 0;
+ }
+ \endcode
+
+ If you are compiling in C++, you cannot use the designated intializers so
+ you must do:
+
+ \code
+ #include <avr/io.h>
+
+ FUSES =
+ {
+ LFUSE_DEFAULT, // .low
+ (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN), // .high
+ EFUSE_DEFAULT, // .extended
+ };
+
+ int main(void)
+ {
+ return 0;
+ }
+ \endcode
+
+
+ However there are a number of caveats that you need to be aware of to
+ use this API properly.
+
+ Be sure to include <avr/io.h> to get all of the definitions for the API.
+ The FUSES macro defines a global variable to store the fuse data. This
+ variable is assigned to its own linker section. Assign the desired fuse
+ values immediately in the variable initialization.
+
+ The .fuse section in the ELF file will get its values from the initial
+ variable assignment ONLY. This means that you can NOT assign values to
+ this variable in functions and the new values will not be put into the
+ ELF .fuse section.
+
+ The global variable is declared in the FUSES macro has two leading
+ underscores, which means that it is reserved for the "implementation",
+ meaning the library, so it will not conflict with a user-named variable.
+
+ You must initialize ALL fields in the __fuse_t structure. This is because
+ the fuse bits in all bytes default to a logical 1, meaning unprogrammed.
+ Normal uninitialized data defaults to all locgial zeros. So it is vital that
+ all fuse bytes are initialized, even with default data. If they are not,
+ then the fuse bits may not programmed to the desired settings.
+
+ Be sure to have the -mmcu=<em>device</em> flag in your compile command line and
+ your linker command line to have the correct device selected and to have
+ the correct I/O header file included when you include <avr/io.h>.
+
+ You can print out the contents of the .fuse section in the ELF file by
+ using this command line:
+ \code
+ avr-objdump -s -j .fuse <ELF file>
+ \endcode
+ The section contents shows the address on the left, then the data going from
+ lower address to a higher address, left to right.
+
+*/
+
+#ifndef __ASSEMBLER__
+
+#ifndef FUSEMEM
+#define FUSEMEM __attribute__((section (".fuse")))
+#endif
+
+#if FUSE_MEMORY_SIZE > 3
+
+typedef struct
+{
+ unsigned char byte[FUSE_MEMORY_SIZE];
+} __fuse_t;
+
+
+#elif FUSE_MEMORY_SIZE == 3
+
+typedef struct
+{
+ unsigned char low;
+ unsigned char high;
+ unsigned char extended;
+} __fuse_t;
+
+#elif FUSE_MEMORY_SIZE == 2
+
+typedef struct
+{
+ unsigned char low;
+ unsigned char high;
+} __fuse_t;
+
+#elif FUSE_MEMORY_SIZE == 1
+
+typedef struct
+{
+ unsigned char byte;
+} __fuse_t;
+
+#endif
+
+#ifndef FUSES
+#define FUSES __fuse_t __fuse FUSEMEM
+#endif
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* _AVR_FUSE_H_ */