Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

131 lines
3.5KB

  1. #include "Arduino.h"
  2. #include "pins_arduino.h"
  3. #include "debug/printf.h"
  4. #define DR_INDEX 0
  5. #define GDIR_INDEX 1
  6. #define PSR_INDEX 2
  7. #define ICR1_INDEX 3
  8. #define ICR2_INDEX 4
  9. #define IMR_INDEX 5
  10. #define ISR_INDEX 6
  11. #define EDGE_INDEX 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_INDEX] & gpio[IMR_INDEX];
  29. if (status) {
  30. gpio[ISR_INDEX] = 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. #endif
  48. void attachInterrupt(uint8_t pin, void (*function)(void), int mode)
  49. {
  50. if (pin >= CORE_NUM_DIGITAL) return;
  51. //printf("attachInterrupt, pin=%u\n", pin);
  52. volatile uint32_t *gpio = portOutputRegister(pin);
  53. volatile uint32_t *mux = portConfigRegister(pin);
  54. //volatile uint32_t *pad = portControlRegister(pin);
  55. uint32_t mask = digitalPinToBitMask(pin);
  56. voidFuncPtr *table;
  57. #if defined(__IMXRT1062__)
  58. switch((uint32_t)gpio) {
  59. case (uint32_t)&GPIO6_DR:
  60. table = isr_table_gpio1;
  61. break;
  62. case (uint32_t)&GPIO7_DR:
  63. table = isr_table_gpio2;
  64. break;
  65. case (uint32_t)&GPIO8_DR:
  66. table = isr_table_gpio3;
  67. break;
  68. case (uint32_t)&GPIO9_DR:
  69. table = isr_table_gpio4;
  70. break;
  71. default:
  72. return;
  73. }
  74. attachInterruptVector(IRQ_GPIO6789, &irq_gpio6789);
  75. NVIC_ENABLE_IRQ(IRQ_GPIO6789);
  76. #endif
  77. uint32_t icr;
  78. switch (mode) {
  79. case CHANGE: icr = 0; break;
  80. case RISING: icr = 2; break;
  81. case FALLING: icr = 3; break;
  82. case LOW: icr = 0; break;
  83. case HIGH: icr = 1; break;
  84. default: return;
  85. }
  86. // TODO: global interrupt disable to protect these read-modify-write accesses?
  87. gpio[IMR_INDEX] &= ~mask; // disable interrupt
  88. *mux = 5; // pin is GPIO
  89. gpio[GDIR_INDEX] &= ~mask; // pin to input mode
  90. uint32_t index = __builtin_ctz(mask);
  91. table[index] = function;
  92. if (mode == CHANGE) {
  93. gpio[EDGE_INDEX] |= mask;
  94. } else {
  95. gpio[EDGE_INDEX] &= ~mask;
  96. if (index < 15) {
  97. uint32_t shift = index * 2;
  98. gpio[ICR1_INDEX] = (gpio[ICR1_INDEX] & ~(3 << shift)) | (icr << shift);
  99. } else {
  100. uint32_t shift = (index - 16) * 2;
  101. gpio[ICR2_INDEX] = (gpio[ICR2_INDEX] & ~(3 << shift)) | (icr << shift);
  102. }
  103. }
  104. gpio[ISR_INDEX] = mask; // clear any prior pending interrupt
  105. gpio[IMR_INDEX] |= mask; // enable interrupt
  106. }
  107. void detachInterrupt(uint8_t pin)
  108. {
  109. if (pin >= CORE_NUM_DIGITAL) return;
  110. volatile uint32_t *gpio = portOutputRegister(pin);
  111. uint32_t mask = digitalPinToBitMask(pin);
  112. gpio[IMR_INDEX] &= ~mask;
  113. }