2 * Copyright © 2013 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 #include <ao_fast_timer.h>
21 static void (*ao_fast_timer_callback[AO_FAST_TIMER_MAX])(void);
22 static uint8_t ao_fast_timer_count;
23 static uint8_t ao_fast_timer_users;
26 ao_fast_timer_enable(void)
28 stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) |
29 (0 << STM_TIM67_CR1_OPM) |
30 (1 << STM_TIM67_CR1_URS) |
31 (0 << STM_TIM67_CR1_UDIS) |
32 (1 << STM_TIM67_CR1_CEN));
36 ao_fast_timer_disable(void)
38 stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) |
39 (0 << STM_TIM67_CR1_OPM) |
40 (1 << STM_TIM67_CR1_URS) |
41 (0 << STM_TIM67_CR1_UDIS) |
42 (0 << STM_TIM67_CR1_CEN));
46 ao_fast_timer_on(void (*callback)(void))
48 ao_fast_timer_callback[ao_fast_timer_count] = callback;
49 if (!ao_fast_timer_count++)
50 ao_fast_timer_enable();
54 ao_fast_timer_off(void (*callback)(void))
58 for (n = 0; n < ao_fast_timer_count; n++)
59 if (ao_fast_timer_callback[n] == callback) {
60 for (; n < ao_fast_timer_count-1; n++) {
61 ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1];
63 if (!--ao_fast_timer_count)
64 ao_fast_timer_disable();
69 void stm_tim6_isr(void)
72 if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) {
75 for (i = 0; i < ao_fast_timer_count; i++)
76 (*ao_fast_timer_callback[i])();
81 * According to the STM clock-configuration, timers run
82 * twice as fast as the APB1 clock *if* the APB1 prescaler
86 #if AO_APB1_PRESCALER > 1
87 #define TIMER_23467_SCALER 2
89 #define TIMER_23467_SCALER 1
92 #ifndef FAST_TIMER_FREQ
93 #define FAST_TIMER_FREQ 10000
96 #define TIMER_FAST ((AO_PCLK1 * TIMER_23467_SCALER) / FAST_TIMER_FREQ)
99 ao_fast_timer_init(void)
101 if (!ao_fast_timer_users) {
102 stm_nvic_set_enable(STM_ISR_TIM6_POS);
103 stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY);
105 /* Turn on timer 6 */
106 stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN);
108 stm_tim6.psc = TIMER_FAST;
112 /* Enable update interrupt */
113 stm_tim6.dier = (1 << STM_TIM67_DIER_UIE);
115 /* Poke timer to reload values */
116 stm_tim6.egr |= (1 << STM_TIM67_EGR_UG);
118 stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS);
119 ao_fast_timer_disable();
121 if (ao_fast_timer_users == AO_FAST_TIMER_MAX)
122 ao_panic(AO_PANIC_FAST_TIMER);
123 ao_fast_timer_users++;