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

cpu/rpx0xx: add periph_usbus support #20817

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

fengelhardt
Copy link
Contributor

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.

@github-actions github-actions bot added the Area: cpu Area: CPU/MCU ports label Aug 18, 2024
@dylad dylad self-requested a review August 19, 2024 08:43
@benpicco benpicco requested a review from bergzand August 19, 2024 08:43
@fengelhardt fengelhardt changed the title cpu/rpxx0xx: add periph_usbus support cpu/rpx0xx: add periph_usbus support Aug 20, 2024
Copy link
Member

@dylad dylad left a 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.

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);
Copy link
Member

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);

cpu/rpx0xx/periph/usbdev.c Outdated Show resolved Hide resolved
@dylad
Copy link
Member

dylad commented Aug 29, 2024

With these changes, I can now receive the setup request from the host. Its interrupt is fired but never served by _usbdev_esr() and it loops forever so we never response to the setup request.

}
if (USBCTRL_REGS->INTS) {
/* Device specific interrupt */
_disable_irq();
Copy link
Member

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

cpu/rpx0xx/periph/usbdev.c Outdated Show resolved Hide resolved
@fengelhardt
Copy link
Contributor Author

With these changes, I can now receive the setup request from the host. Its interrupt is fired but never served by _usbdev_esr() and it loops forever so we never response to the setup request.

I already wondered how to handle setup packets. usbdev_event_t has no event defined for this case, so I can not notify usbus. Do I have to handle it here in the periph driver?

@fengelhardt
Copy link
Contributor Author

fengelhardt commented Aug 31, 2024

Added a fixup with your suggestions @dylad, and improved handling of INTS in isr_usbctrl(). Now the line reset seems to work, and the EP 0 is initialized.

I had no time to test further yet. Maybe tomorrow I can also check my packet flow.

@github-actions github-actions bot added Area: USB Area: Universal Serial Bus Area: sys Area: System labels Sep 1, 2024
@fengelhardt
Copy link
Contributor Author

Now the setup requests are recognized by usbus, but control flow is still garbage.

@dylad
Copy link
Member

dylad commented Sep 4, 2024

From what I can tell this is normal.
Setup packets are not put in EP0 buffer but at the beginning of DPSRAM (offset 0).
Currently, you try to pass DPSRAM + 0x100 to USBUS which contains garbage, thus USBUS doesn't recognize the setup packets.
However, if you pass the right offset when you received a setup packet I can clearly see that the host is requesting the device descriptor 🎉
Unfortunately it's seem there is an issue when responding to the request. I'm not even sure the host sees the response yet. I'll try to check with wireshark next debugging session.

Comment on lines 627 to 631
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);
Copy link
Member

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.

@fengelhardt
Copy link
Contributor Author

Setup packets are not put in EP0 buffer but at the beginning of DPSRAM (offset 0).

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.

@fengelhardt
Copy link
Contributor Author

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.

@dylad
Copy link
Member

dylad commented Sep 12, 2024

I'll see if I can find some times this weekend to help you with that.

Copy link
Member

@dylad dylad left a 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.

Comment on lines +636 to +643
_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);
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: cpu Area: CPU/MCU ports Area: sys Area: System Area: USB Area: Universal Serial Bus
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants