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:
parent
a2ee0679d1
commit
e40ae97638
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*===========================================================================*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
127
os/hal/src/pwm.c
127
os/hal/src/pwm.c
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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 monitor reset init monitor sleep 50 "/>
|
||||
<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="<?xml version="1.0" encoding="UTF-8" standalone="no"?><contentList/>"/>
|
||||
<stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <globalVariableList/> "/>
|
||||
<stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <memoryBlockExpressionList/> "/>
|
||||
<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>
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -48,4 +48,5 @@
|
|||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
<storageModule moduleId="refreshScope"/>
|
||||
</cproject>
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue