diff options
Diffstat (limited to 'libmaple')
| -rw-r--r-- | libmaple/timers.c | 493 | ||||
| -rw-r--r-- | libmaple/timers.h | 65 | 
2 files changed, 187 insertions, 371 deletions
| diff --git a/libmaple/timers.c b/libmaple/timers.c index 6fa2848..2941cd6 100644 --- a/libmaple/timers.c +++ b/libmaple/timers.c @@ -35,103 +35,58 @@  #include "nvic.h"  #include "timers.h" -typedef struct { -    volatile uint16 CR1; -    uint16  RESERVED0; -    volatile uint16 CR2; -    uint16  RESERVED1; -    volatile uint16 SMCR; -    uint16  RESERVED2; -    volatile uint16 DIER; -    uint16  RESERVED3; -    volatile uint16 SR; -    uint16  RESERVED4; -    volatile uint16 EGR; -    uint16  RESERVED5; -    volatile uint16 CCMR1; -    uint16  RESERVED6; -    volatile uint16 CCMR2; -    uint16  RESERVED7; -    volatile uint16 CCER; -    uint16  RESERVED8; -    volatile uint16 CNT; -    uint16  RESERVED9; -    volatile uint16 PSC; -    uint16  RESERVED10; -    volatile uint16 ARR; -    uint16  RESERVED11; -    volatile uint16 RCR; -    uint16  RESERVED12; -    volatile uint16 CCR1; -    uint16  RESERVED13; -    volatile uint16 CCR2; -    uint16  RESERVED14; -    volatile uint16 CCR3; -    uint16  RESERVED15; -    volatile uint16 CCR4; -    uint16  RESERVED16; -    volatile uint16 BDTR;   // Not used in general purpose timers -    uint16  RESERVED17;     // Not used in general purpose timers -    volatile uint16 DCR; -    uint16  RESERVED18; -    volatile uint16 DMAR; -    uint16  RESERVED19; -} Timer; - -// These are the output compare interrupt functions that get called by the -// handlers below -volatile static voidFuncPtr timer1_handlers[4]; -volatile static voidFuncPtr timer2_handlers[4]; -volatile static voidFuncPtr timer3_handlers[4]; -volatile static voidFuncPtr timer4_handlers[4]; -#if NR_TIMERS >= 8 -volatile static voidFuncPtr timer5_handlers[4]; // High-density devices only -volatile static voidFuncPtr timer8_handlers[4]; // High-density devices only -#endif +// Timer descriptor table +struct timer_dev timer_dev_table[] = { +   [TIMER1] = { +      .base = (timer_port*)TIMER1_BASE, +      .rcc_dev_num = RCC_TIMER1, +      .nvic_dev_num = NVIC_TIMER1 +   }, +   [TIMER2] = { +      .base = (timer_port*)TIMER2_BASE, +      .rcc_dev_num = RCC_TIMER2, +      .nvic_dev_num = NVIC_TIMER2 +   }, +   [TIMER3] = { +      .base = (timer_port*)TIMER3_BASE, +      .rcc_dev_num = RCC_TIMER3, +      .nvic_dev_num = NVIC_TIMER3 +   }, +   [TIMER4] = { +      .base = (timer_port*)TIMER4_BASE, +      .rcc_dev_num = RCC_TIMER4, +      .nvic_dev_num = NVIC_TIMER4 +   }, +   #if NR_TIMERS >= 8 +   // High density devices only (eg, Maple Native) +   [TIMER5] = { +      .base = (timer_port*)TIMER5_BASE, +      .rcc_dev_num = RCC_TIMER5, +      .nvic_dev_num = NVIC_TIMER5 +   }, +   [TIMER8] = { +      .base = (timer_port*)TIMER8_BASE, +      .rcc_dev_num = RCC_TIMER8, +      .nvic_dev_num = NVIC_TIMER8 +   }, +   #endif  +};  // This function should probably be rewriten to take (timer_num, mode) and have  // prescaler set elsewhere. The mode can be passed through to set_mode at the   // end  void timer_init(uint8 timer_num, uint16 prescale) { -     -    Timer *timer; uint8 is_advanced = 0; +    ASSERT((timer_num != TIMER6) && (timer_num != TIMER7));     // TODO: doesn't catch 6+7 -    ASSERT(timer_num > 0 && timer_num <= 4); +    timer_port *timer = timer_dev_table[timer_num].base; +    uint8 is_advanced = 0; -    switch(timer_num) { -    case 1: -        timer = (Timer*)TIMER1_BASE; -        rcc_clk_enable(RCC_TIMER1); -        is_advanced = 1; -        break; -    case 2: -        timer = (Timer*)TIMER2_BASE; -        rcc_clk_enable(RCC_TIMER2); -        break; -    case 3: -        timer = (Timer*)TIMER3_BASE; -        rcc_clk_enable(RCC_TIMER3); -        break; -    case 4: -        timer = (Timer*)TIMER4_BASE; -        rcc_clk_enable(RCC_TIMER4); -        break; -    #if NR_TIMERS >= 8 -    case 5: -        timer = (Timer*)TIMER5_BASE; -        rcc_clk_enable(RCC_TIMER5); -        break; -    case 8: -        timer = (Timer*)TIMER8_BASE; -        rcc_clk_enable(RCC_TIMER8); +    if((timer_num == TIMER1) || (timer_num == TIMER8)) {          is_advanced = 1; -        break; -    #endif -    default: -        ASSERT(0); -        return;      } +    rcc_clk_enable(timer_dev_table[timer_num].rcc_dev_num); +      timer->CR1 = ARPE;        // No clock division                                // Do not buffer auto-reload preload                                // Edge aligned @@ -176,155 +131,47 @@ void timer_init(uint8 timer_num, uint16 prescale) {  // Stops the counter; the mode and settings are not modified  void timer_pause(uint8 timer_num) {  -    Timer *timer; -    ASSERT(timer_num > 0 && timer_num <= 4); +    timer_port *timer = timer_dev_table[timer_num].base; -    switch(timer_num) { -    case 1: -        timer = (Timer*)TIMER1_BASE; -        break; -    case 2: -        timer = (Timer*)TIMER2_BASE; -        break; -    case 3: -        timer = (Timer*)TIMER3_BASE; -        break; -    case 4: -        timer = (Timer*)TIMER4_BASE; -        break; -    default: -        ASSERT(0); -        return; -    }      timer->CR1 &= ~(0x0001);    // CEN  }  // Starts the counter; the mode and settings are not modified  void timer_resume(uint8 timer_num) {  -    Timer *timer; -    ASSERT(timer_num > 0 && timer_num <= 4); +    timer_port *timer = timer_dev_table[timer_num].base; -    switch(timer_num) { -    case 1: -        timer = (Timer*)TIMER1_BASE; -        break; -    case 2: -        timer = (Timer*)TIMER2_BASE; -        break; -    case 3: -        timer = (Timer*)TIMER3_BASE; -        break; -    case 4: -        timer = (Timer*)TIMER4_BASE; -        break; -    default: -        ASSERT(0); -        return; -    } -    timer->CR1 |= 0x0001;    // CEN +    timer->CR1 |= 0x0001;       // CEN  }  // This function sets the counter value via register for the specified timer.  // Can't think of specific usecases except for resetting to zero but it's easy  // to implement and allows for "creative" programming  void timer_set_count(uint8 timer_num, uint16 value) {  -Timer *timer; -ASSERT(timer_num > 0 && timer_num <= 4); +    timer_port *timer = timer_dev_table[timer_num].base; -    switch(timer_num) { -    case 1: -        timer = (Timer*)TIMER1_BASE; -        break; -    case 2: -        timer = (Timer*)TIMER2_BASE; -        break; -    case 3: -        timer = (Timer*)TIMER3_BASE; -        break; -    case 4: -        timer = (Timer*)TIMER4_BASE; -        break; -    default: -        ASSERT(0); -        return; -    }      timer->CNT = value;  }  // Returns the current timer counter value. Probably very inaccurate if the  // counter is running with a low prescaler.  uint16 timer_get_count(uint8 timer_num) { -    Timer *timer; -    ASSERT(timer_num > 0 && timer_num <= 4); +    timer_port *timer = timer_dev_table[timer_num].base; -    switch(timer_num) { -    case 1: -        timer = (Timer*)TIMER1_BASE; -        break; -    case 2: -        timer = (Timer*)TIMER2_BASE; -        break; -    case 3: -        timer = (Timer*)TIMER3_BASE; -        break; -    case 4: -        timer = (Timer*)TIMER4_BASE; -        break; -    default: -        ASSERT(0); -        return; -    }      return timer->CNT;  }  // Does what it says  void timer_set_prescaler(uint8 timer_num, uint16 prescale) { -    Timer *timer; -    ASSERT(timer_num > 0 && timer_num <= 4); +    timer_port *timer = timer_dev_table[timer_num].base; -    switch(timer_num) { -    case 1: -        timer = (Timer*)TIMER1_BASE; -        break; -    case 2: -        timer = (Timer*)TIMER2_BASE; -        break; -    case 3: -        timer = (Timer*)TIMER3_BASE; -        break; -    case 4: -        timer = (Timer*)TIMER4_BASE; -        break; -    default: -        ASSERT(0); -        return; -    }      timer->PSC = prescale;  }  // This sets the "reload" or "overflow" value for the entire timer. We should  // probably settle on either "reload" or "overflow" to prevent confusion?  void timer_set_reload(uint8 timer_num, uint16 max_reload) { -    Timer *timer; -    ASSERT(timer_num > 0 && timer_num <= 4); +    timer_port *timer = timer_dev_table[timer_num].base; -    switch(timer_num) { -    case 1: -        timer = (Timer*)TIMER1_BASE; -        break; -    case 2: -        timer = (Timer*)TIMER2_BASE; -        break; -    case 3: -        timer = (Timer*)TIMER3_BASE; -        break; -    case 4: -        timer = (Timer*)TIMER4_BASE; -        break; -    default: -        ASSERT(0); -        return; -    }      timer->ARR = max_reload;  } @@ -332,70 +179,36 @@ void timer_set_reload(uint8 timer_num, uint16 max_reload) {  // or similar to prevent interrupts and PWM output without 16 seperate function  // calls to timer_set_mode  void timer_disable_all(void) { +    // TODO: refactor      // Note: this must be very robust because it gets called from, eg, ASSERT -    Timer *timer;  -    Timer *timers[4] = { (Timer*)TIMER1_BASE, -                         (Timer*)TIMER2_BASE,  -                         (Timer*)TIMER3_BASE,  -                         (Timer*)TIMER4_BASE,  -                       };  +    timer_port *timer;   +    timer_port *timers[4] = { (timer_port*)TIMER1_BASE, +                         (timer_port*)TIMER2_BASE,   +                         (timer_port*)TIMER3_BASE,   +                         (timer_port*)TIMER4_BASE,   +                       };        int i; -    for (i = 0; i < 4; i++) {  -        timer = timers[i];  -        timer->CR1 = 0;  -        timer->CCER = 0;  -    }  +    for (i = 0; i < 4; i++) {   +        timer = timers[i];   +        timer->CR1 = 0;   +        timer->CCER = 0;   +    }  }  // Sets the mode of individual timer channels, including a DISABLE mode  void timer_set_mode(uint8 timer_num, uint8 channel, uint8 mode) { -    Timer *timer; -    switch (timer_num) { -    case 1: -        timer = (Timer*)TIMER1_BASE; -        break; -    case 2: -        timer = (Timer*)TIMER2_BASE; -        break; -    case 3: -        timer = (Timer*)TIMER3_BASE; -        break; -    case 4: -        timer = (Timer*)TIMER4_BASE; -        break; -    default: -        ASSERT(0); -    } +    timer_port *timer = timer_dev_table[timer_num].base; +    ASSERT(channel >= 1); +      switch(mode) {      case TIMER_DISABLED:          // Disable the channel          // Disable any interrupt          // Clear interrupt SR? (TODO) -        switch (channel) { -        case 1: -            timer->DIER &= ~(1 << channel); // 1-indexed compare nums -            timer->CCER &= ~(0x1); -            timer_detach_interrupt(timer_num, channel); -            break; -        case 2: -            timer->DIER &= ~(1 << channel); // 1-indexed compare nums -            timer->CCER &= ~(0x10); -            timer_detach_interrupt(timer_num, channel); -            break; -        case 3: -            timer->DIER &= ~(1 << channel); // 1-indexed compare nums -            timer->CCER &= ~(0x100); -            timer_detach_interrupt(timer_num, channel); -            break; -        case 4: -            timer->DIER &= ~(1 << channel); // 1-indexed compare nums -            timer->CCER &= ~(0x1000); -            timer_detach_interrupt(timer_num, channel); -            break; -        default: -            ASSERT(0); -        } +        timer->DIER &= ~(1 << channel); // 1-indexed compare nums +        timer_detach_interrupt(timer_num, channel); +        timer->CCER &= ~(1 << (4*(channel - 1))); // 0-indexed           break;      case TIMER_PWM:          // Set CCMR mode @@ -403,34 +216,29 @@ void timer_set_mode(uint8 timer_num, uint8 channel, uint8 mode) {          // Disable any interrupt          // Clear interrupt SR? (TODO)          // Enable channel +        timer->DIER &= ~(1 << channel); // 1-indexed compare nums          switch (channel) {          case 1: -            timer->DIER &= ~(1 << channel); // 1-indexed compare nums              timer->CCMR1 &= ~(0xFF);                  timer->CCMR1 |= 0x68;       // PWM mode 1, enable preload register. -            timer->CCER  |= 0x0001;     // enable ch              break;          case 2: -            timer->DIER &= ~(1 << channel); // 1-indexed compare nums              timer->CCMR1 &= ~(0xFF00);                  timer->CCMR1 |= (0x68 << 8);// PWM mode 1, enable preload register. -            timer->CCER  |= 0x0010;     // enable ch              break;          case 3: -            timer->DIER &= ~(1 << channel); // 1-indexed compare nums              timer->CCMR2 &= ~(0xFF);                  timer->CCMR2 |= 0x68;       // PWM mode 1, enable preload register. -            timer->CCER  |= 0x0100;     // enable ch              break;          case 4: -            timer->DIER &= ~(1 << channel); // 1-indexed compare nums              timer->CCMR2 &= ~(0xFF00);                  timer->CCMR2 |= (0x68 << 8);// PWM mode 1, enable preload register. -            timer->CCER  |= 0x1000;     // enable ch              break;          default:              ASSERT(0);          } +        timer->CCER |= (1 << (4*(channel - 1))); // Enable +        break;      case TIMER_OUTPUTCOMPARE:          // Set CCMR mode          // Keep existing reload value @@ -441,26 +249,23 @@ void timer_set_mode(uint8 timer_num, uint8 channel, uint8 mode) {          case 1:              timer->CCMR1 &= ~(0xFF);                  timer->CCMR1 |= 0x0010;       // PWM mode 1, enable preload register. -            timer->CCER  |= 0x001;        // enable ch              break;          case 2:              timer->CCMR1 &= ~(0xFF00);                  timer->CCMR1 |= 0x1000;       // PWM mode 1, enable preload register. -            timer->CCER  |= 0x0010;       // enable ch              break;          case 3:              timer->CCMR2 &= ~(0xFF);                  timer->CCMR2 |= 0x0010;       // PWM mode 1, enable preload register. -            timer->CCER  |= 0x0100;       // enable ch              break;          case 4:              timer->CCMR2 &= ~(0xFF00);                  timer->CCMR2 |= 0x1000;       // PWM mode 1, enable preload register. -            timer->CCER  |= 0x1000;       // enable ch              break;          default:              ASSERT(0);          } +        timer->CCER |= (1 << (4*(channel - 1))); // Enable          break;      default:          ASSERT(0); @@ -470,25 +275,11 @@ void timer_set_mode(uint8 timer_num, uint8 channel, uint8 mode) {  // This sets the compare value (aka the trigger) for a given timer channel  void timer_set_compare_value(uint8 timer_num, uint8 compare_num, uint16 value) {      // The faster version of this function is the inline timer_pwm_write_ccr +    // +    timer_port *timer = timer_dev_table[timer_num].base; -    Timer *timer; TimerCCR *timer_ccr;  -    ASSERT(timer_num <= 4 && timer_num > 0 &&  -        compare_num > 0 && compare_num <= 4); +    ASSERT(compare_num > 0 && compare_num <= 4); -    switch(timer_num) { -    case 1: -        timer = (Timer*)TIMER1_BASE; -        break; -    case 2: -        timer = (Timer*)TIMER2_BASE; -        break; -    case 3: -        timer = (Timer*)TIMER3_BASE; -        break; -    case 4: -        timer = (Timer*)TIMER4_BASE; -        break; -    }      switch(compare_num) {      case 1:          timer->CCR1 = value; @@ -508,63 +299,22 @@ void timer_set_compare_value(uint8 timer_num, uint8 compare_num, uint16 value) {  // Stores a pointer to the passed usercode interrupt function and configures  // the actual ISR so that it will actually be called  void timer_attach_interrupt(uint8 timer_num, uint8 compare_num, voidFuncPtr handler) { -    Timer *timer; -    ASSERT(timer_num > 0 && timer_num <= 4 && compare_num > 0 && compare_num <= 4); +    ASSERT(compare_num > 0 && compare_num <= 4); -    switch(timer_num) { -    case 1: -        timer = (Timer*)TIMER1_BASE; -        timer1_handlers[compare_num-1] = handler; -        nvic_irq_enable(NVIC_TIMER1); -        timer->DIER |= (1 << compare_num); // 1-indexed compare nums -        break; -    case 2: -        timer = (Timer*)TIMER2_BASE; -        timer2_handlers[compare_num-1] = handler; -        nvic_irq_enable(NVIC_TIMER2); -        timer->DIER |= (1 << compare_num); // 1-indexed compare nums -        break; -    case 3: -        timer = (Timer*)TIMER3_BASE; -        timer3_handlers[compare_num-1] = handler; -        nvic_irq_enable(NVIC_TIMER3); -        timer->DIER |= (1 << compare_num); // 1-indexed compare nums -        break; -    case 4: -        timer = (Timer*)TIMER4_BASE; -        timer4_handlers[compare_num-1] = handler; -        nvic_irq_enable(NVIC_TIMER4); -        timer->DIER |= (1 << compare_num); // 1-indexed compare nums -        break; -    } +    timer_port *timer = timer_dev_table[timer_num].base; + +    timer_dev_table[timer_num].handlers[compare_num-1] = handler; +    timer->DIER |= (1 << compare_num); // 1-indexed compare nums +    nvic_irq_enable(timer_dev_table[timer_num].nvic_dev_num);  }  void timer_detach_interrupt(uint8 timer_num, uint8 compare_num) { -    Timer *timer; -    ASSERT(timer_num > 0 && timer_num <= 4 && compare_num > 0 && compare_num <= 4); +    ASSERT(compare_num > 0 && compare_num <= 4); -    switch(timer_num) { -    case 1: -        timer = (Timer*)TIMER1_BASE; -        timer1_handlers[compare_num-1] = 0; -        timer->DIER &= ~(1 << compare_num); // 1-indexed compare nums -        break; -    case 2: -        timer = (Timer*)TIMER2_BASE; -        timer2_handlers[compare_num-1] = 0; -        timer->DIER &= ~(1 << compare_num); // 1-indexed compare nums -        break; -    case 3: -        timer = (Timer*)TIMER3_BASE; -        timer3_handlers[compare_num-1] = 0; -        timer->DIER &= ~(1 << compare_num); // 1-indexed compare nums -        break; -    case 4: -        timer = (Timer*)TIMER4_BASE; -        timer4_handlers[compare_num-1] = 0; -        timer->DIER &= ~(1 << compare_num); // 1-indexed compare nums -        break; -    } +    timer_port *timer = timer_dev_table[timer_num].base; + +    timer_dev_table[timer_num].handlers[compare_num-1] = 0; +    timer->DIER &= ~(1 << compare_num); // 1-indexed compare nums  }  // The following are the actual interrupt handlers; 1 for each timer which must @@ -575,34 +325,35 @@ void timer_detach_interrupt(uint8 timer_num, uint8 compare_num) {  //  // This is a rather long implementation...  void TIM1_CC_IRQHandler(void) { -    Timer *timer = (Timer*)TIMER1_BASE; +    timer_port *timer = (timer_port*)TIMER1_BASE;      uint16 sr_buffer;       sr_buffer = timer->SR; +      // Simply switch/case-ing here doesn't work because multiple       // CC flags may be high.       if(sr_buffer & 0x10){ // CC4 flag          timer->SR &= ~(0x10); -        if(timer1_handlers[3]) { -            timer1_handlers[3](); +        if(timer_dev_table[TIMER1].handlers[3]) { +            timer_dev_table[TIMER1].handlers[3]();          }      }      if(sr_buffer & 0x8){ // CC3 flag          timer->SR &= ~(0x8); -        if(timer1_handlers[2]) { -            timer1_handlers[2](); +        if(timer_dev_table[TIMER1].handlers[2]) { +            timer_dev_table[TIMER1].handlers[2]();          }      }      if(sr_buffer & 0x4){ // CC2 flag          timer->SR &= ~(0x4); -        if(timer1_handlers[1]) { -            timer1_handlers[1](); +        if(timer_dev_table[TIMER1].handlers[1]) { +            timer_dev_table[TIMER1].handlers[1]();          }      }      if(sr_buffer & 0x2){ // CC1 flag          timer->SR &= ~(0x2); -        if(timer1_handlers[0]) { -            timer1_handlers[0](); +        if(timer_dev_table[TIMER1].handlers[0]) { +            timer_dev_table[TIMER1].handlers[0]();          }      }      if(sr_buffer & 0x1){ // Update flag @@ -612,32 +363,32 @@ void TIM1_CC_IRQHandler(void) {  }  void TIM2_IRQHandler(void) {      // This is a rather long implementation... -    Timer *timer = (Timer*)TIMER2_BASE; +    timer_port *timer = (timer_port*)TIMER2_BASE;      uint16 sr_buffer;       sr_buffer = timer->SR;      if(sr_buffer & 0x10){ // CC4 flag          timer->SR &= ~(0x10); -        if(timer2_handlers[3]) { -            timer2_handlers[3](); +        if(timer_dev_table[TIMER2].handlers[3]) { +            timer_dev_table[TIMER2].handlers[3]();          }      }      if(sr_buffer & 0x8){ // CC3 flag          timer->SR &= ~(0x8); -        if(timer2_handlers[2]) { -            timer2_handlers[2](); +        if(timer_dev_table[TIMER2].handlers[2]) { +            timer_dev_table[TIMER2].handlers[2]();          }      }      if(sr_buffer & 0x4){ // CC2 flag          timer->SR &= ~(0x4); -        if(timer2_handlers[1]) { -            timer2_handlers[1](); +        if(timer_dev_table[TIMER2].handlers[1]) { +            timer_dev_table[TIMER2].handlers[1]();          }      }      if(sr_buffer & 0x2){ // CC1 flag          timer->SR &= ~(0x2); -        if(timer2_handlers[0]) { -            timer2_handlers[0](); +        if(timer_dev_table[TIMER2].handlers[0]) { +            timer_dev_table[TIMER2].handlers[0]();          }      }      if(sr_buffer & 0x1){ // Update flag @@ -647,32 +398,32 @@ void TIM2_IRQHandler(void) {  }  void TIM3_IRQHandler(void) {      // This is a rather long implementation... -    Timer *timer = (Timer*)TIMER3_BASE; +    timer_port *timer = (timer_port*)TIMER3_BASE;      uint16 sr_buffer;       sr_buffer = timer->SR;      if(sr_buffer & 0x10){ // CC4 flag          timer->SR &= ~(0x10); -        if(timer3_handlers[3]) { -            timer3_handlers[3](); +        if(timer_dev_table[TIMER3].handlers[3]) { +            timer_dev_table[TIMER3].handlers[3]();          }      }      if(sr_buffer & 0x8){ // CC3 flag          timer->SR &= ~(0x8); -        if(timer3_handlers[2]) { -            timer3_handlers[2](); +        if(timer_dev_table[TIMER3].handlers[2]) { +            timer_dev_table[TIMER3].handlers[2]();          }      }      if(sr_buffer & 0x4){ // CC2 flag          timer->SR &= ~(0x4); -        if(timer3_handlers[1]) { -            timer3_handlers[1](); +        if(timer_dev_table[TIMER3].handlers[1]) { +            timer_dev_table[TIMER3].handlers[1]();          }      }      if(sr_buffer & 0x2){ // CC1 flag          timer->SR &= ~(0x2); -        if(timer3_handlers[0]) { -            timer3_handlers[0](); +        if(timer_dev_table[TIMER3].handlers[0]) { +            timer_dev_table[TIMER3].handlers[0]();          }      }      if(sr_buffer & 0x1){ // Update flag @@ -683,32 +434,32 @@ void TIM3_IRQHandler(void) {  void TIM4_IRQHandler(void) {      // This is a rather long implementation... -    Timer *timer = (Timer*)TIMER4_BASE; +    timer_port*timer = (timer_port*)TIMER4_BASE;      uint16 sr_buffer;       sr_buffer = timer->SR;      if(sr_buffer & 0x10){ // CC4 flag          timer->SR &= ~(0x10); -        if(timer4_handlers[3]) { -            timer4_handlers[3](); +        if(timer_dev_table[TIMER4].handlers[3]) { +            timer_dev_table[TIMER4].handlers[3]();          }      }      if(sr_buffer & 0x8){ // CC3 flag          timer->SR &= ~(0x8); -        if(timer4_handlers[2]) { -            timer4_handlers[2](); +        if(timer_dev_table[TIMER4].handlers[2]) { +            timer_dev_table[TIMER4].handlers[2]();          }      }      if(sr_buffer & 0x4){ // CC2 flag          timer->SR &= ~(0x4); -        if(timer4_handlers[1]) { -            timer4_handlers[1](); +        if(timer_dev_table[TIMER4].handlers[1]) { +            timer_dev_table[TIMER4].handlers[1]();          }      }      if(sr_buffer & 0x2){ // CC1 flag          timer->SR &= ~(0x2); -        if(timer4_handlers[0]) { -            timer4_handlers[0](); +        if(timer_dev_table[TIMER4].handlers[0]) { +            timer_dev_table[TIMER4].handlers[0]();          }      }      if(sr_buffer & 0x1){ // Update flag diff --git a/libmaple/timers.h b/libmaple/timers.h index c49a00e..448a533 100644 --- a/libmaple/timers.h +++ b/libmaple/timers.h @@ -137,6 +137,71 @@ typedef volatile uint32* TimerCCR;  #define TIMER_PWM               1  #define TIMER_OUTPUTCOMPARE     2 +typedef struct { +    volatile uint16 CR1; +    uint16  RESERVED0; +    volatile uint16 CR2; +    uint16  RESERVED1; +    volatile uint16 SMCR; +    uint16  RESERVED2; +    volatile uint16 DIER; +    uint16  RESERVED3; +    volatile uint16 SR; +    uint16  RESERVED4; +    volatile uint16 EGR; +    uint16  RESERVED5; +    volatile uint16 CCMR1; +    uint16  RESERVED6; +    volatile uint16 CCMR2; +    uint16  RESERVED7; +    volatile uint16 CCER; +    uint16  RESERVED8; +    volatile uint16 CNT; +    uint16  RESERVED9; +    volatile uint16 PSC; +    uint16  RESERVED10; +    volatile uint16 ARR; +    uint16  RESERVED11; +    volatile uint16 RCR; +    uint16  RESERVED12; +    volatile uint16 CCR1; +    uint16  RESERVED13; +    volatile uint16 CCR2; +    uint16  RESERVED14; +    volatile uint16 CCR3; +    uint16  RESERVED15; +    volatile uint16 CCR4; +    uint16  RESERVED16; +    volatile uint16 BDTR;   // Not used in general purpose timers +    uint16  RESERVED17;     // Not used in general purpose timers +    volatile uint16 DCR; +    uint16  RESERVED18; +    volatile uint16 DMAR; +    uint16  RESERVED19; +} timer_port; + +// timer device numbers +enum { +   TIMER1, +   TIMER2, +   TIMER3, +   TIMER4, +   TIMER5,      // High density only +   TIMER6,      // High density only; no compare +   TIMER7,      // High density only; no compare +   TIMER8,      // High density only +}; + +// timer descriptor  +struct timer_dev { +   timer_port *base; +   const uint8 rcc_dev_num; +   const uint8 nvic_dev_num; +   volatile voidFuncPtr handlers[4]; +}; + +extern struct timer_dev timer_dev_table[]; +  /* Turn on timer with prescale as the divisor   * void timer_init(uint32 timer, uint16 prescale)   *      timer     ->  {1-4} | 
