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.

TMS320F28379D: how to correctly setup both CAN lines to work with interrupt

Genius 12490 points
Part Number: TMS320F28379D
Other Parts Discussed in Thread: LAUNCHXL-F28379D, C2000WARE

Title:  how to correctly setup both CAN lines to work with interrupt

Part: TMS320F28379DZWTT

Question:

I’ve been working with the launchpad LAUNCHXL-F28379D and I am trying to work with both CAN lines on my project.
CANB is correctly setup with GPIO 17 and 12, CANA is connected to an external transceiver.

I followed the C2000Ware example to setup a ISR to go off whenever a CAN message is received.

CANB works perfectly.

The issue with CANA is that I am able to correctly send messagges but it doesn’t recevie.

With a CAN sniffer I am able to send messages to the F28379D but my guess is that the ISR never start.

I think there is something wrong with the interrupt lines, but I cant figure out what.

Below is my code:

<code snippet>

#include "can_management.h"

 

 

void canSetup()

{

    //

    // Configure GPIO pins for CANTX/CANRX

    //

    GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXB);

    GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXB);

 

    GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA);

    GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXA);

    //

    // Initialize the CAN controller

    //

    CAN_initModule(CANB_BASE);

    CAN_initModule(CANA_BASE);

 

    //

    // Set up the CAN bus bit rate to 500kHz for each module

    // 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_setBitRate(CANB_BASE, DEVICE_SYSCLK_FREQ, 1000000, 10);

    CAN_setBitRate(CANA_BASE, DEVICE_SYSCLK_FREQ, 1000000, 10);

 

 

    //

    //FROM can_ex2_loopback_interrupts.c example ---------------------------------------------

    //

    //

 

    //

    // Enable interrupts on the CAN peripheral.

    // Enables Interrupt line 0, Error & Status Change interrupts in CAN_CTL

    // register.

    //

    CAN_enableInterrupt(CANB_BASE, CAN_INT_IE0 | CAN_INT_ERROR |

                        CAN_INT_STATUS);

 

    CAN_enableInterrupt(CANA_BASE, CAN_INT_IE1 | CAN_INT_ERROR |

                        CAN_INT_STATUS);

 

    //

    // Interrupts that are used in this example are re-mapped to

    // ISR functions found within this file.

    // This registers the interrupt handler in PIE vector table.

    //

    Interrupt_register(INT_CANB0, &canISR_B);

    Interrupt_register(INT_CANA1, &canISR_A);

 

 

    //

    // Enable the CAN interrupt signal

    //

    Interrupt_enable(INT_CANB0);

    CAN_enableGlobalInterrupt(CANB_BASE, CAN_GLOBAL_INT_CANINT0);

 

    Interrupt_enable(INT_CANA1);

    CAN_enableGlobalInterrupt(CANA_BASE, CAN_GLOBAL_INT_CANINT1);

 

    //

    // Initialize the receive message object used for receiving CAN messages.

 

    int i;

    for (i = 0; i<4; i++)

    {

        CAN_setupMessageObject(CANB_BASE, OBJ_ID_FROM_AMK, AMK_VAL_1_IDS[i],        //AMK actual values 1

                               CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0x1FFFFFF0,

                               CAN_MSG_OBJ_RX_INT_ENABLE | CAN_MSG_OBJ_USE_ID_FILTER, MSG_DATA_LENGTH);

 

        CAN_setupMessageObject(CANB_BASE, OBJ_ID_FROM_AMK, AMK_VAL_2_IDS[i],        //AMK actual values 2

                               CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0x1FFFFFF0,

                               CAN_MSG_OBJ_RX_INT_ENABLE | CAN_MSG_OBJ_USE_ID_FILTER, MSG_DATA_LENGTH);

 

        CAN_setupMessageObject(CANB_BASE, (14 + i), AMK_SETPOINTS_IDS[i],           //AMK setpoints

                               CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_TX, 0,

                               CAN_MSG_OBJ_NO_FLAGS, sizeof(CAN_AMK_SET_POINT[i]));

 

    }

 

    CAN_setupMessageObject(CANB_BASE, OBJ_ID_FROM_SENDYNE, SENDYNE_ID,            //SENDYNE

                           CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0x0,

                           CAN_MSG_OBJ_RX_INT_ENABLE , MSG_DATA_LENGTH);

 

    CAN_setupMessageObject(CANA_BASE, 1, 0x120,

                            CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0x0,

                            CAN_MSG_OBJ_RX_INT_ENABLE , MSG_DATA_LENGTH);

 

    CAN_setupMessageObject(CANA_BASE, 2, 0x100,

                           CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_TX, 0,

                           CAN_MSG_OBJ_NO_FLAGS, 8);

 

    //

    // Start CAN module operations

    //

    CAN_startModule(CANB_BASE);

    CAN_startModule(CANA_BASE);

 

 

}

 

 

//

// CAN ISR - The interrupt service routine called when a CAN interrupt is

//           triggered.  It checks for the cause of the interrupt, and

//           maintains a count of all messages that have been transmitted.

//

__interrupt void

canISR_B(void)

