Enhanced PWM driver

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7208 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
gdisirio 2014-08-30 13:54:04 +00:00
parent a2ee0679d1
commit e40ae97638
15 changed files with 395 additions and 71 deletions

View File

@ -87,7 +87,7 @@ typedef enum {
typedef struct PWMDriver PWMDriver;
/**
* @brief PWM notification callback type.
* @brief Type of a PWM notification callback.
*
* @param[in] pwmp pointer to a @p PWMDriver object
*/
@ -187,13 +187,15 @@ typedef void (*pwmcallback_t)(PWMDriver *pwmp);
* or immediately (fallback implementation).
*
* @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...channels-1)
* @param[in] width PWM pulse width as clock pulses number
*
* @iclass
*/
#define pwmEnableChannelI(pwmp, channel, width) \
pwm_lld_enable_channel(pwmp, channel, width)
#define pwmEnableChannelI(pwmp, channel, width) do { \
(pwmp)->enabled |= 1 << (channel); \
pwm_lld_enable_channel(pwmp, channel, width); \
} while (0)
/**
* @brief Disables a PWM channel.
@ -205,24 +207,26 @@ typedef void (*pwmcallback_t)(PWMDriver *pwmp);
* or immediately (fallback implementation).
*
* @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...channels-1)
*
* @iclass
*/
#define pwmDisableChannelI(pwmp, channel) \
pwm_lld_disable_channel(pwmp, channel)
#define pwmDisableChannelI(pwmp, channel) do { \
(pwmp)->enabled &= ~(1 << (channel)); \
pwm_lld_disable_channel(pwmp, channel); \
} while (0)
/**
* @brief Returns a PWM channel status.
* @pre The PWM unit must have been activated using @p pwmStart().
*
* @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...channels-1)
*
* @iclass
*/
#define pwmIsChannelEnabledI(pwmp, channel) \
pwm_lld_is_channel_enabled(pwmp, channel)
((bool)((pwmp)->enabled & (1 << (channel))))
/** @} */
/*===========================================================================*/
@ -241,6 +245,10 @@ extern "C" {
pwmchannel_t channel,
pwmcnt_t width);
void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel);
void pwmEnablePeriodicNotification(PWMDriver *pwmp);
void pwmDisablePeriodicNotification(PWMDriver *pwmp);
void pwmEnableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel);
void pwmDisableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel);
#ifdef __cplusplus
}
#endif

View File

