Aha! I posted in the General Discussion and Technical Support Boards before debugging lead me here. The IRQ_FLEXPWM2_0 (137) vector does not seem to be functioning properly.
I set the FLEXPWM2_SM0CTRL register so that reload flags should occur once per pwm cycle (ie the flag is set upon pwmCount = SM0Val1). I also added a debugging output to the valArampUpISR() by toggling a digital pin every time the ISR executed. D7 is the digital debugging output, <D0,D1,D2> are pwm channels <A,B,C>.
Here is a zoomed out shot of the scope showing the channelA ramp-up:
Here is the o-scope output when the Teensy runs at 150Mhz (reload ISR every ~1.5u):
Here is the o-scope output when the Teensy runs at 24MHz (reload ISR every ~3u):
This is my source code:
As you can see, the RF flag is not only set many times a pwm period, but the frequency at which it is set is dependent on the Clock rate. The program sets the Prescaler such that the pwm period is ~40 kHz regardless of the clock frequency. Even when I set a 1kHz pwm period, the reload flag is set at the same frequency (resulting in hundreds of ISRs every pwm period).
Thank you for any help, I would love to find out that this is my own doing and not a problem with the Teensy Platform.
For reference the links to my previous posts can be found here:
https://forum.pjrc.com/threads/70640-trouble-attaching-consecutive-ISRs-to-the-same-FLEXPWM-IRQ
https://forum.pjrc.com/threads/70644-T4-1-attachInterruptVector()-and-NVIC-Controller
I set the FLEXPWM2_SM0CTRL register so that reload flags should occur once per pwm cycle (ie the flag is set upon pwmCount = SM0Val1). I also added a debugging output to the valArampUpISR() by toggling a digital pin every time the ISR executed. D7 is the digital debugging output, <D0,D1,D2> are pwm channels <A,B,C>.
Here is a zoomed out shot of the scope showing the channelA ramp-up:
Here is the o-scope output when the Teensy runs at 150Mhz (reload ISR every ~1.5u):
Here is the o-scope output when the Teensy runs at 24MHz (reload ISR every ~3u):
This is my source code:
Code:
#include <Arduino.h>
#include "imxrt.h"
#include "core_pins.h"
#define ChannelA 4
#define ChannelB 33
#define ChannelC 5
#define Maske 0x03
struct trapTest
{
uint16_t dutyRamp;
uint16_t period;
volatile bool state;
};
trapTest trap;
trapTest* trap1 = &trap;
void setOutputFrequency(float frequency)
{
uint32_t CurrentCycles = (uint32_t)((float)F_BUS_ACTUAL / frequency + 0.5);
uint32_t Prescaler = 0;
//Falls Frequenz zu gering Prescaler switchen!
while (CurrentCycles > 65535 && Prescaler < 7) {
CurrentCycles = CurrentCycles >> 1;
Prescaler = Prescaler + 1;
}
if (CurrentCycles > 65535) {
CurrentCycles = 65535;
}
else if (CurrentCycles < 2) {
CurrentCycles = 2; //minimale Cycles --> 10nS oder so
}
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_CLDOK(Maske);
FLEXPWM2_SM0CTRL = FLEXPWM_SMCTRL_FULL | FLEXPWM_SMCTRL_PRSC(Prescaler); //Erst nach vollem Cycle updaten und Prescaler setzen!
FLEXPWM2_SM1CTRL = FLEXPWM_SMCTRL_FULL | FLEXPWM_SMCTRL_PRSC(Prescaler); //same prescaler for SM1
FLEXPWM2_SM0VAL1 = CurrentCycles - 1; //Cycles f�r Periodendauer setzen!
FLEXPWM2_SM1VAL1 = CurrentCycles - 1; //same period for SM1
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_LDOK(Maske);
trap1->period = FLEXPWM2_SM0VAL1;
}
static inline void clearInterrupt()
{
FLEXPWM2_SM0STS &= ~0x1000;
}
void valArampUpISR()
{
if (FLEXPWM2_SM0VAL2 > 3)
{
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_CLDOK(Maske);
FLEXPWM2_SM0VAL2 -= trap1->dutyRamp;
FLEXPWM2_SM0VAL3 += trap1->dutyRamp;
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_LDOK(Maske);
}
trap1->state = !trap1->state;
digitalWrite(9,trap1->state);
clearInterrupt();
}
void valBrampDownISR()
{
if (FLEXPWM2_SM0VAL4 + 1 < FLEXPWM2_SM0VAL5)
{
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_CLDOK(Maske);
FLEXPWM2_SM0VAL4 += trap1->dutyRamp;
FLEXPWM2_SM0VAL5 -= trap1->dutyRamp;
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_LDOK(Maske);
}
clearInterrupt();
}
void setOutputPWM(uint16_t valAL, uint16_t valAH, uint16_t valBL, uint16_t valBH,
uint16_t valCL, uint16_t valCH)
{
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_CLDOK(Maske);
FLEXPWM2_SM0VAL2 = valAL;
FLEXPWM2_SM0VAL3 = valAH;
FLEXPWM2_SM0VAL4 = valBL;
FLEXPWM2_SM0VAL5 = valBH;
FLEXPWM2_SM1VAL2 = valCL;
FLEXPWM2_SM1VAL3 = valCH;
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_LDOK(Maske);
}
void initTest()
{
*(portConfigRegister(ChannelA)) = 1; //trap->pin1, initializes muxval in pwm.c pwm_pin_info struct
*(portConfigRegister(ChannelB)) = 1; //trap->pin2
*(portConfigRegister(ChannelC)) = 1; //trap->pin3
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_CLDOK(Maske);
FLEXPWM2_SM0CTRL |= (uint16_t)0x0400; //Full cycle reloads, enable LDMOD for instant reloads
FLEXPWM2_SM1CTRL |= (uint16_t)0x0400;
FLEXPWM2_SM0CTRL &= (uint16_t)~0x0800; //disable half cycle reloads
FLEXPWM2_SM1CTRL &= (uint16_t)~0x0800;
FLEXPWM2_SM1CTRL2 |= FLEXPWM_SMCTRL2_CLK_SEL(0x02); //SM1 relies on SM0 clock
FLEXPWM2_OUTEN |= FLEXPWM_OUTEN_PWMA_EN(Maske);
FLEXPWM2_OUTEN |= FLEXPWM_OUTEN_PWMB_EN(Maske);
//FLEXPWM2_SM0CTRL2 |= (uint16_t)0x00C0; //FRCEN, FRCSEL !ACHTUNG!, STILL need to add FRCOUT to pwmOutput,
//FLEXPWM2_SM1CTRL2 |= (uint16_t)0x00C8; //SM1 relies on SM0 FRC //... setup sel45 for initial values
FLEXPWM2_SM0INTEN |= 0x1000;
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_LDOK(Maske);
}
void printInitState()
{
Serial.println("initTest");
Serial.println("SM0INTEN: ");
for(int x = 15; x >= 0; --x)
{
Serial.print(bitRead(FLEXPWM2_SM0INTEN, x));
}
Serial.println();
Serial.println("SM0CTRL: ");
for(int x = 15; x >= 0; --x)
{
Serial.print(bitRead(FLEXPWM2_SM0CTRL, x));
}
Serial.println();
}
void setup() {
pinMode(9,OUTPUT);
digitalWrite(9,LOW);
Serial.begin(115200);
Serial.println("Begin");
setOutputFrequency(40000.0);
setOutputPWM(trap1->period/2,trap1->period/2,0,trap1->period,trap1->period/4,trap1->period*3/4);
initTest();
printInitState();
delay(500);
trap1->dutyRamp = 1;
attachInterruptVector(IRQ_FLEXPWM2_0, valArampUpISR);
NVIC_ENABLE_IRQ(IRQ_FLEXPWM2_0);
delay(500);
FLEXPWM2_SM0INTEN &= ~0x1000;
NVIC_DISABLE_IRQ(IRQ_FLEXPWM2_0);
clearInterrupt();
attachInterruptVector(IRQ_FLEXPWM2_0,valBrampDownISR);
NVIC_ENABLE_IRQ(IRQ_FLEXPWM2_0);
FLEXPWM2_SM0INTEN |= 0x1000;
}
void loop() {
// put your main code here, to run repeatedly:
}
As you can see, the RF flag is not only set many times a pwm period, but the frequency at which it is set is dependent on the Clock rate. The program sets the Prescaler such that the pwm period is ~40 kHz regardless of the clock frequency. Even when I set a 1kHz pwm period, the reload flag is set at the same frequency (resulting in hundreds of ISRs every pwm period).
Thank you for any help, I would love to find out that this is my own doing and not a problem with the Teensy Platform.
For reference the links to my previous posts can be found here:
https://forum.pjrc.com/threads/70640-trouble-attaching-consecutive-ISRs-to-the-same-FLEXPWM-IRQ
https://forum.pjrc.com/threads/70644-T4-1-attachInterruptVector()-and-NVIC-Controller