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.

TMS320F28335: CAN cannot receive data

Part Number: TMS320F28335


Hi team,

Here's an issue from the customer may need your help:

Can baud rate 1 MHz, 3 nodes on CAN bus, host F28335, 2 slaves STM32F103.

After a period of operation, the DSP cannot enter CAN to receive interrupts, the bus usage is around 10%, and using the CAN monitoring tool it is found that the DSP message was sent, but the probability of occurrence is low. After printing CANES, CANTEC, CANREC, the error count is basically 0, because ABO=1 is set, CANES has not been processed:

/*
 * CanA.c
 *
 *  Created on: 2021年4月14日
 *      Author: NE3696
 *		 Email: mingwei.huang@e-nebula.com
 */


#include "Can.h"
#include "COProtocol.h"
#include <stdio.h>
#include "NEDataManager.h"

canRxIsrFunc _gCanARxIsrFunc = NULL;
canTxIsrFunc _gCanATxIsrFunc = NULL;

static void canAInitFunc(canConfigT *config);
static void canARegisterRxIsrFunc(canRxIsrFunc rxIsrFunc);
static void canARegisterTxIsrFunc(canTxIsrFunc txIsrFunc);
static Uint16 canAXmitMsg(Uint32 msgId, Uint16 *pdata, Uint16 msgLength, Uint16 type);
static Uint16 canASetRxMailBox(Uint32 cobId, Uint16 mailNumber, Uint16 dlc, Uint16 type);
static Uint32 canAerrorGet(void);

__interrupt void _gEcanARxIsr(void);
__interrupt void _gEcanATxIsr(void);


CanAccessT gCanAAccess = {
    canAInitFunc,
    canASetRxMailBox,
    canARegisterRxIsrFunc,
    canARegisterTxIsrFunc,
    canAXmitMsg,
    canAerrorGet
};

static canConfigT gCanAConfig = {.baudRate = CanBaudrate75MHZ250KBPS, .frameType = StandardFrame};

static void _canAInitMailBox(Uint16 type)
{
    // disable all mailbox first.
    ECanaRegs.CANME.all = 0;

    //ECanaRegs.CANGAM.all = 0x81FC0000; // set AMI = 1, ignore nodeId unused..
    ECanaRegs.CANMD.all = 0xFFFF0000; // 16-31 接收  0-15 发送
    ECanaRegs.CANME.all = 0xFFFF0000; // enable RX  16-31

    // set lam for rx mail box.
    volatile union CANLAM_REG *lam = &ECanaLAMRegs.LAM16;
    Uint16 i = 0;
    while (i < 16)
    {
        lam = &ECanaLAMRegs.LAM16 + i;
        if(type == StandardFrame) // standard frame
        {
            lam->all = 0x81fc0000;
        }
        else // expand frame
        {
            // lam->all = 0xFFFFFFF;// receive all message
            lam->all = 0x00000000;// must match all id
        }
        i++;
    }
}


static Uint16 gCanAMailboxIdleIndex = 16;
static Uint16 canASetRxMailBox(Uint32 cobId, Uint16 mailCount, Uint16 dlc, Uint16 type)
{
    if (gCanAMailboxIdleIndex >= 32 || (gCanAMailboxIdleIndex+mailCount > 32))
    {
        return CAN_ERROR;
    }

    volatile struct MBOX *pMailbox;
    Uint32 tempME = ECanaRegs.CANME.all;
    Uint32 flag = 0;

    while (mailCount--)
    {
        flag = 1L<<gCanAMailboxIdleIndex;

        pMailbox = &ECanaMboxes.MBOX0 + gCanAMailboxIdleIndex;

        // disable first
        ECanaRegs.CANME.all = tempME & ~flag;

        pMailbox->MSGID.all = 0;
        pMailbox->MSGID.bit.AME = 1; // only for rx mail box. Receive lam
        if(type == StandardFrame)
        {
            pMailbox->MSGID.bit.STDMSGID = cobId;
        }
        else
        {
            pMailbox->MSGID.all = cobId;
            pMailbox->MSGID.bit.IDE = 1;
            pMailbox->MSGID.bit.AME = 1;
            pMailbox->MSGID.bit.AAM = 0;
        }

        ECanaRegs.CANME.all = tempME | flag;

        pMailbox->MSGCTRL.bit.DLC = dlc&0xf;
        pMailbox->MDL.all = 0;
        pMailbox->MDH.all = 0;

        gCanAMailboxIdleIndex++;
    }

    return CAN_OK;
}

