/** * @brief Configures and activates the ICU peripheral. * * @param[in] icup pointer to the @p ICUDriver object * * @notapi */ void icu_lld_start(ICUDriver *icup) { uint32_t psc; osalDbgAssert((icup->config->channel == ICU_CHANNEL_1) || (icup->config->channel == ICU_CHANNEL_2), "invalid input"); if (icup->state == ICU_STOP) { /* Clock activation and timer reset.*/ #if STM32_ICU_USE_TIM1 if (&ICUD1 == icup) { rccEnableTIM1(FALSE); rccResetTIM1(); nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY); nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY); #if defined(STM32_TIM1CLK) icup->clock = STM32_TIM1CLK; #else icup->clock = STM32_TIMCLK2; #endif } #endif #if STM32_ICU_USE_TIM2 if (&ICUD2 == icup) { rccEnableTIM2(FALSE); rccResetTIM2(); nvicEnableVector(STM32_TIM2_NUMBER, STM32_ICU_TIM2_IRQ_PRIORITY); icup->clock = STM32_TIMCLK1; } #endif #if STM32_ICU_USE_TIM3 if (&ICUD3 == icup) { rccEnableTIM3(FALSE); rccResetTIM3(); nvicEnableVector(STM32_TIM3_NUMBER, STM32_ICU_TIM3_IRQ_PRIORITY); icup->clock = STM32_TIMCLK1; } #endif #if STM32_ICU_USE_TIM4 if (&ICUD4 == icup) { rccEnableTIM4(FALSE); rccResetTIM4(); nvicEnableVector(STM32_TIM4_NUMBER, STM32_ICU_TIM4_IRQ_PRIORITY); icup->clock = STM32_TIMCLK1; } #endif #if STM32_ICU_USE_TIM5 if (&ICUD5 == icup) { rccEnableTIM5(FALSE); rccResetTIM5(); nvicEnableVector(STM32_TIM5_NUMBER, STM32_ICU_TIM5_IRQ_PRIORITY); icup->clock = STM32_TIMCLK1; } #endif #if STM32_ICU_USE_TIM8 if (&ICUD8 == icup) { rccEnableTIM8(FALSE); rccResetTIM8(); nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY); nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY); #if defined(STM32_TIM8CLK) icup->clock = STM32_TIM8CLK; #else icup->clock = STM32_TIMCLK2; #endif } #endif #if STM32_ICU_USE_TIM9 if (&ICUD9 == icup) { rccEnableTIM9(FALSE); rccResetTIM9(); nvicEnableVector(STM32_TIM9_NUMBER, STM32_ICU_TIM9_IRQ_PRIORITY); icup->clock = STM32_TIMCLK2; } #endif } else { /* Driver re-configuration scenario, it must be stopped first.*/ icup->tim->CR1 = 0; /* Timer disabled. */ icup->tim->CCR[0] = 0; /* Comparator 1 disabled. */ icup->tim->CCR[1] = 0; /* Comparator 2 disabled. */ icup->tim->CNT = 0; /* Counter reset to zero. */ } /* Timer configuration.*/ icup->tim->SR = 0; /* Clear eventual pending IRQs. */ icup->tim->DIER = icup->config->dier & /* DMA-related DIER settings. */ ~STM32_TIM_DIER_IRQ_MASK; psc = (icup->clock / icup->config->frequency) - 1; osalDbgAssert((psc <= 0xFFFF) && ((psc + 1) * icup->config->frequency) == icup->clock, "invalid frequency"); icup->tim->PSC = psc; icup->tim->ARR = 0xFFFF; if (icup->config->channel == ICU_CHANNEL_1) { /* Selected input 1. CCMR1_CC1S = 01 = CH1 Input on TI1. CCMR1_CC2S = 10 = CH2 Input on TI1.*/ icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(1) | STM32_TIM_CCMR1_CC2S(2); /* SMCR_TS = 101, input is TI1FP1. SMCR_SMS = 100, reset on rising edge.*/ icup->tim->SMCR = STM32_TIM_SMCR_TS(5) | STM32_TIM_SMCR_SMS(4); /* The CCER settings depend on the selected trigger mode. ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; else icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P | STM32_TIM_CCER_CC2E; /* Direct pointers to the capture registers in order to make reading data faster from within callbacks.*/ icup->wccrp = &icup->tim->CCR[1]; icup->pccrp = &icup->tim->CCR[0]; } else { /* Selected input 2. CCMR1_CC1S = 10 = CH1 Input on TI2. CCMR1_CC2S = 01 = CH2 Input on TI2.*/ icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(2) | STM32_TIM_CCMR1_CC2S(1); /* SMCR_TS = 110, input is TI2FP2. SMCR_SMS = 100, reset on rising edge.*/ icup->tim->SMCR = STM32_TIM_SMCR_TS(6) | STM32_TIM_SMCR_SMS(4); /* The CCER settings depend on the selected trigger mode. ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P | STM32_TIM_CCER_CC2E; else icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; /* Direct pointers to the capture registers in order to make reading data faster from within callbacks.*/ icup->wccrp = &icup->tim->CCR[0]; icup->pccrp = &icup->tim->CCR[1]; } }
/** * @brief Configures and activates the TIMCAP peripheral. * * @param[in] timcapp pointer to the @p TIMCAPDriver object * * @notapi */ void timcap_lld_start(TIMCAPDriver *timcapp) { uint32_t psc; const timcapchannel_t tim_max_channel = timcap_get_max_timer_channel(timcapp); if (timcapp->state == TIMCAP_STOP) { /* Clock activation and timer reset.*/ #if STM32_TIMCAP_USE_TIM1 if (&TIMCAPD1 == timcapp) { rccEnableTIM1(FALSE); rccResetTIM1(); nvicEnableVector(STM32_TIM1_UP_NUMBER, CORTEX_PRIORITY_MASK(STM32_TIMCAP_TIM1_IRQ_PRIORITY)); nvicEnableVector(STM32_TIM1_CC_NUMBER, CORTEX_PRIORITY_MASK(STM32_TIMCAP_TIM1_IRQ_PRIORITY)); #if defined(STM32_TIM1CLK) timcapp->clock = STM32_TIM1CLK; #else timcapp->clock = STM32_TIMCLK2; #endif } #endif #if STM32_TIMCAP_USE_TIM2 if (&TIMCAPD2 == timcapp) { rccEnableTIM2(FALSE); rccResetTIM2(); nvicEnableVector(STM32_TIM2_NUMBER, CORTEX_PRIORITY_MASK(STM32_TIMCAP_TIM2_IRQ_PRIORITY)); timcapp->clock = STM32_TIMCLK1; } #endif #if STM32_TIMCAP_USE_TIM3 if (&TIMCAPD3 == timcapp) { rccEnableTIM3(FALSE); rccResetTIM3(); nvicEnableVector(STM32_TIM3_NUMBER, CORTEX_PRIORITY_MASK(STM32_TIMCAP_TIM3_IRQ_PRIORITY)); timcapp->clock = STM32_TIMCLK1; } #endif #if STM32_TIMCAP_USE_TIM4 if (&TIMCAPD4 == timcapp) { rccEnableTIM4(FALSE); rccResetTIM4(); nvicEnableVector(STM32_TIM4_NUMBER, CORTEX_PRIORITY_MASK(STM32_TIMCAP_TIM4_IRQ_PRIORITY)); timcapp->clock = STM32_TIMCLK1; } #endif #if STM32_TIMCAP_USE_TIM5 if (&TIMCAPD5 == timcapp) { rccEnableTIM5(FALSE); rccResetTIM5(); nvicEnableVector(STM32_TIM5_NUMBER, CORTEX_PRIORITY_MASK(STM32_TIMCAP_TIM5_IRQ_PRIORITY)); timcapp->clock = STM32_TIMCLK1; } #endif #if STM32_TIMCAP_USE_TIM8 if (&TIMCAPD8 == timcapp) { rccEnableTIM8(FALSE); rccResetTIM8(); nvicEnableVector(STM32_TIM8_UP_NUMBER, CORTEX_PRIORITY_MASK(STM32_TIMCAP_TIM8_IRQ_PRIORITY)); nvicEnableVector(STM32_TIM8_CC_NUMBER, CORTEX_PRIORITY_MASK(STM32_TIMCAP_TIM8_IRQ_PRIORITY)); #if defined(STM32_TIM8CLK) timcapp->clock = STM32_TIM8CLK; #else timcapp->clock = STM32_TIMCLK2; #endif } #endif #if STM32_TIMCAP_USE_TIM9 if (&TIMCAPD9 == timcapp) { rccEnableTIM9(FALSE); rccResetTIM9(); nvicEnableVector(STM32_TIM9_NUMBER, CORTEX_PRIORITY_MASK(STM32_TIMCAP_TIM9_IRQ_PRIORITY)); timcapp->clock = STM32_TIMCLK1; } #endif } else { /* Driver re-configuration scenario, it must be stopped first.*/ timcapp->tim->CR1 = 0; /* Timer disabled. */ timcapp->tim->DIER = timcapp->config->dier &/* DMA-related DIER settings. */ ~STM32_TIM_DIER_IRQ_MASK; timcapp->tim->SR = 0; /* Clear eventual pending IRQs. */ timcapp->tim->CCR[0] = 0; /* Comparator 1 disabled. */ timcapp->tim->CCR[1] = 0; /* Comparator 2 disabled. */ if( tim_max_channel >= TIMCAP_CHANNEL_3 ) timcapp->tim->CCR[2] = 0; /* Comparator 3 disabled. */ if( tim_max_channel >= TIMCAP_CHANNEL_4 ) timcapp->tim->CCR[3] = 0; /* Comparator 4 disabled. */ timcapp->tim->CNT = 0; /* Counter reset to zero. */ } /* Timer configuration.*/ psc = (timcapp->clock / timcapp->config->frequency) - 1; chDbgAssert((psc <= 0xFFFF) && ((psc + 1) * timcapp->config->frequency) == timcapp->clock, "timcap_lld_start(), #1", "invalid frequency"); timcapp->tim->PSC = (uint16_t)psc; //timcapp->tim->ARR = 0xFFFF; timcapp->tim->ARR = timcap_get_max_arr(timcapp); timcapp->tim->CCMR1 = 0; timcapp->tim->CCMR2 = 0; timcapp->tim->CCER = 0; timcapchannel_t chan = TIMCAP_CHANNEL_1; /*go through each non-NULL callback channel and enable the capture register on rising/falling edge*/ for( chan = TIMCAP_CHANNEL_1; chan <= tim_max_channel; chan++ ) { if( timcapp->config->capture_cb_array[chan] == NULL ) { continue; } switch (chan) { case TIMCAP_CHANNEL_1: /*CCMR1_CC1S = 01 = CH1 Input on TI1.*/ timcapp->tim->CCMR1 |= STM32_TIM_CCMR1_CC1S(1); break; case TIMCAP_CHANNEL_2: /*CCMR1_CC2S = 10 = CH2 Input on TI1.*/ timcapp->tim->CCMR1 |= STM32_TIM_CCMR1_CC2S(1); break; case TIMCAP_CHANNEL_3: timcapp->tim->CCMR2 |= STM32_TIM_CCMR2_CC3S(1); break; case TIMCAP_CHANNEL_4: timcapp->tim->CCMR2 |= STM32_TIM_CCMR2_CC4S(1); break; } /* The CCER settings depend on the selected trigger mode. TIMCAP_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. TIMCAP_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ if (timcapp->config->modes[chan] == TIMCAP_INPUT_ACTIVE_HIGH) { switch (chan) { case TIMCAP_CHANNEL_1: timcapp->tim->CCER |= STM32_TIM_CCER_CC1E; break; case TIMCAP_CHANNEL_2: timcapp->tim->CCER |= STM32_TIM_CCER_CC2E; break; case TIMCAP_CHANNEL_3: timcapp->tim->CCER |= STM32_TIM_CCER_CC3E; break; case TIMCAP_CHANNEL_4: timcapp->tim->CCER |= STM32_TIM_CCER_CC4E; break; } } else { switch (chan) { case TIMCAP_CHANNEL_1: timcapp->tim->CCER |= STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P; break; case TIMCAP_CHANNEL_2: timcapp->tim->CCER |= STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; break; case TIMCAP_CHANNEL_3: timcapp->tim->CCER |= STM32_TIM_CCER_CC3E | STM32_TIM_CCER_CC3P; break; case TIMCAP_CHANNEL_4: timcapp->tim->CCER |= STM32_TIM_CCER_CC4E | STM32_TIM_CCER_CC4P; break; } } /* Direct pointers to the capture registers in order to make reading data faster from within callbacks.*/ timcapp->ccr_p[chan] = &timcapp->tim->CCR[chan]; } /* SMCR_TS = 101, input is TI1FP1.*/ timcapp->tim->SMCR = STM32_TIM_SMCR_TS(5); }