$treeview $search $mathjax $extrastylesheet
avr-libc
2.0.0
$projectbrief
|
$projectbrief
|
$searchbox |
AVR Libc Home Page |
AVR Libc Development Pages |
||||
Main Page |
User Manual |
Library Reference |
FAQ |
Example Projects |
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 #ifndef __DOXYGEN__ 00141 /* Create common bit definitions. */ 00142 #ifdef ASB 00143 #define __COMMON_ASB ASB 00144 #else 00145 #define __COMMON_ASB RWWSB 00146 #endif 00147 00148 #ifdef ASRE 00149 #define __COMMON_ASRE ASRE 00150 #else 00151 #define __COMMON_ASRE RWWSRE 00152 #endif 00153 00154 /* Define the bit positions of the Boot Lock Bits. */ 00155 00156 #define BLB12 5 00157 #define BLB11 4 00158 #define BLB02 3 00159 #define BLB01 2 00160 #endif /* __DOXYGEN__ */ 00161 00162 /** \ingroup avr_boot 00163 \def boot_spm_interrupt_enable() 00164 Enable the SPM interrupt. */ 00165 00166 #define boot_spm_interrupt_enable() (__SPM_REG |= (uint8_t)_BV(SPMIE)) 00167 00168 /** \ingroup avr_boot 00169 \def boot_spm_interrupt_disable() 00170 Disable the SPM interrupt. */ 00171 00172 #define boot_spm_interrupt_disable() (__SPM_REG &= (uint8_t)~_BV(SPMIE)) 00173 00174 /** \ingroup avr_boot 00175 \def boot_is_spm_interrupt() 00176 Check if the SPM interrupt is enabled. */ 00177 00178 #define boot_is_spm_interrupt() (__SPM_REG & (uint8_t)_BV(SPMIE)) 00179 00180 /** \ingroup avr_boot 00181 \def boot_rww_busy() 00182 Check if the RWW section is busy. */ 00183 00184 #define boot_rww_busy() (__SPM_REG & (uint8_t)_BV(__COMMON_ASB)) 00185 00186 /** \ingroup avr_boot 00187 \def boot_spm_busy() 00188 Check if the SPM instruction is busy. */ 00189 00190 #define boot_spm_busy() (__SPM_REG & (uint8_t)_BV(__SPM_ENABLE)) 00191 00192 /** \ingroup avr_boot 00193 \def boot_spm_busy_wait() 00194 Wait while the SPM instruction is busy. */ 00195 00196 #define boot_spm_busy_wait() do{}while(boot_spm_busy()) 00197 00198 #ifndef __DOXYGEN__ 00199 #define __BOOT_PAGE_ERASE (_BV(__SPM_ENABLE) | _BV(PGERS)) 00200 #define __BOOT_PAGE_WRITE (_BV(__SPM_ENABLE) | _BV(PGWRT)) 00201 #define __BOOT_PAGE_FILL _BV(__SPM_ENABLE) 00202 #define __BOOT_RWW_ENABLE (_BV(__SPM_ENABLE) | _BV(__COMMON_ASRE)) 00203 #if defined(BLBSET) 00204 #define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(BLBSET)) 00205 #elif defined(RFLB) /* Some devices have RFLB defined instead of BLBSET. */ 00206 #define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(RFLB)) 00207 #endif 00208 00209 #define __boot_page_fill_normal(address, data) \ 00210 (__extension__({ \ 00211 __asm__ __volatile__ \ 00212 ( \ 00213 "movw r0, %3\n\t" \ 00214 "sts %0, %1\n\t" \ 00215 "spm\n\t" \ 00216 "clr r1\n\t" \ 00217 : \ 00218 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00219 "r" ((uint8_t)(__BOOT_PAGE_FILL)), \ 00220 "z" ((uint16_t)(address)), \ 00221 "r" ((uint16_t)(data)) \ 00222 : "r0" \ 00223 ); \ 00224 })) 00225 00226 #define __boot_page_fill_alternate(address, data)\ 00227 (__extension__({ \ 00228 __asm__ __volatile__ \ 00229 ( \ 00230 "movw r0, %3\n\t" \ 00231 "sts %0, %1\n\t" \ 00232 "spm\n\t" \ 00233 ".word 0xffff\n\t" \ 00234 "nop\n\t" \ 00235 "clr r1\n\t" \ 00236 : \ 00237 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00238 "r" ((uint8_t)(__BOOT_PAGE_FILL)), \ 00239 "z" ((uint16_t)(address)), \ 00240 "r" ((uint16_t)(data)) \ 00241 : "r0" \ 00242 ); \ 00243 })) 00244 00245 #define __boot_page_fill_extended(address, data) \ 00246 (__extension__({ \ 00247 __asm__ __volatile__ \ 00248 ( \ 00249 "movw r0, %4\n\t" \ 00250 "movw r30, %A3\n\t" \ 00251 "sts %1, %C3\n\t" \ 00252 "sts %0, %2\n\t" \ 00253 "spm\n\t" \ 00254 "clr r1\n\t" \ 00255 : \ 00256 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00257 "i" (_SFR_MEM_ADDR(RAMPZ)), \ 00258 "r" ((uint8_t)(__BOOT_PAGE_FILL)), \ 00259 "r" ((uint32_t)(address)), \ 00260 "r" ((uint16_t)(data)) \ 00261 : "r0", "r30", "r31" \ 00262 ); \ 00263 })) 00264 00265 #define __boot_page_erase_normal(address) \ 00266 (__extension__({ \ 00267 __asm__ __volatile__ \ 00268 ( \ 00269 "sts %0, %1\n\t" \ 00270 "spm\n\t" \ 00271 : \ 00272 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00273 "r" ((uint8_t)(__BOOT_PAGE_ERASE)), \ 00274 "z" ((uint16_t)(address)) \ 00275 ); \ 00276 })) 00277 00278 #define __boot_page_erase_alternate(address) \ 00279 (__extension__({ \ 00280 __asm__ __volatile__ \ 00281 ( \ 00282 "sts %0, %1\n\t" \ 00283 "spm\n\t" \ 00284 ".word 0xffff\n\t" \ 00285 "nop\n\t" \ 00286 : \ 00287 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00288 "r" ((uint8_t)(__BOOT_PAGE_ERASE)), \ 00289 "z" ((uint16_t)(address)) \ 00290 ); \ 00291 })) 00292 00293 #define __boot_page_erase_extended(address) \ 00294 (__extension__({ \ 00295 __asm__ __volatile__ \ 00296 ( \ 00297 "movw r30, %A3\n\t" \ 00298 "sts %1, %C3\n\t" \ 00299 "sts %0, %2\n\t" \ 00300 "spm\n\t" \ 00301 : \ 00302 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00303 "i" (_SFR_MEM_ADDR(RAMPZ)), \ 00304 "r" ((uint8_t)(__BOOT_PAGE_ERASE)), \ 00305 "r" ((uint32_t)(address)) \ 00306 : "r30", "r31" \ 00307 ); \ 00308 })) 00309 00310 #define __boot_page_write_normal(address) \ 00311 (__extension__({ \ 00312 __asm__ __volatile__ \ 00313 ( \ 00314 "sts %0, %1\n\t" \ 00315 "spm\n\t" \ 00316 : \ 00317 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00318 "r" ((uint8_t)(__BOOT_PAGE_WRITE)), \ 00319 "z" ((uint16_t)(address)) \ 00320 ); \ 00321 })) 00322 00323 #define __boot_page_write_alternate(address) \ 00324 (__extension__({ \ 00325 __asm__ __volatile__ \ 00326 ( \ 00327 "sts %0, %1\n\t" \ 00328 "spm\n\t" \ 00329 ".word 0xffff\n\t" \ 00330 "nop\n\t" \ 00331 : \ 00332 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00333 "r" ((uint8_t)(__BOOT_PAGE_WRITE)), \ 00334 "z" ((uint16_t)(address)) \ 00335 ); \ 00336 })) 00337 00338 #define __boot_page_write_extended(address) \ 00339 (__extension__({ \ 00340 __asm__ __volatile__ \ 00341 ( \ 00342 "movw r30, %A3\n\t" \ 00343 "sts %1, %C3\n\t" \ 00344 "sts %0, %2\n\t" \ 00345 "spm\n\t" \ 00346 : \ 00347 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00348 "i" (_SFR_MEM_ADDR(RAMPZ)), \ 00349 "r" ((uint8_t)(__BOOT_PAGE_WRITE)), \ 00350 "r" ((uint32_t)(address)) \ 00351 : "r30", "r31" \ 00352 ); \ 00353 })) 00354 00355 #define __boot_rww_enable() \ 00356 (__extension__({ \ 00357 __asm__ __volatile__ \ 00358 ( \ 00359 "sts %0, %1\n\t" \ 00360 "spm\n\t" \ 00361 : \ 00362 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00363 "r" ((uint8_t)(__BOOT_RWW_ENABLE)) \ 00364 ); \ 00365 })) 00366 00367 #define __boot_rww_enable_alternate() \ 00368 (__extension__({ \ 00369 __asm__ __volatile__ \ 00370 ( \ 00371 "sts %0, %1\n\t" \ 00372 "spm\n\t" \ 00373 ".word 0xffff\n\t" \ 00374 "nop\n\t" \ 00375 : \ 00376 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00377 "r" ((uint8_t)(__BOOT_RWW_ENABLE)) \ 00378 ); \ 00379 })) 00380 00381 /* From the mega16/mega128 data sheets (maybe others): 00382 00383 Bits by SPM To set the Boot Loader Lock bits, write the desired data to 00384 R0, write "X0001001" to SPMCR and execute SPM within four clock cycles 00385 after writing SPMCR. The only accessible Lock bits are the Boot Lock bits 00386 that may prevent the Application and Boot Loader section from any 00387 software update by the MCU. 00388 00389 If bits 5..2 in R0 are cleared (zero), the corresponding Boot Lock bit 00390 will be programmed if an SPM instruction is executed within four cycles 00391 after BLBSET and SPMEN (or SELFPRGEN) are set in SPMCR. The Z-pointer is 00392 don't care during this operation, but for future compatibility it is 00393 recommended to load the Z-pointer with $0001 (same as used for reading the 00394 Lock bits). For future compatibility It is also recommended to set bits 7, 00395 6, 1, and 0 in R0 to 1 when writing the Lock bits. When programming the 00396 Lock bits the entire Flash can be read during the operation. */ 00397 00398 #define __boot_lock_bits_set(lock_bits) \ 00399 (__extension__({ \ 00400 uint8_t value = (uint8_t)(~(lock_bits)); \ 00401 __asm__ __volatile__ \ 00402 ( \ 00403 "ldi r30, 1\n\t" \ 00404 "ldi r31, 0\n\t" \ 00405 "mov r0, %2\n\t" \ 00406 "sts %0, %1\n\t" \ 00407 "spm\n\t" \ 00408 : \ 00409 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00410 "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)), \ 00411 "r" (value) \ 00412 : "r0", "r30", "r31" \ 00413 ); \ 00414 })) 00415 00416 #define __boot_lock_bits_set_alternate(lock_bits) \ 00417 (__extension__({ \ 00418 uint8_t value = (uint8_t)(~(lock_bits)); \ 00419 __asm__ __volatile__ \ 00420 ( \ 00421 "ldi r30, 1\n\t" \ 00422 "ldi r31, 0\n\t" \ 00423 "mov r0, %2\n\t" \ 00424 "sts %0, %1\n\t" \ 00425 "spm\n\t" \ 00426 ".word 0xffff\n\t" \ 00427 "nop\n\t" \ 00428 : \ 00429 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00430 "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)), \ 00431 "r" (value) \ 00432 : "r0", "r30", "r31" \ 00433 ); \ 00434 })) 00435 #endif /* __DOXYGEN__ */ 00436 00437 /* 00438 Reading lock and fuse bits: 00439 00440 Similarly to writing the lock bits above, set BLBSET and SPMEN (or 00441 SELFPRGEN) bits in __SPMREG, and then (within four clock cycles) issue an 00442 LPM instruction. 00443 00444 Z address: contents: 00445 0x0000 low fuse bits 00446 0x0001 lock bits 00447 0x0002 extended fuse bits 00448 0x0003 high fuse bits 00449 00450 Sounds confusing, doesn't it? 00451 00452 Unlike the macros in pgmspace.h, no need to care for non-enhanced 00453 cores here as these old cores do not provide SPM support anyway. 00454 */ 00455 00456 /** \ingroup avr_boot 00457 \def GET_LOW_FUSE_BITS 00458 address to read the low fuse bits, using boot_lock_fuse_bits_get 00459 */ 00460 #define GET_LOW_FUSE_BITS (0x0000) 00461 /** \ingroup avr_boot 00462 \def GET_LOCK_BITS 00463 address to read the lock bits, using boot_lock_fuse_bits_get 00464 */ 00465 #define GET_LOCK_BITS (0x0001) 00466 /** \ingroup avr_boot 00467 \def GET_EXTENDED_FUSE_BITS 00468 address to read the extended fuse bits, using boot_lock_fuse_bits_get 00469 */ 00470 #define GET_EXTENDED_FUSE_BITS (0x0002) 00471 /** \ingroup avr_boot 00472 \def GET_HIGH_FUSE_BITS 00473 address to read the high fuse bits, using boot_lock_fuse_bits_get 00474 */ 00475 #define GET_HIGH_FUSE_BITS (0x0003) 00476 00477 /** \ingroup avr_boot 00478 \def boot_lock_fuse_bits_get(address) 00479 00480 Read the lock or fuse bits at \c address. 00481 00482 Parameter \c address can be any of GET_LOW_FUSE_BITS, 00483 GET_LOCK_BITS, GET_EXTENDED_FUSE_BITS, or GET_HIGH_FUSE_BITS. 00484 00485 \note The lock and fuse bits returned are the physical values, 00486 i.e. a bit returned as 0 means the corresponding fuse or lock bit 00487 is programmed. 00488 */ 00489 #define boot_lock_fuse_bits_get(address) \ 00490 (__extension__({ \ 00491 uint8_t __result; \ 00492 __asm__ __volatile__ \ 00493 ( \ 00494 "sts %1, %2\n\t" \ 00495 "lpm %0, Z\n\t" \ 00496 : "=r" (__result) \ 00497 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00498 "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)), \ 00499 "z" ((uint16_t)(address)) \ 00500 ); \ 00501 __result; \ 00502 })) 00503 00504 #ifndef __DOXYGEN__ 00505 #define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD)) 00506 #endif 00507 /** \ingroup avr_boot 00508 \def boot_signature_byte_get(address) 00509 00510 Read the Signature Row byte at \c address. For some MCU types, 00511 this function can also retrieve the factory-stored oscillator 00512 calibration bytes. 00513 00514 Parameter \c address can be 0-0x1f as documented by the datasheet. 00515 \note The values are MCU type dependent. 00516 */ 00517 00518 #define boot_signature_byte_get(addr) \ 00519 (__extension__({ \ 00520 uint8_t __result; \ 00521 __asm__ __volatile__ \ 00522 ( \ 00523 "sts %1, %2\n\t" \ 00524 "lpm %0, Z" "\n\t" \ 00525 : "=r" (__result) \ 00526 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ 00527 "r" ((uint8_t)(__BOOT_SIGROW_READ)), \ 00528 "z" ((uint16_t)(addr)) \ 00529 ); \ 00530 __result; \ 00531 })) 00532 00533 /** \ingroup avr_boot 00534 \def boot_page_fill(address, data) 00535 00536 Fill the bootloader temporary page buffer for flash 00537 address with data word. 00538 00539 \note The address is a byte address. The data is a word. The AVR 00540 writes data to the buffer a word at a time, but addresses the buffer 00541 per byte! So, increment your address by 2 between calls, and send 2 00542 data bytes in a word format! The LSB of the data is written to the lower 00543 address; the MSB of the data is written to the higher address.*/ 00544 00545 /** \ingroup avr_boot 00546 \def boot_page_erase(address) 00547 00548 Erase the flash page that contains address. 00549 00550 \note address is a byte address in flash, not a word address. */ 00551 00552 /** \ingroup avr_boot 00553 \def boot_page_write(address) 00554 00555 Write the bootloader temporary page buffer 00556 to flash page that contains address. 00557 00558 \note address is a byte address in flash, not a word address. */ 00559 00560 /** \ingroup avr_boot 00561 \def boot_rww_enable() 00562 00563 Enable the Read-While-Write memory section. */ 00564 00565 /** \ingroup avr_boot 00566 \def boot_lock_bits_set(lock_bits) 00567 00568 Set the bootloader lock bits. 00569 00570 \param lock_bits A mask of which Boot Loader Lock Bits to set. 00571 00572 \note In this context, a 'set bit' will be written to a zero value. 00573 Note also that only BLBxx bits can be programmed by this command. 00574 00575 For example, to disallow the SPM instruction from writing to the Boot 00576 Loader memory section of flash, you would use this macro as such: 00577 00578 \code 00579 boot_lock_bits_set (_BV (BLB11)); 00580 \endcode 00581 00582 \note Like any lock bits, the Boot Loader Lock Bits, once set, 00583 cannot be cleared again except by a chip erase which will in turn 00584 also erase the boot loader itself. */ 00585 00586 /* Normal versions of the macros use 16-bit addresses. 00587 Extended versions of the macros use 32-bit addresses. 00588 Alternate versions of the macros use 16-bit addresses and require special 00589 instruction sequences after LPM. 00590 00591 FLASHEND is defined in the ioXXXX.h file. 00592 USHRT_MAX is defined in <limits.h>. */ 00593 00594 #if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \ 00595 || defined(__AVR_ATmega323__) 00596 00597 /* Alternate: ATmega161/163/323 and 16 bit address */ 00598 #define boot_page_fill(address, data) __boot_page_fill_alternate(address, data) 00599 #define boot_page_erase(address) __boot_page_erase_alternate(address) 00600 #define boot_page_write(address) __boot_page_write_alternate(address) 00601 #define boot_rww_enable() __boot_rww_enable_alternate() 00602 #define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits) 00603 00604 #elif (FLASHEND > USHRT_MAX) 00605 00606 /* Extended: >16 bit address */ 00607 #define boot_page_fill(address, data) __boot_page_fill_extended(address, data) 00608 #define boot_page_erase(address) __boot_page_erase_extended(address) 00609 #define boot_page_write(address) __boot_page_write_extended(address) 00610 #define boot_rww_enable() __boot_rww_enable() 00611 #define boot_lock_bits_set(lock_bits) __boot_lock_bits_set(lock_bits) 00612 00613 #else 00614 00615 /* Normal: 16 bit address */ 00616 #define boot_page_fill(address, data) __boot_page_fill_normal(address, data) 00617 #define boot_page_erase(address) __boot_page_erase_normal(address) 00618 #define boot_page_write(address) __boot_page_write_normal(address) 00619 #define boot_rww_enable() __boot_rww_enable() 00620 #define boot_lock_bits_set(lock_bits) __boot_lock_bits_set(lock_bits) 00621 00622 #endif 00623 00624 /** \ingroup avr_boot 00625 00626 Same as boot_page_fill() except it waits for eeprom and spm operations to 00627 complete before filling the page. */ 00628 00629 #define boot_page_fill_safe(address, data) \ 00630 do { \ 00631 boot_spm_busy_wait(); \ 00632 eeprom_busy_wait(); \ 00633 boot_page_fill(address, data); \ 00634 } while (0) 00635 00636 /** \ingroup avr_boot 00637 00638 Same as boot_page_erase() except it waits for eeprom and spm operations to 00639 complete before erasing the page. */ 00640 00641 #define boot_page_erase_safe(address) \ 00642 do { \ 00643 boot_spm_busy_wait(); \ 00644 eeprom_busy_wait(); \ 00645 boot_page_erase (address); \ 00646 } while (0) 00647 00648 /** \ingroup avr_boot 00649 00650 Same as boot_page_write() except it waits for eeprom and spm operations to 00651 complete before writing the page. */ 00652 00653 #define boot_page_write_safe(address) \ 00654 do { \ 00655 boot_spm_busy_wait(); \ 00656 eeprom_busy_wait(); \ 00657 boot_page_write (address); \ 00658 } while (0) 00659 00660 /** \ingroup avr_boot 00661 00662 Same as boot_rww_enable() except waits for eeprom and spm operations to 00663 complete before enabling the RWW mameory. */ 00664 00665 #define boot_rww_enable_safe() \ 00666 do { \ 00667 boot_spm_busy_wait(); \ 00668 eeprom_busy_wait(); \ 00669 boot_rww_enable(); \ 00670 } while (0) 00671 00672 /** \ingroup avr_boot 00673 00674 Same as boot_lock_bits_set() except waits for eeprom and spm operations to 00675 complete before setting the lock bits. */ 00676 00677 #define boot_lock_bits_set_safe(lock_bits) \ 00678 do { \ 00679 boot_spm_busy_wait(); \ 00680 eeprom_busy_wait(); \ 00681 boot_lock_bits_set (lock_bits); \ 00682 } while (0) 00683 00684 #endif /* _AVR_BOOT_H_ */