-
Notifications
You must be signed in to change notification settings - Fork 997
atsamd5x: improve USBCDC #1452
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
atsamd5x: improve USBCDC #1452
Conversation
|
Since up to 128 bytes can be sent in a single pass, writing up to 128 bytes is very fast. We can make it even faster by using the send completion interrupt.
testcode: |
|
You can increase the size of the RingBuffer by setting the following head and tail to volatile.Register16 // src/machine/buffer.go
type RingBuffer struct {
rxbuffer [bufferSize]volatile.Register8
head volatile.Register8
tail volatile.Register8
}If you want to make it larger than 128, you must also change the following usbEndpointDescriptors[usb_CDC_ENDPOINT_IN].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[usb_CDC_ENDPOINT_IN])))) |
|
@sago35 it appears you have implemented the interrupt solution: if i == usb_CDC_ENDPOINT_IN {
UART0.waitTxc = false
}However it appears that your proposed Is that correct? |
|
Also, it would seem that a similar change could be made to the SAMD21 support, is that true @sago35 ? |
I'll do a
Yes. but,,, |
|
I'm not sure I fully understand this code, but I don't see anything weird with it. Sidenote: this gives me even more reason that USB should be separated out in a new package. I think the code would be easier to follow if the code that sends a buffer over USB and the code that buffers for the next transmission is cleanly separated with an API. |
|
@sago35 what is the specific race condition you are seeing? |
Calling usbcdc.TxBuffer.Put(c) with multiple priorities will cause problems. interrupt.Disable() can be built and used with interp-rewrite branch.
|
| for i := uint8(0); i < sz; i++ { | ||
| udd_ep_in_cache_buffer[usb_CDC_ENDPOINT_IN][i], _ = usbcdc.TxBuffer.Get() | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This process is a byte copy, but it's a waste of time.
I will create a new PR that improves on this part of the process.
| timeout := 10000 | ||
| ok := false | ||
| for !ok { | ||
| ok = usbcdc.TxBuffer.Put(c) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RingBuffer.Put() does not consider calling from multiple priorities.
interrupt.Disable() is required.
Increased speed by increasing the size of the data to be sent at a time.
I also made it so that it waits more than 1ms before timeout, so it probably won't time out.
Right now we're using the Get() process from a RingBuffer, but we can optimize it further and send the data from the RingBuffer directly.
However, the code is complicated by the fact that the ADDR register needs to be a 4 byte align.
When the PR is merged, #1175 in atsamd5x is solved.
This PR is designed to flush() every 1ms.