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;
25 #if AO_FAST_TIMER == 1
27 # define AO_FAST_TIMER_TYPE 18
28 # define stm_tim stm_tim1
29 # define stm_tim_isr stm_tim1_up_isr
30 # define STM_ISR_TIM_POS STM_ISR_TIM1_UP_POS
31 # define STM_RCC_APBENR_TIMEN STM_RCC_APB2ENR_TIM1EN
33 #elif AO_FAST_TIMER == 2
35 # define AO_FAST_TIMER_TYPE 234
36 # define stm_tim stm_tim2
37 # define stm_tim_isr stm_tim2_isr
38 # define STM_ISR_TIM_POS STM_ISR_TIM2_POS
39 # define STM_RCC_APBENR_TIMEN STM_RCC_APB1ENR_TIM2EN
41 #elif AO_FAST_TIMER == 3
43 # define AO_FAST_TIMER_TYPE 234
44 # define stm_tim stm_tim3
45 # define stm_tim_isr stm_tim3_isr
46 # define STM_ISR_TIM_POS STM_ISR_TIM3_POS
47 # define STM_RCC_APBENR_TIMEN STM_RCC_APB1ENR_TIM3EN
49 #elif AO_FAST_TIMER == 4
51 # define AO_FAST_TIMER_TYPE 234
52 # define stm_tim stm_tim4
53 # define stm_tim_isr stm_tim4_isr
54 # define STM_ISR_TIM_POS STM_ISR_TIM4_POS
55 # define STM_RCC_APBENR_TIMEN STM_RCC_APB1ENR_TIM4EN
61 #if AO_FAST_TIMER_TYPE == 18
63 #define STM_TIM_CR1(cen) ((0 << STM_TIM18_CR1_CKD) | \
64 (0 << STM_TIM18_CR1_ARPE) | \
65 (0 << STM_TIM18_CR1_CMS) | \
66 (0 << STM_TIM18_CR1_DIR) | \
67 (0 << STM_TIM18_CR1_OPM) | \
68 (1 << STM_TIM18_CR1_URS) | \
69 (0 << STM_TIM18_CR1_UDIS) | \
70 ((cen) << STM_TIM18_CR1_CEN))
71 #define STM_TIM_SR_UIF STM_TIM18_SR_UIF
72 #define STM_TIM_DIER_UIE STM_TIM18_DIER_UIE
73 #define STM_TIM_EGR_UG STM_TIM18_EGR_UG
74 #define STM_TIM_CR2_MMS STM_TIM18_CR2_MMS
75 #define STM_TIM_CR2_MMS_RESET STM_TIM18_CR2_MMS_RESET
77 #define AO_TIM_PCLK AO_PCLK2
80 * According to the STM clock-configuration, timers 18 run
81 * twice as fast as the APB2 clock *if* the APB2 prescaler
85 #if AO_APB2_PRESCALER > 1
86 #define AO_TIM_SCALER 2
88 #define AO_TIM_SCALER 1
91 #define STM_RCC_APB_TIM stm_rcc.apb2enr
93 #elif AO_FAST_TIMER_TYPE == 234
95 #define STM_TIM_CR1(cen) ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) | \
96 (0 << STM_TIM234_CR1_ARPE) | \
97 (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) | \
98 (0 << STM_TIM234_CR1_DIR) | \
99 (0 << STM_TIM234_CR1_OPM) | \
100 (0 << STM_TIM234_CR1_URS) | \
101 (0 << STM_TIM234_CR1_UDIS) | \
102 ((cen) << STM_TIM234_CR1_CEN)) \
104 #define AO_TIM_PCLK AO_PCLK1
107 * According to the STM clock-configuration, timers 234 run
108 * twice as fast as the APB1 clock *if* the APB1 prescaler
112 #if AO_APB1_PRESCALER > 1
113 #define AO_TIM_SCALER 2
115 #define AO_TIM_SCALER 1
118 #define STM_TIM_SR_UIF STM_TIM234_SR_UIF
119 #define STM_TIM_DIER_UIE STM_TIM234_DIER_UIE
120 #define STM_TIM_EGR_UG STM_TIM234_EGR_UG
121 #define STM_TIM_CR2_MMS STM_TIM234_CR2_MMS
122 #define STM_TIM_CR2_MMS_RESET STM_TIM234_CR2_MMS_RESET
124 #define STM_RCC_APB_TIM stm_rcc.apb1enr
129 ao_fast_timer_enable(void)
131 stm_tim.cr1 = STM_TIM_CR1(1);
135 ao_fast_timer_disable(void)
137 stm_tim.cr1 = STM_TIM_CR1(0);
141 ao_fast_timer_on(void (*callback)(void))
143 ao_fast_timer_callback[ao_fast_timer_count] = callback;
144 if (!ao_fast_timer_count++)
145 ao_fast_timer_enable();
149 ao_fast_timer_off(void (*callback)(void))
153 for (n = 0; n < ao_fast_timer_count; n++)
154 if (ao_fast_timer_callback[n] == callback) {
155 for (; n < ao_fast_timer_count-1; n++) {
156 ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1];
158 if (!--ao_fast_timer_count)
159 ao_fast_timer_disable();
164 void stm_tim_isr(void)
167 if (stm_tim.sr & (1 << STM_TIM_SR_UIF)) {
170 for (i = 0; i < ao_fast_timer_count; i++)
171 (*ao_fast_timer_callback[i])();
175 #ifndef FAST_TIMER_FREQ
176 #define FAST_TIMER_FREQ 10000
179 #define TIMER_FAST ((AO_TIM_PCLK * AO_TIM_SCALER) / FAST_TIMER_FREQ)
182 ao_fast_timer_init(void)
184 if (!ao_fast_timer_users) {
185 stm_nvic_set_enable(STM_ISR_TIM_POS);
186 stm_nvic_set_priority(STM_ISR_TIM_POS, AO_STM_NVIC_CLOCK_PRIORITY);
188 /* Turn on timer 1 */
189 STM_RCC_APB_TIM |= (1 << STM_RCC_APBENR_TIMEN);
191 stm_tim.psc = TIMER_FAST;
195 /* Enable update interrupt */
196 stm_tim.dier = (1 << STM_TIM_DIER_UIE);
198 /* Poke timer to reload values */
199 stm_tim.egr |= (1 << STM_TIM_EGR_UG);
201 stm_tim.cr2 = (STM_TIM_CR2_MMS_RESET << STM_TIM_CR2_MMS);
202 ao_fast_timer_disable();
204 if (ao_fast_timer_users == AO_FAST_TIMER_MAX)
205 ao_panic(AO_PANIC_FAST_TIMER);
206 ao_fast_timer_users++;