git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2417 35acf78f-673a-0410-8e92-d51de3d6d3f4

This commit is contained in:
gdisirio 2010-11-22 17:17:51 +00:00
parent 955425572d
commit 2c644359b5
1 changed files with 60 additions and 104 deletions

View File

@ -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 */