util.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #ifndef MY_UTIL_H_
  2. #define MY_UTIL_H_
  3. #include <stdint.h>
  4. #include <avr/eeprom.h>
  5. #include <avr/interrupt.h>
  6. #include <avr/pgmspace.h>
  7. #include <util/delay.h>
  8. #define likely(x) __builtin_expect(!!(x), 1)
  9. #define unlikely(x) __builtin_expect(!!(x), 0)
  10. #ifndef offsetof
  11. # define offsetof(type, member) ((size_t)&((type *)0)->member)
  12. #endif
  13. #undef typeof
  14. #define typeof __typeof__
  15. #undef container_of
  16. #define container_of(p, type, member) ({ \
  17. typeof(((type *)0)->member) *__m = (p); \
  18. (type *)((char *)__m - offsetof(type, member)); })
  19. #define min(a, b) ((a) < (b) ? (a) : (b))
  20. #define max(a, b) ((a) > (b) ? (a) : (b))
  21. #define abs(x) ((x) >= 0 ? (x) : -(x))
  22. #define lo8(x) ((uint8_t)(x))
  23. #define hi8(x) ((uint8_t)((x) >> 8))
  24. #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
  25. #define BIT(nr) (1ull << (nr))
  26. /* Progmem pointer annotation. */
  27. #define PROGPTR /* progmem pointer */
  28. /* Memory barrier.
  29. * The CPU doesn't have runtime reordering, so we just
  30. * need a compiler memory clobber. */
  31. #define mb() __asm__ __volatile__("" : : : "memory")
  32. #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
  33. /* Atomic 8bit load and store.
  34. * On AVR 8bit loads and stores are always atomic. However, use
  35. * ACCESS_ONCE() to suppress compiler optimization. */
  36. #define ATOMIC_LOAD8(u8var) ACCESS_ONCE(u8var)
  37. #define ATOMIC_STORE8(u8var, newval) do { ACCESS_ONCE(u8var) = newval; } while (0)
  38. /* Generic atomic load and store helpers. */
  39. #define ATOMIC_LOAD(var) ({ \
  40. typeof(var) _retval = 0; \
  41. if (sizeof(_retval) == 1) \
  42. _retval = ATOMIC_LOAD8(var); \
  43. else \
  44. _ATOMIC_LOAD_invalid_size(); \
  45. _retval; \
  46. })
  47. #define ATOMIC_STORE(var, newval) do { \
  48. typeof(var) _dummyvar; \
  49. if (sizeof(_dummyvar) == 1) \
  50. ATOMIC_STORE8(var, newval); \
  51. else \
  52. _ATOMIC_STORE_invalid_size(); \
  53. } while (0)
  54. extern void _ATOMIC_LOAD_invalid_size(void); /* Linker error helper */
  55. extern void _ATOMIC_STORE_invalid_size(void); /* Linker error helper */
  56. /* Convert something indirectly to a string */
  57. #define __stringify(x) #x
  58. #define stringify(x) __stringify(x)
  59. /* Assertions */
  60. void do_panic(const char PROGPTR *msg) __attribute__((noreturn));
  61. #define panic(string_literal) do_panic(PSTR(string_literal))
  62. #define BUILD_BUG_ON(x) ((void)sizeof(char[1 - 2 * !!(x)]))
  63. #define BUG_ON(x) \
  64. do { \
  65. if (unlikely(x)) \
  66. panic(__FILE__ \
  67. stringify(__LINE__)); \
  68. } while (0)
  69. /** reboot - Reboot the device */
  70. void reboot(void) __attribute__((noreturn));
  71. void long_delay_ms(uint16_t ms);
  72. /* Delay one CPU cycle */
  73. #undef nop
  74. #define nop() __asm__ __volatile__("nop\n" : : : "memory")
  75. /* Code flow attributes */
  76. #define noreturn __attribute__((__noreturn__))
  77. #define _mainfunc __attribute__((__OS_main__))
  78. #if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 5
  79. # define unreachable() __builtin_unreachable()
  80. #else
  81. # define unreachable() while (1)
  82. #endif
  83. /* Forced no-inline */
  84. #define noinline __attribute__((__noinline__))
  85. /* Forced no-instrumentation */
  86. #define noinstrument __attribute__((__no_instrument_function__))
  87. typedef _Bool bool;
  88. static inline void irq_disable(void)
  89. {
  90. cli();
  91. mb();
  92. }
  93. static inline void irq_enable(void)
  94. {
  95. mb();
  96. sei();
  97. }
  98. static inline uint8_t irq_disable_save(void)
  99. {
  100. uint8_t sreg = SREG;
  101. cli();
  102. mb();
  103. return sreg;
  104. }
  105. static inline void irq_restore(uint8_t sreg_flags)
  106. {
  107. mb();
  108. SREG = sreg_flags;
  109. }
  110. #define __irqs_disabled(sreg) (!((sreg) & (1 << SREG_I)))
  111. #define irqs_disabled() __irqs_disabled(SREG)
  112. /* Convert a number (0-F) to a hexadecimal ASCII digit */
  113. char hexdigit_to_ascii(uint8_t digit) noinstrument;
  114. /* Smart program memory read */
  115. #define pgm_read(ptr) ({ \
  116. typeof(*(ptr)) *_pgm_ptr = (ptr); \
  117. uint32_t _pgm_ret; \
  118. if (sizeof(*_pgm_ptr) == 1) \
  119. _pgm_ret = (uint8_t)pgm_read_byte(_pgm_ptr); \
  120. else if (sizeof(*_pgm_ptr) == 2) \
  121. _pgm_ret = (uint16_t)pgm_read_word(_pgm_ptr); \
  122. else if (sizeof(*_pgm_ptr) == 4) \
  123. _pgm_ret = (uint32_t)pgm_read_dword(_pgm_ptr); \
  124. else \
  125. _pgm_read_invalid_type_size(); \
  126. _pgm_ret; \
  127. })
  128. extern void _pgm_read_invalid_type_size(void);
  129. /* Find first set bit.
  130. * Returns 0, if no bit is set. */
  131. uint8_t ffs16(uint16_t value);
  132. #define DIV_ROUND_UP(n, d) (((n) + (d) - 1ul) / (d))
  133. #endif /* MY_UTIL_H_ */