espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
12.93k stars 7.09k forks source link

TWAI timing oddities (IDFGH-11149) #12316

Open mickeyl opened 9 months ago

mickeyl commented 9 months ago

Answers checklist.

General issue report

I'm using TWAI to interface with ECUs in vehicles. Some of the ECUs need a pretty deterministic timing (i.e. send a frame every 350µs), which is why I'm thinking about adjusting the TWAI driver to do that. Before I got into that I took a look at the best-case timing, which looks pretty strange. The following data has been acquired on CAN bus configured to 500KBit/sec with two additional devices:

  1. A commercial Bosch ECU (EDC17-derivative),
  2. A CAN monitor in listen-only mode.

For testing, I used the following code in a loop that runs every second:

         twai_message_t message = {
            .identifier = 0x7E0,
            .data_length_code = 8,
            .data = { 0x02, 0x3E, 0x80, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA }
        };

        for (int i = 0; i < 10; ++i) {
            //Queue message for transmission
            if (twai_transmit(&message, pdMS_TO_TICKS(1000)) != ESP_OK) {
                printf("Failed to queue message for transmission\n");
            }
        }
        printf("Messages queued for transmission\n");

So I enqueue 10 frames into the queue (which is setup for 100 frames) and I would expect that these frames are then transmitted with a relatively stable timing.

Here is a dump made on linux from another CAN device in listen-only mode. The timestamps are delta-timestamps.

 (000.000012)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000006)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000246)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000237)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000232)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000250)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000224)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000228)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000244)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.998355)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000013)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000029)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000219)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000232)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000226)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000257)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000257)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000206)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000232)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.998332)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000020)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000029)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000510)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000206)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000228)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000247)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000226)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000245)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.998334)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000003)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000527)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000207)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000215)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000222)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000249)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000252)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000230)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.997967)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000013)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000178)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000217)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000268)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000206)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000221)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000248)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000250)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'
 (000.000226)  can0  7E0   [8]  02 3E 80 AA AA AA AA AA   '.>......'

This looks pretty unstable to me. Notice that the first two of the 10 frames are transmitted very fast (less than 15 µs between a frame), but then it takes about 200 µs each for the rest of the 8. Once there was even a 500µs interval.

Do you have any idea what we can do to improve that? This is on an ESP32S3 without any other tasks, so there should be enough bandwidth.

wanckl commented 9 months ago

@mickeyl Hi, based on your test, I think I have an idea:

The driver using queue construct a front and background system, data is actually send by background.
As you ask a e.g. 350us interval time, which is enough for data timing, then, if you set your queue_size=1 and timeout=0, then setup a 350us timer to enqueue data every timer event, this can ensure the interval low limit. meanwhile you should also adjust your code to ensure the ISR background for TWAI not interrupted by others, it should ensure the interval high limit.

anyway, it is possible based on exist driver architecture, I'm glade if you agree about this, and hope it can help you

mickeyl commented 9 months ago

@wanckl Thanks for your answer. I understand queue_size=1, but where would I configure timeout=0?

I also understand the need for configuring "ISR background for TWAI not interrupted by others, it should ensure the interval high limit.", but where/how can I do that? I can't seem to setup an IRQ priority for TWAI when IRAM is set ­– or can I?

wanckl commented 9 months ago

@mickeyl Sorry for confusing you, timeout means 2nd argument of twai_transmission: ticks_to_wait.

while, yeah, no IRQ priority you can set, now you can only don't init/enable other features like WIFI or BLE or others, keep twai a minimal app.
Good news is I herd that they are plan to public the IRQ priority to user, but maybe hardware/architecture different, there may just little choices you can use.

:hand_over_mouth:

moefear85 commented 6 months ago

Did you set freertos frequency to 1000Hz?

mickeyl commented 6 months ago

Yes