cancel
Showing results for 
Search instead for 
Did you mean: 

How to read out all CAN messages in the FIFO buffer

adam_bm
Associate II

Hi,

I'm new to the ST family of processorers and we are currentl using the SPC58EC discovery board at the company I'm currently working at.

Background:

I'm trying to make an application read out and print on serial what is being sent on the CAN bus. Right now I'm using the following lines of code in the main loop:

 returnvalue = can_lld_receive(&CAND2, CAN_FIFO0_RXBUFFER, &rxf);

   if (returnvalue == CAN_MSG_OK) {

write_can_msg(0, 0, rxf.ID, rxf.data8, rxf.DLC);

rxCounterPoll++;

pal_lld_clearpad(PORT_F, PF_LED2);

   }

which works OK. I have set up the FIFO buffer to have 64 slots and when I flood the CAN bus with messages using busmaster the FIFO buffer seems to be working.

To my issue: when I fill up the FIFO buffer it seems like the above lines of code does not empty it when I stop flooding the bus. After filling up the buffer if I wait a couple of seconds and then start sending a new message one by one, can_lld_receive executes still the old messages when a new one is received for a while before comming to the new ones that I am now sending. Meaning that I get some form of "lag" in the readout.

Questions:

Any thoughts about what I am doing wrong? Is there another command to readout what is left in the buffer? Is there a setting that can be made regarding the buffer that I might have missed?

Thank you for your time!

//Adam

1 ACCEPTED SOLUTION

Accepted Solutions
adam_bm
Associate II

Hi Domenico,

Thank you for the answer! Unfortunately it didn't seem to solve the problem. I still get the issue when the readout has a longer period than the messages are sent.

I read abit about the code you proposed. And tried changing the code in the: can_lld_receive function to:

 /* read from FIFO 0 */

 if (msgbuf == CAN_FIFO0_RXBUFFER) {

  //if(canp->mcan->IR.B.RF0N == 1){

  if(canp->mcan->RXF0S.B.F0FL > 0)

  {

   rxbuffer = canp->mcan->RXF0S.B.F0GI;

   /* read message */

   can_lld_readBuffer(canp, CAN_FIFO0_RXBUFFER, rxbuffer, crfp);

   /* release fifo0 rx buffer */

   canp->mcan->RXF0A.B.F0AI = canp->mcan->RXF0S.B.F0GI;

   /* clear flag */

   canp->mcan->IR.B.RF0N = 1;

  } else {

   return CAN_MSG_WAIT;

  }

 }

And it seems to work, I will need to continue investigating it next week though. Thank you for your help so far. I will get back with updates on how it went. 

//Adam

View solution in original post

5 REPLIES 5
ELund.2
Associate

I can not give you an answer, but I would also like to know the answer

DCARR
Associate III

Hi All,

I`ve checked the low level driver code and I saw that the "can_lld_receive" function do not check if there are new messages into the FIFO before accessing FIFO buffers. This because the driver was designed to be used with FIFO Rx interrupt, not in polling mode. Accessing the FIFO buffers also if the FIFO is empty can drive to driver malfunction and so my proposal (workaround) is to check the FIFO fill level before reading messages and so, the code in this ticket should be modified as below adding a check on FIFO fill level before calling the "can_lld_receive" function:

if (CAND2.mcan->RXF0S.B.F0FL > 0)

returnvalue = can_lld_receive(&CAND2, CAN_FIFO0_RXBUFFER, &rxf);

if (returnvalue == CAN_MSG_OK) {

write_can_msg(0, 0, rxf.ID, rxf.data8, rxf.DLC);

rxCounterPoll++;

pal_lld_clearpad(PORT_F, PF_LED2);

}

Best regards

Domenico

adam_bm
Associate II

Hi Domenico,

Thank you for the answer! Unfortunately it didn't seem to solve the problem. I still get the issue when the readout has a longer period than the messages are sent.

I read abit about the code you proposed. And tried changing the code in the: can_lld_receive function to:

 /* read from FIFO 0 */

 if (msgbuf == CAN_FIFO0_RXBUFFER) {

  //if(canp->mcan->IR.B.RF0N == 1){

  if(canp->mcan->RXF0S.B.F0FL > 0)

  {

   rxbuffer = canp->mcan->RXF0S.B.F0GI;

   /* read message */

   can_lld_readBuffer(canp, CAN_FIFO0_RXBUFFER, rxbuffer, crfp);

   /* release fifo0 rx buffer */

   canp->mcan->RXF0A.B.F0AI = canp->mcan->RXF0S.B.F0GI;

   /* clear flag */

   canp->mcan->IR.B.RF0N = 1;

  } else {

   return CAN_MSG_WAIT;

  }

 }

And it seems to work, I will need to continue investigating it next week though. Thank you for your help so far. I will get back with updates on how it went. 

//Adam

DCARR
Associate III

Hi Adam,

I don`t see any relevant delay reading the FIFO RX buffers when I use the CAN in a standalone way.

My advice is to check your application to understand the root cause of delayed calls to buffers reading function.

Best regards

Domenico

adam_bm
Associate II

Hi Domenico,

I think the above changes I posted worked actually so I will keep that. It was probably as you said regarding reading when the buffer is empty. The above line of code solved that issue.

Thank you for your help!

//Adam