chipKIT® Development Platform

Inspired by Arduino™

Change notification on MX250

Created Thu, 29 Jan 2015 21:40:27 +0000 by majenko


majenko

Thu, 29 Jan 2015 21:40:27 +0000

Ok, so I have been fighting with this all evening, and while I am usually the one who gives the answers, this time it's me asking for answers ;)

I am trying to get Change Notification working on the MX250 etc chips. But it just won't trigger the interrupt.

At the moment I'm trying to get things going manually, before it all gets wrapped up in my DebouncedInput class. Everything works, but the damn interrupt just won't fire. I know the change notification side of things is working fine, since the interrupt flag is being set.

Here's my CN setup code:

ANSELACLR = 1<<3;
	TRISASET = 1<<3;
	CNPUASET = 1<<3;
	CNENASET = 1<<3;
	CNCONASET = 1<<15;

	clearIntFlag(_CHANGE_NOTICE_A_IRQ);
	setIntVector(_CHANGE_NOTICE_VECTOR, isr);
	setIntEnable(_CHANGE_NOTICE_A_IRQ);
	setIntPriority(_CHANGE_NOTICE_A_IRQ, 6, 0);

The button is on A3.

The ISR is simply:

void __attribute__((interrupt)) isr() {
	(void)PORTA;
	LATBINV = 1<<13;
	clearIntFlag(_CHANGE_NOTICE_A_IRQ);
}

B13 is an LED and set to output.

If I do some debugging by printing the relevant register values etc I get:

CNENA = 8
CNCONA = 8000
CNAIE = 1
CNAIF = 0
Address of ISR: 0x9D004100
Address of vec: 0x9D004100

So everything seems to be being set right.

If I examine the CNSTATA register in loop with this:

void loop() {
	static int v = CNSTATA;

	if (v != CNSTATA) {
		v = CNSTATA;
		Serial.println(v, HEX);
		Serial.print("CNAIF: ");
		Serial.println(IFS1bits.CNAIF, DEC);
		Serial.print("CNAIE: ");
		Serial.println(IEC1bits.CNAIE, DEC);
		(void)PORTA;
	}
}

then I can see the CN status changing as I press the button:

8
CNAIF: 1
CNAIE: 1
0
CNAIF: 1
CNAIE: 1

So the change notification is being detected, and the interrupt flag is being set.

Yet the interrupt doesn't trigger.

However - if I attach the interrupt to a timer with no changes other than to add the clearing of the timer interrupt flag, the LED flashes merrily away - so the ISR itself is working fine.

So it's like there's some extra register I need to set to globally enable change notification interrupts, but there is no such register as far as I can see.

So what am I doing wrong...?!

Here's my test code in full:

void __attribute__((interrupt)) isr() {
	(void)PORTA;
	LATBINV = 1<<13;
	clearIntFlag(_CHANGE_NOTICE_A_IRQ);
	clearIntFlag(_TIMER_2_IRQ);		
}

void setup() {
	Serial.begin(9600);
	pinMode(PIN_LED1, OUTPUT);	
	ANSELACLR = 1<<3;
	TRISASET = 1<<3;
	CNPUASET = 1<<3;
	CNENASET = 1<<3;
	CNCONASET = 1<<15;

	clearIntFlag(_CHANGE_NOTICE_A_IRQ);
	setIntVector(_CHANGE_NOTICE_VECTOR, isr);
	setIntEnable(_CHANGE_NOTICE_A_IRQ);
	setIntPriority(_CHANGE_NOTICE_A_IRQ, 6, 0);

	TRISBCLR = 1<<13;

	while(!Serial);
	delay(1000);
	Serial.print("CNENA = ");
	Serial.println(CNENA, HEX);
	Serial.print("CNCONA = ");
	Serial.println(CNCONA, HEX);
	Serial.print("CNAIE = ");
	Serial.println(IEC1bits.CNAIE, DEC);
	Serial.print("CNAIF = ");
	Serial.println(IFS1bits.CNAIF, DEC);
	Serial.print("Address of ISR: 0x");
	Serial.println((uint32_t)&isr, HEX);
	Serial.print("Address of vec: 0x");
	Serial.println((uint32_t)getIntVector(_CHANGE_NOTICE_VECTOR), HEX);
}

void loop() {
	static int v = CNSTATA;

	if (v != CNSTATA) {
		v = CNSTATA;
		Serial.println(v, HEX);
		Serial.print("CNAIF: ");
		Serial.println(IFS1bits.CNAIF, DEC);
		Serial.print("CNAIE: ");
		Serial.println(IEC1bits.CNAIE, DEC);
		(void)PORTA;
	}
}

dangeljs

Fri, 30 Jan 2015 03:38:10 +0000

This may be a silly question, but do you need to set the sub-priorty level to something other than zero? For example:

setIntPriority(_CHANGE_NOTICE_A_IRQ, 6, 1);

Reading in the datasheet it says setting to 0 turns it off, but it didn't seem explicit to me whether that was only the group priority or the sub-priority.


lstandage

Fri, 30 Jan 2015 06:01:28 +0000

Would you post the basic schematic for your setup? Are you using a crystal, because I'm not sure how to use RA3 as an I/O pin when it is an oscillator pin.


majenko

Fri, 30 Jan 2015 09:44:35 +0000

It's using an external clock module (SI501, 8MHz), and RA3 functions perfectly fine as a normal input pin. As I mentioned, the state-change is reported completely correctly. If I examine RA3 manually I can read the state of the button.

I'll attach another button to another IO pin and see if that works or not - see if it's something specific to RA3, though I doubt it will be since the actual change notification itself is working correctly.

The basic schematic is clock on CLKI, button on RA3 to ground (internal pullup enabled), and LED on B13 with 100Ω resistor to ground (also all the other standard ancillary components)

I have never used anything but SPL = 0 for any other interrupts (never had any need to subdivide the priorities). It's only IPL = 0 that disables the interrupt. The timer I attached to the ISR had SPL = 0 and worked perfectly.


dangeljs

Fri, 30 Jan 2015 12:46:39 +0000

Could you print IPC8 to the console to ensure that the priorties are being set. Perhaps there is something in the header that is assigning your priority values to the wrong address.


majenko

Fri, 30 Jan 2015 13:21:53 +0000

dangeljs, you're a marvel!

You hit the nail on the head - well, close enough anyway.

It was entirely my fault, not the headers, but it was the priority not being set. And why?

Because you set it on the vector, not the IRQ.

I had

setIntPriority(_CHANGE_NOTICE_A_IRQ, 6, 0);

when I should have had: setIntPriority(_CHANGE_NOTICE_VECTOR, 6, 0); [/code]

Really that function should be named setVectorPriority not setIntPriority since you're setting it on the vector not the interrupt.


madias

Sun, 01 Feb 2015 22:55:17 +0000

Really that function should be named setVectorPriority not setIntPriority since you're setting it on the vector not the interrupt.

+1 for this. Made me crazy more than once.