Closed alexmadeathing closed 1 year ago
First things first, unfortunately Rust is not a good choice for stable development for AVR (yet). There are probably still bugs in rustc/LLVM, and atmega-usbd is definitely not stable. If you want a (relatively) painless development and support experience, I recommend using LUFA.
This crate is a very early prototype and I personally cannot provide support in every possible scenario; I've only really tested this on Windows/Linux with usbd-hid
, and I don't use it very often. Currently I rely on library users to have the willingness and the low-level knowledge of USB on AVR to diagnose errors/bugs themselves. If they're willing to take the time to help solve it, I may be able to provide some guidance on specific problems.
With that out of the way, I'll try to answer your other questions:
The interrupt stuff - Interrupt service routines (ISRs) are generally not implemented in library crates, for several reasons:
main
, there can only be one ISR for each interrupt vector. If a library implements an ISR, it prevents the user of the library from creating their own, which they may want to do to perform other things when the interrupt happens.main
and/or other ISRs. In this case, they need access to the USB device to call its poll()
function. The easiest way to do this is using static
global variables, and it's not clear how the library should define those and the APIs to initialize them. Partly because it depends on the specific UsbClass
types you're using, and also partly because main
and/or other ISRs will need access to that context to update it, and there is not one "best" way to manage that shared mutable access. It's just best to leave it for the library user to manually manage.There are "runtime" libraries like rtic
that can implement the interrupts and shared resources for you, but generally the library just defines a set of macros that are invoked by the library user to set it all up.
Polling in the main loop - It is true that stm32-usbd
allows you to poll USB in the main loop without using interrupts at all. I used to write code that way. Personally I prefer using interrupts, especially on AVR where the processing power is generally much more limited. You may have a lot of other things going on in the main loop between polls that could slow down the USB. Interrupts fix that; they have priority (except in critical sections) and can be used to handle events as quickly/timely as possible.
In terms of supporting this for atmega-usbd - I think it was supported earlier (in 3accdcab12db8159b7cbb4d1dcef569d4c9630fc, the HID example used main-loop polling) but I haven't paid much attention to it for the reasons I mentioned.
PLL section - I'm not sure why it still works when you remove it. I would say try power cycling it after flashing that code, and see if it still works. It definitely is required for clocking the USB peripheral; it's possible in your case that PLL is kept configured after reset or maybe by a bootloader.
Hope this helps.
Thank you for taking the time to consider my questions and write all that out. You went above and beyond. I appreciate it.
Noted regarding the ISRs and PLL section.
Alright. I'll work out whether I want to continue with Rust for this. I think I do, but it just means I might need to get down and dirty with datasheets and low level registers. And frankly, I can see I have a lot to learn about embedded in general.
I'll close this issue as I see it doesn't really relate to your lib.
I want to clarify - Rust on AVR is usable, but it may take a lot more time and effort to do things compared to other embedded targets. You might encounter very weird compiler bugs sometimes (though that is becoming less common).
As a hobby, I would recommend it if you don't mind spending a lot of time digging and learning. That's what I do, and that's why I made this - I wanted to write my own Rust firmware for some AVR-based keyboards I own. It's been very rewarding getting this to work and helping make progress in support for AVR.
However, if you are designing a device from scratch and you want it to "just work" without much effort, I would either 1. drop AVR or 2. drop Rust. If you want to try out embedded Rust and don't care about the specific microcontroller, there is pretty good support for ARM Cortex-M chips. I've worked specifically with STM32 and RP2040, and both have good HAL libraries.
Ahhh thanks for the tips buddy. I actually have a few teensys lying around which are cortex M4 if I remember correctly. I'll dust them off. A bit overpowered for my project but that's no biggie as maybe I can drive a display too. Yes, it is just a hobby. I'm a C++ coder by profession, but haven't really explored embedded much, and Rust is my happy place, so I'm experimenting for fun.
Speaking of keyboards, what do you have? I've built myself a couple Corne splits for home and work and a Reviung for travelling. Via/QMK so not Rust yet, but I'm sure they will be soon. How far along is your firmware?
Hi, so I managed to implement a simple midi controller yesterday, using
usbd-midi
andatmega-usbd
. I'm not new to Rust and have done some arduino embedded before, but this was the first time I joined the two. Frankly, I'm still a newbie at embedded in general. So I have a few questions if you don't mind.I realise this library is still fledgeling. Thank you for implementing it. You saved me a big headache!