static void canAInitFunc(canConfigT *pConfig)
{
    if (NULL == pConfig)
    {
        pConfig = &gCanAConfig;
    }
    else
    {
        gCanAConfig = *pConfig; // update config
    }

    struct ECAN_REGS ECanaShadow;

    EALLOW;

    // set interrupt function
    PieVectTable.ECAN0INTA = &_gEcanATxIsr;
    PieVectTable.ECAN1INTA = &_gEcanARxIsr;

    // enable tx/rx
    ECanaShadow.CANTIOC.all = ECanaRegs.CANTIOC.all;
    ECanaShadow.CANTIOC.bit.TXFUNC = 1;
    ECanaRegs.CANTIOC.all = ECanaShadow.CANTIOC.all;

    ECanaShadow.CANRIOC.all = ECanaRegs.CANRIOC.all;
    ECanaShadow.CANRIOC.bit.RXFUNC = 1;
    ECanaRegs.CANRIOC.all = ECanaShadow.CANRIOC.all;
    EDIS;

    _canAInitMailBox(pConfig->frameType);

    EALLOW;
    ECanaRegs.CANMIM.all = 0xFFFF0000; // enable all mailbox interrupt
    ECanaRegs.CANMIL.all = 0xFFFF0000; // mailBox 16-31 in int1  , others in int0
    ECanaRegs.CANGIM.all = 0x2; // enable INT 0(tx), INT 1 (rx)

    // Request permission to change the configuration registers
    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.CCR = 1;
	ECanaShadow.CANMC.bit.DBO = 1;
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
    EDIS;

    // Wait until the CPU has been granted permission to change the
    // configuration registers
    // Wait for CCE bit to be set..
    do
    {
      ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    } while(ECanaShadow.CANES.bit.CCE != 1 );


    // Configure the eCAN timing
    EALLOW;
    ECanaShadow.CANBTC.all = ECanaRegs.CANBTC.all;
    ECanaShadow.CANBTC.bit.BRPREG = gCanBaudBRPValues[pConfig->baudRate];    // (BRPREG + 1) = 10 feeds a 15 MHz CAN clock
    ECanaShadow.CANBTC.bit.TSEG2REG = 5 ; // to the CAN module. (150 / 10 = 15)
    ECanaShadow.CANBTC.bit.TSEG1REG = 7;  // Bit time = 15
    ECanaRegs.CANBTC.all = ECanaShadow.CANBTC.all;

    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.CCR = 0;
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
    EDIS;

    // Wait until the CPU no longer has permission to change the
    // configuration registers
    do
    {
      ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    } while(ECanaShadow.CANES.bit.CCE != 0 );

    // Configure the eCAN for self test mode
    // Enable the enhanced features of the eCAN.
    EALLOW;
    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.DBO = 1;    //
    ECanaShadow.CANMC.bit.ABO = 1;    // auto bus on
    ECanaShadow.CANMC.bit.SCB = 1;    // eCAN mode (reqd to access 32 mailboxes)
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

    ECanaRegs.CANTA.all = 0xFFFFFFFF; /* Clear all TAn bits */
    ECanaRegs.CANRMP.all = 0xFFFFFFFF; /* Clear all RMPn bits */
    ECanaRegs.CANGIF0.all = 0xFFFFFFFF; /* Clear all interrupt flag bits */
    ECanaRegs.CANGIF1.all = 0xFFFFFFFF;
    EDIS;

    // set mailBox

}

static void canARegisterRxIsrFunc(canRxIsrFunc rxIsrFunc)
{
    _gCanARxIsrFunc = rxIsrFunc;
}

static void canARegisterTxIsrFunc(canTxIsrFunc txIsrFunc)
{
    _gCanATxIsrFunc = txIsrFunc;
}

volatile Uint16 gCanANextSendIndex = 0;

static Uint16 canAXmitMsg(Uint32 msgId, Uint16 *pdata, Uint16 msgLength, Uint16 type)
{
    // according to msgId, get the mail index
    Uint16 i = 0,  delay_cnt = 0;
    volatile struct MBOX *Mailbox;
    Uint32 flag;
    Uint32 tempME = ECanaRegs.CANME.all;
    Uint16 mailIndex;

    for (i = 0; i < 16; i++)
    {
        mailIndex = gCanANextSendIndex;
        flag = (1UL<<mailIndex);
        if (0 == (ECanaRegs.CANTRS.all&flag))
        {
            Mailbox = &ECanaMboxes.MBOX0 + mailIndex;
            gCanANextSendIndex = (gCanANextSendIndex+1)&0xF;
            ECanaRegs.CANME.all = tempME & (~flag);
            if(type == StandardFrame)
            {
                Mailbox->MSGID.all = 0;
                Mailbox->MSGID.bit.STDMSGID = msgId;
            }
            else
            {
                Mailbox->MSGID.bit.IDE = 1;
                Mailbox->MSGID.all = 0x80000000 | msgId;
            }
            // EDIS;

            Mailbox->MSGCTRL.all = 0;
            Mailbox->MSGCTRL.bit.RTR = 0;
            Mailbox->MSGCTRL.bit.TPL = 0;
            Mailbox->MSGCTRL.bit.DLC = msgLength&0xf;
            Mailbox->MDL.all = pdata[0] | (pdata[1]<<8) | (((Uint32)pdata[2])<<16) | (((Uint32)pdata[3])<<24);
            Mailbox->MDH.all = pdata[4] | (pdata[5]<<8) | (((Uint32)pdata[6])<<16) | (((Uint32)pdata[7])<<24);

            ECanaRegs.CANME.all  = tempME | flag;
            ECanaRegs.CANTRS.all = flag; // send data.

            while(((ECanaRegs.CANTA.all&flag) != flag) &&(delay_cnt++ < 20000)) {};
            if(delay_cnt >= 20000)
            {
                return CAN_ERROR;
            }
            ECanaRegs.CANTA.all = flag;
            break;
        }
    }

    if (i >= 16)
    {
        return CAN_ERROR;
    }

    return CAN_OK;
}

