kopia lustrzana https://github.com/micropython/micropython
mimxrt/hal/pwm_backport: Fix 0 and 65536 edge cases of PWM's duty_u16.
It should be that: - duty_u16=0: output low, no pulse - duty_u16=65536: output high, no pulse That previously did not apply to all of the three PWM mechanisms of this port. This commit fixes it. Signed-off-by: robert-hh <robert@hammelrath.com>pull/12114/head
rodzic
a9821c0185
commit
a9a219d8bf
|
@ -18,10 +18,10 @@
|
||||||
#include "hal/pwm_backport.h"
|
#include "hal/pwm_backport.h"
|
||||||
|
|
||||||
void PWM_UpdatePwmDutycycle_u16(
|
void PWM_UpdatePwmDutycycle_u16(
|
||||||
PWM_Type *base, pwm_submodule_t subModule, pwm_channels_t pwmSignal, uint16_t dutyCycle, uint16_t Center_u16) {
|
PWM_Type *base, pwm_submodule_t subModule, pwm_channels_t pwmSignal, uint32_t dutyCycle, uint16_t Center_u16) {
|
||||||
assert((uint16_t)pwmSignal < 2U);
|
assert((uint16_t)pwmSignal < 2U);
|
||||||
uint16_t pulseCnt = 0, pwmHighPulse = 0;
|
uint32_t pulseCnt = 0, pwmHighPulse = 0;
|
||||||
uint16_t center;
|
uint32_t center;
|
||||||
|
|
||||||
// check and confine bounds for Center_u16
|
// check and confine bounds for Center_u16
|
||||||
if ((Center_u16 + dutyCycle / 2) >= PWM_FULL_SCALE) {
|
if ((Center_u16 + dutyCycle / 2) >= PWM_FULL_SCALE) {
|
||||||
|
@ -36,11 +36,21 @@ void PWM_UpdatePwmDutycycle_u16(
|
||||||
|
|
||||||
// Setup the PWM dutycycle of channel A or B
|
// Setup the PWM dutycycle of channel A or B
|
||||||
if (pwmSignal == kPWM_PwmA) {
|
if (pwmSignal == kPWM_PwmA) {
|
||||||
base->SM[subModule].VAL2 = center - pwmHighPulse / 2;
|
if (dutyCycle >= 65536) {
|
||||||
base->SM[subModule].VAL3 = base->SM[subModule].VAL2 + pwmHighPulse;
|
base->SM[subModule].VAL2 = 0;
|
||||||
|
base->SM[subModule].VAL3 = pulseCnt;
|
||||||
|
} else {
|
||||||
|
base->SM[subModule].VAL2 = center - pwmHighPulse / 2;
|
||||||
|
base->SM[subModule].VAL3 = base->SM[subModule].VAL2 + pwmHighPulse;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
base->SM[subModule].VAL4 = center - pwmHighPulse / 2;
|
if (dutyCycle >= 65536) {
|
||||||
base->SM[subModule].VAL5 = base->SM[subModule].VAL4 + pwmHighPulse;
|
base->SM[subModule].VAL4 = 0;
|
||||||
|
base->SM[subModule].VAL5 = pulseCnt;
|
||||||
|
} else {
|
||||||
|
base->SM[subModule].VAL4 = center - pwmHighPulse / 2;
|
||||||
|
base->SM[subModule].VAL5 = base->SM[subModule].VAL4 + pwmHighPulse;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,33 +96,33 @@ void PWM_SetupPwm_u16(PWM_Type *base, pwm_submodule_t subModule, pwm_signal_para
|
||||||
}
|
}
|
||||||
|
|
||||||
void PWM_SetupPwmx_u16(PWM_Type *base, pwm_submodule_t subModule,
|
void PWM_SetupPwmx_u16(PWM_Type *base, pwm_submodule_t subModule,
|
||||||
uint32_t pwmFreq_Hz, uint16_t duty_cycle, uint8_t invert, uint32_t srcClock_Hz) {
|
uint32_t pwmFreq_Hz, uint32_t duty_cycle, uint8_t invert, uint32_t srcClock_Hz) {
|
||||||
|
|
||||||
uint32_t pulseCnt;
|
uint32_t pulseCnt;
|
||||||
uint32_t pwmClock;
|
uint32_t pwmClock;
|
||||||
|
|
||||||
// Divide the clock by the prescale value
|
// Divide the clock by the prescale value
|
||||||
pwmClock = (srcClock_Hz / (1U << ((base->SM[subModule].CTRL & PWM_CTRL_PRSC_MASK) >> PWM_CTRL_PRSC_SHIFT)));
|
pwmClock = (srcClock_Hz / (1U << ((base->SM[subModule].CTRL & PWM_CTRL_PRSC_MASK) >> PWM_CTRL_PRSC_SHIFT)));
|
||||||
pulseCnt = (pwmClock + (pwmFreq_Hz - 1) / 2) / pwmFreq_Hz;
|
pulseCnt = (pwmClock + (pwmFreq_Hz - 1) / 2) / pwmFreq_Hz - 1;
|
||||||
base->SM[subModule].INIT = 0;
|
base->SM[subModule].INIT = 0;
|
||||||
base->SM[subModule].VAL0 = ((uint32_t)duty_cycle * pulseCnt) / PWM_FULL_SCALE - 1;
|
base->SM[subModule].VAL0 = ((uint32_t)duty_cycle * pulseCnt) / PWM_FULL_SCALE;
|
||||||
base->SM[subModule].VAL1 = pulseCnt - 1;
|
base->SM[subModule].VAL1 = pulseCnt;
|
||||||
|
|
||||||
base->SM[subModule].OCTRL = (base->SM[subModule].OCTRL & ~PWM_OCTRL_POLX_MASK) | PWM_OCTRL_POLX(!invert);
|
base->SM[subModule].OCTRL = (base->SM[subModule].OCTRL & ~PWM_OCTRL_POLX_MASK) | PWM_OCTRL_POLX(!invert);
|
||||||
|
|
||||||
base->OUTEN |= (1U << subModule);
|
// Switch the output on or off.
|
||||||
|
if (duty_cycle == 0) {
|
||||||
|
base->OUTEN &= ~(1U << subModule);
|
||||||
|
} else {
|
||||||
|
base->OUTEN |= (1U << subModule);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FSL_FEATURE_SOC_TMR_COUNT
|
#ifdef FSL_FEATURE_SOC_TMR_COUNT
|
||||||
status_t QTMR_SetupPwm_u16(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t pwmFreqHz,
|
status_t QTMR_SetupPwm_u16(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t pwmFreqHz,
|
||||||
uint16_t dutyCycleU16, bool outputPolarity, uint32_t srcClock_Hz, bool is_init) {
|
uint32_t dutyCycleU16, bool outputPolarity, uint32_t srcClock_Hz, bool is_init) {
|
||||||
uint32_t periodCount, highCount, lowCount, reg;
|
uint32_t periodCount, highCount, lowCount, reg;
|
||||||
|
|
||||||
if (dutyCycleU16 >= PWM_FULL_SCALE) {
|
|
||||||
// Invalid dutycycle
|
|
||||||
return kStatus_Fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Counter values to generate a PWM signal
|
// Counter values to generate a PWM signal
|
||||||
periodCount = ((srcClock_Hz + (pwmFreqHz - 1) / 2) / pwmFreqHz) - 2;
|
periodCount = ((srcClock_Hz + (pwmFreqHz - 1) / 2) / pwmFreqHz) - 2;
|
||||||
highCount = (periodCount * dutyCycleU16) / PWM_FULL_SCALE;
|
highCount = (periodCount * dutyCycleU16) / PWM_FULL_SCALE;
|
||||||
|
@ -147,11 +157,18 @@ status_t QTMR_SetupPwm_u16(TMR_Type *base, qtmr_channel_selection_t channel, uin
|
||||||
|
|
||||||
reg = base->CHANNEL[channel].CTRL;
|
reg = base->CHANNEL[channel].CTRL;
|
||||||
reg &= ~(TMR_CTRL_OUTMODE_MASK);
|
reg &= ~(TMR_CTRL_OUTMODE_MASK);
|
||||||
// Count until compare value is reached and re-initialize the counter, toggle OFLAG output
|
if (dutyCycleU16 == 0) {
|
||||||
// using alternating compare register
|
// Clear the output at the next compare
|
||||||
reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ToggleOnAltCompareReg));
|
reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ClearOnCompare));
|
||||||
|
} else if (dutyCycleU16 >= 65536) {
|
||||||
|
// Set the output at the next compare
|
||||||
|
reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_SetOnCompare));
|
||||||
|
} else {
|
||||||
|
// Count until compare value is reached and re-initialize the counter, toggle OFLAG output
|
||||||
|
// using alternating compare register
|
||||||
|
reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ToggleOnAltCompareReg));
|
||||||
|
}
|
||||||
base->CHANNEL[channel].CTRL = reg;
|
base->CHANNEL[channel].CTRL = reg;
|
||||||
|
|
||||||
return kStatus_Success;
|
return kStatus_Success;
|
||||||
}
|
}
|
||||||
#endif // FSL_FEATURE_SOC_TMR_COUNT
|
#endif // FSL_FEATURE_SOC_TMR_COUNT
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
typedef struct _pwm_signal_param_u16
|
typedef struct _pwm_signal_param_u16
|
||||||
{
|
{
|
||||||
pwm_channels_t pwmChannel; // PWM channel being configured; PWM A or PWM B
|
pwm_channels_t pwmChannel; // PWM channel being configured; PWM A or PWM B
|
||||||
uint16_t dutyCycle_u16; // PWM pulse width, value should be between 0 to 65536
|
uint32_t dutyCycle_u16; // PWM pulse width, value should be between 0 to 65536
|
||||||
uint16_t Center_u16; // Center of the pulse, value should be between 0 to 65536
|
uint16_t Center_u16; // Center of the pulse, value should be between 0 to 65536
|
||||||
pwm_level_select_t level; // PWM output active level select */
|
pwm_level_select_t level; // PWM output active level select */
|
||||||
uint16_t deadtimeValue; // The deadtime value; only used if channel pair is operating in complementary mode
|
uint16_t deadtimeValue; // The deadtime value; only used if channel pair is operating in complementary mode
|
||||||
|
@ -27,17 +27,17 @@ typedef struct _pwm_signal_param_u16
|
||||||
#define PWM_FULL_SCALE (65536UL)
|
#define PWM_FULL_SCALE (65536UL)
|
||||||
|
|
||||||
void PWM_UpdatePwmDutycycle_u16(PWM_Type *base, pwm_submodule_t subModule,
|
void PWM_UpdatePwmDutycycle_u16(PWM_Type *base, pwm_submodule_t subModule,
|
||||||
pwm_channels_t pwmSignal, uint16_t dutyCycle, uint16_t center);
|
pwm_channels_t pwmSignal, uint32_t dutyCycle, uint16_t center);
|
||||||
|
|
||||||
void PWM_SetupPwm_u16(PWM_Type *base, pwm_submodule_t subModule, pwm_signal_param_u16_t *chnlParams,
|
void PWM_SetupPwm_u16(PWM_Type *base, pwm_submodule_t subModule, pwm_signal_param_u16_t *chnlParams,
|
||||||
uint32_t pwmFreq_Hz, uint32_t srcClock_Hz, bool output_enable);
|
uint32_t pwmFreq_Hz, uint32_t srcClock_Hz, bool output_enable);
|
||||||
|
|
||||||
void PWM_SetupPwmx_u16(PWM_Type *base, pwm_submodule_t subModule,
|
void PWM_SetupPwmx_u16(PWM_Type *base, pwm_submodule_t subModule,
|
||||||
uint32_t pwmFreq_Hz, uint16_t duty_cycle, uint8_t invert, uint32_t srcClock_Hz);
|
uint32_t pwmFreq_Hz, uint32_t duty_cycle, uint8_t invert, uint32_t srcClock_Hz);
|
||||||
|
|
||||||
#ifdef FSL_FEATURE_SOC_TMR_COUNT
|
#ifdef FSL_FEATURE_SOC_TMR_COUNT
|
||||||
status_t QTMR_SetupPwm_u16(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t pwmFreqHz,
|
status_t QTMR_SetupPwm_u16(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t pwmFreqHz,
|
||||||
uint16_t dutyCycleU16, bool outputPolarity, uint32_t srcClock_Hz, bool is_init);
|
uint32_t dutyCycleU16, bool outputPolarity, uint32_t srcClock_Hz, bool is_init);
|
||||||
#endif // FSL_FEATURE_SOC_TMR_COUNT
|
#endif // FSL_FEATURE_SOC_TMR_COUNT
|
||||||
|
|
||||||
#endif // PWM_BACKPORT_H
|
#endif // PWM_BACKPORT_H
|
||||||
|
|
Ładowanie…
Reference in New Issue