From 32e43fdb02ddb7582866c29dad5e6c87f3315605 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 21 Nov 2010 13:45:22 +0000 Subject: Fixed bug 3114481. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2409 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/pwm.h | 4 +- os/hal/platforms/STM32/pwm_lld.c | 173 ++++++++++++++++++--------------------- os/hal/platforms/STM32/pwm_lld.h | 7 +- os/hal/src/pwm.c | 13 +-- os/hal/templates/pwm_lld.c | 30 ++----- os/hal/templates/pwm_lld.h | 7 +- 6 files changed, 104 insertions(+), 130 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/pwm.h b/os/hal/include/pwm.h index 867cc1de6..ff1ba575f 100644 --- a/os/hal/include/pwm.h +++ b/os/hal/include/pwm.h @@ -82,7 +82,7 @@ typedef enum { * @iclass */ #define pwmEnableChannelI(pwmp, channel, width) { \ - pwm_lld_enable_channel(pwmp, channel, width); \ + pwm_lld_set_channel(pwmp, channel, width); \ } /** @@ -97,7 +97,7 @@ typedef enum { * @iclass */ #define pwmDisableChannelI(pwmp, channel) { \ - pwm_lld_disable_channel(pwmp, channel); \ + pwm_lld_set_channel(pwmp, channel, 0); \ } /*===========================================================================*/ diff --git a/os/hal/platforms/STM32/pwm_lld.c b/os/hal/platforms/STM32/pwm_lld.c index 335c0c8bd..f3588123a 100644 --- a/os/hal/platforms/STM32/pwm_lld.c +++ b/os/hal/platforms/STM32/pwm_lld.c @@ -414,115 +414,102 @@ void pwm_lld_stop(PWMDriver *pwmp) { } /** - * @brief Enables a PWM channel. + * @brief Disables, enables or reprograms a PWM channel. * * @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 + * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) + * @param[in] width PWM pulse width as clock pulses number, note that + * specifying zero disables the channel and enforces + * the output to the idle state. * * @notapi */ -void pwm_lld_enable_channel(PWMDriver *pwmp, - pwmchannel_t channel, - pwmcnt_t width) { - - /* - * Changes the pulse 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; - } - 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. - */ +void pwm_lld_set_channel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width) { + + if (width == 0) { + /* Channel disable mode.*/ + pwmp->pd_enabled_channels &= ~(1 << channel); 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; + pwmp->pd_tim->CCR1 = 0; + pwmp->pd_tim->CCMR1 = (pwmp->pd_tim->CCMR1 & 0xFF00) | TIM_CCMR1_OC1M_2; + pwmp->pd_tim->DIER &= ~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; + pwmp->pd_tim->CCR2 = 0; + pwmp->pd_tim->CCMR1 = (pwmp->pd_tim->CCMR1 & 0x00FF) | TIM_CCMR1_OC2M_2; + pwmp->pd_tim->DIER &= ~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; + pwmp->pd_tim->CCR3 = 0; + pwmp->pd_tim->CCMR2 = (pwmp->pd_tim->CCMR2 & 0xFF00) | TIM_CCMR2_OC3M_2; + pwmp->pd_tim->DIER &= ~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; + pwmp->pd_tim->CCR4 = 0; + pwmp->pd_tim->CCMR2 = (pwmp->pd_tim->CCMR2 & 0x00FF) | TIM_CCMR2_OC4M_2; + pwmp->pd_tim->DIER &= ~TIM_DIER_CC4IE; break; } } -} - -/** - * @brief Disables a PWM channel. - * @details The channel is disabled and its output line returned to the - * idle state. - * - * @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->pd_enabled_channels &= ~(1 << channel); - switch (channel) { - case 0: - pwmp->pd_tim->CCR1 = 0; - pwmp->pd_tim->CCMR1 = (pwmp->pd_tim->CCMR1 & 0xFF00) | TIM_CCMR1_OC1M_2; - pwmp->pd_tim->DIER &= ~TIM_DIER_CC1IE; - break; - case 1: - pwmp->pd_tim->CCR2 = 0; - pwmp->pd_tim->CCMR1 = (pwmp->pd_tim->CCMR1 & 0x00FF) | TIM_CCMR1_OC2M_2; - pwmp->pd_tim->DIER &= ~TIM_DIER_CC2IE; - break; - case 2: - pwmp->pd_tim->CCR3 = 0; - pwmp->pd_tim->CCMR2 = (pwmp->pd_tim->CCMR2 & 0xFF00) | TIM_CCMR2_OC3M_2; - pwmp->pd_tim->DIER &= ~TIM_DIER_CC3IE; - break; - case 3: - pwmp->pd_tim->CCR4 = 0; - pwmp->pd_tim->CCMR2 = (pwmp->pd_tim->CCMR2 & 0x00FF) | TIM_CCMR2_OC4M_2; - pwmp->pd_tim->DIER &= ~TIM_DIER_CC4IE; - break; + else { + /* Channel enable or reprogram mode.*/ + 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; + } + 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; + } + } } } diff --git a/os/hal/platforms/STM32/pwm_lld.h b/os/hal/platforms/STM32/pwm_lld.h index 194e60b48..4c3b99e4d 100644 --- a/os/hal/platforms/STM32/pwm_lld.h +++ b/os/hal/platforms/STM32/pwm_lld.h @@ -344,10 +344,9 @@ extern "C" { void pwm_lld_init(void); void pwm_lld_start(PWMDriver *pwmp); void pwm_lld_stop(PWMDriver *pwmp); - void pwm_lld_enable_channel(PWMDriver *pwmp, - pwmchannel_t channel, - pwmcnt_t width); - void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel); + void pwm_lld_set_channel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width); #ifdef __cplusplus } #endif diff --git a/os/hal/src/pwm.c b/os/hal/src/pwm.c index 79cc73b30..ecf9eba3f 100644 --- a/os/hal/src/pwm.c +++ b/os/hal/src/pwm.c @@ -117,8 +117,9 @@ void pwmStop(PWMDriver *pwmp) { * @details Programs (or reprograms) a PWM channel. * * @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 + * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) + * @param[in] width PWM pulse width as clock pulses number, setting the + * width at zero is equivalent to disabling the channel * * @api */ @@ -132,17 +133,17 @@ void pwmEnableChannel(PWMDriver *pwmp, chSysLock(); chDbgAssert(pwmp->pd_state == PWM_READY, "pwmEnableChannel(), #1", "not ready"); - pwm_lld_enable_channel(pwmp, channel, width); + pwm_lld_set_channel(pwmp, channel, width); chSysUnlock(); } /** - * @brief Disables a PWM channel. + * @brief Disables a PWM channel. * @details The channel is disabled and its output line returned to the * idle state. * * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1]) + * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) * * @api */ @@ -154,7 +155,7 @@ void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel) { chSysLock(); chDbgAssert(pwmp->pd_state == PWM_READY, "pwmDisableChannel(), #1", "not ready"); - pwm_lld_disable_channel(pwmp, channel); + pwm_lld_set_channel(pwmp, channel, 0); chSysUnlock(); } diff --git a/os/hal/templates/pwm_lld.c b/os/hal/templates/pwm_lld.c index 4f9aab29b..5a4838ade 100644 --- a/os/hal/templates/pwm_lld.c +++ b/os/hal/templates/pwm_lld.c @@ -102,31 +102,19 @@ bool_t pwm_lld_is_enabled(PWMDriver *pwmp, pwmchannel_t channel) { } /** - * @brief Enables a PWM channel. + * @brief Disables, enables or reprograms a PWM channel. * - * @param[in] pwmp pointer to the @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) { - -} - -/** - * @brief Disables a PWM channel. - * @details The channel is disabled and its output line returned to the - * idle state. - * - * @param[in] pwmp pointer to the @p PWMDriver object - * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1]) + * @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, note that + * specifying zero disables the channel and enforces + * the output to the idle state. * * @notapi */ -void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) { +void pwm_lld_set_channel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width) { } diff --git a/os/hal/templates/pwm_lld.h b/os/hal/templates/pwm_lld.h index 2b8cf294f..3e81959e7 100644 --- a/os/hal/templates/pwm_lld.h +++ b/os/hal/templates/pwm_lld.h @@ -195,10 +195,9 @@ extern "C" { void pwm_lld_start(PWMDriver *pwmp); void pwm_lld_stop(PWMDriver *pwmp); bool_t pwm_lld_is_enabled(PWMDriver *pwmp, pwmchannel_t channel); - void pwm_lld_enable_channel(PWMDriver *pwmp, - pwmchannel_t channel, - pwmcnt_t width); - void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel); + void pwm_lld_set_channel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width); #ifdef __cplusplus } #endif -- cgit v1.2.3