X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=src%2Fstm%2Fao_exti_stm.c;h=11099b02112994d023df580d5cbb01e2748af91b;hp=013d453be2f456dce4540280d3bb4a81e3157745;hb=6171892fa32e8a662a494ec6ba28a82fddc68589;hpb=1489263b895a2a825e29d0560c9b1dbba8a3f431 diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 013d453b..11099b02 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -20,39 +20,56 @@ static void (*ao_exti_callback[16])(void); -static void -ao_exti_isr(void) { - uint32_t pending = stm_exti.pr; - uint8_t pin; +uint32_t ao_last_exti; + +static void ao_exti_one_isr(uint8_t pin) { + uint32_t pending = (ao_last_exti = stm_exti.pr) & (1 << pin); - /* Clear pending interrupts */ stm_exti.pr = pending; - for (pin = 0; pin < 16 && pending; pin++) { - uint32_t mask = (1 << pin); + if (pending && ao_exti_callback[pin]) + (*ao_exti_callback[pin])(); +} - if (pending & mask) { - pending &= ~mask; - if (ao_exti_callback[pin]) - (*ao_exti_callback[pin])(); - } +static void ao_exti_range_isr(uint8_t first, uint8_t last, uint16_t mask) { + uint16_t pending = (ao_last_exti = stm_exti.pr) & mask; + uint8_t pin; + static uint16_t last_mask; + static uint8_t last_pin; + + if (pending == last_mask) { + stm_exti.pr = last_mask; + (*ao_exti_callback[last_pin])(); + return; } + stm_exti.pr = pending; + for (pin = first; pin <= last; pin++) + if ((pending & ((uint32_t) 1 << pin)) && ao_exti_callback[pin]) { + last_mask = (1 << pin); + last_pin = pin; + (*ao_exti_callback[pin])(); + } } -void stm_exti0_isr(void) { ao_exti_isr(); } -void stm_exti1_isr(void) { ao_exti_isr(); } -void stm_exti2_isr(void) { ao_exti_isr(); } -void stm_exti3_isr(void) { ao_exti_isr(); } -void stm_exti4_isr(void) { ao_exti_isr(); } -void stm_exti9_5_isr(void) { ao_exti_isr(); } -void stm_exti15_10_isr(void) { ao_exti_isr(); } +void stm_exti0_isr(void) { ao_exti_one_isr(0); } +void stm_exti1_isr(void) { ao_exti_one_isr(1); } +void stm_exti2_isr(void) { ao_exti_one_isr(2); } +void stm_exti3_isr(void) { ao_exti_one_isr(3); } +void stm_exti4_isr(void) { ao_exti_one_isr(4); } +void stm_exti9_5_isr(void) { ao_exti_range_isr(5, 9, 0x3e0); } +void stm_exti15_10_isr(void) { ao_exti_range_isr(10, 15, 0xfc00); } void ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) { uint32_t mask = 1 << pin; uint32_t pupdr; uint8_t irq; - + uint8_t prio; + ao_exti_callback[pin] = callback; + + /* configure gpio to interrupt routing */ + stm_exticr_set(gpio, pin); + /* configure pin as input, setting selected pull-up/down mode */ stm_moder_set(gpio, pin, STM_MODER_INPUT); switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) { @@ -71,11 +88,14 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback /* Set interrupt mask and rising/falling mode */ stm_exti.imr &= ~mask; - stm_exti.rtsr |= mask; if (mode & AO_EXTI_MODE_RISING) stm_exti.rtsr |= mask; + else + stm_exti.rtsr &= ~mask; if (mode & AO_EXTI_MODE_FALLING) stm_exti.ftsr |= mask; + else + stm_exti.ftsr &= ~mask; if (pin <= 4) irq = STM_ISR_EXTI0_POS + pin; @@ -83,27 +103,58 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback irq = STM_ISR_EXTI9_5_POS; else irq = STM_ISR_EXTI15_10_POS; - stm_nvic_set_priority(irq, 10); + + /* Set priority */ + prio = AO_STM_NVIC_MED_PRIORITY; + if (mode & AO_EXTI_PRIORITY_LOW) + prio = AO_STM_NVIC_LOW_PRIORITY; + else if (mode & AO_EXTI_PRIORITY_HIGH) + prio = AO_STM_NVIC_HIGH_PRIORITY; + + stm_nvic_set_priority(irq, prio); stm_nvic_set_enable(irq); } +void +ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) { + uint32_t mask = 1 << pin; + + if (mode & AO_EXTI_MODE_RISING) + stm_exti.rtsr |= mask; + else + stm_exti.rtsr &= ~mask; + if (mode & AO_EXTI_MODE_FALLING) + stm_exti.ftsr |= mask; + else + stm_exti.ftsr &= ~mask; +} + +void +ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) { + ao_exti_callback[pin] = callback; +} + void ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) { + uint32_t mask = (1 << pin); + stm_exti.pr = mask; stm_exti.imr |= (1 << pin); } void ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) { - stm_exti.imr &= ~(1 << pin); + uint32_t mask = (1 << pin); + stm_exti.imr &= ~mask; + stm_exti.pr = mask; } void ao_exti_init(void) { - stm_nvic_set_priority(STM_ISR_EXTI1_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI2_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI3_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI4_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI9_5_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI15_10_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI1_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI2_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI3_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI4_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI9_5_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI15_10_POS, AO_STM_NVIC_MED_PRIORITY); }