@ -114,15 +114,19 @@ static void pwm_lld_serve_interrupt(PWMDriver *pwmp) {
sr = pwmp->tim->SR;
sr &= pwmp->tim->DIER & STM32_TIM_DIER_IRQ_MASK;
pwmp->tim->SR = ~sr;
if ((sr & STM32_TIM_SR_CC1IF) != 0)
if (((sr & STM32_TIM_SR_CC1IF) != 0) &&
(pwmp->config->channels[0].callback != NULL))
pwmp->config->channels[0].callback(pwmp);
if ((sr & STM32_TIM_SR_CC2IF) != 0)
if (((sr & STM32_TIM_SR_CC2IF) != 0) &&
(pwmp->config->channels[1].callback != NULL))
pwmp->config->channels[1].callback(pwmp);
if ((sr & STM32_TIM_SR_CC3IF) != 0)
if (((sr & STM32_TIM_SR_CC3IF) != 0) &&
(pwmp->config->channels[2].callback != NULL))
pwmp->config->channels[2].callback(pwmp);
if ((sr & STM32_TIM_SR_CC4IF) != 0)
if (((sr & STM32_TIM_SR_CC4IF) != 0) &&
(pwmp->config->channels[3].callback != NULL))
pwmp->config->channels[3].callback(pwmp);
if ((sr & STM32_TIM_SR_UIF) != 0)
if (((sr & STM32_TIM_SR_UIF) != 0) && (pwmp->config->callback != NULL))
pwmp->config->callback(pwmp);
}
#endif /* STM32_PWM_USE_TIM2 || ... || STM32_PWM_USE_TIM5 */
@ -148,7 +152,8 @@ OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) {
OSAL_IRQ_PROLOGUE();
STM32_TIM1->SR = ~STM32_TIM_SR_UIF;
PWMD1.config->callback(&PWMD1);
if (PWMD1.config->callback != NULL)
PWMD1.config->callback(&PWMD1);
OSAL_IRQ_EPILOGUE();
}
@ -169,15 +174,22 @@ OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) {
OSAL_IRQ_PROLOGUE();
sr = STM32_TIM1->SR & STM32_TIM1->DIER & STM32_TIM_DIER_IRQ_MASK;
sr = STM32_TIM1->SR & STM32_TIM1->DIER & (STM32_TIM_DIER_CC1IE |
STM32_TIM_DIER_CC2IE |
STM32_TIM_DIER_CC3IE |
STM32_TIM_DIER_CC4IE);
STM32_TIM1->SR = ~sr;
if ((sr & STM32_TIM_SR_CC1IF) != 0)
if (((sr & STM32_TIM_SR_CC1IF) != 0) &&
(PWMD1.config->channels[0].callback != NULL))
PWMD1.config->channels[0].callback(&PWMD1);
if ((sr & STM32_TIM_SR_CC2IF) != 0)
if (((sr & STM32_TIM_SR_CC2IF) != 0) &&
(PWMD1.config->channels[1].callback != NULL))
PWMD1.config->channels[1].callback(&PWMD1);
if ((sr & STM32_TIM_SR_CC3IF) != 0)
if (((sr & STM32_TIM_SR_CC3IF) != 0) &&
(PWMD1.config->channels[2].callback != NULL))
PWMD1.config->channels[2].callback(&PWMD1);
if ((sr & STM32_TIM_SR_CC4IF) != 0)
if (((sr & STM32_TIM_SR_CC4IF) != 0) &&
(PWMD1.config->channels[3].callback != NULL))
PWMD1.config->channels[3].callback(&PWMD1);
OSAL_IRQ_EPILOGUE();
@ -277,7 +289,8 @@ OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) {
OSAL_IRQ_PROLOGUE();
STM32_TIM8->SR = ~TIM_SR_UIF;
PWMD8.config->callback(&PWMD8);
if (PWMD8.config->callback != NULL)
PWMD8.config->callback(&PWMD8);
OSAL_IRQ_EPILOGUE();
}
@ -298,15 +311,22 @@ OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) {
OSAL_IRQ_PROLOGUE();
sr = STM32_TIM8->SR & STM32_TIM8->DIER & STM32_TIM_DIER_IRQ_MASK;
sr = STM32_TIM8->SR & STM32_TIM8->DIER & (STM32_TIM_DIER_CC1IE |
STM32_TIM_DIER_CC2IE |
STM32_TIM_DIER_CC3IE |
STM32_TIM_DIER_CC4IE);
STM32_TIM8->SR = ~sr;
if ((sr & STM32_TIM_SR_CC1IF) != 0)
if (((sr & STM32_TIM_SR_CC1IF) != 0) &&
(PWMD8.config->channels[0].callback != NULL))
PWMD8.config->channels[0].callback(&PWMD8);
if ((sr & STM32_TIM_SR_CC2IF) != 0)
if (((sr & STM32_TIM_SR_CC2IF) != 0) &&
(PWMD8.config->channels[1].callback != NULL))
PWMD8.config->channels[1].callback(&PWMD8);
if ((sr & STM32_TIM_SR_CC3IF) != 0)
if (((sr & STM32_TIM_SR_CC3IF) != 0) &&
(PWMD8.config->channels[2].callback != NULL))
PWMD8.config->channels[2].callback(&PWMD8);
if ((sr & STM32_TIM_SR_CC4IF) != 0)
if (((sr & STM32_TIM_SR_CC4IF) != 0) &&
(PWMD8.config->channels[3].callback != NULL))
PWMD8.config->channels[3].callback(&PWMD8);
OSAL_IRQ_EPILOGUE();
@ -346,42 +366,49 @@ void pwm_lld_init(void) {
#if STM32_PWM_USE_TIM1
/* Driver initialization.*/
pwmObjectInit(&PWMD1);
PWMD1.channels = STM32_TIM1_CHANNELS;
PWMD1.tim = STM32_TIM1;
#endif
#if STM32_PWM_USE_TIM2
/* Driver initialization.*/
pwmObjectInit(&PWMD2);
PWMD2.channels = STM32_TIM2_CHANNELS;
PWMD2.tim = STM32_TIM2;
#endif
#if STM32_PWM_USE_TIM3
/* Driver initialization.*/
pwmObjectInit(&PWMD3);
PWMD3.channels = STM32_TIM3_CHANNELS;
PWMD3.tim = STM32_TIM3;
#endif
#if STM32_PWM_USE_TIM4
/* Driver initialization.*/
pwmObjectInit(&PWMD4);
PWMD4.channels = STM32_TIM4_CHANNELS;
PWMD4.tim = STM32_TIM4;
#endif
#if STM32_PWM_USE_TIM5
/* Driver initialization.*/
pwmObjectInit(&PWMD5);
PWMD5.channels = STM32_TIM5_CHANNELS;
PWMD5.tim = STM32_TIM5;
#endif
#if STM32_PWM_USE_TIM8
/* Driver initialization.*/
pwmObjectInit(&PWMD8);
PWMD8.channels = STM32_TIM8_CHANNELS;
PWMD8.tim = STM32_TIM8;
#endif
#if STM32_PWM_USE_TIM9
/* Driver initialization.*/
pwmObjectInit(&PWMD9);
PWMD9.channels = STM32_TIM9_CHANNELS;
PWMD9.tim = STM32_TIM9;
#endif
}
@ -475,6 +502,10 @@ void pwm_lld_start(PWMDriver *pwmp) {
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.*/
@ -486,6 +517,12 @@ void pwm_lld_start(PWMDriver *pwmp) {
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. */
}
@ -571,7 +608,6 @@ void pwm_lld_start(PWMDriver *pwmp) {
pwmp->tim->CCER = ccer;
pwmp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */
pwmp->tim->DIER |= pwmp->config->callback == NULL ? 0 : STM32_TIM_DIER_UIE;
pwmp->tim->SR = 0; /* Clear pending IRQs. */
#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8
#if STM32_PWM_USE_ADVANCED
@ -655,9 +691,10 @@ void pwm_lld_stop(PWMDriver *pwmp) {
* @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...PWM_CHANNELS-1)
* @param[in] channel PWM channel identifier (0...channels-1)
* @param[in] width PWM pulse width as clock pulses number
*
* @notapi
@ -666,36 +703,121 @@ 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);
}
}
/* 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.
* @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...PWM_CHANNELS-1)
* @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
}
/**
* @brief Enables the periodic activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @note If the notification is already enabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
*
* @notapi
*/
void pwm_lld_enable_periodic_notification(PWMDriver *pwmp) {
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 & STM32_TIM_DIER_UIE) == 0) {
pwmp->tim->DIER = dier | STM32_TIM_DIER_UIE;
pwmp->tim->SR &= STM32_TIM_SR_UIF;
}
}
/**
* @brief Disables the periodic activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @note If the notification is already disabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
*
* @notapi
*/
void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) {
pwmp->tim->DIER &= ~STM32_TIM_DIER_UIE;
}
/**
* @brief Enables a channel de-activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @pre The channel must have been activated using @p pwmEnableChannel().
* @note If the notification is already enabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] channel PWM channel identifier (0...channels-1)
*
* @notapi
*/
void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel) {
uint32_t dier = pwmp->tim->DIER;
#if STM32_TIM_MAX_CHANNELS > 4
/* Channels 4 and 5 do not support callbacks.*/
osalDbgAssert(channel < 4, "callback not supported");
#endif
/* 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 channel de-activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @pre The channel must have been activated using @p pwmEnableChannel().
* @note If the notification is already disabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] channel PWM channel identifier (0...channels-1)
*
* @notapi
*/
void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel) {
pwmp->tim->DIER &= ~(2 << channel);
}
#endif /* HAL_USE_PWM */

