Improvements to the PWM driver.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2853 35acf78f-673a-0410-8e92-d51de3d6d3f4master
parent
8cdc7bd8f3
commit
a58a524d4c
|
@ -57,13 +57,16 @@ typedef enum {
|
||||||
} pwmstate_t;
|
} pwmstate_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief PWM logic mode.
|
* @brief Type of a structure representing a PWM driver.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef struct PWMDriver PWMDriver;
|
||||||
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. */
|
* @brief PWM notification callback type.
|
||||||
} pwmmode_t;
|
*
|
||||||
|
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||||
|
*/
|
||||||
|
typedef void (*pwmcallback_t)(PWMDriver *pwmp);
|
||||||
|
|
||||||
#include "pwm_lld.h"
|
#include "pwm_lld.h"
|
||||||
|
|
||||||
|
@ -72,12 +75,86 @@ typedef enum {
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enables a PWM channel.
|
* @brief Converts from fraction to pulse width.
|
||||||
* @details Programs (or reprograms) a PWM channel.
|
* @note Be careful with rounding errors, this is integer math not magic.
|
||||||
* @note This function has to be invoked from a lock zone.
|
* 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] pwmp pointer to a @p PWMDriver object
|
||||||
* @param[in] channel PWM channel identifier
|
* @param[in] denominator denominator of the fraction
|
||||||
|
* @param[in] numerator numerator of the fraction
|
||||||
|
* @return The pulse width to be passed to @p pwmEnableChannel().
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
#define PWM_FRACTION_TO_WIDTH(pwmp, denominator, numerator) \
|
||||||
|
((uint16_t)((((uint32_t)(pwmp)->period) * \
|
||||||
|
(uint32_t)(numerator)) / (uint32_t)(denominator)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Changes the period the PWM peripheral.
|
||||||
|
* @details This function changes the period of a PWM unit that has already
|
||||||
|
* been activated using @p pwmStart().
|
||||||
|
* @pre The PWM unit must have been activated using @p pwmStart().
|
||||||
|
* @post The PWM unit period is changed to the new value.
|
||||||
|
* @post Any active channel is disabled by this function and must be
|
||||||
|
* activated explicitly using @p pwmEnableChannel().
|
||||||
|
* @note Depending on the hardware implementation this function has
|
||||||
|
* effect starting on the next cycle (recommended implementation)
|
||||||
|
* or immediately (fallback implementation).
|
||||||
|
*
|
||||||
|
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||||
|
*
|
||||||
|
* @iclass
|
||||||
|
*/
|
||||||
|
#define pwmChangePeriodI(pwmp, period) { \
|
||||||
|
(pwmp)->period = (period); \
|
||||||
|
pwm_lld_change_period(pwmp, period); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enables a PWM channel.
|
||||||
|
* @pre The PWM unit must have been activated using @p pwmStart().
|
||||||
|
* @post The channel is active using the specified configuration.
|
||||||
|
* @note Depending on the hardware implementation this function has
|
||||||
|
* effect starting on the next cycle (recommended implementation)
|
||||||
|
* 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] width PWM pulse width as clock pulses number
|
* @param[in] width PWM pulse width as clock pulses number
|
||||||
*
|
*
|
||||||
* @iclass
|
* @iclass
|
||||||
|
@ -87,12 +164,15 @@ typedef enum {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Disables a PWM channel.
|
* @brief Disables a PWM channel.
|
||||||
* @details The channel is disabled and its output line returned to the
|
* @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.
|
* idle state.
|
||||||
* @note This function has to be invoked from a lock zone.
|
* @note Depending on the hardware implementation this function has
|
||||||
|
* effect starting on the next cycle (recommended implementation)
|
||||||
|
* or immediately (fallback implementation).
|
||||||
*
|
*
|
||||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
* @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)
|
||||||
*
|
*
|
||||||
* @iclass
|
* @iclass
|
||||||
*/
|
*/
|
||||||
|
@ -110,6 +190,7 @@ extern "C" {
|
||||||
void pwmObjectInit(PWMDriver *pwmp);
|
void pwmObjectInit(PWMDriver *pwmp);
|
||||||
void pwmStart(PWMDriver *pwmp, const PWMConfig *config);
|
void pwmStart(PWMDriver *pwmp, const PWMConfig *config);
|
||||||
void pwmStop(PWMDriver *pwmp);
|
void pwmStop(PWMDriver *pwmp);
|
||||||
|
void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period);
|
||||||
void pwmEnableChannel(PWMDriver *pwmp,
|
void pwmEnableChannel(PWMDriver *pwmp,
|
||||||
pwmchannel_t channel,
|
pwmchannel_t channel,
|
||||||
pwmcnt_t width);
|
pwmcnt_t width);
|
||||||
|
|
|
@ -325,6 +325,7 @@ void gpt_lld_stop(GPTDriver *gptp) {
|
||||||
if (gptp->state == GPT_READY) {
|
if (gptp->state == GPT_READY) {
|
||||||
gptp->tim->CR1 = 0; /* Timer disabled. */
|
gptp->tim->CR1 = 0; /* Timer disabled. */
|
||||||
gptp->tim->DIER = 0; /* All IRQs disabled. */
|
gptp->tim->DIER = 0; /* All IRQs disabled. */
|
||||||
|
gptp->tim->SR = 0; /* Clear eventual pending IRQs. */
|
||||||
|
|
||||||
#if STM32_GPT_USE_TIM1
|
#if STM32_GPT_USE_TIM1
|
||||||
if (&GPTD1 == gptp) {
|
if (&GPTD1 == gptp) {
|
||||||
|
|
|
@ -289,12 +289,15 @@ void pwm_lld_init(void) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Configures and activates the PWM peripheral.
|
* @brief Configures and activates the PWM peripheral.
|
||||||
|
* @note Starting a driver that is already in the @p PWM_READY state
|
||||||
|
* disables all the active channels.
|
||||||
*
|
*
|
||||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
void pwm_lld_start(PWMDriver *pwmp) {
|
void pwm_lld_start(PWMDriver *pwmp) {
|
||||||
|
uint32_t clock, psc;
|
||||||
uint16_t ccer;
|
uint16_t ccer;
|
||||||
|
|
||||||
/* Reset channels.*/
|
/* Reset channels.*/
|
||||||
|
@ -311,6 +314,7 @@ void pwm_lld_start(PWMDriver *pwmp) {
|
||||||
CORTEX_PRIORITY_MASK(STM32_PWM_TIM1_IRQ_PRIORITY));
|
CORTEX_PRIORITY_MASK(STM32_PWM_TIM1_IRQ_PRIORITY));
|
||||||
NVICEnableVector(TIM1_CC_IRQn,
|
NVICEnableVector(TIM1_CC_IRQn,
|
||||||
CORTEX_PRIORITY_MASK(STM32_PWM_TIM1_IRQ_PRIORITY));
|
CORTEX_PRIORITY_MASK(STM32_PWM_TIM1_IRQ_PRIORITY));
|
||||||
|
clock = STM32_TIMCLK2;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if STM32_PWM_USE_TIM2
|
#if STM32_PWM_USE_TIM2
|
||||||
|
@ -320,6 +324,7 @@ void pwm_lld_start(PWMDriver *pwmp) {
|
||||||
RCC->APB1RSTR = 0;
|
RCC->APB1RSTR = 0;
|
||||||
NVICEnableVector(TIM2_IRQn,
|
NVICEnableVector(TIM2_IRQn,
|
||||||
CORTEX_PRIORITY_MASK(STM32_PWM_TIM2_IRQ_PRIORITY));
|
CORTEX_PRIORITY_MASK(STM32_PWM_TIM2_IRQ_PRIORITY));
|
||||||
|
clock = STM32_TIMCLK1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if STM32_PWM_USE_TIM3
|
#if STM32_PWM_USE_TIM3
|
||||||
|
@ -329,6 +334,7 @@ void pwm_lld_start(PWMDriver *pwmp) {
|
||||||
RCC->APB1RSTR = 0;
|
RCC->APB1RSTR = 0;
|
||||||
NVICEnableVector(TIM3_IRQn,
|
NVICEnableVector(TIM3_IRQn,
|
||||||
CORTEX_PRIORITY_MASK(STM32_PWM_TIM3_IRQ_PRIORITY));
|
CORTEX_PRIORITY_MASK(STM32_PWM_TIM3_IRQ_PRIORITY));
|
||||||
|
clock = STM32_TIMCLK1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if STM32_PWM_USE_TIM4
|
#if STM32_PWM_USE_TIM4
|
||||||
|
@ -338,6 +344,7 @@ void pwm_lld_start(PWMDriver *pwmp) {
|
||||||
RCC->APB1RSTR = 0;
|
RCC->APB1RSTR = 0;
|
||||||
NVICEnableVector(TIM4_IRQn,
|
NVICEnableVector(TIM4_IRQn,
|
||||||
CORTEX_PRIORITY_MASK(STM32_PWM_TIM4_IRQ_PRIORITY));
|
CORTEX_PRIORITY_MASK(STM32_PWM_TIM4_IRQ_PRIORITY));
|
||||||
|
clock = STM32_TIMCLK1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -348,6 +355,7 @@ void pwm_lld_start(PWMDriver *pwmp) {
|
||||||
RCC->APB1RSTR = 0;
|
RCC->APB1RSTR = 0;
|
||||||
NVICEnableVector(TIM5_IRQn,
|
NVICEnableVector(TIM5_IRQn,
|
||||||
CORTEX_PRIORITY_MASK(STM32_PWM_TIM5_IRQ_PRIORITY));
|
CORTEX_PRIORITY_MASK(STM32_PWM_TIM5_IRQ_PRIORITY));
|
||||||
|
clock = STM32_TIMCLK1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -364,21 +372,26 @@ void pwm_lld_start(PWMDriver *pwmp) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Driver re-configuration scenario, it must be stopped first.*/
|
/* Driver re-configuration scenario, it must be stopped first.*/
|
||||||
/* Really required ?????????? */
|
pwmp->enabled_channels = 0; /* All channels disabled. */
|
||||||
pwmp->tim->CR1 = 0; /* Timer stopped. */
|
pwmp->tim->CR1 = 0; /* Timer disabled. */
|
||||||
pwmp->tim->CR2 = 0; /* Timer stopped. */
|
pwmp->tim->DIER = 0; /* All IRQs disabled. */
|
||||||
pwmp->tim->SMCR = 0; /* Slave mode disabled. */
|
pwmp->tim->SR = 0; /* Clear eventual pending IRQs. */
|
||||||
pwmp->tim->CCR1 = 0; /* Comparator 1 disabled. */
|
pwmp->tim->CCR1 = 0; /* Comparator 1 disabled. */
|
||||||
pwmp->tim->CCR2 = 0; /* Comparator 2 disabled. */
|
pwmp->tim->CCR2 = 0; /* Comparator 2 disabled. */
|
||||||
pwmp->tim->CCR3 = 0; /* Comparator 3 disabled. */
|
pwmp->tim->CCR3 = 0; /* Comparator 3 disabled. */
|
||||||
pwmp->tim->CCR4 = 0; /* Comparator 4 disabled. */
|
pwmp->tim->CCR4 = 0; /* Comparator 4 disabled. */
|
||||||
pwmp->tim->CNT = 0;
|
pwmp->tim->CNT = 0; /* Counter reset to zero. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Timer configuration.*/
|
/* Timer configuration.*/
|
||||||
|
psc = (clock / pwmp->config->frequency) - 1;
|
||||||
|
chDbgAssert((psc <= 0xFFFF) &&
|
||||||
|
((psc + 1) * pwmp->config->frequency) == clock,
|
||||||
|
"pwm_lld_start(), #1", "invalid frequency");
|
||||||
|
pwmp->tim->PSC = (uint16_t)psc;
|
||||||
|
pwmp->tim->ARR = (uint16_t)(pwmp->period - 1);
|
||||||
pwmp->tim->CR2 = pwmp->config->cr2;
|
pwmp->tim->CR2 = pwmp->config->cr2;
|
||||||
pwmp->tim->PSC = pwmp->config->psc;
|
|
||||||
pwmp->tim->ARR = pwmp->config->arr;
|
|
||||||
/* Output enables and polarities setup.*/
|
/* Output enables and polarities setup.*/
|
||||||
ccer = 0;
|
ccer = 0;
|
||||||
switch (pwmp->config->channels[0].mode) {
|
switch (pwmp->config->channels[0].mode) {
|
||||||
|
@ -434,17 +447,9 @@ void pwm_lld_stop(PWMDriver *pwmp) {
|
||||||
/* If in ready state then disables the PWM clock.*/
|
/* If in ready state then disables the PWM clock.*/
|
||||||
if (pwmp->state == PWM_READY) {
|
if (pwmp->state == PWM_READY) {
|
||||||
pwmp->enabled_channels = 0; /* All channels disabled. */
|
pwmp->enabled_channels = 0; /* All channels disabled. */
|
||||||
pwmp->tim->CR1 = 0;
|
pwmp->tim->CR1 = 0; /* Timer disabled. */
|
||||||
pwmp->tim->CR2 = 0;
|
pwmp->tim->DIER = 0; /* All IRQs disabled. */
|
||||||
pwmp->tim->CCER = 0; /* Outputs disabled. */
|
pwmp->tim->SR = 0; /* Clear eventual pending IRQs. */
|
||||||
pwmp->tim->CCR1 = 0; /* Comparator 1 disabled. */
|
|
||||||
pwmp->tim->CCR2 = 0; /* Comparator 2 disabled. */
|
|
||||||
pwmp->tim->CCR3 = 0; /* Comparator 3 disabled. */
|
|
||||||
pwmp->tim->CCR4 = 0; /* Comparator 4 disabled. */
|
|
||||||
pwmp->tim->BDTR = 0;
|
|
||||||
pwmp->tim->DIER = 0;
|
|
||||||
pwmp->tim->SR = 0;
|
|
||||||
pwmp->tim->EGR = TIM_EGR_UG; /* Update event. */
|
|
||||||
|
|
||||||
#if STM32_PWM_USE_TIM1
|
#if STM32_PWM_USE_TIM1
|
||||||
if (&PWMD1 == pwmp) {
|
if (&PWMD1 == pwmp) {
|
||||||
|
@ -480,8 +485,39 @@ void pwm_lld_stop(PWMDriver *pwmp) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Changes the period the PWM peripheral.
|
||||||
|
* @details This function changes the period of a PWM unit that has already
|
||||||
|
* been activated using @p pwmStart().
|
||||||
|
* @pre The PWM unit must have been activated using @p pwmStart().
|
||||||
|
* @post The PWM unit period is changed to the new value.
|
||||||
|
* @post Any active channel is disabled by this function and must be
|
||||||
|
* activated explicitly using @p pwmEnableChannel().
|
||||||
|
* @note The function has effect at the next cycle start.
|
||||||
|
*
|
||||||
|
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
void pwm_lld_change_period(PWMDriver *pwmp, pwmcnt_t period) {
|
||||||
|
|
||||||
|
pwmp->enabled_channels = 0; /* All channels disabled. */
|
||||||
|
pwmp->tim->DIER &= ~(TIM_DIER_CC1IE |
|
||||||
|
TIM_DIER_CC2IE |
|
||||||
|
TIM_DIER_CC3IE |
|
||||||
|
TIM_DIER_CC4IE); /* Channels sources disabled. */
|
||||||
|
pwmp->tim->SR = ~(TIM_SR_CC1IF |
|
||||||
|
TIM_SR_CC1IF |
|
||||||
|
TIM_SR_CC1IF |
|
||||||
|
TIM_SR_CC1IF); /* Clears eventual pending IRQs. */
|
||||||
|
pwmp->tim->ARR = (uint16_t)(period - 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enables a PWM channel.
|
* @brief Enables a PWM channel.
|
||||||
|
* @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.
|
||||||
*
|
*
|
||||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||||
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
||||||
|
@ -508,8 +544,10 @@ void pwm_lld_enable_channel(PWMDriver *pwmp,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Disables a PWM channel.
|
* @brief Disables a PWM channel.
|
||||||
* @details The channel is disabled and its output line returned to the
|
* @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.
|
* idle state.
|
||||||
|
* @note The function has effect at the next cycle start.
|
||||||
*
|
*
|
||||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||||
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
||||||
|
|
|
@ -169,16 +169,13 @@ typedef uint8_t pwmchannel_t;
|
||||||
typedef uint16_t pwmcnt_t;
|
typedef uint16_t pwmcnt_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Type of a structure representing an PWM driver.
|
* @brief PWM logic mode.
|
||||||
*/
|
*/
|
||||||
typedef struct PWMDriver PWMDriver;
|
typedef enum {
|
||||||
|
PWM_OUTPUT_DISABLED = 0, /**< Output not driven, callback only. */
|
||||||
/**
|
PWM_OUTPUT_ACTIVE_HIGH = 1, /**< Idle is logic level 0. */
|
||||||
* @brief PWM notification callback type.
|
PWM_OUTPUT_ACTIVE_LOW = 2 /**< Idle is logic level 1. */
|
||||||
*
|
} pwmmode_t;
|
||||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
|
||||||
*/
|
|
||||||
typedef void (*pwmcallback_t)(PWMDriver *pwmp);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief PWM driver channel configuration structure.
|
* @brief PWM driver channel configuration structure.
|
||||||
|
@ -201,6 +198,18 @@ typedef struct {
|
||||||
* @brief PWM driver configuration structure.
|
* @brief PWM driver configuration structure.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
/**
|
||||||
|
* @brief Timer clock in Hz.
|
||||||
|
* @note The low level can use assertions in order to catch invalid
|
||||||
|
* frequency specifications.
|
||||||
|
*/
|
||||||
|
uint32_t frequency;
|
||||||
|
/**
|
||||||
|
* @brief PWM period in ticks.
|
||||||
|
* @note The low level can use assertions in order to catch invalid
|
||||||
|
* period specifications.
|
||||||
|
*/
|
||||||
|
pwmcnt_t period;
|
||||||
/**
|
/**
|
||||||
* @brief Periodic callback pointer.
|
* @brief Periodic callback pointer.
|
||||||
* @note This callback is invoked on PWM counter reset. If set to
|
* @note This callback is invoked on PWM counter reset. If set to
|
||||||
|
@ -212,14 +221,6 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
PWMChannelConfig channels[PWM_CHANNELS];
|
PWMChannelConfig channels[PWM_CHANNELS];
|
||||||
/* End of the mandatory fields.*/
|
/* End of the mandatory fields.*/
|
||||||
/**
|
|
||||||
* @brief TIM PSC (pre-scaler) register initialization data.
|
|
||||||
*/
|
|
||||||
uint16_t psc;
|
|
||||||
/**
|
|
||||||
* @brief TIM ARR (auto-reload) register initialization data.
|
|
||||||
*/
|
|
||||||
uint16_t arr;
|
|
||||||
/**
|
/**
|
||||||
* @brief TIM CR2 register initialization data.
|
* @brief TIM CR2 register initialization data.
|
||||||
* @note The value of this field should normally be equal to zero.
|
* @note The value of this field should normally be equal to zero.
|
||||||
|
@ -239,6 +240,10 @@ struct PWMDriver {
|
||||||
* @brief Current driver configuration data.
|
* @brief Current driver configuration data.
|
||||||
*/
|
*/
|
||||||
const PWMConfig *config;
|
const PWMConfig *config;
|
||||||
|
/**
|
||||||
|
* @brief Current PWM period in ticks.
|
||||||
|
*/
|
||||||
|
pwmcnt_t period;
|
||||||
#if defined(PWM_DRIVER_EXT_FIELDS)
|
#if defined(PWM_DRIVER_EXT_FIELDS)
|
||||||
PWM_DRIVER_EXT_FIELDS
|
PWM_DRIVER_EXT_FIELDS
|
||||||
#endif
|
#endif
|
||||||
|
@ -257,90 +262,6 @@ struct PWMDriver {
|
||||||
/* Driver macros. */
|
/* 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 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 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] pwmp pointer to a @p PWMDriver object
|
|
||||||
* @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)->config->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. */
|
/* External declarations. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -371,6 +292,7 @@ extern "C" {
|
||||||
void pwm_lld_init(void);
|
void pwm_lld_init(void);
|
||||||
void pwm_lld_start(PWMDriver *pwmp);
|
void pwm_lld_start(PWMDriver *pwmp);
|
||||||
void pwm_lld_stop(PWMDriver *pwmp);
|
void pwm_lld_stop(PWMDriver *pwmp);
|
||||||
|
void pwm_lld_change_period(PWMDriver *pwmp, pwmcnt_t period);
|
||||||
void pwm_lld_enable_channel(PWMDriver *pwmp,
|
void pwm_lld_enable_channel(PWMDriver *pwmp,
|
||||||
pwmchannel_t channel,
|
pwmchannel_t channel,
|
||||||
pwmcnt_t width);
|
pwmcnt_t width);
|
||||||
|
|
|
@ -77,6 +77,8 @@ void pwmObjectInit(PWMDriver *pwmp) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Configures and activates the PWM peripheral.
|
* @brief Configures and activates the PWM peripheral.
|
||||||
|
* @note Starting a driver that is already in the @p PWM_READY state
|
||||||
|
* disables all the active channels.
|
||||||
*
|
*
|
||||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||||
* @param[in] config pointer to a @p PWMConfig object
|
* @param[in] config pointer to a @p PWMConfig object
|
||||||
|
@ -91,6 +93,7 @@ void pwmStart(PWMDriver *pwmp, const PWMConfig *config) {
|
||||||
chDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY),
|
chDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY),
|
||||||
"pwmStart(), #1", "invalid state");
|
"pwmStart(), #1", "invalid state");
|
||||||
pwmp->config = config;
|
pwmp->config = config;
|
||||||
|
pwmp->period = config->period;
|
||||||
pwm_lld_start(pwmp);
|
pwm_lld_start(pwmp);
|
||||||
pwmp->state = PWM_READY;
|
pwmp->state = PWM_READY;
|
||||||
chSysUnlock();
|
chSysUnlock();
|
||||||
|
@ -115,9 +118,41 @@ void pwmStop(PWMDriver *pwmp) {
|
||||||
chSysUnlock();
|
chSysUnlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Changes the period the PWM peripheral.
|
||||||
|
* @details This function changes the period of a PWM unit that has already
|
||||||
|
* been activated using @p pwmStart().
|
||||||
|
* @pre The PWM unit must have been activated using @p pwmStart().
|
||||||
|
* @post The PWM unit period is changed to the new value.
|
||||||
|
* @post Any active channel is disabled by this function and must be
|
||||||
|
* activated explicitly using @p pwmEnableChannel().
|
||||||
|
* @note Depending on the hardware implementation this function has
|
||||||
|
* effect starting on the next cycle (recommended implementation)
|
||||||
|
* or immediately (fallback implementation).
|
||||||
|
*
|
||||||
|
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period) {
|
||||||
|
|
||||||
|
chDbgCheck(pwmp != NULL, "pwmChangePeriod");
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
chDbgAssert(pwmp->state == PWM_READY,
|
||||||
|
"pwmChangePeriod(), #1", "invalid state");
|
||||||
|
pwmp->period = period;
|
||||||
|
pwm_lld_change_period(pwmp, period);
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enables a PWM channel.
|
* @brief Enables a PWM channel.
|
||||||
* @details Programs (or reprograms) a PWM channel.
|
* @pre The PWM unit must have been activated using @p pwmStart().
|
||||||
|
* @post The channel is active using the specified configuration.
|
||||||
|
* @note Depending on the hardware implementation this function has
|
||||||
|
* effect starting on the next cycle (recommended implementation)
|
||||||
|
* or immediately (fallback implementation).
|
||||||
*
|
*
|
||||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||||
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
||||||
|
@ -141,8 +176,12 @@ void pwmEnableChannel(PWMDriver *pwmp,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Disables a PWM channel.
|
* @brief Disables a PWM channel.
|
||||||
* @details The channel is disabled and its output line returned to the
|
* @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.
|
* idle state.
|
||||||
|
* @note Depending on the hardware implementation this function has
|
||||||
|
* effect starting on the next cycle (recommended implementation)
|
||||||
|
* or immediately (fallback implementation).
|
||||||
*
|
*
|
||||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||||
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
||||||
|
|
|
@ -87,23 +87,32 @@ void pwm_lld_stop(PWMDriver *pwmp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Determines whatever the PWM channel is already enabled.
|
* @brief Changes the period the PWM peripheral.
|
||||||
|
* @details This function changes the period of a PWM unit that has already
|
||||||
|
* been activated using @p pwmStart().
|
||||||
|
* @pre The PWM unit must have been activated using @p pwmStart().
|
||||||
|
* @post The PWM unit period is changed to the new value.
|
||||||
|
* @post Any active channel is disabled by this function and must be
|
||||||
|
* activated explicitly using @p pwmEnableChannel().
|
||||||
|
* @note Depending on the hardware implementation this function has
|
||||||
|
* effect starting on the next cycle (recommended implementation)
|
||||||
|
* or immediately (fallback implementation).
|
||||||
*
|
*
|
||||||
* @param[in] pwmp pointer to the @p PWMDriver object
|
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||||
* @param[in] channel PWM channel identifier
|
|
||||||
* @return The PWM channel status.
|
|
||||||
* @retval FALSE the channel is not enabled.
|
|
||||||
* @retval TRUE the channel is enabled.
|
|
||||||
*
|
*
|
||||||
* @notapi
|
* @api
|
||||||
*/
|
*/
|
||||||
bool_t pwm_lld_is_enabled(PWMDriver *pwmp, pwmchannel_t channel) {
|
void pwm_lld_change_period(PWMDriver *pwmp, pwmcnt_t period) {
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enables a PWM channel.
|
* @brief Enables a PWM channel.
|
||||||
|
* @pre The PWM unit must have been activated using @p pwmStart().
|
||||||
|
* @post The channel is active using the specified configuration.
|
||||||
|
* @note Depending on the hardware implementation this function has
|
||||||
|
* effect starting on the next cycle (recommended implementation)
|
||||||
|
* or immediately (fallback implementation).
|
||||||
*
|
*
|
||||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||||
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
||||||
|
@ -119,11 +128,17 @@ void pwm_lld_enable_channel(PWMDriver *pwmp,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Disables a PWM channel.
|
* @brief Disables a PWM channel.
|
||||||
* @details The channel is disabled and its output line returned to the
|
* @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.
|
* idle state.
|
||||||
|
* @note Depending on the hardware implementation this function has
|
||||||
|
* effect starting on the next cycle (recommended implementation)
|
||||||
|
* or immediately (fallback implementation).
|
||||||
*
|
*
|
||||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
* @param[in] pwmp pointer to a @p PWMDriver object
|
||||||
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
* @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1)
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
*/
|
*/
|
||||||
void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) {
|
void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) {
|
||||||
|
|
||||||
|
|
|
@ -65,16 +65,13 @@ typedef uint8_t pwmchannel_t;
|
||||||
typedef uint16_t pwmcnt_t;
|
typedef uint16_t pwmcnt_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Type of a structure representing an PWM driver.
|
* @brief PWM logic mode.
|
||||||
*/
|
*/
|
||||||
typedef struct PWMDriver PWMDriver;
|
typedef enum {
|
||||||
|
PWM_OUTPUT_DISABLED = 0, /**< Output not driven, callback only. */
|
||||||
/**
|
PWM_OUTPUT_ACTIVE_HIGH = 1, /**< Idle is logic level 0. */
|
||||||
* @brief PWM notification callback type.
|
PWM_OUTPUT_ACTIVE_LOW = 2 /**< Idle is logic level 1. */
|
||||||
*
|
} pwmmode_t;
|
||||||
* @param[in] pwmp pointer to a @p PWMDriver object
|
|
||||||
*/
|
|
||||||
typedef void (*pwmcallback_t)(PWMDriver *pwmp);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief PWM driver channel configuration structure.
|
* @brief PWM driver channel configuration structure.
|
||||||
|
@ -101,6 +98,18 @@ typedef struct {
|
||||||
* architecture dependent, fields.
|
* architecture dependent, fields.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
/**
|
||||||
|
* @brief Timer clock in Hz.
|
||||||
|
* @note The low level can use assertions in order to catch invalid
|
||||||
|
* frequency specifications.
|
||||||
|
*/
|
||||||
|
uint32_t frequency;
|
||||||
|
/**
|
||||||
|
* @brief PWM period in ticks.
|
||||||
|
* @note The low level can use assertions in order to catch invalid
|
||||||
|
* period specifications.
|
||||||
|
*/
|
||||||
|
pwmcnt_t period;
|
||||||
/**
|
/**
|
||||||
* @brief Periodic callback pointer.
|
* @brief Periodic callback pointer.
|
||||||
* @note This callback is invoked on PWM counter reset. If set to
|
* @note This callback is invoked on PWM counter reset. If set to
|
||||||
|
@ -128,6 +137,10 @@ struct PWMDriver {
|
||||||
* @brief Current configuration data.
|
* @brief Current configuration data.
|
||||||
*/
|
*/
|
||||||
const PWMConfig *config;
|
const PWMConfig *config;
|
||||||
|
/**
|
||||||
|
* @brief Current PWM period in ticks.
|
||||||
|
*/
|
||||||
|
pwmcnt_t period;
|
||||||
#if defined(PWM_DRIVER_EXT_FIELDS)
|
#if defined(PWM_DRIVER_EXT_FIELDS)
|
||||||
PWM_DRIVER_EXT_FIELDS
|
PWM_DRIVER_EXT_FIELDS
|
||||||
#endif
|
#endif
|
||||||
|
@ -138,54 +151,6 @@ struct PWMDriver {
|
||||||
/* Driver macros. */
|
/* 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] pwmp pointer to a @p PWMDriver object
|
|
||||||
* @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. */
|
/* External declarations. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -196,7 +161,7 @@ extern "C" {
|
||||||
void pwm_lld_init(void);
|
void pwm_lld_init(void);
|
||||||
void pwm_lld_start(PWMDriver *pwmp);
|
void pwm_lld_start(PWMDriver *pwmp);
|
||||||
void pwm_lld_stop(PWMDriver *pwmp);
|
void pwm_lld_stop(PWMDriver *pwmp);
|
||||||
bool_t pwm_lld_is_enabled(PWMDriver *pwmp, pwmchannel_t channel);
|
void pwm_lld_change_period(PWMDriver *pwmp, pwmcnt_t period);
|
||||||
void pwm_lld_enable_channel(PWMDriver *pwmp,
|
void pwm_lld_enable_channel(PWMDriver *pwmp,
|
||||||
pwmchannel_t channel,
|
pwmchannel_t channel,
|
||||||
pwmcnt_t width);
|
pwmcnt_t width);
|
||||||
|
|
|
@ -79,7 +79,14 @@
|
||||||
- FIX: Fixed wrong checks in I/O Queues (bug 3219197)(backported to 2.2.3).
|
- FIX: Fixed wrong checks in I/O Queues (bug 3219197)(backported to 2.2.3).
|
||||||
- FIX: Fixed invalid assertion in adcConvert() (bug 3205410)(backported
|
- FIX: Fixed invalid assertion in adcConvert() (bug 3205410)(backported
|
||||||
to 2.2.3).
|
to 2.2.3).
|
||||||
- NEW: Added new ICU driver model, Input Capture Unit..
|
- NEW: Improvements to the PWM driver model:
|
||||||
|
- Easier configuration similar to the GPT driver initializations, macros
|
||||||
|
are no more required.
|
||||||
|
- Added a new function that allows to change the PWM period on the fly,
|
||||||
|
even from within callbacks. Formerly it was required to stop and restart
|
||||||
|
the driver.
|
||||||
|
- Improved driver documentation.
|
||||||
|
- NEW: Added new ICU driver model, Input Capture Unit.
|
||||||
- NEW: ICU driver implementation for STM32.
|
- NEW: ICU driver implementation for STM32.
|
||||||
- NEW: Implemented stack checking in the Cortex-Mx RVCT port (backported
|
- NEW: Implemented stack checking in the Cortex-Mx RVCT port (backported
|
||||||
to 2.2.3).
|
to 2.2.3).
|
||||||
|
|
|
@ -21,33 +21,21 @@
|
||||||
#include "ch.h"
|
#include "ch.h"
|
||||||
#include "hal.h"
|
#include "hal.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* Red LEDs blinker thread, times are in milliseconds.
|
|
||||||
*/
|
|
||||||
static WORKING_AREA(waThread1, 128);
|
|
||||||
static msg_t Thread1(void *arg) {
|
|
||||||
|
|
||||||
(void)arg;
|
|
||||||
while (TRUE) {
|
|
||||||
palClearPad(IOPORT3, GPIOC_LED);
|
|
||||||
chThdSleepMilliseconds(500);
|
|
||||||
palSetPad(IOPORT3, GPIOC_LED);
|
|
||||||
chThdSleepMilliseconds(500);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pwmpcb(PWMDriver *pwmp) {
|
static void pwmpcb(PWMDriver *pwmp) {
|
||||||
|
|
||||||
(void)pwmp;
|
(void)pwmp;
|
||||||
|
palSetPad(IOPORT3, GPIOC_LED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pwmc1cb(PWMDriver *pwmp) {
|
static void pwmc1cb(PWMDriver *pwmp) {
|
||||||
|
|
||||||
(void)pwmp;
|
(void)pwmp;
|
||||||
|
palClearPad(IOPORT3, GPIOC_LED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PWMConfig pwmcfg = {
|
static PWMConfig pwmcfg = {
|
||||||
|
10000, /* 10KHz PWM clock frequency. */
|
||||||
|
10000, /* Initial PWM period 1S. */
|
||||||
pwmpcb,
|
pwmpcb,
|
||||||
{
|
{
|
||||||
{PWM_OUTPUT_ACTIVE_HIGH, pwmc1cb},
|
{PWM_OUTPUT_ACTIVE_HIGH, pwmc1cb},
|
||||||
|
@ -55,8 +43,6 @@ static PWMConfig pwmcfg = {
|
||||||
{PWM_OUTPUT_DISABLED, NULL},
|
{PWM_OUTPUT_DISABLED, NULL},
|
||||||
{PWM_OUTPUT_DISABLED, NULL}
|
{PWM_OUTPUT_DISABLED, NULL}
|
||||||
},
|
},
|
||||||
PWM_COMPUTE_PSC(STM32_TIMCLK1, 10000), /* 10KHz PWM clock frequency. */
|
|
||||||
PWM_COMPUTE_ARR(10000, 1000000), /* PWM period 1S. */
|
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -76,9 +62,9 @@ int main(void) {
|
||||||
chSysInit();
|
chSysInit();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates the blinker thread.
|
* LED initially off.
|
||||||
*/
|
*/
|
||||||
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
|
palSetPad(IOPORT3, GPIOC_LED);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initializes the PWM driver 1.
|
* Initializes the PWM driver 1.
|
||||||
|
@ -88,9 +74,9 @@ int main(void) {
|
||||||
chThdSleepMilliseconds(2000);
|
chThdSleepMilliseconds(2000);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Starts the channel 0 using 50% duty cycle.
|
* Starts the channel 0 using 25% duty cycle.
|
||||||
*/
|
*/
|
||||||
pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 5000));
|
pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 2500));
|
||||||
chThdSleepMilliseconds(5000);
|
chThdSleepMilliseconds(5000);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -99,11 +85,19 @@ int main(void) {
|
||||||
pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 7500));
|
pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 7500));
|
||||||
chThdSleepMilliseconds(5000);
|
chThdSleepMilliseconds(5000);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Changes PWM period to half second and duty cycle to 50%.
|
||||||
|
*/
|
||||||
|
pwmChangePeriod(&PWMD1, 5000);
|
||||||
|
pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 5000));
|
||||||
|
chThdSleepMilliseconds(5000);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disables channel 0.
|
* Disables channel 0.
|
||||||
*/
|
*/
|
||||||
pwmDisableChannel(&PWMD1, 0);
|
pwmDisableChannel(&PWMD1, 0);
|
||||||
|
pwmStop(&PWMD1);
|
||||||
|
palSetPad(IOPORT3, GPIOC_LED);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Normal main() thread activity, in this demo it does nothing.
|
* Normal main() thread activity, in this demo it does nothing.
|
||||||
|
|
Loading…
Reference in New Issue