wait.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #pragma once
  2. #include <inttypes.h>
  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif
  6. #if defined(__ARMEL__) || defined(__ARMEB__)
  7. # ifndef __OPTIMIZE__
  8. # pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed"
  9. # endif
  10. # define wait_cpuclock(x) wait_cpuclock_allnop(x)
  11. # define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t"
  12. __attribute__((always_inline)) static inline void wait_cpuclock_allnop(unsigned int n) { /* n: 1..135 */
  13. /* The argument n must be a constant expression.
  14. * That way, compiler optimization will remove unnecessary code. */
  15. if (n < 1) {
  16. return;
  17. }
  18. if (n > 8) {
  19. unsigned int n8 = n / 8;
  20. n = n - n8 * 8;
  21. switch (n8) {
  22. case 16:
  23. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  24. case 15:
  25. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  26. case 14:
  27. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  28. case 13:
  29. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  30. case 12:
  31. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  32. case 11:
  33. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  34. case 10:
  35. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  36. case 9:
  37. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  38. case 8:
  39. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  40. case 7:
  41. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  42. case 6:
  43. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  44. case 5:
  45. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  46. case 4:
  47. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  48. case 3:
  49. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  50. case 2:
  51. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  52. case 1:
  53. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  54. case 0:
  55. break;
  56. }
  57. }
  58. switch (n) {
  59. case 8:
  60. asm volatile("nop" ::: "memory");
  61. case 7:
  62. asm volatile("nop" ::: "memory");
  63. case 6:
  64. asm volatile("nop" ::: "memory");
  65. case 5:
  66. asm volatile("nop" ::: "memory");
  67. case 4:
  68. asm volatile("nop" ::: "memory");
  69. case 3:
  70. asm volatile("nop" ::: "memory");
  71. case 2:
  72. asm volatile("nop" ::: "memory");
  73. case 1:
  74. asm volatile("nop" ::: "memory");
  75. case 0:
  76. break;
  77. }
  78. }
  79. #endif
  80. #if defined(__AVR__)
  81. # include <util/delay.h>
  82. # define wait_ms(ms) _delay_ms(ms)
  83. # define wait_us(us) _delay_us(us)
  84. # define wait_cpuclock(x) __builtin_avr_delay_cycles(x)
  85. #elif defined PROTOCOL_CHIBIOS
  86. # include <ch.h>
  87. # define wait_ms(ms) \
  88. do { \
  89. if (ms != 0) { \
  90. chThdSleepMilliseconds(ms); \
  91. } else { \
  92. chThdSleepMicroseconds(1); \
  93. } \
  94. } while (0)
  95. # define wait_us(us) \
  96. do { \
  97. if (us != 0) { \
  98. chThdSleepMicroseconds(us); \
  99. } else { \
  100. chThdSleepMicroseconds(1); \
  101. } \
  102. } while (0)
  103. #elif defined PROTOCOL_ARM_ATSAM
  104. # include "clks.h"
  105. # define wait_ms(ms) CLK_delay_ms(ms)
  106. # define wait_us(us) CLK_delay_us(us)
  107. #else // Unit tests
  108. void wait_ms(uint32_t ms);
  109. # define wait_us(us) wait_ms(us / 1000)
  110. #endif
  111. #ifdef __cplusplus
  112. }
  113. #endif