X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fsamd21%2Fao_exti_samd21.c;fp=src%2Fsamd21%2Fao_exti_samd21.c;h=962197837713975d0950d9e7db048fe0ae0f5050;hb=13f0b70a6346c9cfe04e5c494d3f34aa92e0db8b;hp=aa865cc2d2aef6103466ab3a019f54fb05a3ddac;hpb=ca76309700a3f6ec9775f6e6cce5915dcb4515c9;p=fw%2Faltos diff --git a/src/samd21/ao_exti_samd21.c b/src/samd21/ao_exti_samd21.c index aa865cc2..96219783 100644 --- a/src/samd21/ao_exti_samd21.c +++ b/src/samd21/ao_exti_samd21.c @@ -19,145 +19,151 @@ #include #include -struct samd21_exti { - void (*callback)(void); - uint8_t port; - uint8_t pin; +struct ao_samd21_exti { + void (*callback)(void); + struct samd21_port *port; + uint8_t pin; }; -#if 0 -static struct samd21_exti ao_samd_exti[SAMD21_NUM_EVSYS]; +static struct ao_samd21_exti ao_samd21_exti[SAMD21_NUM_EIC]; + +static uint8_t +pin_id(struct samd21_port *port, uint8_t pin) +{ + /* Why, atmel, why? */ + if (port == &samd21_port_a) { + switch (pin) { + case 24: + case 25: + case 27: + return pin - 12; + case 28: + case 30: + case 31: + return pin - 20; + default: + break; + } + } + + /* most pins use exti mapped to their pin number directly (mod 16) */ + return pin & 0xf; +} -static uint32_t ao_exti_inuse; -#endif void -samd21_evsys_isr(void) +samd21_eic_isr(void) { + uint32_t intflag = samd21_eic.intflag; + uint8_t id; + + for (id = 0; id < SAMD21_NUM_EIC; id++) { + uint32_t mask = (1 << id); + + if (intflag & mask) { + samd21_eic.intflag = mask; + if (ao_samd21_exti[id].callback) + (*ao_samd21_exti[id].callback)(); + } + } +} + +static void +_ao_exti_set_sense(uint8_t id, uint8_t mode) +{ + uint8_t sense = mode & (SAMD21_EIC_CONFIG_SENSE_RISE | SAMD21_EIC_CONFIG_SENSE_FALL); + uint8_t n = SAMD21_EIC_CONFIG_N(id); + uint32_t config; + + config = samd21_eic.config[n]; + config &= ~(SAMD21_EIC_CONFIG_SENSE_MASK << SAMD21_EIC_CONFIG_SENSE(id)); + config |= (sense << SAMD21_EIC_CONFIG_SENSE(id)); + samd21_eic.config[n] = config; } void ao_exti_setup (struct samd21_port *port, uint8_t pin, uint8_t mode, void (*callback)(void)) { - (void) port; - (void) pin; - (void) mode; - (void) callback; -#if 0 - uint8_t id = pin_id(port,pin); - uint8_t pint; - uint8_t mask; - uint8_t prio; - - for (pint = 0; pint < SAMD21_NUM_EVSYS; pint++) - if ((ao_exti_inuse & (1 << pint)) == 0) - break; + uint8_t id = pin_id(port,pin); + struct ao_samd21_exti *exti = &ao_samd21_exti[id]; - if (pint == SAMD21_NUM_EVSYS) + if (exti->port) ao_panic(AO_PANIC_EXTI); if (!(mode & AO_EXTI_PIN_NOCONFIGURE)) ao_enable_input(port, pin, mode); ao_arch_block_interrupts(); - mask = (1 << pint); - ao_exti_inuse |= mask; - ao_pint_enabled &= (uint8_t) ~mask; - - ao_pint_map[id] = pint; - ao_exti_callback[pint] = callback; - /* configure gpio to interrupt routing */ - lpc_scb.pintsel[pint] = id; + exti->port = port; + exti->pin = pin; + exti->callback = callback; /* Set edge triggered */ - lpc_gpio_pin.isel &= ~mask; + _ao_exti_set_sense(id, mode); - ao_pint_enabled &= (uint8_t) ~mask; - ao_pint_mode[pint] = mode; - _ao_exti_set_enable(pint); - - /* Set interrupt mask and rising/falling mode */ - - prio = AO_LPC_NVIC_MED_PRIORITY; - if (mode & AO_EXTI_PRIORITY_LOW) - prio = AO_LPC_NVIC_LOW_PRIORITY; - else if (mode & AO_EXTI_PRIORITY_HIGH) - prio = AO_LPC_NVIC_HIGH_PRIORITY; - - /* Set priority and enable */ - lpc_nvic_set_priority(LPC_ISR_PIN_INT0_POS + pint, prio); - lpc_nvic_set_enable(LPC_ISR_PIN_INT0_POS + pint); ao_arch_release_interrupts(); -#endif } void ao_exti_set_mode(struct samd21_port *port, uint8_t pin, uint8_t mode) { - (void) port; - (void) pin; - (void) mode; -#if 0 - uint8_t id = pin_id(port,pin); - uint8_t pint = ao_pint_map[id]; + uint8_t id = pin_id(port,pin); ao_arch_block_interrupts(); - ao_pint_mode[pint] = mode; - _ao_exti_set_enable(pint); + _ao_exti_set_sense(id, mode); ao_arch_release_interrupts(); -#endif } void ao_exti_set_callback(struct samd21_port *port, uint8_t pin, void (*callback)(void)) { - (void) port; - (void) pin; - (void) callback; -#if 0 uint8_t id = pin_id(port,pin); - uint8_t pint = ao_pint_map[id]; - ao_exti_callback[pint] = callback; -#endif + ao_arch_block_interrupts(); + ao_samd21_exti[id].callback = callback; + ao_arch_release_interrupts(); } void ao_exti_enable(struct samd21_port *port, uint8_t pin) { - (void) port; - (void) pin; -#if 0 uint8_t id = pin_id(port,pin); - uint8_t pint = ao_pint_map[id]; - uint8_t mask = 1 << pint; ao_arch_block_interrupts(); - ao_pint_enabled |= mask; - _ao_exti_set_enable(pint); + samd21_eic.intenset = 1 << id; + /* configure gpio to interrupt routing */ + samd21_port_pmux_set(port, pin, SAMD21_PORT_PMUX_FUNC_A); ao_arch_release_interrupts(); -#endif } void ao_exti_disable(struct samd21_port *port, uint8_t pin) { - (void) port; - (void) pin; -#if 0 uint8_t id = pin_id(port,pin); - uint8_t pint = ao_pint_map[id]; - uint8_t mask = 1 << pint; ao_arch_block_interrupts(); - ao_pint_enabled &= (uint8_t) ~mask; - _ao_exti_set_enable(pint); + samd21_eic.intenclr = 1 << id; + /* configure gpio to interrupt routing */ + samd21_port_pmux_clr(port, pin); ao_arch_release_interrupts(); -#endif } void ao_exti_init(void) { + samd21_gclk_clkctrl(0, SAMD21_GCLK_CLKCTRL_ID_EIC); + + /* Reset */ + samd21_eic.ctrl = (1 << SAMD21_EIC_CTRL_SWRST); + + while (samd21_eic.status & (1 << SAMD21_EIC_STATUS_SYNCBUSY)) + ; + + /* Wire up interrupts */ + samd21_nvic_set_enable(SAMD21_NVIC_ISR_EIC_POS); + samd21_nvic_set_priority(SAMD21_NVIC_ISR_EIC_POS, 3); + + /* Enable */ + samd21_eic.ctrl = (1 << SAMD21_EIC_CTRL_ENABLE); }