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} |