Skip to content

Conversation

gschorcht
Copy link
Contributor

Contribution description

This PR adds tinyUSB open-source cross-platform USB Host/Device stack for embedded systems as package.

The initial intention was to add USB support for ESP32-S2 and ESP32-S3 since the tinyUSB stack includes a hardware driver for these ESP32x SoCs. The ESP-IDF also uses tinyUSB for USB support, but integrates tinyUSB. Instead of using the tinyUSB from ESP-IDF, this PR adds tinyUSB as a package to be able to use it for other platforms like STM32 and nRF. STM32 support is also provided by this PR.

Testing procedure

Compile and flash the test application tests/pkg_tinyusb_cdc_msc.

BOARD=esp32s3-devkit make -j8 -C tests/pkg_tinyusb_cdc_msc flash

It should be possible to use any STM32 board that also supports feature periph_usbdev

This application uses the tinyUSB device stack to emulate a mass storage device (MSC) with a communication interface (CDC).

Once the application is flashed, the device should be mounted when it is
connected to a host. That is,

  • the mass storage interface is mounted as volume TinyUSB MSC in the operating system and
  • the communication interface is mounted as a serial device, for example as /dev/ttyACM0 on Linux.

It should then be possible

  1. to read from and write to the mass storage device with the usual file operations of the operating system
  2. to connect to the serial interface of the device with a terminal program, e.g.
    python -m serial.tools.miniterm /dev/ttyACM0 115200
    
    and get the entered characters sent back.

The test application uses LED0, if present, to indicate the status of the device by blinking at different frequencies.

Issues/PRs references

@github-actions github-actions bot added Area: boards Area: Board ports Area: build system Area: Build system Area: cpu Area: CPU/MCU ports Area: doc Area: Documentation Area: Kconfig Area: Kconfig integration Area: pkg Area: External package ports Area: tests Area: tests and testing framework Platform: ESP Platform: This PR/issue effects ESP-based platforms labels Sep 14, 2022
@gschorcht gschorcht added Type: new feature The issue requests / The PR implemements a new feature for RIOT CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Sep 14, 2022
@benpicco benpicco requested review from bergzand and dylad September 14, 2022 08:37
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.

Thanks @gschorcht That's a pretty nice package !
I took a quick glance at it. I think I have a supported ST boards somewhere in my basement so I should be able to run some tests. But I cannot test on ESP side.
I'll dive further when I'll run some tests.

@dylad
Copy link
Member

dylad commented Sep 16, 2022

@gschorcht I give this PR a try with a stm32f429i-disc1 but with no luck so far. It seems we are stuck here
Which STM32-based did you try on your side ?

@gschorcht
Copy link
Contributor Author

gschorcht commented Sep 17, 2022

@gschorcht I give this PR a try with a stm32f429i-disc1 but with no luck so far. It seems we are stuck here Which STM32-based did you try on your side ?

Hm, I have tested it with a nucleo-f767zi withouth any problems. So I thought that it works with STM32F4 family supported by the tinyUSB also.

@gschorcht
Copy link
Contributor Author

gschorcht commented Sep 17, 2022

@gschorcht I give this PR a try with a stm32f429i-disc1 but with no luck so far. It seems we are stuck here Which STM32-based did you try on your side ?

If it sucks here, the Synopsys DWC2 core seems to be not available at this point. I will check.

@gschorcht gschorcht added the State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet label Sep 17, 2022
@gschorcht
Copy link
Contributor Author

@gschorcht I give this PR a try with a stm32f429i-disc1 but with no luck so far. It seems we are stuck here Which STM32-based did you try on your side ?

If it sucks here, the Synopsys DWC2 core seems to be not available at this point. I will check.

@dylad Could you please check the DWC2_CORE_REV used by STM32F429i at address 0x50000040 with debugger or printf?