#pragma CODE_SECTION(_gEcanARxIsr, "ramfuncs");
__interrupt void _gEcanARxIsr(void)
{

    canRegCpy.IntCnt0++;

    // get mail box first
    Uint16 mailBoxIndex = ECanaRegs.CANGIF1.bit.MIV1;
    volatile struct MBOX *Mailbox;

    PieCtrlRegs.PIEACK.all |= PIEACK_GROUP9;          // Issue PIE ack
    // int nesting test
    IER |= M_INT3;
    EINT;
    ERTM;

    canRegCpy.IntCnt1++;
    // get data.
    if (ECanaRegs.CANRMP.all & (1L<<mailBoxIndex))
    {

        // canRegCpy.IntCnt2++;
		ECanaRegs.CANRMP.all = (1L<<mailBoxIndex);// reset flag

        if (_gCanARxIsrFunc)
        {
            // canRegCpy.IntCnt3++;
            Mailbox = &ECanaMboxes.MBOX0 + mailBoxIndex;
            COMessageT msg;
            if(!Mailbox->MSGID.bit.IDE)
            {
                msg.cobId = Mailbox->MSGID.bit.STDMSGID;
            }
            else
            {   msg.ide = 1;
                msg.msgId = ~(7UL<<29) & Mailbox->MSGID.all;
            }
            msg.data[0] = Mailbox->MDL.byte.BYTE3;
            msg.data[1] = Mailbox->MDL.byte.BYTE2;
            msg.data[2] = Mailbox->MDL.byte.BYTE1;
            msg.data[3] = Mailbox->MDL.byte.BYTE0;
            msg.data[4] = Mailbox->MDH.byte.BYTE7;
            msg.data[5] = Mailbox->MDH.byte.BYTE6;
            msg.data[6] = Mailbox->MDH.byte.BYTE5;
            msg.data[7] = Mailbox->MDH.byte.BYTE4;
            msg.dataLength = Mailbox->MSGCTRL.bit.DLC & 0x0F;
            msg.data64 = ((Uint64)Mailbox->MDH.all << 32) | Mailbox->MDL.all;

            if (msg.cobId == 0x581) {
                canRegCpy.IntCnt2 = msg.data[4] | (msg.data[5]<<8);
            }
            _gCanARxIsrFunc(&msg);
        }

    }
}

#pragma CODE_SECTION(_gEcanATxIsr, "ramfuncs");
__interrupt void _gEcanATxIsr(void)
{
    PieCtrlRegs.PIEACK.all |= PIEACK_GROUP9;          // Issue PIE ack
    // int nesting test
    IER |= M_INT3;
    EINT;
    ERTM;
}

Uint32 canAerrorGet(void)
{
    Uint32 temp;

    temp = (((ECanaRegs.CANES.all & 0x1F) << 25) | ECanaRegs.CANES.all) & 0xFFFF0000;
    temp |= ((ECanaRegs.CANREC.all << 8) | ECanaRegs.CANTEC.all) & 0xFFFF;
    return temp;
}

The CAN receive interrupt GIF1 flag involves a bit access issue (shadow register operation is required) and the baud rate in the code changed to 250Khz due to debug.

Could you help check this case? Thanks.

Best Regards,

Cherry

  • Cherry,

              Debugging code is not something we can support on the e2e forum. I request customer to look at the Debug tips provided. Most CAN issues can be resolved by going through this checklist. 

    If the mailbox interrupt is not asserted, it could be that the frame was not actually received in the mailbox.

    using the CAN monitoring tool it is found that the DSP message was sent,

    Message sent does not necessarily mean the message was received. Often this happens because the receive mailbox is not correctly configured anymore. either the MSGID is not an exact match or the filtering criterion does not work anymore. Please have customer verify if this is the case. Interrupts cannot suddenly stop working. There definitely has to be a configuration error.