Example #1
0
void Timer_t::Init() {
#if defined STM32L1XX
    if(ANY_OF_3(ITmr, TIM9, TIM10, TIM11)) PClk = &Clk.APB2FreqHz;
    else PClk = &Clk.APB1FreqHz;
    if     (ITmr == TIM2)  { rccEnableTIM2(FALSE); }
    else if(ITmr == TIM3)  { rccEnableTIM3(FALSE); }
    else if(ITmr == TIM4)  { rccEnableTIM4(FALSE); }
    else if(ITmr == TIM6)  { rccEnableAPB1(RCC_APB1ENR_TIM6EN,  FALSE); }
    else if(ITmr == TIM7)  { rccEnableAPB1(RCC_APB1ENR_TIM7EN,  FALSE); }
    else if(ITmr == TIM9)  { rccEnableAPB2(RCC_APB2ENR_TIM9EN,  FALSE); }
    else if(ITmr == TIM10) { rccEnableAPB2(RCC_APB2ENR_TIM10EN, FALSE); }
    else if(ITmr == TIM11) { rccEnableAPB2(RCC_APB2ENR_TIM11EN, FALSE); }
#elif defined STM32F0XX
    if     (ITmr == TIM1)  { rccEnableTIM1(FALSE); }
    else if(ITmr == TIM2)  { rccEnableTIM2(FALSE); }
    else if(ITmr == TIM3)  { rccEnableTIM3(FALSE); }
#ifdef TIM6
    else if(ITmr == TIM6)  { rccEnableAPB1(RCC_APB1ENR_TIM6EN,  FALSE); }
#endif
    else if(ITmr == TIM14) { RCC->APB1ENR |= RCC_APB1ENR_TIM14EN; }
#ifdef TIM15
    else if(ITmr == TIM15) { RCC->APB2ENR |= RCC_APB2ENR_TIM15EN; }
#endif
    else if(ITmr == TIM16) { RCC->APB2ENR |= RCC_APB2ENR_TIM16EN; }
    else if(ITmr == TIM17) { RCC->APB2ENR |= RCC_APB2ENR_TIM17EN; }
    // Clock src
    PClk = &Clk.APBFreqHz;
#elif defined STM32F2XX || defined STM32F4XX
    if(ANY_OF_5(ITmr, TIM1, TIM8, TIM9, TIM10, TIM11)) PClk = &Clk.APB2FreqHz;
    else PClk = &Clk.APB1FreqHz;
    if     (ITmr == TIM1)  { rccEnableTIM1(FALSE); }
    else if(ITmr == TIM2)  { rccEnableTIM2(FALSE); }
    else if(ITmr == TIM3)  { rccEnableTIM3(FALSE); }
    else if(ITmr == TIM4)  { rccEnableTIM4(FALSE); }
    else if(ITmr == TIM5)  { rccEnableTIM5(FALSE); }
    else if(ITmr == TIM6)  { rccEnableTIM6(FALSE); }
    else if(ITmr == TIM7)  { rccEnableTIM7(FALSE); }
    else if(ITmr == TIM8)  { rccEnableTIM8(FALSE); }
    else if(ITmr == TIM9)  { rccEnableTIM9(FALSE); }
    else if(ITmr == TIM10)  { RCC->APB2ENR |= RCC_APB2ENR_TIM10EN; }
    else if(ITmr == TIM11)  { rccEnableTIM11(FALSE); }
    else if(ITmr == TIM12)  { rccEnableTIM12(FALSE); }
    else if(ITmr == TIM13)  { RCC->APB1ENR |= RCC_APB1ENR_TIM13EN; }
    else if(ITmr == TIM14)  { rccEnableTIM14(FALSE); }
#elif defined STM32F10X_LD_VL
    if(ANY_OF_4(ITmr, TIM1, TIM15, TIM16, TIM17)) PClk = &Clk.APB2FreqHz;
    else PClk = &Clk.APB1FreqHz;
    if     (ITmr == TIM1)  { rccEnableTIM1(FALSE); }
    else if(ITmr == TIM2)  { rccEnableTIM2(FALSE); }
    else if(ITmr == TIM3)  { rccEnableTIM3(FALSE); }
    else if(ITmr == TIM15) { RCC->APB2ENR |= RCC_APB2ENR_TIM15EN; }
    else if(ITmr == TIM16) { RCC->APB2ENR |= RCC_APB2ENR_TIM16EN; }
    else if(ITmr == TIM17) { RCC->APB2ENR |= RCC_APB2ENR_TIM17EN; }
#endif
}
Example #2
0
void LedChnl_t::Init() const {
    // ==== GPIO setup ====
    if(PTimer == TIM2) PinSetupAlterFunc(PGpio, Pin, omPushPull, pudNone, AF1);
    else if(PTimer == TIM3 or PTimer == TIM4) PinSetupAlterFunc(PGpio, Pin, omPushPull, pudNone, AF2);
    else PinSetupAlterFunc(PGpio, Pin, omPushPull, pudNone, AF3);

    // ==== Timer setup ====
    if     (PTimer == TIM2)  { rccEnableTIM2(FALSE); }
    else if(PTimer == TIM3)  { rccEnableTIM3(FALSE); }
    else if(PTimer == TIM4)  { rccEnableTIM4(FALSE); }
    else if(PTimer == TIM9)  { rccEnableTIM9(FALSE); }
    else if(PTimer == TIM10) { rccEnableAPB2(RCC_APB2ENR_TIM10EN, FALSE); }
    else if(PTimer == TIM11) { rccEnableAPB2(RCC_APB2ENR_TIM11EN, FALSE); }

    PTimer->CR1 = TIM_CR1_CEN; // Enable timer, set clk division to 0, AutoReload not buffered
    PTimer->CR2 = 0;
    PTimer->ARR = LED_TOP_VALUE;

    // ==== Timer's channel ====
#if LED_INVERTED_PWM
#define PwmMode 0b111
#else
#define PwmMode 0b110
#endif
    switch(TmrChnl) {
        case 1:
            PTimer->CCMR1 |= (PwmMode << 4);
            PTimer->CCER  |= TIM_CCER_CC1E;
            break;
        case 2:
            PTimer->CCMR1 |= (PwmMode << 12);
            PTimer->CCER  |= TIM_CCER_CC2E;
            break;
        case 3:
            PTimer->CCMR2 |= (PwmMode << 4);
            PTimer->CCER  |= TIM_CCER_CC3E;
            break;
        case 4:
            PTimer->CCMR2 |= (PwmMode << 12);
            PTimer->CCER  |= TIM_CCER_CC4E;
            break;
        default: break;
    }
}
Example #3
0
/**
 * @brief   Configures and activates the PWM peripheral.
 * @note    Starting a driver that is already in the @p PWM_READY state
 *          disables all the active channels.
 *
 * @param[in] pwmp      pointer to a @p PWMDriver object
 *
 * @notapi
 */
