98# define __SPM_REG SPMCSR
101# define __SPM_REG SPMCR
103# error AVR processor does not provide bootloader support!
110# define __SPM_ENABLE SPMEN
111#elif defined(SELFPRGEN)
112# define __SPM_ENABLE SELFPRGEN
114# error Cannot find SPM Enable bit definition!
125#define BOOTLOADER_SECTION __attribute__ ((__section__(".bootloader")))
130#define __COMMON_ASB ASB
132#define __COMMON_ASB RWWSB
136#define __COMMON_ASRE ASRE
138#define __COMMON_ASRE RWWSRE
153#define boot_spm_interrupt_enable() (__SPM_REG |= (uint8_t)_BV(SPMIE))
159#define boot_spm_interrupt_disable() (__SPM_REG &= (uint8_t)~_BV(SPMIE))
165#define boot_is_spm_interrupt() (__SPM_REG & (uint8_t)_BV(SPMIE))
171#define boot_rww_busy() (__SPM_REG & (uint8_t)_BV(__COMMON_ASB))
177#define boot_spm_busy() (__SPM_REG & (uint8_t)_BV(__SPM_ENABLE))
183#define boot_spm_busy_wait() do{}while(boot_spm_busy())
186#define __BOOT_PAGE_ERASE (_BV(__SPM_ENABLE) | _BV(PGERS))
187#define __BOOT_PAGE_WRITE (_BV(__SPM_ENABLE) | _BV(PGWRT))
188#define __BOOT_PAGE_FILL _BV(__SPM_ENABLE)
189#define __BOOT_RWW_ENABLE (_BV(__SPM_ENABLE) | _BV(__COMMON_ASRE))
191#define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(BLBSET))
193#define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(RFLB))
195#define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(RWFLB))
198#define __boot_page_fill_normal(address, data) \
200 if (_SFR_IO_REG_P(__SPM_REG)) \
201 __asm__ __volatile__ ( \
202 "movw r0, %3" "\n\t" \
203 "out %0, %1" "\n\t" \
207 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
208 "r" ((uint8_t)(__BOOT_PAGE_FILL)), \
209 "z" ((uint16_t)(address)), \
210 "r" ((uint16_t)(data)) \
213 __asm__ __volatile__ ( \
214 "movw r0, %3" "\n\t" \
215 "sts %0, %1" "\n\t" \
219 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
220 "r" ((uint8_t)(__BOOT_PAGE_FILL)), \
221 "z" ((uint16_t)(address)), \
222 "r" ((uint16_t)(data)) \
226#define __boot_page_fill_alternate(address, data)\
228 __asm__ __volatile__ \
230 "movw r0, %3" "\n\t" \
231 "sts %0, %1" "\n\t" \
233 ".word 0xffff" "\n\t" \
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__ \
249 "movw r0, %4" "\n\t" \
250 "movw r30, %A3" "\n\t" \
251 "out %1, %C3" "\n\t" \
252 "sts %0, %2" "\n\t" \
256 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
257 "i" (_SFR_IO_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 if (_SFR_IO_REG_P(__SPM_REG)) \
268 __asm__ __volatile__ ( \
269 "out %0, %1" "\n\t" \
272 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
273 "r" ((uint8_t)(__BOOT_PAGE_ERASE)), \
274 "z" ((uint16_t)(address))); \
276 __asm__ __volatile__ ( \
277 "sts %0, %1" "\n\t" \
280 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
281 "r" ((uint8_t)(__BOOT_PAGE_ERASE)), \
282 "z" ((uint16_t)(address))); \
285#define __boot_page_erase_alternate(address) \
287 __asm__ __volatile__ \
289 "sts %0, %1" "\n\t" \
291 ".word 0xffff" "\n\t" \
294 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
295 "r" ((uint8_t)(__BOOT_PAGE_ERASE)), \
296 "z" ((uint16_t)(address)) \
300#define __boot_page_erase_extended(address) \
302 __asm__ __volatile__ \
304 "movw r30, %A3" "\n\t" \
305 "out %1, %C3" "\n\t" \
306 "sts %0, %2" "\n\t" \
309 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
310 "i" (_SFR_IO_ADDR(RAMPZ)), \
311 "r" ((uint8_t)(__BOOT_PAGE_ERASE)), \
312 "r" ((uint32_t)(address)) \
317#define __boot_page_write_normal(address) \
319 if (_SFR_IO_REG_P(__SPM_REG)) \
320 __asm__ __volatile__ ( \
321 "out %0, %1" "\n\t" \
324 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
325 "r" ((uint8_t)(__BOOT_PAGE_WRITE)), \
326 "z" ((uint16_t)(address))); \
328 __asm__ __volatile__ ( \
329 "sts %0, %1" "\n\t" \
332 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
333 "r" ((uint8_t)(__BOOT_PAGE_WRITE)), \
334 "z" ((uint16_t)(address))); \
337#define __boot_page_write_alternate(address) \
339 __asm__ __volatile__ \
341 "sts %0, %1" "\n\t" \
343 ".word 0xffff" "\n\t" \
346 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
347 "r" ((uint8_t)(__BOOT_PAGE_WRITE)), \
348 "z" ((uint16_t)(address)) \
352#define __boot_page_write_extended(address) \
354 __asm__ __volatile__ \
356 "movw r30, %A3" "\n\t" \
357 "out %1, %C3" "\n\t" \
358 "sts %0, %2" "\n\t" \
361 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
362 "i" (_SFR_IO_ADDR(RAMPZ)), \
363 "r" ((uint8_t)(__BOOT_PAGE_WRITE)), \
364 "r" ((uint32_t)(address)) \
369#define __boot_rww_enable() \
371 __asm__ __volatile__ \
373 "sts %0, %1" "\n\t" \
376 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
377 "r" ((uint8_t)(__BOOT_RWW_ENABLE)) \
381#define __boot_rww_enable_alternate() \
383 __asm__ __volatile__ \
385 "sts %0, %1" "\n\t" \
387 ".word 0xffff" "\n\t" \
390 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
391 "r" ((uint8_t)(__BOOT_RWW_ENABLE)) \
412#define __boot_lock_bits_set(lock_bits) \
414 uint8_t value = (uint8_t)(~(lock_bits)); \
415 __asm__ __volatile__ \
417 "ldi r30, 1" "\n\t" \
418 "ldi r31, 0" "\n\t" \
419 "mov r0, %2" "\n\t" \
420 "sts %0, %1" "\n\t" \
423 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
424 "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)), \
426 : "r0", "r30", "r31" \
430#define __boot_lock_bits_set_alternate(lock_bits) \
432 uint8_t value = (uint8_t)(~(lock_bits)); \
433 __asm__ __volatile__ \
435 "ldi r30, 1" "\n\t" \
436 "ldi r31, 0" "\n\t" \
437 "mov r0, %2" "\n\t" \
438 "sts %0, %1" "\n\t" \
440 ".word 0xffff" "\n\t" \
443 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
444 "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)), \
446 : "r0", "r30", "r31" \
474#define GET_LOW_FUSE_BITS (0x0000)
479#define GET_LOCK_BITS (0x0001)
484#define GET_EXTENDED_FUSE_BITS (0x0002)
489#define GET_HIGH_FUSE_BITS (0x0003)
503#define boot_lock_fuse_bits_get(address) \
506 __asm__ __volatile__ \
511 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
512 "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)), \
513 "z" ((uint16_t)(address)) \
520# define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
522# define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(RSIG))
537#define boot_signature_byte_get(addr) \
540 __asm__ __volatile__ \
542 "sts %1, %2" "\n\t" \
545 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
546 "r" ((uint8_t)(__BOOT_SIGROW_READ)), \
547 "z" ((uint16_t)(addr)) \
613#if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \
614 || defined(__AVR_ATmega323__)
617#define boot_page_fill(address, data) __boot_page_fill_alternate(address, data)
618#define boot_page_erase(address) __boot_page_erase_alternate(address)
619#define boot_page_write(address) __boot_page_write_alternate(address)
620#define boot_rww_enable() __boot_rww_enable_alternate()
621#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits)
623#elif (FLASHEND > USHRT_MAX)
626#define boot_page_fill(address, data) __boot_page_fill_extended(address, data)
627#define boot_page_erase(address) __boot_page_erase_extended(address)
628#define boot_page_write(address) __boot_page_write_extended(address)
629#define boot_rww_enable() __boot_rww_enable()
630#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set(lock_bits)
635#define boot_page_fill(address, data) __boot_page_fill_normal(address, data)
636#define boot_page_erase(address) __boot_page_erase_normal(address)
637#define boot_page_write(address) __boot_page_write_normal(address)
638#define boot_rww_enable() __boot_rww_enable()
639#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set(lock_bits)
648#define boot_page_fill_safe(address, data) \
650 boot_spm_busy_wait(); \
651 eeprom_busy_wait(); \
652 boot_page_fill(address, data); \
660#define boot_page_erase_safe(address) \
662 boot_spm_busy_wait(); \
663 eeprom_busy_wait(); \
664 boot_page_erase (address); \
672#define boot_page_write_safe(address) \
674 boot_spm_busy_wait(); \
675 eeprom_busy_wait(); \
676 boot_page_write (address); \
684#define boot_rww_enable_safe() \
686 boot_spm_busy_wait(); \
687 eeprom_busy_wait(); \
696#define boot_lock_bits_set_safe(lock_bits) \
698 boot_spm_busy_wait(); \
699 eeprom_busy_wait(); \
700 boot_lock_bits_set (lock_bits); \