Author Topic: Anyone know how to write a basic USB stack?  (Read 11422 times)

0 Members and 1 Guest are viewing this topic.

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Anyone know how to write a basic USB stack?
« on: October 17, 2017, 12:34:38 pm »
The light switch boards arrived and I have assembled one. Now I need to get the USB of the STM32F042F4P6 up. Almost all material I read online points me at ST's firmware library. That library depends on either Cube or Std_Periph_Library, neither of which I feel comfortable touching with a ten-foot pole due to the overly complicated structure and the associated code bloat. This is a microcontroller with 16kB Flash and 6kB SRAM - bloat is the last thing I want to introduce.

So is there any guide on writing a simple USB stack from the ground up, directly operating on the registers? I am okay with being limited to one endpoint as that is all needed to implement a vendor-class device with WinUSB response headers, which would work anywhere with libusb.

This is also relevant when writing code for those 8-bit USB microcotnrollers, like ATmega16U2 or PIC16F1455.
« Last Edit: October 17, 2017, 12:36:09 pm by technix »
 

Offline xani

  • Frequent Contributor
  • **
  • Posts: 400
 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5317
  • Country: gb
Re: Anyone know how to write a basic USB stack?
« Reply #2 on: October 17, 2017, 01:25:42 pm »
You could take a look at how V-USB does it, it doesn't even need a USB peripheral, just GPIOs and some careful timing. It's limited to low speed devices though, which might or might not be a problem depending on your application.
 

Offline mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13726
  • Country: gb
    • Mike's Electric Stuff
Re: Anyone know how to write a basic USB stack?
« Reply #3 on: October 17, 2017, 01:56:53 pm »
You could take a look at how V-USB does it, it doesn't even need a USB peripheral, just GPIOs and some careful timing. It's limited to low speed devices though, which might or might not be a problem depending on your application.
If it has USB hardware, it make sense to use it. The problem is where the documentation of the product says little more than "Use our driver library" , or is inaccurate & issues only know internally by the people who did the library.
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Re: Anyone know how to write a basic USB stack?
« Reply #4 on: October 17, 2017, 03:04:22 pm »
You could take a look at how V-USB does it, it doesn't even need a USB peripheral, just GPIOs and some careful timing. It's limited to low speed devices though, which might or might not be a problem depending on your application.
If it has USB hardware, it make sense to use it. The problem is where the documentation of the product says little more than "Use our driver library" , or is inaccurate & issues only know internally by the people who did the library.
Even the library does NOT work: I decided to take a look at Cube's emitted code. The compiled library boilerplate (ST's USB library + Cube, its hard dependency) took 16,144 out of 16,384 available bytes of Flash memory with -Og optimization, 13,764 if optimized with -Os (breaking debugging.) So 240 bytes for the whole application?!? I am seriously wondering how did ST fit their DFU bootloader into the 13k mask ROM on the chip...

Currently my hand written code used 2,020 bytes. (No USB yet, not going to touch the bloatware known as Cube or ST's libraries any time soon.)
« Last Edit: October 17, 2017, 03:12:27 pm by technix »
 

Offline tszaboo

  • Super Contributor
  • ***
  • Posts: 7357
  • Country: nl
  • Current job: ATEX product design
Re: Anyone know how to write a basic USB stack?
« Reply #5 on: October 17, 2017, 03:41:44 pm »
Even the library does NOT work: I decided to take a look at Cube's emitted code. The compiled library boilerplate (ST's USB library + Cube, its hard dependency) took 16,144 out of 16,384 available bytes of Flash memory with -Og optimization, 13,764 if optimized with -Os (breaking debugging.) So 240 bytes for the whole application?!? I am seriously wondering how did ST fit their DFU bootloader into the 13k mask ROM on the chip...

