104#include <avr/eeprom.h>
111# define __SPM_REG SPMCSR
114# define __SPM_REG SPMCR
116# error AVR processor does not provide bootloader support!
123# define __SPM_ENABLE SPMEN
124#elif defined(SELFPRGEN)
125# define __SPM_ENABLE SELFPRGEN
127# error Cannot find SPM Enable bit definition!
138#define BOOTLOADER_SECTION __attribute__ ((section (".bootloader")))
143#define __COMMON_ASB ASB
145#define __COMMON_ASB RWWSB
149#define __COMMON_ASRE ASRE
151#define __COMMON_ASRE RWWSRE
166#define boot_spm_interrupt_enable() (__SPM_REG |= (uint8_t)_BV(SPMIE))
172#define boot_spm_interrupt_disable() (__SPM_REG &= (uint8_t)~_BV(SPMIE))
178#define boot_is_spm_interrupt() (__SPM_REG & (uint8_t)_BV(SPMIE))
184#define boot_rww_busy() (__SPM_REG & (uint8_t)_BV(__COMMON_ASB))
190#define boot_spm_busy() (__SPM_REG & (uint8_t)_BV(__SPM_ENABLE))
196#define boot_spm_busy_wait() do{}while(boot_spm_busy())
199#define __BOOT_PAGE_ERASE (_BV(__SPM_ENABLE) | _BV(PGERS))
200#define __BOOT_PAGE_WRITE (_BV(__SPM_ENABLE) | _BV(PGWRT))
201#define __BOOT_PAGE_FILL _BV(__SPM_ENABLE)
202#define __BOOT_RWW_ENABLE (_BV(__SPM_ENABLE) | _BV(__COMMON_ASRE))
204#define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(BLBSET))
206#define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(RFLB))
209#define __boot_page_fill_normal(address, data) \
211 __asm__ __volatile__ \
218 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
219 "r" ((uint8_t)(__BOOT_PAGE_FILL)), \
220 "z" ((uint16_t)(address)), \
221 "r" ((uint16_t)(data)) \
226#define __boot_page_fill_alternate(address, data)\
228 __asm__ __volatile__ \
237 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
238 "r" ((uint8_t)(__BOOT_PAGE_FILL)), \
239 "z" ((uint16_t)(address)), \
240 "r" ((uint16_t)(data)) \
245#define __boot_page_fill_extended(address, data) \
247 __asm__ __volatile__ \
250 "movw r30, %A3\n\t" \
256 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
257 "i" (_SFR_MEM_ADDR(RAMPZ)), \
258 "r" ((uint8_t)(__BOOT_PAGE_FILL)), \
259 "r" ((uint32_t)(address)), \
260 "r" ((uint16_t)(data)) \
261 : "r0", "r30", "r31" \
265#define __boot_page_erase_normal(address) \
267 __asm__ __volatile__ \
272 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
273 "r" ((uint8_t)(__BOOT_PAGE_ERASE)), \
274 "z" ((uint16_t)(address)) \
278#define __boot_page_erase_alternate(address) \
280 __asm__ __volatile__ \
287 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
288 "r" ((uint8_t)(__BOOT_PAGE_ERASE)), \
289 "z" ((uint16_t)(address)) \
293#define __boot_page_erase_extended(address) \
295 __asm__ __volatile__ \
297 "movw r30, %A3\n\t" \
302 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
303 "i" (_SFR_MEM_ADDR(RAMPZ)), \
304 "r" ((uint8_t)(__BOOT_PAGE_ERASE)), \
305 "r" ((uint32_t)(address)) \
310#define __boot_page_write_normal(address) \
312 __asm__ __volatile__ \
317 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
318 "r" ((uint8_t)(__BOOT_PAGE_WRITE)), \
319 "z" ((uint16_t)(address)) \
323#define __boot_page_write_alternate(address) \
325 __asm__ __volatile__ \
332 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
333 "r" ((uint8_t)(__BOOT_PAGE_WRITE)), \
334 "z" ((uint16_t)(address)) \
338#define __boot_page_write_extended(address) \
340 __asm__ __volatile__ \
342 "movw r30, %A3\n\t" \
347 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
348 "i" (_SFR_MEM_ADDR(RAMPZ)), \
349 "r" ((uint8_t)(__BOOT_PAGE_WRITE)), \
350 "r" ((uint32_t)(address)) \
355#define __boot_rww_enable() \
357 __asm__ __volatile__ \
362 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
363 "r" ((uint8_t)(__BOOT_RWW_ENABLE)) \
367#define __boot_rww_enable_alternate() \
369 __asm__ __volatile__ \
376 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
377 "r" ((uint8_t)(__BOOT_RWW_ENABLE)) \
398#define __boot_lock_bits_set(lock_bits) \
400 uint8_t value = (uint8_t)(~(lock_bits)); \
401 __asm__ __volatile__ \
409 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
410 "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)), \
412 : "r0", "r30", "r31" \
416#define __boot_lock_bits_set_alternate(lock_bits) \
418 uint8_t value = (uint8_t)(~(lock_bits)); \
419 __asm__ __volatile__ \
429 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
430 "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)), \
432 : "r0", "r30", "r31" \
460#define GET_LOW_FUSE_BITS (0x0000)
465#define GET_LOCK_BITS (0x0001)
470#define GET_EXTENDED_FUSE_BITS (0x0002)
475#define GET_HIGH_FUSE_BITS (0x0003)
489#define boot_lock_fuse_bits_get(address) \
492 __asm__ __volatile__ \
497 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
498 "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)), \
499 "z" ((uint16_t)(address)) \
505#define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
518#define boot_signature_byte_get(addr) \
521 __asm__ __volatile__ \
526 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
527 "r" ((uint8_t)(__BOOT_SIGROW_READ)), \
528 "z" ((uint16_t)(addr)) \
594#if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \
595 || defined(__AVR_ATmega323__)
598#define boot_page_fill(address, data) __boot_page_fill_alternate(address, data)
599#define boot_page_erase(address) __boot_page_erase_alternate(address)
600#define boot_page_write(address) __boot_page_write_alternate(address)
601#define boot_rww_enable() __boot_rww_enable_alternate()
602#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits)
604#elif (FLASHEND > USHRT_MAX)
607#define boot_page_fill(address, data) __boot_page_fill_extended(address, data)
608#define boot_page_erase(address) __boot_page_erase_extended(address)
609#define boot_page_write(address) __boot_page_write_extended(address)
610#define boot_rww_enable() __boot_rww_enable()
611#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set(lock_bits)
616#define boot_page_fill(address, data) __boot_page_fill_normal(address, data)
617#define boot_page_erase(address) __boot_page_erase_normal(address)
618#define boot_page_write(address) __boot_page_write_normal(address)
619#define boot_rww_enable() __boot_rww_enable()
620#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set(lock_bits)
629#define boot_page_fill_safe(address, data) \
631 boot_spm_busy_wait(); \
632 eeprom_busy_wait(); \
633 boot_page_fill(address, data); \
641#define boot_page_erase_safe(address) \
643 boot_spm_busy_wait(); \
644 eeprom_busy_wait(); \
645 boot_page_erase (address); \
653#define boot_page_write_safe(address) \
655 boot_spm_busy_wait(); \
656 eeprom_busy_wait(); \
657 boot_page_write (address); \
665#define boot_rww_enable_safe() \
667 boot_spm_busy_wait(); \
668 eeprom_busy_wait(); \
677#define boot_lock_bits_set_safe(lock_bits) \
679 boot_spm_busy_wait(); \
680 eeprom_busy_wait(); \
681 boot_lock_bits_set (lock_bits); \