void pwm_lld_start(PWMDriver *pwmp) {
  uint32_t psc;
  uint32_t ccer;
  uint32_t dier;

  if (pwmp->state == PWM_STOP) {
    /* Clock activation and timer reset.*/
#if STM32_PWM_USE_TIM1
    if (&PWMD1 == pwmp) {
      rccEnableTIM1(FALSE);
      rccResetTIM1();
      nvicEnableVector(STM32_TIM1_UP_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_PWM_TIM1_IRQ_PRIORITY));
      nvicEnableVector(STM32_TIM1_CC_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_PWM_TIM1_IRQ_PRIORITY));
#if defined(STM32_TIM1CLK)
      pwmp->clock = STM32_TIM1CLK;
#else
      pwmp->clock = STM32_TIMCLK2;
#endif
    }
#endif
#if STM32_PWM_USE_TIM2
    if (&PWMD2 == pwmp) {
      rccEnableTIM2(FALSE);
      rccResetTIM2();
      nvicEnableVector(STM32_TIM2_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_PWM_TIM2_IRQ_PRIORITY));
      pwmp->clock = STM32_TIMCLK1;
    }
#endif
#if STM32_PWM_USE_TIM3
    if (&PWMD3 == pwmp) {
      rccEnableTIM3(FALSE);
      rccResetTIM3();
      nvicEnableVector(STM32_TIM3_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_PWM_TIM3_IRQ_PRIORITY));
      pwmp->clock = STM32_TIMCLK1;
    }
#endif
#if STM32_PWM_USE_TIM4
    if (&PWMD4 == pwmp) {
      rccEnableTIM4(FALSE);
      rccResetTIM4();
      nvicEnableVector(STM32_TIM4_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_PWM_TIM4_IRQ_PRIORITY));
      pwmp->clock = STM32_TIMCLK1;
    }
#endif

#if STM32_PWM_USE_TIM5
    if (&PWMD5 == pwmp) {
      rccEnableTIM5(FALSE);
      rccResetTIM5();
      nvicEnableVector(STM32_TIM5_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_PWM_TIM5_IRQ_PRIORITY));
      pwmp->clock = STM32_TIMCLK1;
    }
#endif
#if STM32_PWM_USE_TIM8
    if (&PWMD8 == pwmp) {
      rccEnableTIM8(FALSE);
      rccResetTIM8();
      nvicEnableVector(STM32_TIM8_UP_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_PWM_TIM8_IRQ_PRIORITY));
      nvicEnableVector(STM32_TIM8_CC_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_PWM_TIM8_IRQ_PRIORITY));
#if defined(STM32_TIM8CLK)
      pwmp->clock = STM32_TIM8CLK;
#else
      pwmp->clock = STM32_TIMCLK2;
#endif
    }
#endif
#if STM32_PWM_USE_TIM9
    if (&PWMD9 == pwmp) {
      rccEnableTIM9(FALSE);
      rccResetTIM9();
      nvicEnableVector(STM32_TIM9_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_PWM_TIM9_IRQ_PRIORITY));
      pwmp->clock = STM32_TIMCLK2;
    }
#endif

    /* All channels configured in PWM1 mode with preload enabled and will
       stay that way until the driver is stopped.*/
    pwmp->tim->CCMR1 = STM32_TIM_CCMR1_OC1M(6) | STM32_TIM_CCMR1_OC1PE |
                       STM32_TIM_CCMR1_OC2M(6) | STM32_TIM_CCMR1_OC2PE;
    pwmp->tim->CCMR2 = STM32_TIM_CCMR2_OC3M(6) | STM32_TIM_CCMR2_OC3PE |
                       STM32_TIM_CCMR2_OC4M(6) | STM32_TIM_CCMR2_OC4PE;
  }
  else {
    /* Driver re-configuration scenario, it must be stopped first.*/
    pwmp->tim->CR1    = 0;                  /* Timer disabled.              */
    pwmp->tim->CCR[0] = 0;                  /* Comparator 1 disabled.       */
    pwmp->tim->CCR[1] = 0;                  /* Comparator 2 disabled.       */
    pwmp->tim->CCR[2] = 0;                  /* Comparator 3 disabled.       */
    pwmp->tim->CCR[3] = 0;                  /* Comparator 4 disabled.       */
    pwmp->tim->CNT  = 0;                    /* Counter reset to zero.       */
  }

  /* Timer configuration.*/
  psc = (pwmp->clock / pwmp->config->frequency) - 1;
  chDbgAssert((psc <= 0xFFFF) &&
              ((psc + 1) * pwmp->config->frequency) == pwmp->clock,
              "pwm_lld_start(), #1", "invalid frequency");
  pwmp->tim->PSC  = (uint16_t)psc;
  pwmp->tim->ARR  = (uint16_t)(pwmp->period - 1);
  pwmp->tim->CR2  = pwmp->config->cr2;

  /* Output enables and polarities setup.*/
  ccer = 0;
  switch (pwmp->config->channels[0].mode & PWM_OUTPUT_MASK) {
  case PWM_OUTPUT_ACTIVE_LOW:
    ccer |= STM32_TIM_CCER_CC1P;
  case PWM_OUTPUT_ACTIVE_HIGH:
    ccer |= STM32_TIM_CCER_CC1E;
  default:
    ;
  }
  switch (pwmp->config->channels[1].mode & PWM_OUTPUT_MASK) {
  case PWM_OUTPUT_ACTIVE_LOW:
    ccer |= STM32_TIM_CCER_CC2P;
  case PWM_OUTPUT_ACTIVE_HIGH:
    ccer |= STM32_TIM_CCER_CC2E;
  default:
    ;
  }
  switch (pwmp->config->channels[2].mode & PWM_OUTPUT_MASK) {
  case PWM_OUTPUT_ACTIVE_LOW:
    ccer |= STM32_TIM_CCER_CC3P;
  case PWM_OUTPUT_ACTIVE_HIGH:
    ccer |= STM32_TIM_CCER_CC3E;
  default:
    ;
  }
  switch (pwmp->config->channels[3].mode & PWM_OUTPUT_MASK) {
  case PWM_OUTPUT_ACTIVE_LOW:
    ccer |= STM32_TIM_CCER_CC4P;
  case PWM_OUTPUT_ACTIVE_HIGH:
    ccer |= STM32_TIM_CCER_CC4E;
  default:
    ;
  }
