Inconsistent CAN reception Issue

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Inconsistent CAN reception Issue

Jump to solution
663 Views
Anilpatil_SasvaAuto
Contributor III

Subject: Inconsistent CAN Message Reception Issue

Hello Team,

I am encountering an issue with receiving CAN messages consistently. I have configured 4 message buffers (MBs) to receive 4 Rx messages.

Issue:
Observation 1: When I send the first message (0x301) from the IG block in the CANOE tool, the MPC5748G micro can receive the message, and the respective ISR hits. However, if I send the same message again, the ISR does not hit at any time.


Observation 2: Following observation 1, if I send the second message (0x302), the MPC5748G micro can receive the message, and the respective ISR hits. If I send the first message again, the ISR hits, but subsequent attempts to send the same message do not trigger the ISR.

Observation 3: If the same message is sent successively, none of the ISRs will be triggered repeatedly. However, sending four different messages one by one will trigger the respective ISRs.

Your help with this issue would be greatly appreciated. Please provide the solution on urgent basis.

Thank you.

Please review the following functions:

1.CAN Initialization function:

void Can_InitCAN0 (void)
{
uint8_t index;

CAN_0.MCR.B.MDIS = 1; /* Disable module before selecting clock source*/
CAN_0.CTRL1.B.CLKsrc=0; /* Clock Source = oscillator clock (40 MHz) */
CAN_0.MCR.B.MDIS = 0; /* Enable module for config. (Sets FRZ, HALT)*/

while (!CAN_0.MCR.B.FRZACK) {}/* Wait for freeze acknowledge to set */
/* Good practice: wait for FRZACK on freeze mode entry/exit */

CAN_0.CTRL1.R = 0x04DB0086; /* CAN bus: 40 MHz clksrc, 500 kbps with 16 tq */ // 0x27590000
/* PRESDIV+1 = Fclksrc/Ftq = 40 MHz/8MHz = 5 */
/* so PRESDIV = 4 */
/* PSEG2 = Phase_Seg2 - 1 = 4 - 1 = 3 */
/* PSEG1 = PSEG2 = 3 */
/* PROPSEG= Prop_Seg - 1 = 7 - 1 = 6 */
/* RJW = Resync Jump Width - 1 = 4 = 1 */
/* SMP = 1: use 3 bits per CAN sample */
/* CLKsrc=0 (unchanged): Fcanclk= Fxtal= 40 MHz*/

CAN_0.MCR.R |= CAN_MCR_FRZ | CAN_MCR_HALT; /* enabled to enter Freeze mode */

while (0 == CAN_0.MCR.B.FRZACK){};
while (0 == CAN_0.MCR.B.NOTRDY){}; /* double check that we are actually in freeze mode */

CAN_0.MCR.B.IRMQ = 1; /* Individual Rx Masking And Queue Enable */
#ifdef CAN_0_LOOP_BACK_ENABLED
CAN_0.MCR.B.SRXDIS = 0; /* Self Reception Enable */
#else
CAN_0.MCR.B.SRXDIS = 1; /* Self Reception Disable */
#endif
CAN_0.MCR.B.RFEN = 0; /* RX FIFO Disabled */
CAN_0.MCR.B.AEN = 1; /* Abort Enabled */
CAN_0.MCR.B.FDEN = 0; /* CAN-FD Enabled */
CAN_0.MCR.B.IDAM = 0; /* ID Acceptance Mode is one full ID */
CAN_0.MCR.B.MAXMB = 0x3F; /* 64 MBs */

CAN_0.CTRL1.B.SMP = 1; /* SMP = 1: use 3 bits per CAN sample */
#ifdef CAN_0_LOOP_BACK_ENABLED
CAN_0.CTRL1.B.LPB = 1; /* Loopback Enabled */
#else
CAN_0.CTRL1.B.LPB = 0; /* Loopback Disabled */
#endif

for (index=0; index<96; index++)
{
CAN_0.MB[index].CS.R = 0; /* Inactivate all 96 message buffers */
}

/****Disable CAN FD****/
#if 0
CAN_0.FDCTRL.B.FDRATE = 1; /* Flexible Data Rate Enabled */
CAN_0.FDCTRL.B.MBDSR0 = 0; /* MB data size for R0 is 8 Bytes */
CAN_0.FDCTRL.B.MBDSR1 = 3; /* MB data size for R1 is 64 Bytes */
CAN_0.FDCTRL.B.MBDSR2 = 3; /* MB data size for R2 is 64 Bytes */

CAN_0.CBT.R = 0x80242844; /* Bit timing parameters */
CAN_0.FDCBT.R = 0x001614C6; /* Bit timing parameters */
#endif
for (index=0; index<96; index++)
{
CAN_0.RXIMR[index].R = 0x1FFFFFFF; /* RX Individual Mask is set to check all bits with MB ID */
}

CAN_0.RXIMR[45].R = 0; /* MB 45 used for TX */

/* enable interrupt for MB45 - Transmit complete Interrupt */
CAN_0.IMASK2.R |= 1U << 13U;

Can_InitCAN0RxMsgBuffers ();

CAN_0.RXMGMASK.R = 0x1FFFFFFF;

INTC.PSR[568].B.PRC_SELN = 0x8;
INTC.PSR[568].B.PRIN = 12;

INTC.PSR[569].B.PRC_SELN = 0x8;
INTC.PSR[569].B.PRIN = 12;

INTC.PSR[570].B.PRC_SELN = 0x8;
INTC.PSR[570].B.PRIN = 12;

INTC.PSR[571].B.PRC_SELN = 0x8;
INTC.PSR[571].B.PRIN = 12;

INTC.PSR[572].B.PRC_SELN = 0x8;
INTC.PSR[572].B.PRIN = 12;

INTC.PSR[573].B.PRC_SELN = 0x8;
INTC.PSR[573].B.PRIN = 12;

Can0PortInit ();

/*CAN_0.CTRL2.R |= 0x00001000u; // ISOCANFD Enabled*/

CAN_0.IFLAG1.R = 0xFFFFFFFFU;
CAN_0.IFLAG2.R = 0xFFFFFFFFU;

/* enable the FlexCAN module, reset and freeze */
CAN_0.MCR.R &= ~(CAN_MCR_FRZ | CAN_MCR_HALT);

while (CAN_0.MCR.B.FRZACK & CAN_0.MCR.B.NOTRDY) {} /* Wait to clear */
/* Good practice: wait for FRZACK on freeze mode entry/exit */
}

