olarity inversion with FlexPWM

whitelightning

New member
Hi everyone,


I’m working on a project using the Teensy 4.1, and I’m trying to generate two pairs of complementary PWM signals for driving MOSFET driver circuits.


My goal:
✅ Use FLEXPWM2 submodules SM0 and SM2, both channels A and B.
✅ Generate PWM at 1 MHz frequency, 50% duty cycle.
✅ Add ~50 ns dead time between A and B in each submodule.
✅ Invert the polarity of both outputs relative to their default.
✅ Outputs mapped as follows:


  • SM0 (FLEXPWM2_SM0):
    • Pin 4 → FLEXPWM2_PWM0_A
    • Pin 33 → FLEXPWM2_PWM0_B
  • SM2 (FLEXPWM2_SM2):
    • Pin 6 → FLEXPWM2_PWM2_A
    • Pin 9 → FLEXPWM2_PWM2_B

I want:


  • A and B channels on each submodule to be complementary (when A is HIGH → B is LOW and vice versa).
  • ~50 ns dead time between switching.
  • All outputs inverted relative to default polarity.

What I’ve tried:


  • eFlexPWM library – but it doesn’t expose polarity inversion or direct register access for FLEXPWM2 SM0 and SM2.
  • Direct register-level programming based on the IMXRT1060 reference manual.
  • Reading PJRC forum posts about using OCTRL, DTCNT0/1, and OUTEN registers.
  • Manually configuring mux registers to route the PWM outputs to the desired pins.

My problems:


  • I can’t get output signals on pins 4, 33, 6, and 9 with my register-level code.
  • I’m not sure if I’m correctly enabling clocks and setting CCM_CCGR4 for FLEXPWM2.
  • I’m unclear on the proper way to invert the polarity of SM0 A/B and SM2 A/B outputs.
  • I’m confused about the necessary IOMUXC_SW_MUX and SW_PAD settings for routing PWM2 SM0 and SM2 outputs to the correct pins.

My questions:
✅ Does anyone have working code examples (register-level or using libraries) that:


  • Enable FLEXPWM2 properly.
  • Configure both SM0 and SM2 for 1 MHz PWM, 50% duty.
  • Set ~50 ns dead time for each submodule.
  • Invert output polarity for channels A and B.
  • Drive signals to pins 4, 33, 6, and 9.

✅ Is there any special clock gating or IOMUX setup required beyond CCM_CCGR4 and the SW_MUX registers?


✅ Is there a reliable way to invert PWM polarity purely in registers for FLEXPWM2 SM0 and SM2?


I’ve been working on this for a couple of weeks and keep hitting roadblocks. Any examples, code snippets, or insights would be hugely appreciated!


Thanks so much for your help.
 
The eFlexPwmSimple example uses those 4 pins, so that gets you most of the way there. The comments in the example refer to a "level" setting, and searching the files in the src folder shows function setupLevel(), which has two forms, one for a single channel and one for both A and B channels of one submodule. I haven't tried it, but it seems like that would provide the inversion you're looking for.
 
Thank you for your response. It is my understanding that setup level() would work great for a lower frequency. unfortunately I need to switch a GaN dual half bridge at 1mhz to both sides of a transformer and ultimately a piezo.. So, I need a way to set the bits in the picture below, while retaining the ability to add deadtime. Ive been able to do everything in eflexpwm that I need except switch those two bits for a submodule. I have tried to write directly to the registers and all attempts at that have resulted in no output. Thank you for your time and attention to this matter.
 

Attachments

  • invert POLA.png
    invert POLA.png
    106.2 KB · Views: 59
The level field sets those bits, and it's in the same channel data structure as the deadtime, so I don't understand what you mean when you say you can't set those flags. Have you experimented with the setupLevel() function?

Regarding your 1 MHz PWM frequency, do you want to update duty cycle at 1 MHz? That would likely be approaching the limits of the T4's capabilites and would not leave much time for calculations.
 
Hi [Joe / All],


Thanks for your earlier help clarifying that the level field in the pwm_signal_param_t struct controls the POLA and POLB bits. I’ve been digging deeper, and I wanted to follow up because I’m still seeing no output on my Teensy 4.1 despite applying your advice.




What I’ve Tried​

I’m using the eFlexPWM library v0.2.11 on Teensy 4.1 (Arduino 1.8.19, Teensyduino 1.59).
My goal:

  • 1 MHz PWM
  • 50% duty cycle
  • Complementary A/B signals
  • Inter-pair complementary across two submodules (so SM1 is inverted from SM0)
  • Deadtime inserted
I updated my code to use:
cpp
CopyEdit
sm0.setupLevel(kPWM_HighTrue);
sm1.setupLevel(kPWM_LowTrue);

and confirmed that kPWM_LowTrue should flip the polarity bits in OCTRL.

I’m using:
ini
CopyEdit
SM0_A = Pin 4
SM0_B = Pin 33
SM1_A = Pin 6
SM1_B = Pin 9

I’m setting duty cycles via:

cpp
CopyEdit
sm0.updateDutyCycle(50, ChanA);
sm0.updateDutyCycle(50, ChanB);

The Problem​


Despite all of that, I’m getting no PWM output on the pins. The signals remain stuck low (or high, depending on the pin config) but never toggle. I’ve tested with an oscilloscope.

What I Suspect​


I think there’s something deeper going on in hardware registers, such as:

  • The FlexPWM clock not running
  • LDOK bits not getting set after config
  • MASK registers preventing output
  • MUX config not properly applied to the pins

For example, I’ve read that PWM1->OUTEN and PWM1->MCTRL sometimes need to be manually set for outputs to activate. The eFlexPWM library might not be handling those final steps completely.

My Next Steps​


I plan to:


Check the hardware registers directly:
cpp
CopyEdit
Serial.println(PWM1->MASK, HEX);
Serial.println(PWM1->MCTRL, HEX);
Serial.println(PWM1->OUTEN, HEX);


  1. Force-enable outputs manually:
cpp
CopyEdit
PWM1->MCTRL |= (1 << 0) | (1 << 1);
PWM1->OUTEN = 0xFF;


  1. Test a single pin first (e.g. Pin 4) in independent mode, to confirm if any PWM signal comes out at all.
 
Your outline doesn't tell me what you've done, and you haven't shown your code.

Step 1, build and run the eFlexPWM examples with no changes and confirm that you get the expected outputs. I've done that and I know they both work.

Step 2, make changes from there.

For example, increase PWM frequency in reasonable steps from the default 10 kHz and see how far you can go toward 1 MHz before things break down.
 
Back
Top