FTM and DMA interrupt seem to be triggering continuously

Status
Not open for further replies.

hmpws

Member
In my code the DMA interrupt seems to be triggering all the time even though I had it on a rising edge input capture (which is only triggered once, confirmed by measuring with a scope.

Some of the relevant codes are:
Code:
#include <DMAchannel.h>

FASTRUN void INT_ISR() {
	// check timer overflow
	if ((FTM1_SC & FTM_SC_TOF) != 0) { //read the timer overflow flag (TOF in FTM1_SC)
		FTM1_SC &= ~FTM_SC_TOF; //if set, clear overflow flag
		ftmCounterOVF++; //increment overflow counter
	}
	if ((FTM1_C1SC & FTM_CSC_CHF) != 0) { //look for CH1 event flag
		FTM1_C1SC &= ~FTM_CSC_CHF; //clear CH1 event flag
	}
	timerOvfBuffer= ftmCounterOVF;
	timerCounterBuffer = ftmCounterVal;
	Serial.print(timerOvfBuffer);
	Serial.print(" ");
	Serial.println(timerCounterBuffer);
}

void setup() {
	// configure FTM1
	FTM1_MODE = 0x05; //set write-protect disable (WPDIS) bit to modify other registers
	FTM1_SC = 0x00; //set status/control to zero = disable all internal clock sources
	FTM1_MOD = 0xFFFF; // overflow when maximum value reached
	FTM1_C1SC = 0x45; // CHF=0, CHIE=1 (has to be enabled for DMA), MSB=0, MSA=0, ELSB=0 ELSA=1 (input capture - rising edge), 0, DMA=1	
	// configure pins
	PORTB_PCR0 |= 0x600; //MUX = alternative function 6 on PTB0 (FTM1_QD_PHA)
	PORTA_PCR13 |= 0x700; //MUX = alternative function 7 on PTA13 (FTM1_QD_PHB)
	PORTB_PCR1 |= 0x300; //MUX = alternative function 3 on PTB1 (FTM1_CH1)
	// set to quadrature mode
	FTM1_QDCTRL = 0x0F; // count up on rising edge when PHB is high, see pg. 1186
	// reset counter values
	ftmCounterOVF = 0;
	FTM1_CNT = 0x0000; //reset count to zero
	// configure DMA channel to move timer value
	dma.source(*(uint32_t*)&(FTM1_C1V));
	dma.destination(*(uint16_t*)&(ftmCounterVal));
	dma.transferSize(2);
	dma.transferCount(1);
	dma.interruptAtCompletion();
	dma.attachInterrupt(INT_ISR);
	dma.triggerAtHardwareEvent(DMAMUX_SOURCE_FTM1_CH1);
	dma.enable();
}


The same number keeps getting printed even though it should only occur once. Do I have to use dma.clearComplete() or something similar?

Thanks.
 
I made a test case. Please connect pin 11 to 17. I couldn't find the edit button, sorry!

Code:
/*
	Test FTM input capture interrupt
	pin 11 (input) -> pin 17 (FTM)
*/

#include <DMAChannel.h>

static DMAChannel dma;
volatile uint16_t ftmCounterOVF = 0;
volatile uint16_t ftmCounterVal = 0;

void INT_ISR() {
	Serial.println("Got here!");
	//DMA_CINT = DMA_CINT_CAIR; // clear all dma int
	dma.clearInterrupt();
}

void setup()
{
	Serial.begin(115200);
	delay(5000);
	Serial.println("Starting...");
	
	// setting up pins
	pinMode(11, OUTPUT);
	digitalWriteFast(11, 0);
	
	// *** set up timer for counting square wave ***
	// configure FTM1
	FTM1_MODE = 0x05; //set write-protect disable (WPDIS) bit to modify other registers
	FTM1_SC = 0x00; //set status/control to zero = disable all internal clock sources
	FTM1_MOD = 0xFFFF; // overflow when maximum value reached
	FTM1_C1SC = 0x45; // CHF=0, CHIE=1 (has to be enabled for DMA), MSB=0, MSA=0, ELSB=0 ELSA=1 (input capture - rising edge), 0, DMA=1
	// configure pins
	PORTB_PCR0 |= 0x600; //MUX = alternative function 6 on PTB0 (FTM1_QD_PHA)
	PORTA_PCR13 |= 0x700; //MUX = alternative function 7 on PTA13 (FTM1_QD_PHB)
	PORTB_PCR1 |= 0x300; //MUX = alternative function 3 on PTB1 (FTM1_CH1)
	// set to quadrature mode
	FTM1_QDCTRL = 0x0F; // count up on rising edge when PHB is high, see pg. 1186
	// reset counter values
	ftmCounterOVF = 0;
	FTM1_CNT = 0x0000; //reset count to zero
	// configure DMA channel to move timer value
	dma.source(*(uint32_t*)&(FTM1_C1V));
	dma.destination(*(uint16_t*)&(ftmCounterVal));
	dma.transferSize(2);
	dma.transferCount(1);
	dma.attachInterrupt(INT_ISR);
	dma.interruptAtCompletion();
	dma.triggerAtHardwareEvent(DMAMUX_SOURCE_FTM1_CH1);
	dma.enable();
	
	// Try input capture
	digitalWriteFast(11, 1);
	//dma.triggerManual();
	Serial.print(dma.complete());
	Serial.print(" ");
	Serial.println(ftmCounterVal);
	delay(1000);
	Serial.print(dma.complete());
	Serial.print(" ");
	Serial.println(ftmCounterVal); // need to connect another signal source to pin 4 and 16
}

void loop()
{

}

On further inspection, it seems that the FTM has nothing with this at all. The ISR just keep running even when the channel is triggered manually.

I solved the problem by clearing the interrupt flag (pg. 545 of manual)! DMA_CINT = DMA_CINT_CAIR; // clear all dma int

How would I go about clearing the flag using DMAChannel? I find the dma.clearInterrupt()!

Thanks for the great library!

Edit: I have tidied my test case in case someone find this useful.
 
Last edited:
Status
Not open for further replies.
Back
Top