printf("XXXX %08lx\n", *((uint32_t *)0x50000040);

or

printf("XXXX %08lx\n", _global_regs->Reserved40[0]);

in function tinyusb_hw_init_dev in pkg/tinyusb/hw/hw_stm32.c below periph_clk_en(conf->ahb, conf->rcc_mask);

periph_clk_en(conf->ahb, conf->rcc_mask);

@dylad
Copy link
Member

dylad commented Sep 22, 2022

@gschorcht
I've added

    printf("XXXX %08lx\n", *((uint32_t *)0x50000040));
    printf("XXXX %08lx\n", global_regs->Reserved40[0]);
    printf("XXXX %08lx\n", *((uint32_t *)0x50000040));

just after the periph_clk_en() function as requested.

Got this output:

2022-09-22 21:00:28,281 # main(): This is RIOT! (Version: 2022.10-devel-586-gdc3257-pkg/tinyusb)
2022-09-22 21:00:28,471 # XXXX 00000000
2022-09-22 21:00:28,472 # XXXX 4f54281a
2022-09-22 21:00:28,473 # XXXX 00000000

@dylad
Copy link
Member

dylad commented Sep 22, 2022

I've replaced 0x50000000ULby 0x40040000UL and I got the same result as global_regs->Reserved40[0]
Seems like we are using USB_OTG_HS_PERIPH_BASE, not USB_OTG_FS_PERIPH_BASE

@dylad
Copy link
Member

dylad commented Sep 22, 2022

I've made some progress with:
CFLAGS="-DTINYUSB_TUD_RHPORT=1" make BOARD=stm32f429i-disc1 -C tests/pkg_tinyusb_cdc_msc flash
I'm not stuck anymore but enumeration fails now. I'll investigate further this weekend.

@gschorcht
Copy link
Contributor Author

I've replaced 0x50000000ULby 0x40040000UL and I got the same result as global_regs->Reserved40[0]
Seems like we are using USB_OTG_HS_PERIPH_BASE, not USB_OTG_FS_PERIPH_BASE

Ah, I see, the peripheral configuration includes cfg_usb_otg_hs_fs.h instead of cfg_usb_otg_fs.h. It seems that the stm32f429-dis1 board is the only STM32 board that uses the OTG HS controller instead of the OTG FS controller which is RHPORT=1 in tinyUSB terminology for whatever RHPORT stands. And, only the OTG HS controller seems to be a Sysopsys DWC2 core.

* ...
* // initialize the tinyUSB stack including used peripherals and
* // start the tinyUSB thread
* tinyusb_setup();
Copy link
Member

Choose a reason for hiding this comment

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

Why is this not auto-init'ed?

Copy link
Member

Choose a reason for hiding this comment

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

Do you mind if we add this in a followup PR ?
This PR is already in good shape.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why is this not auto-init'ed?

Good question. If it is possible to create a thread during the auto-init and the scheduler is already running, it should be possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have a local commit that implements auto-initialization. It only needed a few changes:

 pkg/tinyusb/Makefile.dep                     |  2 ++
 pkg/tinyusb/contrib/tinyusb.c                | 13 +++++++++++++
 pkg/tinyusb/doc.txt                          |  6 ++++--
 sys/auto_init/include/auto_init_priorities.h |  6 ++++++
 tests/pkg_tinyusb_cdc_msc/main.c             |  4 ----
 5 files changed, 25 insertions(+), 6 deletions(-)

Should I provide it or should we add this in a followup PR?

Copy link
Contributor Author

@gschorcht gschorcht Oct 1, 2022

Choose a reason for hiding this comment

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

See commit 1879a1c.

*
* tinyUSB is an open-source cross-platform USB Host/Device stack for
* embedded systems.
*
Copy link
Member

Choose a reason for hiding this comment

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

How does tinyUSB relate to the usbus native RIOT modules? Is it (or can it be) used on top of the existing usbus? Or is it mutually exclusive? (E.g. because the set of supported hardware is distinct -- and what when one gains support for a device another has?)

Copy link
Member

Choose a reason for hiding this comment

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

tinyUSB and USBUS are mutually exclusive.
tinyUSB provides both the USB stack and the lowlevel driver whereas usbus depends on periph_usbdev
FWICT, tinyUSB has more features and support more lowlevel peripherals than usbus/periph_usbdev but as @gschorcht pointed out here, it looks like tinyUSB uses more RAM/ROM than our stack.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How does tinyUSB relate to the usbus native RIOT modules?

As @dylad said, tinyUSB includes the USB host and device stack as well as device drivers for a variety of platforms. Also, the stack supports many more device classes than usbus.

Is it (or can it be) used on top of the existing usbus? Or is it mutually exclusive? (E.g. because the set of supported hardware is distinct -- and what when one gains support for a device another has?)

tinyUSB device driver use the same hardware as periph_usbdev. So either tinyUSB or usbus can be used. But, theoretically, it should be possible to implement an interface to use the tinyUSB stack on-top of a periph_usbdev device driver or to use usbus on top of a tinyUSB device driver. This would require to map the interface of tinyUSB device drivers to the periph_usbdev interface.

Comment on lines +26 to +29
FEATURES_CONFLICT_MSG += "Only one standard C library can be used."

FEATURES_CONFLICT += periph_gpio_irq:periph_gpio_ll_irq
FEATURES_CONFLICT_MSG += "Only one GPIO IRQ implementation can be used"
FEATURES_CONFLICT_MSG += "Only one GPIO IRQ implementation can be used."
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this belong to another PR ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm, it's such a small change that improves readability. Since we are touching the file anyway, I thought we could improve it. Without this small change, the message looks like this:

Rationale: Only one standard C library can be used Only one GPIO IRQ implementation can be used Package tinyUSB is not yet compatible with periph_usbdev.

That is, the message is completely unstructured.

With this small change, the message looks like this:

Rationale: Only one standard C library can be used. Only one GPIO IRQ implementation can be used. Package tinyUSB is not yet compatible with periph_usbdev.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is, the problem is that all messages are simply strung together without punctuation.

@dylad
Copy link
Member

dylad commented Sep 30, 2022

Got tinyUSB working on my SAME54-XPRO 😍

@gschorcht
Copy link
Contributor Author

Got tinyUSB working on my SAME54-XPRO heart_eyes

I got USB OTG HS with external ULPI PHY working on stm32f746g-disco.

@github-actions github-actions bot added the Area: sys Area: System label Oct 1, 2022
@gschorcht
Copy link
Contributor Author

This should result into following definitions that could be overridden in the makefile:

  • the board uses only USB OTG FS: TINYUSB_TUD_RHPORT=0 and TINYUSB_TUH_RHPORT=0
  • the board uses only USB OTG HS: TINYUSB_TUD_RHPORT=1 and TINYUSB_TUH_RHPORT=1
  • the board uses both: TINYUSB_TUD_RHPORT=0 and TINYUSB_TUH_RHPORT=1

Now that I am experimenting with the USB OTG HS port with UPLI HS PHY on the board stm32f746g-disco, I am wondering if defining these defaults is really the way to go. tinyUSB host stack does not work at all for STM32 and the other platforms that RIOT supports.

The reason is that tinyUSB needs one driver for the USB device stack according to the API defined in tinyusb/src/device/dcd.h and another one for the USB host stack according to the API defined in tinyusb/src/host/hcd.h. At the moment, tinyUSB has only USB device stack drivers for STM32 and the other platforms that RIOT supports. That is, the host stack can't be used at the moment.

To use bothe the USB OTG FS and the USB OTG HS port for the device stack, we have to change the logic. Defining TINYUSB_TUD_RHPORT is not sufficient. We would need something like TINYUSB_TUD0_RHPORT and TINYUSB_TUD1_RHPORT.

@gschorcht
Copy link
Contributor Author

It seems that the stm32f429-dis1 board is the only STM32 board that uses the OTG HS controller instead of the OTG FS controller which is RHPORT=1 in tinyUSB terminology for whatever RHPORT stands.

Ah, now I got it. RHPORT stands for Root-Hub port.

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.

Last comment on my side. Feels free to squash at the same time.

#define TINYUSB_TUH_RHPORT 0
#endif

#define HSE_VALUE CLOCK_HSE
Copy link
Member

Choose a reason for hiding this comment

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

Why is this define here ?
Could you add a comment about that if it's really needed please ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why is this define here ?

Hm, it could be a leftover from trying to use tinyusb/src/portable/st/synopsys/dcd_synopsys.c as a driver. I have removed it. Let's see if Murdock is happy. If so, it was just a leftover. If not, Murdock will tell us why.

Copy link
Member

Choose a reason for hiding this comment

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

Indeed, Murdock has the answer ! This was not a leftover.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm, it's not really to me, why this is required for this one board only.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah ok, I see. stm32f723e-disco is the only board that uses a STM32F723 for which the CMSIS defines USB_HS_PHYC, that is, the internal UTMI HS PHY is used. Interesting, this will help us to support also UTMI in RIOT's Synopsys DWC2 driver for OTG HS interfaces (PR #18679).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

BTW, according to the schematic, the stm32f723e-disco is also a board with USB OTG FS as well as USB OTG HS connector. The internal UTMI HS PHY is used with the USB OTG HS interface.

@dylad
Copy link
Member

dylad commented Oct 3, 2022

To use bothe the USB OTG FS and the USB OTG HS port for the device stack, we have to change the logic. Defining TINYUSB_TUD_RHPORT is not sufficient. We would need something like TINYUSB_TUD0_RHPORT and TINYUSB_TUD1_RHPORT

The current state looks good to me, we can prepare something later to enable support for both controllers at the same time.

@dylad dylad added Reviewed: 1-fundamentals The fundamentals of the PR were reviewed according to the maintainer guidelines Reviewed: 2-code-design The code design of the PR was reviewed according to the maintainer guidelines Reviewed: 3-testing The PR was tested according to the maintainer guidelines Reviewed: 4-code-style The adherence to coding conventions by the PR were reviewed according to the maintainer guidelines Reviewed: 5-documentation The documentation details of the PR were reviewed according to the maintainer guidelines labels Oct 3, 2022
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.

ACK.
Code looks good, tested work on stm32f429i-disc1 and I trust @gschorcht testing on ESP32.

@dylad
Copy link
Member

dylad commented Oct 4, 2022

Here we go.

@dylad dylad merged commit 11aebb6 into RIOT-OS:master Oct 4, 2022
@gschorcht
Copy link
Contributor Author

@dylad Thanks for reviewing, testing and merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: boards Area: Board ports Area: build system Area: Build system Area: cpu Area: CPU/MCU ports Area: doc Area: Documentation Area: drivers Area: Device drivers Area: Kconfig Area: Kconfig integration Area: pkg Area: External package ports Area: sys Area: System Area: tests Area: tests and testing framework CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ARM Platform: This PR/issue effects ARM-based platforms Platform: ESP Platform: This PR/issue effects ESP-based platforms Reviewed: 1-fundamentals The fundamentals of the PR were reviewed according to the maintainer guidelines Reviewed: 2-code-design The code design of the PR was reviewed according to the maintainer guidelines Reviewed: 3-testing The PR was tested according to the maintainer guidelines Reviewed: 4-code-style The adherence to coding conventions by the PR were reviewed according to the maintainer guidelines Reviewed: 5-documentation The documentation details of the PR were reviewed according to the maintainer guidelines Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants