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?
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.
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
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 1 | Header 2 | Header 3 | |
---|---|---|---|
Tx | Rx | ||
ID null , Data 0x0 | |||
ID null , Data 0x0 | |||
ID null , Data 0x0 | |||
ID null , Data 0x0 | |||
ID null , Data 0x0 | |||
No. 1 | ID 0x1, Data 0x11 | ID 0x1 , Data 0x11 | |
No. 2 | ID 0x2, Data 0x12 | ID 0x2 , Data 0x12 | |
| ID 0x3, Data 0x13 | ID 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.
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).
Hi York:
I will reproduce your issue in my side and update to you later
Regards
Daniel