2.CAN ISR for 4 MBs are as below:

void Can_MsgBuf0003ISR (void)
{
uint8 Channel;
uint8 ReturnValue = 0U;
uint32 RegValue;

Channel = 0U;

if (0U != (CAN_0.IFLAG1.R & (1U << Can_RxMsgBufConfig[Channel].MB)))
{
ReturnValue |= Can_RxMsg ( Channel, Can_RxMsgBufConfig[Channel].MsgPtr);
}

Channel = 1U;
if (0U != (CAN_0.IFLAG1.R & (1U << Can_RxMsgBufConfig[Channel].MB)))
{
ReturnValue |= Can_RxMsg ( Channel, Can_RxMsgBufConfig[Channel].MsgPtr);
}

Channel = 2U;
if (0U != (CAN_0.IFLAG1.R & (1U << Can_RxMsgBufConfig[Channel].MB)))
{
ReturnValue |= Can_RxMsg ( Channel, Can_RxMsgBufConfig[Channel].MsgPtr);
}

Channel = 3U;
if (0U != (CAN_0.IFLAG1.R & (1U << Can_RxMsgBufConfig[Channel].MB)))
{
ReturnValue |= Can_RxMsg ( Channel, Can_RxMsgBufConfig[Channel].MsgPtr);
}
}

3.Message buffers initialization function:

void Can_InitCAN0RxMsgBuffers (void)
{
uint8 MsgIndex;
uint32 StandardID;

for (MsgIndex=0; MsgIndex < NUM_OF_RX_MSGS; MsgIndex++)
{
StandardID = Can_RxMsgBufConfig[MsgIndex].StdID;

*((uint32 *)(CAN0_BASE_REG_ADDR + Can_RxMsgBufConfig[MsgIndex].MBAddrOffset)) = MB_CS_SET_EDL | MB_CS_SET_BRS | MB_CS_CODE_INACTIVE | MB_CS_STD_IDE;

*((uint32 *)(CAN0_BASE_REG_ADDR + Can_RxMsgBufConfig[MsgIndex].MBAddrOffset + 4U)) = MB_STD_ID & (StandardID << 18);

*((uint32 *)(CAN0_BASE_REG_ADDR + Can_RxMsgBufConfig[MsgIndex].MBAddrOffset)) |= MB_CS_CODE_EMPTY;

if (Can_RxMsgBufConfig[MsgIndex].MB < 32U)
{
CAN_0.IMASK1.R |= 1 << Can_RxMsgBufConfig[MsgIndex].MB;
}
else
{
CAN_0.IMASK2.R |= 1 << (Can_RxMsgBufConfig[MsgIndex].MB - 32U);
}
}
}

