ZigEmbeddedGroup / microzig

Unified abstraction layer and HAL for several microcontrollers
zlib License
1.07k stars 81 forks source link

Support serial over USB (CEC ADC) #161

Open negz opened 7 months ago

negz commented 7 months ago

I'd like to have a log.zig logFn that I could use to emit debug logs over USB, rather than UART.

Currently Microzig has support for acting as a USB HID device. I believe emitting debug logs over USB would require support for acting as a "serial device", which uses USB CDC/ADC.

negz commented 7 months ago

https://github.com/tinygo-org/tinygo/blob/731532cd2/src/machine/usb.go#L261

I'm attempting to take a shot at this, using TinyGo's implementation as a reference. In part because it seems more minimal than alternatives like TinyUSB. I believe TinyGo have implemented just enough of CEC to be a serial device, not support for modems etc. I'm also trying to use TinyGo as a reference because I'm fluent in Go, but not Zig, or microcontrollers, or USB. 😄

rosshadden commented 5 months ago

Any luck with this? I read that picotool needs the firmware running on a microcontroller to implement USB-CDC in order for its load --force argument to work (letting you reboot picos outside of BOOTSEL mode). When using C you can set pico_enable_stdio_usb(<project-name> 1) in CMakeLists.txt to accomplish this.

Apparently this is because picotool uses PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE though I don't know enough of how this stuff works to provide any of my own insight.

negz commented 5 months ago

Unfortunately I didn't get very far before my vacation ended.

I was finding it pretty hard to figure out how to cleanly extend the existing USB implementation. A lot of this is probably just because I don't know Zig, but I think it was exacerbated by the fact that the implementation isn't designed for extensibility.

My understanding based on https://github.com/ZigEmbeddedGroup/raspberrypi-rp2040/pull/40 is that the USB implementation is a port of https://github.com/cbiffle/rp2040-usb-device-in-one-file/blob/4878f4/src/main.rs, which per its header comments is intended "for reference and study".

Here's what I ended up with. It's mostly just all the structs that I think are needed to make CDC work: https://github.com/ZigEmbeddedGroup/microzig/commit/846e994e

arkadiuszwojcik commented 1 month ago

I have some progress on this, but further work depends on this PR: #201. Chunked data support is required because USB CEC ADC config descriptor length is above regular packet size (64 bytes).

arkadiuszwojcik commented 1 month ago

With #201 merged, I was playing around with USB-CDC. I had a working prototype, but the way the config was defined was very ugly. Now I have a new prototype with a much nicer approach. I would like to know your opinion on it. Here is main file and here is the main tagged union that does the trick with some comptime magic. Config code can be simplified more with default values for some fields. There is also new serialize_buff (temporary name) method and ole one serialize left for comparison. Any pros and cons of such solution?

@r4gus @negz @rosshadden