summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrobert-hh <robert@hammelrath.com>2024-11-06 20:26:27 +0100
committerDamien George <damien@micropython.org>2024-11-18 16:11:13 +1100
commite2532e0f725107becea3cf7e6d14727ab3abec7c (patch)
tree5dfa564fe2a03c9ffbd73a41513941b8091aeb59
parent898407defbb6327fde379304846999033bf349c5 (diff)
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 <robert@hammelrath.com>
-rw-r--r--ports/mimxrt/hal/pwm_backport.c8
-rw-r--r--ports/mimxrt/machine_pwm.c29
2 files changed, 28 insertions, 9 deletions
diff --git a/ports/mimxrt/hal/pwm_backport.c b/ports/mimxrt/hal/pwm_backport.c
index 3df826496..7815fd1df 100644
--- a/ports/mimxrt/hal/pwm_backport.c
+++ b/ports/mimxrt/hal/pwm_backport.c
@@ -110,12 +110,8 @@ void PWM_SetupPwmx_u16(PWM_Type *base, pwm_submodule_t subModule,
base->SM[subModule].OCTRL = (base->SM[subModule].OCTRL & ~PWM_OCTRL_POLX_MASK) | PWM_OCTRL_POLX(!invert);
- // Switch the output on or off.
- if (duty_cycle == 0) {
- base->OUTEN &= ~(1U << subModule);
- } else {
- base->OUTEN |= (1U << subModule);
- }
+ // Enable PWM output
+ base->OUTEN |= (1U << subModule);
}
#ifdef FSL_FEATURE_SOC_TMR_COUNT
diff --git a/ports/mimxrt/machine_pwm.c b/ports/mimxrt/machine_pwm.c
index f9ae5e22e..b68521281 100644
--- a/ports/mimxrt/machine_pwm.c
+++ b/ports/mimxrt/machine_pwm.c
@@ -45,6 +45,8 @@
typedef struct _machine_pwm_obj_t {
mp_obj_base_t base;
PWM_Type *instance;
+ const machine_pin_obj_t *pwm_pin;
+ const machine_pin_af_obj_t *pwm_pin_af_obj;
bool is_flexpwm;
uint8_t complementary;
uint8_t module;
@@ -255,6 +257,8 @@ static void configure_flexpwm(machine_pwm_obj_t *self) {
PWM_SetupFaultDisableMap(self->instance, self->submodule, self->channel2, kPWM_faultchannel_1, 0);
}
+ // clear the load okay bit for the submodules in case there is a pending load
+ PWM_SetPwmLdok(self->instance, 1 << self->submodule, false);
if (self->channel1 != kPWM_PwmX) { // Only for A/B channels
// Initialize the channel parameters
pwmSignal.pwmChannel = self->channel1;
@@ -283,6 +287,17 @@ static void configure_flexpwm(machine_pwm_obj_t *self) {
self->instance->SM[self->submodule].CTRL &= ~(PWM_CTRL_DBLEN_MASK | PWM_CTRL_SPLIT_MASK);
}
} else {
+ if (self->duty_u16 == 0) {
+ // For duty_u16 == 0 just set the output to GPIO mode
+ if (self->invert) {
+ mp_hal_pin_high(self->pwm_pin);
+ } else {
+ mp_hal_pin_low(self->pwm_pin);
+ }
+ IOMUXC_SetPinMux(self->pwm_pin->muxRegister, PIN_AF_MODE_ALT5, 0, 0, 0, 0U);
+ } else {
+ IOMUXC_SetPinMux(self->pwm_pin->muxRegister, self->pwm_pin_af_obj->af_mode, 0, 0, 0, 0U);
+ }
PWM_SetupPwmx_u16(self->instance, self->submodule, self->freq, self->duty_u16,
self->invert, pwmSourceClockInHz);
if (self->xor) {
@@ -408,12 +423,16 @@ static void mp_machine_pwm_init_helper(machine_pwm_obj_t *self,
}
self->center = center;
} else { // Use alignment setting shortcut
- if (args[ARG_align].u_int >= 0) {
+ uint32_t duty = self->duty_u16;
+ if (duty == VALUE_NOT_SET && self->duty_ns != VALUE_NOT_SET) {
+ duty = duty_ns_to_duty_u16(self->freq, self->duty_ns);
+ }
+ if (args[ARG_align].u_int >= 0 && duty != VALUE_NOT_SET && self->freq != VALUE_NOT_SET) {
uint8_t align = args[ARG_align].u_int & 3; // limit to 0..3
if (align == PWM_BEGIN) {
- self->center = self->duty_u16 / 2;
+ self->center = duty / 2;
} else if (align == PWM_END) {
- self->center = PWM_FULL_SCALE - self->duty_u16 / 2;
+ self->center = PWM_FULL_SCALE - duty / 2;
} else {
self->center = 32768; // Default value: mid.
}
@@ -515,6 +534,8 @@ static mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args
// Create and populate the PWM object.
machine_pwm_obj_t *self = mp_obj_malloc(machine_pwm_obj_t, &machine_pwm_type);
+ self->pwm_pin = pin1;
+ self->pwm_pin_af_obj = af_obj1;
self->is_flexpwm = is_flexpwm;
self->instance = af_obj1->instance;
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
// Initialize the Pin(s).
CLOCK_EnableClock(kCLOCK_Iomuxc); // just in case it was not set yet
+ // Configure PWMX channels to pin output mode to be prepared for duty_u16 == 0.
+ mp_hal_pin_output(pin1);
IOMUXC_SetPinMux(pin1->muxRegister, af_obj1->af_mode, af_obj1->input_register, af_obj1->input_daisy,
pin1->configRegister, 0U);
IOMUXC_SetPinConfig(pin1->muxRegister, af_obj1->af_mode, af_obj1->input_register, af_obj1->input_daisy,