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.

150 lines
3.8KB

  1. #include "Arduino.h"
  2. #include "pins_arduino.h"
  3. #include "debug/printf.h"
  4. static void dummy_isr() {};
  5. typedef void (*voidFuncPtr)(void);
  6. // TODO: define these properly in core_pins.h - don't waste memory
  7. #define CORE_MAX_PIN_PORT1 31
  8. #define CORE_MAX_PIN_PORT2 31
  9. #define CORE_MAX_PIN_PORT3 31
  10. #define CORE_MAX_PIN_PORT4 31
  11. voidFuncPtr isr_table_gpio1[CORE_MAX_PIN_PORT1+1] = { [0 ... CORE_MAX_PIN_PORT1] = dummy_isr };
  12. voidFuncPtr isr_table_gpio2[CORE_MAX_PIN_PORT2+1] = { [0 ... CORE_MAX_PIN_PORT2] = dummy_isr };
  13. voidFuncPtr isr_table_gpio3[CORE_MAX_PIN_PORT3+1] = { [0 ... CORE_MAX_PIN_PORT3] = dummy_isr };
  14. voidFuncPtr isr_table_gpio4[CORE_MAX_PIN_PORT4+1] = { [0 ... CORE_MAX_PIN_PORT4] = dummy_isr };
  15. #define DR 0
  16. #define GDIR 1
  17. #define PSR 2
  18. #define ICR1 3
  19. #define ICR2 4
  20. #define IMR 5
  21. #define ISR 6
  22. #define EDGE 7
  23. FASTRUN
  24. void irq_anyport(volatile uint32_t *gpio, voidFuncPtr *table)
  25. {
  26. uint32_t status = gpio[ISR] & gpio[IMR];
  27. gpio[ISR] = status;
  28. while (status) {
  29. uint32_t index = __builtin_ctz(status);
  30. table[index]();
  31. status = status & ~(1 << index);
  32. //status = status & (status - 1);
  33. }
  34. }
  35. FASTRUN
  36. void irq_gpio1(void)
  37. {
  38. irq_anyport(&GPIO1_DR, isr_table_gpio1);
  39. }
  40. FASTRUN
  41. void irq_gpio2(void)
  42. {
  43. irq_anyport(&GPIO2_DR, isr_table_gpio2);
  44. }
  45. FASTRUN
  46. void irq_gpio3(void)
  47. {
  48. irq_anyport(&GPIO3_DR, isr_table_gpio3);
  49. }
  50. FASTRUN
  51. void irq_gpio4(void)
  52. {
  53. irq_anyport(&GPIO4_DR, isr_table_gpio4);
  54. }
  55. void attachInterrupt(uint8_t pin, void (*function)(void), int mode)
  56. {
  57. if (pin >= CORE_NUM_DIGITAL) return;
  58. //printf("attachInterrupt, pin=%u\n", pin);
  59. volatile uint32_t *gpio = portOutputRegister(pin);
  60. volatile uint32_t *mux = portConfigRegister(pin);
  61. //volatile uint32_t *pad = portControlRegister(pin);
  62. uint32_t mask = digitalPinToBitMask(pin);
  63. voidFuncPtr *table;
  64. switch((uint32_t)gpio) {
  65. case (uint32_t)&GPIO1_DR:
  66. table = isr_table_gpio1;
  67. attachInterruptVector(IRQ_GPIO1_0_15, &irq_gpio1);
  68. attachInterruptVector(IRQ_GPIO1_16_31, &irq_gpio1);
  69. NVIC_ENABLE_IRQ(IRQ_GPIO1_0_15);
  70. NVIC_ENABLE_IRQ(IRQ_GPIO1_16_31);
  71. break;
  72. case (uint32_t)&GPIO2_DR:
  73. table = isr_table_gpio2;
  74. attachInterruptVector(IRQ_GPIO2_0_15, &irq_gpio2);
  75. attachInterruptVector(IRQ_GPIO2_16_31, &irq_gpio2);
  76. NVIC_ENABLE_IRQ(IRQ_GPIO2_0_15);
  77. NVIC_ENABLE_IRQ(IRQ_GPIO2_16_31);
  78. break;
  79. case (uint32_t)&GPIO3_DR:
  80. table = isr_table_gpio3;
  81. attachInterruptVector(IRQ_GPIO3_0_15, &irq_gpio3);
  82. attachInterruptVector(IRQ_GPIO3_16_31, &irq_gpio3);
  83. NVIC_ENABLE_IRQ(IRQ_GPIO3_0_15);
  84. NVIC_ENABLE_IRQ(IRQ_GPIO3_16_31);
  85. break;
  86. case (uint32_t)&GPIO4_DR:
  87. table = isr_table_gpio4;
  88. attachInterruptVector(IRQ_GPIO4_0_15, &irq_gpio4);
  89. attachInterruptVector(IRQ_GPIO4_16_31, &irq_gpio4);
  90. NVIC_ENABLE_IRQ(IRQ_GPIO4_0_15);
  91. NVIC_ENABLE_IRQ(IRQ_GPIO4_16_31);
  92. break;
  93. default:
  94. return;
  95. }
  96. uint32_t icr;
  97. switch (mode) {
  98. case CHANGE: icr = 0; break;
  99. case RISING: icr = 2; break;
  100. case FALLING: icr = 3; break;
  101. case LOW: icr = 0; break;
  102. case HIGH: icr = 1; break;
  103. default: return;
  104. }
  105. // TODO: global interrupt disable to protect these read-modify-write accesses?
  106. gpio[IMR] &= ~mask; // disable interrupt
  107. *mux = 5; // pin is GPIO
  108. gpio[GDIR] &= ~mask; // pin to input mode
  109. uint32_t index = __builtin_ctz(mask);
  110. table[index] = function;
  111. if (mode == CHANGE) {
  112. gpio[EDGE] |= mask;
  113. } else {
  114. gpio[EDGE] &= ~mask;
  115. if (index < 15) {
  116. uint32_t shift = index * 2;
  117. gpio[ICR1] = (gpio[ICR1] & ~(3 << shift)) | (icr << shift);
  118. } else {
  119. uint32_t shift = (index - 16) * 2;
  120. gpio[ICR2] = (gpio[ICR2] & ~(3 << shift)) | (icr << shift);
  121. }
  122. }
  123. gpio[ISR] = mask; // clear any prior pending interrupt
  124. gpio[IMR] |= mask; // enable interrupt
  125. }
  126. void detachInterrupt(uint8_t pin)
  127. {
  128. if (pin >= CORE_NUM_DIGITAL) return;
  129. volatile uint32_t *gpio = portOutputRegister(pin);
  130. uint32_t mask = digitalPinToBitMask(pin);
  131. gpio[IMR] &= ~mask;
  132. }