aboutsummaryrefslogtreecommitdiffstats
path: root/libmaple
diff options
context:
space:
mode:
Diffstat (limited to 'libmaple')
-rw-r--r--libmaple/timers.c493
-rw-r--r--libmaple/timers.h65
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}