1 /* 2 * Copyright (c) 2017 The Fuchsia Authors. 3 * 4 * Use of this source code is governed by a MIT-style 5 * license that can be found in the LICENSE file or at 6 * https://opensource.org/licenses/MIT 7 */ 8 9 #include <platform/timer_capture.h> 10 11 #include <arch/arm/cm.h> 12 #include <assert.h> 13 #include <platform/rcc.h> 14 15 typedef enum { 16 STM32_TIM_NOT_FOUND = -1, 17 STM32_TIM1_INDEX = 0, 18 STM32_TIM2_INDEX, 19 STM32_TIM3_INDEX, 20 STM32_TIM6_INDEX, 21 STM32_TIM7_INDEX, 22 STM32_TIM14_INDEX, 23 STM32_TIM15_INDEX, 24 STM32_TIM16_INDEX, 25 STM32_TIM17_INDEX, 26 STM32_NUM_TIMERS, 27 } stm32_timer_index_t; 28 29 typedef TIM_TypeDef stm32_timer_regs_t; 30 31 #define STM32_TIMER_FLAGS_32_BIT (1 << 0) 32 typedef struct stm32_timer_config_ { 33 stm32_timer_regs_t *regs; 34 uint32_t flags; 35 stm32_rcc_clk_t clock; 36 int irq; 37 } stm32_timer_config_t; 38 39 static const stm32_timer_config_t stm32_timer_config[] = { 40 #ifdef TIM1 41 [STM32_TIM1_INDEX] = { 42 .regs = TIM1, 43 .flags = 0, 44 .clock = STM32_RCC_CLK_TIM1, 45 // TIM1 has two interrupts. This one and TIM1_BRK_UP_TRG_COM_IRQn. 46 // This will need to be supported when more than just capture is 47 // supported. 48 .irq = TIM1_CC_IRQn, 49 }, 50 #endif 51 #ifdef TIM2 52 [STM32_TIM2_INDEX] = { 53 .regs = TIM2, 54 .flags = STM32_TIMER_FLAGS_32_BIT, 55 .clock = STM32_RCC_CLK_TIM2, 56 .irq = TIM2_IRQn, 57 }, 58 #endif 59 #ifdef TIM3 60 [STM32_TIM3_INDEX] = { 61 .regs = TIM3, 62 .flags = 0, 63 .clock = STM32_RCC_CLK_TIM3, 64 .irq = TIM3_IRQn, 65 }, 66 #endif 67 #ifdef TIM6 68 [STM32_TIM6_INDEX] = { 69 .regs = TIM6, 70 .flags = 0, 71 .clock = STM32_RCC_CLK_TIM6, 72 .irq = TIM6_IRQn, 73 }, 74 #endif 75 #ifdef TIM7 76 [STM32_TIM7_INDEX] = { 77 .regs = TIM7, 78 .flags = 0, 79 .clock = STM32_RCC_CLK_TIM7, 80 .irq = TIM7_IRQn, 81 }, 82 #endif 83 #ifdef TIM14 84 [STM32_TIM14_INDEX] = { 85 .regs = TIM14, 86 .flags = 0, 87 .clock = STM32_RCC_CLK_TIM14, 88 .irq = TIM14_IRQn, 89 }, 90 #endif 91 #ifdef TIM15 92 [STM32_TIM15_INDEX] = { 93 .regs = TIM15, 94 .flags = 0, 95 .clock = STM32_RCC_CLK_TIM15, 96 .irq = TIM15_IRQn, 97 }, 98 #endif 99 #ifdef TIM16 100 [STM32_TIM16_INDEX] = { 101 .regs = TIM16, 102 .flags = 0, 103 .clock = STM32_RCC_CLK_TIM16, 104 .irq = TIM16_IRQn, 105 }, 106 #endif 107 #ifdef TIM17 108 [STM32_TIM17_INDEX] = { 109 .regs = TIM17, 110 .flags = 0, 111 .clock = STM32_RCC_CLK_TIM17, 112 .irq = TIM17_IRQn, 113 }, 114 #endif 115 }; 116 117 static stm32_timer_capture_t *stm32_timer_capture_data[STM32_NUM_TIMERS]; 118 stm32_timer_enable(const stm32_timer_config_t * config)119 static void stm32_timer_enable(const stm32_timer_config_t *config) { 120 stm32_rcc_set_enable(config->clock, true); 121 } 122 stm32_timer_get_index(int timer)123 static stm32_timer_index_t stm32_timer_get_index(int timer) { 124 switch (timer) { 125 case 1: 126 return STM32_TIM1_INDEX; 127 case 2: 128 return STM32_TIM2_INDEX; 129 case 3: 130 return STM32_TIM3_INDEX; 131 case 6: 132 return STM32_TIM6_INDEX; 133 case 7: 134 return STM32_TIM7_INDEX; 135 case 14: 136 return STM32_TIM14_INDEX; 137 case 15: 138 return STM32_TIM15_INDEX; 139 case 16: 140 return STM32_TIM16_INDEX; 141 case 17: 142 return STM32_TIM17_INDEX; 143 default: 144 return STM32_TIM_NOT_FOUND; 145 } 146 } 147 stm32_timer_get_config(int timer)148 static const stm32_timer_config_t *stm32_timer_get_config(int timer) { 149 stm32_timer_index_t index = stm32_timer_get_index(timer); 150 if (index == STM32_TIM_NOT_FOUND) { 151 return NULL; 152 } 153 return &stm32_timer_config[index]; 154 } 155 stm32_timer_is_32_bit(int timer)156 static bool stm32_timer_is_32_bit(int timer) { 157 switch (timer) { 158 case 2: 159 return true; 160 default: 161 return false; 162 } 163 } 164 stm32_timer_capture_setup_chan(stm32_timer_capture_t * tc,int chan)165 static void stm32_timer_capture_setup_chan(stm32_timer_capture_t *tc, int chan) { 166 stm32_timer_regs_t *regs = tc->config->regs; 167 volatile uint32_t *ccmr = chan & 0x2 ? ®s->CCMR2 : ®s->CCMR1; 168 int shift = 8 * (chan & 1); 169 170 uint32_t val = *ccmr; 171 val &= 0xff << shift; 172 val |= TIM_CCMR1_CC1S_0 << shift; 173 *ccmr = val; 174 175 uint32_t config = TIM_CCER_CC1E; 176 uint32_t flags = tc->chan[chan].flags; 177 if (flags & STM32_TIMER_CAPTURE_CHAN_FLAG_FALLING) { 178 config |= TIM_CCER_CC1P; 179 if (flags & STM32_TIMER_CAPTURE_CHAN_FLAG_RISING) { 180 config |= TIM_CCER_CC1NP; 181 } 182 } 183 184 shift = 4 * (chan & 3); 185 val = regs->CCER; 186 val &= 0xf << shift; 187 val |= config << shift; 188 regs->CCER = val; 189 } 190 stm32_timer_get_ccr(stm32_timer_capture_t * tc,int chan)191 static uint32_t stm32_timer_get_ccr(stm32_timer_capture_t *tc, int chan) { 192 assert(0 <= chan && chan <= 3); 193 switch (chan) { 194 case 0: 195 return tc->config->regs->CCR1; 196 case 1: 197 return tc->config->regs->CCR2; 198 case 2: 199 return tc->config->regs->CCR3; 200 default: // 3 201 return tc->config->regs->CCR4; 202 } 203 } 204 stm32_timer_inc_overflow(stm32_timer_capture_t * tc,uint64_t overflow)205 static uint64_t stm32_timer_inc_overflow(stm32_timer_capture_t *tc, uint64_t overflow) { 206 uint64_t inc; 207 if (tc->config->flags & STM32_TIMER_FLAGS_32_BIT) { 208 inc = 0x100000000ULL; 209 } else { 210 inc = 0x10000ULL; 211 } 212 return overflow + inc; 213 } 214 stm32_timer_median_val(stm32_timer_capture_t * tc)215 static uint32_t stm32_timer_median_val(stm32_timer_capture_t *tc) { 216 if (tc->config->flags & STM32_TIMER_FLAGS_32_BIT) { 217 return 0x7fffffff; 218 } else { 219 return 0x7fff; 220 } 221 } 222 223 // Assumes interrupts are disabled. stm32_timer_calc_value(stm32_timer_capture_t * tc,uint32_t sr,uint32_t val)224 static uint64_t stm32_timer_calc_value(stm32_timer_capture_t *tc, uint32_t sr, uint32_t val) { 225 uint64_t overflow = tc->overflow; 226 // Since we could be processing an overflow and capture interrupts at the 227 // same time, we don't know the ordering of the two. Here we assume 228 // that if the capture event occurred in the lower half of the counter 229 // range, the overflow happened before the capture. 230 if (sr & TIM_SR_UIF && val < stm32_timer_median_val(tc)) { 231 overflow = stm32_timer_inc_overflow(tc, overflow); 232 } 233 return overflow | val; 234 } 235 stm32_timer_capture_chan_irq(stm32_timer_capture_t * tc,uint32_t sr,int chan)236 static bool stm32_timer_capture_chan_irq(stm32_timer_capture_t *tc, uint32_t sr, int chan) { 237 if (tc->chan[chan].cb == NULL) { 238 return false; 239 } 240 if (sr & (TIM_SR_CC1IF << chan)) { 241 uint32_t val = stm32_timer_get_ccr(tc, chan); 242 return tc->chan[chan].cb(stm32_timer_calc_value(tc, sr, val)); 243 } 244 return false; 245 } 246 stm32_timer_capture_irq(stm32_timer_index_t index)247 static void stm32_timer_capture_irq(stm32_timer_index_t index) { 248 arm_cm_irq_entry(); 249 bool resched = false; 250 251 stm32_timer_capture_t *tc = stm32_timer_capture_data[index]; 252 if (tc == NULL) { 253 goto out; 254 } 255 256 uint32_t sr = tc->config->regs->SR; 257 uint32_t irq_ack = ~0U; 258 259 // Since these read their corresponding CCR registers, the status flags 260 // do not need to be explicitly cleared. 261 resched |= stm32_timer_capture_chan_irq(tc, sr, 0); 262 resched |= stm32_timer_capture_chan_irq(tc, sr, 1); 263 resched |= stm32_timer_capture_chan_irq(tc, sr, 2); 264 resched |= stm32_timer_capture_chan_irq(tc, sr, 3); 265 266 267 // We process overflow after compares in order to handle overflow race 268 // detection there. 269 spin_lock_saved_state_t state; 270 spin_lock_irqsave(&tc->overflow_lock, state); 271 if (sr & TIM_SR_UIF) { 272 tc->overflow = stm32_timer_inc_overflow(tc, tc->overflow); 273 irq_ack &= ~TIM_SR_UIF; 274 } 275 tc->config->regs->SR = irq_ack; 276 spin_unlock_irqrestore(&tc->overflow_lock, state); 277 278 out: 279 arm_cm_irq_exit(resched); 280 } 281 stm32_TIM1_IRQ(void)282 void stm32_TIM1_IRQ(void) { 283 stm32_timer_capture_irq(STM32_TIM1_INDEX); 284 } 285 stm32_TIM2_IRQ(void)286 void stm32_TIM2_IRQ(void) { 287 stm32_timer_capture_irq(STM32_TIM2_INDEX); 288 } 289 stm32_TIM3_IRQ(void)290 void stm32_TIM3_IRQ(void) { 291 stm32_timer_capture_irq(STM32_TIM3_INDEX); 292 } 293 stm32_TIM6_IRQ(void)294 void stm32_TIM6_IRQ(void) { 295 stm32_timer_capture_irq(STM32_TIM6_INDEX); 296 } 297 stm32_TIM7_IRQ(void)298 void stm32_TIM7_IRQ(void) { 299 stm32_timer_capture_irq(STM32_TIM7_INDEX); 300 } 301 stm32_TIM14_IRQ(void)302 void stm32_TIM14_IRQ(void) { 303 stm32_timer_capture_irq(STM32_TIM14_INDEX); 304 } 305 stm32_TIM15_IRQ(void)306 void stm32_TIM15_IRQ(void) { 307 stm32_timer_capture_irq(STM32_TIM15_INDEX); 308 } 309 stm32_TIM16_IRQ(void)310 void stm32_TIM16_IRQ(void) { 311 stm32_timer_capture_irq(STM32_TIM16_INDEX); 312 } 313 stm32_TIM17_IRQ(void)314 void stm32_TIM17_IRQ(void) { 315 stm32_timer_capture_irq(STM32_TIM17_INDEX); 316 } 317 stm32_timer_capture_setup(stm32_timer_capture_t * tc,int timer,uint16_t prescaler)318 status_t stm32_timer_capture_setup(stm32_timer_capture_t *tc, int timer, uint16_t prescaler) { 319 assert(prescaler > 0); 320 321 tc->config = stm32_timer_get_config(timer); 322 if (tc->config == NULL) { 323 return ERR_NOT_FOUND; 324 } 325 326 stm32_timer_enable(tc->config); 327 328 stm32_timer_capture_data[stm32_timer_get_index(timer)] = tc; 329 330 tc->overflow = 0; 331 spin_lock_init(&tc->overflow_lock); 332 333 tc->config->regs->CR1 = 0; 334 335 // The prescaler value applied by hardware is PSC + 1. 336 tc->config->regs->PSC = prescaler > 0 ? prescaler - 1 : 0; 337 338 uint32_t dier = TIM_DIER_UIE; 339 340 int i; 341 for (i = 0; i < 4; i++) { 342 if (tc->chan[i].flags & STM32_TIMER_CAPTURE_CHAN_FLAG_ENABLE) { 343 dier |= TIM_DIER_CC1IE << i; 344 stm32_timer_capture_setup_chan(tc, i); 345 } 346 } 347 348 tc->config->regs->DIER = dier; 349 tc->config->regs->CR1 |= TIM_CR1_CEN; 350 351 NVIC_EnableIRQ(tc->config->irq); 352 353 return NO_ERROR; 354 } 355 stm32_timer_capture_get_counter(stm32_timer_capture_t * tc)356 uint64_t stm32_timer_capture_get_counter(stm32_timer_capture_t *tc) { 357 // Protect against tc->overflow being updated while we calculate the value. 358 spin_lock_saved_state_t state; 359 spin_lock_irqsave(&tc->overflow_lock, state); 360 361 uint32_t cnt = tc->config->regs->CNT; 362 uint32_t sr = tc->config->regs->SR; 363 uint64_t value = stm32_timer_calc_value(tc, sr, cnt); 364 365 spin_unlock_irqrestore(&tc->overflow_lock, state); 366 return value; 367 } 368 stm32_timer_init(void)369 void stm32_timer_init(void) { 370 } 371 stm32_timer_early_init(void)372 void stm32_timer_early_init(void) { 373 } 374