選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

interrupt.c 3.9KB

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