FlexCAN check if rx frame with DLC shorter than 8 is available

cancel
Showing results for 
Search instead for 
Did you mean: 

FlexCAN check if rx frame with DLC shorter than 8 is available

556 Views
adria
Contributor I

Hi,

I am trying to read can frames by polling and, to check whether there a new frame available I check the corresponding bit from the IFLAG register. What I am seeing is that if the CAN message doesn't have a DLC equal to 8 bytes, then checking the IFLAG doesn't work. Does that make sense? Can anybody tell me how to check for a received frame no matter the DLC value?

I am using FLEXCAN0 through PTE4 and PTE5. The code line I use to check if there is a new frame is:

if ((CAN0->IFLAG1 >> 4) & 1)

Best regards,

Adria

Tags (1)
0 Kudos
6 Replies

431 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi Adria,

MB flag is set when message is successfully sent or received, regardless of payload.

Do you configure right addresses for the MB you are using? Tables 53-14 to 53-17 of the RM summarizes MB's address offset for different MBDSRn setting. 

The code should be correct for checking the MB4 flag.

BR, Petr

0 Kudos

431 Views
adria
Contributor I

Hi Petr,

Thanks for your answer.

I found out that DLC was not the cause, as you said. But I am still facing the same issue.

I configure FlexCAN0 with no FD feature, so I have 32 MB with 4 words each one (which makes a "classic size" payload of 8 bytes per message buffer)

Best regards,

Adria

0 Kudos

431 Views
adria
Contributor I

Hi again,

Sorry I accidentally sent my last message without finishing it...

Continuation:

I want to receive a bunch of CAN messages by polling and I don't want to transmit anything between receptions. The problem appears when I check for new message received. I do it by reading IFLAG1 for MB 4 (which is the one I enable for reception).

Best regards,

Adria

0 Kudos

431 Views
adria
Contributor I

Hi again,

Sorry, but each time you press Ctrl+S it posts the question and I do press those keys a lot, it is just a costume. I wish I could edit the first message and just add the text that is missing but I don't find the option to edit.

Continuation:

So, for the first CAN message received, the IFLAG1 works perfect. But for the next ones, it doesn't work, so I can't know when I have a new available CAN message after receiving the first one. I don't transmit anything after receiving the first message.

Any idea of what can be going on?

My CAN init function is as follows:

/*************************************************

**************** CODE START ****************

*************************************************/

#define MSG_BUF_SIZE 4 /* Msg Buffer Size. (CAN 2.0AB: 2 hdr + 2 data= 4 words) */
uint32_t i=0;

PCC->PCCn[PCC_FlexCAN0_INDEX] |= PCC_PCCn_CGC_MASK; /* CGC=1: enable clock to FlexCAN0 */
CAN0->MCR |= CAN_MCR_MDIS_MASK; /* MDIS=1: Disable module before selecting clock */
CAN0->CTRL1 &= ~CAN_CTRL1_CLKSRC_MASK; /* CLKSRC=0: Clock Source = oscillator (8 MHz) */
CAN0->MCR &= ~CAN_MCR_MDIS_MASK; /* MDIS=0; Enable module config. (Sets FRZ, HALT)*/
while (!((CAN0->MCR & CAN_MCR_FRZACK_MASK) >> CAN_MCR_FRZACK_SHIFT)) {}
/* Good practice: wait for FRZACK=1 on freeze mode entry/exit */
CAN0->CTRL1 = 0x00DB0006; /* Configure for 500 KHz bit time */
/* Time quanta freq = 16 time quanta x 500 KHz bit time= 8MHz */
/* PRESDIV+1 = Fclksrc/Ftq = 8 MHz/8 MHz = 1 */
/* so PRESDIV = 0 */
/* PSEG2 = Phase_Seg2 - 1 = 4 - 1 = 3 */
/* PSEG1 = PSEG2 = 3 */
/* PROPSEG= Prop_Seg - 1 = 7 - 1 = 6 */
/* RJW: since Phase_Seg2 >=4, RJW+1=4 so RJW=3. */
/* SMP = 1: use 3 bits per CAN sample */
/* CLKSRC=0 (unchanged): Fcanclk= Fosc= 8 MHz */
for(i=0; i<128; i++ ) { /* CAN0: clear 32 msg bufs x 4 words/msg buf = 128 words*/
CAN0->RAMn[i] = 0; /* Clear msg buf word */
}
for(i=0; i<16; i++ ) { /* In FRZ mode, init CAN0 16 msg buf filters */
CAN0->RXIMR[i] = 0xFFFFFFFF; /* Check all ID bits for incoming messages */
}
CAN0->RXMGMASK = 0x1FFFFFFF; /* Global acceptance mask: check all ID bits */
CAN0->RAMn[ 4*MSG_BUF_SIZE + 0] = 0x04000000; /* Msg Buf 4, word 0: Enable for reception */
/* EDL,BRS,ESI=0: CANFD not used */
/* CODE=4: MB set to RX inactive */
/* IDE=0: Standard ID */
/* SRR, RTR, TIME STAMP = 0: not applicable */
CAN0->RAMn[ 4*MSG_BUF_SIZE + 1] = 0x7E0 << 18; /* Msg Buf 4, word 1: */
/* PRIO = 0: CANFD not used */
CAN0->MCR = 0x0000001F; /* Negate FlexCAN 1 halt state for 32 MBs */
while ((CAN0->MCR && CAN_MCR_FRZACK_MASK) >> CAN_MCR_FRZACK_SHIFT) {}
/* Good practice: wait for FRZACK to clear (not in freeze mode) */
while ((CAN0->MCR && CAN_MCR_NOTRDY_MASK) >> CAN_MCR_NOTRDY_SHIFT) {}
/* Good practice: wait for NOTRDY to clear (module ready) */

