Using DMA to drive PWM signal on Teensy 4.0

Status
Not open for further replies.

Setanko

Member
Hello,

I am currently working on a project in which I would like to use DMA to update PWM pulse length on the Teensy 4 board. More specifically, I would like to use the PWM counter reset as a trigger for DMA to move data from an array in my code to one of the VALx registers of the PWM peripheral (in my case, VAL3 register of Submodule 0 of FlexPWM2). After reading through the manual (https://www.pjrc.com/teensy/IMXRT1060RM_rev2.pdf), Paul's PWM.c code (https://github.com/PaulStoffregen/cores/blob/master/teensy4/pwm.c), and some other forum posts, I realized that I should 1. use Paul's DMAChannel library and 2. also need to set a LDOK bit in addition to updating the VALx register in order to get the PWM pulse length to actually change. However, after working on this for a few days, I'm still not getting anywhere code-wise. Are there any examples of DMA being used in combination with PWM that I can take a look at, or alternatively, can anyone suggest a general layout for how my code might look?

Many thanks.
 
Driving FLEXPWM with DMA

Hello,

I am currently working on a project in which I would like to use DMA to update PWM pulse length on the Teensy 4 board. More specifically, I would like to use the PWM counter reset as a trigger for DMA to move data from an array in my code to one of the VALx registers of the PWM peripheral (in my case, VAL3 register of Submodule 0 of FlexPWM2). After reading through the manual (https://www.pjrc.com/teensy/IMXRT1060RM_rev2.pdf), Paul's PWM.c code (https://github.com/PaulStoffregen/cores/blob/master/teensy4/pwm.c), and some other forum posts, I realized that I should 1. use Paul's DMAChannel library and 2. also need to set a LDOK bit in addition to updating the VALx register in order to get the PWM pulse length to actually change. However, after working on this for a few days, I'm still not getting anywhere code-wise. Are there any examples of DMA being used in combination with PWM that I can take a look at, or alternatively, can anyone suggest a general layout for how my code might look?

Many thanks.

Looks like you are close. From your description, the following should vary the duty cycle.
Code:
void loop() {
  FLEXPWM2_SM0VAL3 = val3; 
  FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_LDOK(??);
  val3 = (val3+1)%30000;
  delay(1);
}

If that works, remove FLEXPWM2 stuff from the loop and add the following in your setup:

Code:
void dmaSetup() {
  FLEXPWM2_SM0DMAEN = FLEXPWM_SMDMAEN_VALDE;  // Enable DMA  FLEXPWM2 submodule 0
  dma.destination((uint16_t&) FLEXPWM2_SM0VAL3);   // Load the pulse width register
  dma.sourceBuffer(dma_source.data(), sizeof(dma_source));
  dma.triggerAtHardwareEvent(DMAMUX_SOURCE_FLEXPWM2_WRITE0);   // Trigger the DMA from PWM2 write on SM0
  dma.enable();
}
 
Status
Not open for further replies.
Back
Top