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.

Missing TX CAN interrupt on F28075

I am missing some (up to 25%) of Tx Interrupts when transmitting back-to-back CAN messages at 1 Mbps. All messages transmitted appear to be sent properly. I always check the the CAN transmission request register bit (CAN_TXRQ_21) for my transmit message object and only transmit if the message object bit is clear. I'm wondering if it is possible to see, via CAN_TXRQ_21, that there is no tranmission in progress and start a tranmission before the interrupt for the previous transmission has fired and if this would explain my observation. I also wondering if there is a way to guarantee that that all transmissions produce an interrupt.

  • John,

    Can you please post the ISR code you're using? I'm specifically interested in code that writes to PIEACK and CAN_GLB_INT_CLR.

    Thanks,
  • I'm attaching my CAN isr.

    Can_Isr.c
    interrupt void CANA_1_Isr(void)
    {
        unsigned long ulStatus;
    
        // Read the CAN interrupt status to find the cause of the interrupt.
        // This call returns the value of the CAN_INT register. The CAN_INT
        // has two fields, INT1ID [bits 22-16] and INT0ID [bits 15-0]. Since
        // Interrupt line 1 is not enabled INT1ID will not be set and the
        // mailbox indication will be part of INT0ID.
        ulStatus = CANIntStatus((uint32_t) &CanaRegs, CAN_INT_STS_CAUSE);
    
        // If the INT0ID field equals CAN_INT_INT0ID_STATUS then this is a
        // status interrupt, which is a higher priority that any mailbox
        // interrupt.
        if(ulStatus == CAN_INT_INT0ID_STATUS)
        {
            // This is a status interrupt so now we read the error and status
            // register, CAN_ES. This will return a field of status and
            // error bits that can indicate various status and errors.
            // The act of reading this register will clear the interrupt.
            // If the CAN peripheral is not connected to a CAN bus with other
            // CAN devices present, then errors will occur and will be indicated
            // in this register.
            ulStatus = CANStatusGet((uint32_t) &CanaRegs, CAN_STS_CONTROL);
    
            // Check to see if an error occured. We are going to set the
            // error flag if any bit in the error status register is set (
            // except for CAN_ES_TXOK and CAN_ES_TXOK which are success
            // statuses) and the LEC field [bits 2-0] is not 7 (no CAN bus
            // event occured since that last time this register was read) or
            // 0 (no error).
            if(((ulStatus & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != CAN_STATUS_LEC_MSK) &&
                ((ulStatus & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != CAN_STATUS_LEC_NONE))
            {
                // Set a flag to indicate some errors may have occurred.
                g_canErrFlag = 1;
            }
            // The call to CANStatusGet(), i.e., reading CAN_ES, clears the status
            // interrupt.
        }
    
        /*************************************************************************
        Values between 1 and 32 in INT0ID (or INT1ID if interrupt line 1 is
        is enabled) indicate the source of the interrupt is one of the messaage
        objects (mailboxes) and INT0ID (or INT1ID) will point to the message
        object. Message object 1 has the highest priority and 32 the lowest.
    
        The message object will be read and it's IntPnd bit cleared. This allows
        the enabled interrupt line (0 or 1) to be reasserted and INT0ID
        (or INT1ID) of CAN_INT to point to the next higher message object with a
        pending interrupt.
    
        This ISR is setup to handle message object and status (and error)
        interrupts. If message object handling is ever dedicated to interrupt line
        1 then the INT1ID field wil be used to identify the message object with
        the message object number located in bits [20-16] instead of bits
        [4-0] of the CAN_INT register.
        *************************************************************************/
    
        // Check if the cause is message object TRANSMIT_MAILBOX, which what we
        // are using for sending messages.
        else if(ulStatus == TRANSMIT_MAILBOX)
        {
            // Getting to this point means that the TX interrupt occurred on
            // message object TRANSMIT_MAILBOX, and the message TX is complete.
            // Clear the message object interrupt.
            CANIntClear((uint32_t) &CanaRegs, TRANSMIT_MAILBOX);
    
            // Increment a counter to keep track of how many messages have been
            // sent.  Could rollover but used in debugger only.
            g_canTxMsgCount++;
    
            // Since the message was sent, clear any error flags.
            g_canErrFlag = 0;
        }
    
        // Check if the cause is message object STD_RECEIVE_MAILBOX, which what we are using for
        // receiving messages with a standard header (arbitration id).
        else if(ulStatus == STD_RECEIVE_MAILBOX)
        {
            // Getting to this point means that the RX interrupt occurred on
            // message object STD_RECEIVE_MAILBOX, and the message RX is complete.
    
            // Receive the CAN message
            Can_Receive(CAN_CHANNEL_A, STD_RECEIVE_MAILBOX);
    
            // No need to clear the mailbox pending interrupt here. This is done
            // with the call to CANMessageGet() in Can_Receive().
    
            // Increment a counter to keep track of how many messages have been
            // received in this mailbox.  Could rollover but used in debugger only.
            g_canStdRxMsgCount++;
    
            // Since the message was received, clear any error flags.
            g_canErrFlag = 0;
        }
    
        // Check if the cause is message object EXT_RECEIVE_MAILBOX, which what we are using for
        // receiving messages with a extended header (arbitration id).
        else if(ulStatus == EXT_RECEIVE_MAILBOX)
        {
            // Getting to this point means that the RX interrupt occurred on
            // message object EXT_RECEIVE_MAILBOX, and the message RX is complete.
    
            // Receive the CAN message
            Can_Receive(CAN_CHANNEL_A, EXT_RECEIVE_MAILBOX);
    
            // No need to clear the mailbox pending interrupt here. This is done
            // with the call to CANMessageGet() in Can_Receive().
    
            // Increment a counter to keep track of how many messages have been
            // received in this mailbox. Could rollover but used in debugger only.
            g_canExtRxMsgCount++;
    
            // Since the message was received, clear any error flags.
            g_canErrFlag = 0;
        }
    
        CANGlobalIntClear((uint32_t) &CanaRegs, CAN_GLB_INT_CANINT0);
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
    }