FlexCAN RxFIFO working example

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

FlexCAN RxFIFO working example

3,438 Views
robertyork
Contributor II

I'm using Codewarrior 10.6.4, MQX 4.1 and a K70 board, and have been using the fsl_flexcan drivers for CAN. I've gotten them working to a point, but I need to switch to the RxFIFO mode, and I've been having troubles. I've used the example code to get the mailbox method working, but I swapped the flags for what mode it's in, and it won't run. Here's the flags from the example:

    flexcan1_data.is_rx_fifo_needed = TRUE;

    flexcan1_data.is_rx_mb_needed = FALSE;

So I changed these as above, and I'm not getting any CAN data now. Is there something else I need to modify in the example to change from MB to FIFO mode? Does anyone have another working example of FIFO operation? I'm kind of stuck here.

Just to clarify, taking the example FlexCAN code (fsl_flexcan_test.c) and in the default state, using MBs, it works fine. I just don't know exactly how to enable the RxFIFO mode, and when I've tried to figure it out, it seems to run and transmit fine, I just can't receive anything.

Edit:

I've found out my problem with getting the RxFIFO version working. It was an issue with my ID masks. Now I have that working, I've run into another small problem; I can't seem to get anything but the front element in the FIFO. I've been digging through the driver source and I can't seem to figure out how you tell the driver to give you the next message in the FIFO. Any one have ideas on this? As far as I can tell, the line:

        result = (flexcan_start_receive(instance, &flexcan1_data, RX_mailbox_num, RX_identifier, 1,

                                  &is_rx_mb_data, &is_rx_fifo_data, &rx_mb, &rx_fifo));

Only returns back if there's new messages, but it starts out with several blank messages that I have to empty out, so I always seem to be a few messages behind. I imagine if I received a message while parsing another, I would get even further behind. How do I just jump through the elements in the FIFO?

Tags (4)
0 Kudos
5 Replies

1,196 Views
sivakrishnaband
Contributor I

Hi,

Whatever you faced issue on RXFIFO, even i am also facing.

Is that issue resolved?. in case if it resolved let me known the solution or code.

Thanks & Regards,

Siva Krishna.

0 Kudos

1,196 Views
danielchen
NXP TechSupport
NXP TechSupport

I sent 11 frames with my can analyzer, and  received 11 frames with my tower board (K70F120m).  My test result is as follows:

                 Tx :                                             Rx:

No. 1 ID 0x1, Data 0x11              ID null , Data 0x0
No. 2 ID 0x2, Data 0x12              ID null , Data 0x0
No. 3 ID 0x3, Data 0x13              ID null , Data 0x0
No. 4 ID 0x4, Data 0x14              ID null , Data 0x0
No. 5 ID 0x5, Data 0x15              ID null , Data 0x0
No. 6 ID 0x6, Data 0x16              ID 0x1 , Data 0x11
No. 7 ID 0x7, Data 0x17              ID 0x2 , Data 0x12
No. 8 ID 0x8, Data 0x18              ID 0x3 , Data 0x13
No. 9 ID 0x9, Data 0x19              ID 0x4 , Data 0x14
No. 10 ID 0x10, Data 0x20             ID 0x5 , Data 0x15
No. 11 ID 0x11, Data 0x21       

     ID 0x6 , Data 0x16

From the result, it seems that the data is not lost,  they entered into a FIFO. and the depth of the FIFO is 6

0 Kudos

1,196 Views
robertyork
Contributor II

Daniel,

Thank you for the response. That is exactly the result I see on my system as well.

However, if, for example, you were to send one message a second, I would get ID 0x1 6 seconds behind. For my application, getting messages 6 messages behind is unacceptable. Also, if you look at what is in the buffer, as far as I can tell, the buffer is already full at this point. If I were to get 6 messages all at the same time, back to back, I could theoretically get messages faster than I can parse the old ones, and with the buffer already full, I'd potentially lose data.

Really what I need is a way to pull data out of, or service, the queue. I can't wait for a received message, I need to be able to get data out at will. This function is required of a FIFO, and the driver has it, but currently, only upon the event of receiving a message.

