hathach / tinyusb

An open source cross-platform USB stack for embedded system
https://www.tinyusb.org
MIT License
4.89k stars 1.03k forks source link

STM32F0x2 Support #104

Closed cr1901 closed 5 years ago

cr1901 commented 5 years ago

Porting layer

Description I do not know when I'll get around to this, but I have an interest in using the crystal less USB feature of the STM32F0x2 family for future projects as, say, an cheap FPGA bootloader interface.

This is a Cortex-M0, and more importantly, the PHY provided is different from the Synopsys IP for other STM32 families. So no code duplication will be possible from STM32F4/F3/H7/etc. Thankfully, the PHY is also simpler and less featureful, so I think a port wouldn't take as long as it took me with the Synopsys PHYs.

pigrew commented 5 years ago

It looks like the STM32F070x6/B, STM32F0708, and STM32F048 are very similar (but some don't have the automatic clock adjustment). It'd be nice if the port would support the entire family.

(I've been doing development with the 070 nucleo board with the ST stack, but am evaluating if I want to switch to TinyUSB.)

For example, based on the device headers, the only difference between 070 and 072 regarding USB is:

#define RCC_CFGR3_USBSW_HSI48 (0x00000000U) /*!< HSI48 oscillator clock used as USB clock source */

cr1901 commented 5 years ago

@pigrew Well, the STM32 families using the Synopsys PHY are about to be abstracted into a single driver. In fact, the same code should be usable on RISC-V, ESP32, and other microcontroller families that elected to use the same Synopsys IP.

I don't see why the same can't be done with the homegrown (?) PHY used by other STM32s. But as of right now, I am unsure when I will be working on this as my "for fun" projects are all on the backburner.

pigrew commented 5 years ago

Thanks for your reply! If I make any progress towards porting, I'll post a note here (I have to wrap my head around the library architecture first). My medium-term goal is writing a USBTMC class driver, but I would need the HAL port first.

As a side note, the F070 board doesn't have a USB device connector. I cut a USB cable in half and crimped on a 0.100" pitch header to connect to the board's pins (GND, D+, D-). I couldn't get the DFU bootloader working, but running their CDC example is successful.

pigrew commented 5 years ago

I've started working on the code a little bit. I'll post my fork on github once I get EP0 up and running, but probably not make a pull request until I get some transfers going. I'm having trouble with the initialization methods for the endpoint states at the moment.... Also, the initialization done by HAL is a little bit different than what is described in the reference manual (e.g. adding time delays to let the hardware settle).

pigrew commented 5 years ago

Sheesh.... that was difficult to do without a proper logic analyzer. It took me the longest time to realize that adding printf to the code made it too slow to respond to the host, causing enumeration to fail.

There are also a bunch of features which I'm not planning to implement, like double-buffering or DMA (since I don't need high throughput). Also one can rearrange the priority of the endpoints, but I might just leave it to prioritize endpoints with lower IDs.

Anyway, EP0 is (mostly) working, though probably quite buggy. It lists the composite device properly in Windows, demonstrating that a control endpoint can work. I've been using a 'F070RB nucleo board, though my final target is the 'F042.

image

https://github.com/pigrew/tinyusb/tree/stm32f0

hathach commented 5 years ago

@pigrew superb !! That is a already a great progress getting passed the enumeration. Don't worry too much about advance features like double-buffering, just leave sufficient comment. We can always improve it later. I have an STM32F072 discovery board here, when you feel it is ready, please submit a PR, so that we can help to test and review it.

pigrew commented 5 years ago

@hathach

I'm confused about how to handle zero length/multiple packet transfers (assuming BULK for the moment). (My device is currently crashing in the CDC application when it receives a 64-byte transfer in the OUT direction). The Porting documentation says "TODO: who handles zero-length data packets?".

Bulk transfers seem to be working for single-data-packets at the moment... I also found a weird optimization bug which might have been in the ST HAL code I was working from (not too sure).

My current assumptions for OUT:

This leaves some questions about OUT:

And some for IN:

And one for CONTROL:

cr1901 commented 5 years ago

@pigrew FWIW, my Synopsys port relies on the upper layers handling zero-length packets and passing them down to the driver1. I've not run into problems yet.

  1. Aside from having to detect ZLPs, which my driver needs to know to stop the xfer.
hathach commented 5 years ago

The transfer complete function should be called when a packet of (length ==0 or MAX_PACKET_LEN) is received. At this point the endpoint should NAK any further transactions until the next time dcd_xfer(OUT) is called.

not exactly, device stack expect dcd to handle the whole transfer (by DMA or manually ISR trigger within dcd) and only call dcd xfer complete when the whole data is received e.g dcd_xfer(512) --> complete is only invoked when either 512 bytes is received or a short packet received.

To handle buffer when size > max packet size, for each a transaction complete (1 packet), you simply write/read data to/from the buffer provided by the dcd_edpt_xfer() then increase the buffer pointer by the amount of data received until all data is received or a short packet is received --> transfer complete.

For now you should not worry about zero length packet (ZLP), it is mostly used by control transfer for ACK phase

pigrew commented 5 years ago

Should we name the driver as "stm32_usba" or "stm32_fsdev" or something like that, as the driver should work for F0, some F1, F3, L0, L1 and maybe L4?

ST released a PDF describing the differences between the various USB hardware in their micros

(All of these appear to use very similar peripherals; we can use ifdef in the code where needed based on defines set in CMSIS.).

hathach commented 5 years ago

@pigrew yeah, exactly, there are probably only 2 or 3 USB IP are used for all the stm32 family. I think stm32_fsdev is better, we will also rename the current used by stm32f4 & h7 when we merged them together :)

pigrew commented 5 years ago

I've created pull request #123, but I'm sure that there are some infrastructure things I'm missing (I've not yet figure out how to run unit tests or created a board package.). I'll look at these things and update the pull request. I've been using Windows and am not sure how easy it will be for me to deal with them. Meanwhile, if there are any code comments, I'd appreciate them.

EDIT: Looks like I've fixed most of the build issues, but have not tested its build (only the builds I made through my IDE).

pigrew commented 5 years ago

@hathach or @cr1901 ,

Could we add a dcd method for invoking the USB interrupt handler? Or would suggest how to proceed with interrupts on the ST port?

On some STM32F3, the interrupt is shared by CAN and USB, so the USB stack can't directly define the interrupt handler since both the CAN and USB handlers must be called. My board_test() module is currently failing the CI build because it isn't including the tusb drivers. Perhaps you could look at the code and suggest a fix?

It'd probably involve changing all the existing drivers, but I think the bsp should define the interrupt handler and call the dcd handler as needed. Prehaps we should add "void tud_handle_irq(uint8_t port)" which would call the appropriate "void dcd_handle_interrupt(uint8_t port)"? The port is for devices whose driver would have multiple instances (like one for FS and another for HS).

Another note is that TI-RTOS will intercept all of the interrupts, and then re-dispatch them (drivers are not allowed to directly handle the interrupts). We should think about how that would be handled, too (especially as I see someone wants to work on a MSP430 port, which would be good to be compatible with TI-RTOS).

hathach commented 5 years ago

@pigrew yeah, this is a very good point, there will probably an dcd_irq_handler(rhport) to address this issue. However, since it is system-wide modification. It is better to have its own PR, I will need to run through other ports and re-test them all !!! Other repo such as Arduino usb library, circuipython will likely to be changed as well !

Therefore, for now, please just change it to match current format for your PR, and open an separate issue for this irq handler (pasting your above comment is sufficient enough).

hathach commented 5 years ago

should be implemented by #123