8000 2nd USB CDC works at first, then device won't connect to computer · Issue #6018 · adafruit/circuitpython · GitHub
[go: up one dir, main page]

Skip to content

2nd USB CDC works at first, then device won't connect to computer #6018

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

Closed
Turtle49 opened this issue Feb 11, 2022 · 14 comments · Fixed by #7100
Closed

2nd USB CDC works at first, then device won't connect to computer #6018

Turtle49 opened this issue Feb 11, 2022 · 14 comments · Fixed by #7100
Assignees
Milestone

Comments

@Turtle49
Copy link

CircuitPython version

Adafruit CircuitPython 7.1.1 on 2022-01-14; Adafruit Feather M4 Express with samd51j19
Adafruit CircuitPython 7.1.1 on 2022-01-14; Adafruit Feather M0 Adalogger with samd21g18 (2 different devices)

Code/REPL

#boot.py
import usb_cdc
usb_cdc.enable(console=True, data=True)    # Enable console and data

Behavior

When connected to a Windows machine sees the microcontroller as "Unknown USB device (device descriptor request failed)". When connected to a Rpi, there is no apparent acknowledgement of plugging it in and there are no new objects in /dev.

Description

I enabled CDC in boot.py as above and I established communications between microcontrollers (M4, 2 different M0 Adalogger) and hosts (3 different Win10 tested, Raspberry Pi 4). I wrote and successfully tested code, per Adafruit guides here, here and here (thank you!!).

A few hours later the device stops ceases to behave well. Instead, now when connected to a computer, the microcontroller is unable to connect to the computer in "normal" mode.

When connected to a Windows machine sees the microcontroller as "Unknown USB device (device descriptor request failed)" No new COM devices become present, REPL does not work, CIRCUITPY does not appear. I tried Device Cleanup Tool v1.2.1 to no avail. When connected to a Rpi, there is no apparent acknowledgement of plugging it in and there are no new objects in /dev (when it worked, I saw them as ttyACM0 and ttyACM1, rather than ttyUSBx).

However, the microcontrollers connect in "safe" and "boot" modes. Removing usb_cdc.enable from boot.py makes it so that REPL/CIRCUITPY connects as usual, and behaves as expected in other ways.

