CAN FIFO Issues & Questions

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

CAN FIFO Issues & Questions

4,515 Views
jeremiahg
Contributor III

I'm having some troubles filtering CAN messages. Specifically, the RX individual masks don't seem to be doing anything. I am using the global Rx Fifo mask which does work. I have my CAN configured with 16 Mailboxes, 16 RX FIFO Filters, Use Rx FIFO, and the Payload Size of 8. From what I read in the reference manual, Table Elements 0-9 should be affected by RX Individual Masks when enabled. What I don't know is how to enable them. I don't see any registers that enable them. I thought they're enabled when setting them using

FLEXCAN_DRV_SetRxIndividualMask(can_instance, FLEXCAN_MSG_ID_EXT, 0U, 0xff0000);‍‍

What exactly am I missing here? Right now the messages are only filtered based on the global mask and my ID table elements.

I noticed something strange when switching from the normal Rx to FIFO Rx. When a CAN messaged was received with the normal Rx, it would look like

Identifier         DATA:   B0   B1   B2   B3   B4   B5   B6   B7

but when received via the Rx FIFO, it would like like

Identifier         DATA:   B3  B2   B1   B0   B7   B6   B5   B4

I couldn't figure out why my CAN messages weren't functioning correctly until I found out the data needed to be swapped. The identifier was correct, but the data was not. I have not located anything in the reference manual that discusses endianness differences with the CAN FIFO.

I sending the messages with CANalyzer as 

Identifier         DATA:   B0   B1   B2   B3   B4   B5   B6   B7

Lastly, I just want to make sure I'm emptying the FIFO buffer correctly. I'm using ProcessorExpert functions. What I do is read

if(FLEXCAN_DRV_GetReceiveStatus(indexCANPort) == FLEXCAN_STATUS_SUCCESS‍) ...

Then read my buffer with the received CAN message. Finally I start the next receive by

FLEXCAN_DRV_RxFifo(FSL_CANCOM1, &RxBuffer[indexCANPort]);

I've put

FLEXCAN_DRV_GetReceiveStatus(indexCANPort) == FLEXCAN_STATUS_SUCCESS‍

in a for loop with a maximum limit of 6 checks in case there is more than one message in the FIFO. This approach seems to work as I've seen times when at least two messages were pulled out of the FIFO. Is this the correct approach? I don't see any other PE functions that can tell me how many messages are in the FIFO.

I'm using S32 Design Studio V1.2 with S32_SDK_EAR_0.8.1 and my MCU is the S32K144 64-pin V1.0.

I wanted to see if anything changed with the next SDK version, but the only way to access the change log for the SDK is to installed S32 Design Studio V1.3. This requires V2.0 MCUs. I actually installed it awhile back until I realized it doesn't support V1.0 MCUs. It also caused havoc with my V1.2 install as the SDK links changed.

Thanks,

Jeremiah

Labels (1)
Tags (2)
6 Replies

2,740 Views
mikhail_l
Contributor II

Hi Jeremiah,

I also noticed CAN data byte swapping problem in RX FIFO mode. In normal (mailbox) mode it does not happen.

I am currently reversing received bytes in my code to fix the problem, but it looks like a hardware bug to me.

Using debugger. I see swapped bytes in dedicated CAN RAM memory even before driver code reads them.

Have you learned anything new about this issue?

Thanks,

Mikhail

2,740 Views
jeremiahg
Contributor III

Mikhail,

No, I have not learned regarding the byte swapping. I presenting what I was experiencing above. I've seen a few other threads here discussing byte swapping too. I have not seen official answer to why it is different when not using the FIFO. I'm going with the flow for now, swapping the bytes when I read the FIFO buffer.

I did learn that the global mask for the FIFO is just like the individual one where you need to shift the mask by one bit. My CAN filtering is working pretty well now with an ID table along with the global mask.

I know in a few weeks if anything has change when I move to S32 Design Studio V1.3 with Update 1. I have some boards coming with the V2.0 MCU that supports V1.3 IDE.

Regards,

Jeremiah

2,740 Views
mikhail_l
Contributor II

Hi Jeremiah,

It is a driver issue as Petr correctly pointed out in another thread. The driver correctly handles conversion to little endian in normal (mailbox) mode, but does not do it in RX FIFO mode.

2,740 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi Jeremiah,

The Individual masking is enabled by MCR[IRMQ] bit. Once set the individual RX masking is enabled. The ID Filter elements then use RX individual mask registers and RX FIFO global mask register as per setting of CTRL2[RFFN]

 pastedImage_1.png