4.Receive_Msg() function:

uint8 Can_RxMsg (uint8 Channel, Can_MsgType * Msg)
{
uint32 IFlag;
uint8 *P8CAN0RxMBData;
uint8 Index;
uint8 ReturnValue = 0U;

if (Channel < NUM_OF_RX_MSGS)
{
if (Can_RxMsgBufConfig[Channel].MB < 32U)
{
IFlag = CAN_0.IFLAG1.R & (1U << Can_RxMsgBufConfig[Channel].MB);
}
else
{
IFlag = CAN_0.IFLAG2.R & (1U << (Can_RxMsgBufConfig[Channel].MB - 32U));
}

if (0U != IFlag)
{
Msg->StdID = ((*((uint32 *)(CAN0_BASE_REG_ADDR + Can_RxMsgBufConfig[Channel].MBAddrOffset + 4U))) & MB_STD_ID) >> 18;

Msg->DLC = ((*((uint32 *)(CAN0_BASE_REG_ADDR + Can_RxMsgBufConfig[Channel].MBAddrOffset))) & MB_CS_DLC) >> 16;

Msg->NoOfBytes = Can_CalcNoOfBytes (Msg->DLC);

P8CAN0RxMBData = (uint8 *) (CAN0_BASE_REG_ADDR + Can_RxMsgBufConfig[Channel].MBAddrOffset + 8U);

for (Index=0; Index < Msg->NoOfBytes; Index++)
{
Msg->Payload[Index] = *(P8CAN0RxMBData + Index); /* Load data to be transmitted */
}


if (Can_RxMsgBufConfig[Channel].MB < 32U)
{
CAN_0.IFLAG1.R = (1U << Can_RxMsgBufConfig[Channel].MB);
}
else
{
CAN_0.IFLAG2.R = (1U << (Can_RxMsgBufConfig[Channel].MB - 32U));
}

LED_DS7 = ~LED_DS7;

Msg->MsgRcvd++;

ReturnValue = 1U;

CAN_0.IFLAG1.R = 0xFFFFFFFFU;
CAN_0.IFLAG2.R = 0xFFFFFFFFU;
}
}

return (ReturnValue);
}

5.Unmask Interrupt function:

void Can_UnMaskInterrupt (uint8 Channel, uint32 RegValue)
{
uint8 IntrID = Can_RxMsgBufConfig[Channel].IntrID;

switch (IntrID)
{
case 0U : CAN_0.IMASK1.R = RegValue;
break;

case 1U : CAN_0.IMASK1.R = RegValue;
break;

case 2U : CAN_0.IMASK1.R = RegValue;
break;

case 3U : CAN_0.IMASK1.R = RegValue;
break;

case 4U : CAN_0.IMASK1.R = RegValue;
break;

case 5U : CAN_0.IMASK2.R = RegValue;
break;

default : break;
}
}

6.Mask Interrupt function:

uint32 Can_MaskInterrupt (uint8 Channel)
{
uint32 RegValue;
uint8 IntrID = Can_RxMsgBufConfig[Channel].IntrID;

switch (IntrID)
{
case 0U : RegValue = CAN_0.IMASK1.R;
CAN_0.IMASK1.R &= 0xFFFFFFF0U; // MB 0-3
break;

case 1U : RegValue = CAN_0.IMASK1.R;
CAN_0.IMASK1.R &= 0xFFFFFF0FU; // MB 4-7
break;

case 2U : RegValue = CAN_0.IMASK1.R;
CAN_0.IMASK1.R &= 0xFFFFF0FFU; // MB 8-11
break;

case 3U : RegValue = CAN_0.IMASK1.R;
CAN_0.IMASK1.R &= 0xFFFF0FFFU; // MB 12-15
break;

case 4U : RegValue = CAN_0.IMASK1.R;
CAN_0.IMASK1.R &= 0x0000FFFFU; // MB 16 - 31
break;

case 5U : RegValue = CAN_0.IMASK2.R;
CAN_0.IMASK2.R &= 0x00000000U; // MB 32+ ... including MB 45 used for TX
break;

default : break;
}

return RegValue;
}

 