#if STM32_PWM_USE_ADVANCED
#if STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8
  if (&PWMD1 == pwmp) {
#endif
#if !STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8
  if (&PWMD8 == pwmp) {
#endif
#if STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8
  if ((&PWMD1 == pwmp) || (&PWMD8 == pwmp)) {
#endif
    switch (pwmp->config->channels[0].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) {
    case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW:
      ccer |= STM32_TIM_CCER_CC1NP;
    case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH:
      ccer |= STM32_TIM_CCER_CC1NE;
    default:
      ;
    }
    switch (pwmp->config->channels[1].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) {
    case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW:
      ccer |= STM32_TIM_CCER_CC2NP;
    case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH:
      ccer |= STM32_TIM_CCER_CC2NE;
    default:
      ;
    }
    switch (pwmp->config->channels[2].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) {
    case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW:
      ccer |= STM32_TIM_CCER_CC3NP;
    case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH:
      ccer |= STM32_TIM_CCER_CC3NE;
    default:
      ;
    }
  }
#endif /* STM32_PWM_USE_ADVANCED*/

  pwmp->tim->CCER  = ccer;
  pwmp->tim->EGR   = STM32_TIM_EGR_UG;      /* Update event.                */
  pwmp->tim->SR    = 0;                     /* Clear pending IRQs.          */
  pwmp->tim->DIER  = (pwmp->config->callback == NULL ? 0 : STM32_TIM_DIER_UIE) |
                     (pwmp->config->dier & ~STM32_TIM_DIER_IRQ_MASK);
#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8
#if STM32_PWM_USE_ADVANCED
  pwmp->tim->BDTR  = pwmp->config->bdtr | STM32_TIM_BDTR_MOE;
#else
  pwmp->tim->BDTR  = STM32_TIM_BDTR_MOE;
#endif
#endif
  /* Timer configured and started.*/
  pwmp->tim->CR1   = STM32_TIM_CR1_ARPE | STM32_TIM_CR1_URS |
                     STM32_TIM_CR1_CEN;
}

/**
 * @brief   Deactivates the PWM peripheral.
 *
 * @param[in] pwmp      pointer to a @p PWMDriver object
 *
 * @notapi
 */
void pwm_lld_stop(PWMDriver *pwmp) {

  /* If in ready state then disables the PWM clock.*/
  if (pwmp->state == PWM_READY) {
    pwmp->tim->CR1  = 0;                    /* Timer disabled.              */
    pwmp->tim->DIER = 0;                    /* All IRQs disabled.           */
    pwmp->tim->SR   = 0;                    /* Clear eventual pending IRQs. */
#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8
    pwmp->tim->BDTR  = 0;
#endif

#if STM32_PWM_USE_TIM1
    if (&PWMD1 == pwmp) {
      nvicDisableVector(STM32_TIM1_UP_NUMBER);
      nvicDisableVector(STM32_TIM1_CC_NUMBER);
      rccDisableTIM1(FALSE);
    }
#endif
#if STM32_PWM_USE_TIM2
    if (&PWMD2 == pwmp) {
      nvicDisableVector(STM32_TIM2_NUMBER);
      rccDisableTIM2(FALSE);
    }
#endif
#if STM32_PWM_USE_TIM3
    if (&PWMD3 == pwmp) {
      nvicDisableVector(STM32_TIM3_NUMBER);
      rccDisableTIM3(FALSE);
    }
#endif
#if STM32_PWM_USE_TIM4
    if (&PWMD4 == pwmp) {
      nvicDisableVector(STM32_TIM4_NUMBER);
      rccDisableTIM4(FALSE);
    }
#endif
#if STM32_PWM_USE_TIM5
    if (&PWMD5 == pwmp) {
      nvicDisableVector(STM32_TIM5_NUMBER);
      rccDisableTIM5(FALSE);
    }
#endif
#if STM32_PWM_USE_TIM8
    if (&PWMD8 == pwmp) {
      nvicDisableVector(STM32_TIM8_UP_NUMBER);
      nvicDisableVector(STM32_TIM8_CC_NUMBER);
      rccDisableTIM8(FALSE);
    }
#endif
#if STM32_PWM_USE_TIM9
    if (&PWMD9 == pwmp) {
      nvicDisableVector(STM32_TIM9_NUMBER);
      rccDisableTIM9(FALSE);
    }
#endif
  }
}

/**
 * @brief   Enables a PWM channel.
 * @pre     The PWM unit must have been activated using @p pwmStart().
 * @post    The channel is active using the specified configuration.
 * @note    The function has effect at the next cycle start.
 *
 * @param[in] pwmp      pointer to a @p PWMDriver object
 * @param[in] channel   PWM channel identifier (0...PWM_CHANNELS-1)
 * @param[in] width     PWM pulse width as clock pulses number
 *
 * @notapi
 */
void pwm_lld_enable_channel(PWMDriver *pwmp,
                            pwmchannel_t channel,
                            pwmcnt_t width) {

  pwmp->tim->CCR[channel] = width;                  /* New duty cycle.      */
  /* If there is a callback defined for the channel then the associated
     interrupt must be enabled.*/
  if (pwmp->config->channels[channel].callback != NULL) {
    uint32_t dier = pwmp->tim->DIER;
    /* If the IRQ is not already enabled care must be taken to clear it,
       it is probably already pending because the timer is running.*/
    if ((dier & (2 << channel)) == 0) {
      pwmp->tim->DIER = dier | (2 << channel);
      pwmp->tim->SR   = ~(2 << channel);
    }
  }
}

/**
 * @brief   Disables a PWM channel.
 * @pre     The PWM unit must have been activated using @p pwmStart().
 * @post    The channel is disabled and its output line returned to the
 *          idle state.
 * @note    The function has effect at the next cycle start.
 *
 * @param[in] pwmp      pointer to a @p PWMDriver object
 * @param[in] channel   PWM channel identifier (0...PWM_CHANNELS-1)
 *
 * @notapi
 */
void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) {

  pwmp->tim->CCR[channel] = 0;
  pwmp->tim->DIER &= ~(2 << channel);
}
Example #4
0
/**
 * @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;

  chDbgAssert((icup->config->channel == ICU_CHANNEL_1) ||
              (icup->config->channel == ICU_CHANNEL_2),
              "icu_lld_start(), #1", "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,
                       CORTEX_PRIORITY_MASK(STM32_ICU_TIM1_IRQ_PRIORITY));
      nvicEnableVector(STM32_TIM1_CC_NUMBER,
                       CORTEX_PRIORITY_MASK(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,
                       CORTEX_PRIORITY_MASK(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,
                       CORTEX_PRIORITY_MASK(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,
                       CORTEX_PRIORITY_MASK(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,
                       CORTEX_PRIORITY_MASK(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,
                       CORTEX_PRIORITY_MASK(STM32_ICU_TIM8_IRQ_PRIORITY));
      nvicEnableVector(STM32_TIM8_CC_NUMBER,
                       CORTEX_PRIORITY_MASK(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,
                       CORTEX_PRIORITY_MASK(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;
  chDbgAssert((psc <= 0xFFFF) &&
              ((psc + 1) * icup->config->frequency) == icup->clock,
              "icu_lld_start(), #1", "invalid frequency");
  icup->tim->PSC  = (uint16_t)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];
  }
}
Example #5
0
/**
 * @brief   Configures and activates the PWM peripheral.
 * @note    Starting a driver that is already in the @p PWM_READY state
 *          disables all the active channels.
 *
 * @param[in] pwmp      pointer to a @p PWMDriver object
 *
 * @notapi
 */