View File

@ -36,8 +36,12 @@
/**
* @brief Number of PWM channels per PWM driver.
*/
#define PWM_CHANNELS 4
#define PWM_CHANNELS STM32_TIM_MAX_CHANNELS
/**
* @name STM32-specific PWM complementary output mode macros
* @{
*/
/**
* @brief Complementary output modes mask.
* @note This is an STM32-specific setting.
@ -67,6 +71,7 @@
* timers TIM1 and TIM8.
*/
#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW 0x20
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
@ -283,22 +288,27 @@
/*===========================================================================*/
/**
* @brief PWM mode type.
* @brief Type of a PWM mode.
*/
typedef uint32_t pwmmode_t;
/**
* @brief PWM channel type.
* @brief Type of a PWM channel.
*/
typedef uint8_t pwmchannel_t;
/**
* @brief PWM counter type.
* @brief Type of a channels mask.
*/
typedef uint32_t pwmchnmsk_t;
/**
* @brief Type of a PWM counter.
*/
typedef uint16_t pwmcnt_t;
/**
* @brief PWM driver channel configuration structure.
* @brief Type of a PWM driver channel configuration structure.
*/
typedef struct {
/**
@ -315,7 +325,7 @@ typedef struct {
} PWMChannelConfig;
/**
* @brief PWM driver configuration structure.
* @brief Type of a PWM driver configuration structure.
*/
typedef struct {
/**
@ -377,6 +387,14 @@ struct PWMDriver {
* @brief Current PWM period in ticks.
*/
pwmcnt_t period;
/**
* @brief Mask of the enabled channels.
*/
pwmchnmsk_t enabled;
/**
* @brief Number of channels in this instance.
*/
pwmchannel_t channels;
#if defined(PWM_DRIVER_EXT_FIELDS)
PWM_DRIVER_EXT_FIELDS
#endif
@ -414,19 +432,6 @@ struct PWMDriver {
#define pwm_lld_change_period(pwmp, period) \
((pwmp)->tim->ARR = (uint16_t)((period) - 1))
/**
* @brief Returns a PWM channel status.
* @pre The PWM unit must have been activated using @p pwmStart().
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
*
* @notapi
*/
#define pwm_lld_is_channel_enabled(pwmp, channel) \
(((pwmp)->tim->CCR[channel] != 0) || \
(((pwmp)->tim->DIER & (2 << channel)) != 0))
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
@ -469,6 +474,12 @@ extern "C" {
pwmchannel_t channel,
pwmcnt_t width);
void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel);
void pwm_lld_enable_periodic_notification(PWMDriver *pwmp);
void pwm_lld_disable_periodic_notification(PWMDriver *pwmp);
void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel);
void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel);
#ifdef __cplusplus
}
#endif

