Fixed bugs 3114467 and 3114481.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/stable_2.0.x@2442 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
fc2a392477
commit
cdada0e185
|
@ -57,34 +57,50 @@
|
|||
* @brief Driver state machine possible states.
|
||||
*/
|
||||
typedef enum {
|
||||
PWM_UNINIT = 0, /**< @brief Not initialized. */
|
||||
PWM_STOP = 1, /**< @brief Stopped. */
|
||||
PWM_READY = 2, /**< @brief Ready. */
|
||||
PWM_UNINIT = 0, /**< Not initialized. */
|
||||
PWM_STOP = 1, /**< Stopped. */
|
||||
PWM_READY = 2, /**< Ready. */
|
||||
} pwmstate_t;
|
||||
|
||||
/**
|
||||
* @brief PWM logic mode.
|
||||
*/
|
||||
typedef enum {
|
||||
PWM_OUTPUT_DISABLED = 0, /**< @brief Output not driven, callback
|
||||
only. */
|
||||
PWM_OUTPUT_ACTIVE_HIGH = 1, /**< @brief Idle is logic level 0. */
|
||||
PWM_OUTPUT_ACTIVE_LOW = 2 /**< @brief Idle is logic level 1. */
|
||||
PWM_OUTPUT_DISABLED = 0, /**< Output not driven, callback only. */
|
||||
PWM_OUTPUT_ACTIVE_HIGH = 1, /**< Idle is logic level 0. */
|
||||
PWM_OUTPUT_ACTIVE_LOW = 2 /**< Idle is logic level 1. */
|
||||
} pwmmode_t;
|
||||
|
||||
/**
|
||||
* @brief PWM notification callback type.
|
||||
*
|
||||
* @param[in] active current channel output state
|
||||
*/
|
||||
typedef void (*pwmcallback_t)(void);
|
||||
|
||||
#include "pwm_lld.h"
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables a PWM channel.
|
||||
* @details Programs (or reprograms) a PWM channel.
|
||||
* @note This function has to be invoked from a lock zone.
|
||||
*
|
||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||
* @param[in] channel PWM channel identifier
|
||||
* @param[in] width PWM pulse width as clock pulses number
|
||||
*/
|
||||
#define pwmEnableChannelI(pwmp, channel, width) \
|
||||
pwm_lld_enable_channel(pwmp, channel, width)
|
||||
|
||||
/**
|
||||
* @brief Disables a PWM channel.
|
||||
* @details The channel is disabled and its output line returned to the
|
||||
* idle state.
|
||||
* @note This function has to be invoked from a lock zone.
|
||||
*
|
||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||
* @param[in] channel PWM channel identifier
|
||||
*/
|
||||
#define pwmDisableChannelI(pwmp, channel) \
|
||||
pwm_lld_disable_channel(pwmp, channel)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
/**
|
||||
* @file STM32/pwm_lld.c
|
||||
* @brief STM32 PWM subsystem low level driver header.
|
||||
*
|
||||
* @addtogroup STM32_PWM
|
||||
* @{
|
||||
*/
|
||||
|
@ -80,23 +81,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 USE_STM32_PWM2 || USE_STM32_PWM3 || USE_STM32_PWM4 || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Common TIM2...TIM4 IRQ handler.
|
||||
|
@ -111,15 +95,15 @@ static void serve_interrupt(PWMDriver *pwmp) {
|
|||
pwmp->pd_tim->SR = ~(TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF |
|
||||
TIM_SR_CC4IF | TIM_SR_UIF);
|
||||
if ((sr & TIM_SR_CC1IF) != 0)
|
||||
pwmp->pd_config->pc_channels[0].pcc_callback();
|
||||
pwmp->pd_config->pc_channels[0].pcc_callback(pwmp);
|
||||
if ((sr & TIM_SR_CC2IF) != 0)
|
||||
pwmp->pd_config->pc_channels[1].pcc_callback();
|
||||
pwmp->pd_config->pc_channels[1].pcc_callback(pwmp);
|
||||
if ((sr & TIM_SR_CC3IF) != 0)
|
||||
pwmp->pd_config->pc_channels[2].pcc_callback();
|
||||
pwmp->pd_config->pc_channels[2].pcc_callback(pwmp);
|
||||
if ((sr & TIM_SR_CC4IF) != 0)
|
||||
pwmp->pd_config->pc_channels[3].pcc_callback();
|
||||
pwmp->pd_config->pc_channels[3].pcc_callback(pwmp);
|
||||
if ((sr & TIM_SR_UIF) != 0)
|
||||
pwmp->pd_config->pc_callback();
|
||||
pwmp->pd_config->pc_callback(pwmp);
|
||||
}
|
||||
#endif /* USE_STM32_PWM2 || USE_STM32_PWM3 || USE_STM32_PWM4 */
|
||||
|
||||
|
@ -139,7 +123,7 @@ CH_IRQ_HANDLER(VectorA4) {
|
|||
CH_IRQ_PROLOGUE();
|
||||
|
||||
TIM1->SR = ~TIM_SR_UIF;
|
||||
PWMD1.pd_config->pc_callback();
|
||||
PWMD1.pd_config->pc_callback(&PWMD1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
@ -158,13 +142,13 @@ CH_IRQ_HANDLER(VectorAC) {
|
|||
sr = TIM1->SR & TIM1->DIER;
|
||||
TIM1->SR = ~(TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF | TIM_SR_CC4IF);
|
||||
if ((sr & TIM_SR_CC1IF) != 0)
|
||||
PWMD1.pd_config->pc_channels[0].pcc_callback();
|
||||
PWMD1.pd_config->pc_channels[0].pcc_callback(&PWMD1);
|
||||
if ((sr & TIM_SR_CC2IF) != 0)
|
||||
PWMD1.pd_config->pc_channels[1].pcc_callback();
|
||||
PWMD1.pd_config->pc_channels[1].pcc_callback(&PWMD1);
|
||||
if ((sr & TIM_SR_CC3IF) != 0)
|
||||
PWMD1.pd_config->pc_channels[2].pcc_callback();
|
||||
PWMD1.pd_config->pc_channels[2].pcc_callback(&PWMD1);
|
||||
if ((sr & TIM_SR_CC4IF) != 0)
|
||||
PWMD1.pd_config->pc_channels[3].pcc_callback();
|
||||
PWMD1.pd_config->pc_channels[3].pcc_callback(&PWMD1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
@ -274,48 +258,66 @@ 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 USE_STM32_PWM1
|
||||
if (&PWMD1 == pwmp) {
|
||||
NVICEnableVector(TIM1_UP_IRQn,
|
||||
CORTEX_PRIORITY_MASK(STM32_PWM1_IRQ_PRIORITY));
|
||||
NVICEnableVector(TIM1_CC_IRQn,
|
||||
CORTEX_PRIORITY_MASK(STM32_PWM1_IRQ_PRIORITY));
|
||||
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
|
||||
RCC->APB2RSTR = RCC_APB2RSTR_TIM1RST;
|
||||
RCC->APB2RSTR = 0;
|
||||
NVICEnableVector(TIM1_UP_IRQn,
|
||||
CORTEX_PRIORITY_MASK(STM32_PWM_TIM1_IRQ_PRIORITY));
|
||||
NVICEnableVector(TIM1_CC_IRQn,
|
||||
CORTEX_PRIORITY_MASK(STM32_PWM_TIM1_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
#if USE_STM32_PWM2
|
||||
if (&PWMD2 == pwmp) {
|
||||
NVICEnableVector(TIM2_IRQn,
|
||||
CORTEX_PRIORITY_MASK(STM32_PWM2_IRQ_PRIORITY));
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
|
||||
RCC->APB1RSTR = RCC_APB1RSTR_TIM2RST;
|
||||
RCC->APB1RSTR = 0;
|
||||
NVICEnableVector(TIM2_IRQn,
|
||||
CORTEX_PRIORITY_MASK(STM32_PWM_TIM2_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
#if USE_STM32_PWM3
|
||||
if (&PWMD3 == pwmp) {
|
||||
NVICEnableVector(TIM3_IRQn,
|
||||
CORTEX_PRIORITY_MASK(STM32_PWM3_IRQ_PRIORITY));
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
|
||||
RCC->APB1RSTR = RCC_APB1RSTR_TIM3RST;
|
||||
RCC->APB1RSTR = 0;
|
||||
NVICEnableVector(TIM3_IRQn,
|
||||
CORTEX_PRIORITY_MASK(STM32_PWM_TIM3_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
#if USE_STM32_PWM4
|
||||
if (&PWMD4 == pwmp) {
|
||||
NVICEnableVector(TIM4_IRQn,
|
||||
CORTEX_PRIORITY_MASK(STM32_PWM4_IRQ_PRIORITY));
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
|
||||
RCC->APB1RSTR = RCC_APB1RSTR_TIM4RST;
|
||||
RCC->APB1RSTR = 0;
|
||||
NVICEnableVector(TIM4_IRQn,
|
||||
CORTEX_PRIORITY_MASK(STM32_PWM_TIM4_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* Reset channels.*/
|
||||
stop_channels(pwmp);
|
||||
|
||||
/* Configuration or reconfiguration.*/
|
||||
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. */
|
||||
pwmp->pd_tim->CNT = 0;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
pwmp->pd_tim->ARR = pwmp->pd_config->pc_arr;
|
||||
/* Output enables and polarities setup.*/
|
||||
ccer = 0;
|
||||
|
@ -356,8 +358,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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -368,10 +370,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_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 USE_STM32_PWM1
|
||||
if (&PWMD1 == pwmp) {
|
||||
|
@ -405,72 +415,22 @@ void pwm_lld_stop(PWMDriver *pwmp) {
|
|||
* @brief Enables a PWM channel.
|
||||
*
|
||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||
* @param[in] channel PWM channel identifier
|
||||
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
||||
* @param[in] width PWM pulse width as clock pulses number
|
||||
*/
|
||||
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;
|
||||
}
|
||||
*(&pwmp->pd_tim->CCR1 + (channel * 2)) = width; /* New duty cycle. */
|
||||
if ((pwmp->pd_enabled_channels & (1 << channel)) == 0) {
|
||||
/*
|
||||
* The channel is not enabled yet.
|
||||
*/
|
||||
/* 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[channel].pcc_callback) {
|
||||
pwmp->pd_tim->SR = ~(2 << channel);
|
||||
pwmp->pd_tim->DIER |= (2 << channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -481,33 +441,13 @@ void pwm_lld_enable_channel(PWMDriver *pwmp,
|
|||
* idle state.
|
||||
*
|
||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||
* @param[in] channel PWM channel identifier
|
||||
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
||||
*/
|
||||
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 /* CH_HAL_USE_PWM */
|
||||
|
|
|
@ -15,26 +15,20 @@
|
|||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file STM32/pwm_lld.h
|
||||
* @brief STM32 PWM subsystem low level driver header.
|
||||
* @addtogroup STM32_PWM
|
||||
*
|
||||
* @addtogroup PWM
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _PWM_LLD_H_
|
||||
#define _PWM_LLD_H_
|
||||
|
||||
#if CH_HAL_USE_PWM || defined(__DOXYGEN__)
|
||||
#if HAL_USE_PWM || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
|
@ -54,8 +48,8 @@
|
|||
* @details If set to @p TRUE the support for PWM1 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(USE_STM32_PWM1) || defined(__DOXYGEN__)
|
||||
#define USE_STM32_PWM1 TRUE
|
||||
#if !defined(STM32_PWM_USE_TIM1) || defined(__DOXYGEN__)
|
||||
#define STM32_PWM_USE_TIM1 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -63,8 +57,8 @@
|
|||
* @details If set to @p TRUE the support for PWM2 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(USE_STM32_PWM2) || defined(__DOXYGEN__)
|
||||
#define USE_STM32_PWM2 TRUE
|
||||
#if !defined(STM32_PWM_USE_TIM2) || defined(__DOXYGEN__)
|
||||
#define STM32_PWM_USE_TIM2 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -72,8 +66,8 @@
|
|||
* @details If set to @p TRUE the support for PWM3 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(USE_STM32_PWM3) || defined(__DOXYGEN__)
|
||||
#define USE_STM32_PWM3 TRUE
|
||||
#if !defined(STM32_PWM_USE_TIM3) || defined(__DOXYGEN__)
|
||||
#define STM32_PWM_USE_TIM3 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -81,44 +75,82 @@
|
|||
* @details If set to @p TRUE the support for PWM4 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(USE_STM32_PWM4) || defined(__DOXYGEN__)
|
||||
#define USE_STM32_PWM4 TRUE
|
||||
#if !defined(STM32_PWM_USE_TIM4) || defined(__DOXYGEN__)
|
||||
#define STM32_PWM_USE_TIM4 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PWM5 driver enable switch.
|
||||
* @details If set to @p TRUE the support for PWM5 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(STM32_PWM_USE_TIM5) || defined(__DOXYGEN__)
|
||||
#define STM32_PWM_USE_TIM5 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PWM1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(STM32_PWM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define STM32_PWM1_IRQ_PRIORITY 7
|
||||
#if !defined(STM32_PWM_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define STM32_PWM_TIM1_IRQ_PRIORITY 7
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PWM2 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(STM32_PWM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define STM32_PWM2_IRQ_PRIORITY 7
|
||||
#if !defined(STM32_PWM_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define STM32_PWM_TIM2_IRQ_PRIORITY 7
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PWM3 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(STM32_PWM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define STM32_PWM3_IRQ_PRIORITY 7
|
||||
#if !defined(STM32_PWM_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define STM32_PWM_TIM3_IRQ_PRIORITY 7
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PWM4 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(STM32_PWM4_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define STM32_PWM4_IRQ_PRIORITY 7
|
||||
#if !defined(STM32_PWM_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define STM32_PWM_TIM4_IRQ_PRIORITY 7
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PWM5 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(STM32_PWM_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define STM32_PWM_TIM5_IRQ_PRIORITY 7
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Configuration checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if USE_STM32_PWM4 && defined(STM32F10X_LD)
|
||||
#error "TIM4 not present in low density STM32 devices"
|
||||
#if STM32_PWM_USE_TIM1 && !STM32_HAS_TIM1
|
||||
#error "TIM1 not present in the selected device"
|
||||
#endif
|
||||
|
||||
#if STM32_PWM_USE_TIM2 && !STM32_HAS_TIM2
|
||||
#error "TIM2 not present in the selected device"
|
||||
#endif
|
||||
|
||||
#if STM32_PWM_USE_TIM3 && !STM32_HAS_TIM3
|
||||
#error "TIM3 not present in the selected device"
|
||||
#endif
|
||||
|
||||
#if STM32_PWM_USE_TIM4 && !STM32_HAS_TIM4
|
||||
#error "TIM4 not present in the selected device"
|
||||
#endif
|
||||
|
||||
#if STM32_PWM_USE_TIM5 && !STM32_HAS_TIM5
|
||||
#error "TIM5 not present in the selected device"
|
||||
#endif
|
||||
|
||||
#if !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM2 && \
|
||||
!STM32_PWM_USE_TIM3 && !STM32_PWM_USE_TIM4 && \
|
||||
!STM32_PWM_USE_TIM5
|
||||
#error "PWM driver activated but no TIM peripheral assigned"
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
|
@ -135,9 +167,20 @@ typedef uint8_t pwmchannel_t;
|
|||
*/
|
||||
typedef uint16_t pwmcnt_t;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an PWM driver.
|
||||
*/
|
||||
typedef struct PWMDriver PWMDriver;
|
||||
|
||||
/**
|
||||
* @brief PWM notification callback type.
|
||||
*
|
||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||
*/
|
||||
typedef void (*pwmcallback_t)(PWMDriver *pwmp);
|
||||
|
||||
/**
|
||||
* @brief PWM driver channel configuration structure.
|
||||
* @note It could be empty on some architectures.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
|
@ -146,7 +189,7 @@ typedef struct {
|
|||
pwmmode_t pcc_mode;
|
||||
/**
|
||||
* @brief Channel callback pointer.
|
||||
* @details This callback is invoked on the channel compare event. If set to
|
||||
* @note This callback is invoked on the channel compare event. If set to
|
||||
* @p NULL then the callback is disabled.
|
||||
*/
|
||||
pwmcallback_t pcc_callback;
|
||||
|
@ -155,12 +198,11 @@ typedef struct {
|
|||
|
||||
/**
|
||||
* @brief PWM driver configuration structure.
|
||||
* @note It could be empty on some architectures.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Periodic callback pointer.
|
||||
* @details This callback is invoked on PWM counter reset. If set to
|
||||
* @note This callback is invoked on PWM counter reset. If set to
|
||||
* @p NULL then the callback is disabled.
|
||||
*/
|
||||
pwmcallback_t pc_callback;
|
||||
|
@ -187,7 +229,7 @@ typedef struct {
|
|||
/**
|
||||
* @brief Structure representing a PWM driver.
|
||||
*/
|
||||
typedef struct {
|
||||
struct PWMDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
|
@ -196,6 +238,9 @@ typedef struct {
|
|||
* @brief Current driver configuration data.
|
||||
*/
|
||||
const PWMConfig *pd_config;
|
||||
#if defined(PWM_DRIVER_EXT_FIELDS)
|
||||
PWM_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Bit mask of the enabled channels.
|
||||
|
@ -205,32 +250,119 @@ typedef struct {
|
|||
* @brief Pointer to the TIMx registers block.
|
||||
*/
|
||||
TIM_TypeDef *pd_tim;
|
||||
} PWMDriver;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief PWM clock prescaler initialization utility.
|
||||
* @note The real clock value is rounded to the lower valid value, please
|
||||
* make sure that the source clock frequency is a multiple of the
|
||||
* requested PWM clock frequency.
|
||||
* @note The calculated value must fit into an unsigned 16 bits integer.
|
||||
*
|
||||
* @param[in] clksrc clock source frequency, depending on the target timer
|
||||
* cell it can be one of:
|
||||
* - STM32_TIMCLK1
|
||||
* - STM32_TIMCLK2
|
||||
* .
|
||||
* Please refer to the STM32 HAL driver documentation
|
||||
* and/or the STM32 Reference Manual for the right clock
|
||||
* source.
|
||||
* @param[in] pwmclk PWM clock frequency in cycles
|
||||
* @return The value to be stored in the @p pc_psc field of the
|
||||
* @p PWMConfig structure.
|
||||
*/
|
||||
#define PWM_COMPUTE_PSC(clksrc, pwmclk) \
|
||||
((uint16_t)(((clksrc) / (pwmclk)) - 1))
|
||||
|
||||
/**
|
||||
* @brief PWM cycle period initialization utility.
|
||||
* @note The calculated value must fit into an unsigned 16 bits integer.
|
||||
*
|
||||
* @param[in] pwmclk PWM clock frequency in cycles
|
||||
* @param[in] pwmperiod PWM cycle period in nanoseconds
|
||||
* @return The value to be stored in the @p pc_arr field of the
|
||||
* @p PWMConfig structure.
|
||||
*/
|
||||
#define PWM_COMPUTE_ARR(pwmclk, pwmperiod) \
|
||||
((uint16_t)(((pwmclk) / (1000000000 / (pwmperiod))) - 1))
|
||||
|
||||
/**
|
||||
* @brief Converts from fraction to pulse width.
|
||||
* @note Be careful with rounding errors, this is integer math not magic.
|
||||
* You can specify tenths of thousandth but make sure you have the
|
||||
* proper hardware resolution by carefully choosing the clock source
|
||||
* and prescaler settings, see @p PWM_COMPUTE_PSC.
|
||||
*
|
||||
* @param[in] numerator numerator of the fraction
|
||||
* @param[in] denominator percentage as an integer between 0 and numerator
|
||||
* @return The pulse width to be passed to @p pwmEnableChannel().
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
#define PWM_FRACTION_TO_WIDTH(pwmp, numerator, denominator) \
|
||||
((uint16_t)((((uint32_t)(pwmp)->pd_config->pc_arr + 1UL) * \
|
||||
(uint32_t)(denominator)) / (uint32_t)(numerator)))
|
||||
|
||||
/**
|
||||
* @brief Converts from degrees to pulse width.
|
||||
* @note Be careful with rounding errors, this is integer math not magic.
|
||||
* You can specify hundredths of degrees but make sure you have the
|
||||
* proper hardware resolution by carefully choosing the clock source
|
||||
* and prescaler settings, see @p PWM_COMPUTE_PSC.
|
||||
*
|
||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||
* @param[in] degrees degrees as an integer between 0 and 36000
|
||||
* @return The pulse width to be passed to @p pwmEnableChannel().
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
#define PWM_DEGREES_TO_WIDTH(pwmp, degrees) \
|
||||
PWM_FRACTION_TO_WIDTH(pwmp, 36000, degrees)
|
||||
|
||||
/**
|
||||
* @brief Converts from percentage to pulse width.
|
||||
* @note Be careful with rounding errors, this is integer math not magic.
|
||||
* You can specify tenths of thousandth but make sure you have the
|
||||
* proper hardware resolution by carefully choosing the clock source
|
||||
* and prescaler settings, see @p PWM_COMPUTE_PSC.
|
||||
*
|
||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||
* @param[in] percentage percentage as an integer between 0 and 10000
|
||||
* @return The pulse width to be passed to @p pwmEnableChannel().
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
#define PWM_PERCENTAGE_TO_WIDTH(pwmp, percentage) \
|
||||
PWM_FRACTION_TO_WIDTH(pwmp, 10000, percentage)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if defined(USE_STM32_PWM1) && !defined(__DOXYGEN__)
|
||||
#if defined(STM32_PWM_USE_TIM1) && !defined(__DOXYGEN__)
|
||||
extern PWMDriver PWMD1;
|
||||
#endif
|
||||
|
||||
#if defined(USE_STM32_PWM2) && !defined(__DOXYGEN__)
|
||||
#if defined(STM32_PWM_USE_TIM2) && !defined(__DOXYGEN__)
|
||||
extern PWMDriver PWMD2;
|
||||
#endif
|
||||
|
||||
#if defined(USE_STM32_PWM3) && !defined(__DOXYGEN__)
|
||||
#if defined(STM32_PWM_USE_TIM3) && !defined(__DOXYGEN__)
|
||||
extern PWMDriver PWMD3;
|
||||
#endif
|
||||
|
||||
#if defined(USE_STM32_PWM4) && !defined(__DOXYGEN__)
|
||||
#if defined(STM32_PWM_USE_TIM4) && !defined(__DOXYGEN__)
|
||||
extern PWMDriver PWMD4;
|
||||
#endif
|
||||
|
||||
#if defined(STM32_PWM_USE_TIM5) && !defined(__DOXYGEN__)
|
||||
extern PWMDriver PWMD5;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -245,7 +377,7 @@ extern "C" {
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif /* CH_HAL_USE_PWM */
|
||||
#endif /* HAL_USE_PWM */
|
||||
|
||||
#endif /* _PWM_LLD_H_ */
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
/**
|
||||
* @file pwm.c
|
||||
* @brief PWM Driver code.
|
||||
*
|
||||
* @addtogroup PWM
|
||||
* @{
|
||||
*/
|
||||
|
@ -34,7 +35,7 @@
|
|||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if CH_HAL_USE_PWM || defined(__DOXYGEN__)
|
||||
#if HAL_USE_PWM || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
|
@ -69,6 +70,9 @@ void pwmObjectInit(PWMDriver *pwmp) {
|
|||
|
||||
pwmp->pd_state = PWM_STOP;
|
||||
pwmp->pd_config = NULL;
|
||||
#if defined(PWM_DRIVER_EXT_INIT_HOOK)
|
||||
PWM_DRIVER_EXT_INIT_HOOK(pwmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,8 +87,7 @@ void pwmStart(PWMDriver *pwmp, const PWMConfig *config) {
|
|||
|
||||
chSysLock();
|
||||
chDbgAssert((pwmp->pd_state == PWM_STOP) || (pwmp->pd_state == PWM_READY),
|
||||
"pwmStart(), #1",
|
||||
"invalid state");
|
||||
"pwmStart(), #1", "invalid state");
|
||||
pwmp->pd_config = config;
|
||||
pwm_lld_start(pwmp);
|
||||
pwmp->pd_state = PWM_READY;
|
||||
|
@ -102,8 +105,7 @@ void pwmStop(PWMDriver *pwmp) {
|
|||
|
||||
chSysLock();
|
||||
chDbgAssert((pwmp->pd_state == PWM_STOP) || (pwmp->pd_state == PWM_READY),
|
||||
"pwmStop(), #1",
|
||||
"invalid state");
|
||||
"pwmStop(), #1", "invalid state");
|
||||
pwm_lld_stop(pwmp);
|
||||
pwmp->pd_state = PWM_STOP;
|
||||
chSysUnlock();
|
||||
|
@ -111,9 +113,10 @@ void pwmStop(PWMDriver *pwmp) {
|
|||
|
||||
/**
|
||||
* @brief Enables a PWM channel.
|
||||
* @details Programs (or reprograms) a PWM channel.
|
||||
*
|
||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||
* @param[in] channel PWM channel identifier
|
||||
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
||||
* @param[in] width PWM pulse width as clock pulses number
|
||||
*/
|
||||
void pwmEnableChannel(PWMDriver *pwmp,
|
||||
|
@ -125,7 +128,7 @@ void pwmEnableChannel(PWMDriver *pwmp,
|
|||
|
||||
chSysLock();
|
||||
chDbgAssert(pwmp->pd_state == PWM_READY,
|
||||
"pwmEnableChannel(), #1", "invalid state");
|
||||
"pwmEnableChannel(), #1", "not ready");
|
||||
pwm_lld_enable_channel(pwmp, channel, width);
|
||||
chSysUnlock();
|
||||
}
|
||||
|
@ -136,7 +139,7 @@ void pwmEnableChannel(PWMDriver *pwmp,
|
|||
* idle state.
|
||||
*
|
||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||
* @param[in] channel PWM channel identifier
|
||||
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
||||
*/
|
||||
void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel) {
|
||||
|
||||
|
@ -145,7 +148,7 @@ void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel) {
|
|||
|
||||
chSysLock();
|
||||
chDbgAssert(pwmp->pd_state == PWM_READY,
|
||||
"pwmDisableChannel(), #1", "invalid state");
|
||||
"pwmDisableChannel(), #1", "not ready");
|
||||
pwm_lld_disable_channel(pwmp, channel);
|
||||
chSysUnlock();
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if CH_HAL_USE_PWM || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
@ -98,25 +100,11 @@ bool_t pwm_lld_is_enabled(PWMDriver *pwmp, pwmchannel_t channel) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables a callback mode for the specified PWM channel.
|
||||
* @details The callback mode must be set before starting a PWM channel.
|
||||
*
|
||||
* @param[in] pwmp pointer to the @p PWMDriver object
|
||||
* @param[in] channel PWM channel identifier
|
||||
* @param[in] edge output edge mode
|
||||
* @param[in] callback callback function
|
||||
*/
|
||||
void pwm_lld_set_callback(PWMDriver *pwmp, pwmchannel_t channel,
|
||||
pwmedge_t edge, pwmcallback_t callback) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables a PWM channel.
|
||||
*
|
||||
* @param[in] pwmp pointer to the @p PWMDriver object
|
||||
* @param[in] channel PWM channel identifier
|
||||
* @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
|
||||
*/
|
||||
void pwm_lld_enable_channel(PWMDriver *pwmp,
|
||||
|
@ -130,11 +118,13 @@ void pwm_lld_enable_channel(PWMDriver *pwmp,
|
|||
* @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
|
||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
||||
*/
|
||||
void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) {
|
||||
|
||||
}
|
||||
|
||||
#endif /* CH_HAL_USE_PWM */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#ifndef _PWM_LLD_H_
|
||||
#define _PWM_LLD_H_
|
||||
|
||||
#if CH_HAL_USE_PWM || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
@ -69,17 +71,61 @@ typedef uint8_t pwmchannel_t;
|
|||
typedef uint16_t pwmcnt_t;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
* @note It could be empty on some architectures.
|
||||
* @brief Type of a structure representing an PWM driver.
|
||||
*/
|
||||
typedef struct PWMDriver PWMDriver;
|
||||
|
||||
/**
|
||||
* @brief PWM notification callback type.
|
||||
*
|
||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||
*/
|
||||
typedef void (*pwmcallback_t)(PWMDriver *pwmp);
|
||||
|
||||
/**
|
||||
* @brief PWM driver channel configuration structure.
|
||||
* @note Some architectures may not be able to support the channel mode
|
||||
* or the callback, in this case the fields are ignored.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Channel active logic level.
|
||||
*/
|
||||
pwmmode_t pcc_mode;
|
||||
/**
|
||||
* @brief Channel callback pointer.
|
||||
* @note This callback is invoked on the channel compare event. If set to
|
||||
* @p NULL then the callback is disabled.
|
||||
*/
|
||||
pwmcallback_t pcc_callback;
|
||||
/* End of the mandatory fields.*/
|
||||
} PWMChannelConfig;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
* @note Implementations may extend this structure to contain more,
|
||||
* architecture dependent, fields.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Periodic callback pointer.
|
||||
* @note This callback is invoked on PWM counter reset. If set to
|
||||
* @p NULL then the callback is disabled.
|
||||
*/
|
||||
pwmcallback_t pc_callback;
|
||||
/**
|
||||
* @brief Channels configurations.
|
||||
*/
|
||||
PWMChannelConfig pc_channels[PWM_CHANNELS];
|
||||
/* End of the mandatory fields.*/
|
||||
} PWMConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing an PWM driver.
|
||||
* @note Implementations may extend this structure to contain more,
|
||||
* architecture dependent, fields.
|
||||
*/
|
||||
typedef struct {
|
||||
struct PWMDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
|
@ -88,13 +134,63 @@ typedef struct {
|
|||
* @brief Current configuration data.
|
||||
*/
|
||||
const PWMConfig *pd_config;
|
||||
#if defined(PWM_DRIVER_EXT_FIELDS)
|
||||
PWM_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
} PWMDriver;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Converts from fraction to pulse width.
|
||||
* @note Be careful with rounding errors, this is integer math not magic.
|
||||
* You can specify tenths of thousandth but make sure you have the
|
||||
* proper hardware resolution by carefully choosing the clock source
|
||||
* and prescaler settings, see @p PWM_COMPUTE_PSC.
|
||||
*
|
||||
* @param[in] numerator numerator of the fraction
|
||||
* @param[in] denominator percentage as an integer between 0 and numerator
|
||||
* @return The pulse width to be passed to @p pwmEnableChannel().
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
#define PWM_FRACTION_TO_WIDTH(pwmp, numerator, denominator) 0
|
||||
|
||||
/**
|
||||
* @brief Converts from degrees to pulse width.
|
||||
* @note Be careful with rounding errors, this is integer math not magic.
|
||||
* You can specify hundredths of degrees but make sure you have the
|
||||
* proper hardware resolution by carefully choosing the clock source
|
||||
* and prescaler settings, see @p PWM_COMPUTE_PSC.
|
||||
*
|
||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||
* @param[in] degrees degrees as an integer between 0 and 36000
|
||||
* @return The pulse width to be passed to @p pwmEnableChannel().
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
#define PWM_DEGREES_TO_WIDTH(pwmp, degrees) \
|
||||
PWM_FRACTION_TO_WIDTH(pwmp, 36000, degrees)
|
||||
|
||||
/**
|
||||
* @brief Converts from percentage to pulse width.
|
||||
* @note Be careful with rounding errors, this is integer math not magic.
|
||||
* You can specify tenths of thousandth but make sure you have the
|
||||
* proper hardware resolution by carefully choosing the clock source
|
||||
* and prescaler settings, see @p PWM_COMPUTE_PSC.
|
||||
*
|
||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||
* @param[in] percentage percentage as an integer between 0 and 10000
|
||||
* @return The pulse width to be passed to @p pwmEnableChannel().
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
#define PWM_PERCENTAGE_TO_WIDTH(pwmp, percentage) \
|
||||
PWM_FRACTION_TO_WIDTH(pwmp, 10000, percentage)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
@ -106,8 +202,6 @@ 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_set_callback(PWMDriver *pwmp, pwmchannel_t channel,
|
||||
pwmedge_t edge, pwmcallback_t callback);
|
||||
void pwm_lld_enable_channel(PWMDriver *pwmp,
|
||||
pwmchannel_t channel,
|
||||
pwmcnt_t width);
|
||||
|
@ -116,6 +210,8 @@ extern "C" {
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif /* CH_HAL_USE_PWM */
|
||||
|
||||
#endif /* _PWM_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -61,6 +61,12 @@
|
|||
*** 2.0.8 ***
|
||||
- FIX: Fixed failed memory recovery by registry scan, improved the related
|
||||
test case (bug 3116888).
|
||||
- FIX: Fixed PWM channels going to ACTIVE state when the pulse width is
|
||||
set to zero in the STM32 PWM driver (bug 3114481).
|
||||
- FIX: Fixed PWM channels return to IDLE state in STM32 PWM driver (bug
|
||||
3114467).
|
||||
- CHANGE: Bugs 3114467 and 3114481 have been fixed by backporting the 2.1.x
|
||||
PWM driver, there is a difference in the PWM callback parameters.
|
||||
|
||||
*** 2.0.7 ***
|
||||
- FIX: Fixed typo in board name (bug 3113574).
|
||||
|
|
Loading…
Reference in New Issue