|
|
View previous topic :: View next topic |
Author |
Message |
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
PIC24EP interrupt_active with INTR_CN_PIN not working? |
Posted: Tue Dec 05, 2017 9:46 am |
|
|
Device: PIC24EP512GP806
Compiler: 5.026
I'm using a bunch of external interrupts -- all the INT_EXT0 to 4 -- and also using three others with INTR_CN_PIN.
After 1 minute of inactivity, the circuit goes to sleep and can only wake-up via external interrupts.
When an interrupt wakes-up the unit, the code calls interrupt_active( _interrupt_ ) for each interrupt like this:
Code: |
fprintf( MONITOR_SERIAL, "\n\rINT_CN_PIN 1: %d", interrupt_active( INTR_CN_PIN | MY_CN_PIN_1 ));
fprintf( MONITOR_SERIAL, "\n\rINT_CN_PIN 2: %d", interrupt_active( INTR_CN_PIN | MY_CN_PIN_2 ));
fprintf( MONITOR_SERIAL, "\n\rINT_CN_PIN 3: %d", interrupt_active( INTR_CN_PIN | MY_CN_PIN_3 ));
fprintf( MONITOR_SERIAL, "\n\rINT_EXT0 : %d", interrupt_active( INT_EXT0 ));
fprintf( MONITOR_SERIAL, "\n\rINT_EXT1 : %d", interrupt_active( INT_EXT1 ));
fprintf( MONITOR_SERIAL, "\n\rINT_EXT2 : %d", interrupt_active( INT_EXT2 ));
fprintf( MONITOR_SERIAL, "\n\rINT_EXT3 : %d", interrupt_active( INT_EXT3 ));
fprintf( MONITOR_SERIAL, "\n\rINT_EXT4 : %d", interrupt_active( INT_EXT4 )); |
So when the unit is externally triggered, I am expecting to see which interrupt woke-up the unit.
What happens is the following: for all of the INT_EXT0-4, I will see a '1' in the fprintf statement for the external interrupt that generated the interrupt.
So if INT_EXT0 is triggered, then the fprintf will look like this:
INT_CN_PIN 1: 0
INT_CN_PIN 2: 0
INT_CN_PIN 3: 0
INT_EXT0 : 1
INT_EXT1 : 0
INT_EXT2 : 0
INT_EXT3 : 0
INT_EXT4 : 0
But for the three CN interrupts, let's say CN_PIN2 wakes-up the unit (because the interrupt _does_ wake-up the unit as expected), the fprintf _does not_ print a '1' for the interrupt that got triggered and the output is like this:
INT_CN_PIN 1: 0
INT_CN_PIN 2: 0 <-- Shouldn't it be a '1' here?
INT_CN_PIN 3: 0
INT_EXT0 : 0
INT_EXT1 : 0
INT_EXT2 : 0
INT_EXT3 : 0
INT_EXT4 : 0
So should I be using 'interrupt_active' on CN interrupt pins? Should this work?
I'm sure it's something silly I missed but I can't seem to figure it out.
Thanks,
Ben |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Tue Dec 05, 2017 12:36 pm |
|
|
Interrupt_active, can only test for the actual interrupt.
The pin number is not an interrupt. It is a mask fed into the interrupt setup to determine which pins can trigger the actual interrupt.... |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Tue Dec 05, 2017 12:49 pm |
|
|
So I have changed the line to the following:
Code: | fprintf( MONITOR_SERIAL, "\n\rINT_CN_PIN: %d", interrupt_active( INTR_CN_PIN )); |
and it still prints '0'.
All others will display a '1' if triggered but that one just returns '0', regardless, although it triggers just fine.
[EDIT] Also, I presume that I use the PIN mask when disabling one of the CN pins, correct? What about the 'clear_interrupt()' function? Should I pass the pin mask or not?
Any information is appreciated.
Thanks,
Ben |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Wed Dec 06, 2017 8:12 am |
|
|
Anyone? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Wed Dec 06, 2017 8:23 am |
|
|
OK, I'll take a stab even though I don't use that PIC but heck maybe this will work ??
re:
Quote: |
fprintf( MONITOR_SERIAL, "\n\rINT_CN_PIN 1: %d", interrupt_active( INTR_CN_PIN | MY_CN_PIN_1 )); |
What if you printout the entire register that holds the INTR_CN_PINs ? Whatever the register is called that holds the 'status' of those pins.
Also... have a look at the listing to confirm the correct register IS being accessed by the compiler? Maybe a bug is reading the wrong register ?
Like I said, just thinking out loud here. Maybe you've done all this but....
worth a shot ??
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Wed Dec 06, 2017 8:45 am |
|
|
Yours is a very early compiler.
Doing a very basic test:
Code: |
int1 test;
enable_interrupts(INTR_CN_PIN | PIN_G6);
while(TRUE)
{
test=interrupt_active(INTR_CN_PIN);
}
|
Then looking at the assembler:
Code: |
.................... enable_interrupts(INTR_CN_PIN | PIN_G6);
00218: BSET.B E68.6 //CNIEG6 bit set.
0021A: BSET.B 822.3 //CNIE set
....................
....................
....................
....................
.................... while(TRUE)
.................... {
.................... test=interrupt_active(INTR_CN_PIN);
0021C: BCLR.B 1002.0 //clears 'test'
0021E: BTSC.B 7FC.0 //Uurgh should be testing 0x802.3......
00220: BSET.B 1002.0 //sets 'test' if this is set.
00222: GOTO 21C
|
It is testing the wrong bit for CNIF.
So code a work-around as:
Code: |
#BIT CNIF=getenv("BIT:CNIF")
|
Then just test CNIF instead of using interrupt_active. Also clear the interrupt by setting CNIF=FALSE;
Clear interrupts is also accessing the wrong register.
Report it to CCS, and they may provide you with a new devices file to fix it. The other interrupts seem largely to be right, on a quick test. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Wed Dec 06, 2017 8:52 am |
|
|
Hi Jay,
Thanks for the help. I may have found a solution that seems to be working and that's what I'm testing out at the moment.
As TTelmah said, I can't call interrupt_active with the pin mask in the function - I can only pass the interrupt mask - and that makes sense (although it would have been nice from CCS to implement that). Then I tried <interrupt_active( INTR_CN_PIN );> but that still returns '0' and obviously it's not helping.
Again, this scenario is only when the MCU is waking-up from sleep.
So rather than relying on the <interrupt_active()> function to return if a CN interrupt got triggered, given that the MCU can *only* wake-up on an interrupt (all five EXT_INT and two CN_INT), the first thing I do is check all the EXT_INT interrupts with interrupt_active() because these have precedence on the CN interrupts.
If none of the EXT_INT interrupts got triggered, then it means that a CN interrupt got fired in which case I read both inputs using input( pin_name) and check which one changed.
It's working well, thanks for your input though, it's appreciated.
Benoit |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1355
|
|
Posted: Wed Dec 06, 2017 9:08 am |
|
|
benoitstjean wrote: | As TTelmah said, I can't call interrupt_active with the pin mask in the function - I can only pass the interrupt mask - and that makes sense (although it would have been nice from CCS to implement that). |
Just some things to consider:
I didn't look at that particular chip's data sheet, but the PIC24's I have used don't generally provide that flag for individual CN pins and only provide the general CN interrupt active flag. If your particular chip is similar then there really isn't anything CCS can do. Without hardware support, the runtime code has no knowledge of who tripped the interrupt, just that the interrupt was triggered. Even if they check the pins to see which have different values, due to the (relatively) time consuming interrupt handling process, the states may have changed and the current values could be wrong. It's a very tough problem without proper hardware support.
Now if your chip does supply separate interrupt active flags for each pin, then yes, it would definitely be a nice feature. I didn't check the datasheet to confirm though. If it does, definitely email CCS support requesting it. It would be a welcome addition. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Wed Dec 06, 2017 9:14 am |
|
|
Yes.
On some chips they do already give this on recent compiler versions. It depends on the masks that are actually triggered and available. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Wed Dec 06, 2017 9:15 am |
|
|
Hi Ttelmah,
Thanks for digging into this that deep.
I have 5.026, 5.069 and 5.071 but there appears to be a bug or a change introduced somewhere between 5.026 and 5.071 in the area of RAM and ROM space calculations and caused some grief when compiling for the HJ versions. I spent many days with CCS trying to figure-out what was the problem and I don't remember exactly what the outcome was and I'd have re-read all emails exchanged with CCS support.
All in all, along the road, I changed from the PIC24HJ to the PIC24EP but because I still have units with one PIC and other units with the newer PICs, compiling the HJ code in 5.071 was not possible due to the changes introduced with the RAM and ROM calculations (e.g. the code compiled fine with 5.026 but failed with 'out-of-rom' or something on newer versions) so I had to stick with 5.026.
However, the 5.071 IDE contains a feature not available in 5.026 and that's the __BUILDCOUNT__ option. So what CCS got me to do was to use the 5.071 IDE with the 5.026 PCB/PCM/PCH and PCD.
I think that when I compiled the HJ code in 5.026, the RAM was around 88% and ROM around 92% and all worked fine. Then, compiling the exact same code in 5.069 / 5.071 failed with the out-of-rom or something. So although it compiled fine with 5.026, compiling the exact same code for the EP MCU in 5.071 was clearly exceeding the RAM and ROM space of the HJ PICs (e.g. if it was 92% ROM on the HJ, I would have expected it to be around 46% on the EP but it was like 52%). Then compiling the code for the EP version on 5.026 showed a much lower RAM and ROM usage than when it is compiled in 5.071.
All this to say that I am not using the most recent compiler because of the the RAM and ROM calculation issues which are consistent between MCU/compiler versions and I am currently using a butchered compiler.
Benoit |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Tue Dec 12, 2017 8:16 am |
|
|
I guess I have another question on the INT_CN interrupt:
When you enable it, you do this:
enable_interrupts( INTR_CN_PIN | PIN_xx );
Since <interrupt_active( int_xx )> function requires only the interrupt mask, when you clear it and disable it, do you need to specify the mask like this:
clear_interrupt( INTR_CN_PIN | PIN_xx );
disable_interrupts( INTR_CN_PIN | PIN_xx );
Or is it like this:
clear_interrupt( INTR_CN_PIN );
disable_interrupts( INTR_CN_PIN );
I can always send an email to CCS also but if the answer is here, then everyone will benefit from it.
Thanks again,
Ben |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Tue Dec 12, 2017 8:37 am |
|
|
That actually depends on the chip, and the age of the compiler.
On _some_ chips, there is a separate flag set for each pin, though still only one physical interrupt. On these, including the pin number will also clear this flag (on recent compilers).
The interrupt flag itself is always cleared without needing the pin specification.
Though remember that like the old PortB change interrupt the flag will reset immediately unless the pin has been read. It is the act of 'reading' that copies the pin to the latch used for change, so until the pin is read the flag will keep resetting. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|