View File

@ -431,8 +431,7 @@ typedef struct {
volatile uint32_t DMAR;
volatile uint32_t OR;
volatile uint32_t CCMR3;
volatile uint32_t CCR5;
volatile uint32_t CCR6;
volatile uint32_t CCXR[2];
} stm32_tim_t;
/*===========================================================================*/

View File

@ -106,6 +106,8 @@
#define STM32_HAS_SPI6 FALSE
/* TIM attributes.*/
#define STM32_TIM_MAX_CHANNELS 4
#define STM32_HAS_TIM1 TRUE
#define STM32_TIM1_IS_32BITS FALSE
#define STM32_TIM1_CHANNELS 4
@ -236,6 +238,8 @@
#define STM32_HAS_SPI6 FALSE
/* TIM attributes.*/
#define STM32_TIM_MAX_CHANNELS 4
#define STM32_HAS_TIM1 TRUE
#define STM32_TIM1_IS_32BITS FALSE
#define STM32_TIM1_CHANNELS 4
@ -363,6 +367,8 @@
#define STM32_HAS_SPI6 FALSE
/* TIM attributes.*/
#define STM32_TIM_MAX_CHANNELS 4
#define STM32_HAS_TIM1 TRUE
#define STM32_TIM1_IS_32BITS FALSE
#define STM32_TIM1_CHANNELS 4

View File

@ -193,6 +193,8 @@
#endif /* !(defined(STM32F427_437xx) || defined(STM32F429_439xx)) */
/* TIM attributes.*/
#define STM32_TIM_MAX_CHANNELS 4
#define STM32_HAS_TIM1 TRUE
#define STM32_TIM1_IS_32BITS FALSE
#define STM32_TIM1_CHANNELS 4

View File

