About the CAN controller.

jcsbanks
Posts: 55
Joined: Tue Mar 28, 2017 8:03 pm

Re: About the CAN controller.

Postby jcsbanks » Mon Jun 18, 2018 8:44 pm

Really good idea to send from CAN Tx interrupt, will try that, thanks. I was sending a wake up from the interrupt to a task and getting undesirable latency.

Latency massively affects throughput in my application, CAN bus is by far my only bottleneck. If a CAN packet is 0.25ms, I want a response on the CAN bus in the same millisecond window to transfer lots of data.

ThomasB
Posts: 37
Joined: Sun Dec 25, 2016 12:11 am

Re: About the CAN controller.

Postby ThomasB » Mon Jun 18, 2018 8:50 pm

You also might want to try placing the application in the ISR. This is the fastest yet nastiest solution. You might mess up the complete timing behavior of the chip or experience stack overflows. But hey, it would be very fast 8-)

jcsbanks
Posts: 55
Joined: Tue Mar 28, 2017 8:03 pm

Re: About the CAN controller.

Postby jcsbanks » Mon Jun 18, 2018 8:59 pm

That would be very nasty, it is going very fast now with 100% CAN bus loads over many millions of frames whilst running WiFI without errors. My peak load will be about 50% in actual use.

jcsbanks
Posts: 55
Joined: Tue Mar 28, 2017 8:03 pm

Re: About the CAN controller.

Postby jcsbanks » Tue Jun 19, 2018 10:43 am

To implement the CAN Tx queue using interrupt:

Code: Select all

int CAN_write_frame(CAN_frame_t* p_frame)
{
   if (MODULE_CAN->SR.B.TBS && !uxQueueMessagesWaiting(tx_queue))
   {
      CAN_Tx(p_frame);
      return 0;
   }   
   return xQueueSend( tx_queue, p_frame, 10/portTICK_PERIOD_MS );
}


Original CAN_write_frame is renamed to CAN_Tx.

In the ISR:

Code: Select all

   // Handle TX complete interrupt
   CAN_frame_t frame;
   if (interrupt & __CAN_IRQ_TX)
   {
      if(xQueueReceiveFromISR(tx_queue, &frame, NULL))
         CAN_Tx(&frame);
   }


This works really well, but I'm considering whether to make a critical/atomic section to avoid problems where a transmit complete interrupt may arrive at the wrong time. No one likes these, so thinking carefully.

ThomasB
Posts: 37
Joined: Sun Dec 25, 2016 12:11 am

Re: About the CAN controller.

Postby ThomasB » Tue Jun 19, 2018 3:02 pm

Nice. Yes, critical sections might make sense. You only need to temporarily deactivate the TX interrupt so no need to disable global interrupts.

PS : you might to want to compare tbs against a value or use TCS. Simply for clean code if people use your snippet.

jcsbanks
Posts: 55
Joined: Tue Mar 28, 2017 8:03 pm

Re: About the CAN controller.

Postby jcsbanks » Tue Jun 19, 2018 3:16 pm

Code: Select all

int CAN_write_frame(CAN_frame_t* p_frame)
{
   int status = 0;
   MODULE_CAN->IER.B.TIE = 0;
   if (uxQueueMessagesWaiting(tx_queue))
      status = xQueueSend( tx_queue, p_frame, 0 );
   else if (MODULE_CAN->SR.B.TBS)
      CAN_Tx(p_frame);
   MODULE_CAN->IER.B.TIE = 1;
   return status;
}


Somehow this is missing 1% of transmit frames when the bus loads increase and sometimes the Tx queue just fills up, whereas the other example was not. By trying to stop one race I think I've made a block where a transmit interrupt is lost when it was needed to service the queue as the Tx queue runs at low capacity and then suddenly fills apparently randomly. Edit: I think that this method of disabling the interrupt is not suitable because it means the SJA1000 doesn't trigger an interrupt, whereas I just want the ESP32 CPU to defer responding to this interrupt during the critical section.

jcsbanks
Posts: 55
Joined: Tue Mar 28, 2017 8:03 pm

Re: About the CAN controller.

Postby jcsbanks » Tue Jun 19, 2018 4:56 pm

This does work if heavy handed, but applicable to my application in particular. Maybe there is a way to get it just to defer CAN_isr.

Was this what you mean about comparing to a value? I use TBS instead of TCS because it seems analogous to the TIE, the buffer is available even if the previous transmission is not complete.

Code: Select all

portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
int CAN_write_frame(CAN_frame_t* p_frame)
{
   portENTER_CRITICAL(&mux);

   if (MODULE_CAN->SR.B.TBS==1 && !uxQueueMessagesWaiting(tx_queue))
   {
      CAN_Tx(p_frame);
   }   
   else
   {
      xQueueSend( tx_queue, p_frame, 0 );
   }

   portEXIT_CRITICAL(&mux);
   return 0;
}

Walkramis
Posts: 1
Joined: Tue Jul 03, 2018 4:03 pm

Re: About the CAN controller.

Postby Walkramis » Thu Jul 05, 2018 12:48 pm

Hello everyone!

First I would like to direct a big thanks to @ThomasB and @rudi for their work on the library, truly wonderful!

However I am having some issues regarding the speed of receiving messages. I am running a bus at 500kbps with quite a heavy load (just above 1000 messages per second, extended frames). Currently I'm running it from a logfile from a raspberry in order to do some validation tests to make sure all messages arrive.
Currently (running the example code) I am able to receive messages for between 10-20 seconds before I start dropping frames.
I have experimented some with the example code as well as tried to increase the frequency of the board which have made some improvements, but not enough. In my final application it is not likely that these loads will occur constantly, but I would like to optimize for it.
I am using a sn65hvd230 chip together with the esp32.

Now for my questions:
1. Is this load at all possible with the esp32?
2. Would another transceiver help?
3. If possible, what changes would I need to do to the code in order for it to work (and how much cpu power would be left for other purposes).
4. I read something on an earlier page about moving from FreeRTOS to ISR which dropped the latency significantly for @jcsbanks. How would I go about doing this? (I am very new to the esp32 chip, the espressif IDF as well as FreeRTOS)

Thanks in advance!

jcsbanks
Posts: 55
Joined: Tue Mar 28, 2017 8:03 pm

Re: About the CAN controller.

Postby jcsbanks » Thu Jul 05, 2018 1:27 pm

The changes I am using are in my post in page 15. This way it handles a full CAN bus for hours on end with no dropped frames, with SN65HVD230. I have not measured CPU load but not had any problems.

Who is online

Users browsing this forum: WiFive and 1 guest