void pwm_lld_start(PWMDriver *pwmp) {
  uint32_t psc;
  uint32_t ccer;

  if (pwmp->state == PWM_STOP) {
    /* Clock activation and timer reset.*/
#if STM32_PWM_USE_TIM1
    if (&PWMD1 == pwmp) {
      rccEnableTIM1(FALSE);
      rccResetTIM1();
#if !defined(STM32_TIM1_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY);
      nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM1CLK)
      pwmp->clock = STM32_TIM1CLK;
#else
      pwmp->clock = STM32_TIMCLK2;
#endif
    }
#endif

#if STM32_PWM_USE_TIM2
    if (&PWMD2 == pwmp) {
      rccEnableTIM2(FALSE);
      rccResetTIM2();
#if !defined(STM32_TIM2_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM2_NUMBER, STM32_PWM_TIM2_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM2CLK)
      pwmp->clock = STM32_TIM2CLK;
#else
      pwmp->clock = STM32_TIMCLK1;
#endif
    }
#endif

#if STM32_PWM_USE_TIM3
    if (&PWMD3 == pwmp) {
      rccEnableTIM3(FALSE);
      rccResetTIM3();
#if !defined(STM32_TIM3_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM3_NUMBER, STM32_PWM_TIM3_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM3CLK)
      pwmp->clock = STM32_TIM3CLK;
#else
      pwmp->clock = STM32_TIMCLK1;
#endif
    }
#endif

#if STM32_PWM_USE_TIM4
    if (&PWMD4 == pwmp) {
      rccEnableTIM4(FALSE);
      rccResetTIM4();
#if !defined(STM32_TIM4_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM4_NUMBER, STM32_PWM_TIM4_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM4CLK)
      pwmp->clock = STM32_TIM4CLK;
#else
      pwmp->clock = STM32_TIMCLK1;
#endif
    }
#endif

#if STM32_PWM_USE_TIM5
    if (&PWMD5 == pwmp) {
      rccEnableTIM5(FALSE);
      rccResetTIM5();
#if !defined(STM32_TIM5_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM5_NUMBER, STM32_PWM_TIM5_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM5CLK)
      pwmp->clock = STM32_TIM5CLK;
#else
      pwmp->clock = STM32_TIMCLK1;
#endif
    }
#endif

#if STM32_PWM_USE_TIM8
    if (&PWMD8 == pwmp) {
      rccEnableTIM8(FALSE);
      rccResetTIM8();
#if !defined(STM32_TIM8_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY);
      nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM8CLK)
      pwmp->clock = STM32_TIM8CLK;
#else
      pwmp->clock = STM32_TIMCLK2;
#endif
    }
#endif

#if STM32_PWM_USE_TIM9
    if (&PWMD9 == pwmp) {
      rccEnableTIM9(FALSE);
      rccResetTIM9();
#if !defined(STM32_TIM9_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM9_NUMBER, STM32_PWM_TIM9_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM9CLK)
      pwmp->clock = STM32_TIM9CLK;
#else
      pwmp->clock = STM32_TIMCLK2;
#endif
    }
#endif

    /* All channels configured in PWM1 mode with preload enabled and will
       stay that way until the driver is stopped.*/
    pwmp->tim->CCMR1 = STM32_TIM_CCMR1_OC1M(6) | STM32_TIM_CCMR1_OC1PE |
                       STM32_TIM_CCMR1_OC2M(6) | STM32_TIM_CCMR1_OC2PE;
    pwmp->tim->CCMR2 = STM32_TIM_CCMR2_OC3M(6) | STM32_TIM_CCMR2_OC3PE |
                       STM32_TIM_CCMR2_OC4M(6) | STM32_TIM_CCMR2_OC4PE;
#if STM32_TIM_MAX_CHANNELS > 4
    pwmp->tim->CCMR3 = STM32_TIM_CCMR3_OC5M(6) | STM32_TIM_CCMR3_OC5PE |
                       STM32_TIM_CCMR3_OC6M(6) | STM32_TIM_CCMR3_OC6PE;
#endif
  }
  else {
    /* Driver re-configuration scenario, it must be stopped first.*/
    pwmp->tim->CR1    = 0;                  /* Timer disabled.              */
    pwmp->tim->CCR[0] = 0;                  /* Comparator 1 disabled.       */
    pwmp->tim->CCR[1] = 0;                  /* Comparator 2 disabled.       */
    pwmp->tim->CCR[2] = 0;                  /* Comparator 3 disabled.       */
    pwmp->tim->CCR[3] = 0;                  /* Comparator 4 disabled.       */
#if STM32_TIM_MAX_CHANNELS > 4
    if (pwmp->channels > 4) {
      pwmp->tim->CCXR[0] = 0;               /* Comparator 5 disabled.       */
      pwmp->tim->CCXR[1] = 0;               /* Comparator 6 disabled.       */
    }
#endif
    pwmp->tim->CNT  = 0;                    /* Counter reset to zero.       */
  }

  /* Timer configuration.*/
  psc = (pwmp->clock / pwmp->config->frequency) - 1;
  osalDbgAssert((psc <= 0xFFFF) &&
                ((psc + 1) * pwmp->config->frequency) == pwmp->clock,
                "invalid frequency");
  pwmp->tim->PSC  = psc;
  pwmp->tim->ARR  = pwmp->period - 1;
  pwmp->tim->CR2  = pwmp->config->cr2;

  /* Output enables and polarities setup.*/
  ccer = 0;
  switch (pwmp->config->channels[0].mode & PWM_OUTPUT_MASK) {
  case PWM_OUTPUT_ACTIVE_LOW:
    ccer |= STM32_TIM_CCER_CC1P;
  case PWM_OUTPUT_ACTIVE_HIGH:
    ccer |= STM32_TIM_CCER_CC1E;
  default:
    ;
  }
  switch (pwmp->config->channels[1].mode & PWM_OUTPUT_MASK) {
  case PWM_OUTPUT_ACTIVE_LOW:
    ccer |= STM32_TIM_CCER_CC2P;
  case PWM_OUTPUT_ACTIVE_HIGH:
    ccer |= STM32_TIM_CCER_CC2E;
  default:
    ;
  }
  switch (pwmp->config->channels[2].mode & PWM_OUTPUT_MASK) {
  case PWM_OUTPUT_ACTIVE_LOW:
    ccer |= STM32_TIM_CCER_CC3P;
  case PWM_OUTPUT_ACTIVE_HIGH:
    ccer |= STM32_TIM_CCER_CC3E;
  default:
    ;
  }
  switch (pwmp->config->channels[3].mode & PWM_OUTPUT_MASK) {
  case PWM_OUTPUT_ACTIVE_LOW:
    ccer |= STM32_TIM_CCER_CC4P;
  case PWM_OUTPUT_ACTIVE_HIGH:
    ccer |= STM32_TIM_CCER_CC4E;
  default:
    ;
  }