@ -73,6 +73,8 @@ void pwmObjectInit(PWMDriver *pwmp) {
pwmp->state = PWM_STOP;
pwmp->config = NULL;
pwmp->enabled = 0;
pwmp->channels = 0;
#if defined(PWM_DRIVER_EXT_INIT_HOOK)
PWM_DRIVER_EXT_INIT_HOOK(pwmp);
#endif
@ -117,7 +119,8 @@ void pwmStop(PWMDriver *pwmp) {
osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY),
"invalid state");
pwm_lld_stop(pwmp);
pwmp->state = PWM_STOP;
pwmp->enabled = 0;
pwmp->state = PWM_STOP;
osalSysUnlock();
}
@ -155,7 +158,7 @@ void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period) {
* or immediately (fallback implementation).
*
* @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...channels-1)
* @param[in] width PWM pulse width as clock pulses number
*
* @api
@ -164,16 +167,19 @@ void pwmEnableChannel(PWMDriver *pwmp,
pwmchannel_t channel,
pwmcnt_t width) {
osalDbgCheck((pwmp != NULL) && (channel < PWM_CHANNELS));
osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
osalSysLock();
osalDbgAssert(pwmp->state == PWM_READY, "not ready");
pwm_lld_enable_channel(pwmp, channel, width);
pwmEnableChannelI(pwmp, channel, width);
osalSysUnlock();
}
/**
* @brief Disables a PWM channel.
* @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.
@ -182,17 +188,122 @@ void pwmEnableChannel(PWMDriver *pwmp,
* or immediately (fallback implementation).
*
* @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...channels-1)
*
* @api
*/
void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel) {
osalDbgCheck((pwmp != NULL) && (channel < PWM_CHANNELS));
osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
osalSysLock();
osalDbgAssert(pwmp->state == PWM_READY, "not ready");
pwm_lld_disable_channel(pwmp, channel);
pwmDisableChannelI(pwmp, channel);
osalSysUnlock();
}
/**
* @brief Enables the periodic activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @note If the notification is already enabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
*
* @api
*/
void pwmEnablePeriodicNotification(PWMDriver *pwmp) {
osalDbgCheck(pwmp != NULL);
osalSysLock();
osalDbgAssert(pwmp->state == PWM_READY, "not ready");
osalDbgAssert(pwmp->config->callback != NULL, "undefined periodic callback");
pwm_lld_enable_periodic_notification(pwmp);
osalSysUnlock();
}
/**
* @brief Disables the periodic activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @note If the notification is already disabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
*
* @api
*/
void pwmDisablePeriodicNotification(PWMDriver *pwmp) {
osalDbgCheck(pwmp != NULL);
osalSysLock();
osalDbgAssert(pwmp->state == PWM_READY, "not ready");
osalDbgAssert(pwmp->config->callback != NULL, "undefined periodic callback");
pwm_lld_disable_periodic_notification(pwmp);
osalSysUnlock();
}
/**
* @brief Enables a channel de-activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @pre The channel must have been activated using @p pwmEnableChannel().
* @note If the notification is already enabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] channel PWM channel identifier (0...channels-1)
*
* @api
*/
void pwmEnableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel) {
osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
osalSysLock();
osalDbgAssert(pwmp->state == PWM_READY, "not ready");
osalDbgAssert((pwmp->enabled & (1 << channel)) != 0,
"channel not enabled");
osalDbgAssert(pwmp->config->channels[channel].callback != NULL,
"undefined channel callback");
pwm_lld_enable_channel_notification(pwmp, channel);
osalSysUnlock();
}
/**
* @brief Disables a channel de-activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @pre The channel must have been activated using @p pwmEnableChannel().
* @note If the notification is already disabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] channel PWM channel identifier (0...channels-1)
*
* @api
*/
void pwmDisableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel) {
osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
osalSysLock();
osalDbgAssert(pwmp->state == PWM_READY, "not ready");
osalDbgAssert((pwmp->enabled & (1 << channel)) != 0,
"channel not enabled");
osalDbgAssert(pwmp->config->channels[channel].callback != NULL,
"undefined channel callback");
pwm_lld_disable_channel_notification(pwmp, channel);
osalSysUnlock();
}

View File

