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>.
The ramp up on Channel A also occurs correctly:
*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:
Thank you for any help!
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>.
The ramp up on Channel A also occurs correctly:
*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!