|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- #include "Arduino.h"
- #include "pins_arduino.h"
- #include "debug/printf.h"
-
- static void dummy_isr() {};
- typedef void (*voidFuncPtr)(void);
-
- // TODO: Use of Fast GPIO6 - GPIO9 probably breaks everything about attachInterrupt()
-
- // TODO: define these properly in core_pins.h - don't waste memory
- #define CORE_MAX_PIN_PORT1 31
- #define CORE_MAX_PIN_PORT2 31
- #define CORE_MAX_PIN_PORT3 31
- #define CORE_MAX_PIN_PORT4 31
-
- voidFuncPtr isr_table_gpio1[CORE_MAX_PIN_PORT1+1] = { [0 ... CORE_MAX_PIN_PORT1] = dummy_isr };
- voidFuncPtr isr_table_gpio2[CORE_MAX_PIN_PORT2+1] = { [0 ... CORE_MAX_PIN_PORT2] = dummy_isr };
- voidFuncPtr isr_table_gpio3[CORE_MAX_PIN_PORT3+1] = { [0 ... CORE_MAX_PIN_PORT3] = dummy_isr };
- voidFuncPtr isr_table_gpio4[CORE_MAX_PIN_PORT4+1] = { [0 ... CORE_MAX_PIN_PORT4] = dummy_isr };
-
- #define DR 0
- #define GDIR 1
- #define PSR 2
- #define ICR1 3
- #define ICR2 4
- #define IMR 5
- #define ISR 6
- #define EDGE 7
-
- FASTRUN
- void irq_anyport(volatile uint32_t *gpio, voidFuncPtr *table)
- {
- uint32_t status = gpio[ISR] & gpio[IMR];
- gpio[ISR] = status;
- while (status) {
- uint32_t index = __builtin_ctz(status);
- table[index]();
- status = status & ~(1 << index);
- //status = status & (status - 1);
- }
- }
-
- FASTRUN
- void irq_gpio1(void)
- {
- irq_anyport(&GPIO1_DR, isr_table_gpio1);
- }
-
- FASTRUN
- void irq_gpio2(void)
- {
- irq_anyport(&GPIO2_DR, isr_table_gpio2);
- }
-
- FASTRUN
- void irq_gpio3(void)
- {
- irq_anyport(&GPIO3_DR, isr_table_gpio3);
- }
-
- FASTRUN
- void irq_gpio4(void)
- {
- irq_anyport(&GPIO4_DR, isr_table_gpio4);
- }
-
-
-
- void attachInterrupt(uint8_t pin, void (*function)(void), int mode)
- {
- if (pin >= CORE_NUM_DIGITAL) return;
- //printf("attachInterrupt, pin=%u\n", pin);
- volatile uint32_t *gpio = portOutputRegister(pin);
- volatile uint32_t *mux = portConfigRegister(pin);
- //volatile uint32_t *pad = portControlRegister(pin);
- uint32_t mask = digitalPinToBitMask(pin);
-
- voidFuncPtr *table;
- switch((uint32_t)gpio) {
- case (uint32_t)&GPIO1_DR:
- table = isr_table_gpio1;
- attachInterruptVector(IRQ_GPIO1_0_15, &irq_gpio1);
- attachInterruptVector(IRQ_GPIO1_16_31, &irq_gpio1);
- NVIC_ENABLE_IRQ(IRQ_GPIO1_0_15);
- NVIC_ENABLE_IRQ(IRQ_GPIO1_16_31);
- break;
- case (uint32_t)&GPIO2_DR:
- table = isr_table_gpio2;
- attachInterruptVector(IRQ_GPIO2_0_15, &irq_gpio2);
- attachInterruptVector(IRQ_GPIO2_16_31, &irq_gpio2);
- NVIC_ENABLE_IRQ(IRQ_GPIO2_0_15);
- NVIC_ENABLE_IRQ(IRQ_GPIO2_16_31);
- break;
- case (uint32_t)&GPIO3_DR:
- table = isr_table_gpio3;
- attachInterruptVector(IRQ_GPIO3_0_15, &irq_gpio3);
- attachInterruptVector(IRQ_GPIO3_16_31, &irq_gpio3);
- NVIC_ENABLE_IRQ(IRQ_GPIO3_0_15);
- NVIC_ENABLE_IRQ(IRQ_GPIO3_16_31);
- break;
- case (uint32_t)&GPIO4_DR:
- table = isr_table_gpio4;
- attachInterruptVector(IRQ_GPIO4_0_15, &irq_gpio4);
- attachInterruptVector(IRQ_GPIO4_16_31, &irq_gpio4);
- NVIC_ENABLE_IRQ(IRQ_GPIO4_0_15);
- NVIC_ENABLE_IRQ(IRQ_GPIO4_16_31);
- break;
- default:
- return;
- }
-
- uint32_t icr;
- switch (mode) {
- case CHANGE: icr = 0; break;
- case RISING: icr = 2; break;
- case FALLING: icr = 3; break;
- case LOW: icr = 0; break;
- case HIGH: icr = 1; break;
- default: return;
- }
-
- // TODO: global interrupt disable to protect these read-modify-write accesses?
- gpio[IMR] &= ~mask; // disable interrupt
- *mux = 5; // pin is GPIO
- gpio[GDIR] &= ~mask; // pin to input mode
- uint32_t index = __builtin_ctz(mask);
- table[index] = function;
- if (mode == CHANGE) {
- gpio[EDGE] |= mask;
- } else {
- gpio[EDGE] &= ~mask;
- if (index < 15) {
- uint32_t shift = index * 2;
- gpio[ICR1] = (gpio[ICR1] & ~(3 << shift)) | (icr << shift);
- } else {
- uint32_t shift = (index - 16) * 2;
- gpio[ICR2] = (gpio[ICR2] & ~(3 << shift)) | (icr << shift);
- }
- }
- gpio[ISR] = mask; // clear any prior pending interrupt
- gpio[IMR] |= mask; // enable interrupt
- }
-
- void detachInterrupt(uint8_t pin)
- {
- if (pin >= CORE_NUM_DIGITAL) return;
- volatile uint32_t *gpio = portOutputRegister(pin);
- uint32_t mask = digitalPinToBitMask(pin);
- gpio[IMR] &= ~mask;
- }
-
|