Electronic – Migrated from C18 to Hi-Tech C 18.. Interrupt not working

c18hi-tech-compilerinterruptspic

Here is my source code. This code is working perfectly fine in C18 Compiler. Not until I migrated to Hi Tech C. It does not enter the interrupt service routine. Moreover, it somehow corrupted sid variable passed on to a function. Instead of passing a value of 0x501, it passed 0x000. Is there anything that I have missed in configuring an interrupt?

    #include <p18f25k80.h>
    #include <stdio.h>
    #include "ect_2014_debugger.h"
    #include "ect_2014_can.h"

    //#pragma config CONFIG1L = 0x15
    __CONFIG(1, RETEN_OFF & INTOSCSEL_HIGH & SOSCSEL_DIG & XINST_OFF);
    //#pragma config CONFIG1H = 0x92
    __CONFIG(2, FOSC_HS2 & PLLCFG_ON & FCMEN_OFF & IESO_ON);
    //#pragma config CONFIG2L = 0x78
    __CONFIG(3, PWRTEN_ON & BOREN_OFF & BORV_3 & BORPWR_ZPBORMV);
    //#pragma config CONFIG2H = 0x7C
    __CONFIG(4, WDTEN_OFF & WDTPS_1048576);
    //#pragma config CONFIG3H = 0x89
    __CONFIG(5, CANMX_PORTB & MSSPMSK_MSK7 & MCLRE_ON);
    //#pragma config CONFIG4L = 0x80
    __CONFIG(6, STVREN_OFF & BBSIZ_BB1K);
    //#pragma config CONFIG5L = 0xF
    __CONFIG(7, CP0_OFF & CP1_OFF & CP2_OFF & CP3_OFF);
    //#pragma config CONFIG5H = 0xC0
    __CONFIG(8, CPB_OFF & CPD_OFF);
    //#pragma config CONFIG6L = 0xF
    __CONFIG(9, WRT0_OFF & WRT1_OFF & WRT2_OFF & WRT3_OFF);
    //#pragma config CONFIG6H = 0xE0
    __CONFIG(10, WRTC_OFF & WRTB_OFF & WRTD_OFF);
    //#pragma config CONFIG7L = 0xF
    __CONFIG(11, EBTR0_OFF & EBTR1_OFF & EBTR2_OFF & EBTR3_OFF);
    //#pragma config CONFIG7H = 0x40
    __CONFIG(12, EBTRB_OFF);


    /* CAN Header */
    // CAN = PORTB
    #define SID_CAN1 0x500
    #define SID_CAN2 0x501
    #define NOMASK 0x7FF

    void interrupt ISR(void) {
        unsigned char rxbuf[8] = {0};
        unsigned int sid = 0, dlc = 0, i = 0;
        unsigned char rtr = 0;

        if (PIR5bits.RXB0IF && PIE5bits.RXB0IE) {
            printf("Interrupt inside\n\r");
            rtr = receive_can_msg_rxb0(rxbuf, &sid, &dlc); // Automatically clears the interrupt flag.
            if (!rtr) { // Data Frame
                if (sid == SID_CAN2) {
                    printf("SID = %x\n\rDLC = %d\n\r", sid, dlc);
                    for (i = 0; i < 8; i++)
                        printf("rxbuf[%d] = %d\n\r", i, rxbuf[i]);
                    printf("\n\r\n\r");
                }
            }
       }
    }
    //void interrupt ISR(void);
    void main() {
        unsigned int sid[2] = {SID_CAN2, 0};
        unsigned int mask[2] = {NOMASK, NOMASK};
        initUART(1); // Used for debugging
        RCONbits.IPEN = 0;  // Disable Priority Interrupts
        initCAN(&sid[0], mask); // SID = 0x501; MASK = NOMASK


        while (1);
    }

