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

[ext] Add TinyUSB module and port for STM32 and SAM #478

Merged
merged 9 commits into from
Sep 30, 2020

Conversation

salkinium
Copy link
Member

@salkinium salkinium commented Sep 19, 2020

This adds a stripped-down TinyUSB submodule, and lbuildifies it as a follow-up for #477.

  • CMSIS header compliance for ST and SAM
  • Lbuildular, modular TinyUSB
  • Automatic FreeRTOS support
  • Common tusb_config.h generator
  • Map class options to lbuild
  • Port platform-generic descriptors like tinyusb_get_serial()
  • Examples
  • Port platform-generic USBSerial
  • Integrate [usb] Add USB support to SAM based on tinyusb #477 work.
  • H/W Testing
    • SAMD21 CDC Serial
    • SAMD21 Bossac Arduino-style hack
    • STM32F103 Blue Pill
    • STM32F303 Disco
    • STM32F407 Disco
    • STM32F429 Nucleo
    • STM32F746 Disco (only fs)
    • STM32F411 Mini
    • STM32F401 Mini
  • Documentation

Limitations:

  • No Host class generated.
  • Cannot get STM32F469 Disco FS to work (there's no TinyUSB example either).
  • Cannot get STM32F746 Disco HS to work (even though there is a TinyUSB example for this).
  • Did not implement all device class enumerators, due to lack of motivation:
    • HID
    • NET
    • USBTMC

cc @henrikssn @strongly-typed

@salkinium
Copy link
Member Author

salkinium commented Sep 19, 2020

I got a little over-exited and accidentally modularized the entire tinyusb source code. I have a hunch that I can generate the descriptors automatically that way for multiple classes in one device. Or maybe I've drunk too much tea…

(The original repo was a ~30MB download, so I made a partial clone for ~300kB).

ext/hathach/module.lb Outdated Show resolved Hide resolved
ext/hathach/module.lb Outdated Show resolved Hide resolved
ext/hathach/module.lb Outdated Show resolved Hide resolved
ext/st/module.md Show resolved Hide resolved
src/modm/platform/clock/sam/gclk.cpp.in Show resolved Hide resolved
tools/build_script_generator/common.py Show resolved Hide resolved
@henrikssn
Copy link
Contributor

Very cool, this is much less hacky than my PR :D

Re the modularization thing - I did look through the linker output of the example in my PR and it seems like the linker did quite a good job of kicking out all the unused stuff. The binary size was about 9.5-10kB which might serve as a good benchmark for this effort (I don't find 10kB for a hello world example "tiny" at all so any improvements are highly welcome!)

@salkinium
Copy link
Member Author

salkinium commented Sep 19, 2020

The aggressive modularization is mostly to cut down compile time, by just compiling less files ;-P This is the only reason we can compile the HAL for all 2000+ devices in the CI within a reasonable time (<10mins per family).

The linker is pretty good at garbage collection, and I've stripped the linkerscript down to the bare minimum of sections. BUT we don't use LTO, even though it might be a good idea to look into this.

@salkinium
Copy link
Member Author

I couldn't get this to work in hardware, I'm not sure why though… I'll have to verify all clock sources and double check the hardware connections… The tinyusb debug printf hasn't printed any errors, not sure if it is supposed to…

@henrikssn
Copy link
Contributor

Is this completely merged with #477 now?

If yes, then I can retest it on my SAM device to help you narrow down the issue. Unfortunately tinyusb doesn't seem to output anything useful on serial until it starts to work...

ext/hathach/tusb_config.h.in Show resolved Hide resolved
ext/hathach/tusb_port.cpp.in Show resolved Hide resolved
ext/hathach/uart.hpp Outdated Show resolved Hide resolved
examples/stm32f469_discovery/usb/main.cpp Outdated Show resolved Hide resolved
ext/hathach/uart.hpp Show resolved Hide resolved
@salkinium

This comment has been minimized.

@henrikssn

This comment has been minimized.

Copy link
Contributor

@henrikssn henrikssn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for merging this!

src/modm/platform/usb/stm32/usb.hpp.in Show resolved Hide resolved
examples/samd/usbserial/main.cpp Outdated Show resolved Hide resolved
src/modm/platform/usb/sam/usb.hpp.in Outdated Show resolved Hide resolved
src/modm/platform/usb/sam/usb.hpp.in Outdated Show resolved Hide resolved
src/modm/platform/usb/sam/usb.hpp.in Outdated Show resolved Hide resolved
@salkinium

This comment has been minimized.

@salkinium
Copy link
Member Author

Can you try if #477 works on your SAMD board?

Tested it on a fresh clone of your branch, but it fails in the exact same way: The USB port appears, I can picocom --imap lfcrlf -b 115200 /dev/tty.usbmodem14101 connect to it, but there's no output, even though the LED on the board turns off, so the SAMD does register a connection. The bossac -a doesn't work either.

Perhaps this is a macOS problem? Or maybe I'm using the wrong command to open the serial port?
The SystemProfiler does recognize it correctly:

@salkinium
Copy link
Member Author

My branch shows the exact same system information, so perhaps it's a macOS 10.14 problem? What OS are you testing this on?

@salkinium
Copy link
Member Author

My branch shows the exact same system information, so perhaps it's a macOS 10.14 problem? What OS are you testing this on?

No, the issue is simply that modm::endl does not automatically flush: with an additional << modm::flush IT WORKS!!!

@salkinium
Copy link
Member Author

The Arduino hack works too, but I don't have the UF2 bootloader on my device, I have the original Bossa bootloader and no idea how to jump into double tap mode here…

@salkinium
Copy link
Member Author

salkinium commented Sep 20, 2020

So the bootloader on my board is this one: https://github.com/arduino/ArduinoCore-samd/tree/master/bootloaders/zero

And the address is the same, but the magic is different 0x07738135. This does make the bootloader active, however bossac times out before the bootloader is initialized (it works fine on the second call to bossac). So this isn't a very reliable hack.

@henrikssn
Copy link
Contributor

henrikssn commented Sep 20, 2020

Latest commit works reliably for me.

So the bootloader on my board is this one: https://github.com/arduino/ArduinoCore-samd/tree/master/bootloaders/zero

And the address is the same, but the magic is different 0x07738135. This does make the bootloader active, however bossac times out before the bootloader is initialized (it works fine on the second call to bossac). So this isn't a very reliable hack.

This is a better bootloader which works reliably: https://github.com/microsoft/uf2-samdx1
Adafruit has prebuilt binaries for it if you use the SAMD21G18A: https://github.com/adafruit/uf2-samdx1

I guess we should make the magic constant an lbuild option given that the SAM bootloader developers couldn't agree on a single one...

@salkinium
Copy link
Member Author

Ok, I'll look into the STM32 side next weekend.

I guess we should make the magic constant an lbuild option given that the SAM bootloader developers couldn't agree on a single one...

Pfff, lame, let's simply™ scan the bootloader binary image to determine the right magic constant ;-P

@salkinium
Copy link
Member Author

STM32 Blue Pill CDC example is working after fixing the interrupt filtering code.

@salkinium
Copy link
Member Author

I've implemented auto-generation of USB descriptors, at least for the device type.
For this I've added a list option to lbuild, which preserves order and duplicates, so that the :tinyusb:config can be given as device.cdc,device.msc, device.cdc,device.midi or device.cdc,device.cdc, This works very well for CDC, MSC, MIDI, VENDOR and I assume will work for DFU_RT and HID well too (once I add them). However, USBTMC and NET seem more complicated (and I'm not sure yet how to test it). I'll keep polishing.

I've tested USB sucessfully on STM32F1, STM32F3, STM32F4 both fsdev and synosys hardware. However, I've noticed a couple of limitations.

  • The limiting factor on STM32 fsdev devices is the size of the dedicated USB RAM, which is just 512B or 1024B large. You can enumerate three CDC devices, but you can only open two of them because the EP buffers are allocated dynamically.
  • The limiting factor on STM32 fs synopsys devices is the number of endpoints, which are just 4 or 6 EP. For example: EP0 is always used, CDC uses EP1 and EP2 and MSC uses EP4.

So you're limited to only two device classes in general. Unfortunately error reporting in TinyUSB is terrible, since their TU_ASSERT implementation isn't hookable, and always calls the bkpt instruction, which will hardfault if no debugger is attached. This is caught by modm_abandon, which will blink the LEDs and reboot into a nice infinite loop ;-P. I think I'm going to have to patch TinyUSB for this and try to upstream it, because this is an unacceptable way to debug.

I'll try with STM32F7 next, which has a HS Synopsys device and more resources and report back.

@henrikssn
Copy link
Contributor

+1 for improving debuggability, this is by far the biggest con of tinyusb (maybe apart from that it is written in C).

@salkinium
Copy link
Member Author

This is now feature complete, I still need to fix the CI though. I didn't add the arduino serial hack to the library nor to the BSP, since the bootloader magic numbers are different. You can add it to your application for now.

I tested this in HW in all the boards I could find with the USB port.

@salkinium salkinium force-pushed the feature/tinyusb branch 2 times, most recently from d3a1a26 to 7cd766d Compare September 26, 2020 21:09
@salkinium
Copy link
Member Author

I have STM32F401/411 Mini boards, however I don't have a USB-C to USB-A converter (it's in the mail), so I didn't implement BSP support for that. Perhaps @rleh can add it later?

