Skip to content

USB support for Leonardo #572

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

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open

Conversation

supersimple33
Copy link

I have take the code which was written by @agausmann here and turned it into this PR with a number of modifications so that it is hopefully useful to programmers working at every level of this repository.

At the generic level I have added a new macro (v2) to make a AvrGenericUsbBus struct which implements UsbDevices UsbBus trait. Then at the mcu hal I have called this macro and then also provided it with a SuspendNotifier struct and implemented a new trait ClearInterrupts for necessary interrupt registers. I also define mcu specific constants here as well. At the arduino hal level I import all the important parts from the mcu hal level and then also supply two convenience macros for creating parts of the USB setup. Finally I have added the code for a new example which uses all of this code and follows the demo keyboard as set out in the original atmega-usbd.

This addresses #40.
I have also included some code for the atmega8u2 in anticipation of #568.

@supersimple33
Copy link
Author

I won't have access to my leonardo for a few weeks and haven't been able to test these changes which is why I marked as draft. If someone can confirm they work which I don't see why they wouldn't then I'll open for review.

@supersimple33 supersimple33 marked this pull request as ready for review August 9, 2024 14:06
@rattboi
Copy link

rattboi commented Oct 12, 2024

I can confirm that this seems to be working as expected. I built avr-hal against his PR and used his keyboard example on an ItsyBitsy 32u4, pretending it's a Leonardo.

After flashing with ravedude, a new USB HID keyboard device showed up.

setting d2 low triggers the payload and you can see the hello world string in my terminal.

[1579390.792130] usb 1-1: USB disconnect, device number 10
[1579391.999568] usb 1-1: new full-speed USB device number 11 using xhci_hcd
[1579392.169033] usb 1-1: New USB device found, idVendor=1209, idProduct=0001, bcdDevice= 0.10
[1579392.169048] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[1579392.169054] usb 1-1: Product: Bar
[1579392.169058] usb 1-1: Manufacturer: Foo
[1579392.190625] input: Foo Bar as /devices/pci0000:00/0000:00:08.1/0000:c1:00.3/usb1/1-1/1-1:1.0/0003:1209:0001.003A/input/input90
[1579392.243546] hid-generic 0003:1209:0001.003A: input,hidraw9: USB HID v1.10 Keyboard [Foo Bar] on usb-0000:c1:00.3-1/input0
[1579392.325168] input: Foo Bar as /devices/virtual/input/input91

ratttop :: code/avr-rust/avr-hal-test ‹main*› % HelloHello WorldHello WoHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World

@Merlin04
Copy link

Merlin04 commented Feb 4, 2025

currently using this PR for a usb midi device with a Pro Micro board (also pretending it's a Leonardo) and it works great - would be awesome to see this merged at some point!

@supersimple33
Copy link
Author

@Rahix

@bobozaur
Copy link

@supersimple33 First of all thanks for the PR! I'm using it in one of my projects and it seems to work great!

However, I have some questions/observations that I'll leave here in case someone more knowledgeable than me can clarify them or for other people that might run into this:

  • I'm setting the hardware timer0 for some operations and that must get set before the USB part for some reason. Trying to setup USB prior to the timer results in crashes.
  • In the USB interrupts I'm accessing some shared state through a Mutex<RefCell<T>>. I spent a lot of time banging my head against walls for why this was not working correctly to discover that the problem is in fact in the USB_GEN interrupt. Not accessing the shared state there through interrupt::free() makes the code behave as expected. In my scenario that's fine, because the state is really used for transmitting some information in USB_COM and doesn't really serve any purpose in USB_GEN (but I still poll the usb_device in USB_GEN). I don't really get why this happens though, as I'm not using any nested interrupts so I don't see how there could be contention on the Mutex. It could theoretically be a timing issue as well, though the code is pretty lean even with the Mutex. Pretty strange, but fortunately got to the bottom of it.
  • I wanted to tweak some of the behavior of the AvrGenericUsbBus in terms of the usb_device::usb::UsbBus impl and I intended to do that through a newtype wrapper and reimplement the trait. However, even though all fields are marked as pub, the compiler yells that the fields are not found. Maybe that's because of the create_usb_bus! macro misbehaving? I have to ask, why even create the macro? It seems to me that a direct implementation of the type, along with all the conditionally compiled parts, would suffice. After all the digging I realized I don't need to tweak the UsbBus impl after all, but having the possibility to do it would be nice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants