|
|
View previous topic :: View next topic |
Author |
Message |
tssir
Joined: 14 Feb 2016 Posts: 24
|
Interruption loops ... despite flag clear |
Posted: Wed Sep 07, 2016 3:10 pm |
|
|
Hello,
My interruption handler loops. Despite interruption flag clearing code is presents.
Compiler version 5.043
PIC16F1705, standard run mode at 3.3V
My test code :
Code: |
#include <16F1705.h>
#fuses INTRC_IO,WDT_SW,NOPUT,NOMCLR,PROTECT,BROWNOUT,BORV25,NOCLKOUT,NOIESO,NOFCMEN,NOWRT,NOPPS1WAY,NOZCDDIS,NOPLLEN,NOSTVREN,NOLPBOR,NODEBUG,NOLVP
#use delay(clock=32MHZ)
#USE fast_io(A)
#USE fast_io(C)
#define IO_LED PIN_A2
#define TRIS_A (0b00010011)
#define PULLUPS_A (0b00010011)
#define TRIS_C (0b00011111)
#define PULLUPS_C (0b00011111)
// --------------------------------------------------------------------------------------
#define LED_OFF TRUE
#define LED_ON FALSE
// --------------------------------------------------------------------------------------
unsigned int8 i;
// --------------------------------------------------------------------------------------
#byte IOCAF=getenv("SFR:IOCAF")
#byte IOCCF=getenv("SFR:IOCCF")
#INT_RA
void handler_ra(void)
{
// Rapid blink
output_bit(IO_LED,LED_ON); delay_ms(50);
output_bit(IO_LED,LED_OFF); delay_ms(250);
output_bit(IO_LED,LED_ON); delay_ms(50);
// Read input for automatic flag clear
i=input_a();
// Useless manual clear by ccs function, for test
clear_interrupt(INT_RA); // Useless, not concern, for test
clear_interrupt(INT_RA0);
clear_interrupt(INT_RA1);
IOCAF=0; // Useless (only & operation allowed for IOCxF), for test
}
#INT_RC
void handler_rc(void)
{
// Rapid blink
output_bit(IO_LED,LED_ON); delay_ms(50);
output_bit(IO_LED,LED_OFF); delay_ms(250);
output_bit(IO_LED,LED_ON); delay_ms(50);
// Read input for automatic flag clear
i=input_c();
// Useless manual clear by ccs function, for test
clear_interrupt(INT_RC); // Useless, not concern, for test
clear_interrupt(INT_RC0);
clear_interrupt(INT_RC1);
clear_interrupt(INT_RC2);
clear_interrupt(INT_RC3);
clear_interrupt(INT_RC4);
clear_interrupt(INT_RC5);
IOCCF=0; // Useless (only & operation allowed for IOCxF), for test
}
// --------------------------------------------------------------------------------------
void main(void)
{
setup_wdt(WDT_OFF); // Disable WDT to prevent CPU reset before first sleep
set_tris_a(TRIS_A);
set_tris_c(TRIS_C);
port_a_pullups(PULLUPS_A);
port_c_pullups(PULLUPS_C);
// Need to scan RC0-5 RA0-1
enable_interrupts(INT_RC5);
enable_interrupts(INT_RC4);
enable_interrupts(INT_RC3);
enable_interrupts(INT_RC2);
enable_interrupts(INT_RC1);
enable_interrupts(INT_RC0);
enable_interrupts(INT_RA1);
enable_interrupts(INT_RA0);
output_bit(IO_LED,LED_OFF);
// Two long blinks
output_bit(IO_LED,LED_OFF); delay_ms(500);
output_bit(IO_LED,LED_ON); delay_ms(500);
output_bit(IO_LED,LED_OFF); delay_ms(500);
output_bit(IO_LED,LED_ON); delay_ms(500);
output_bit(IO_LED,LED_OFF);
// Setup WDT to out from sleep or reset if stucked
setup_wdt(WDT_1S+WDT_ON);
enable_interrupts(GLOBAL);
while(true)
{
// Wait for interrupt or WDT
sleep();
output_bit(IO_LED,LED_OFF);
}
}
|
CCS compiling seem not bad :
Code: |
.................... void handler_ra(void)
.................... {
.................... // Rapid blink
.................... output_bit(IO_LED,LED_ON); delay_ms(50);
0039: MOVLB 02
003A: BCF 0C.2
003B: MOVLW 32
003C: MOVLB 00
003D: MOVWF 28
003E: CALL 024
.................... output_bit(IO_LED,LED_OFF); delay_ms(250);
003F: MOVLB 02
0040: BSF 0C.2
0041: MOVLW FA
0042: MOVLB 00
0043: MOVWF 28
0044: CALL 024
.................... output_bit(IO_LED,LED_ON); delay_ms(50);
0045: MOVLB 02
0046: BCF 0C.2
0047: MOVLW 32
0048: MOVLB 00
0049: MOVWF 28
004A: CALL 024
.................... // Read input for automatic flag clear
.................... i=input_a();
004B: MOVF 0C,W
004C: MOVWF 25
.................... // Useless manual clear by ccs function, for test
.................... clear_interrupt(INT_RA); // Useless, not concern, for test
004D: MOVF 0E,W
.................... clear_interrupt(INT_RA0);
004E: MOVLB 07
004F: BCF 13.0
.................... clear_interrupt(INT_RA1);
0050: BCF 13.1
.................... IOCAF=0; // Useless (only & operation allowed for IOCxF), for test
0051: CLRF 13
.................... }
0052: MOVLW FF
0053: XORWF 13,W
0054: ANDWF 13,F
0055: BCF 0B.0
0056: MOVLP 00
0057: MOVLB 00
0058: GOTO 017
|
CCS injects a propper interruption flag clear (i think) :
Code: |
0052: MOVLW FF
0053: XORWF 13,W
0054: ANDWF 13,F
|
Running behaviour :
Start with two long led blinks. Wait for an input state change.
If i change an input, i can see some rapid blinks. After a second, two long blinks.
Some rapid blinks means that interruption raised and handler code is executed, but it loops until WDT reset the CPU (one second after last sleep).
Normal behaviour is one handler execution, off the led, and go sleep again.
Why my interruption handler code loops ? I read many interruption/CCS problems on this forum. But I can't see why my code not working. Any idea ? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Sep 07, 2016 3:42 pm |
|
|
Quote: | #define TRIS_C (0b00011111)
#define PULLUPS_C (0b00011111) |
In the code above, you have TRIS set to output and pull-ups disabled for
pin C5. But in the code below, you are using pin C5. It's not going
to work correctly for that pin with the pullups turned off and the TRIS set
to output.
Quote: |
// Need to scan RC0-5 RA0-1
enable_interrupts(INT_RC5);
enable_interrupts(INT_RC4);
enable_interrupts(INT_RC3);
enable_interrupts(INT_RC2);
enable_interrupts(INT_RC1);
enable_interrupts(INT_RC0);
enable_interrupts(INT_RA1);
enable_interrupts(INT_RA0);
|
Also in my version of the compiler 5.061, it allows selecting which edge
to interrupt on (rising or falling). Do you want to interrupt on both edges ?
Your code is currently setup for that.
Code: | #define INT_RC5 0x32200B08
#define INT_RC5_L2H 0x12200B08
#define INT_RC5_H2L 0x22200B08 |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Wed Sep 07, 2016 4:05 pm |
|
|
As said many, many times before ...it's a really, really BAD idea to have ANY delays in ANY ISR..
It defeats the reason to use an ISR....
Jay |
|
|
tssir
Joined: 14 Feb 2016 Posts: 24
|
|
Posted: Thu Sep 08, 2016 12:27 am |
|
|
Correct. I add C5 tris and pullup.
Currently, without any settings, it raise interrupt on both edges. I need this behavior.
I try with INT_RC4_L2H and INT_RC4_H2L. It has no influence about interruption clear :
Code: | .................... clear_interrupt(INT_RC4);
0073: BCF 19.4
.................... clear_interrupt(INT_RC4_L2H);
0074: BCF 19.4
.................... clear_interrupt(INT_RC4_H2L);
0075: BCF 19.4
|
@temtronic : You are true. Original interruption code :
Code: |
#INT_RA
void handler_ra(void)
{
i=input_a();
wakeupIsInterruption=true;
clear_interrupt(INT_RA0);
clear_interrupt(INT_RA1);
}
|
Set wakeupIsInterruption global variable, and wakeup from sleep. That's all I expect from this interruption. |
|
|
tssir
Joined: 14 Feb 2016 Posts: 24
|
|
Posted: Thu Sep 08, 2016 1:00 am |
|
|
I found a clue ...
It seems that both interruptions are mixed.
On RC changes, #INT_RA is called.
I try this code :
Code: |
#INT_RA
void handler_ra(void)
{
// Rapid blink
output_bit(IO_LED,LED_ON); delay_ms(50);
output_bit(IO_LED,LED_OFF); delay_ms(100);
output_bit(IO_LED,LED_ON);
// Read input for automatic flag clear
i=input_a();
clear_interrupt(INT_RA0);
clear_interrupt(INT_RA1);
clear_interrupt(INT_RC0);
clear_interrupt(INT_RC1);
clear_interrupt(INT_RC2);
clear_interrupt(INT_RC3);
clear_interrupt(INT_RC4);
clear_interrupt(INT_RC5);
}
#INT_RC
void handler_rc(void)
{
i=input_c();
}
|
Then ... it works ! No more loops.
After some tries, it seems that any state changes on RA and RC raise #INT_RA. Never #INT_RC. Then i need to clear INT_RCx flags on #INT_RA too.
Luckily, both interruptions do sames things, on my design. It is a good solution for me.
For your information, interruption setup code :
Code: |
.................... enable_interrupts(INT_RC5);
0075: BSF 0B.3
0076: MOVLB 07
0077: BSF 17.5
0078: BSF 18.5
.................... enable_interrupts(INT_RC4);
0079: BSF 0B.3
007A: BSF 17.4
007B: BSF 18.4
.................... enable_interrupts(INT_RC3);
007C: BSF 0B.3
007D: BSF 17.3
007E: BSF 18.3
.................... enable_interrupts(INT_RC2);
007F: BSF 0B.3
0080: BSF 17.2
0081: BSF 18.2
.................... enable_interrupts(INT_RC1);
0082: BSF 0B.3
0083: BSF 17.1
0084: BSF 18.1
.................... enable_interrupts(INT_RC0);
0085: BSF 0B.3
0086: BSF 17.0
0087: BSF 18.0
.................... enable_interrupts(INT_RA1);
0088: BSF 0B.3
0089: BSF 11.1
008A: BSF 12.1
.................... enable_interrupts(INT_RA0);
008B: BSF 0B.3
008C: BSF 11.0
008D: BSF 12.0
|
|
|
|
|
|
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
|