92#include <avr/eeprom.h>
99# define __SPM_REG SPMCSR
102# define __SPM_REG SPMCR
104# error AVR processor does not provide bootloader support!
111# define __SPM_ENABLE SPMEN
112#elif defined(SELFPRGEN)
113# define __SPM_ENABLE SELFPRGEN
115# error Cannot find SPM Enable bit definition!
126#define BOOTLOADER_SECTION __attribute__ ((__section__(".bootloader")))
131#define __COMMON_ASB ASB
133#define __COMMON_ASB RWWSB
137#define __COMMON_ASRE ASRE
139#define __COMMON_ASRE RWWSRE
154#define boot_spm_interrupt_enable() (__SPM_REG |= (uint8_t)_BV(SPMIE))
160#define boot_spm_interrupt_disable() (__SPM_REG &= (uint8_t)~_BV(SPMIE))
166#define boot_is_spm_interrupt() (__SPM_REG & (uint8_t)_BV(SPMIE))
172#define boot_rww_busy() (__SPM_REG & (uint8_t)_BV(__COMMON_ASB))
178#define boot_spm_busy() (__SPM_REG & (uint8_t)_BV(__SPM_ENABLE))
184#define boot_spm_busy_wait() do{}while(boot_spm_busy())
187#define __BOOT_PAGE_ERASE (_BV(__SPM_ENABLE) | _BV(PGERS))
188#define __BOOT_PAGE_WRITE (_BV(__SPM_ENABLE) | _BV(PGWRT))
189#define __BOOT_PAGE_FILL _BV(__SPM_ENABLE)
190#define __BOOT_RWW_ENABLE (_BV(__SPM_ENABLE) | _BV(__COMMON_ASRE))
192#define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(BLBSET))
194#define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(RFLB))
196#define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(RWFLB))
199#define __boot_page_fill_normal(address, data) \
201 if (_SFR_IO_REG_P(__SPM_REG)) \
202 __asm__ __volatile__ ( \
203 "movw r0, %3" "\n\t" \
204 "out %0, %1" "\n\t" \
208 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
209 "r" ((uint8_t)(__BOOT_PAGE_FILL)), \
210 "z" ((uint16_t)(address)), \
211 "r" ((uint16_t)(data)) \
214 __asm__ __volatile__ ( \
215 "movw r0, %3" "\n\t" \
216 "sts %0, %1" "\n\t" \
220 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
221 "r" ((uint8_t)(__BOOT_PAGE_FILL)), \
222 "z" ((uint16_t)(address)), \
223 "r" ((uint16_t)(data)) \
227#define __boot_page_fill_alternate(address, data)\
229 __asm__ __volatile__ \
231 "movw r0, %3" "\n\t" \
232 "sts %0, %1" "\n\t" \
234 ".word 0xffff" "\n\t" \
238 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
239 "r" ((uint8_t)(__BOOT_PAGE_FILL)), \
240 "z" ((uint16_t)(address)), \
241 "r" ((uint16_t)(data)) \
246#define __boot_page_fill_extended(address, data) \
248 __asm__ __volatile__ \
250 "movw r0, %4" "\n\t" \
251 "movw r30, %A3" "\n\t" \
252 "out %1, %C3" "\n\t" \
253 "sts %0, %2" "\n\t" \
257 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
258 "i" (_SFR_IO_ADDR(RAMPZ)), \
259 "r" ((uint8_t)(__BOOT_PAGE_FILL)), \
260 "r" ((uint32_t)(address)), \
261 "r" ((uint16_t)(data)) \
262 : "r0", "r30", "r31" \
266#define __boot_page_erase_normal(address) \
268 if (_SFR_IO_REG_P(__SPM_REG)) \
269 __asm__ __volatile__ ( \
270 "out %0, %1" "\n\t" \
273 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
274 "r" ((uint8_t)(__BOOT_PAGE_ERASE)), \
275 "z" ((uint16_t)(address))); \
277 __asm__ __volatile__ ( \
278 "sts %0, %1" "\n\t" \
281 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
282 "r" ((uint8_t)(__BOOT_PAGE_ERASE)), \
283 "z" ((uint16_t)(address))); \
286#define __boot_page_erase_alternate(address) \
288 __asm__ __volatile__ \
290 "sts %0, %1" "\n\t" \
292 ".word 0xffff" "\n\t" \
295 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
296 "r" ((uint8_t)(__BOOT_PAGE_ERASE)), \
297 "z" ((uint16_t)(address)) \
301#define __boot_page_erase_extended(address) \
303 __asm__ __volatile__ \
305 "movw r30, %A3" "\n\t" \
306 "out %1, %C3" "\n\t" \
307 "sts %0, %2" "\n\t" \
310 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
311 "i" (_SFR_IO_ADDR(RAMPZ)), \
312 "r" ((uint8_t)(__BOOT_PAGE_ERASE)), \
313 "r" ((uint32_t)(address)) \
318#define __boot_page_write_normal(address) \
320 if (_SFR_IO_REG_P(__SPM_REG)) \
321 __asm__ __volatile__ ( \
322 "out %0, %1" "\n\t" \
325 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
326 "r" ((uint8_t)(__BOOT_PAGE_WRITE)), \
327 "z" ((uint16_t)(address))); \
329 __asm__ __volatile__ ( \
330 "sts %0, %1" "\n\t" \
333 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
334 "r" ((uint8_t)(__BOOT_PAGE_WRITE)), \
335 "z" ((uint16_t)(address))); \
338#define __boot_page_write_alternate(address) \
340 __asm__ __volatile__ \
342 "sts %0, %1" "\n\t" \
344 ".word 0xffff" "\n\t" \
347 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
348 "r" ((uint8_t)(__BOOT_PAGE_WRITE)), \
349 "z" ((uint16_t)(address)) \
353#define __boot_page_write_extended(address) \
355 __asm__ __volatile__ \
357 "movw r30, %A3" "\n\t" \
358 "out %1, %C3" "\n\t" \
359 "sts %0, %2" "\n\t" \
362 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
363 "i" (_SFR_IO_ADDR(RAMPZ)), \
364 "r" ((uint8_t)(__BOOT_PAGE_WRITE)), \
365 "r" ((uint32_t)(address)) \
370#define __boot_rww_enable() \
372 __asm__ __volatile__ \
374 "sts %0, %1" "\n\t" \
377 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
378 "r" ((uint8_t)(__BOOT_RWW_ENABLE)) \
382#define __boot_rww_enable_alternate() \
384 __asm__ __volatile__ \
386 "sts %0, %1" "\n\t" \
388 ".word 0xffff" "\n\t" \
391 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
392 "r" ((uint8_t)(__BOOT_RWW_ENABLE)) \
413#define __boot_lock_bits_set(lock_bits) \
415 uint8_t value = (uint8_t)(~(lock_bits)); \
416 __asm__ __volatile__ \
418 "ldi r30, 1" "\n\t" \
419 "ldi r31, 0" "\n\t" \
420 "mov r0, %2" "\n\t" \
421 "sts %0, %1" "\n\t" \
424 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
425 "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)), \
427 : "r0", "r30", "r31" \
431#define __boot_lock_bits_set_alternate(lock_bits) \
433 uint8_t value = (uint8_t)(~(lock_bits)); \
434 __asm__ __volatile__ \
436 "ldi r30, 1" "\n\t" \
437 "ldi r31, 0" "\n\t" \
438 "mov r0, %2" "\n\t" \
439 "sts %0, %1" "\n\t" \
441 ".word 0xffff" "\n\t" \
444 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
445 "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)), \
447 : "r0", "r30", "r31" \
475#define GET_LOW_FUSE_BITS (0x0000)
480#define GET_LOCK_BITS (0x0001)
485#define GET_EXTENDED_FUSE_BITS (0x0002)
490#define GET_HIGH_FUSE_BITS (0x0003)
504#define boot_lock_fuse_bits_get(address) \
507 __asm__ __volatile__ \
512 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
513 "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)), \
514 "z" ((uint16_t)(address)) \
521# define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
523# define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(RSIG))
538#define boot_signature_byte_get(addr) \
541 __asm__ __volatile__ \
543 "sts %1, %2" "\n\t" \
546 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
547 "r" ((uint8_t)(__BOOT_SIGROW_READ)), \
548 "z" ((uint16_t)(addr)) \
614#if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \
615 || defined(__AVR_ATmega323__)
618#define boot_page_fill(address, data) __boot_page_fill_alternate(address, data)
619#define boot_page_erase(address) __boot_page_erase_alternate(address)
620#define boot_page_write(address) __boot_page_write_alternate(address)
621#define boot_rww_enable() __boot_rww_enable_alternate()
622#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits)
624#elif (FLASHEND > USHRT_MAX)
627#define boot_page_fill(address, data) __boot_page_fill_extended(address, data)
628#define boot_page_erase(address) __boot_page_erase_extended(address)
629#define boot_page_write(address) __boot_page_write_extended(address)
630#define boot_rww_enable() __boot_rww_enable()
631#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set(lock_bits)
636#define boot_page_fill(address, data) __boot_page_fill_normal(address, data)
637#define boot_page_erase(address) __boot_page_erase_normal(address)
638#define boot_page_write(address) __boot_page_write_normal(address)
639#define boot_rww_enable() __boot_rww_enable()
640#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set(lock_bits)
649#define boot_page_fill_safe(address, data) \
651 boot_spm_busy_wait(); \
652 eeprom_busy_wait(); \
653 boot_page_fill(address, data); \
661#define boot_page_erase_safe(address) \
663 boot_spm_busy_wait(); \
664 eeprom_busy_wait(); \
665 boot_page_erase (address); \
673#define boot_page_write_safe(address) \
675 boot_spm_busy_wait(); \
676 eeprom_busy_wait(); \
677 boot_page_write (address); \
685#define boot_rww_enable_safe() \
687 boot_spm_busy_wait(); \
688 eeprom_busy_wait(); \
697#define boot_lock_bits_set_safe(lock_bits) \
699 boot_spm_busy_wait(); \
700 eeprom_busy_wait(); \
701 boot_lock_bits_set (lock_bits); \