#if STM32_PWM_USE_ADVANCED
#if STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8
  if (&PWMD1 == pwmp) {
#endif
#if !STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8
  if (&PWMD8 == pwmp) {
#endif
#if STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8
  if ((&PWMD1 == pwmp) || (&PWMD8 == pwmp)) {
#endif
    switch (pwmp->config->channels[0].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) {
    case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW:
      ccer |= STM32_TIM_CCER_CC1NP;
    case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH:
      ccer |= STM32_TIM_CCER_CC1NE;
    default:
      ;
    }
    switch (pwmp->config->channels[1].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) {
    case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW:
      ccer |= STM32_TIM_CCER_CC2NP;
    case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH:
      ccer |= STM32_TIM_CCER_CC2NE;
    default:
      ;
    }
    switch (pwmp->config->channels[2].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) {
    case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW:
      ccer |= STM32_TIM_CCER_CC3NP;
    case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH:
      ccer |= STM32_TIM_CCER_CC3NE;
    default:
      ;
    }
  }
#endif /* STM32_PWM_USE_ADVANCED*/

  pwmp->tim->CCER  = ccer;
  pwmp->tim->EGR   = STM32_TIM_EGR_UG;      /* Update event.                */
  pwmp->tim->SR    = 0;                     /* Clear pending IRQs.          */
  pwmp->tim->DIER  = pwmp->config->dier &   /* DMA-related DIER settings.   */
                     ~STM32_TIM_DIER_IRQ_MASK;
#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8
#if STM32_PWM_USE_ADVANCED
  pwmp->tim->BDTR  = pwmp->config->bdtr | STM32_TIM_BDTR_MOE;
#else
  pwmp->tim->BDTR  = STM32_TIM_BDTR_MOE;
#endif
#endif
  /* Timer configured and started.*/
  pwmp->tim->CR1   = STM32_TIM_CR1_ARPE | STM32_TIM_CR1_URS |
                     STM32_TIM_CR1_CEN;
}

/**
 * @brief   Deactivates the PWM peripheral.
 *
 * @param[in] pwmp      pointer to a @p PWMDriver object
 *
 * @notapi
 */
void pwm_lld_stop(PWMDriver *pwmp) {

  /* If in ready state then disables the PWM clock.*/
  if (pwmp->state == PWM_READY) {
    pwmp->tim->CR1  = 0;                    /* Timer disabled.              */
    pwmp->tim->DIER = 0;                    /* All IRQs disabled.           */
    pwmp->tim->SR   = 0;                    /* Clear eventual pending IRQs. */
#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8
    pwmp->tim->BDTR  = 0;
#endif

#if STM32_PWM_USE_TIM1
    if (&PWMD1 == pwmp) {
#if !defined(STM32_TIM1_SUPPRESS_ISR)
      nvicDisableVector(STM32_TIM1_UP_NUMBER);
      nvicDisableVector(STM32_TIM1_CC_NUMBER);
#endif
      rccDisableTIM1(FALSE);
    }
#endif

#if STM32_PWM_USE_TIM2
    if (&PWMD2 == pwmp) {
#if !defined(STM32_TIM2_SUPPRESS_ISR)
      nvicDisableVector(STM32_TIM2_NUMBER);
#endif
      rccDisableTIM2(FALSE);
    }
#endif

#if STM32_PWM_USE_TIM3
    if (&PWMD3 == pwmp) {
#if !defined(STM32_TIM3_SUPPRESS_ISR)
      nvicDisableVector(STM32_TIM3_NUMBER);
#endif
      rccDisableTIM3(FALSE);
    }
#endif

#if STM32_PWM_USE_TIM4
    if (&PWMD4 == pwmp) {
#if !defined(STM32_TIM4_SUPPRESS_ISR)
      nvicDisableVector(STM32_TIM4_NUMBER);
#endif
      rccDisableTIM4(FALSE);
    }
#endif

#if STM32_PWM_USE_TIM5
    if (&PWMD5 == pwmp) {
#if !defined(STM32_TIM5_SUPPRESS_ISR)
      nvicDisableVector(STM32_TIM5_NUMBER);
#endif
      rccDisableTIM5(FALSE);
    }
#endif

#if STM32_PWM_USE_TIM8
    if (&PWMD8 == pwmp) {
#if !defined(STM32_TIM8_SUPPRESS_ISR)
      nvicDisableVector(STM32_TIM8_UP_NUMBER);
      nvicDisableVector(STM32_TIM8_CC_NUMBER);
#endif
      rccDisableTIM8(FALSE);
    }
#endif

#if STM32_PWM_USE_TIM9
    if (&PWMD9 == pwmp) {
#if !defined(STM32_TIM9_SUPPRESS_ISR)
      nvicDisableVector(STM32_TIM9_NUMBER);
#endif
      rccDisableTIM9(FALSE);
    }
#endif
  }
}

/**
 * @brief   Enables a PWM channel.
 * @pre     The PWM unit must have been activated using @p pwmStart().
 * @post    The channel is active using the specified configuration.
 * @note    The function has effect at the next cycle start.
 * @note    Channel notification is not enabled.
 *
 * @param[in] pwmp      pointer to a @p PWMDriver object
 * @param[in] channel   PWM channel identifier (0...channels-1)
 * @param[in] width     PWM pulse width as clock pulses number
 *
 * @notapi
 */
void pwm_lld_enable_channel(PWMDriver *pwmp,
                            pwmchannel_t channel,
                            pwmcnt_t width) {

  /* Changing channel duty cycle on the fly.*/
#if STM32_TIM_MAX_CHANNELS <= 4
  pwmp->tim->CCR[channel] = width;
#else
  if (channel < 4)
    pwmp->tim->CCR[channel] = width;
  else
    pwmp->tim->CCXR[channel - 4] = width;
#endif
}

/**
 * @brief   Disables a PWM channel and its notification.
 * @pre     The PWM unit must have been activated using @p pwmStart().
 * @post    The channel is disabled and its output line returned to the
 *          idle state.
 * @note    The function has effect at the next cycle start.
 *
 * @param[in] pwmp      pointer to a @p PWMDriver object
 * @param[in] channel   PWM channel identifier (0...channels-1)
 *
 * @notapi
 */
void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) {

#if STM32_TIM_MAX_CHANNELS <= 4
  pwmp->tim->CCR[channel] = 0;
  pwmp->tim->DIER &= ~(2 << channel);
#else
  if (channel < 4) {
    pwmp->tim->CCR[channel] = 0;
    pwmp->tim->DIER &= ~(2 << channel);
  }
  else
    pwmp->tim->CCXR[channel - 4] = 0;
#endif
}
Example #6
0
/**
 * @brief   Configures and activates the GPT peripheral.
 *
 * @param[in] gptp      pointer to the @p GPTDriver object
 *
 * @notapi
 */