For your setting above highlighted option is valid.

The FLEXCAN_DRV_SetRxMaskType (FSL_CANCOM1, 1) is used to set the MCR[IRMQ] bit. Must be written in Freeze mode.

 

Regarding the data bytes swapping; the module itself does not do any byte swapping.

Seems the API does this. Not sure why. See more in functions FLEXCAN_HAL_ReadRxFifo() and FLEXCAN_HAL_GetMsgBuff(). But it looks the bytes are swapped when regular MB is read, not the RX FIFO.

 

Your code for clearing the RXFIFO could work.

You can also use CAN_IFLAG1[BUF0I] to empty FIFO content as written in chapter 47.5.8.2 "Clear FIFO Operation" of the RM. Writing 1 to CAN_IFLAG1[BUF0I] will empty the RXFIFO, but must be done in Freeze mode. The code could be following…

 

FLEXCAN_HAL_EnterFreezeMode(FSL_CANCOM1);          // set Freeze mode

FLEXCAN_HAL_ClearMsgBuffIntStatusFlag(FSL_CANCOM1, 0xE1) // empty fifo and clear other RXFIFO flags

FLEXCAN_HAL_ExitFreezeMode(FSL_CANCOM1); // exit Freeze mode

BR, Petr

2,740 Views
jeremiahg
Contributor III

Pter,

Thanks for the information. I actually tried that before and the individual masking wasn't working. I did some testing with each bit in the message and learned something interesting. The individual mask value had to be shifting left by one bit. For example, I had ID Filter Tabe 0 as

0x00E80000

an originally had Individual Mask Element 0 as

0x00FF0000

I expected a CAN message with ID 0x00E8FF00 to be received. I didn't get the message. so I tried 0x00E84F00. I received this message. The CAN messages are correctly passed when the original Individual Mask Element 0 was

0x01FE0000

All of my individual masks function correctly when I left shifted the mask value by 1. I didn't dig into the drivers. I am using the ProcessorExpert function

FLEXCAN_DRV_SetRxIndividualMask(can_instance, FLEXCAN_MSG_ID_EXT, 0U, 0xff0000 << 1);

 

I'm going to write my own drivers for the Rx FIFO so I can react to the interrupts provided by the FIFO, especially when it is almost full. I'm still having issues when the bus load is over 50%. Either that or use DMA.

Regards,

Jeremiah

2,740 Views
abidbodal
Contributor II

Jeremiah, 

I believe you are correct I ran into the same thing. I am using the kinetis K20DX256 (KSDK 1.3) and when we call FlexCanDevice_SetRxIndividualMask() in the driver it calls FLEXCAN_HAL_SetRxIndividualExtMask() which writes to the  CANx_RXIMRn register:

FLEXCAN_HAL_SetRxIndividualExtMask(){

....

CAN_WR_RXIMR(base, msgBuffIdx, CAN_ID_EXT(extMask));

....

}

CAN_ID_EXT is defined as:

#define CAN_ID_EXT_MASK 0x3FFFFu
#define CAN_ID_EXT_SHIFT 0
#define CAN_ID_EXT(x) (((uint32_t)(((uint32_t)(x))<<CAN_ID_EXT_SHIFT))&CAN_ID_EXT_MASK)

There are two issues with this:

1. CAN_ID_EXT_MASK would only set the extended ID part of the ID even though the maximum possible value of an extended mask would be 0x1fffffff

2. If RX is set up to use a FIFO then we need to look at RXFGMASK register to see what the bits mean. In the CANx_RXFGMASK definition, if we have selected to use full RXIDA format then the ID would be bits FGM[29:1]. So therefore we would need to shift by 1 bit (as you have done)

pastedImage_18.png

This is the solution I had for this issue. I modified the driver so 

FLEXCAN_HAL_SetRxIndividualStdMask{

...

CAN_WR_RXIMR(base, msgBuffIdx, ((CAN_ID_STD(stdMask))<<1));

..

}

FLEXCAN_HAL_SetRxIndividualExtMask(

   ...

   //The reason the value has been OR'ed by 0x40000000 is because we want to set the IDE bit since it is an extended message

   CAN_WR_RXIMR(base, msgBuffIdx, (((extMask & 0x1FFFFFFF)<<1))| 0x40000000); 

   ...

}

Note: This solution works for FIFO masks but will not work for mailboxes because CANx_RXMGMASK is defined as MG[28:0]

Thanks,

Abid.