About the CAN controller.
Re: About the CAN controller.
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.
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.
Re: About the CAN controller.
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
my page: http://www.barth-dev.de/
Re: About the CAN controller.
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.
Re: About the CAN controller.
To implement the CAN Tx queue using interrupt:
Original CAN_write_frame is renamed to CAN_Tx.
In the ISR:
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.
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 );
}
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);
}
Re: About the CAN controller.
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.
PS : you might to want to compare tbs against a value or use TCS. Simply for clean code if people use your snippet.
my page: http://www.barth-dev.de/
Re: About the CAN controller.
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;
}
Re: About the CAN controller.
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.
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;
}
Re: About the CAN controller.
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!
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!
Re: About the CAN controller.
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.
Re: About the CAN controller.
HI there!jcsbanks wrote:Bit more info after playing all afternoon.
The Tx pin is connected to the tranceiver from pin on ESP32 Devkit C to pin on the tranceiver chip, but the ESP32 cannot transmit. Pulling either Tx or Rx connection from ESP32 to tranceiver stops reception. The ECU only sends a single packet (but repeatedly) when powered up to the ESP32, until the Kvaser joins the CAN bus, then the ECU transmits its usual variety of IDs, so it looks like it is also diagnosing CAN off. I have swapped the Tx and Rx pins on ESP32 both physically and also in the software and I can still receive, so it doesn't seem like a faulty GPIO. It could be a faulty tranceiver I guess. Or some setting I'm missing or have messed up.
I am trying my luck on having a CAN connection (obviously posting here) on an ESP32 WROOM, external SN65HVD230. THis is my first ESP CAN. I do very much have the issue @jcsbanks described before. I tried 2 ESP modules and 2 transceivers...
I can only _receive_ on my test setup on a 500kB CAN (like from Thomas B. example). I have a stable CAN with 2 other participants (arduino) and want to add my ESP32 to this CAN. When I try to send, I get following error interrupts
0x80 __CAN_IRQ_BUS_ERR
0x4 __CAN_IRQ_ERR
0x20 __CAN_IRQ_ERR_PASSIVE
0x4 __CAN_IRQ_ERR .
Did anyone experience this? What could I have messed up here?
Best Regards
Bernd
Who is online
Users browsing this forum: Priyanshkpatel and 50 guests