Here is the initCAN function:

    void initCAN(unsigned int * sid, unsigned int * mask) {
            PIE5bits.RXB0IE = 0;
            PIE5bits.RXB1IE = 0;
            char i = 0;
            // 1. Initial LAT and TRIS bits for RX and TX CAN.
            TRISBbits.TRISB2 = 0; // TX
            TRISBbits.TRISB3 = 1; // RX
            LATBbits.LATB2 = 0; // Initialize 0 for TX
            // 2. Ensure that the ECAN module is in Configuration Mode
            /* CANCON is the CAN Control Register */
            CANCONbits.REQOP = 4; // REQOP<2:0> is a group of 3 bits; ensures that ECAN module
        #ifdef CAN_DEBUGGER
            printf("******* ECAN Module Initialization *******\n\r");
            printf("The ECAN Module is currently requesting to be in configuration mode.\n\r");
        #endif
            while (CANSTATbits.OPMODE != 4);
            // A request to configuration mode might not be honored immediately, as do to loopback,
            // disable, and etc. It is a good practice though to wait until the request to configuration
            // mode is completed.
        #ifdef CAN_DEBUGGER
            printf("The ECAN Module is now in configuration mode.\n\r");
        #endif
            // 3. Select ECAN Operational Mode.
            /* ECANCON is the Enhanced CAN Control Register.*/
            ECANCONbits.MDSEL = 0; // Configures the ECAN module to mode 0.
            // 4. Set up the Baud Rate registers.
            // Sync Jump Width is subtracted from Phase_seg2 or added to phase_seg1 to synchronize itself
            // to the data bit to be sampled.
            CIOCONbits.ENDRHI = 1; // 0 - Transcieverless CAN; 1 - Transciever CAN
            CIOCONbits.CLKSEL = 0; // Use the PLL as the CAN clock source, 64MHz
            // FOSC = 64 Mbps; Tosc = 15.625ns
            BRGCON1bits.BRP = 1; // Tq(us) = (2*(1+1))/64MHz = 62.5 ns
            // Nominal Bit Time = Tq*sigma
            // sigma = 1us/62.5ns = 16Tq
            BRGCON1bits.SJW = 0; // SJQ = 1Tq is typically enough as shown in the datasheet.
            BRGCON2bits.SEG2PHTS = 1; // Seg_phase 2 length = Freely Programmable
            BRGCON2bits.SAM = 0; //Bus line is sampled once at the sample point
            BRGCON2bits.SEG1PH = 0b111; //Phase segment 1 = 8TQ
            BRGCON2bits.PRSEG = 0b000; //Propagation segment = 1TQ
            BRGCON3bits.SEG2PH = 0b101; //Phase segment 2 = 6TQ
            // Verifying the baud rate configuration..
            // 1+8+1+6 = 16Tq.
            // Prop_Seg (1) + Phase_Seg1 (8) >= Phase_seg 2 (6) : TRUE
            // Phase_seg2(6) >= Sync Jump Width(1) : TRUE

            // 5. Set up the Filter and Mask Registers
            RXB0CON = 0; // Receive buffer is open to new messages; Receive all messages filtered dependent on
            // EXIDEN bit;
            RXB1CON = 0; // Same as RXB0CON.

        //    // Initialize Acceptance Filters and Masks to 0x00:
            RXF0SIDH = 0; // SID10 to SID3
            RXF0SIDL = 0; // SID2 to SID0; Standard frame
            RXF1SIDH = 0;
            RXF1SIDL = 0;
            RXF2SIDH = 0;
            RXF2SIDL = 0;
            RXF3SIDH = 0;
            RXF3SIDL = 0;
            RXF4SIDH = 0;
            RXF4SIDL = 0;
            RXF5SIDH = 0;
            RXF5SIDL = 0;
            RXM0SIDH = 0xFF;
            RXM0SIDL = 0xFF;
            RXM1SIDH = 0xFF;
            RXM1SIDL = 0xFF;
            // Acceptance Filters (RXF0 and RXF1) and filter mask (RXM0) are associated with RXB0.
            // Acceptance Filters (RXF2 to RXF5) and filter mask (RXM1) are associated with RXB1.
            for (i = 0; i < 5 && *sid != 0; i++) {
                if (i == 0) {
        #ifdef CAN_DEBUGGER
                    printf("** Associated with RXB0 **\n\r");
                    printf("Message Acceptance Filter %d: %x\n\r", i, *sid);
        #endif
                    RXF0SIDH = (*sid & 0x7F8) >> 3; // SID10 to SID3
                    RXF0SIDL = (*sid++ & 0x007) << 5; // SID2 to SID0; Standard frame
                    RXF0EIDH = 0;
                    RXF0EIDL = 0;
                } else if (i == 1) {
        #ifdef CAN_DEBUGGER
                    printf("Message Acceptance Filter %d: %x\n\r", i, *sid);
        #endif
                    RXF1SIDH = (*sid & 0x7F8) >> 3; // SID10 to SID3
                    RXF1SIDL = (*sid++ & 0x007) << 5; // SID2 to SID0; Standard frame
                    RXF1EIDH = 0;
                    RXF1EIDL = 0;
                } else if (i == 2) {
        #ifdef CAN_DEBUGGER
                    printf("** Associated with RXB1 **\n\r");
                    printf("Message Acceptance Filter %d: %x\n\r", i, *sid);
        #endif
                    RXF2SIDH = (*sid & 0x7F8) >> 3; // SID10 to SID3
                    RXF2SIDL = (*sid++ & 0x007) << 5; // SID2 to SID0; Standard frame
                    RXF2EIDH = 0;
                    RXF2EIDL = 0;
                } else if (i == 3) {
        #ifdef CAN_DEBUGGER
                    printf("Message Acceptance Filter %d: %x\n\r", i, *sid);
        #endif
                    RXF3SIDH = (*sid & 0x7F8) >> 3; // SID10 to SID3
                    RXF3SIDL = (*sid++ & 0x007) << 5; // SID2 to SID0; Standard frame
                    RXF3EIDH = 0;
                    RXF3EIDL = 0;
                } else if (i == 4) {
        #ifdef CAN_DEBUGGER
                    printf("Message Acceptance Filter %d: %x\n\r", i, *sid);
        #endif
                    RXF4SIDH = (*sid & 0x7F8) >> 3; // SID10 to SID3
                    RXF4SIDL = (*sid++ & 0x007) << 5; // SID2 to SID0; Standard frame
                    RXF4EIDH = 0;
                    RXF4EIDL = 0;
                } else if (i == 5) {
        #ifdef CAN_DEBUGGER
                    printf("Message Acceptance Filter %d: %x\n\r", i, *sid);
        #endif
                    RXF5SIDH = (*sid & 0x7F8) >> 3; // SID10 to SID3
                    RXF5SIDL = (*sid++ & 0x007) << 5; // SID2 to SID0; Standard frame
                    RXF5EIDH = 0;
                    RXF5EIDL = 0;
                }
            }

            for (i = 0; i < 2 && *mask != 0; i++) {
                if (i == 0) {
        #ifdef CAN_DEBUGGER
                    printf("\n\r** Associated with RXB0 **\n\r");
                    printf("Message Acceptance Mask %d: %x\n\r", i, *mask);
        #endif
                    //Mask 0
                    RXM0SIDH = (*mask & 0x7F8) >> 3;
                    RXM0SIDL = (*mask++ & 0x007) << 5;
                    RXM0EIDH = 0xFF;
                    RXM0EIDL = 0xFF;
                } else if (i == 1) {
        #ifdef CAN_DEBUGGER
                    printf("** Associated with RXB1 **\n\r");
                    printf("Message Acceptance Mask %d: %x\n\r", i, *mask);
        #endif
                    //Mask 1
                    RXM1SIDH = (*mask & 0x7F8) >> 3;
                    RXM1SIDL = (*mask++ & 0x007) << 5;
                    RXM1EIDH = 0xFF;
                    RXM1EIDL = 0xFF;
                }
            }
            // 6. Set the ECAN Module to normal mode or any other mode required by the application logic.
            CANCONbits.REQOP = 0; // Normal Mode
            while (CANSTATbits.OPMODE != 0); // Wait until ECAN module is configured as normal mode.
        #ifdef CAN_DEBUGGER
            printf("******* ECAN Module is now operating in normal mode *******\n\r");
        #endif
            // (Optional) Enable interrupts.
            PIR5bits.RXB0IF = 0;
            PIR5bits.RXB1IF = 0;
            PIE5bits.RXB0IE = 1;
            PIE5bits.RXB1IE = 1;
            INTCONbits.GIE = 1;
            INTCONbits.PEIE = 1;
        #ifdef CAN_DEBUGGER
            printf("******* Interrupts are also enabled! *******\n\r");
        #endif
        }

