Port interrupt problems on ATX256A3

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am trying to use the port interrupts to sense the falling edge from an off-chip ADC data ready signal (DRDY active low) that indicates the data is ready to read by SPI.

My interrupt never triggers. I can see the data ready signal with a falling edge on an oscilloscope.

Any help is appreciated.

// SPI configured previously
// Enable interrupts.
	PMIC.CTRL |= PMIC_MEDLVLEN_bm;
	sei();

	// Set IO12 (PF1) to output and configure as pull up
	PORTF.DIRSET = PIN1_bm;
	PORTF.PIN1CTRL = PORT_OPC_WIREDANDPULL_gc;
	PORTF.OUTSET = PIN1_bm;

	// Configure IO13 (PF0) to capture ADC DRDY signal
	PORTF.DIRCLR = PIN0_bm;
	PORTF.PIN0CTRL = PORT_ISC_FALLING_gc;
	PORTF.INTCTRL = PORT_INT1LVL_MED_gc;
	PORTF.INT1MASK = PIN0_bm;
			
	

		
	// Configure clock for AD7767 MCLK to 128Hz
	// f_MCLK(128Hz) = f_PER(2^21Hz) / (period (2^14-1Hz) + 1)
	// Set IO14 (PE5) to output
	PORTE.DIRSET = PIN5_bm;
	// Set Waveform generator mode and enable the CCx output to IO14 (PE5)
	TCE1.CTRLB = TC_WGMODE_SS_gc | TC1_CCBEN_bm;
	// set period
	TCE1.PER = 0x3FFF;  // 0x3FFF for 128Hz
	TCE1.CCBBUF = 0x1FFF;  // 0x1FFF for 128 Hz
	// Set oscillator source and frequency and start
	TCE1.CTRLA = ( TCE1.CTRLA & ~TC1_CLKSEL_gm ) | TC_CLKSEL_DIV1_gc;
	
	sampleCount = 0;

	
	// wait for ADC to collect samples
	while(sampleCount < NUM_SAMPLES);
	
	// turn off timer and interupts
	TCE1.CTRLA = ( TCE1.CTRLA & ~TC1_CLKSEL_gm ) | TC_CLKSEL_OFF_gc;
	PMIC.CTRL &= ~PMIC_MEDLVLEN_bm;	
	cli();

