Teensy 4.1 core updated for C++20
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.

203 lines
5.0KB

  1. #include "Arduino.h"
  2. #include "pins_arduino.h"
  3. #include "debug/printf.h"
  4. #define DR 0
  5. #define GDIR 1
  6. #define PSR 2
  7. #define ICR1 3
  8. #define ICR2 4
  9. #define IMR 5
  10. #define ISR 6
  11. #define EDGE 7
  12. static void dummy_isr() {};
  13. typedef void (*voidFuncPtr)(void);
  14. // TODO: Use of Fast GPIO6 - GPIO9 probably breaks everything about attachInterrupt()
  15. // TODO: define these properly in core_pins.h - don't waste memory
  16. #define CORE_MAX_PIN_PORT1 31
  17. #define CORE_MAX_PIN_PORT2 31
  18. #define CORE_MAX_PIN_PORT3 31
  19. #define CORE_MAX_PIN_PORT4 31
  20. voidFuncPtr isr_table_gpio1[CORE_MAX_PIN_PORT1+1] = { [0 ... CORE_MAX_PIN_PORT1] = dummy_isr };
  21. voidFuncPtr isr_table_gpio2[CORE_MAX_PIN_PORT2+1] = { [0 ... CORE_MAX_PIN_PORT2] = dummy_isr };
  22. voidFuncPtr isr_table_gpio3[CORE_MAX_PIN_PORT3+1] = { [0 ... CORE_MAX_PIN_PORT3] = dummy_isr };
  23. voidFuncPtr isr_table_gpio4[CORE_MAX_PIN_PORT4+1] = { [0 ... CORE_MAX_PIN_PORT4] = dummy_isr };
  24. #if defined(__IMXRT1062__)
  25. FASTRUN static inline __attribute__((always_inline))
  26. inline void irq_anyport(volatile uint32_t *gpio, voidFuncPtr *table)
  27. {
  28. uint32_t status = gpio[ISR] & gpio[IMR];
  29. if (status) {
  30. gpio[ISR] = status;
  31. while (status) {
  32. uint32_t index = __builtin_ctz(status);
  33. table[index]();
  34. status = status & ~(1 << index);
  35. //status = status & (status - 1);
  36. }
  37. }
  38. }
  39. FASTRUN
  40. void irq_gpio6789(void)
  41. {
  42. irq_anyport(&GPIO6_DR, isr_table_gpio1);
  43. irq_anyport(&GPIO7_DR, isr_table_gpio2);
  44. irq_anyport(&GPIO8_DR, isr_table_gpio3);
  45. irq_anyport(&GPIO9_DR, isr_table_gpio4);
  46. }
  47. #elif defined(__IMXRT1052__)
  48. FASTRUN
  49. void irq_anyport(volatile uint32_t *gpio, voidFuncPtr *table)
  50. {
  51. uint32_t status = gpio[ISR] & gpio[IMR];
  52. gpio[ISR] = status;
  53. while (status) {
  54. uint32_t index = __builtin_ctz(status);
  55. table[index]();
  56. status = status & ~(1 << index);
  57. //status = status & (status - 1);
  58. }
  59. }
  60. FASTRUN
  61. void irq_gpio1(void)
  62. {
  63. irq_anyport(&GPIO1_DR, isr_table_gpio1);
  64. }
  65. FASTRUN
  66. void irq_gpio2(void)
  67. {
  68. irq_anyport(&GPIO2_DR, isr_table_gpio2);
  69. }
  70. FASTRUN
  71. void irq_gpio3(void)
  72. {
  73. irq_anyport(&GPIO3_DR, isr_table_gpio3);
  74. }
  75. FASTRUN
  76. void irq_gpio4(void)
  77. {
  78. irq_anyport(&GPIO4_DR, isr_table_gpio4);
  79. }
  80. #endif
  81. void attachInterrupt(uint8_t pin, void (*function)(void), int mode)
  82. {
  83. if (pin >= CORE_NUM_DIGITAL) return;
  84. //printf("attachInterrupt, pin=%u\n", pin);
  85. volatile uint32_t *gpio = portOutputRegister(pin);
  86. volatile uint32_t *mux = portConfigRegister(pin);
  87. //volatile uint32_t *pad = portControlRegister(pin);
  88. uint32_t mask = digitalPinToBitMask(pin);
  89. voidFuncPtr *table;
  90. #if defined(__IMXRT1062__)
  91. switch((uint32_t)gpio) {
  92. case (uint32_t)&GPIO6_DR:
  93. table = isr_table_gpio1;
  94. break;
  95. case (uint32_t)&GPIO7_DR:
  96. table = isr_table_gpio2;
  97. break;
  98. case (uint32_t)&GPIO8_DR:
  99. table = isr_table_gpio3;
  100. break;
  101. case (uint32_t)&GPIO9_DR:
  102. table = isr_table_gpio4;
  103. break;
  104. default:
  105. return;
  106. }
  107. attachInterruptVector(IRQ_GPIO6789, &irq_gpio6789);
  108. NVIC_ENABLE_IRQ(IRQ_GPIO6789);
  109. #elif defined(__IMXRT1052__)
  110. switch((uint32_t)gpio) {
  111. case (uint32_t)&GPIO1_DR:
  112. table = isr_table_gpio1;
  113. attachInterruptVector(IRQ_GPIO1_0_15, &irq_gpio1);
  114. attachInterruptVector(IRQ_GPIO1_16_31, &irq_gpio1);
  115. NVIC_ENABLE_IRQ(IRQ_GPIO1_0_15);
  116. NVIC_ENABLE_IRQ(IRQ_GPIO1_16_31);
  117. break;
  118. case (uint32_t)&GPIO2_DR:
  119. table = isr_table_gpio2;
  120. attachInterruptVector(IRQ_GPIO2_0_15, &irq_gpio2);
  121. attachInterruptVector(IRQ_GPIO2_16_31, &irq_gpio2);
  122. NVIC_ENABLE_IRQ(IRQ_GPIO2_0_15);
  123. NVIC_ENABLE_IRQ(IRQ_GPIO2_16_31);
  124. break;
  125. case (uint32_t)&GPIO3_DR:
  126. table = isr_table_gpio3;
  127. attachInterruptVector(IRQ_GPIO3_0_15, &irq_gpio3);
  128. attachInterruptVector(IRQ_GPIO3_16_31, &irq_gpio3);
  129. NVIC_ENABLE_IRQ(IRQ_GPIO3_0_15);
  130. NVIC_ENABLE_IRQ(IRQ_GPIO3_16_31);
  131. break;
  132. case (uint32_t)&GPIO4_DR:
  133. table = isr_table_gpio4;
  134. attachInterruptVector(IRQ_GPIO4_0_15, &irq_gpio4);
  135. attachInterruptVector(IRQ_GPIO4_16_31, &irq_gpio4);
  136. NVIC_ENABLE_IRQ(IRQ_GPIO4_0_15);
  137. NVIC_ENABLE_IRQ(IRQ_GPIO4_16_31);
  138. break;
  139. default:
  140. return;
  141. }
  142. #endif
  143. uint32_t icr;
  144. switch (mode) {
  145. case CHANGE: icr = 0; break;
  146. case RISING: icr = 2; break;
  147. case FALLING: icr = 3; break;
  148. case LOW: icr = 0; break;
  149. case HIGH: icr = 1; break;
  150. default: return;
  151. }
  152. // TODO: global interrupt disable to protect these read-modify-write accesses?
  153. gpio[IMR] &= ~mask; // disable interrupt
  154. *mux = 5; // pin is GPIO
  155. gpio[GDIR] &= ~mask; // pin to input mode
  156. uint32_t index = __builtin_ctz(mask);
  157. table[index] = function;
  158. if (mode == CHANGE) {
  159. gpio[EDGE] |= mask;
  160. } else {
  161. gpio[EDGE] &= ~mask;
  162. if (index < 15) {
  163. uint32_t shift = index * 2;
  164. gpio[ICR1] = (gpio[ICR1] & ~(3 << shift)) | (icr << shift);
  165. } else {
  166. uint32_t shift = (index - 16) * 2;
  167. gpio[ICR2] = (gpio[ICR2] & ~(3 << shift)) | (icr << shift);
  168. }
  169. }
  170. gpio[ISR] = mask; // clear any prior pending interrupt
  171. gpio[IMR] |= mask; // enable interrupt
  172. }
  173. void detachInterrupt(uint8_t pin)
  174. {
  175. if (pin >= CORE_NUM_DIGITAL) return;
  176. volatile uint32_t *gpio = portOutputRegister(pin);
  177. uint32_t mask = digitalPinToBitMask(pin);
  178. gpio[IMR] &= ~mask;
  179. }