@ -94,6 +94,7 @@ int main(void) {
* The two pins have to be externally connected together.
*/
pwmStart(&PWMD1, &pwmcfg);
pwmEnablePeriodicNotification(&PWMD1);
palSetPadMode(GPIOA, 8, PAL_MODE_ALTERNATE(2));
icuStart(&ICUD3, &icucfg);
palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(1));
@ -104,6 +105,7 @@ int main(void) {
* Starts the PWM channel 0 using 75% duty cycle.
*/
pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 7500));
pwmEnableChannelNotification(&PWMD1, 0);
chThdSleepMilliseconds(5000);
/*

View File

@ -92,6 +92,7 @@ int main(void) {
* Initializes the PWM driver 1 and ICU driver 4.
*/
pwmStart(&PWMD1, &pwmcfg);
pwmEnablePeriodicNotification(&PWMD1);
palSetPadMode(IOPORT1, 8, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
icuStart(&ICUD4, &icucfg);
icuEnable(&ICUD4);
@ -101,6 +102,7 @@ int main(void) {
* Starts the PWM channel 0 using 75% duty cycle.
*/
pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 7500));
pwmEnableChannelNotification(&PWMD1, 0);
chThdSleepMilliseconds(5000);
/*

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.cdt.debug.gdbjtag.launchConfigurationType">
<stringAttribute key="bad_container_name" value="\STM32F30x-PWM-ICU\debug"/>
<intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.delay" value="1"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.doHalt" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.doReset" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageFileName" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageOffset" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.initCommands" value="set remotetimeout 20&#13;&#10;monitor reset init&#13;&#10;monitor sleep 50&#13;&#10;"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.ipAddress" value="localhost"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.jtagDevice" value="Generic TCP/IP"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadImage" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadSymbols" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.pcRegister" value=""/>
<intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.portNumber" value="3333"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.runCommands" value=""/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setPcRegister" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setResume" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setStopAt" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.stopAt" value="main"/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsFileName" value=""/>
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsOffset" value=""/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForImage" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForSymbols" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForImage" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForSymbols" value="true"/>
<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useRemoteTarget" value="true"/>
<stringAttribute key="org.eclipse.cdt.debug.mi.core.DEBUG_NAME" value="arm-none-eabi-gdb"/>
<stringAttribute key="org.eclipse.cdt.debug.mi.core.commandFactory" value="Standard"/>
<stringAttribute key="org.eclipse.cdt.debug.mi.core.protocol" value="mi"/>
<booleanAttribute key="org.eclipse.cdt.debug.mi.core.verboseMode" value="false"/>
<stringAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_NAME" value="arm-none-eabi-gdb"/>
<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>
<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.FORMAT" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&lt;contentList/&gt;"/>
<stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;globalVariableList/&gt;&#13;&#10;"/>
<stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;memoryBlockExpressionList/&gt;&#13;&#10;"/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="./build/ch.elf"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="STM32F30x-PWM-ICU"/>
<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="true"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="0.1093754934"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/STM32F30x-PWM-ICU"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
</listAttribute>
</launchConfiguration>

View File

@ -89,6 +89,7 @@ int main(void) {
* The two pins have to be externally connected together.
*/
pwmStart(&PWMD4, &pwmcfg);
pwmEnablePeriodicNotification(&PWMD4);
palSetPadMode(GPIOD, 12, PAL_MODE_ALTERNATE(2));
icuStart(&ICUD3, &icucfg);
palSetPadMode(GPIOC, 6, PAL_MODE_ALTERNATE(2));
@ -99,6 +100,7 @@ int main(void) {
* Starts the PWM channel 0 using 75% duty cycle.
*/
pwmEnableChannel(&PWMD4, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD4, 7500));
pwmEnableChannelNotification(&PWMD4, 0);
chThdSleepMilliseconds(5000);
/*

View File

@ -89,6 +89,7 @@ int main(void) {
* The two pins have to be externally connected together.
*/
pwmStart(&PWMD5, &pwmcfg);
pwmEnablePeriodicNotification(&PWMD5);
palSetPadMode(GPIOC, 0, PAL_MODE_ALTERNATE(2));
icuStart(&ICUD3, &icucfg);
palSetPadMode(GPIOC, 6, PAL_MODE_ALTERNATE(2));
@ -99,6 +100,7 @@ int main(void) {
* Starts the PWM channel 0 using 75% duty cycle.
*/
pwmEnableChannel(&PWMD5, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD5, 7500));
pwmEnableChannelNotification(&PWMD5, 0);
chThdSleepMilliseconds(5000);
/*

View File

@ -89,6 +89,7 @@ int main(void) {
* The two pins have to be externally connected together.
*/
pwmStart(&PWMD1, &pwmcfg);
pwmEnablePeriodicNotification(&PWMD1);
palSetPadMode(GPIOA, 8, PAL_MODE_ALTERNATE(1));
icuStart(&ICUD3, &icucfg);
palSetPadMode(GPIOC, 6, PAL_MODE_ALTERNATE(2));
@ -99,6 +100,7 @@ int main(void) {
* Starts the PWM channel 0 using 75% duty cycle.
*/
pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 7500));
pwmEnableChannelNotification(&PWMD1, 0);
chThdSleepMilliseconds(5000);
/*

View File

@ -48,4 +48,5 @@
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope"/>
</cproject>

View File

@ -89,6 +89,7 @@ int main(void) {
* The two pins have to be externally connected together.
*/
pwmStart(&PWMD2, &pwmcfg);
pwmEnablePeriodicNotification(&PWMD2);
palSetPadMode(GPIOA, 15, PAL_MODE_ALTERNATE(1));
icuStart(&ICUD3, &icucfg);
palSetPadMode(GPIOC, 6, PAL_MODE_ALTERNATE(2));
@ -99,6 +100,7 @@ int main(void) {
* Starts the PWM channel 0 using 75% duty cycle.
*/
pwmEnableChannel(&PWMD2, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD2, 7500));
pwmEnableChannelNotification(&PWMD2, 0);
chThdSleepMilliseconds(5000);
/*