boot_opt.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // Get all the "standard" definitions from the official boot.h
  2. #include <avr/boot.h>
  3. /*
  4. * Implement some optimized versions that will use OUT instead
  5. * of STS to write SPMCSR.
  6. * (However, omit the *_extended_short, since by the time you
  7. * need _extended_, the extra byte shouldn't be relevant any more)
  8. *
  9. * The C preprocessor can not determin at compile time whether SPMCSR is
  10. * "out of range" of the OUT instruction, but we CAN do that in the
  11. * assembler. We can even make it pretty with a macro.
  12. * With this modification, the _short functions should work on cpus
  13. * (like ATmega128) where STS is required.
  14. */
  15. asm(".macro __wr_spmcsr p, v \n\t"
  16. ".if \\p > 0x57 \n\t"
  17. "sts \\p, \\v \n\t"
  18. ".else \n\t"
  19. "out \\p-0x20, \\v \n\t"
  20. ".endif \n\t"
  21. ".endm \n");
  22. #if defined(__SPM_REG)
  23. #define __boot_page_fill_short(address, data) \
  24. (__extension__({ \
  25. __asm__ __volatile__ \
  26. ( \
  27. "movw r0, %3\n\t" \
  28. "__wr_spmcsr %0, %1\n\t" \
  29. "spm\n\t" \
  30. "clr r1\n\t" \
  31. : \
  32. : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
  33. "r" ((uint8_t)__BOOT_PAGE_FILL), \
  34. "z" ((uint16_t)address), \
  35. "r" ((uint16_t)data) \
  36. : "r0" \
  37. ); \
  38. }))
  39. #define __boot_page_erase_short(address) \
  40. (__extension__({ \
  41. __asm__ __volatile__ \
  42. ( \
  43. "__wr_spmcsr %0, %1\n\t" \
  44. "spm\n\t" \
  45. : \
  46. : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
  47. "r" ((uint8_t)__BOOT_PAGE_ERASE), \
  48. "z" ((uint16_t)address) \
  49. ); \
  50. }))
  51. #define __boot_page_write_short(address) \
  52. (__extension__({ \
  53. __asm__ __volatile__ \
  54. ( \
  55. "__wr_spmcsr %0, %1\n\t" \
  56. "spm\n\t" \
  57. : \
  58. : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
  59. "r" ((uint8_t)__BOOT_PAGE_WRITE), \
  60. "z" ((uint16_t)address) \
  61. ); \
  62. }))
  63. #define __boot_rww_enable_short() \
  64. (__extension__({ \
  65. __asm__ __volatile__ \
  66. ( \
  67. "__wr_spmcsr %0, %1\n\t" \
  68. "spm\n\t" \
  69. : \
  70. : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
  71. "r" ((uint8_t)__BOOT_RWW_ENABLE) \
  72. ); \
  73. }))
  74. #endif // __SPM_REG
  75. #ifndef __boot_page_erase_short
  76. /*
  77. * if __SPM_REG didn't get defined by now, but we didn't exit it means
  78. * we have some sort of new-fangled chip that post-dates the version
  79. * of boot.h that we know about. In this case, it's possible that the
  80. * standard boot.h still has workable functions, so we'll alias those.
  81. */
  82. #define __boot_page_fill_short(address, data) boot_page_fill(address, data)
  83. #define __boot_page_erase_short(address) boot_page_erase(address)
  84. #define __boot_page_write_short(address) boot_page_write(address)
  85. #define __boot_rww_enable_short() boot_rww_enable()
  86. #endif