Normally I would implement this in one of two ways. Either I would have a function like the current one, flexcan_start_receive(), but that returns with data if there is data in the FIFO, rather than upon receipt of a message. Or, I would have another set of functions to check if there's an item in the FIFO, and if so, a function to pull that item out.

Edit, to clarify, this is what I would expect to see:

Header 1Header 2Header 3
TxRx
ID null , Data 0x0
ID null , Data 0x0
ID null , Data 0x0
ID null , Data 0x0
ID null , Data 0x0
No. 1ID 0x1, Data 0x11ID 0x1 , Data 0x11
No. 2ID 0x2, Data 0x12ID 0x2 , Data 0x12
No. 3
ID 0x3, Data 0x13ID 0x3 , Data 0x13

Etc.. Basically, I would expect it to see the blank messages, spin through them as fast as it can, even before the first message arrives. Then it should block on the now empty FIFO until No. 1 is received, and immediately parse that.

I've been digging through the K70 reference manual, the fsl_flexcan_driver.c and the fsl_flexcan_hal.c, and learned that it SHOULD be behaving as I described, not as observed. Here's a snippet from the interrupt handler in the driver.c:

flexcan_irq_handler(..)

...

    // get the interrupt flag

    tmp_reg = (flexcan_hal_get_all_mb_int_flags(instance)) & CAN_IMASK1_BUFLM_MASK;

    // check Tx/Rx interrupt flag and clear the interrupt

    if(tmp_reg){

        if (tmp_reg & 0x20)

        {

            int_fifo = TRUE;

        }

        if (tmp_reg & (1 << rx_mb_idx))

        {

            int_mb = TRUE;

        }

        // clear the interrupt and unlock message buffer

        _lwevent_set(&event, tmp_reg);

        flexcan_hal_clear_mb_int_flag(instance, tmp_reg);

        flexcan_hal_unlock_rx_mb(instance);

...

Basically, it's checking to see if the bit 0x20 is set, if so, it sets a global that there was a fifo interrupt. Then it clears the interrupts by setting that flag again. Reading the reference manual, that bit relates to there being data in the FIFO, and indeed, by setting that flag back into the register, you clear it and let the processor set the flag once again if there's still more data waiting to be read. This assumes MCR[RFEN] (RxFIFO Enable) is set. Should be a safe bet, but I'll double check.

I see no reason why this is not acting as I expect. I'm rather confused why we're seeing something different.

Edit: Some more information.. in the last couple lines in the irq handler above, you'll notice it sets the event flag with _lwevent_set(&event, tmp_reg);, then it clears the interrupt flags (which allows the FlexCAN to then post the interrupt again if there's still data). I expected setting the event to allow the blocked flexcan_start_receive() function to run and read the data, and then after that it would do the flexcan_hal_clear_mb_int_flag(instance, tmp_reg). To test this, after I get data from that, I check the interrupt flags by calling flexcan_hal_get_all_mb_int_flags(instance). I'm getting a 0 every time. To me, that implies the interrupt has been reset and the processor doesn't think there's data in the FIFO at all; yet we know that's not true, as eventually data pushed in 6 messages ago shows up.

After more fiddling, I've confirmed it's setting the event, then continues on to clear the flags and unlock the MB before the event handler catches and lets the flexcan_start_receive() function to return. It's almost like the CANx_IFLAG1[BUF5I] flag doesn't seem to be working as described in the reference manual. The reference manual states the flag indicates when there is a message in the FIFO. At the HAL layer, it's behaving more like indicating when a message is received, not when there's messages in the FIFO. Not sure if there's a bug here, or some configuration settings, priorities, or other task issues are mucking things up.

0 Kudos

1,196 Views
tomaszsliwinski
Contributor III

I think I see a related issue on Vybrid (TWR-VF65GS10).  Works fine when asking for one MB (up to 8 bytes) at a time.  But is there a way to queue them up?  I need to increase throughput on the receive.  Is there a way to ask the driver for multiple MBs?  Say, get 16 MBs at a time (so 16 x 8 bytes).

0 Kudos

1,196 Views
danielchen
NXP TechSupport
NXP TechSupport

Hi York:

I will reproduce your issue in my side and update to you later

Regards

Daniel

0 Kudos