void gpt_lld_start(GPTDriver *gptp) {
  uint16_t psc;

  if (gptp->state == GPT_STOP) {
    /* Clock activation.*/
#if STM32_GPT_USE_TIM1
    if (&GPTD1 == gptp) {
      rccEnableTIM1(FALSE);
      rccResetTIM1();
#if !defined(STM32_TIM1_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_GPT_TIM1_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM1CLK)
      gptp->clock = STM32_TIM1CLK;
#else
      gptp->clock = STM32_TIMCLK2;
#endif
    }
#endif

#if STM32_GPT_USE_TIM2
    if (&GPTD2 == gptp) {
      rccEnableTIM2(FALSE);
      rccResetTIM2();
#if !defined(STM32_TIM2_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM2_NUMBER, STM32_GPT_TIM2_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM2CLK)
      gptp->clock = STM32_TIM2CLK;
#else
      gptp->clock = STM32_TIMCLK1;
#endif
    }
#endif

#if STM32_GPT_USE_TIM3
    if (&GPTD3 == gptp) {
      rccEnableTIM3(FALSE);
      rccResetTIM3();
#if !defined(STM32_TIM3_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM3_NUMBER, STM32_GPT_TIM3_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM3CLK)
      gptp->clock = STM32_TIM3CLK;
#else
      gptp->clock = STM32_TIMCLK1;
#endif
    }
#endif

#if STM32_GPT_USE_TIM4
    if (&GPTD4 == gptp) {
      rccEnableTIM4(FALSE);
      rccResetTIM4();
#if !defined(STM32_TIM4_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM4_NUMBER, STM32_GPT_TIM4_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM4CLK)
      gptp->clock = STM32_TIM4CLK;
#else
      gptp->clock = STM32_TIMCLK1;
#endif
    }
#endif

#if STM32_GPT_USE_TIM5
    if (&GPTD5 == gptp) {
      rccEnableTIM5(FALSE);
      rccResetTIM5();
#if !defined(STM32_TIM5_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM5_NUMBER, STM32_GPT_TIM5_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM5CLK)
      gptp->clock = STM32_TIM5CLK;
#else
      gptp->clock = STM32_TIMCLK1;
#endif
    }
#endif

#if STM32_GPT_USE_TIM6
    if (&GPTD6 == gptp) {
      rccEnableTIM6(FALSE);
      rccResetTIM6();
#if !defined(STM32_TIM6_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM6_NUMBER, STM32_GPT_TIM6_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM6CLK)
      gptp->clock = STM32_TIM6CLK;
#else
      gptp->clock = STM32_TIMCLK1;
#endif
    }
#endif

#if STM32_GPT_USE_TIM7
    if (&GPTD7 == gptp) {
      rccEnableTIM7(FALSE);
      rccResetTIM7();
#if !defined(STM32_TIM7_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM7_NUMBER, STM32_GPT_TIM7_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM7CLK)
      gptp->clock = STM32_TIM7CLK;
#else
      gptp->clock = STM32_TIMCLK1;
#endif
    }
#endif

#if STM32_GPT_USE_TIM8
    if (&GPTD8 == gptp) {
      rccEnableTIM8(FALSE);
      rccResetTIM8();
#if !defined(STM32_TIM8_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_GPT_TIM8_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM8CLK)
      gptp->clock = STM32_TIM8CLK;
#else
      gptp->clock = STM32_TIMCLK2;
#endif
    }
#endif

#if STM32_GPT_USE_TIM9
    if (&GPTD9 == gptp) {
      rccEnableTIM9(FALSE);
      rccResetTIM9();
#if !defined(STM32_TIM9_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM9_NUMBER, STM32_GPT_TIM9_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM9CLK)
      gptp->clock = STM32_TIM9CLK;
#else
      gptp->clock = STM32_TIMCLK2;
#endif
    }
#endif

#if STM32_GPT_USE_TIM11
    if (&GPTD11 == gptp) {
      rccEnableTIM11(FALSE);
      rccResetTIM11();
#if !defined(STM32_TIM11_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM11_NUMBER, STM32_GPT_TIM11_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM11CLK)
      gptp->clock = STM32_TIM11CLK;
#else
      gptp->clock = STM32_TIMCLK2;
#endif
    }
#endif

#if STM32_GPT_USE_TIM12
    if (&GPTD12 == gptp) {
      rccEnableTIM12(FALSE);
      rccResetTIM12();
#if !defined(STM32_TIM12_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM12_NUMBER, STM32_GPT_TIM12_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM12CLK)
      gptp->clock = STM32_TIM12CLK;
#else
      gptp->clock = STM32_TIMCLK1;
#endif
    }
#endif

#if STM32_GPT_USE_TIM14
    if (&GPTD14 == gptp) {
      rccEnableTIM14(FALSE);
      rccResetTIM14();
#if !defined(STM32_TIM14_SUPPRESS_ISR)
      nvicEnableVector(STM32_TIM14_NUMBER, STM32_GPT_TIM14_IRQ_PRIORITY);
#endif
#if defined(STM32_TIM14CLK)
      gptp->clock = STM32_TIM14CLK;
#else
      gptp->clock = STM32_TIMCLK1;
#endif
    }
#endif
  }

  /* Prescaler value calculation.*/
  psc = (uint16_t)((gptp->clock / gptp->config->frequency) - 1);
  osalDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock,
                "invalid frequency");

  /* Timer configuration.*/
  gptp->tim->CR1  = 0;                          /* Initially stopped.       */
  gptp->tim->CR2  = gptp->config->cr2;
  gptp->tim->PSC  = psc;                        /* Prescaler value.         */
  gptp->tim->SR   = 0;                          /* Clear pending IRQs.      */
  gptp->tim->DIER = gptp->config->dier &        /* DMA-related DIER bits.   */
                    ~STM32_TIM_DIER_IRQ_MASK;
}
/**
 * @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, STM32_TIMCAP_TIM1_IRQ_PRIORITY);
      nvicEnableVector(STM32_TIM1_CC_NUMBER, 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, 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, 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, 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, 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, STM32_TIMCAP_TIM8_IRQ_PRIORITY);
      nvicEnableVector(STM32_TIM8_CC_NUMBER, 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, 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;
  osalDbgAssert((psc <= 0xFFFF) &&
              ((psc + 1) * timcapp->config->frequency) == timcapp->clock,
              "invalid frequency");
  timcapp->tim->PSC  = (uint16_t)psc;
  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_DISABLED: Input not used.
       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 if (timcapp->config->modes[chan] == TIMCAP_INPUT_ACTIVE_LOW) {
      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;
      }
    }
    else {
      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;
      }
    }
    /* 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);
}
Example #8
0
void PwmPin_t::Init(GPIO_TypeDef *GPIO, uint16_t N, TIM_TypeDef* PTim, uint8_t Chnl, uint16_t TopValue, bool Inverted) {
    Tim = PTim;
    if(Tim == TIM2) {
        rccEnableTIM2(FALSE);
        PinSetupAlterFunc(GPIO, N, omPushPull, pudNone, AF1);
    }
    else if(Tim == TIM3) {
        rccEnableTIM3(FALSE);
        PinSetupAlterFunc(GPIO, N, omPushPull, pudNone, AF2);
    }
    else if(Tim == TIM4) {
        rccEnableTIM4(FALSE);
        PinSetupAlterFunc(GPIO, N, omPushPull, pudNone, AF2);
    }
    else if(Tim == TIM9) {
        rccEnableTIM9(FALSE);
        PinSetupAlterFunc(GPIO, N, omPushPull, pudNone, AF3);
    }
    else if(Tim == TIM10) {
        rccEnableAPB2(RCC_APB2ENR_TIM10EN, FALSE);
        PinSetupAlterFunc(GPIO, N, omPushPull, pudNone, AF3);
    }
    else if(Tim == TIM11) {
        rccEnableAPB2(RCC_APB2ENR_TIM11EN, FALSE);
        PinSetupAlterFunc(GPIO, N, omPushPull, pudNone, AF3);
    }
    // Clock src
    if(ANY_OF_3(Tim, TIM2, TIM3, TIM4)) PClk = &Clk.APB1FreqHz;
    else PClk = &Clk.APB2FreqHz;

    // Common
    Tim->CR1 = TIM_CR1_CEN; // Enable timer, set clk division to 0, AutoReload not buffered
    Tim->CR2 = 0;
    Tim->ARR = TopValue;

    // Output
    uint16_t tmp = Inverted? 0b111 : 0b110; // PWM mode 1 or 2
    switch(Chnl) {
        case 1:
            PCCR = &Tim->CCR1;
            Tim->CCMR1 |= (tmp << 4);
            Tim->CCER  |= TIM_CCER_CC1E;
            break;

        case 2:
            PCCR = &Tim->CCR2;
            Tim->CCMR1 |= (tmp << 12);
            Tim->CCER  |= TIM_CCER_CC2E;
            break;

        case 3:
            PCCR = &Tim->CCR3;
            Tim->CCMR2 |= (tmp << 4);
            Tim->CCER  |= TIM_CCER_CC3E;
            break;

        case 4:
            PCCR = &Tim->CCR4;
            Tim->CCMR2 |= (tmp << 12);
            Tim->CCER  |= TIM_CCER_CC4E;
            break;

        default: break;
    }
    *PCCR = 0;
}
/**
 * @brief   Configures and activates the EICU peripheral.
 *
 * @param[in] eicup     Pointer to the @p EICUDriver object
 *
 * @notapi
 */
