aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmaple/timers.c493
-rw-r--r--libmaple/timers.h65
-rw-r--r--wirish/HardwareTimer.cpp47
-rw-r--r--wirish/HardwareTimer.h10
-rw-r--r--wirish/comm/HardwareSPI.cpp4
-rw-r--r--wirish/comm/HardwareSerial.cpp4
-rw-r--r--wirish/wirish.c12
7 files changed, 206 insertions, 429 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}
diff --git a/wirish/HardwareTimer.cpp b/wirish/HardwareTimer.cpp
index f55e6b0..99863c1 100644
--- a/wirish/HardwareTimer.cpp
+++ b/wirish/HardwareTimer.cpp
@@ -32,8 +32,10 @@
#include "HardwareTimer.h"
HardwareTimer::HardwareTimer(uint8 timerNum) {
- ASSERT(timerNum <= NR_TIMERS);
+ ASSERT(timerNum <= NR_TIMERS && timerNum != 6 && timerNum != 7);
+
this->timerNum = timerNum;
+
// Need to remember over flow for bounds checking
this->overflow = 0xFFFF;
}
@@ -104,7 +106,6 @@ void HardwareTimer::setCompare2(uint16 val) {
timer_set_compare_value(this->timerNum,2,val);
}
void HardwareTimer::setCompare3(uint16 val) {
- ASSERT(this->timerNum);
if(val > this->overflow)
val = this->overflow;
timer_set_compare_value(this->timerNum,3,val);
@@ -138,43 +139,13 @@ void HardwareTimer::detachCompare3Interrupt(void) {
void HardwareTimer::detachCompare4Interrupt(void) {
timer_detach_interrupt(this->timerNum,4);
}
-#if NR_TIMERS >= 8
-void HardwareTimer::setChannel5Mode(uint8 mode) {
- timer_set_mode(this->timerNum,5,mode);
-}
-void HardwareTimer::setChannel8Mode(uint8 mode) {
- timer_set_mode(this->timerNum,8,mode);
-}
-void HardwareTimer::setCompare5(uint16 val) {
- if(val > this->overflow)
- val = this->overflow;
- timer_set_compare_value(this->timerNum,5,val);
-}
-void HardwareTimer::setCompare8(uint16 val) {
- if(val > this->overflow)
- val = this->overflow;
- timer_set_compare_value(this->timerNum,8,val);
-}
-void HardwareTimer::attachCompare5Interrupt(voidFuncPtr handler) {
- timer_attach_interrupt(this->timerNum,5,handler);
-}
-void HardwareTimer::attachCompare8Interrupt(voidFuncPtr handler) {
- timer_attach_interrupt(this->timerNum,8,handler);
-}
-void HardwareTimer::detachCompare5Interrupt(void) {
- timer_detach_interrupt(this->timerNum,5);
-}
-void HardwareTimer::detachCompare8Interrupt(void) {
- timer_detach_interrupt(this->timerNum,8);
-}
-#endif
-HardwareTimer Timer1(1);
-HardwareTimer Timer2(2);
-HardwareTimer Timer3(3);
-HardwareTimer Timer4(4);
+HardwareTimer Timer1(TIMER1);
+HardwareTimer Timer2(TIMER2);
+HardwareTimer Timer3(TIMER3);
+HardwareTimer Timer4(TIMER4);
#if NR_TIMERS >= 8
-HardwareTimer Timer5(5); // High-density devices only
-HardwareTimer Timer8(8); // High-density devices only
+HardwareTimer Timer5(TIMER5); // High-density devices only
+HardwareTimer Timer8(TIMER8); // High-density devices only
#endif
diff --git a/wirish/HardwareTimer.h b/wirish/HardwareTimer.h
index 3f986e4..aa48718 100644
--- a/wirish/HardwareTimer.h
+++ b/wirish/HardwareTimer.h
@@ -62,16 +62,6 @@ class HardwareTimer {
void detachCompare2Interrupt(void);
void detachCompare3Interrupt(void);
void detachCompare4Interrupt(void);
- #if NR_TIMERS >= 8
- void setChannel5Mode(uint8 mode);
- void setChannel8Mode(uint8 mode);
- void setCompare5(uint16 val); // truncates to overflow
- void setCompare8(uint16 val); // truncates to overflow
- void attachCompare5Interrupt(voidFuncPtr handler);
- void attachCompare8Interrupt(voidFuncPtr handler);
- void detachCompare5Interrupt(void);
- void detachCompare8Interrupt(void);
- #endif
};
extern HardwareTimer Timer1;
diff --git a/wirish/comm/HardwareSPI.cpp b/wirish/comm/HardwareSPI.cpp
index eadcdd7..5f42db7 100644
--- a/wirish/comm/HardwareSPI.cpp
+++ b/wirish/comm/HardwareSPI.cpp
@@ -95,8 +95,8 @@ void HardwareSPI::begin(SPIFrequency freq, uint32 endianness, uint32 mode) {
}
/* Turn off PWM on shared pins */
- timer_set_mode(3, 2, TIMER_DISABLED);
- timer_set_mode(3, 1, TIMER_DISABLED);
+ timer_set_mode(TIMER3, 2, TIMER_DISABLED);
+ timer_set_mode(TIMER3, 1, TIMER_DISABLED);
}
endianness = (endianness == LSBFIRST) ? SPI_LSBFIRST : SPI_MSBFIRST;
diff --git a/wirish/comm/HardwareSerial.cpp b/wirish/comm/HardwareSerial.cpp
index 6399ad5..902b160 100644
--- a/wirish/comm/HardwareSerial.cpp
+++ b/wirish/comm/HardwareSerial.cpp
@@ -34,8 +34,8 @@
#include "gpio.h"
#include "timers.h"
-HardwareSerial Serial1(USART1, 4500000UL, GPIOA_BASE, 9, 10, 1, 2);
-HardwareSerial Serial2(USART2, 2250000UL, GPIOA_BASE, 2, 3, 2, 3);
+HardwareSerial Serial1(USART1, 4500000UL, GPIOA_BASE, 9, 10, TIMER1, 2);
+HardwareSerial Serial2(USART2, 2250000UL, GPIOA_BASE, 2, 3, TIMER2, 3);
HardwareSerial Serial3(USART3, 2250000UL, GPIOB_BASE, 10, 11, 0, 0);
// TODO: High density device ports
diff --git a/wirish/wirish.c b/wirish/wirish.c
index 9f3b19e..5407131 100644
--- a/wirish/wirish.c
+++ b/wirish/wirish.c
@@ -66,13 +66,13 @@ void init(void) {
systick_init(MAPLE_RELOAD_VAL);
gpio_init();
adc_init();
- timer_init(1, 1);
- timer_init(2, 1);
- timer_init(3, 1);
- timer_init(4, 1);
+ timer_init(TIMER1, 1);
+ timer_init(TIMER2, 1);
+ timer_init(TIMER3, 1);
+ timer_init(TIMER4, 1);
#if NR_TIMERS >= 8
- timer_init(5, 1);
- timer_init(8, 1);
+ timer_init(TIMER5, 1);
+ timer_init(TIMER8, 1);
#endif
setupUSB();
}