如题,求助,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;
}