void eicu_lld_start(EICUDriver *eicup) {
  uint32_t psc;
  size_t ch;

  osalDbgAssert((eicup->config->iccfgp[0] != NULL) ||
                (eicup->config->iccfgp[1] != NULL) ||
                (eicup->config->iccfgp[2] != NULL) ||
                (eicup->config->iccfgp[3] != NULL),
                 "invalid input configuration");

  if (eicup->state == EICU_STOP) {
    /* Clock activation and timer reset.*/
#if STM32_EICU_USE_TIM1
    if (&EICUD1 == eicup) {
      rccEnableTIM1(FALSE);
      rccResetTIM1();
      nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_EICU_TIM1_IRQ_PRIORITY);
      nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_EICU_TIM1_IRQ_PRIORITY);
      eicup->channels = 4;
#if defined(STM32_TIM1CLK)
      eicup->clock = STM32_TIM1CLK;
#else
      eicup->clock = STM32_TIMCLK2;
#endif
    }
#endif
#if STM32_EICU_USE_TIM2
    if (&EICUD2 == eicup) {
      rccEnableTIM2(FALSE);
      rccResetTIM2();
      nvicEnableVector(STM32_TIM2_NUMBER, STM32_EICU_TIM2_IRQ_PRIORITY);
      eicup->channels = 4;
      eicup->clock = STM32_TIMCLK1;
    }
#endif
#if STM32_EICU_USE_TIM3
    if (&EICUD3 == eicup) {
      rccEnableTIM3(FALSE);
      rccResetTIM3();
      nvicEnableVector(STM32_TIM3_NUMBER, STM32_EICU_TIM3_IRQ_PRIORITY);
      eicup->channels = 4;
      eicup->clock = STM32_TIMCLK1;
    }
#endif
#if STM32_EICU_USE_TIM4
    if (&EICUD4 == eicup) {
      rccEnableTIM4(FALSE);
      rccResetTIM4();
      nvicEnableVector(STM32_TIM4_NUMBER, STM32_EICU_TIM4_IRQ_PRIORITY);
      eicup->channels = 4;
      eicup->clock = STM32_TIMCLK1;
    }
#endif
#if STM32_EICU_USE_TIM5
    if (&EICUD5 == eicup) {
      rccEnableTIM5(FALSE);
      rccResetTIM5();
      nvicEnableVector(STM32_TIM5_NUMBER, STM32_EICU_TIM5_IRQ_PRIORITY);
      eicup->channels = 4;
      eicup->clock = STM32_TIMCLK1;
    }
#endif
#if STM32_EICU_USE_TIM8
    if (&EICUD8 == eicup) {
      rccEnableTIM8(FALSE);
      rccResetTIM8();
      nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_EICU_TIM8_IRQ_PRIORITY);
      nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_EICU_TIM8_IRQ_PRIORITY);
      eicup->channels = 4;
#if defined(STM32_TIM8CLK)
      eicup->clock = STM32_TIM8CLK;
#else
      eicup->clock = STM32_TIMCLK2;
#endif
    }
#endif
#if STM32_EICU_USE_TIM9
    if (&EICUD9 == eicup) {
      rccEnableTIM9(FALSE);
      rccResetTIM9();
      nvicEnableVector(STM32_TIM9_NUMBER, STM32_EICU_TIM9_IRQ_PRIORITY);
      eicup->channels = 2;
      eicup->clock = STM32_TIMCLK2;
    }
#endif
#if STM32_EICU_USE_TIM12
    if (&EICUD12 == eicup) {
      rccEnableTIM12(FALSE);
      rccResetTIM12();
      nvicEnableVector(STM32_TIM12_NUMBER, STM32_EICU_TIM12_IRQ_PRIORITY);
      eicup->channels = 2;
      eicup->clock = STM32_TIMCLK1;
    }
#endif
#if STM32_EICU_USE_TIM10
    if (&EICUD10 == eicup) {
      rccEnableTIM10(FALSE);
      rccResetTIM10();
      nvicEnableVector(STM32_TIM10_NUMBER, STM32_EICU_TIM10_IRQ_PRIORITY);
      eicup->channels = 1;
      eicup->clock = STM32_TIMCLK2;
    }
#endif
#if STM32_EICU_USE_TIM11
    if (&EICUD11 == eicup) {
      rccEnableTIM11(FALSE);
      rccResetTIM11();
      nvicEnableVector(STM32_TIM11_NUMBER, STM32_EICU_TIM11_IRQ_PRIORITY);
      eicup->channels = 1;
      eicup->clock = STM32_TIMCLK2;
    }
#endif
#if STM32_EICU_USE_TIM13
    if (&EICUD13 == eicup) {
      rccEnableTIM13(FALSE);
      rccResetTIM13();
      nvicEnableVector(STM32_TIM13_NUMBER, STM32_EICU_TIM13_IRQ_PRIORITY);
      eicup->channels = 1;
      eicup->clock = STM32_TIMCLK1;
    }
#endif
#if STM32_EICU_USE_TIM14
    if (&EICUD14 == eicup) {
      rccEnableTIM14(FALSE);
      rccResetTIM14();
      nvicEnableVector(STM32_TIM14_NUMBER, STM32_EICU_TIM14_IRQ_PRIORITY);
      eicup->channels = 1;
      eicup->clock = STM32_TIMCLK1;
    }
