Skip to content

Commit e2532e0

Browse files
robert-hhdpgeorge
authored andcommitted
mimxrt/machine_pwm: Fix a few inconsistencies with PWM output.
Changes in this commit: - When setting PWM parameters of a FLEXPWM AB channel twice within a PWM cycle, the second setting was ignored. Now the second setting persists. - With `duty_u16(0)` a FLEXPWM X channel was set to high impedance. Now it is set to low impedance with value 0 for `invert=False`, and 1 for `invert=True`. - The align parameter requires a duty rate and frequency to be set. Align will now be ignored if freq or duty are missing. Signed-off-by: robert-hh <[email protected]>
1 parent 898407d commit e2532e0

File tree

2 files changed

+28
-9
lines changed

2 files changed

+28
-9
lines changed

ports/mimxrt/hal/pwm_backport.c

+2-6
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,8 @@ void PWM_SetupPwmx_u16(PWM_Type *base, pwm_submodule_t subModule,
110110

111111
base->SM[subModule].OCTRL = (base->SM[subModule].OCTRL & ~PWM_OCTRL_POLX_MASK) | PWM_OCTRL_POLX(!invert);
112112

113-
// Switch the output on or off.
114-
if (duty_cycle == 0) {
115-
base->OUTEN &= ~(1U << subModule);
116-
} else {
117-
base->OUTEN |= (1U << subModule);
118-
}
113+
// Enable PWM output
114+
base->OUTEN |= (1U << subModule);
119115
}
120116

121117
#ifdef FSL_FEATURE_SOC_TMR_COUNT

ports/mimxrt/machine_pwm.c

+26-3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
typedef struct _machine_pwm_obj_t {
4646
mp_obj_base_t base;
4747
PWM_Type *instance;
48+
const machine_pin_obj_t *pwm_pin;
49+
const machine_pin_af_obj_t *pwm_pin_af_obj;
4850
bool is_flexpwm;
4951
uint8_t complementary;
5052
uint8_t module;
@@ -255,6 +257,8 @@ static void configure_flexpwm(machine_pwm_obj_t *self) {
255257
PWM_SetupFaultDisableMap(self->instance, self->submodule, self->channel2, kPWM_faultchannel_1, 0);
256258
}
257259

260+
// clear the load okay bit for the submodules in case there is a pending load
261+
PWM_SetPwmLdok(self->instance, 1 << self->submodule, false);
258262
if (self->channel1 != kPWM_PwmX) { // Only for A/B channels
259263
// Initialize the channel parameters
260264
pwmSignal.pwmChannel = self->channel1;
@@ -283,6 +287,17 @@ static void configure_flexpwm(machine_pwm_obj_t *self) {
283287
self->instance->SM[self->submodule].CTRL &= ~(PWM_CTRL_DBLEN_MASK | PWM_CTRL_SPLIT_MASK);
284288
}
285289
} else {
290+
if (self->duty_u16 == 0) {
291+
// For duty_u16 == 0 just set the output to GPIO mode
292+
if (self->invert) {
293+
mp_hal_pin_high(self->pwm_pin);
294+
} else {
295+
mp_hal_pin_low(self->pwm_pin);
296+
}
297+
IOMUXC_SetPinMux(self->pwm_pin->muxRegister, PIN_AF_MODE_ALT5, 0, 0, 0, 0U);
298+
} else {
299+
IOMUXC_SetPinMux(self->pwm_pin->muxRegister, self->pwm_pin_af_obj->af_mode, 0, 0, 0, 0U);
300+
}
286301
PWM_SetupPwmx_u16(self->instance, self->submodule, self->freq, self->duty_u16,
287302
self->invert, pwmSourceClockInHz);
288303
if (self->xor) {
@@ -408,12 +423,16 @@ static void mp_machine_pwm_init_helper(machine_pwm_obj_t *self,
408423
}
409424
self->center = center;
410425
} else { // Use alignment setting shortcut
411-
if (args[ARG_align].u_int >= 0) {
426+
uint32_t duty = self->duty_u16;
427+
if (duty == VALUE_NOT_SET && self->duty_ns != VALUE_NOT_SET) {
428+
duty = duty_ns_to_duty_u16(self->freq, self->duty_ns);
429+
}
430+
if (args[ARG_align].u_int >= 0 && duty != VALUE_NOT_SET && self->freq != VALUE_NOT_SET) {
412431
uint8_t align = args[ARG_align].u_int & 3; // limit to 0..3
413432
if (align == PWM_BEGIN) {
414-
self->center = self->duty_u16 / 2;
433+
self->center = duty / 2;
415434
} else if (align == PWM_END) {
416-
self->center = PWM_FULL_SCALE - self->duty_u16 / 2;
435+
self->center = PWM_FULL_SCALE - duty / 2;
417436
} else {
418437
self->center = 32768; // Default value: mid.
419438
}
@@ -515,6 +534,8 @@ static mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args
515534

516535
// Create and populate the PWM object.
517536
machine_pwm_obj_t *self = mp_obj_malloc(machine_pwm_obj_t, &machine_pwm_type);
537+
self->pwm_pin = pin1;
538+
self->pwm_pin_af_obj = af_obj1;
518539
self->is_flexpwm = is_flexpwm;
519540
self->instance = af_obj1->instance;
520541
self->module = module;
@@ -534,6 +555,8 @@ static mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args
534555

535556
// Initialize the Pin(s).
536557
CLOCK_EnableClock(kCLOCK_Iomuxc); // just in case it was not set yet
558+
// Configure PWMX channels to pin output mode to be prepared for duty_u16 == 0.
559+
mp_hal_pin_output(pin1);
537560
IOMUXC_SetPinMux(pin1->muxRegister, af_obj1->af_mode, af_obj1->input_register, af_obj1->input_daisy,
538561
pin1->configRegister, 0U);
539562
IOMUXC_SetPinConfig(pin1->muxRegister, af_obj1->af_mode, af_obj1->input_register, af_obj1->input_daisy,

0 commit comments

Comments
 (0)