And here's the C18 source code:

    #include <p18f25k80.h>
    #include <stdio.h>
    #include "ect_2014_debugger.h"
    #include "ect_2014_can.h"
    #pragma config RETEN = OFF    //Ultra low-power regulator is Disabled
    #pragma config XINST = OFF    //Extended Instruction Set Disabled
    #pragma config IESO = ON      //Two speed start-up mode enable
    #pragma config FOSC = HS2     //HS oscillator (High power, 16 MHz - 25 MHz)
    #pragma config PLLCFG = ON    //Enable PLL x4
    #pragma config PWRTEN = ON    //Enable Power Up timer
    #pragma config BOREN = OFF    //Disable Brown Out Detection
    #pragma config WDTEN = OFF    //Disable Watch Dog Timer
    #pragma config MCLRE = ON     //Enable MCLR
    #pragma config CP0 = OFF,CP1 = OFF,CP2 = OFF,CP3 = OFF,CPB = OFF,CPD = OFF
    #pragma config WRT0 = OFF,WRT1 = OFF,WRT2 = OFF,WRT3 = OFF,WRTC = OFF,WRTB = OFF,WRTD = OFF
    #pragma config EBTR0 = OFF,EBTR1 = OFF,EBTR2 = OFF,EBTR3 = OFF,EBTRB = OFF
    #pragma config SOSCSEL = DIG   //RC0 and RC1 are digital IO

    /* CAN Header */
    #pragma config CANMX = PORTB  // ECAN TX and RX pins are located on RB2 and RB3, respectively
    #define SID_CAN1 0x500
    #define SID_CAN2 0x501
    #define NOMASK 0x7FF

    void isr(void);
    #pragma code high_vector=0x08

    void interrupt_at_high_vector(void) {
        _asm GOTO isr _endasm
    }
    #pragma code
    #pragma interrupt isr

    void isr(void) {
        unsigned char rxbuf[8] = {0};
        unsigned int sid = 0, dlc = 0, i = 0;
        unsigned char rtr = 0;
        if (PIR5bits.RXB0IF && PIE5bits.RXB0IE) {
            printf((const far rom char*) "Interrupt inside\n\r");
            rtr = receive_can_msg_rxb0(rxbuf, &sid, &dlc); // Automatically clears the interrupt flag.
            if (!rtr) { // Data Frame
                if (sid == SID_CAN2) {
                    printf((const far rom char*) "SID = %x\n\r", sid);
                    for (i = 0; i < 8; i++)
                        printf((const far rom char *) "rxbuf[%d] = %d\n\r", i, rxbuf[i]);
                    printf((const far rom char *) "\n\r\n\r");
                }
            }
        }
    }

    void main() {

        unsigned int sid[2] = {SID_CAN2, 0};
        unsigned int mask[2] = {NOMASK, NOMASK};
        int i,j;
        initUART(1); // Used for debugging
        initCAN(sid, mask); // SID = 0x501; MASK = NOMASK


        while (1)
            for (i = 0; i < 1000; i++)
                for (j = 0; j < 1000; j++)
                    if (i == 999 && j == 999)
                        printf("RXB0IF = %d\n\rRXB1IF = %d\n\rRXFUL = %d\n\r", PIR5bits.RXB0IF, PIR5bits.RXB0IF,RXB0CONbits.RXFUL);

    }

Best Answer

Please double check if you are activating the IPEN bit (IPEN means interrupt priority feature). If it is activated you need to declare the interrupt service routine with a priority:

void interrupt low_priority LowISR( void )
{

}

void interrupt high_priority HighISR( void )
{ 

}

See the next example of my EcanInit function for the 18F26K80:

// Configure the port pins for CAN operation
TRISBbits.TRISB3 = 1;   // CANRX in - Changed to accomodate 18F4680 - CG
TRISBbits.TRISB2 = 0;   // CANTX out

// Establish the ECAN interrupt priorities and enable the ECAN receive interrupt.       
BIE0 = ECAN_BUFFER_INTERRUPT_ENABLE;
PIE5 = ECAN_RX_INT_ENABLE_FIFO | ECAN_ERROR_INT_ENABLE;

RCONbits.IPEN = 1;

IPR5 &= 0xE0;
IPR5 |= ECAN_INTERRUPT_PRIORITY;

I hope this helps.