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: DCAN and interrupts

Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE

I changed can_ex2_loopback_interrupts sample from C2000Ware 3.04 to consider differences in my hardware setup (CAN-B instead of CAN-A, other GPIOs and 1 Mbit/s instead of 500 Kbit/s). Also I disabled external loopback mode and the code that sends packets (because I want to test receive part). Now I see two strange behaviour:

1) ISR is called twice after receiving a CAN-packet with CAN-id 0x1 which is specified as an ID for receive mailbox. The first time it is called as a response to status change and the second time it's called as a response to mailbox event.

It seems to me that from the point of performance both events should be handled in one call. So the logic of ISR should be like so:

         //
    // Read the CAN interrupt status to find the cause of the interrupt
    //
    status = CAN_getInterruptCause(CAN_BASE);

    //
    // If the cause is a controller status interrupt, then get the status
    //
    if(status == CAN_INT_INT0ID_STATUS)
    {
        // code from sample
        // ...
        
        // read interrupt status again to get another causes
        status = CAN_getInterruptCause(CAN_BASE);               // <----- new code
    }

    //
    // Check if the cause is the transmit message object 1
    //
    if(status == TX_MSG_OBJ_ID)         // <--- here without "else"
    {
        // ...

        // not sure whether should I repeat call to CAN_getInterruptCause() here as above and remove "else" clause from below
    }

    //
    // Check if the cause is the receive message object 2
    //
    else if(status == RX_MSG_OBJ_ID)                    // <------ maybe one should remove "else" keyword here as above
    {
        // ...
    }

    // ...

2) ISR is called even if CAN-packet with any other ID is received. What's the purpose of such behaviour? Why controller reacts to packets that it's not interrested in (i.e. is not configured for receiving them)?

I don't want to react to any CAN-packet in CAN-network but want to react to errors. Is it possible ?

Regards,
Alex

  • I think ISR should be implemented as a loop until CAN_getInterruptCause() returns zero:

        status = CAN_getInterruptCause(CAN_BASE);

        while( status != 0 ){

            if(status == CAN_INT_INT0ID_STATUS)
            {

               // ...
            }
            else if(status == TX_MSG_OBJ_ID)
            {
               // ...

            }

            else if(status == RX_MSG_OBJ_ID)
            {
               // ...

            }

            else
            {
               // ...

            }

            status = CAN_getInterruptCause(CAN_BASE);
        }

        CAN_clearGlobalInterruptStatus(CAN_BASE, CAN_GLOBAL_INT_CANINT0);

        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);

    Regards,
    Alex

  • You are correct that the ISR is entered twice. The examples are just to help someone get started on using the DCAN module. They may or may not correlate well to a real-world situation.

    CAN_CTL register has separate enable bits for Error and Status change. You could enable the former and disable the latter. It also has IE0 & IE1 bits using which you can enable valid message object interrupts.

  • CAN_CTL register has separate enable bits for Error and Status change. You could enable the former and disable the latter. It also has IE0 & IE1 bits using which you can enable valid message object interrupts.

    Do you mean to clear CAN_CTL.SIE ? If I do so then I will miss LEC changes, don't I?

  • LEC changes primarily pertain to error conditions. By keeping EIE active you should still be able to have interrupts generated for errors.

  • Sorry, I don't understand. I see four error bits that can trigger an interrupt if CAN_CTL.EIE is set: PER, Boff, EWarn, EPass. PER pertains to Message RAM so we have only three error bits that describe the state of the CAN bus. All of these three error bits (Boff, EWarn, EPass) are set or cleared based on internal error counters. And they don't describe the cause why those internal error counters were incremented.

    So one has three alternatives regarding error diagnostic:

    1) disable both EIE and SIE and therefore ignore any error

    2) disable SIE and enable EIE and get only summary information about state of the CAN bus

    3) enable both SIE and EIE and get triggered on every error on the bus. But in this case one has to react to any received CAN packet even for good packets for other nodes on the bus, even when the bus is working perfect.

    Do I understand it right?

    Regards,
    Alex

  • I see four error bits that can trigger an interrupt if CAN_CTL.EIE is set: PER, Boff, EWarn, EPass.

    Per spec, EPass does not assert an interrupt, but this is not very important to the discussion.

    we have only three error bits that describe the state of the CAN bus.

    These 3 bits reflect the state of the error counters, which in turn is a reflection of the bus condition,

    All of these three error bits (Boff, EWarn, EPass) are set or cleared based on internal error counters.

    True.

    And they don't describe the cause why those internal error counters were incremented.

    True, but LEC indicates the type of error encountered.

    Your understanding is correct.

    In a properly designed/configured network, communication errors should be rare. It could happen due to external noise, but the bus should recover on its own once the disturbances vanish. That is how the protocol is designed. On a different note, Application report http://www.ti.com/lit/spracq3 provides a tool to introduce error at a chosen bit location. You can use this tool to generate different types of errors.