This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28388D: Can Interrupt

Part Number: TMS320F28388D
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hi all,

I'm using a TMS320F28388D and working on receiving data through the CAN bus.

In polling mode, I'm successfully receiving CAN messages using a while loop.

However, when I configure the CAN peripheral for interrupt mode, the receive interrupt is never triggered, and no data is received.

To test the setup, I’m sending CAN messages from a Microchip CAN Bus Analyzer Tool. The messages are received correctly in polling mode, but not in interrupt mode.

CAN Peripheral: Configured via syscfg

Test Setup: Microchip CAN Bus Analyzer is used to send messages

Observation:

Polling mode works fine (data is received)

Interrupt mode doesn’t work:

No interrupt fires

No data received

Below is the configuration of Sys config

Thanks

  • Hi Sudhir,

    I don't think Sysconfig creates the ISR (interrupt service routine) in main file.  Sysconfig creates the ISR definition and enables the interrupt as part of Board_init() function.  Please refer to an existing CAN example that has the ISR function.  Examples can_ex2_loopback_interrupts and can_ex3_external_transmit have the ISR function __interrupt void canISR(void) in main.  Without this handler, the interrupt will not be serviced.

    Best regards,

    Joseph

  • Hi Joseph,

    Thanks for reply, 

    Yes, I had already written the ISR function  in the main file as shown in the example codes. I also ran both can_ex2_loopback_interrupts and can_ex3_external_transmit examples, but unfortunately, the interrupt is still not getting triggered in my case.

    Please let me know if there’s anything else I might be missing or if you have any suggestions for further debugging

    Below is my ISR 

    void INT_myCAN0_0_ISR()
    {
    uint32_t status;

    //
    // Read the CAN-B interrupt status to find the cause of the interrupt
    //
    status = CAN_getInterruptCause(myCAN0_BASE);

    //
    // If the cause is a controller status interrupt, then get the status
    //
    if(status == CAN_INT_INT0ID_STATUS)
    {
    //
    // Read the controller status. This will return a field of status
    // error bits that can indicate various errors. Error processing
    // is not done in this example for simplicity. Refer to the
    // API documentation for details about the error status bits.
    // The act of reading this status will clear the interrupt.
    //
    status = CAN_getStatus(myCAN0_BASE);

    //
    // Check to see if an error occurred.
    //
    if(((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_MSK) &&
    ((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_NONE))
    {
    //
    // Set a flag to indicate some errors may have occurred.
    //
    errorFlag = 1;
    }
    }
    //
    // Check if the cause is the CAN-B receive message object 1
    //
    else if(status == RX_MSG_OBJ_ID)
    {
    //
    // Get the received message
    //
    CAN_readMessage(myCAN0_BASE, RX_MSG_OBJ_ID, rxMsgData);

    //
    // Getting to this point means that the RX interrupt occurred on
    // message object 1, and the message RX is complete. Clear the
    // message object interrupt.
    //
    CAN_clearInterruptStatus(myCAN0_BASE, RX_MSG_OBJ_ID);

    //
    // Increment a counter to keep track of how many messages have been
    // received. In a real application this could be used to set flags to
    // indicate when a message is received.
    //
    // rxMsgCount++;

    //
    // Since the message was received, clear any error flags.
    //
    errorFlag = 0;
    }
    //
    // If something unexpected caused the interrupt, this would handle it.
    //
    else
    {
    //
    // Spurious interrupt handling can go here.
    //
    }

    //
    // Clear the global interrupt flag for the CAN interrupt line
    //
    CAN_clearGlobalInterruptStatus(myCAN0_BASE, CAN_GLOBAL_INT_CANINT0);

    //
    // Acknowledge this interrupt located in group 9
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    // CAN_readMessage(myCAN0_BASE, myCAN0_MessageObj1_ID, &rxMsgData);
    // CAN_clearInterruptStatus(myCAN0_BASE, myCAN0_MessageObj1_ID);
    // CAN_clearGlobalInterruptStatus(myCAN0_BASE,CAN_GLOBAL_INT_CANINT0 );
    // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    }

    Thanks

  • Hi Sudhir,

    Can you send a snippet of the CAN message object set up?  You might need to set the interrupt flag in one of the arguments to the set up object function.  Also send a snippet of the CAN interrupt functions that were generated by Sysconfig.  You may need additional step for CAN interrupt to take effect.

    Regards,

    Joseph

  • HI, Joseph,

    Thanks for reply, 

    Below is the snippet of the CAN message object setup 

    void myCAN0_init(){
    CAN_initModule(myCAN0_BASE);
    //
    // Refer to the Driver Library User Guide for information on how to set
    // tighter timing control. Additionally, consult the device data sheet
    // for more information about the CAN module clocking.
    //
    CAN_setBitTiming(myCAN0_BASE, 7, 0, 15, 7, 3);
    //
    // Enable CAN Interrupts
    //
    CAN_enableInterrupt(myCAN0_BASE, CAN_INT_ERROR|CAN_INT_IE0|CAN_INT_IE1|CAN_INT_STATUS);
    CAN_enableGlobalInterrupt(myCAN0_BASE, CAN_GLOBAL_INT_CANINT0);
    CAN_enableGlobalInterrupt(myCAN0_BASE, CAN_GLOBAL_INT_CANINT1);
    //
    // Initialize the transmit message object used for sending CAN messages.
    // Message Object Parameters:
    // Message Object ID Number: 1
    // Message Identifier: 0
    // Message Frame: CAN_MSG_FRAME_STD
    // Message Type: CAN_MSG_OBJ_TYPE_TX
    // Message ID Mask: 0
    // Message Object Flags:
    // Message Data Length: 4 Bytes
    //
    CAN_setupMessageObject(myCAN0_BASE, 1, myCAN0_MessageObj1_ID, CAN_MSG_FRAME_STD,CAN_MSG_OBJ_TYPE_TX, 0, 0,4);
    //
    // Initialize the transmit message object used for sending CAN messages.
    // Message Object Parameters:
    // Message Object ID Number: 2
    // Message Identifier: 1
    // Message Frame: CAN_MSG_FRAME_STD
    // Message Type: CAN_MSG_OBJ_TYPE_RX
    // Message ID Mask: 1
    // Message Object Flags: CAN_MSG_OBJ_USE_ID_FILTER
    // Message Data Length: 0 Bytes
    //
    CAN_setupMessageObject(myCAN0_BASE, 2, myCAN0_MessageObj2_ID, CAN_MSG_FRAME_STD,CAN_MSG_OBJ_TYPE_RX, 1, CAN_MSG_OBJ_USE_ID_FILTER,0);
    CAN_setInterruptMux(myCAN0_BASE, 2);
    //
    // Start CAN module operations
    //
    CAN_startModule(myCAN0_BASE);
    }

    Interrupt_register(INT_myCAN0_0, &INT_myCAN0_0_ISR);
    Interrupt_enable(INT_myCAN0_0);

    // Interrupt Setings for INT_myCAN0_1
    Interrupt_register(INT_myCAN0_1, &INT_myCAN0_1_ISR);
    Interrupt_enable(INT_myCAN0_1);

    void INT_myCAN0_0_ISR()
    {
    uint32_t status;

    //
    // Read the CAN-B interrupt status to find the cause of the interrupt
    //
    status = CAN_getInterruptCause(myCAN0_BASE);

    //
    // If the cause is a controller status interrupt, then get the status
    //
    if(status == CAN_INT_INT0ID_STATUS)
    {
    //
    // Read the controller status. This will return a field of status
    // error bits that can indicate various errors. Error processing
    // is not done in this example for simplicity. Refer to the
    // API documentation for details about the error status bits.
    // The act of reading this status will clear the interrupt.
    //
    status = CAN_getStatus(myCAN0_BASE);

    //
    // Check to see if an error occurred.
    //
    if(((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_MSK) &&
    ((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_NONE))
    {
    //
    // Set a flag to indicate some errors may have occurred.
    //
    errorFlag = 1;
    CAN_clearInterruptStatus(myCAN0_BASE, RX_MSG_OBJ_ID);
    CAN_clearGlobalInterruptStatus(myCAN0_BASE, CAN_GLOBAL_INT_CANINT0);

    //
    // Acknowledge this interrupt located in group 9
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    }
    }
    //
    // Check if the cause is the CAN-B receive message object 1
    //
    else if(status == RX_MSG_OBJ_ID)
    {
    //
    // Get the received message
    //
    CAN_readMessage(myCAN0_BASE, RX_MSG_OBJ_ID, rxMsgData);

    //
    // Getting to this point means that the RX interrupt occurred on
    // message object 1, and the message RX is complete. Clear the
    // message object interrupt.
    //
    CAN_clearInterruptStatus(myCAN0_BASE, RX_MSG_OBJ_ID);

    //
    // Increment a counter to keep track of how many messages have been
    // received. In a real application this could be used to set flags to
    // indicate when a message is received.
    //
    // rxMsgCount++;

    //
    // Since the message was received, clear any error flags.
    //
    errorFlag = 0;
    }
    //
    // If something unexpected caused the interrupt, this would handle it.
    //
    else
    {
    //
    // Spurious interrupt handling can go here.
    //
    }

    //
    // Clear the global interrupt flag for the CAN interrupt line
    //
    CAN_clearGlobalInterruptStatus(myCAN0_BASE, CAN_GLOBAL_INT_CANINT0);

    //
    // Acknowledge this interrupt located in group 9
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    // CAN_readMessage(myCAN0_BASE, myCAN0_MessageObj1_ID, &rxMsgData);
    // CAN_clearInterruptStatus(myCAN0_BASE, myCAN0_MessageObj1_ID);
    // CAN_clearGlobalInterruptStatus(myCAN0_BASE,CAN_GLOBAL_INT_CANINT0 );
    // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    }
    void INT_myCAN0_1_ISR()
    {
    // CAN_readMessage(myCAN0_BASE, myCAN0_MessageObj1_ID, &rxMsgData);
    // CAN_clearInterruptStatus(myCAN0_BASE, myCAN0_MessageObj1_ID);
    // CAN_clearGlobalInterruptStatus(myCAN0_BASE,CAN_GLOBAL_INT_CANINT1 );
    // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    uint32_t status;

    //
    // Read the CAN-B interrupt status to find the cause of the interrupt
    //
    status = CAN_getInterruptCause(myCAN0_BASE);

    //
    // If the cause is a controller status interrupt, then get the status
    //
    if(status == CAN_INT_INT0ID_STATUS)
    {
    //
    // Read the controller status. This will return a field of status
    // error bits that can indicate various errors. Error processing
    // is not done in this example for simplicity. Refer to the
    // API documentation for details about the error status bits.
    // The act of reading this status will clear the interrupt.
    //
    status = CAN_getStatus(myCAN0_BASE);

    //
    // Check to see if an error occurred.
    //
    if(((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_MSK) &&
    ((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_NONE))
    {
    //
    // Set a flag to indicate some errors may have occurred.
    //
    errorFlag = 1;
    }
    }
    //
    // Check if the cause is the CAN-B receive message object 1
    //
    else if(status == RX_MSG_OBJ_ID)
    {
    //
    // Get the received message
    //
    CAN_readMessage(myCAN0_BASE, RX_MSG_OBJ_ID, rxMsgData);

    //
    // Getting to this point means that the RX interrupt occurred on
    // message object 1, and the message RX is complete. Clear the
    // message object interrupt.
    //
    CAN_clearInterruptStatus(myCAN0_BASE, RX_MSG_OBJ_ID);

    //
    // Increment a counter to keep track of how many messages have been
    // received. In a real application this could be used to set flags to
    // indicate when a message is received.
    //
    // rxMsgCount++;

    //
    // Since the message was received, clear any error flags.
    //
    errorFlag = 0;
    }
    //
    // If something unexpected caused the interrupt, this would handle it.
    //
    else
    {
    //
    // Spurious interrupt handling can go here.
    //
    }

    //
    // Clear the global interrupt flag for the CAN interrupt line
    //
    CAN_clearGlobalInterruptStatus(myCAN0_BASE, CAN_GLOBAL_INT_CANINT1);

    //
    // Acknowledge this interrupt located in group 9
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    }  

    now this time interrupt is triggered but getting error and stuck in error loop 

    status = CAN_getInterruptCause(myCAN0_BASE);

    //
    // If the cause is a controller status interrupt, then get the status
    //
    if(status == CAN_INT_INT0ID_STATUS)
    {
    //
    // Read the controller status. This will return a field of status
    // error bits that can indicate various errors. Error processing
    // is not done in this example for simplicity. Refer to the
    // API documentation for details about the error status bits.
    // The act of reading this status will clear the interrupt.
    //
    status = CAN_getStatus(myCAN0_BASE);

    //
    // Check to see if an error occurred.
    //
    if(((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_MSK) &&
    ((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_NONE))
    {
    //
    // Set a flag to indicate some errors may have occurred.
    //
    errorFlag = 1;
    CAN_clearInterruptStatus(myCAN0_BASE, RX_MSG_OBJ_ID);
    CAN_clearGlobalInterruptStatus(myCAN0_BASE, CAN_GLOBAL_INT_CANINT0);

    //
    // Acknowledge this interrupt located in group 9
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    }
    }  Thanks

  • Hi Sudhir,

    When inserting code to the post, please use the "Insert" tab below and choose the "</> Code" option next time.  This makes the post more readable by separating code snippets and texts of the posts.

    Looking at setup objects statements below:

    CAN_setupMessageObject(myCAN0_BASE, 1, myCAN0_MessageObj1_ID, CAN_MSG_FRAME_STD,CAN_MSG_OBJ_TYPE_TX, 0, CAN_MSG_OBJ_TX_INT_ENABLE,4);
    
    CAN_setupMessageObject(myCAN0_BASE, 2, myCAN0_MessageObj2_ID, CAN_MSG_FRAME_STD,CAN_MSG_OBJ_TYPE_RX, 1, CAN_MSG_OBJ_USE_ID_FILTER|CAN_MSG_OBJ_RX_INT_ENABLE,0);
    
    

    The second to last argument of function CAN_setupMessageObject() has to be modified to include the interrupt flag.  Please see above snippet.  The changes above should trigger the interrupt for any sent or received CAN frame.

    Please try adding these flags to the object setup function calls.

    Regards,

    Joseph