AVR Libc Home Page AVRs AVR Libc Development Pages
Main Page User Manual Library Reference FAQ Alphabetical Index Example Projects

boot.h

Go to the documentation of this file.
00001 /* Copyright (c) 2002,2003,2004,2005,2006,2007,2008,2009  Eric B. Weddington
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    * Redistributions in binary form must reproduce the above copyright
00010      notice, this list of conditions and the following disclaimer in
00011      the documentation and/or other materials provided with the
00012      distribution.
00013    * Neither the name of the copyright holders nor the names of
00014      contributors may be used to endorse or promote products derived
00015      from this software without specific prior written permission.
00016 
00017   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027   POSSIBILITY OF SUCH DAMAGE. */
00028 
00029 /* $Id$ */
00030 
00031 #ifndef _AVR_BOOT_H_
00032 #define _AVR_BOOT_H_    1
00033 
00034 /** \file */
00035 /** \defgroup avr_boot <avr/boot.h>: Bootloader Support Utilities
00036     \code
00037     #include <avr/io.h>
00038     #include <avr/boot.h>
00039     \endcode
00040 
00041     The macros in this module provide a C language interface to the
00042     bootloader support functionality of certain AVR processors. These
00043     macros are designed to work with all sizes of flash memory.
00044 
00045     Global interrupts are not automatically disabled for these macros. It
00046     is left up to the programmer to do this. See the code example below. 
00047     Also see the processor datasheet for caveats on having global interrupts 
00048     enabled during writing of the Flash.
00049 
00050     \note Not all AVR processors provide bootloader support. See your
00051     processor datasheet to see if it provides bootloader support.
00052 
00053     \todo From email with Marek: On smaller devices (all except ATmega64/128),
00054     __SPM_REG is in the I/O space, accessible with the shorter "in" and "out"
00055     instructions - since the boot loader has a limited size, this could be an
00056     important optimization.
00057 
00058     \par API Usage Example
00059     The following code shows typical usage of the boot API.
00060 
00061     \code
00062     #include <inttypes.h>
00063     #include <avr/interrupt.h>
00064     #include <avr/pgmspace.h>
00065     
00066     void boot_program_page (uint32_t page, uint8_t *buf)
00067     {
00068         uint16_t i;
00069         uint8_t sreg;
00070 
00071         // Disable interrupts.
00072 
00073         sreg = SREG;
00074         cli();
00075     
00076         eeprom_busy_wait ();
00077 
00078         boot_page_erase (page);
00079         boot_spm_busy_wait ();      // Wait until the memory is erased.
00080 
00081         for (i=0; i<SPM_PAGESIZE; i+=2)
00082         {
00083             // Set up little-endian word.
00084 
00085             uint16_t w = *buf++;
00086             w += (*buf++) << 8;
00087         
00088             boot_page_fill (page + i, w);
00089         }
00090 
00091         boot_page_write (page);     // Store buffer in flash page.
00092         boot_spm_busy_wait();       // Wait until the memory is written.
00093 
00094         // Reenable RWW-section again. We need this if we want to jump back
00095         // to the application after bootloading.
00096 
00097         boot_rww_enable ();
00098 
00099         // Re-enable interrupts (if they were ever enabled).
00100 
00101         SREG = sreg;
00102     }\endcode */
00103 
00104 #include <avr/eeprom.h>
00105 #include <avr/io.h>
00106 #include <inttypes.h>
00107 #include <limits.h>
00108 
00109 /* Check for SPM Control Register in processor. */
00110 #if defined (SPMCSR)
00111 #  define __SPM_REG    SPMCSR
00112 #else
00113 #  if defined (SPMCR)
00114 #    define __SPM_REG    SPMCR
00115 #  else
00116 #    error AVR processor does not provide bootloader support!
00117 #  endif
00118 #endif
00119 
00120 
00121 /* Check for SPM Enable bit. */
00122 #if defined(SPMEN)
00123 #  define __SPM_ENABLE  SPMEN
00124 #elif defined(SELFPRGEN)
00125 #  define __SPM_ENABLE  SELFPRGEN
00126 #else
00127 #  error Cannot find SPM Enable bit definition!
00128 #endif
00129 
00130 /** \ingroup avr_boot
00131     \def BOOTLOADER_SECTION
00132 
00133     Used to declare a function or variable to be placed into a
00134     new section called .bootloader. This section and its contents
00135     can then be relocated to any address (such as the bootloader
00136     NRWW area) at link-time. */
00137 
00138 #define BOOTLOADER_SECTION    __attribute__ ((section (".bootloader")))
00139 
00140 /* Create common bit definitions. */
00141 #ifdef ASB
00142 #define __COMMON_ASB    ASB
00143 #else
00144 #define __COMMON_ASB    RWWSB
00145 #endif
00146 
00147 #ifdef ASRE
00148 #define __COMMON_ASRE   ASRE
00149 #else
00150 #define __COMMON_ASRE   RWWSRE
00151 #endif
00152 
00153 /* Define the bit positions of the Boot Lock Bits. */
00154 
00155 #define BLB12           5
00156 #define BLB11           4
00157 #define BLB02           3
00158 #define BLB01           2
00159 
00160 /** \ingroup avr_boot
00161     \def boot_spm_interrupt_enable()
00162     Enable the SPM interrupt. */
00163 
00164 #define boot_spm_interrupt_enable()   (__SPM_REG |= (uint8_t)_BV(SPMIE))
00165 
00166 /** \ingroup avr_boot
00167     \def boot_spm_interrupt_disable()
00168     Disable the SPM interrupt. */
00169 
00170 #define boot_spm_interrupt_disable()  (__SPM_REG &= (uint8_t)~_BV(SPMIE))
00171 
00172 /** \ingroup avr_boot
00173     \def boot_is_spm_interrupt()
00174     Check if the SPM interrupt is enabled. */
00175 
00176 #define boot_is_spm_interrupt()       (__SPM_REG & (uint8_t)_BV(SPMIE))
00177 
00178 /** \ingroup avr_boot
00179     \def boot_rww_busy()
00180     Check if the RWW section is busy. */
00181 
00182 #define boot_rww_busy()          (__SPM_REG & (uint8_t)_BV(__COMMON_ASB))
00183 
00184 /** \ingroup avr_boot
00185     \def boot_spm_busy()
00186     Check if the SPM instruction is busy. */
00187 
00188 #define boot_spm_busy()               (__SPM_REG & (uint8_t)_BV(__SPM_ENABLE))
00189 
00190 /** \ingroup avr_boot
00191     \def boot_spm_busy_wait()
00192     Wait while the SPM instruction is busy. */
00193 
00194 #define boot_spm_busy_wait()          do{}while(boot_spm_busy())
00195 
00196 #define __BOOT_PAGE_ERASE         (_BV(__SPM_ENABLE) | _BV(PGERS))
00197 #define __BOOT_PAGE_WRITE         (_BV(__SPM_ENABLE) | _BV(PGWRT))
00198 #define __BOOT_PAGE_FILL          _BV(__SPM_ENABLE)
00199 #define __BOOT_RWW_ENABLE         (_BV(__SPM_ENABLE) | _BV(__COMMON_ASRE))
00200 #if defined(BLBSET)
00201 #define __BOOT_LOCK_BITS_SET      (_BV(__SPM_ENABLE) | _BV(BLBSET))
00202 #elif defined(RFLB)  /* Some devices have RFLB defined instead of BLBSET. */
00203 #define __BOOT_LOCK_BITS_SET      (_BV(__SPM_ENABLE) | _BV(RFLB))
00204 #endif
00205 
00206 #define __boot_page_fill_normal(address, data)   \
00207 (__extension__({                                 \
00208     __asm__ __volatile__                         \
00209     (                                            \
00210         "movw  r0, %3\n\t"                       \
00211         "sts %0, %1\n\t"                         \
00212         "spm\n\t"                                \
00213         "clr  r1\n\t"                            \
00214         :                                        \
00215         : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
00216           "r" ((uint8_t)(__BOOT_PAGE_FILL)),     \
00217           "z" ((uint16_t)(address)),             \
00218           "r" ((uint16_t)(data))                 \
00219         : "r0"                                   \
00220     );                                           \
00221 }))
00222 
00223 #define __boot_page_fill_alternate(address, data)\
00224 (__extension__({                                 \
00225     __asm__ __volatile__                         \
00226     (                                            \
00227         "movw  r0, %3\n\t"                       \
00228         "sts %0, %1\n\t"                         \
00229         "spm\n\t"                                \
00230         ".word 0xffff\n\t"                       \
00231         "nop\n\t"                                \
00232         "clr  r1\n\t"                            \
00233         :                                        \
00234         : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
00235           "r" ((uint8_t)(__BOOT_PAGE_FILL)),     \
00236           "z" ((uint16_t)(address)),             \
00237           "r" ((uint16_t)(data))                 \
00238         : "r0"                                   \
00239     );                                           \
00240 }))
00241 
00242 #define __boot_page_fill_extended(address, data) \
00243 (__extension__({                                 \
00244     __asm__ __volatile__                         \
00245     (                                            \
00246         "movw  r0, %4\n\t"                       \
00247         "movw r30, %A3\n\t"                      \
00248         "sts %1, %C3\n\t"                        \
00249         "sts %0, %2\n\t"                         \
00250         "spm\n\t"                                \
00251         "clr  r1\n\t"                            \
00252         :                                        \
00253         : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
00254           "i" (_SFR_MEM_ADDR(RAMPZ)),            \
00255           "r" ((uint8_t)(__BOOT_PAGE_FILL)),     \
00256           "r" ((uint32_t)(address)),             \
00257           "r" ((uint16_t)(data))                 \
00258         : "r0", "r30", "r31"                     \
00259     );                                           \
00260 }))
00261 
00262 #define __boot_page_erase_normal(address)        \
00263 (__extension__({                                 \
00264     __asm__ __volatile__                         \
00265     (                                            \
00266         "sts %0, %1\n\t"                         \
00267         "spm\n\t"                                \
00268         :                                        \
00269         : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
00270           "r" ((uint8_t)(__BOOT_PAGE_ERASE)),    \
00271           "z" ((uint16_t)(address))              \
00272     );                                           \
00273 }))
00274 
00275 #define __boot_page_erase_alternate(address)     \
00276 (__extension__({                                 \
00277     __asm__ __volatile__                         \
00278     (                                            \
00279         "sts %0, %1\n\t"                         \
00280         "spm\n\t"                                \
00281         ".word 0xffff\n\t"                       \
00282         "nop\n\t"                                \
00283         :                                        \
00284         : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
00285           "r" ((uint8_t)(__BOOT_PAGE_ERASE)),    \
00286           "z" ((uint16_t)(address))              \
00287     );                                           \
00288 }))
00289 
00290 #define __boot_page_erase_extended(address)      \
00291 (__extension__({                                 \
00292     __asm__ __volatile__                         \
00293     (                                            \
00294         "movw r30, %A3\n\t"                      \
00295         "sts  %1, %C3\n\t"                       \
00296         "sts %0, %2\n\t"                         \
00297         "spm\n\t"                                \
00298         :                                        \
00299         : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
00300           "i" (_SFR_MEM_ADDR(RAMPZ)),            \
00301           "r" ((uint8_t)(__BOOT_PAGE_ERASE)),    \
00302           "r" ((uint32_t)(address))              \
00303         : "r30", "r31"                           \
00304     );                                           \
00305 }))
00306 
00307 #define __boot_page_write_normal(address)        \
00308 (__extension__({                                 \
00309     __asm__ __volatile__                         \
00310     (                                            \
00311         "sts %0, %1\n\t"                         \
00312         "spm\n\t"                                \
00313         :                                        \
00314         : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
00315           "r" ((uint8_t)(__BOOT_PAGE_WRITE)),    \
00316           "z" ((uint16_t)(address))              \
00317     );                                           \
00318 }))
00319 
00320 #define __boot_page_write_alternate(address)     \
00321 (__extension__({                                 \
00322     __asm__ __volatile__                         \
00323     (                                            \
00324         "sts %0, %1\n\t"                         \
00325         "spm\n\t"                                \
00326         ".word 0xffff\n\t"                       \
00327         "nop\n\t"                                \
00328         :                                        \
00329         : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
00330           "r" ((uint8_t)(__BOOT_PAGE_WRITE)),    \
00331           "z" ((uint16_t)(address))              \
00332     );                                           \
00333 }))
00334 
00335 #define __boot_page_write_extended(address)      \
00336 (__extension__({                                 \
00337     __asm__ __volatile__                         \
00338     (                                            \
00339         "movw r30, %A3\n\t"                      \
00340         "sts %1, %C3\n\t"                        \
00341         "sts %0, %2\n\t"                         \
00342         "spm\n\t"                                \
00343         :                                        \
00344         : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
00345           "i" (_SFR_MEM_ADDR(RAMPZ)),            \
00346           "r" ((uint8_t)(__BOOT_PAGE_WRITE)),    \
00347           "r" ((uint32_t)(address))              \
00348         : "r30", "r31"                           \
00349     );                                           \
00350 }))
00351 
00352 #define __boot_rww_enable()                      \
00353 (__extension__({                                 \
00354     __asm__ __volatile__                         \
00355     (                                            \
00356         "sts %0, %1\n\t"                         \
00357         "spm\n\t"                                \
00358         :                                        \
00359         : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
00360           "r" ((uint8_t)(__BOOT_RWW_ENABLE))     \
00361     );                                           \
00362 }))
00363 
00364 #define __boot_rww_enable_alternate()            \
00365 (__extension__({                                 \
00366     __asm__ __volatile__                         \
00367     (                                            \
00368         "sts %0, %1\n\t"                         \
00369         "spm\n\t"                                \
00370         ".word 0xffff\n\t"                       \
00371         "nop\n\t"                                \
00372         :                                        \
00373         : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
00374           "r" ((uint8_t)(__BOOT_RWW_ENABLE))     \
00375     );                                           \
00376 }))
00377 
00378 /* From the mega16/mega128 data sheets (maybe others):
00379 
00380      Bits by SPM To set the Boot Loader Lock bits, write the desired data to
00381      R0, write "X0001001" to SPMCR and execute SPM within four clock cycles
00382      after writing SPMCR. The only accessible Lock bits are the Boot Lock bits
00383      that may prevent the Application and Boot Loader section from any
00384      software update by the MCU.
00385 
00386      If bits 5..2 in R0 are cleared (zero), the corresponding Boot Lock bit
00387      will be programmed if an SPM instruction is executed within four cycles
00388      after BLBSET and SPMEN (or SELFPRGEN) are set in SPMCR. The Z-pointer is 
00389      don't care during this operation, but for future compatibility it is 
00390      recommended to load the Z-pointer with $0001 (same as used for reading the 
00391      Lock bits). For future compatibility It is also recommended to set bits 7, 
00392      6, 1, and 0 in R0 to 1 when writing the Lock bits. When programming the 
00393      Lock bits the entire Flash can be read during the operation. */
00394 
00395 #define __boot_lock_bits_set(lock_bits)                    \
00396 (__extension__({                                           \
00397     uint8_t value = (uint8_t)(~(lock_bits));               \
00398     __asm__ __volatile__                                   \
00399     (                                                      \
00400         "ldi r30, 1\n\t"                                   \
00401         "ldi r31, 0\n\t"                                   \
00402         "mov r0, %2\n\t"                                   \
00403         "sts %0, %1\n\t"                                   \
00404         "spm\n\t"                                          \
00405         :                                                  \
00406         : "i" (_SFR_MEM_ADDR(__SPM_REG)),                  \
00407           "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)),           \
00408           "r" (value)                                      \
00409         : "r0", "r30", "r31"                               \
00410     );                                                     \
00411 }))
00412 
00413 #define __boot_lock_bits_set_alternate(lock_bits)          \
00414 (__extension__({                                           \
00415     uint8_t value = (uint8_t)(~(lock_bits));               \
00416     __asm__ __volatile__                                   \
00417     (                                                      \
00418         "ldi r30, 1\n\t"                                   \
00419         "ldi r31, 0\n\t"                                   \
00420         "mov r0, %2\n\t"                                   \
00421         "sts %0, %1\n\t"                                   \
00422         "spm\n\t"                                          \
00423         ".word 0xffff\n\t"                                 \
00424         "nop\n\t"                                          \
00425         :                                                  \
00426         : "i" (_SFR_MEM_ADDR(__SPM_REG)),                  \
00427           "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)),           \
00428           "r" (value)                                      \
00429         : "r0", "r30", "r31"                               \
00430     );                                                     \
00431 }))
00432 
00433 /*
00434    Reading lock and fuse bits:
00435 
00436      Similarly to writing the lock bits above, set BLBSET and SPMEN (or 
00437      SELFPRGEN) bits in __SPMREG, and then (within four clock cycles) issue an 
00438      LPM instruction.
00439 
00440      Z address:       contents:
00441      0x0000           low fuse bits
00442      0x0001           lock bits
00443      0x0002           extended fuse bits
00444      0x0003           high fuse bits
00445 
00446      Sounds confusing, doesn't it?
00447 
00448      Unlike the macros in pgmspace.h, no need to care for non-enhanced
00449      cores here as these old cores do not provide SPM support anyway.
00450  */
00451 
00452 /** \ingroup avr_boot
00453     \def GET_LOW_FUSE_BITS
00454     address to read the low fuse bits, using boot_lock_fuse_bits_get
00455  */
00456 #define GET_LOW_FUSE_BITS           (0x0000)
00457 /** \ingroup avr_boot
00458     \def GET_LOCK_BITS
00459     address to read the lock bits, using boot_lock_fuse_bits_get
00460  */
00461 #define GET_LOCK_BITS               (0x0001)
00462 /** \ingroup avr_boot
00463     \def GET_EXTENDED_FUSE_BITS
00464     address to read the extended fuse bits, using boot_lock_fuse_bits_get
00465  */
00466 #define GET_EXTENDED_FUSE_BITS      (0x0002)
00467 /** \ingroup avr_boot
00468     \def GET_HIGH_FUSE_BITS
00469     address to read the high fuse bits, using boot_lock_fuse_bits_get
00470  */
00471 #define GET_HIGH_FUSE_BITS          (0x0003)
00472 
00473 /** \ingroup avr_boot
00474     \def boot_lock_fuse_bits_get(address)
00475 
00476     Read the lock or fuse bits at \c address.
00477 
00478     Parameter \c address can be any of GET_LOW_FUSE_BITS,
00479     GET_LOCK_BITS, GET_EXTENDED_FUSE_BITS, or GET_HIGH_FUSE_BITS.
00480 
00481     \note The lock and fuse bits returned are the physical values,
00482     i.e. a bit returned as 0 means the corresponding fuse or lock bit
00483     is programmed.
00484  */
00485 #define boot_lock_fuse_bits_get(address)                   \
00486 (__extension__({                                           \
00487     uint8_t __result;                                      \
00488     __asm__ __volatile__                                   \
00489     (                                                      \
00490         "sts %1, %2\n\t"                                   \
00491         "lpm %0, Z\n\t"                                    \
00492         : "=r" (__result)                                  \
00493         : "i" (_SFR_MEM_ADDR(__SPM_REG)),                  \
00494           "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)),           \
00495           "z" ((uint16_t)(address))                        \
00496     );                                                     \
00497     __result;                                              \
00498 }))
00499 
00500 /** \ingroup avr_boot
00501     \def boot_signature_byte_get(address)
00502 
00503     Read the Signature Row byte at \c address.  For some MCU types,
00504     this function can also retrieve the factory-stored oscillator
00505     calibration bytes.
00506 
00507     Parameter \c address can be 0-0x1f as documented by the datasheet.
00508     \note The values are MCU type dependent.
00509 */
00510 
00511 #define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
00512 
00513 #define boot_signature_byte_get(addr) \
00514 (__extension__({                      \
00515       uint8_t __result;                         \
00516       __asm__ __volatile__                      \
00517       (                                         \
00518         "sts %1, %2\n\t"                        \
00519         "lpm %0, Z" "\n\t"                      \
00520         : "=r" (__result)                       \
00521         : "i" (_SFR_MEM_ADDR(__SPM_REG)),       \
00522           "r" ((uint8_t)(__BOOT_SIGROW_READ)),  \
00523           "z" ((uint16_t)(addr))                \
00524       );                                        \
00525       __result;                                 \
00526 }))
00527 
00528 /** \ingroup avr_boot
00529     \def boot_page_fill(address, data)
00530 
00531     Fill the bootloader temporary page buffer for flash 
00532     address with data word. 
00533 
00534     \note The address is a byte address. The data is a word. The AVR 
00535     writes data to the buffer a word at a time, but addresses the buffer
00536     per byte! So, increment your address by 2 between calls, and send 2
00537     data bytes in a word format! The LSB of the data is written to the lower 
00538     address; the MSB of the data is written to the higher address.*/
00539 
00540 /** \ingroup avr_boot
00541     \def boot_page_erase(address)
00542 
00543     Erase the flash page that contains address.
00544 
00545     \note address is a byte address in flash, not a word address. */
00546 
00547 /** \ingroup avr_boot
00548     \def boot_page_write(address)
00549 
00550     Write the bootloader temporary page buffer 
00551     to flash page that contains address.
00552     
00553     \note address is a byte address in flash, not a word address. */
00554 
00555 /** \ingroup avr_boot
00556     \def boot_rww_enable()
00557 
00558     Enable the Read-While-Write memory section. */
00559 
00560 /** \ingroup avr_boot
00561     \def boot_lock_bits_set(lock_bits)
00562 
00563     Set the bootloader lock bits.
00564 
00565     \param lock_bits A mask of which Boot Loader Lock Bits to set.
00566 
00567     \note In this context, a 'set bit' will be written to a zero value.
00568     Note also that only BLBxx bits can be programmed by this command.
00569 
00570     For example, to disallow the SPM instruction from writing to the Boot
00571     Loader memory section of flash, you would use this macro as such:
00572 
00573     \code
00574     boot_lock_bits_set (_BV (BLB11));
00575     \endcode
00576 
00577     \note Like any lock bits, the Boot Loader Lock Bits, once set,
00578     cannot be cleared again except by a chip erase which will in turn
00579     also erase the boot loader itself. */
00580 
00581 /* Normal versions of the macros use 16-bit addresses.
00582    Extended versions of the macros use 32-bit addresses.
00583    Alternate versions of the macros use 16-bit addresses and require special
00584    instruction sequences after LPM.
00585 
00586    FLASHEND is defined in the ioXXXX.h file.
00587    USHRT_MAX is defined in <limits.h>. */ 
00588 
00589 #if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \
00590     || defined(__AVR_ATmega323__)
00591 
00592 /* Alternate: ATmega161/163/323 and 16 bit address */
00593 #define boot_page_fill(address, data) __boot_page_fill_alternate(address, data)
00594 #define boot_page_erase(address)      __boot_page_erase_alternate(address)
00595 #define boot_page_write(address)      __boot_page_write_alternate(address)
00596 #define boot_rww_enable()             __boot_rww_enable_alternate()
00597 #define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits)
00598 
00599 #elif (FLASHEND > USHRT_MAX)
00600 
00601 /* Extended: >16 bit address */
00602 #define boot_page_fill(address, data) __boot_page_fill_extended(address, data)
00603 #define boot_page_erase(address)      __boot_page_erase_extended(address)
00604 #define boot_page_write(address)      __boot_page_write_extended(address)
00605 #define boot_rww_enable()             __boot_rww_enable()
00606 #define boot_lock_bits_set(lock_bits) __boot_lock_bits_set(lock_bits)
00607 
00608 #else
00609 
00610 /* Normal: 16 bit address */
00611 #define boot_page_fill(address, data) __boot_page_fill_normal(address, data)
00612 #define boot_page_erase(address)      __boot_page_erase_normal(address)
00613 #define boot_page_write(address)      __boot_page_write_normal(address)
00614 #define boot_rww_enable()             __boot_rww_enable()
00615 #define boot_lock_bits_set(lock_bits) __boot_lock_bits_set(lock_bits)
00616 
00617 #endif
00618 
00619 /** \ingroup avr_boot
00620 
00621     Same as boot_page_fill() except it waits for eeprom and spm operations to
00622     complete before filling the page. */
00623 
00624 #define boot_page_fill_safe(address, data) \
00625 do { \
00626     boot_spm_busy_wait();                       \
00627     eeprom_busy_wait();                         \
00628     boot_page_fill(address, data);              \
00629 } while (0)
00630 
00631 /** \ingroup avr_boot
00632 
00633     Same as boot_page_erase() except it waits for eeprom and spm operations to
00634     complete before erasing the page. */
00635 
00636 #define boot_page_erase_safe(address) \
00637 do { \
00638     boot_spm_busy_wait();                       \
00639     eeprom_busy_wait();                         \
00640     boot_page_erase (address);                  \
00641 } while (0)
00642 
00643 /** \ingroup avr_boot
00644 
00645     Same as boot_page_write() except it waits for eeprom and spm operations to
00646     complete before writing the page. */
00647 
00648 #define boot_page_write_safe(address) \
00649 do { \
00650     boot_spm_busy_wait();                       \
00651     eeprom_busy_wait();                         \
00652     boot_page_write (address);                  \
00653 } while (0)
00654 
00655 /** \ingroup avr_boot
00656 
00657     Same as boot_rww_enable() except waits for eeprom and spm operations to
00658     complete before enabling the RWW mameory. */
00659 
00660 #define boot_rww_enable_safe() \
00661 do { \
00662     boot_spm_busy_wait();                       \
00663     eeprom_busy_wait();                         \
00664     boot_rww_enable();                          \
00665 } while (0)
00666 
00667 /** \ingroup avr_boot
00668 
00669     Same as boot_lock_bits_set() except waits for eeprom and spm operations to
00670     complete before setting the lock bits. */
00671 
00672 #define boot_lock_bits_set_safe(lock_bits) \
00673 do { \
00674     boot_spm_busy_wait();                       \
00675     eeprom_busy_wait();                         \
00676     boot_lock_bits_set (lock_bits);             \
00677 } while (0)
00678 
00679 #endif /* _AVR_BOOT_H_ */

Automatically generated by Doxygen 1.6.1 on 25 Apr 2014.