2 * Copyright © 2024 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_tim1.cr1 = ((0 << STM_TIM18_CR1_CKD) |
29 (0 << STM_TIM18_CR1_ARPE) |
30 (0 << STM_TIM18_CR1_CMS) |
31 (0 << STM_TIM18_CR1_DIR) |
32 (0 << STM_TIM18_CR1_OPM) |
33 (1 << STM_TIM18_CR1_URS) |
34 (0 << STM_TIM18_CR1_UDIS) |
35 (1 << STM_TIM18_CR1_CEN));
39 ao_fast_timer_disable(void)
41 stm_tim1.cr1 = ((0 << STM_TIM18_CR1_CKD) |
42 (0 << STM_TIM18_CR1_ARPE) |
43 (0 << STM_TIM18_CR1_CMS) |
44 (0 << STM_TIM18_CR1_DIR) |
45 (0 << STM_TIM18_CR1_OPM) |
46 (1 << STM_TIM18_CR1_URS) |
47 (0 << STM_TIM18_CR1_UDIS) |
48 (0 << STM_TIM18_CR1_CEN));
52 ao_fast_timer_on(void (*callback)(void))
54 ao_fast_timer_callback[ao_fast_timer_count] = callback;
55 if (!ao_fast_timer_count++)
56 ao_fast_timer_enable();
60 ao_fast_timer_off(void (*callback)(void))
64 for (n = 0; n < ao_fast_timer_count; n++)
65 if (ao_fast_timer_callback[n] == callback) {
66 for (; n < ao_fast_timer_count-1; n++) {
67 ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1];
69 if (!--ao_fast_timer_count)
70 ao_fast_timer_disable();
75 void stm_tim1_up_isr(void)
78 if (stm_tim1.sr & (1 << STM_TIM18_SR_UIF)) {
81 for (i = 0; i < ao_fast_timer_count; i++)
82 (*ao_fast_timer_callback[i])();
87 * According to the STM clock-configuration, timers run
88 * twice as fast as the APB2 clock *if* the APB2 prescaler
92 #if AO_APB1_PRESCALER > 1
93 #define TIMER_18_SCALER 2
95 #define TIMER_18_SCALER 1
98 #ifndef FAST_TIMER_FREQ
99 #define FAST_TIMER_FREQ 10000
102 #define TIMER_FAST ((AO_PCLK2 * TIMER_18_SCALER) / FAST_TIMER_FREQ)
105 ao_fast_timer_init(void)
107 if (!ao_fast_timer_users) {
108 stm_nvic_set_enable(STM_ISR_TIM1_UP_POS);
109 stm_nvic_set_priority(STM_ISR_TIM1_UP_POS, AO_STM_NVIC_CLOCK_PRIORITY);
111 /* Turn on timer 1 */
112 stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_TIM1EN);
114 stm_tim1.psc = TIMER_FAST;
118 /* Enable update interrupt */
119 stm_tim1.dier = (1 << STM_TIM18_DIER_UIE);
121 /* Poke timer to reload values */
122 stm_tim1.egr |= (1 << STM_TIM18_EGR_UG);
124 stm_tim1.cr2 = (STM_TIM18_CR2_MMS_RESET << STM_TIM18_CR2_MMS);
125 ao_fast_timer_disable();
127 if (ao_fast_timer_users == AO_FAST_TIMER_MAX)
128 ao_panic(AO_PANIC_FAST_TIMER);
129 ao_fast_timer_users++;