43 #define _AVR_BOOT_H_ 1
115 #include <avr/eeprom.h>
117 #include <inttypes.h>
122 # define __SPM_REG SPMCSR
123 #elif defined (SPMCR)
124 # define __SPM_REG SPMCR
126 # error AVR processor does not provide bootloader support!
132 # define __SPM_ENABLE SPMEN
133 #elif defined(SELFPRGEN)
134 # define __SPM_ENABLE SELFPRGEN
136 # error Cannot find SPM Enable bit definition!
147 #define BOOTLOADER_SECTION __attribute__ ((section (".bootloader")))
151 #define __COMMON_ASB ASB
153 #define __COMMON_ASB RWWSB
157 #define __COMMON_ASRE ASRE
159 #define __COMMON_ASRE RWWSRE
173 #define boot_spm_interrupt_enable() (__SPM_REG |= (uint8_t)_BV(SPMIE))
179 #define boot_spm_interrupt_disable() (__SPM_REG &= (uint8_t)~_BV(SPMIE))
185 #define boot_is_spm_interrupt() (__SPM_REG & (uint8_t)_BV(SPMIE))
191 #define boot_rww_busy() (__SPM_REG & (uint8_t)_BV(__COMMON_ASB))
197 #define boot_spm_busy() (__SPM_REG & (uint8_t)_BV(__SPM_ENABLE))
203 #define boot_spm_busy_wait() do{}while(boot_spm_busy())
205 #define __BOOT_PAGE_ERASE (_BV(__SPM_ENABLE) | _BV(PGERS))
206 #define __BOOT_PAGE_WRITE (_BV(__SPM_ENABLE) | _BV(PGWRT))
207 #define __BOOT_PAGE_FILL _BV(__SPM_ENABLE)
208 #define __BOOT_RWW_ENABLE (_BV(__SPM_ENABLE) | _BV(__COMMON_ASRE))
209 #define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(BLBSET))
211 #define __boot_page_fill_short(address, data) \
213 __asm__ __volatile__ \
220 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
221 "r" ((uint8_t)__BOOT_PAGE_FILL), \
222 "z" ((uint16_t)address), \
223 "r" ((uint16_t)data) \
228 #define __boot_page_fill_normal(address, data) \
230 __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_alternate(address, data)\
247 __asm__ __volatile__ \
256 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
257 "r" ((uint8_t)__BOOT_PAGE_FILL), \
258 "z" ((uint16_t)address), \
259 "r" ((uint16_t)data) \
264 #define __boot_page_fill_extended(address, data) \
266 __asm__ __volatile__ \
269 "movw r30, %A3\n\t" \
275 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
276 "i" (_SFR_MEM_ADDR(RAMPZ)), \
277 "r" ((uint8_t)__BOOT_PAGE_FILL), \
278 "r" ((uint32_t)address), \
279 "r" ((uint16_t)data) \
280 : "r0", "r30", "r31" \
284 #define __boot_page_fill_extended_short(address, data) \
286 __asm__ __volatile__ \
289 "movw r30, %A3\n\t" \
295 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
296 "i" (_SFR_IO_ADDR(RAMPZ)), \
297 "r" ((uint8_t)__BOOT_PAGE_FILL), \
298 "r" ((uint32_t)address), \
299 "r" ((uint16_t)data) \
300 : "r0", "r30", "r31" \
304 #define __boot_page_erase_short(address) \
306 __asm__ __volatile__ \
311 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
312 "r" ((uint8_t)__BOOT_PAGE_ERASE), \
313 "z" ((uint16_t)address) \
318 #define __boot_page_erase_normal(address) \
320 __asm__ __volatile__ \
325 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
326 "r" ((uint8_t)__BOOT_PAGE_ERASE), \
327 "z" ((uint16_t)address) \
331 #define __boot_page_erase_alternate(address) \
333 __asm__ __volatile__ \
340 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
341 "r" ((uint8_t)__BOOT_PAGE_ERASE), \
342 "z" ((uint16_t)address) \
346 #define __boot_page_erase_extended(address) \
348 __asm__ __volatile__ \
350 "movw r30, %A3\n\t" \
355 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
356 "i" (_SFR_MEM_ADDR(RAMPZ)), \
357 "r" ((uint8_t)__BOOT_PAGE_ERASE), \
358 "r" ((uint32_t)address) \
362 #define __boot_page_erase_extended_short(address) \
364 __asm__ __volatile__ \
366 "movw r30, %A3\n\t" \
371 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
372 "i" (_SFR_IO_ADDR(RAMPZ)), \
373 "r" ((uint8_t)__BOOT_PAGE_ERASE), \
374 "r" ((uint32_t)address) \
379 #define __boot_page_write_short(address) \
381 __asm__ __volatile__ \
386 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
387 "r" ((uint8_t)__BOOT_PAGE_WRITE), \
388 "z" ((uint16_t)address) \
392 #define __boot_page_write_normal(address) \
394 __asm__ __volatile__ \
399 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
400 "r" ((uint8_t)__BOOT_PAGE_WRITE), \
401 "z" ((uint16_t)address) \
405 #define __boot_page_write_alternate(address) \
407 __asm__ __volatile__ \
414 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
415 "r" ((uint8_t)__BOOT_PAGE_WRITE), \
416 "z" ((uint16_t)address) \
420 #define __boot_page_write_extended(address) \
422 __asm__ __volatile__ \
424 "movw r30, %A3\n\t" \
429 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
430 "i" (_SFR_MEM_ADDR(RAMPZ)), \
431 "r" ((uint8_t)__BOOT_PAGE_WRITE), \
432 "r" ((uint32_t)address) \
436 #define __boot_page_write_extended_short(address) \
438 __asm__ __volatile__ \
440 "movw r30, %A3\n\t" \
445 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
446 "i" (_SFR_IO_ADDR(RAMPZ)), \
447 "r" ((uint8_t)__BOOT_PAGE_WRITE), \
448 "r" ((uint32_t)address) \
453 #define __boot_rww_enable_short() \
455 __asm__ __volatile__ \
460 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
461 "r" ((uint8_t)__BOOT_RWW_ENABLE) \
465 #define __boot_rww_enable() \
467 __asm__ __volatile__ \
472 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
473 "r" ((uint8_t)__BOOT_RWW_ENABLE) \
477 #define __boot_rww_enable_alternate() \
479 __asm__ __volatile__ \
486 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
487 "r" ((uint8_t)__BOOT_RWW_ENABLE) \
508 #define __boot_lock_bits_set_short(lock_bits) \
510 uint8_t value = (uint8_t)(~(lock_bits)); \
511 __asm__ __volatile__ \
519 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
520 "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
522 : "r0", "r30", "r31" \
526 #define __boot_lock_bits_set(lock_bits) \
528 uint8_t value = (uint8_t)(~(lock_bits)); \
529 __asm__ __volatile__ \
537 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
538 "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
540 : "r0", "r30", "r31" \
544 #define __boot_lock_bits_set_alternate(lock_bits) \
546 uint8_t value = (uint8_t)(~(lock_bits)); \
547 __asm__ __volatile__ \
557 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
558 "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
560 : "r0", "r30", "r31" \
587 #define GET_LOW_FUSE_BITS (0x0000)
592 #define GET_LOCK_BITS (0x0001)
597 #define GET_EXTENDED_FUSE_BITS (0x0002)
602 #define GET_HIGH_FUSE_BITS (0x0003)
616 #define boot_lock_fuse_bits_get_short(address) \
619 __asm__ __volatile__ \
626 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
627 "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
629 : "r0", "r30", "r31" \
634 #define boot_lock_fuse_bits_get(address) \
637 __asm__ __volatile__ \
644 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
645 "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
647 : "r0", "r30", "r31" \
663 #define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
665 #define boot_signature_byte_get_short(addr) \
667 uint16_t __addr16 = (uint16_t)(addr); \
669 __asm__ __volatile__ \
674 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
675 "r" ((uint8_t) __BOOT_SIGROW_READ), \
681 #define boot_signature_byte_get(addr) \
683 uint16_t __addr16 = (uint16_t)(addr); \
685 __asm__ __volatile__ \
690 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
691 "r" ((uint8_t) __BOOT_SIGROW_READ), \
758 #if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \
759 || defined(__AVR_ATmega323__)
762 #define boot_page_fill(address, data) __boot_page_fill_alternate(address, data)
763 #define boot_page_erase(address) __boot_page_erase_alternate(address)
764 #define boot_page_write(address) __boot_page_write_alternate(address)
765 #define boot_rww_enable() __boot_rww_enable_alternate()
766 #define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits)
768 #elif (FLASHEND > USHRT_MAX)
771 #define boot_page_fill(address, data) __boot_page_fill_extended_short(address, data)
772 #define boot_page_erase(address) __boot_page_erase_extended_short(address)
773 #define boot_page_write(address) __boot_page_write_extended_short(address)
774 #define boot_rww_enable() __boot_rww_enable_short()
775 #define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits)
780 #define boot_page_fill(address, data) __boot_page_fill_short(address, data)
781 #define boot_page_erase(address) __boot_page_erase_short(address)
782 #define boot_page_write(address) __boot_page_write_short(address)
783 #define boot_rww_enable() __boot_rww_enable_short()
784 #define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits)
793 #define boot_page_fill_safe(address, data) \
795 boot_spm_busy_wait(); \
796 eeprom_busy_wait(); \
797 boot_page_fill(address, data); \
805 #define boot_page_erase_safe(address) \
807 boot_spm_busy_wait(); \
808 eeprom_busy_wait(); \
809 boot_page_erase (address); \
817 #define boot_page_write_safe(address) \
819 boot_spm_busy_wait(); \
820 eeprom_busy_wait(); \
821 boot_page_write (address); \
829 #define boot_rww_enable_safe() \
831 boot_spm_busy_wait(); \
832 eeprom_busy_wait(); \
841 #define boot_lock_bits_set_safe(lock_bits) \
843 boot_spm_busy_wait(); \
844 eeprom_busy_wait(); \
845 boot_lock_bits_set (lock_bits); \