trouble attaching consecutive ISRs to the same FLEXPWM IRQ

tomryan

Member
Hello, this is my first post here. I'm working on a Teensy 4.1 board with the Arduino IDE.

I am testing out the FLEXPWM2 module, submodules 0&1. I am testing symmetrically ramping the pwm duty cycle of the different submodules at every reload opportunity with the IRQ_FLEXPWM2_0 (137) vector. My trouble is that upon attaching my first ISR (valArampUpISR) it runs fine, but the second ISR (valBrampDown) never runs. I don't really understand the attachInterruptVector() fx. My setup is correct enough that the initial duty cycles are correct. For reference <D0,D1,D2> corresponds to channels <A,B,C>.

New.png

The ramp up on Channel A also occurs correctly:
Newr.png

*Note* the attachInterruptVector() and NVIC_ENABLE_IRQ() fxs are called in setup which is where I think my error is. My code is as follows:

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;
  
};

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; //clear interrupt flag
}

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);
    }
    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)0x0804; //Full cycle reloads, enable LDMOD for instant reloads
    FLEXPWM2_SM1CTRL |= (uint16_t)0x0804;

    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 setup() {
  // put your setup code here, to run once:
setOutputFrequency(40000.0);
setOutputPWM(trap1->period/2,trap1->period/2,0,trap1->period,trap1->period/2,trap1->period);
initTest();

delay(500);

trap1->dutyRamp = 1;
attachInterruptVector(IRQ_FLEXPWM2_0, valArampUpISR);
NVIC_ENABLE_IRQ(IRQ_FLEXPWM2_0);

delay(500);

NVIC_DISABLE_IRQ(IRQ_FLEXPWM2_0);
FLEXPWM2_SM0INTEN &= ~0x1000; //disable the interrupt flag upon reload opportunity
clearInterrupt(); //clear the interrupt flag
attachInterruptVector(IRQ_FLEXPWM2_0,valBrampDownISR);
FLEXPWM2_SM0INTEN |= 0x1000; //re-enable the interrupt flag
NVIC_ENABLE_IRQ(IRQ_FLEXPWM2_0);
}


void loop() {
  // put your main code here, to run repeatedly:

}

Thank you for any help!
 
Back
Top