0 Kudos
Reply
1 Solution
647 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

a behavior is due to way you unlock MB. The MB is locked when reading its Control&Status word, it is unlocked when user read free running timer register or read another MB's CS word. When MB is locked it is not free to receive. Read chapter 43.5.7.3 Mailbox lock mechanism for more info.
As you do not unlock MB globally, using CAN_TIMER read, then the MB will get new message once another one is serviced, that is your observation 3.
So add reading CAN_TIMER after MB is serviced in your Can_RxMsg function. 
And remove CAN_0.IFLAG1.R = 0xFFFFFFFFU;CAN_0.IFLAG2.R = 0xFFFFFFFFU; lines at the end as it can also clear other asserted flags. Clear just flag for serviced MB.

BR, Petr 

View solution in original post

0 Kudos
Reply
5 Replies
648 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

a behavior is due to way you unlock MB. The MB is locked when reading its Control&Status word, it is unlocked when user read free running timer register or read another MB's CS word. When MB is locked it is not free to receive. Read chapter 43.5.7.3 Mailbox lock mechanism for more info.
As you do not unlock MB globally, using CAN_TIMER read, then the MB will get new message once another one is serviced, that is your observation 3.
So add reading CAN_TIMER after MB is serviced in your Can_RxMsg function. 
And remove CAN_0.IFLAG1.R = 0xFFFFFFFFU;CAN_0.IFLAG2.R = 0xFFFFFFFFU; lines at the end as it can also clear other asserted flags. Clear just flag for serviced MB.

BR, Petr 

0 Kudos
Reply
641 Views
Anilpatil_SasvaAuto
Contributor III
how to read the CAN_TIMER after MB
0 Kudos
Reply
644 Views
Anilpatil_SasvaAuto
Contributor III
Hello Petr,
Thanks for your reply.
could you please provide the example code to resolve my issue.
Requirement: Each ISR shall hit on successful reception of the respective messages.
please its very urgent
0 Kudos
Reply
640 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

try below function

uint8 Can_RxMsg (uint8 Channel, Can_MsgType * Msg)
{
uint32 IFlag, dummy;
uint8 *P8CAN0RxMBData;
uint8 Index;
uint8 ReturnValue = 0U;

if (Channel < NUM_OF_RX_MSGS)
{
if (Can_RxMsgBufConfig[Channel].MB < 32U)
{
IFlag = CAN_0.IFLAG1.R & (1U << Can_RxMsgBufConfig[Channel].MB);
}
else
{
IFlag = CAN_0.IFLAG2.R & (1U << (Can_RxMsgBufConfig[Channel].MB - 32U));
}

if (0U != IFlag)
{
Msg->StdID = ((*((uint32 *)(CAN0_BASE_REG_ADDR + Can_RxMsgBufConfig[Channel].MBAddrOffset + 4U))) & MB_STD_ID) >> 18;

Msg->DLC = ((*((uint32 *)(CAN0_BASE_REG_ADDR + Can_RxMsgBufConfig[Channel].MBAddrOffset))) & MB_CS_DLC) >> 16;

Msg->NoOfBytes = Can_CalcNoOfBytes (Msg->DLC);

P8CAN0RxMBData = (uint8 *) (CAN0_BASE_REG_ADDR + Can_RxMsgBufConfig[Channel].MBAddrOffset + 8U);

for (Index=0; Index < Msg->NoOfBytes; Index++)
{
Msg->Payload[Index] = *(P8CAN0RxMBData + Index); /* Load data to be transmitted */
}


if (Can_RxMsgBufConfig[Channel].MB < 32U)
{
CAN_0.IFLAG1.R = (1U << Can_RxMsgBufConfig[Channel].MB);
}
else
{
CAN_0.IFLAG2.R = (1U << (Can_RxMsgBufConfig[Channel].MB - 32U));
}

dummy = CAN_0.TIMER.R;  // unlock MB globally

LED_DS7 = ~LED_DS7;

Msg->MsgRcvd++;

ReturnValue = 1U;

//CAN_0.IFLAG1.R = 0xFFFFFFFFU;
//CAN_0.IFLAG2.R = 0xFFFFFFFFU;
}
}

return (ReturnValue);
}

BR, Petr

0 Kudos
Reply
634 Views
Anilpatil_SasvaAuto
Contributor III
Thanks for your support.
Somewhat working. I will let you know the behavior after the complete testing.
0 Kudos
Reply