3
\$\begingroup\$

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);

    }
\$\endgroup\$
  • \$\begingroup\$ But if I remove the ISR, the sid variable passed the correct value. \$\endgroup\$ – Xegara Oct 8 '13 at 10:21
  • \$\begingroup\$ Are you enabling interrupts in another place of your code? \$\endgroup\$ – Daniel Grillo Oct 8 '13 at 11:49
  • \$\begingroup\$ yes sir. I'll add it on the question. \$\endgroup\$ – Xegara Oct 8 '13 at 11:55
  • \$\begingroup\$ Generally, the debugging strategy is to cut back to the smallest code snippet that will reproduce the behavior. Nine times out of ten, that process will give you your answer. \$\endgroup\$ – Scott Seidman Oct 9 '13 at 12:29
1
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.