From 2c644359b52493357f87100afaecb8596eaa2ea3 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 22 Nov 2010 17:17:51 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2417 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/pwm_lld.c | 164 ++++++++++++++------------------------- 1 file changed, 60 insertions(+), 104 deletions(-) (limited to 'os/hal/platforms') diff --git a/os/hal/platforms/STM32/pwm_lld.c b/os/hal/platforms/STM32/pwm_lld.c index 4ef49ebca..9b9140eba 100644 --- a/os/hal/platforms/STM32/pwm_lld.c +++ b/os/hal/platforms/STM32/pwm_lld.c @@ -74,23 +74,6 @@ PWMDriver PWMD4; /* Driver local functions. */ /*===========================================================================*/ -/** - * @brief Stops all channels. - * - * @param[in] pwmp pointer to a @p PWMDriver object - */ -static void stop_channels(PWMDriver *pwmp) { - - pwmp->pd_enabled_channels = 0; /* All channels disabled. */ - pwmp->pd_tim->CCER = 0; /* Outputs disabled. */ - pwmp->pd_tim->CCR1 = 0; /* Comparator 1 disabled. */ - pwmp->pd_tim->CCR2 = 0; /* Comparator 2 disabled. */ - pwmp->pd_tim->CCR3 = 0; /* Comparator 3 disabled. */ - pwmp->pd_tim->CCR4 = 0; /* Comparator 4 disabled. */ - pwmp->pd_tim->CCMR1 = 0; /* Channels 1 and 2 frozen. */ - pwmp->pd_tim->CCMR2 = 0; /* Channels 3 and 4 frozen. */ -} - #if STM32_PWM_USE_TIM2 || STM32_PWM_USE_TIM3 || STM32_PWM_USE_TIM4 || \ defined(__DOXYGEN__) /** @@ -283,45 +266,73 @@ void pwm_lld_init(void) { void pwm_lld_start(PWMDriver *pwmp) { uint16_t ccer; + /* Reset channels.*/ + pwmp->pd_enabled_channels = 0; /* All channels disabled. */ + if (pwmp->pd_state == PWM_STOP) { - /* Clock activation.*/ + /* Clock activation and timer reset.*/ #if STM32_PWM_USE_TIM1 if (&PWMD1 == pwmp) { + RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; + RCC->APB2RSTR = RCC_APB2RSTR_TIM1RST; + RCC->APB2RSTR = 0; NVICEnableVector(TIM1_UP_IRQn, CORTEX_PRIORITY_MASK(STM32_PWM_PWM1_IRQ_PRIORITY)); NVICEnableVector(TIM1_CC_IRQn, CORTEX_PRIORITY_MASK(STM32_PWM_PWM1_IRQ_PRIORITY)); - RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; } #endif #if STM32_PWM_USE_TIM2 if (&PWMD2 == pwmp) { + RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; + RCC->APB1RSTR = RCC_APB1RSTR_TIM1RST; + RCC->APB1RSTR = 0; NVICEnableVector(TIM2_IRQn, CORTEX_PRIORITY_MASK(STM32_PWM_PWM2_IRQ_PRIORITY)); - RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; } #endif #if STM32_PWM_USE_TIM3 if (&PWMD3 == pwmp) { + RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; + RCC->APB1RSTR = RCC_APB1RSTR_TIM3RST; + RCC->APB1RSTR = 0; NVICEnableVector(TIM3_IRQn, CORTEX_PRIORITY_MASK(STM32_PWM_PWM3_IRQ_PRIORITY)); - RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; } #endif #if STM32_PWM_USE_TIM4 if (&PWMD4 == pwmp) { + RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; + RCC->APB1RSTR = RCC_APB1RSTR_TIM4RST; + RCC->APB1RSTR = 0; NVICEnableVector(TIM4_IRQn, CORTEX_PRIORITY_MASK(STM32_PWM_PWM4_IRQ_PRIORITY)); - RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; } #endif + /* All channels configured in PWM1 mode with preload enabled and will + stay that way until the driver is stopped.*/ + pwmp->pd_tim->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | + TIM_CCMR1_OC1PE | + TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2 | + TIM_CCMR1_OC2PE; + pwmp->pd_tim->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2 | + TIM_CCMR2_OC3PE | + TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2 | + TIM_CCMR2_OC4PE; + } + else { + /* Driver re-configuration scenario, it must be stopped first.*/ + /* Really required ?????????? */ + pwmp->pd_tim->CR1 = 0; /* Timer stopped. */ + pwmp->pd_tim->CR2 = 0; /* Timer stopped. */ + pwmp->pd_tim->SMCR = 0; /* Slave mode disabled. */ + pwmp->pd_tim->CCR1 = 0; /* Comparator 1 disabled. */ + pwmp->pd_tim->CCR2 = 0; /* Comparator 2 disabled. */ + pwmp->pd_tim->CCR3 = 0; /* Comparator 3 disabled. */ + pwmp->pd_tim->CCR4 = 0; /* Comparator 4 disabled. */ } - /* Reset channels.*/ - stop_channels(pwmp); - /* Configuration or reconfiguration.*/ - pwmp->pd_tim->CR1 = 0; /* Timer stopped. */ - pwmp->pd_tim->SMCR = 0; /* Slave mode disabled. */ + /* Timer configuration.*/ pwmp->pd_tim->CR2 = pwmp->pd_config->pc_cr2; pwmp->pd_tim->PSC = pwmp->pd_config->pc_psc; pwmp->pd_tim->CNT = 0; @@ -365,8 +376,8 @@ void pwm_lld_start(PWMDriver *pwmp) { pwmp->pd_tim->SR = 0; /* Clear pending IRQs. */ pwmp->pd_tim->DIER = pwmp->pd_config->pc_callback == NULL ? 0 : TIM_DIER_UIE; pwmp->pd_tim->BDTR = TIM_BDTR_MOE; - pwmp->pd_tim->CR1 = TIM_CR1_ARPE | TIM_CR1_URS | - TIM_CR1_CEN; /* Timer configured and started.*/ + /* Timer configured and started.*/ + pwmp->pd_tim->CR1 = TIM_CR1_ARPE | TIM_CR1_URS | TIM_CR1_CEN; } /** @@ -379,10 +390,18 @@ void pwm_lld_start(PWMDriver *pwmp) { void pwm_lld_stop(PWMDriver *pwmp) { /* If in ready state then disables the PWM clock.*/ if (pwmp->pd_state == PWM_READY) { - stop_channels(pwmp); - pwmp->pd_tim->CR1 = 0; - pwmp->pd_tim->BDTR = 0; - pwmp->pd_tim->DIER = 0; + pwmp->pd_enabled_channels = 0; /* All channels disabled. */ + pwmp->pd_tim->CR1 = 0; + pwmp->pd_tim->CR2 = 0; + pwmp->pd_tim->CCER = 0; /* Outputs disabled. */ + pwmp->pd_tim->CCR1 = 0; /* Comparator 1 disabled. */ + pwmp->pd_tim->CCR2 = 0; /* Comparator 2 disabled. */ + pwmp->pd_tim->CCR3 = 0; /* Comparator 3 disabled. */ + pwmp->pd_tim->CCR4 = 0; /* Comparator 4 disabled. */ + pwmp->pd_tim->BDTR = 0; + pwmp->pd_tim->DIER = 0; + pwmp->pd_tim->SR = 0; + pwmp->pd_tim->EGR = TIM_EGR_UG; /* Update event. */ #if STM32_PWM_USE_TIM1 if (&PWMD1 == pwmp) { @@ -425,58 +444,15 @@ void pwm_lld_enable_channel(PWMDriver *pwmp, pwmchannel_t channel, pwmcnt_t width) { - switch (channel) { - case 0: - pwmp->pd_tim->CCR1 = width; - break; - case 1: - pwmp->pd_tim->CCR2 = width; - break; - case 2: - pwmp->pd_tim->CCR3 = width; - break; - case 3: - pwmp->pd_tim->CCR4 = width; - break; - } + *(&pwmp->pd_tim->CCR1 + (channel * 2)) = width; /* New duty cycle. */ if ((pwmp->pd_enabled_channels & (1 << channel)) == 0) { /* The channel is not enabled yet.*/ pwmp->pd_enabled_channels |= (1 << channel); - /* Setup the comparator, the channel is configured as PWM mode 1 with - preload enabled.*/ - switch (channel) { - case 0: - pwmp->pd_tim->CCMR1 = (pwmp->pd_tim->CCMR1 & 0xFF00) | - TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | - TIM_CCMR1_OC1PE; - pwmp->pd_tim->SR = ~TIM_SR_CC1IF; - pwmp->pd_tim->DIER |= pwmp->pd_config->pc_channels[0].pcc_callback == NULL - ? 0 : TIM_DIER_CC1IE; - break; - case 1: - pwmp->pd_tim->CCMR1 = (pwmp->pd_tim->CCMR1 & 0x00FF) | - TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2 | - TIM_CCMR1_OC2PE; - pwmp->pd_tim->SR = ~TIM_SR_CC2IF; - pwmp->pd_tim->DIER |= pwmp->pd_config->pc_channels[1].pcc_callback == NULL - ? 0 : TIM_DIER_CC2IE; - break; - case 2: - pwmp->pd_tim->CCMR2 = (pwmp->pd_tim->CCMR2 & 0xFF00) | - TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2 | - TIM_CCMR2_OC3PE; - pwmp->pd_tim->SR = ~TIM_SR_CC3IF; - pwmp->pd_tim->DIER |= pwmp->pd_config->pc_channels[2].pcc_callback == NULL - ? 0 : TIM_DIER_CC3IE; - break; - case 3: - pwmp->pd_tim->CCMR2 = (pwmp->pd_tim->CCMR2 & 0x00FF) | - TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2 | - TIM_CCMR2_OC4PE; - pwmp->pd_tim->SR = ~TIM_SR_CC4IF; - pwmp->pd_tim->DIER |= pwmp->pd_config->pc_channels[3].pcc_callback == NULL - ? 0 : TIM_DIER_CC4IE; - break; + /* If there is a callback associated to the channel then the proper + interrupt is cleared and enabled.*/ + if (pwmp->pd_config->pc_channels[0].pcc_callback) { + pwmp->pd_tim->SR = ~(2 << channel); + pwmp->pd_tim->DIER |= (2 << channel); } } } @@ -491,29 +467,9 @@ void pwm_lld_enable_channel(PWMDriver *pwmp, */ void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) { + *(&pwmp->pd_tim->CCR1 + (channel * 2)) = 0; + pwmp->pd_tim->DIER = ~(2 << channel); pwmp->pd_enabled_channels &= ~(1 << channel); - switch (channel) { - case 0: - pwmp->pd_tim->CCR1 = 0; - pwmp->pd_tim->CCMR1 = pwmp->pd_tim->CCMR1 & 0xFF00; - pwmp->pd_tim->DIER &= ~TIM_DIER_CC1IE; - break; - case 1: - pwmp->pd_tim->CCR2 = 0; - pwmp->pd_tim->CCMR1 = pwmp->pd_tim->CCMR1 & 0x00FF; - pwmp->pd_tim->DIER &= ~TIM_DIER_CC2IE; - break; - case 2: - pwmp->pd_tim->CCR3 = 0; - pwmp->pd_tim->CCMR2 = pwmp->pd_tim->CCMR2 & 0xFF00; - pwmp->pd_tim->DIER &= ~TIM_DIER_CC3IE; - break; - case 3: - pwmp->pd_tim->CCR4 = 0; - pwmp->pd_tim->CCMR2 = pwmp->pd_tim->CCMR2 & 0x00FF; - pwmp->pd_tim->DIER &= ~TIM_DIER_CC4IE; - break; - } } #endif /* HAL_USE_PWM */ -- cgit v1.2.3