You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
3.1 KiB

  1. /* Copyright 2021 QMK
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 3 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #ifndef __OPTIMIZE__
  17. # pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed"
  18. #endif
  19. #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"
  20. __attribute__((always_inline)) static inline void wait_cpuclock(unsigned int n) { /* n: 1..135 */
  21. /* The argument n must be a constant expression.
  22. * That way, compiler optimization will remove unnecessary code. */
  23. if (n < 1) {
  24. return;
  25. }
  26. if (n > 8) {
  27. unsigned int n8 = n / 8;
  28. n = n - n8 * 8;
  29. switch (n8) {
  30. case 16:
  31. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  32. case 15:
  33. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  34. case 14:
  35. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  36. case 13:
  37. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  38. case 12:
  39. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  40. case 11:
  41. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  42. case 10:
  43. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  44. case 9:
  45. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  46. case 8:
  47. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  48. case 7:
  49. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  50. case 6:
  51. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  52. case 5:
  53. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  54. case 4:
  55. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  56. case 3:
  57. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  58. case 2:
  59. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  60. case 1:
  61. asm volatile(CLOCK_DELAY_NOP8::: "memory");
  62. case 0:
  63. break;
  64. }
  65. }
  66. switch (n) {
  67. case 8:
  68. asm volatile("nop" ::: "memory");
  69. case 7:
  70. asm volatile("nop" ::: "memory");
  71. case 6:
  72. asm volatile("nop" ::: "memory");
  73. case 5:
  74. asm volatile("nop" ::: "memory");
  75. case 4:
  76. asm volatile("nop" ::: "memory");
  77. case 3:
  78. asm volatile("nop" ::: "memory");
  79. case 2:
  80. asm volatile("nop" ::: "memory");
  81. case 1:
  82. asm volatile("nop" ::: "memory");
  83. case 0:
  84. break;
  85. }
  86. }