/*************************************************

***************** CODE END ******************

*************************************************/

My CAN receive function is as follows:

/*************************************************

**************** CODE START ****************

*************************************************/

uint8_t j;

RxCODE = (CAN0->RAMn[ 4*MSG_BUF_SIZE + 0] & 0x07000000) >> 24; /* Read CODE field */
RxID = (CAN0->RAMn[ 4*MSG_BUF_SIZE + 1] & CAN_WMBn_ID_ID_MASK) >> CAN_CTRL2_MRP_SHIFT ;
RxLENGTH = (CAN0->RAMn[ 4*MSG_BUF_SIZE + 0] & CAN_WMBn_CS_DLC_MASK) >> CAN_WMBn_CS_DLC_SHIFT;
for (j=0; j<2; j++) { /* Read two words of data (8 bytes) */
RxDATA[j] = endianswap(CAN0->RAMn[ 4*MSG_BUF_SIZE + 2 + j]);
}
RxTIMESTAMP = (CAN0->RAMn[ 0*MSG_BUF_SIZE + 0] & 0x000FFFF);
CAN0->IFLAG1 = 0x00000010; /* Clear CAN 0 MB 4 flag without clearing others*/

/*************************************************

***************** CODE END ******************

*************************************************/

My CAN check if new message received is as follows:

/*************************************************

**************** CODE START ****************

*************************************************/

return (CAN0->IFLAG1 >> 4) & 1;    // Check if CAN 0 MB 4 flag is set

/*************************************************

***************** CODE END ******************

*************************************************/

Best regards,

Adria

0 Kudos

431 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi Adria,

the code looks correct, however I do not see you are going to unlock the MB4, which is needed to allow the MB to participate for next matching. This is done by reading CODE field of another MB or reading Timer register.

The function for MB reading can be following...

void FLEXCAN0_receive_msg(void)


uint8_t j;
uint32_t dummy;

RxCODE = (CAN0->RAMn[ 4*MSG_BUF_SIZE + 0] & 0x07000000) >> 24; /* Read CODE field */
RxID = (CAN0->RAMn[ 4*MSG_BUF_SIZE + 1] & CAN_WMBn_ID_ID_MASK) >> CAN_WMBn_ID_ID_SHIFT ;
RxLENGTH = (CAN0->RAMn[ 4*MSG_BUF_SIZE + 0] & CAN_WMBn_CS_DLC_MASK) >> CAN_WMBn_CS_DLC_SHIFT;
for (j=0; j<2; j++) { /* Read two words of data (8 bytes) */
RxDATA[j] = CAN0->RAMn[ 4*MSG_BUF_SIZE + 2 + j];
}
RxTIMESTAMP = (CAN0->RAMn[ 0*MSG_BUF_SIZE + 0] & 0x000FFFF);
dummy = CAN0->TIMER; /* Read TIMER to unlock message buffers */
CAN0->IFLAG1 = 0x00000010; /* Clear CAN 0 MB 4 flag without clearing others*/
}

BR, Petr

0 Kudos

431 Views
adria
Contributor I

Hi Petr,

I just found out that the problem wan't the software, it was something wrong with the EVB, I just changed it and it worked.

Thanks a lot for your support.

Best regards,

Adria

0 Kudos