#`usb_uart` performance issue

1 messages · Page 1 of 1 (latest)

crimson scarab
#

been doing some testing with @exotic spindle and he realized that the usb_uart component breaks under high load and/or when the main loop is blocked for any duration.

in particular, usb_host_client_handle_events is being called in the main loop, which means the callbacks get called in the main loop, and callback into the other components, and block. It also means we don’t read the data fast enough because if the loop is busy the events aren’t processed. It only works if the event loop is working perfectly and nothing is blocked. As soon as anything is busy its unstable.

based on Espressif's docs we believe the USB task(s) should have their own thread.

exotic spindle
#

When processing large Z-Wave frames (136 bytes) with verbose logging enabled, we’re see data corruption where frames get partially overwritten with subsequent frame data.

#

When the loop gets busy, there’s a significant delay between USB transfers being available and being processed

#

I’m pretty sure the USB hardware FIFO overflows and drops data

#

I think the solution is to have a dedicated task ```void usb_task(void *arg) {
while (running) {
usb_host_client_handle_events(handle, portMAX_DELAY);
}
}

#

and than transfer the data back and forth to the main loop

raven owl
#

I did initially use a thread when I implemented this, but found that using the loop thread worked ok. It is quite possible that if the loop thread is blocked there could be buffer overflows and using a task might help, though it would then require synchronisation primitives to transfer data to the loop thread, and it's also possible that the buffer overflows might simply shift from one place to another.

exotic spindle
#

I implemented a really hacky queue/lock free queue and the problem went away

raven owl
#

Using a separate task? There is also a field in the host config structure that sets the number of RX FIFO lines, it's possible that using it might enable increasing the FIFO size. Documentation on it is sketchy.

#

If the data is large but bursty then having a big enough buffer, either in the FIFO or a task-managed queue should solve the problem and I assume that's the case here. If the data rate is simply too high for the loop task to process then no amount of buffering is going to help.

#

The problem with using a separate task is that an SRAM allocation for its stack is required, so if that's needed for some applications it might be best as a configurable option.

exotic spindle
#

yes creating a new task and using a queue + lock free ring buffer to transfer solves it

#

its very hacky though .. just did enough to make sure the problem would go away

#

but I've also introduced a crasher somewhere

#

and hard to debug because usb port is tied up connected ot the zwave over usb so can't get serial logs

#

oh I was stack overflowing

exotic spindle
#

ok I've got it cleaned up

#

everything works now at high data rates now

exotic spindle
#

10 restarts of zwave_js addon. no more data corruption