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