-
Notifications
You must be signed in to change notification settings - Fork 2k
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
cpu/rpx0xx: add periph_usbus support #20817
base: master
Are you sure you want to change the base?
Conversation
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.
At first glance, you're missing NVIC_EnableIRQ(USBCTRL_IRQ_IRQn);
.
I used a debugger and check the PLL configuration. It looks fine but I really think some bits are missing (currently 0) like VBUS_DETECTED and SPEED in SIE_STATUS register.
cpu/rpx0xx/periph/usbdev.c
Outdated
io_reg_atomic_set(&USBCTRL_REGS->MAIN_CTRL, | ||
USBCTRL_REGS_MAIN_CTRL_CONTROLLER_EN_Msk); | ||
io_reg_atomic_set(&USBCTRL_REGS->USB_MUXING, | ||
USBCTRL_REGS_USB_MUXING_TO_PHY_Msk); |
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.
RP2040 datasheet also add USBCTRL_REGS_USB_MUXING_SOFTCON_Msk
.
- you should add
io_reg_atomic_set(&USBCTRL_REGS->USB_PWR,
USBCTRL_REGS_USB_PWR_VBUS_DETECT_Msk
| USBCTRL_REGS_USB_PWR_VBUS_DETECT_OVERRIDE_EN_Msk);
With these changes, I can now receive the setup request from the host. Its interrupt is fired but never served by |
} | ||
if (USBCTRL_REGS->INTS) { | ||
/* Device specific interrupt */ | ||
_disable_irq(); |
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.
Disabling all IRQs here will have the side effect to also clear INTS register.
So when USBUS call its ESR callback, it doesn't process any IRQs as INTS is 0.
Depending on the interruption's source, you may need to clear this register either here or in usbdev_esr
I already wondered how to handle setup packets. |
Added a fixup with your suggestions @dylad, and improved handling of I had no time to test further yet. Maybe tomorrow I can also check my packet flow. |
Now the setup requests are recognized by usbus, but control flow is still garbage. |
From what I can tell this is normal. |
cpu/rpx0xx/periph/usbdev.c
Outdated
USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_FULL_0_Pos, | ||
buf_filled_bit); | ||
_ep_buf_ctrl_reg_write(ep->num, ep->dir, | ||
USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_AVAILABLE_0_Pos, | ||
USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_AVAILABLE_0_Msk); |
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.
It seems to me that you're also missing to set (at least) the length field in the Buffer Control register of the endpoint which might explain why the host didn't get the response of the first setup request.
If set to 0, hardware will try to transfer 0 bytes to the host which is obviously wrong.
Wow, I guess I misread the data sheet here... Some tinkering today did not work so far, but I have an idea for solving that. Sadly I have not time over the weekend. Might take me some time to figure that out. |
Still garbage, unfortunately. But I have found a few bugs. I might simply have a race condition between the setup request handling and data packet handling. Not sure how to handle that with usbus. The USB controller treats setup request differently from normal data, which makes it difficult to hand over to usbus. Maybe my endpoint initialization is not correct, too. |
I'll see if I can find some times this weekend to help you with that. |
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.
I'm having a bad time trying to understand the PID stuff on this IP.
For setup request, TinyUSB and the standalone example from raspberry PI tell that we must answer the setup request on PID 1 but there is no such reference in the datasheet.
cpu/rpx0xx/periph/usbdev.c
Outdated
_ep_buf_ctrl_reg_write(ep->num, ep->dir, | ||
USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_FULL_0_Msk, | ||
buf_filled_bit); | ||
_ep_buf_ctrl_reg_write(ep->num, ep->dir, | ||
USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_AVAILABLE_0_Msk, | ||
USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_AVAILABLE_0_Msk); | ||
_ep_buf_ctrl_reg_write(ep->num, ep->dir, len, | ||
USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_LENGTH_0_Msk); |
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.
Let's try to use a variable and write the whole config at once instead.
Moreover, the datasheet states that the AVAILABLE bit should be set AFTER the rest of the configuration in this register. If USB PLL is running at 48 MHz which is our case IIRC. 3 nop instructions are needed before setting the available bit.
I have made some progress based on @dylad 's comments. I think I figured out the usb controller more or less. I get the setup requests and some control flow afterwards. However, I totally misunderstood how RIOT's usbus works and there is is still a problem. It seems I do not receive any packets and the control flow looks wrong. |
2639284
to
8d3b3e3
Compare
I'm making small progress on my side. I am now stuck halfway through the enumeration process. I'll prepare a more in-depth review once the enumeration process works flawlessly. |
Thank you very much @dylad for your effort. I recently thought that it could only be an issue of setting the PID correctly. I tried hardcoding the PID and I could then receive at least one correct packet from the device. Maybe I find some time to study the PID handling of the tinyUSB driver to implement that here. Wish everyone a happy new year btw. |
Hi @fengelhardt Happy new year to you too. |
Maybe let me first try to get it running. The PID handling I need to rework a lot, I think. I hope to find time in he coming days. |
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.
I'm starting the next round of review so it can help you:
The current ISR management needs a rework. Some events are called twice during a single handling which confuse USBUS.
As this is not really easy to explain with Github UI, you may look at my working branch to see what I have done on my side.
I didn't put all the changes I've made in my branch into this review as I am still debugging and thus not a 100% sure this is the right move but feel free to give it a try.
On my side, the first request is answered, then the device is assigned a new USB address by the host. Reset is issue to apply the new address and the enumeration process starts over. The first setup request with the new address is sent and answered but after that nothing... so the host issue a reset after 5 seconds or so and we start over ...
If you have question on some changes I've made, don't hesitate to ask here or on Matrix :)
(len & USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_LENGTH_0_Msk) | ||
| buf_filled_bit | ||
| pid_bit | ||
| USBCTRL_DPRAM_EP0_IN_BUFFER_CONTROL_AVAILABLE_0_Msk; |
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.
Don't set the AVAILABLE bit here. RP2040 datasheet states that this bit needs to be set AFTER (using your busy_wait implementation) others bits to avoid sync issue inside the controller.
|
||
static rpx0xx_usb_ep_t *_get_ep(uint8_t ep_num, usb_ep_dir_t dir) | ||
{ | ||
return &_hw_usb_dev.hw_ep[2 * ep_num + (dir == USB_EP_DIR_OUT ? 0 : 1)]; |
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.
return &_hw_usb_dev.hw_ep[2 * ep_num + (dir == USB_EP_DIR_OUT ? 0 : 1)]; | |
return &_hw_usb_dev.hw_ep[2 * ep_num + (dir == USB_EP_DIR_IN ? 0 : 1)]; |
This looks innocent but this changes is really important.
static void _ep_set_stall(usbdev_ep_t *ep, usbopt_enable_t enable) | ||
{ | ||
rpx0xx_usb_ep_t *hw_ep = _get_ep(ep->num, ep->dir); | ||
hw_ep->next_pid = 0u; |
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.
hw_ep->next_pid = 0u; |
I think this line should be remove for a correct PID management otherwise we end up always using the same PID.
if (hw_ep->data_buf == NULL) { | ||
DEBUG(" tr completed\n"); | ||
_hw_usb_dev.dev.epcb(&hw_ep->ep, USBDEV_EVENT_TR_COMPLETE); | ||
return; | ||
} |
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.
There is no need for this. USBDEV_EVENT_TR_COMPLETE
should be handle by ESR or EP_ESR directly.
DEBUG("[rpx0xx usb] Call _usbdev_ep_xmit(ep.num=%d, ep.dir=%s, buf=%p, len=%u)\n", | ||
ep->num, PRINT_DIR(ep->dir), buf, len); | ||
|
||
assert(buf != NULL); |
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.
You may also drop this one.
USBUS can call this function with a NULL buffer / 0 length in order to send an ACK to Host.
@fengelhardt Finally I've got some good news ! You may find all the changes I've made on my work branch. |
Nice, I will have a look!
08.01.2025 21:30:19 Dylan Laduranty ***@***.***>:
…
@fengelhardt[https://github.com/fengelhardt] Finally I've got some good news !
Copie.d.ecran_20250108_212408.png (view on web)[https://github.com/user-attachments/assets/3d5e2da5-49b8-43ff-bb09-83736f470f6e]
You may find all the changes I've made on my work branch.
—
Reply to this email directly, view it on GitHub[#20817 (comment)], or unsubscribe[https://github.com/notifications/unsubscribe-auth/AAY3EV6U3ZYJD3OIZVDGV4D2JWDFLAVCNFSM6AAAAABMWTG35GVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKNZYGU4TONRYG4].
You are receiving this because you were mentioned.
[Verfolgungsbild][https://github.com/notifications/beacon/AAY3EV67TUCPEZCSOIXQMTT2JWDFLA5CNFSM6AAAAABMWTG35GWGG33NNVSW45C7OR4XAZNMJFZXG5LFINXW23LFNZ2KUY3PNVWWK3TUL5UWJTUZWJDTO.gif]
|
Contribution description
This is a WIP contribution to add USB support for the rpx0xx MCU.
Testing procedure
The code is in a quite early stage. It compiles with
examples/usbus_minimal
, but it hangs somewhere quite early in the initialization. I will debug it as we go, please do not look all to deeply into it yet.With this PR I primarily want to clarify some question I have regarding the USB stack.
Issues/PRs references
#15822 is for RPx0xx feature tracking.