I have re-installed CircuitPython to no avail. I have not attempted previous versions (I can't navigate to the repository of my devices! please, link?). I have turned on, off, re-booted in various orders, and looked for newly-installed drivers.

Additional information

I wonder if it is related to issue #4986, in a way that makes the microcontroller unable to connect at all if the 2nd CDC is enabled.

@Turtle49 Turtle49 added the bug label Feb 11, 2022
@dhalbert
Copy link
Collaborator

Could you upload your code.py that is no longer working? If it is large, if you have a minimal example, that would be great.

@Turtle49
Copy link
Author
Turtle49 commented Feb 11, 2022

On the host/computer I used:

import serial
import time
import adafruit_board_toolkit.circuitpython_serial

comports = adafruit_board_toolkit.circuitpython_serial.data_comports()
device_COM = 'COM6'

if not comports:
    raise Exception("No sensor modules found")

try:
    device = serial.Serial(device_COM, baudrate=115200, bytesize=8, parity='N', stopbits=1, timeout=1, xonxoff=0, rtscts=0)
    device.write(b'hi!')
    response = str(device.readline(), 'utf-8')
    print(response)

finally:
    device.close()

On the CircuitPython side I used:

import time
import usb_cdc

if usb_cdc.data is None:
    print("Need to enable USB CDC serial data in boot.py!")
    while True:
        pass

usbl = usb_cdc.data[1]

def send_data(data):
    data = bytes(data+"\n", 'utf-8')
    usbl.write(data)

def read_data():
    data = usb_cdc.data.read(6)
    return data

usb_cdc.data.timeout = 5

while True:
    print(read_data())
    send_data("Helooo!")
    time.sleep(1)`

@dhalbert
Copy link
Collaborator

When it does not work, see if there are any errors in boot_out.txt in CIRCUITPY. I haven't heard of this happening. Does this happen on all the boards?

@dhalbert
Copy link
Collaborator

You are always using COM6, but it might not be COM6:

comports = adafruit_board_toolkit.circuitpython_serial.data_comports()
device_COM = 'COM6'

There is no usbl defined elsewhere:

    usbl.write(data)

@Turtle49
Copy link
Author
Turtle49 commented Feb 11, 2022

When I boot in safe mode, the boot_out.txt is clean (see below). When the device is not able to connect, I don't know how to access the file that would have generated.

I has happened to all those I've tried: 1 Feather M4 and 2 Adalogger M0. I will test more devices as able.

I change the address manually. 'COM6' has been typical in Windows, 'ttyACM01' in linux/Rpi. I will note that the code never above runs as far as I know ... the microcontroller does not connect REPL or CIRCUITPY when data CDC is enabled.

Code edited for usbl = usb_cdc.data[1] (I had edited it away, apologize)

Adafruit CircuitPython 7.1.1 on 2022-01-14; Adafruit Feather M4 Express with samd51j19 Board ID:feather_m4_express boot.py output:

@tannewt tannewt added this to the Long term milestone Feb 11, 2022
@Turtle49
Copy link
Author

I no longer see the issue in Circuitpython 7.3.0

@nhedler-cubeworks
Copy link

I have encountered this issue on a Pi Pico running version 7.3.1 (just installed); my boot.py in full is the following:

import usb_cdc
usb_cdc.enable(console=True, data=True)

My code.py is:

import usb_cdc
pos = usb_cdc.data.read(1)

I've found that if I start with a working code.py (e.g. empty, or with the read() line commented out) and then change it to the above, it works as expected. After that, a hard-reset will cause the behavior described in the first post: device fails to appear as COM port(s) (or in /dev/ on Linux), does not provide CIRCUITPY drive, and otherwise appears dead.

@dhalbert dhalbert reopened this Jun 23, 2022
@dhalbert
Copy link
Collaborator

@nhedler-cubeworks What are the host computer(s) and their OS versions? Thanks.

@nhedler-cubeworks
Copy link

Windows 10 and some kind of Linux, maybe Mint? Two different systems.

@Neradoc
Copy link
Neradoc commented Jun 23, 2022

I can reproduce the issue on the pico with 7.3.1 and main, on MacOS.
The issue seems to happen if the read() is called before the serial is fully available.
Adding a sleep at the start made the board behave as expected again.

This code.py waits for supervisor.runtime.usb_connected, in case it's related (though it might just insert a wait in the code, like the sleep). It has the board appear correctly and prints out values between 100 and 400ms.

import time
import usb_cdc
# time.sleep(2)

t0 = time.monotonic_ns()
import supervisor
while not supervisor.runtime.usb_connected:
    pass
t1 = time.monotonic_ns()

delta = (t1 - t0) // 1000 / 1000

usb_cdc.data.timeout = 1
usb_cdc.data.read(1)

while True:
    print(delta)
    time.sleep(0.2) # don't flood

@Vexs
Copy link
Vexs commented Jul 16, 2022

I'm able to reproduce this issue as well on 7.3.1 and 8.x.
7.3.0 builds of cirpy do not have this issue, but fortunately Neradoc's solution seems to resolve it.

@er1z
Copy link
er1z commented Jul 29, 2022

Man, thought I fried my Raspberry (was playing with non-micro USB connection). The same issue as above.

Adafruit CircuitPython 7.3.2 on 2022-07-20; Raspberry Pi Pico with rp2040

@tannewt
Copy link
Member
tannewt commented Oct 21, 2022

@hathach It looks like this is hitting a TU_ASSERT on nRF.

0x0006e40c in usbd_edpt_xfer (rhport=0 '\000', ep_addr=0 '\000', buffer=buffer@entry=0x0, total_bytes=total_bytes@entry=0) at ../../lib/tinyusb/src/device/usbd.c:1304
1304      TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0);
(gdb) bt
#0  0x0006e40c in usbd_edpt_xfer (rhport=0 '\000', ep_addr=0 '\000', buffer=buffer@entry=0x0, total_bytes=total_bytes@entry=0) at ../../lib/tinyusb/src/device/usbd.c:1304
#1  0x00073cb4 in _status_stage_xact (rhport=rhport@entry=0 '\000', request=request@entry=0x20011f2c <_ctrl_xfer>) at ../../lib/tinyusb/src/device/usbd_control.c:70
#2  0x0006e1d4 in usbd_control_xfer_cb (rhport=<optimized out>, ep_addr=<optimized out>, result=<optimized out>, xferred_bytes=18) at ../../lib/tinyusb/src/device/usbd_control.c:216
#3  0x0006c3e2 in tud_task () at ../../lib/tinyusb/src/device/usbd.c:562
#4  0x0008ec1a in usb_background () at ../../supervisor/shared/usb/usb.c:203
#5  0x0008ec30 in usb_background_do (unused=<optimized out>) at ../../supervisor/shared/usb/usb.c:220
#6  0x0002ff86 in background_callback_run_all () at ../../supervisor/shared/background_callback.c:97
#7  0x0008dcbc in supervisor_run_background_tasks_if_tick () at ../../supervisor/shared/tick.c:122
#8  0x0003968c in common_hal_usb_cdc_serial_read (self=0x20010530 <usb_cdc_data_obj>, data=0x200175e0 "", len=1, errcode=<optimized out>) at ../../shared-module/usb_cdc/Serial.c:58
#9  0x0008ed10 in usb_cdc_serial_read_stream (self_in=<optimized out>, buf_in=<optimized out>, size=<optimized out>, errcode=<optimized out>) at ../../shared-bindings/usb_cdc/Serial.c:103
#10 0x000830b8 in mp_stream_rw (stream=0x20010530 <usb_cdc_data_obj>, buf_=<optimized out>, size=1, errcode=errcode@entry=0x2003fdb8, flags=flags@entry=0 '\000') at ../../py/stream.c:71
#11 0x000681ae in stream_readinto (n_args=2, args=0x20013f70 <_pystack+24>) at ../../py/stream.c:316
#12 0x000467a4 in fun_builtin_var_call (self_in=0x9bd60 <mp_stream_readinto_obj>, n_args=2, n_kw=0, args=0x20013f70 <_pystack+24>) at ../../py/objfun.c:141
#13 0x0004dc46 in mp_call_function_n_kw (fun_in=0x9bd60 <mp_stream_readinto_obj>, n_args=2, n_kw=0, args=0x20013f70 <_pystack+24>) at ../../py/runtime.c:665
#14 0x00080ccc in mp_call_method_n_kw (n_args=<optimized out>, n_kw=<optimized out>, args=args@entry=0x20013f6c <_pystack+20>) at ../../py/runtime.c:680
#15 0x0004e6b6 in mp_execute_bytecode (code_state=code_state@entry=0x20013f58 <_pystack>, inject_exc=inject_exc@entry=0x0) at ../../py/vm.c:1021
#16 0x000465ee in fun_bc_call (self_in=0x20039700, n_args=0, n_kw=0, args=0x0) at ../../py/objfun.c:297
#17 0x0004dc46 in mp_call_function_n_kw (fun_in=fun_in@entry=0x20039700, n_args=n_args@entry=0, n_kw=n_kw@entry=0, args=args@entry=0x0) at ../../py/runtime.c:665
#18 0x00080c76 in mp_call_function_0 (fun=fun@entry=0x20039700) at ../../py/runtime.c:638
#19 0x0005fe90 in parse_compile_execute (source=0x9fda0, input_kind=input_kind@entry=MP_PARSE_FILE_INPUT, exec_flags=exec_flags@entry=32, result=result@entry=0x20012020 <_exec_result>)
    at ../../shared/runtime/pyexec.c:146
#20 0x0008b568 in pyexec_file (filename=<optimized out>, result=result@entry=0x20012020 <_exec_result>) at ../../shared/runtime/pyexec.c:751
#21 0x0004c174 in maybe_run_list (filenames=filenames@entry=0x9fdf4 <supported_filenames>) at ../../main.c:258
#22 0x00064768 in run_code_py (safe_mode=safe_mode@entry=NO_SAFE_MODE, first_run=first_run@entry=true, simulate_reset=simulate_reset@entry=0x2003ffdf) at ../../main.c:436
#23 0x0004bd38 in main () at ../../main.c:1017

@tannewt tannewt self-assigned this Oct 22, 2022
@tannewt
Copy link
Member
tannewt commented Oct 22, 2022

I found the issue. TinyUSB isn't checking that the CDC structures are actually setup and the read can queue a USB transfer. This transfer can happen on the wrong endpoint when the CDC structures aren't ready! So, we check connected before reading.

dhalbert pushed a commit that referenced this issue Oct 22, 2022
Check for connected before calling read. Otherwise TinyUSB may
setup the read on the wrong endpoint.

Fixes #6018
`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
0