ISR(PORTF_INT1_vect) {

	// collect data from offchip ADC using SPI
	sampleCount++;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PORTF.INT1MASK = 0x01;
PORTF.INTCTRL = PORT_INT1LVL_MED_gc;

I don't know if the order of those 2 lines matter. Your setup for falling is right, I guess you're using the PORTF0 pullup ? Does the ISR vector show up in the *.lss ? I would test with a active low switch/wire to gnd. for now. When it's high, is the pin 3.3 V and 0V when gnd'ed ?

I still can't find the diff. between an interrupt0 and interrupt1 types in d.sht. I made mine work, rising, using interrupt type 0 ( xmega16A4 ).

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The voltage is 0V low and 3.3V high.

The ISR shows up in the .lss file (twice?)

ISR(PORTF_INT0_vect) {
     324:	1f 92       	push	r1
     326:	0f 92       	push	r0
     328:	0f b6       	in	r0, 0x3f	; 63
     32a:	0f 92       	push	r0
     32c:	0b b6       	in	r0, 0x3b	; 59
     32e:	0f 92       	push	r0
     330:	11 24       	eor	r1, r1
     332:	2f 93       	push	r18
     334:	3f 93       	push	r19
     336:	4f 93       	push	r20
     338:	5f 93       	push	r21
     33a:	6f 93       	push	r22
     33c:	7f 93       	push	r23
     33e:	8f 93       	push	r24
     340:	9f 93       	push	r25
     342:	af 93       	push	r26
     344:	bf 93       	push	r27
     346:	ef 93       	push	r30
     348:	ff 93       	push	r31
	// collect data from offchip ADC
	/* Instantiate pointer to ssPort. */
	SPI_MasterSSLow(&PORTC, PIN4_bm);  // enable SPI_SS
     34a:	80 e1       	ldi	r24, 0x10	; 16
     34c:	e0 e4       	ldi	r30, 0x40	; 64
     34e:	f6 e0       	ldi	r31, 0x06	; 6
     350:	86 83       	std	Z+6, r24	; 0x06
	PORTF.OUTCLR = PIN1_bm; // pull ADC_CS down to enable data read
     352:	82 e0       	ldi	r24, 0x02	; 2
     354:	e0 ea       	ldi	r30, 0xA0	; 160
     356:	f6 e0       	ldi	r31, 0x06	; 6
     358:	86 83       	std	Z+6, r24	; 0x06
     35a:	e3 e0       	ldi	r30, 0x03	; 3
     35c:	f0 e2       	ldi	r31, 0x20	; 32
	for(uint8_t bufIndex = 0; bufIndex < 3; bufIndex++) {
		SPIC.DATA = 0xFF; // dummy data to start SPI clock
     35e:	a0 ec       	ldi	r26, 0xC0	; 192
     360:	b8 e0       	ldi	r27, 0x08	; 8
     362:	9f ef       	ldi	r25, 0xFF	; 255
     364:	13 96       	adiw	r26, 0x03	; 3
     366:	9c 93       	st	X, r25
     368:	13 97       	sbiw	r26, 0x03	; 3
		while(!(SPIC.STATUS & SPI_IF_bm));
     36a:	80 91 c2 08 	lds	r24, 0x08C2
     36e:	87 ff       	sbrs	r24, 7
     370:	fc cf       	rjmp	.-8      	; 0x36a <__vector_104+0x46>
		SPIBuffer[bufIndex] = SPIC.DATA;
     372:	80 91 c3 08 	lds	r24, 0x08C3
     376:	81 93       	st	Z+, r24
ISR(PORTF_INT0_vect) {
	// collect data from offchip ADC
	/* Instantiate pointer to ssPort. */
	SPI_MasterSSLow(&PORTC, PIN4_bm);  // enable SPI_SS
	PORTF.OUTCLR = PIN1_bm; // pull ADC_CS down to enable data read
	for(uint8_t bufIndex = 0; bufIndex < 3; bufIndex++) {
     378:	80 e2       	ldi	r24, 0x20	; 32
     37a:	e6 30       	cpi	r30, 0x06	; 6
     37c:	f8 07       	cpc	r31, r24

I changed the order of the lines and changed PORTF0 to input pullup (it was totem w/o pullup). I also changed it to interrupt0 instead just to see if it made a difference. All these changes had no effect.

Here is the revised code:

	// Enable interrupts.
	PMIC.CTRL |= PMIC_MEDLVLEN_bm;
	sei();

	// Set IO12 (PF1) to output and configure as pull up
	PORTF.DIRSET = PIN1_bm;
	PORTF.PIN1CTRL = PORT_OPC_WIREDANDPULL_gc;
	PORTF.OUTSET = PIN1_bm;

	// Configure IO13 (PF0) to capture ADC DRDY signal
	PORTF.DIRCLR = PIN0_bm;
	PORTF.PIN0CTRL = PORT_ISC_FALLING_gc | PORT_OPC_PULLUP_gc;
	PORTF.INT0MASK = PIN0_bm;
	PORTF.INTCTRL = PORT_INT0LVL_MED_gc;
	
			
	

		
	// Configure clock for AD7767 MCLK to 128Hz
	// f_MCLK(128Hz) = f_PER(2^21Hz) / (period (2^14-1Hz) + 1)
	// Set IO14 (PE5) to output
	PORTE.DIRSET = PIN5_bm;
	// Set Waveform generator mode and enable the CCx output to IO14 (PE5)
	TCE1.CTRLB = TC_WGMODE_SS_gc | TC1_CCBEN_bm;
	// set period
	TCE1.PER = 0x3FFF;  // 0x3FFF for 128Hz
	TCE1.CCBBUF = 0x1FFF;  // 0x1FFF for 128 Hz
	// Set oscillator source and frequency and start
	TCE1.CTRLA = ( TCE1.CTRLA & ~TC1_CLKSEL_gm ) | TC_CLKSEL_DIV1_gc;
	
	sampleCount = 0;

	
	// wait for ADC to collect samples
	while(sampleCount < NUM_SAMPLES);
	
	// turn off timer and interupts
	TCE1.CTRLA = ( TCE1.CTRLA & ~TC1_CLKSEL_gm ) | TC_CLKSEL_OFF_gc;
	PMIC.CTRL &= ~PMIC_MEDLVLEN_bm;	
	cli();

	// collect average, max and min of SP samples
	for (sampleCount = 0; sampleCount < NUM_SAMPLES; sampleCount++) {
		sum += SPData[sampleCount];
		if (max < SPData[sampleCount]) { max = SPData[sampleCount];}
		if (min > SPData[sampleCount]) { min = SPData[sampleCount];}
	}
	average = sum / NUM_SAMPLES;

	//convert to mV
	*avgV = (average * ADC_VREF / ADC_MAX);
	*maxV = (max * ADC_VREF / ADC_MAX);
	*minV = (min * ADC_VREF / ADC_MAX);

	ADCPower(FALSE);

}

ISR(PORTF_INT0_vect) {
	// collect data from offchip ADC

Any more ideas? I appreciate your input.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Limited asynch sense mode, falling, won't trigger an ISR() ( I'm not saying you're in that mode, but that may be it. ). Function name appearing 2X in the *.lss happens with GCC compiler, I don't know why. What I meant about that was at the beginning of the .lss file where the vector tables are shown ( but it's in there so ok ) . Sei() should be one of the LAST things you do before the program starts.

My setup is just like yours, EXCEPT I left the input pin in it's default POR state ( so no pullup ). Other than that mine is for PORTC, pin2. So it's not that part of your code. ON the side, you're doing ALOT in your ISR(). I'd get it lean if I were you. Set a volatile flag in ISR() and do stuff in main().

Do you have other ISR()s ? I'd do a :
turn_on_led;
while(1);

as a debug step at the top of the ISR(), until it's fixed. Stick with the PORTF.0 setup the way it is for now, 'cause that's what I know.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

Last Edited: Thu. Jun 16, 2011 - 12:10 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Any chance you are trying to wake up from sleep? According to AVR1313, only Pin2 on any port can asynchronously trigger rising or falling level interrupts. All other pins only support BothEdges or LowLevel sense.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Solved.

To answer the questions, I was not waking from sleep so the sampling was in synchronous mode.

SOLUTION
The code was correct. The issue was that my data ready signal was fairly short duration (~250ns) and the edge detection must be with a software emulated flip flop so it requires at least one sample high. I upped the peripheral clock to 16MHz so there are several samples high and it detects the falling edge now. The data sheet contains a reference to this. I guess I should have followed the adage "if all else fails, read the instructions"

Thank you for all of your input.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Great that you got it working, but that you were trying to wake it was needed info in your OP ( next time... ).

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1