#endif
  }
  else {
    /* Driver re-configuration scenario, it must be stopped first.*/
    eicup->tim->CR1    = 0;                   /* Timer disabled.              */
    eicup->tim->DIER   = eicup->config->dier &/* DMA-related DIER settings.   */
                        ~STM32_TIM_DIER_IRQ_MASK;
    eicup->tim->SR     = 0;                   /* Clear eventual pending IRQs. */
    eicup->tim->CCR[0] = 0;                   /* Comparator 1 disabled.       */
    eicup->tim->CCR[1] = 0;                   /* Comparator 2 disabled.       */
    eicup->tim->CNT    = 0;                   /* Counter reset to zero.       */
  }

  /* Timer configuration.*/
  psc = (eicup->clock / eicup->config->frequency) - 1;
  chDbgAssert((psc <= 0xFFFF) &&
             ((psc + 1) * eicup->config->frequency) == eicup->clock,
               "invalid frequency");
  eicup->tim->PSC   = (uint16_t)psc;
  eicup->tim->ARR   = (eicucnt_t)-1;

  /* Detect width.*/
  if (0xFFFFFFFF == eicup->tim->ARR)
    eicup->width = EICU_WIDTH_32;
  else if (0xFFFF == eicup->tim->ARR)
    eicup->width = EICU_WIDTH_16;
  else
    osalSysHalt("Unsupported width");

  /* Reset registers */
  eicup->tim->SMCR  = 0;
  eicup->tim->CCMR1 = 0;
  if (eicup->channels > 2)
    eicup->tim->CCMR2 = 0;

  /* clean channel structures and set pointers to channel configs */
  for (ch=0; ch<EICU_CHANNEL_ENUM_END; ch++) {
    eicup->channel[ch].last_active = 0;
    eicup->channel[ch].last_idle = 0;
    eicup->channel[ch].config = eicup->config->iccfgp[ch];
    eicup->channel[ch].state = EICU_CH_IDLE;
  }

  /* TIM9 and TIM12 have only 2 channels.*/
  if (eicup->channels == 2) {
    osalDbgCheck((eicup->config->iccfgp[2] == NULL) &&
                 (eicup->config->iccfgp[3] == NULL));
  }

  /* TIM10, TIM11, TIM13 and TIM14 have only 1 channel.*/
  if (eicup->channels == 1) {
    osalDbgCheck((eicup->config->iccfgp[1] == NULL) &&
                 (eicup->config->iccfgp[2] == NULL) &&
                 (eicup->config->iccfgp[3] == NULL));
  }

  start_channels(eicup);
}
Example #10
0
/**
 * @brief   Configures and activates the GPT peripheral.
 *
 * @param[in] gptp      pointer to the @p GPTDriver object
 *
 * @notapi
 */
void gpt_lld_start(GPTDriver *gptp) {
  uint16_t psc;

  if (gptp->state == GPT_STOP) {
    /* Clock activation.*/
#if STM32_GPT_USE_TIM1
    if (&GPTD1 == gptp) {
      rccEnableTIM1(FALSE);
      rccResetTIM1();
      nvicEnableVector(STM32_TIM1_UP_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_GPT_TIM1_IRQ_PRIORITY));
      gptp->clock = STM32_TIMCLK2;
    }
#endif
#if STM32_GPT_USE_TIM2
    if (&GPTD2 == gptp) {
      rccEnableTIM2(FALSE);
      rccResetTIM2();
      nvicEnableVector(STM32_TIM2_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_GPT_TIM2_IRQ_PRIORITY));
      gptp->clock = STM32_TIMCLK1;
    }
#endif
#if STM32_GPT_USE_TIM3
    if (&GPTD3 == gptp) {
      rccEnableTIM3(FALSE);
      rccResetTIM3();
      nvicEnableVector(STM32_TIM3_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_GPT_TIM3_IRQ_PRIORITY));
      gptp->clock = STM32_TIMCLK1;
    }
#endif
#if STM32_GPT_USE_TIM4
    if (&GPTD4 == gptp) {
      rccEnableTIM4(FALSE);
      rccResetTIM4();
      nvicEnableVector(STM32_TIM4_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_GPT_TIM4_IRQ_PRIORITY));
      gptp->clock = STM32_TIMCLK1;
    }
#endif

#if STM32_GPT_USE_TIM5
    if (&GPTD5 == gptp) {
      rccEnableTIM5(FALSE);
      rccResetTIM5();
      nvicEnableVector(STM32_TIM5_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_GPT_TIM5_IRQ_PRIORITY));
      gptp->clock = STM32_TIMCLK1;
    }
#endif

#if STM32_GPT_USE_TIM6
    if (&GPTD6 == gptp) {
      rccEnableTIM6(FALSE);
      rccResetTIM6();
      nvicEnableVector(STM32_TIM6_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_GPT_TIM6_IRQ_PRIORITY));
      gptp->clock = STM32_TIMCLK1;
    }
#endif

#if STM32_GPT_USE_TIM7
    if (&GPTD7 == gptp) {
      rccEnableTIM7(FALSE);
      rccResetTIM7();
      nvicEnableVector(STM32_TIM7_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_GPT_TIM7_IRQ_PRIORITY));
      gptp->clock = STM32_TIMCLK1;
    }
#endif

#if STM32_GPT_USE_TIM8
    if (&GPTD8 == gptp) {
      rccEnableTIM8(FALSE);
      rccResetTIM8();
      nvicEnableVector(STM32_TIM8_UP_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_GPT_TIM8_IRQ_PRIORITY));
      gptp->clock = STM32_TIMCLK2;
    }
#endif

#if STM32_GPT_USE_TIM9
    if (&GPTD9 == gptp) {
      rccEnableTIM9(FALSE);
      rccResetTIM9();
      nvicEnableVector(STM32_TIM9_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_GPT_TIM9_IRQ_PRIORITY));
      gptp->clock = STM32_TIMCLK2;
    }
#endif

#if STM32_GPT_USE_TIM11
    if (&GPTD11 == gptp) {
      rccEnableTIM11(FALSE);
      rccResetTIM11();
      nvicEnableVector(STM32_TIM11_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_GPT_TIM11_IRQ_PRIORITY));
      gptp->clock = STM32_TIMCLK2;
    }
#endif

#if STM32_GPT_USE_TIM12
    if (&GPTD12 == gptp) {
      rccEnableTIM12(FALSE);
      rccResetTIM12();
      nvicEnableVector(STM32_TIM12_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_GPT_TIM12_IRQ_PRIORITY));
      gptp->clock = STM32_TIMCLK1;
    }
#endif

#if STM32_GPT_USE_TIM14
    if (&GPTD14 == gptp) {
      rccEnableTIM14(FALSE);
      rccResetTIM14();
      nvicEnableVector(STM32_TIM14_NUMBER,
                       CORTEX_PRIORITY_MASK(STM32_GPT_TIM14_IRQ_PRIORITY));
      gptp->clock = STM32_TIMCLK1;
    }
#endif
  }

  /* Prescaler value calculation.*/
  psc = (uint16_t)((gptp->clock / gptp->config->frequency) - 1);
  chDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock,
              "gpt_lld_start(), #1", "invalid frequency");

  /* Timer configuration.*/
  gptp->tim->CR1  = 0;                      /* Initially stopped.           */
  gptp->tim->CR2  = TIM_CR2_CCDS;           /* DMA on UE (if any).          */
  gptp->tim->PSC  = psc;                    /* Prescaler value.             */
  gptp->tim->DIER = 0;
}