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运行一段时间后,无法接受数据,但可以发送数据,接收使用中断,发送不用中断

Part Number: TMS320F28335


如题,求助,CAN波特率1MHz,CAN总线上3个节点,主机F28335,2个从机STM32F103,运行一段时间后DSP无法进入CAN接收中断,总线使用率10%左右,使用CAN监测工具发现DSP报文有发送出来,出现概率很低,几天出现一次,打印过CANES和CANTEC,CANREC,错误计数基本都是0,由于设置ABO=1,故没有处理CANES,代码如下:

/*
 * 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;
}