Currently my hand written code used 2,020 bytes. (No USB yet, not going to touch the bloatware known as Cube or ST's libraries any time soon.)
Wow, that's gotta be a new awesome checkbox functionality. Yes it has USB. Yes the code uses 99% of the flash. So what? We said it has USB  :palm:
It also has a bunch of other peripherals. All of them on the same pins. Checkbox checked!
 

Offline __daz__

  • Newbie
  • Posts: 4
  • Country: it
Re: Anyone know how to write a basic USB stack?
« Reply #6 on: October 17, 2017, 03:48:20 pm »
I found this blog entry to be very useful for similar purposes I had in the past  http://andybrown.me.uk/2016/01/09/f042usbhid
« Last Edit: October 17, 2017, 03:54:08 pm by __daz__ »
 
The following users thanked this post: SparkMark

Online JPortici

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: Anyone know how to write a basic USB stack?
« Reply #7 on: October 17, 2017, 03:57:12 pm »
(^ Link is broken.. http://andybrown.me.uk/2016/01/09/f042usbhid/ )

I have the same complaint for microchip.
USB stack for PIC32MK is bigger than the boot flash area, how the * i'm supposed to write an usb bootloader using your tools? Of course i can't use your ready-made usb BL because there isn't one for MK in harmony 2.04 so i have to wait and hope for the new harmony release.. which will be when? who knows!
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Anyone know how to write a basic USB stack?
« Reply #8 on: October 17, 2017, 04:14:08 pm »
An improved version of my USB stack is available here https://github.com/ataradov/vcp . It takes < 4K, and works perfectly on a 16 K device (SAM D11).

And ig you want USB bootloader, then I've got one as well https://github.com/ataradov/bootloaders .
Alex
 

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Re: Anyone know how to write a basic USB stack?
« Reply #9 on: October 17, 2017, 05:36:32 pm »
Even the library does NOT work: I decided to take a look at Cube's emitted code. The compiled library boilerplate (ST's USB library + Cube, its hard dependency) took 16,144 out of 16,384 available bytes of Flash memory with -Og optimization, 13,764 if optimized with -Os (breaking debugging.) So 240 bytes for the whole application?!? I am seriously wondering how did ST fit their DFU bootloader into the 13k mask ROM on the chip...

Currently my hand written code used 2,020 bytes. (No USB yet, not going to touch the bloatware known as Cube or ST's libraries any time soon.)
Wow, that's gotta be a new awesome checkbox functionality. Yes it has USB. Yes the code uses 99% of the flash. So what? We said it has USB  :palm:
It also has a bunch of other peripherals. All of them on the same pins. Checkbox checked!
Umm what are you talking about?  :-\

I have enabled the following peripherals in Cube, all of which needed for my application:

* USB (duh)
* External crystal (dependency of USB)
* 2 PWM on TIM3 (to dim the light and the status LED)
* The USB HID Class driver
* Serial port (for debug messages)

When I tried removing the serial port driver (as if in the final product, where debug messages are no longer needed) and -Os optimization there is still 11,992 bytes of boilerplate.

Just for fun, enabling just the same set of peripherals as my own startup code, Cube emitted 3,596 bytes of code under -Os. While my own code emitted 2,020 bytes with -Og (a lot less optimization than -Os.) Speaking of bloat, that is 1.5k pure bloat introduced by the underwhelming architecture and WET code.
 

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Re: Anyone know how to write a basic USB stack?
« Reply #10 on: October 17, 2017, 05:50:05 pm »
An improved version of my USB stack is available here https://github.com/ataradov/vcp . It takes < 4K, and works perfectly on a 16 K device (SAM D11).

And ig you want USB bootloader, then I've got one as well https://github.com/ataradov/bootloaders .
What is the licensing on your code? Can I take some of your code and put it in my project, which is under a 3-clause BSD license?
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Anyone know how to write a basic USB stack?
« Reply #11 on: October 17, 2017, 05:53:11 pm »
What is the licensing on your code? Can I take some of your code and put it in my project, which is under a 3-clause BSD license?
It is all 3-BSD, feel free to do whatever you want to do with it. No attribution or acknowledgment is required.
Alex
 
The following users thanked this post: laneboysrc

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Re: Anyone know how to write a basic USB stack?
« Reply #12 on: October 17, 2017, 06:06:15 pm »
What is the licensing on your code? Can I take some of your code and put it in my project, which is under a 3-clause BSD license?
It is all 3-BSD, feel free to do whatever you want to do with it. No attribution or acknowledgment is required.
Thanks. I will try to fit your code (maybe not the VCP part - just the enumeration part as I intend to end up using libusb for my project) onto STM32F042.
 

Offline IconicPCB

  • Super Contributor
  • ***
  • Posts: 1534
  • Country: au
Re: Anyone know how to write a basic USB stack?
« Reply #13 on: October 17, 2017, 07:33:07 pm »
 

Offline funkathustra

  • Regular Contributor
  • *
  • Posts: 150
  • Country: us
Re: Anyone know how to write a basic USB stack?
« Reply #14 on: October 17, 2017, 08:17:54 pm »
Even the library does NOT work: I decided to take a look at Cube's emitted code. The compiled library boilerplate (ST's USB library + Cube, its hard dependency) took 16,144 out of 16,384 available bytes of Flash memory with -Og optimization, 13,764 if optimized with -Os (breaking debugging.) [...]
I have enabled the following peripherals in Cube, all of which needed for my application:

* USB (duh)
* External crystal (dependency of USB)
* 2 PWM on TIM3 (to dim the light and the status LED)
* The USB HID Class driver
* Serial port (for debug messages)


For what it's worth, when I enable LTO, I get a slightly-lower 15116-byte flash file with these peripherals enabled. 1300 bytes of flash is plenty of space to implement an RGB LED thing. You can do it with, like, five lines of code.

Removing the serial port gets you down to 13944. -Os gets you wayyy down to 7880 bytes. That's *plenty* of flash for any USB FS HID application I've ever heard of.

I think you're missing the point. The 16 KB (F4) version of the '042 is what you deploy in production (-Os) to save a few cents --- but you'd never develop on them. You develop on the F6 version, which has a much-roomier 32 KB of flash.

Why on earth would you write a USB stack from scratch? If your time is really that worthless, please let me know and I'll send you some contract work I need done  ;D

I think you need to adjust your code size expectations to the platform you're on. If you were on an 8-bit part, 16 KB of flash is plenty for USB (even 8 KB works fine). But on a 32-bit ARM part — even in Thumb mode — that flash gets eaten up pretty quickly (thanks, RISC... ugh).

An improved version of my USB stack is available here https://github.com/ataradov/vcp . It takes < 4K, and works perfectly on a 16 K device (SAM D11).

technix is using HID, not VCP (who uses VCP for anything other than legacy products?)
« Last Edit: October 17, 2017, 08:19:42 pm by funkathustra »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11234
  • Country: us
    • Personal site
Re: Anyone know how to write a basic USB stack?
« Reply #15 on: October 17, 2017, 08:22:35 pm »
Why on earth would you write a USB stack from scratch? If your time is really that worthless, please let me know and I'll send you some contract work I need done  ;D
It is not that hard. It actually saves time in a long run.

technix is using HID, not VCP (who uses VCP for anything other than legacy products?)
That's why I also gave a link to HID bootloader. HID is just raw endpoints, it is way easier and simpler than VCP.
Alex
 

Offline funkathustra

  • Regular Contributor
  • *
  • Posts: 150
  • Country: us
Re: Anyone know how to write a basic USB stack?
« Reply #16 on: October 17, 2017, 09:30:30 pm »
Why on earth would you write a USB stack from scratch?
It is not that hard. It actually saves time in a long run.
I'm not saying it's hard — just that it takes time, and seems redundant. And, if you look through the ST USB stack, I don't see a lot of room for shrinking it in size. It's only got three source files, none of them more than 500 lines long (and 50% of that is Doxygen).

And: how does it save time in the long run?

I've regularly done USB projects for at least 8 years — with Microchip, Freescale, Silicon Labs, and ST stacks — and I've never had any issues nor reasons to build a stack from scratch. I've definitely had to get in there and modify the vendor stack to do different things, but that's a far cry from reinventing the wheel.

I found a minor bug once in the SiLabs stack, sent them a message with the fix, and they patched it in the next release — along with patches for all sorts of other bugs that cover edge cases that I could never thoroughly test myself.

That's why I also gave a link to HID bootloader. HID is just raw endpoints, it is way easier and simpler than VCP.
Didn't notice anything about HID. Comment retracted! And yes, HID and Vendor-class devices are super lightweight.
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3138
  • Country: ca
Re: Anyone know how to write a basic USB stack?
« Reply #17 on: October 18, 2017, 12:19:40 am »
I'm not saying it's hard — just that it takes time, and seems redundant.

IMHO, it's the best way to learn how USB works.
 

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Re: Anyone know how to write a basic USB stack?
« Reply #18 on: October 18, 2017, 03:58:18 am »
Why on earth would you write a USB stack from scratch?
It is not that hard. It actually saves time in a long run.
I'm not saying it's hard — just that it takes time, and seems redundant. And, if you look through the ST USB stack, I don't see a lot of room for shrinking it in size. It's only got three source files, none of them more than 500 lines long (and 50% of that is Doxygen).

And: how does it save time in the long run?

I've regularly done USB projects for at least 8 years — with Microchip, Freescale, Silicon Labs, and ST stacks — and I've never had any issues nor reasons to build a stack from scratch. I've definitely had to get in there and modify the vendor stack to do different things, but that's a far cry from reinventing the wheel.

I found a minor bug once in the SiLabs stack, sent them a message with the fix, and they patched it in the next release — along with patches for all sorts of other bugs that cover edge cases that I could never thoroughly test myself.

That's why I also gave a link to HID bootloader. HID is just raw endpoints, it is way easier and simpler than VCP.
Didn't notice anything about HID. Comment retracted! And yes, HID and Vendor-class devices are super lightweight.
ST's USB stack itself may be small, its dependency sure isn't. The serial port driver should not take a lot of kB. The blank startup code should be a kB or two smaller. Cube is the center of bloat here, and if I am using ST's libraries I cannot get rid of it.
 

Offline krho

  • Regular Contributor
  • *
  • Posts: 223
  • Country: si
Re: Anyone know how to write a basic USB stack?
« Reply #19 on: October 18, 2017, 05:28:37 am »
@technix:

I don't know if there is low-level driver for f0, but if it is, try checking that option in cubeMX, this should shrink things.
The other thing as mentioned in this thread use LTO, it should throw out a lot of code even with Og.
 

Offline mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13726
  • Country: gb
    • Mike's Electric Stuff
Re: Anyone know how to write a basic USB stack?
« Reply #20 on: October 18, 2017, 07:40:59 am »
Why on earth would you write a USB stack from scratch?
It is not that hard. It actually saves time in a long run.
I'm not saying it's hard — just that it takes time, and seems redundant. And, if you look through the ST USB stack, I don't see a lot of room for shrinking it in size. It's only got three source files, none of them more than 500 lines long (and 50% of that is Doxygen).

And: how does it save time in the long run?

I've regularly done USB projects for at least 8 years — with Microchip, Freescale, Silicon Labs, and ST stacks — and I've never had any issues nor reasons to build a stack from scratch. I've definitely had to get in there and modify the vendor stack to do different things, but that's a far cry from reinventing the wheel.

I found a minor bug once in the SiLabs stack, sent them a message with the fix, and they patched it in the next release — along with patches for all sorts of other bugs that cover edge cases that I could never thoroughly test myself.

That's why I also gave a link to HID bootloader. HID is just raw endpoints, it is way easier and simpler than VCP.
Didn't notice anything about HID. Comment retracted! And yes, HID and Vendor-class devices are super lightweight.
ST's USB stack itself may be small, its dependency sure isn't. The serial port driver should not take a lot of kB. The blank startup code should be a kB or two smaller. Cube is the center of bloat here, and if I am using ST's libraries I cannot get rid of it.
If any serial port driver takes more than 1K it needs to be taken out the back and shot. Ditto startup code.
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Re: Anyone know how to write a basic USB stack?
« Reply #21 on: October 18, 2017, 11:13:10 am »
@technix:

I don't know if there is low-level driver for f0, but if it is, try checking that option in cubeMX, this should shrink things.
The other thing as mentioned in this thread use LTO, it should throw out a lot of code even with Og.
There isn't a LL driver for F0. As of LTO it somehow does not play nice with the copy of newlib ARM shipped. Speaking of, my code contains a good portion of linker script magic, which is not compatible with LTO.
 

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Re: Anyone know how to write a basic USB stack?
« Reply #22 on: October 18, 2017, 03:57:35 pm »
Why on earth would you write a USB stack from scratch?
It is not that hard. It actually saves time in a long run.
I'm not saying it's hard — just that it takes time, and seems redundant. And, if you look through the ST USB stack, I don't see a lot of room for shrinking it in size. It's only got three source files, none of them more than 500 lines long (and 50% of that is Doxygen).

And: how does it save time in the long run?

I've regularly done USB projects for at least 8 years — with Microchip, Freescale, Silicon Labs, and ST stacks — and I've never had any issues nor reasons to build a stack from scratch. I've definitely had to get in there and modify the vendor stack to do different things, but that's a far cry from reinventing the wheel.

I found a minor bug once in the SiLabs stack, sent them a message with the fix, and they patched it in the next release — along with patches for all sorts of other bugs that cover edge cases that I could never thoroughly test myself.

That's why I also gave a link to HID bootloader. HID is just raw endpoints, it is way easier and simpler than VCP.
Didn't notice anything about HID. Comment retracted! And yes, HID and Vendor-class devices are super lightweight.
ST's USB stack itself may be small, its dependency sure isn't. The serial port driver should not take a lot of kB. The blank startup code should be a kB or two smaller. Cube is the center of bloat here, and if I am using ST's libraries I cannot get rid of it.
If any serial port driver takes more than 1K it needs to be taken out the back and shot. Ditto startup code.
My own startup code takes about 500 bytes if bypassing newlib's _start. Calling _start (to properly initialize the C and C++ runtime) the code grew to 1.5k though.
 

Offline technixTopic starter

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Re: Anyone know how to write a basic USB stack?
« Reply #23 on: October 18, 2017, 04:00:50 pm »
If your time is really that worthless, please let me know and I'll send you some contract work I need done  ;D
Please let me know if you have any. Be aware that my time will be costly.

I am forced to write my own USB stack because of the sheer bloat of ST's libraries. 99% of the flash for just the boilerplate... You got to be kidding me.
 

Offline mark03

  • Frequent Contributor
  • **
  • Posts: 711
  • Country: us
Re: Anyone know how to write a basic USB stack?
« Reply #24 on: October 18, 2017, 04:27:04 pm »
I don't know if there is low-level driver for f0, but if it is, try checking that option in cubeMX, this should shrink things.

At the last place I worked, we were implementing a suite of STM32 drivers for an IoT reference design.  The client insisted that we build it on top of the ST LL drivers.  I could not see the point of this.  As far as I could tell, the LL "drivers" are nothing more than a thin obfuscation layer on top of the register interface.  Instead of writing a register directly, you call an LL function which...  writes a register.  Adding code layers is no benefit unless you are abstracting away some details, or encapsulating complexity somehow.  AFAICT the LL drivers do neither.

I haven't tried it out yet, but here's an independent USB driver which looks interesting:

Lightweight USB Device Stack
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf