diff options
Diffstat (limited to 'libmaple/timers.c')
-rw-r--r-- | libmaple/timers.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/libmaple/timers.c b/libmaple/timers.c new file mode 100644 index 0000000..e187428 --- /dev/null +++ b/libmaple/timers.c @@ -0,0 +1,192 @@ +/* ***************************************************************************** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Created: 12/18/09 02:37:54 + * Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + * @file timers.c + * + * @brief General timer routines + */ + +#include "libmaple.h" +#include "rcc.h" +#include "timers.h" + +typedef struct { + volatile uint16_t CR1; + uint16_t RESERVED0; + volatile uint16_t CR2; + uint16_t RESERVED1; + volatile uint16_t SMCR; + uint16_t RESERVED2; + volatile uint16_t DIER; + uint16_t RESERVED3; + volatile uint16_t SR; + uint16_t RESERVED4; + volatile uint16_t EGR; + uint16_t RESERVED5; + volatile uint16_t CCMR1; + uint16_t RESERVED6; + volatile uint16_t CCMR2; + uint16_t RESERVED7; + volatile uint16_t CCER; + uint16_t RESERVED8; + volatile uint16_t CNT; + uint16_t RESERVED9; + volatile uint16_t PSC; + uint16_t RESERVED10; + volatile uint16_t ARR; + uint16_t RESERVED11; + volatile uint16_t RCR; + uint16_t RESERVED12; + volatile uint16_t CCR1; + uint16_t RESERVED13; + volatile uint16_t CCR2; + uint16_t RESERVED14; + volatile uint16_t CCR3; + uint16_t RESERVED15; + volatile uint16_t CCR4; + uint16_t RESERVED16; + volatile uint16_t BDTR; // Not used in general purpose timers + uint16_t RESERVED17; // Not used in general purpose timers + volatile uint16_t DCR; + uint16_t RESERVED18; + volatile uint16_t DMAR; + uint16_t RESERVED19; +} Timer; + +void timer_init(uint8_t timer_num, uint16_t prescale) { + Timer *timer; + uint32_t is_advanced = 0; + + ASSERT(timer_num > 0 && timer_num <= 4); + + switch(timer_num) { + case 1: + timer = (Timer*)TIMER1_BASE; + rcc_enable_clk_timer1(); + is_advanced = 1; + break; + case 2: + timer = (Timer*)TIMER2_BASE; + rcc_enable_clk_timer2(); + break; + case 3: + timer = (Timer*)TIMER3_BASE; + rcc_enable_clk_timer3(); + break; + case 4: + timer = (Timer*)TIMER4_BASE; + rcc_enable_clk_timer4(); + break; + } + + timer->CR1 = ARPE; // No clock division + // Do not buffer auto-reload preload + // Edge aligned + // Upcounter + // Do not stop counter at update event + // Update events enabled (etc, see bits [1:2]) + // Counter disabled for now + + timer->PSC = prescale; // Prescaling by prescale (duh) + timer->ARR = 0xFFFF; // Max reload cont + + /* initialize all the channels to 50% duty cycle, + * TODO: none of them actually get output unless the gpio pin + * is set, this will probably consume a bit more power but + * we'll worry about that later. */ + timer->CCR1 = 0x8FFF; // PWM start value + timer->CCMR1 |= 0x68; // PWM mode 1, enable preload register. + timer->CCER |= 0x001; // enable ch + + timer->CCR2 = 0x8FFF; // PWM start value + timer->CCMR1 |= (0x68 << 8);// PWM mode 1, enable preload register. + timer->CCER |= 0x010; // enable ch + + timer->CCR3 = 0x8FFF; // PWM start value + timer->CCMR2 |= 0x68; // PWM mode 1, enable preload register. + timer->CCER |= 0x100; // enable ch + + timer->CCR4 = 0x8FFF; // PWM start value + timer->CCMR2 |= (0x68 << 8);// PWM mode 1, enable preload register. + timer->CCER |= 0x1000; // enable ch + + /* Advanced timer? */ + if (is_advanced) { + timer->BDTR = 0x8000; // moe enable + } + + timer->DIER = 0; // disable update interrupt + timer->EGR = 1; // Initialize update event and shadow registers + timer->CR1 |= 1; // Enable timer +} + +void timers_disable(void) { + Timer *timer; + int i; + Timer *timers[4] = { + (Timer*)TIMER1_BASE, + (Timer*)TIMER2_BASE, + (Timer*)TIMER3_BASE, + (Timer*)TIMER4_BASE, + }; + + for (i = 0; i < 4; i++) { + timer = timers[i]; + timer->CR1 = 0; + timer->CCER = 0; + } +} + +void timers_disable_channel(uint8 timer_num, uint8 channel) { + 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); + } + + switch (channel) { + case 1: + timer->CCER &= ~(0x1); + break; + case 2: + timer->CCER &= ~(0x10); + break; + case 3: + timer->CCER &= ~(0x100); + break; + case 4: + timer->CCER &= ~(0x1000); + break; + default: + ASSERT(0); + } +} |