Skip to content

Commit c6bcbfc

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents be1c8d1 + 5b7e075 commit c6bcbfc

File tree

2 files changed

+106
-23
lines changed

2 files changed

+106
-23
lines changed

ports/mimxrt10xx/common-hal/pwmio/PWMOut.c

Lines changed: 99 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
#include "supervisor/shared/translate.h"
3939
#include "periph.h"
4040

41+
// Debug print support set to zero to enable debug printing
42+
#define ENABLE_DEBUG_PRINTING 0
43+
44+
4145
static void config_periph_pin(const mcu_pwm_obj_t *periph) {
4246
IOMUXC_SetPinMux(
4347
periph->pin->mux_reg, periph->mux_mode,
@@ -83,6 +87,33 @@ static int calculate_pulse_count(uint32_t frequency, uint8_t *prescaler) {
8387
return 0;
8488
}
8589

90+
// ==========================================================
91+
// Debug code
92+
// ==========================================================
93+
#if ENABLE_DEBUG_PRINTING
94+
#define DBGPrintf mp_printf
95+
extern void debug_print_flexpwm_registers(PWM_Type *base);
96+
97+
void debug_print_flexpwm_registers(PWM_Type *base) {
98+
mp_printf(&mp_plat_print,
99+
"\t\tPWM OUTEN:%x MASK:%x SWCOUT:%x DTSRCSEL:%x MCTRL:%x MCTRL2:%x FCTRL:%x FSTS:%x FFILT:%x FTST:%x FCTRL2:%x\n",
100+
base->OUTEN, base->MASK, base->SWCOUT, base->DTSRCSEL, base->MCTRL, base->MCTRL2, base->FCTRL,
101+
base->FSTS, base->FFILT, base->FTST, base->FCTRL2);
102+
for (uint8_t i = 0; i < 4; i++) {
103+
mp_printf(&mp_plat_print,
104+
"\t\t(%u) INIT:%x CTRL2:%x CTRL:%x VAL0:%x VAL1:%x VAL2:%x VAL3:%x VAL4:%x VAL5:%x OCTRL:%x DTCNT0:%x DTCNT1:%x DISMAP: %x %x\n", i,
105+
base->SM[i].INIT, base->SM[i].CTRL2, base->SM[i].CTRL, base->SM[i].VAL0, base->SM[i].VAL1, base->SM[i].VAL2,
106+
base->SM[i].VAL3, base->SM[i].VAL4, base->SM[i].VAL5, base->SM[i].OCTRL, base->SM[i].DTCNT0, base->SM[i].DTCNT1,
107+
base->SM[i].DISMAP[0], base->SM[i].DISMAP[1]);
108+
}
109+
110+
}
111+
#else
112+
#define DBGPrintf(p,...)
113+
inline void debug_print_flexpwm_registers(PWM_Type *base) {
114+
}
115+
#endif
116+
86117
pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
87118
const mcu_pin_obj_t *pin,
88119
uint16_t duty,
@@ -93,6 +124,9 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
93124

94125
const uint32_t pwm_count = sizeof(mcu_pwm_list) / sizeof(mcu_pwm_obj_t);
95126

127+
DBGPrintf(&mp_plat_print, ">>> common_hal_pwmio_pwmout_construct called: pin: %p %u freq:%u duty:%u var:%u\n",
128+
self->pin->gpio, self->pin->number, frequency, duty, variable_frequency);
129+
96130
for (uint32_t i = 0; i < pwm_count; ++i) {
97131
if (mcu_pwm_list[i].pin != pin) {
98132
continue;
@@ -107,6 +141,8 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
107141
return PWMOUT_INVALID_PIN;
108142
}
109143

144+
DBGPrintf(&mp_plat_print, "\tFound in PWM List\n");
145+
110146
config_periph_pin(self->pwm);
111147

112148
pwm_config_t pwmConfig;
@@ -138,33 +174,67 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
138174

139175
pwmConfig.prescale = self->prescaler;
140176

177+
DBGPrintf(&mp_plat_print, "\tCall PWM_Init\n");
141178
if (PWM_Init(self->pwm->pwm, self->pwm->submodule, &pwmConfig) == kStatus_Fail) {
142179
return PWMOUT_INVALID_PIN;
143180
}
144181

145-
pwm_signal_param_t pwmSignal = {
146-
.pwmChannel = self->pwm->channel,
147-
.level = kPWM_HighTrue,
148-
.dutyCyclePercent = 0, // avoid an initial transient
149-
.deadtimeValue = 0, // allow 100% duty cycle
150-
};
151-
152182
// Disable all fault inputs
153183
self->pwm->pwm->SM[self->pwm->submodule].DISMAP[0] = 0;
154184
self->pwm->pwm->SM[self->pwm->submodule].DISMAP[1] = 0;
155185

156-
status_t status = PWM_SetupPwm(self->pwm->pwm, self->pwm->submodule, &pwmSignal, 1, kPWM_EdgeAligned, frequency, PWM_SRC_CLK_FREQ);
157-
158-
if (status != kStatus_Success) {
159-
return PWMOUT_INITIALIZATION_ERROR;
186+
DBGPrintf(&mp_plat_print, "\tCall PWM_SetupPwm %p %x %u\n", self->pwm->pwm, self->pwm->submodule);
187+
// ========================================================================================================
188+
// Not calling the PWM_SetupPwm as it was setup to only work for PWM output on chan A and B but not X
189+
// I have done some experimenting, probably could try others, but again they do not work with X.
190+
// Most of the code checks to see if A if not, then it assume B.
191+
//
192+
// Instead I set it up to work similar to what the Teensy 4.x code does.
193+
//
194+
// That is we set the PWM_CTRL_FULL_MASK, which then uses base->SM[submodule].VAL1 to control
195+
// when the timer is reset, so it sets up your cycle/frequency. But then this implies that X channel
196+
// which uses 0, 1 has to be handled specially. So for the different channels:
197+
// A - Uses VAL2 to turn on (0) and VAL3=duty to turn off
198+
// B - Uses VAL4 to turn on (0) and VAL5 to turn off
199+
// X - As mentioned above VAL1 turns off, but it's set to the timing for frequency. so
200+
// VAL0 turns on, so we set it to VAL1 - duty
201+
//
202+
PWM_Type *base = self->pwm->pwm;
203+
uint8_t submodule = self->pwm->submodule;
204+
205+
uint32_t mask = 1 << submodule;
206+
uint32_t olddiv = base->SM[submodule].VAL1 + 1;
207+
if (self->pulse_count != olddiv) {
208+
base->MCTRL |= PWM_MCTRL_CLDOK(mask);
209+
base->SM[submodule].CTRL = PWM_CTRL_PRSC_MASK | PWM_CTRL_PRSC(self->prescaler);
210+
base->SM[submodule].VAL1 = self->pulse_count - 1;
211+
base->SM[submodule].CTRL2 = PWM_CTRL2_INDEP_MASK | PWM_CTRL2_WAITEN_MASK | PWM_CTRL2_DBGEN_MASK;
212+
213+
if (olddiv == 1) {
214+
base->SM[submodule].CTRL = PWM_CTRL_FULL_MASK;
215+
base->SM[submodule].VAL0 = 0;
216+
base->SM[submodule].VAL2 = 0;
217+
base->SM[submodule].VAL3 = 0;
218+
base->SM[submodule].VAL4 = 0;
219+
base->SM[submodule].VAL5 = 0;
220+
} else {
221+
base->SM[submodule].VAL0 = (base->SM[submodule].VAL0 * self->pulse_count) / olddiv;
222+
base->SM[submodule].VAL3 = (base->SM[submodule].VAL3 * self->pulse_count) / olddiv;
223+
base->SM[submodule].VAL5 = (base->SM[submodule].VAL5 * self->pulse_count) / olddiv;
224+
}
225+
base->MCTRL |= PWM_MCTRL_LDOK(mask);
160226
}
227+
debug_print_flexpwm_registers(self->pwm->pwm);
228+
161229
PWM_SetPwmLdok(self->pwm->pwm, 1 << self->pwm->submodule, true);
162230

163231
PWM_StartTimer(self->pwm->pwm, 1 << self->pwm->submodule);
164232

165233

234+
DBGPrintf(&mp_plat_print, "\tCall common_hal_pwmio_pwmout_set_duty_cycle\n");
166235
common_hal_pwmio_pwmout_set_duty_cycle(self, duty);
167236

237+
DBGPrintf(&mp_plat_print, "\tReturn OK\n");
168238
return PWMOUT_OK;
169239
}
170240

@@ -185,26 +255,38 @@ void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t *self, uint16_t d
185255
// we do not use PWM_UpdatePwmDutycycle because ...
186256
// * it works in integer percents
187257
// * it can't set the "X" duty cycle
258+
// As mentioned in the setting up of the frequency code
259+
// A - Uses VAL2 to turn on (0) and VAL3=duty to turn off
260+
// B - Uses VAL4 to turn on (0) and VAL5 to turn off
261+
// X - As mentioned above VAL1 turns off, but it's set to the timing for frequency. so
262+
// VAL0 turns on, so we set it to VAL1 - duty
263+
264+
DBGPrintf(&mp_plat_print, "common_hal_pwmio_pwmout_set_duty_cycle %u\n", duty);
188265
self->duty_cycle = duty;
266+
PWM_Type *base = self->pwm->pwm;
267+
uint8_t mask = 1 << self->pwm->submodule;
189268
if (duty == 65535) {
190269
self->duty_scaled = self->pulse_count + 1;
191270
} else {
192271
self->duty_scaled = ((uint32_t)duty * self->pulse_count + self->pulse_count / 2) / 65535;
193272
}
194273
switch (self->pwm->channel) {
195274
case kPWM_PwmX:
196-
self->pwm->pwm->SM[self->pwm->submodule].VAL0 = 0;
197-
self->pwm->pwm->SM[self->pwm->submodule].VAL1 = self->duty_scaled;
275+
base->SM[self->pwm->submodule].VAL0 = self->pulse_count - self->duty_scaled;
276+
base->OUTEN |= PWM_OUTEN_PWMX_EN(mask);
198277
break;
199278
case kPWM_PwmA:
200-
self->pwm->pwm->SM[self->pwm->submodule].VAL2 = 0;
201-
self->pwm->pwm->SM[self->pwm->submodule].VAL3 = self->duty_scaled;
279+
base->SM[self->pwm->submodule].VAL3 = self->duty_scaled;
280+
base->OUTEN |= PWM_OUTEN_PWMA_EN(mask);
202281
break;
203282
case kPWM_PwmB:
204-
self->pwm->pwm->SM[self->pwm->submodule].VAL4 = 0;
205-
self->pwm->pwm->SM[self->pwm->submodule].VAL5 = self->duty_scaled;
283+
base->SM[self->pwm->submodule].VAL5 = self->duty_scaled;
284+
base->OUTEN |= PWM_OUTEN_PWMB_EN(mask);
206285
}
207286
PWM_SetPwmLdok(self->pwm->pwm, 1 << self->pwm->submodule, true);
287+
288+
debug_print_flexpwm_registers(self->pwm->pwm);
289+
208290
}
209291

210292
uint16_t common_hal_pwmio_pwmout_get_duty_cycle(pwmio_pwmout_obj_t *self) {

ports/mimxrt10xx/supervisor/port.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,13 @@ void port_interrupt_after_ticks(uint32_t ticks) {
398398

399399
void port_idle_until_interrupt(void) {
400400
// App note here: https://www.nxp.com/docs/en/application-note/AN12085.pdf
401+
// Currently I have disabled the setting into wait mode as this impacts lots of different
402+
// subsystems and it is unclear if you can or should set it generically without having
403+
// a better understanding of user intent. For example by default it will kill PWM
404+
// when in this mode, unless PWM_CTRL2_WAITEN_MASK is set, and even with this set
405+
// it may not work properly if the same timer/subtimer is trying to PWM on multiple channels.
406+
// Maybe at later date, revisit after we have a better understanding on things like which
407+
// timers it impacts and how each subsystem is configured.
401408

402409
// Clear the FPU interrupt because it can prevent us from sleeping.
403410
if (__get_FPSCR() & ~(0x9f)) {
@@ -408,13 +415,7 @@ void port_idle_until_interrupt(void) {
408415
common_hal_mcu_disable_interrupts();
409416
if (!background_callback_pending()) {
410417
NVIC_ClearPendingIRQ(SNVS_HP_WRAPPER_IRQn);
411-
// Don't down clock on debug builds because it prevents the DAP from
412-
// reading memory
413-
#if CIRCUITPY_DEBUG == 0
414-
CLOCK_SetMode(kCLOCK_ModeWait);
415-
#endif
416418
__WFI();
417-
CLOCK_SetMode(kCLOCK_ModeRun);
418419
}
419420
common_hal_mcu_enable_interrupts();
420421
}

0 commit comments

Comments
 (0)