{

    uint32_t status;

 

    //

    // Read the CAN interrupt status to find the cause of the interrupt

    //

    status = CAN_getInterruptCause(CANB_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(CANB_BASE);

 

        //

        // Check to see if an error occurred.

        //

        if(((status  & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 7) &&

           ((status  & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 0))

        {

            //

            // Set a flag to indicate some errors may have occurred.

            //

            errorFlag = 1;

        }

    }

 

    //

    // Check if the cause is the receive message object 2

    //

    else if(status == OBJ_ID_FROM_AMK)

    {

        //

        // Get the received message

        //

        CAN_readMessage(CANB_BASE, OBJ_ID_FROM_AMK, AMK_Values_temp);

 

        id = getMessageID(CANB_BASE,OBJ_ID_FROM_AMK);

 

        if (getAMKValNumber(id) == 1)

        {

            GPIO_togglePin(DEVICE_GPIO_PIN_LED2);

            rxBMsgCount++;

            read_AMK_Values1(AMK_Values_temp, getMotorIndex(id));

        }

        else if (getAMKValNumber(id) == 2)

        {

            GPIO_togglePin(DEVICE_GPIO_PIN_LED2);

            rxBMsgCount++;

            read_AMK_Values2(AMK_Values_temp, getMotorIndex(id));

        }

 

        //

        // Getting to this point means that the RX interrupt occurred on

        // message object 2, and the message RX is complete.  Clear the

        // message object interrupt.

        //

        CAN_clearInterruptStatus(CANB_BASE, OBJ_ID_FROM_AMK);

 

        //

        // 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.

        //

 

 

        //

        // Since the message was received, clear any error flags.

        //

        errorFlag = 0;

    } else if (status == OBJ_ID_FROM_SENDYNE)

    {

 

        //

        // Get the received message

        //

        CAN_readMessage(CANB_BASE, OBJ_ID_FROM_SENDYNE, (uint16_t *) CAN_SENDYNE_ACT_VALUES);

 

        id = getMessageID(CANB_BASE, OBJ_ID_FROM_SENDYNE);

 

        read_SENDYNE_Message(CAN_SENDYNE_ACT_VALUES);

 

        GPIO_togglePin(DEVICE_GPIO_PIN_LED2);

        rxBMsgCount++;

 

        CAN_clearInterruptStatus(CANB_BASE, OBJ_ID_FROM_SENDYNE);

 

    }

 

    //

    // 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(CANB_BASE, CAN_GLOBAL_INT_CANINT0);

 

    //

    // Acknowledge this interrupt located in group 9

    //

    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);

}

 

__interrupt void

canISR_A(void)

{

    uint32_t status;

 

    //

    // Read the CAN interrupt status to find the cause of the interrupt

    //

    status = CAN_getInterruptCause(CANA_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(CANA_BASE);

 

        //

        // Check to see if an error occurred.

        //

        if(((status  & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 7) &&

           ((status  & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 0))

        {

            //

            // Set a flag to indicate some errors may have occurred.

            //

            errorFlag = 1;

        }

    }

 

    //

    // Check if the cause is the receive message object 2

    //

    else if(status == 1)

    {

        //

        // Get the received message

        //

        CAN_readMessage(CANA_BASE, 1, RX_A_temp);

        GPIO_togglePin(DEVICE_GPIO_PIN_LED2);

 

        //

        // Getting to this point means that the RX interrupt occurred on

        // message object 2, and the message RX is complete.  Clear the

        // message object interrupt.

        //

        CAN_clearInterruptStatus(CANA_BASE, 1);

 

        //

        // 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.

        //

        rxAMsgCount++;

 

        //

        // 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(CANA_BASE, CAN_GLOBAL_INT_CANINT1);

 

    //

    // Acknowledge this interrupt located in group 9

    //

    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);

}

 

 

uint32_t getMessageID(uint32_t base, uint32_t objID)

{

    uint32_t msgID = 0;

 

    CAN_transferMessage(base, 2, objID, false);

 

    msgID = HWREG(base + CAN_O_IF2ARB);

    msgID &= CAN_IF2ARB_STD_ID_M;

    msgID = msgID >> CAN_IF2ARB_STD_ID_S;

 

    return msgID;

}

Note that in my project I am also using CPU timer interrupt 0, 1 and 2.

 

Any help is appreciated.

 

Alessandro Fano

 

  • Hi,

    The configuration for the interrupts looks correct. Can you verify if the message id is properly set for the receive object. 

    When you say it is transmitting correctly and not receiving, do you see the messages in the bus? and they are not being transferred to the msg RAM.

    Have you tried this with just polling to check if the connections and msg object configuration is correct (or reading the message after a delay CAN_readMessage()).

    Regards,

    Yashwant

  • Greetings,

     

    I know it is trasmitting correctly because I can check the CAN message using a Kvaser Blackbird v2 as CAN sniffer: what I see is that the message are being transmitted correctly.

    But if I try to send a message to the F28379D using the kvaser, the former never receive it.

    I think the probem is with the ISR, because I try adding a if else() condition so that the ISR go off whenever a message is sent, and it never goes off.

    I try the can_ex5_simple_receive example from C2000Ware and it works, so the connections are fine.

    I think the problem is with the interrupts.

  •     if(status == CAN_INT_INT0ID_STATUS)

    In your code you have enabled line 1 of CANA interrupt but in the ISR Line0 status is being checked and also instead of status == 1 it should be status == 1 << 16 as line 1 status starts from 16th bit of CAN_INT Register . 

    Line0 of CANA is different from Line0 of CANB. Hence you can use line0 for both the instances. 

    You would have to change the below line configurations to 0 for CANA and this code should work.

       Interrupt_enable(INT_CANA1);

        CAN_enableGlobalInterrupt(CANA_BASE, CAN_GLOBAL_INT_CANINT1);

        Interrupt_register(INT_CANA1, &canISR_A);

        CAN_enableInterrupt(CANA_BASE, CAN_INT_IE1 | CAN_INT_ERROR |
  • Thank you for your answer, this resolved my issue.

    Best Regards