diff options
Diffstat (limited to 'libmaple/timer.c')
-rw-r--r-- | libmaple/timer.c | 89 |
1 files changed, 62 insertions, 27 deletions
diff --git a/libmaple/timer.c b/libmaple/timer.c index d64e3e9..d204fef 100644 --- a/libmaple/timer.c +++ b/libmaple/timer.c @@ -152,66 +152,101 @@ static void output_compare_mode(timer_dev *dev, uint8 channel) { timer_cc_enable(dev, channel); } -/* FIXME: These IRQ enable routines fail for timers 9 through 14. - * We don't support those timers yet, so it's OK for now, but this - * really needs to get fixed. */ - -static void enable_advanced_irq(timer_dev *dev, timer_interrupt_id id); -static void enable_nonmuxed_irq(timer_dev *dev); +static void enable_adv_irq(timer_dev *dev, timer_interrupt_id id); +static void enable_bas_gen_irq(timer_dev *dev); static inline void enable_irq(timer_dev *dev, timer_interrupt_id iid) { if (dev->type == TIMER_ADVANCED) { - enable_advanced_irq(dev, iid); + enable_adv_irq(dev, iid); } else { - enable_nonmuxed_irq(dev); + enable_bas_gen_irq(dev); } } -static void enable_advanced_irq(timer_dev *dev, timer_interrupt_id id) { - uint8 is_timer1 = dev->clk_id == RCC_TIMER1; - +/* Advanced control timers have several IRQ lines corresponding to + * different timer interrupts. + * + * Note: This function assumes that the only advanced timers are TIM1 + * and TIM8, and needs the obvious changes if that assumption is + * violated by a later STM32 series. */ +static void enable_adv_irq(timer_dev *dev, timer_interrupt_id id) { + uint8 is_tim1 = dev->clk_id == RCC_TIMER1; + nvic_irq_num irq_num; switch (id) { case TIMER_UPDATE_INTERRUPT: - nvic_irq_enable(is_timer1 ? NVIC_TIMER1_UP : NVIC_TIMER8_UP); + irq_num = (is_tim1 ? + NVIC_TIMER1_UP_TIMER10 : + NVIC_TIMER8_UP_TIMER13); break; - case TIMER_CC1_INTERRUPT: - case TIMER_CC2_INTERRUPT: - case TIMER_CC3_INTERRUPT: + case TIMER_CC1_INTERRUPT: /* Fall through */ + case TIMER_CC2_INTERRUPT: /* ... */ + case TIMER_CC3_INTERRUPT: /* ... */ case TIMER_CC4_INTERRUPT: - nvic_irq_enable(is_timer1 ? NVIC_TIMER1_CC : NVIC_TIMER8_CC); + irq_num = is_tim1 ? NVIC_TIMER1_CC : NVIC_TIMER8_CC; break; - case TIMER_COM_INTERRUPT: + case TIMER_COM_INTERRUPT: /* Fall through */ case TIMER_TRG_INTERRUPT: - nvic_irq_enable(is_timer1 ? NVIC_TIMER1_TRG_COM : NVIC_TIMER8_TRG_COM); + irq_num = (is_tim1 ? + NVIC_TIMER1_TRG_COM_TIMER11 : + NVIC_TIMER8_TRG_COM_TIMER14); break; case TIMER_BREAK_INTERRUPT: - nvic_irq_enable(is_timer1 ? NVIC_TIMER1_BRK : NVIC_TIMER8_BRK); + irq_num = (is_tim1 ? + NVIC_TIMER1_BRK_TIMER9 : + NVIC_TIMER8_BRK_TIMER12); break; + default: + /* Can't happen, but placate the compiler */ + ASSERT(0); + return; } + nvic_irq_enable(irq_num); } -static void enable_nonmuxed_irq(timer_dev *dev) { +/* Basic and general purpose timers have a single IRQ line, which is + * shared by all interrupts supported by a particular timer. */ +static void enable_bas_gen_irq(timer_dev *dev) { + nvic_irq_num irq_num; switch (dev->clk_id) { case RCC_TIMER2: - nvic_irq_enable(NVIC_TIMER2); + irq_num = NVIC_TIMER2; break; case RCC_TIMER3: - nvic_irq_enable(NVIC_TIMER3); + irq_num = NVIC_TIMER3; break; case RCC_TIMER4: - nvic_irq_enable(NVIC_TIMER4); + irq_num = NVIC_TIMER4; break; case RCC_TIMER5: - nvic_irq_enable(NVIC_TIMER5); + irq_num = NVIC_TIMER5; break; case RCC_TIMER6: - nvic_irq_enable(NVIC_TIMER6); + irq_num = NVIC_TIMER6; break; case RCC_TIMER7: - nvic_irq_enable(NVIC_TIMER7); + irq_num = NVIC_TIMER7; + break; + case RCC_TIMER9: + irq_num = NVIC_TIMER1_BRK_TIMER9; + break; + case RCC_TIMER10: + irq_num = NVIC_TIMER1_UP_TIMER10; + break; + case RCC_TIMER11: + irq_num = NVIC_TIMER1_TRG_COM_TIMER11; + break; + case RCC_TIMER12: + irq_num = NVIC_TIMER8_BRK_TIMER12; + break; + case RCC_TIMER13: + irq_num = NVIC_TIMER8_UP_TIMER13; + break; + case RCC_TIMER14: + irq_num = NVIC_TIMER8_TRG_COM_TIMER14; break; default: ASSERT_FAULT(0); - break; + return; } + nvic_irq_enable(irq_num); } |