Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CDC-ACM: Dropped packets when talking with ESP32? (IEC-242) #104

Open
3 tasks done
xobs opened this issue Dec 19, 2024 · 6 comments
Open
3 tasks done

CDC-ACM: Dropped packets when talking with ESP32? (IEC-242) #104

xobs opened this issue Dec 19, 2024 · 6 comments
Assignees
Labels
Status: Opened Issue is new Type: Bug Bug in esp-usb

Comments

@xobs
Copy link

xobs commented Dec 19, 2024

Answers checklist.

  • I have read the component documentation ESP-IDF Components and the issue is not addressed there.
  • I am using target and esp-idf version as defined in component's idf_component.yml
  • I have searched the issue tracker for a similar issue and not found any related issue.

Which component are you using? If you choose Other, provide details in More Information.

host/cdc

ESP-IDF version.

v5.5-dev-847-gcb3ac7429c

Development Kit.

Custom Board

Used Component version.

2.0.6

More Information.

The CDC-ACM driver appears to drop packets.

I have an ESP32S3 that I'm using as a wireless serial port adapter. It's connected to an ESP32C6 via USB. I'm using an external PHY, but the PHY appears to work fine.

As an example of what I'm seeing:

esptool.py v4.8.1
Serial port rfc2217://10.0.237.35:7243
Connecting...
Device PID identification is only supported on COM and /dev/ serial ports.
>>> Write 46 bytes:
    c000082400000000 0007071220555555 | ...$........ UUU
    5555555555555555 5555555555555555 | UUUUUUUUUUUUUUUU
    5555555555555555 5555555555c0     | UUUUUUUUUUUUU.
<<< Read 1 bytes: c0
<<< Read 13 bytes: 010804000707122000000000c0
<<< Read 14 bytes: c0010804000707122000000000c0
<<< Read 0 bytes:

A bit of explanation:

The PC running esptool.py sends a SYNC packet which contains a bunch of U characters. The ESP32C6 then responds with its own SYNC packets (the second byte is 0x01 indicating it's a response). It sends two of these, and then stops responding.

In contrast, when I connect the ESP32C6 directly to a PC, esptool.py reports the following:

Connecting...>>> Write 46 bytes:
    c000082400000000 0007071220555555 | ...$........ UUU
    5555555555555555 5555555555555555 | UUUUUUUUUUUUUUUU
    5555555555555555 5555555555c0     | UUUUUUUUUUUUU.
<<< Read 1 bytes: c0
<<< Read 27 bytes:
    0108040007071220 00000000c0c00108 | ....... ........
    0400070712200000 0000c0           | ..... .....
<<< Read 42 bytes:
    c001080400070712 2000000000c0c001 | ........ .......
    0804000707122000 000000c0c0010804 | ...... .........
    0007071220000000 00c0             | .... .....
<<< Read 42 bytes:
    c001080400070712 2000000000c0c001 | ........ .......
    0804000707122000 000000c0c0010804 | ...... .........
    0007071220000000 00c0             | .... .....

You can see the two packets in the first read, but the two 42-byte reads have been lost.

I'm not sure if the ESP ROM is sending bursts of 14 bytes, and the ESP32S3 stack is seeing the repeated packets and dropping them, but this occurs both if I use https://github.com/igrr/rfc2217-server/ to act as an rfc2217-compliant server (and use esptool.py rfc2217://server:port) or if I do my own thing and use socket:// URLs and directly communicate by sending TCP packets in the cdc_acm_host_device_config_t callback.

@xobs xobs added the Type: Bug Bug in esp-usb label Dec 19, 2024
@espressif-bot espressif-bot added the Status: Opened Issue is new label Dec 19, 2024
@github-actions github-actions bot changed the title CDC-ACM: Dropped packets when talking with ESP32? CDC-ACM: Dropped packets when talking with ESP32? (IEC-242) Dec 19, 2024
@tore-espressif
Copy link
Collaborator

@xobs Thank you for the report. The logs indeed seem incorrect.

Is it possible to share the code that handles usb_host_cdc_acm component? Mainly the RX path? We will try to reproduce it locally

@xobs
Copy link
Author

xobs commented Dec 19, 2024

I can share the entire repository: https://github.com/xobs/rocom

This is built for a board that uses a pair of buffers for an external PHY, but if you have a setup that works with the internal PHY that could work as well.

@tore-espressif
Copy link
Collaborator

Without actually running the code, I found out that you send the data to rfc in the rx callback https://github.com/xobs/rocom/blob/main/main/serial_port_relay.c#L133

A cleaner solution would be to pass the data by copy to a queue and then send it from other task. The CDC-ACM driver will not resume RX transfers before the RX callback returns.

Could you please try moving the rfc2217_server_send_data(s_server, data, data_len); call outside of the RX callback and see if the issue persists?

@xobs
Copy link
Author

xobs commented Dec 20, 2024

Thank you for the mini code review. I assumed that since everything in that path is blocking, I shouldn’t have to double buffer in that way. Additionally, the CDC code doesn’t submit a new IN request until after the callback finishes, so the usb controller shouldn’t be requesting data on that bulk endpoint.

if it were the case that it immediately requeues the transfer and overwrites the buffer then I could see that causing this behaviour, but if it’s doing that then things will very quickly get silently overwritten.

what I really want is a usb protocol trace to figure out if the C6 is sending different data, or whether it’s the S3 that’s missing packets.

@tore-espressif
Copy link
Collaborator

the CDC code doesn’t submit a new IN request until after the callback finishes, so the usb controller shouldn’t be requesting data on that bulk endpoint.

This is true. Until the RX callback returns, you own the data and the CDC driver will not overwrite them.

The issues is, that if you do no enable the RX path (by returning from the callback), the USB device can discard some packets (== the device will not send them to the host).

what I really want is a usb protocol trace to figure out if the C6 is sending different data, or whether it’s the S3 that’s missing packets.

Here the only option is to use a special USB analyzer (such as Beagle 480).

Could you please refactor the RX callback so it returns fast and report with your findings? Then we can proceed with the USB bus analysis on our side

@xobs
Copy link
Author

xobs commented Dec 21, 2024

I've added a second thread and I now use a ringbuffer to pass data to it. The ringbuffer has a timeout of 5 ms, which may be a bit high but it doesn't get triggered at any rate.

I will have access to a USB Beagle next week, so I can see if I can record some traces. But adding the ringbuffer does not make any difference that I can see.

I also tried increasing the priority of the USB task, which also hasn't had an affect on things.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Opened Issue is new Type: Bug Bug in esp-usb
Projects
None yet
Development

No branches or pull requests

3 participants