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.h85
1 files changed, 45 insertions, 40 deletions
diff --git a/cpukit/score/cpu/avr/avr/fuse.h b/cpukit/score/cpu/avr/avr/fuse.h
index 3ba09366f0..7aa4f92a18 100644
--- a/cpukit/score/cpu/avr/avr/fuse.h
+++ b/cpukit/score/cpu/avr/avr/fuse.h
@@ -35,6 +35,11 @@
#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
@@ -49,37 +54,37 @@
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.
+ 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
+
+ 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
+
+ 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.
@@ -97,20 +102,20 @@
\code
#define FUSE_EESAVE ~_BV(3)
\endcode
- \note The _BV macro creates a bit mask from a bit number. It is then
+ \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
@@ -119,15 +124,15 @@
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 =
+ FUSES =
{
.low = LFUSE_DEFAULT,
.high = (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN),
@@ -139,13 +144,13 @@
return 0;
}
\endcode
-
+
Or, using the variable directly instead of the FUSES macro,
-
+
\code
#include <avr/io.h>
- __fuse_t __fuse __attribute__((section (".fuse"))) =
+ __fuse_t __fuse __attribute__((section (".fuse"))) =
{
.low = LFUSE_DEFAULT,
.high = (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN),
@@ -157,14 +162,14 @@
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 =
+ FUSES =
{
LFUSE_DEFAULT, // .low
(FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN), // .high
@@ -176,33 +181,33 @@
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
+ 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
+
+ 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
+
+ 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.
+ 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
+ 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