How to clear IOC interrupt condition on PIC18F26K22

Thread Starter

daryooosh

Joined Jun 15, 2019
56
Hello
I using "MCC" to configure IOC of "RB4" as "any". The CPU is interrupted as i expected but i can't clear interrupt condition so CPU will looped in ISR. I read the datasheet, in datasheet mentioned that :
The user, in the Interrupt Service Routine, can clear the interrupt in the following manner:
1. Any read or write of PORTB to clear the mis-match condition (except when PORTB is the source or destination of a MOVFF instruction).
2. Execute at least one instruction after reading or writing PORTB, then clear the flag bit, RBIF.
So i write my ISR as :
Code:
void myISR(void)
{
    //Only for clear interrupt condition.
    if (PORTB == 0)        NOP();
    
    flag = true;
}
And clear the "" flag on main ISR function as followin :
Code:
void PIN_MANAGER_IOC(void)
{   
    // interrupt on change for pin IOCB4
    if(IOCBbits.IOCB4 == 1)
    {
        myISR();  
    }    
    // Clear global Interrupt-On-Change flag
    INTCONbits.RBIF = 0;
}
Note : I checked assembly code resulted from my code and ensure that the "PORTB" is not read with "MOVFF" instruction.

Are there any mistakes in my codes ?
 

Irving

Joined Jan 30, 2016
3,843
Note : I checked assembly code resulted from my code and ensure that the "PORTB" is not read with "MOVFF" instruction.
Since this code does nothing the compiler has optimised it out. Either turn off optimisation, or make your code do something.
 

Ian Rogers

Joined Dec 12, 2012
1,136
Yes! quite right.
C:
void myISR(void)
{
    char dumdum;      // spare
    //Only for clear interrupt condition.
    if (PORTB == 0) {
       NOP();
       dumdum = PORTB;  // << -- needed to clear interrupt   
       }
    flag = true;
}
 

trebla

Joined Jun 29, 2019
542
Yes! quite right.
C:
void myISR(void)
{
char dumdum; // spare
//Only for clear interrupt condition.
if (PORTB == 0) {
NOP();
dumdum = PORTB; // << -- needed to clear interrupt
}
flag = true;
}
As TS wanted to interrupt to any PORTB state, this routine works only in 50% of cases correctly. Reading to variable must be placed outside if() block, before flag variable assignment.
 

Ian Rogers

Joined Dec 12, 2012
1,136
Going old school... The interrupt cancels on a portb read.. the flag IS cleared at least two command afterwards.. there at least a return..
 

Thread Starter

daryooosh

Joined Jun 15, 2019
56
If you try to read PORTB to a variable then the MOVFF instruction appears on ASM listing?
Yes, The created assembly for :
Code:
char dump = PORTB;
Is :
Code:
movf    129,w,c ;volatile
And for
Code:
    char dump = PORTB;
    if (dump == 0) NOP();
Is :
Code:
;char dump = PORTB;
 movff   3969,isr@dump    ;volatile
And for :
Code:
if (PORTB == 0)  NOP();
Is :
Code:
;if (PORTB == 0)
movf    129,w,c ;volatile
 

Thread Starter

daryooosh

Joined Jun 15, 2019
56
Yes! quite right.
C:
void myISR(void)
{
    char dumdum;      // spare
    //Only for clear interrupt condition.
    if (PORTB == 0) {
       NOP();
       dumdum = PORTB;  // << -- needed to clear interrupt  
       }
    flag = true;
}
In answer to "trebla" i specific output assembly for different C codes and according to datasheet my code must be sufficient for clearing interrupt condition.
 

click_here

Joined Sep 22, 2020
548
I have found a similar problem here and it looks like they mixed in some assembly.

This would be worth giving a go...
Code:
     _asm
     MOVF    PORTB,0,0
     NOP
     _endasm
     INTCONbits.RBIF = 0;
     _asm
     MOVF    PORTB,0,0
     _endasm
     LastKnownPORTB = WREG;
But you'll need to translate it to something that the XC8 compiler expects using asm()
 
Top