@salkinium salkinium force-pushed the feature/tinyusb branch 2 times, most recently from 89d457f to 0883d0e Compare September 26, 2020 21:32
@salkinium
Copy link
Member Author

I didn't implement BSP support for that. Perhaps @rleh can add it later?

TinyUSB had an example for this board, so I added it to the BSP, but didn't test it.

@salkinium salkinium force-pushed the feature/tinyusb branch 2 times, most recently from 0aa6286 to 3a2862c Compare September 27, 2020 00:11
@rleh
Copy link
Member

rleh commented Sep 27, 2020

I've tested the example on Mini-F401 and Mini-F411 boards: Serial and Mass storage both work!
Thanks!

@salkinium
Copy link
Member Author

@henrikssn Please review and test on your hardware.

Copy link
Member

@rleh rleh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice 👍 👍 👍 👍 👍

ext/hathach/module.md Show resolved Hide resolved
ext/hathach/module.md Show resolved Hide resolved
ext/hathach/tusb_port.cpp.in Show resolved Hide resolved
src/modm/board/disco_f746ng/board.hpp Show resolved Hide resolved
src/modm/platform/clock/stm32/rcc.hpp.in Outdated Show resolved Hide resolved
src/modm/platform/gpio/sam/pin.hpp.in Outdated Show resolved Hide resolved
tools/build_script_generator/scons/site_tools/dfu.py Outdated Show resolved Hide resolved
tools/scripts/generate_module_docs.py Outdated Show resolved Hide resolved
@ekiwi
Copy link
Contributor

ekiwi commented Sep 28, 2020

Just wanted to say that this is really exciting. Finally USB support in modm!

@salkinium salkinium merged commit 3072005 into modm-io:develop Sep 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

4 participants