[HN Gopher] Making USB devices - end to end guide to your first ...
       ___________________________________________________________________
        
       Making USB devices - end to end guide to your first gadget
        
       Author : todsacerdoti
       Score  : 350 points
       Date   : 2024-06-03 07:53 UTC (15 hours ago)
        
 (HTM) web link (popovicu.com)
 (TXT) w3m dump (popovicu.com)
        
       | foz wrote:
       | A very nice writeup and intro into USB, although - it's very
       | focused on using an ST microcontroller, which is a lot more steps
       | and toolchains compared the the recent ESP32 ecosystem that
       | offers a number of easy plug-and-play ways to make USB devices
       | work (for example, several projects from Adafruit's learning
       | pages provide basic use cases). Another issue is differential
       | pairs - having designed several working USB boards myself, this
       | has not a concern for beginners, mainly relevant for doing high-
       | speed work. USB controller ICs (as used typically with
       | arduio/esp) can handle a lot of the details for you, so doing the
       | calculations seems overkill, especially for someone making their
       | first gadget.
        
         | lemonlime0x3C33 wrote:
         | I think it is nice to have a basic understanding of
         | differential pairs and impedance, I will admit I never really
         | had to do the calculations since the ecad software I use has
         | several tools for routing differential pairs and even analyzing
         | signals for impedance. But as long as you keep your traces
         | really short it normally doesn't matter.
        
         | vgalin wrote:
         | I recently built a small hand-wired macro pad using an Arduino
         | Pro Micro equipped with ATmega32U4, it's apparently quite
         | popular amongst hobbyists building custom keyboards. Quick and
         | fun project for a beginner, the most tedious part of this
         | project was to carve the wooden case.
        
         | fulladder wrote:
         | > USB controller ICs (as used typically with arduio/esp) can
         | handle a lot of the details for you
         | 
         | Can anyone recommend any good USB controller ICs? I normally
         | just use a microcontroller with USB built in.
        
           | lemonlime0x3C33 wrote:
           | I have had a good experience using microchips USB2514 and
           | USB2512
        
             | stragies wrote:
             | I just looked up the USB2514, and it would seem to not
             | support PerPortPowerSwitching. (used by e.g. uhubctrl to
             | toggle/switch power to individual USB ports). Am I not
             | reading the specs correctly?
        
               | lemonlime0x3C33 wrote:
               | I was able to reset downstream USB devices using usbreset
               | to the individual ports (or the entire hub) in my design,
               | using usbreset. I did also have a hardware reset built in
               | using the cfg_sel0 and cfg_sel1 pins 24 & 25 and RESET_N.
               | I did not try to turn off power to those ports for any
               | extended time so I am not sure if that works.
        
       | arrw wrote:
       | Very cool guide.
       | 
       | But if you are worried about soldering more fiddly stuff like
       | those ARM processors: It doesn't have to be that big, STM32 is
       | nice if you need the power, but for smaller stuff smaller
       | controllers can be preferrable.
       | 
       | E.g. one may also consider using VUSB, which is a library that
       | bit-bangs USB on small Atmel microcontrollers:
       | https://www.obdev.at/products/vusb/index.html Example board
       | schematic we've used to teach students Linux kernel module
       | programming: https://gitlab.cs.fau.de/i4/passt/passtboard-v2 with
       | firmware http://www.poempelfox.de/ds1820tousb/ and
       | https://gitlab.cs.fau.de/i4/passt/ds1820tousb
       | 
       | Also very easy, if you are inclined towards Arduino style
       | programming there are tons of boards you can just use as USB
       | devices with the included libraries in very few lines of code,
       | for example https://www.az-delivery.de/en/products/digispark-
       | board
        
         | unwind wrote:
         | There's also things like the CH32V203 [1] which is a TSSOP-20
         | with hardware USB and costs around $0.81 in singles. The
         | software side might be a little more ... challenging, though.
         | 
         | https://www.wch-ic.com/products/CH32V203.html?
        
           | 15155 wrote:
           | CH32F series is more or less the same and actually has
           | CoreSight SWD and clone STM peripherals
        
           | zoobab wrote:
           | Software USB can also be done on the 10 cents CH32V003:
           | 
           | https://github.com/cnlohr/rv003usb
        
         | michaelt wrote:
         | _> if you are worried about soldering more fiddly stuff like
         | those ARM processors_
         | 
         | If soldering's a worry, you can get quite reasonably priced dev
         | boards with the microcontroller USB port already fitted and
         | working - such as the NUCLEO-F429ZI
         | https://www.st.com/en/evaluation-tools/nucleo-f429zi.html
         | 
         | Very similar to the NUCLEO-F103RB board the post author used,
         | but as well as the USB connector at the top of the board for
         | the built in programmer/debugger, it also has one at the bottom
         | of the board, wired straight to the microcontroller.
         | 
         | You can also download the board's schematics, if you want to
         | copy their choice of ESD protection and suchlike.
        
       | lemonlime0x3C33 wrote:
       | This is a very well written and informative article for working
       | with USB, wish I had it when I first started USB signals.
        
       | dvh wrote:
       | I recently used CH340N (soic 8 virtual com port) and it was
       | really easy. Easy soldering, no extra parts just directly connect
       | to USB, works out of the box on Linux.
        
       | anymouse123456 wrote:
       | Friendly reminder that USB is not free.
       | 
       | You must pay a one-time fee of $6,000 in exchange Vendor ID [0].
       | 
       | [0] https://www.usb.org/getting-vendor-id
        
         | zoobab wrote:
         | See also https://pid.codes/
         | 
         | For the DirtyJTAG project we use one of those:
         | 
         | https://pid.codes/1209/C0CA/
        
         | pjc50 wrote:
         | .. or use someone else's. I believe there's a hobbyist VID
         | under which you can reserve PIDs, or in many cases you can just
         | copy an existing product if your device is generic enough and
         | you're not planning to sell a big production run.
        
           | hananova wrote:
           | There's pid.codes which uses a vid of a defunct organization,
           | but before that there was also the F055 vid. I still use that
           | vid because no company will accept that vid, since it's
           | commonly used by foss projects.
        
         | michaelt wrote:
         | Many chip vendors will give you a PID under their VID if you're
         | making a product. For example this blog post uses and ST chip,
         | and they'll provide a PID if you request it [1] - free of
         | charge, but subject to some conditions.
         | 
         | (Of course if your USB device needs Windows drivers, you'll
         | still have to deal with things like code signing...)
         | 
         | [1] https://community.st.com/t5/stm32-mcus-embedded-
         | software/dea...
        
         | brezelgoring wrote:
         | Wow, first time I hear about it, this is an eye opening
         | experience.
         | 
         | I will think twice now before saying "why couldn't they just
         | use USB for this?"
        
           | kraskoss wrote:
           | Even crazier, it's just a 16 bit value.
           | 
           | What are they gonna do when they run out?
        
           | yjftsjthsd-h wrote:
           | > I will think twice now before saying "why couldn't they
           | just use USB for this?"
           | 
           | I dunno, I think either you're doing a small run and you can
           | just bake in a Teensy or whatever, or you're doing a big run
           | and $6k is a drop in the bucket.
        
         | rm445 wrote:
         | Yeah, I was going to ask about this. I think ST Micro will
         | sublicense you a PID under their VID, but with restrictions,
         | and companies attempting to buy a VID and sell PIDs as a
         | service have been sued?
        
         | Karliss wrote:
         | The part that makes me feel most uncomfortable about usb
         | VID/PIDs is that they are only 16bits each. While I don't think
         | 4billion unique commercial USB devices is limit we will reach
         | anytime soon, efficiently managing the available address space
         | is a different question. And unlike IPv4 addresses a range of
         | USB VID/PIDs can't be as easily reused without making the
         | VID/PID meaningless.
        
           | crote wrote:
           | By that time they'll just add an extra field to the protocol
           | and assign a special "see other field" VID/PID pair.
           | 
           | For a lot of products the VID/PID combo isn't _that_
           | important on a protocol level, and there 's technically no
           | reason why two completely unrelated products couldn't be
           | using the same pair. In practice you're mainly going to use
           | them for software to target a _specific_ device, for example
           | the Linux HID driver uses it to work around hardware
           | /firmware bugs. But HID devices are self-describing, and
           | that's the main mechanism used by the driver to figure out
           | what has been attached and how to behave.
           | 
           | If modern OSes can do the same to distinguish hardware with
           | the extra field, sharing the same value for backwards
           | compatibility with legacy machines really isn't going to be a
           | big deal. It's not like MAC or IPv4 addresses where a clash
           | will essentially kill all communication.
        
         | crote wrote:
         | For hobbyist use you can just pick a random value and it'll
         | _usually_ work. Open-source hardware can get a product ID for
         | free from https://pid.codes. Small-run commercial hardware can
         | usually get a free product ID from the maker of their USB-
         | capable chip. And once you're big enough that you're designing
         | your own chip, $6,000 isn't such a big deal anymore.
         | 
         | So yes, you are _technically_ right, but it really doesn 't
         | matter all that much in practice. USB is by far one of the most
         | accessible major hardware standards out there.
        
         | andoma wrote:
         | FWIW, for my own personal projects I resort to vendor id 6666
         | (Prototype).
        
         | teddyh wrote:
         | I've commonly seen OpenMoko's ID, 1d50, used for free projects.
         | See the list at <http://www.linux-usb.org/usb.ids>.
        
         | hananova wrote:
         | I just use 0xF055 as VID. What is the USB-IF gonna do?
        
         | nudgeee wrote:
         | NXP runs a USB VID/PID Program [0] for small production designs
         | (<10,000 units) that use their MCUs. They'll give you 3 PIDs
         | for free under one of their VIDs. I use this in my side
         | projects (~200 units) and works pretty well!
         | 
         | [0] https://community.nxp.com/t5/Kinetis-Microcontrollers/NXP-
         | US...
        
         | CamperBob2 wrote:
         | Easy way around that is to license your PID(s) from MCS
         | Electronics. They bought a VID before the USB-IF got around to
         | prohibiting resale of PIDs.
        
       | kevmo314 wrote:
       | Are there any development boards with USB 3 support? I'm trying
       | to prototype a USB C monitor sink but having trouble finding a
       | board that has the power necessary to receive DisplayPort over
       | USB.
        
         | dfox wrote:
         | There is this:
         | https://octopart.com/cyusb3kit-003-cypress+semiconductor-494...
         | and the pricing seems reasonable. When I looked for something
         | like that two years ago the prices were order of magnitude
         | higher.
        
           | BertoldVdb wrote:
           | This device is not really suited, it is a high speed USB3.0
           | peripheral. You might be able to use it with the right
           | software, but then you are just using the CPU in it.
        
             | dfox wrote:
             | The way how the Cypress FX series works (and for that
             | matter majority of non-trivial USB-to-something chips do)
             | is that there is a bunch of DMA-capable peripherals inside
             | and the in fact ridiculously underpowered CPU core inside
             | only sets up the required configuration for the DMA
             | transactions to happen.
        
         | BertoldVdb wrote:
         | There is not much power needed to receive DisplayPort over USB
         | (assuming you already can receive displayport signals or just
         | route them to an external monitor).
         | 
         | You just need to implement an USB billboard device (optional to
         | make it work, but required by the spec IIRC) and signal the
         | correct alternate function. Then DisplayPort signalling will be
         | present on the USB-C plug. Then just connect the right AUX
         | wires to the DisplayPort connector.
        
         | 15155 wrote:
         | Most FPGAs with transceivers can do it.
        
           | kevmo314 wrote:
           | Do you have an example? Looking for a product recommendation
           | others have good experience with
        
             | 15155 wrote:
             | https://github.com/enjoy-digital/usb3_pipe
             | 
             | I don't know that there are any fully-baked solutions for
             | it though, but it's definitely doable in-FPGA with some
             | effort.
        
       | perbu wrote:
       | fwiw; I've prototyped some USB gadgets using Raspberry Pi Zeroes
       | and Composite USB in the Linux Kernel. At least storage and
       | serial devices were pretty easy to get going.
       | 
       | You'll need something like a shell script on the Raspberry to
       | initialize the composite kernel module and you'll find the
       | boildplate in the kernel docs.
        
       | the__alchemist wrote:
       | A note on USB-C, to augment the article's note: Wire the CC pins
       | to appropriate resistors, or it probably won't work!
       | 
       | And a note on the differential routing and impedance: For USB
       | 2.0, it's not a big deal. Keep the traces of similar length, and
       | reasonably direct. Probably next to each other. You probably
       | don't need to worry about fine-tuning the length and trace
       | widths, impedance control, RF best practices etc. Just connect
       | the nets.
        
         | jmole wrote:
         | 480MBit/s is fast enough that you do need to worry about best
         | practices and impedance matching within 10% or so. Many MCUs
         | will also need series resistors between the USB PHY pins and
         | the connector.
         | 
         | Will you need to respin a board because you needed to use a 20
         | mil trace instead of 24 mil? Probably not. All things
         | considered, laying out a USB 2.0 differential pair is pretty
         | low stakes. But you should still try and do it right - it's
         | good practice.
        
       | dnpls wrote:
       | what about converting existing devices from USB-A to USB-C? I
       | have a bunch of powerbanks lying around that I'd love to keep
       | using but most of my devices now use a USB-C charging cable,
       | would it be a simple case of replacing the ports and re-soldering
       | or is there any extra component I need to add?
        
         | the__alchemist wrote:
         | I would use an adapter for that use case.
         | 
         | The wiring of the ports on a new design is straightforward; you
         | are using the same pins if it's USB 2.0 (As the article says),
         | plus two extra connections that go to a resistors. If you can
         | find ports that use the same footprint, feasible, but probably
         | not worth it. Desoldering a port is a pain because you have to
         | get all the pins to melting temperature concurrently, and you'd
         | have to figure out how to wire those CC pins.
        
       | the__alchemist wrote:
       | OK, dumb question, but since we're talking USB on STM32: Does
       | anyone know how to support receiving more than 64 bytes in a
       | frame? I've been looping over 64 byte frames in software, but I
       | know it's possible to go higher. (Up to 1Mbyte I think). The
       | problem is, the Reference Manual lists settings for this that are
       | not normal registers. They are a pseudo-register of some sort.
       | Wondering if there is an easy workaround for this! (The non-OTG
       | USB peripheral)
        
         | genter wrote:
         | USB full speed bulk transfer is limited to 64 bytes. (Dunno
         | which stm32 you're talking about, but stm32g4 is only full
         | speed.)
        
           | jmole wrote:
           | A single BULK USB endpoint can only support 64 bytes per
           | transfer. You could make use of multiple endpoints (8 are
           | available in total) or switch to isochronous endpoints which
           | can support up to 1023 bytes per frame.
           | 
           | Most hardware support for isochronous transfers requires DMA
           | on the MCU side, so it tends to be a pain unless your vendor
           | has a library that handles it for you.
           | 
           | You can in general send up to 19 bulk transfers in a single
           | frame (even on a single endpoint), but again, vendor
           | libraries differ wildly in their support for this.
        
             | AdamH12113 wrote:
             | Note that isochronous transfers require kernel-mode drivers
             | on the host side, so you won't be able to use libusb in
             | that case. Bulk transfers are the way to go if you want
             | high throughput.
        
               | the__alchemist wrote:
               | Isn't the restriction just on the reception side? So, if
               | you have a MCU talking to a PC or another MCU, you can
               | _send_ however many bytes you want, but not receive? I
               | say this because A: The Reference Manual only indicates
               | this limit for reception, and B: I only experienced this
               | on reception: PCs seem capable of sending and receiving
               | messages larger than 64-bytes, and STM32s seem capable of
               | sending messages larger than 64-bytes, but not receiving
               | (without isosynchronous, or anything special)
        
               | AdamH12113 wrote:
               | The limits on packet size are based on the transfer type
               | (control, interrupt, isochronous, or bulk) and whether
               | the connection is low speed (1.5 Mbps), full speed (12
               | Mbps) or high speed (480 Mbps). The USB module on the MCU
               | will be designed for the largest possible packet, which
               | IIRC is a full-speed 1023-byte isochronous packet. (MCUs
               | usually aren't fast enough to reach high speed.)
               | 
               | Data larger than one packet can be sent as a multi-packet
               | "transfer". This is where bulk transfers get their
               | throughput -- at full speed, the largest bulk packet is
               | only 64 bytes, but you can send 19 bulk packets per
               | 1-millisecond frame, which gives 1216 bytes/millisecond,
               | more than the 1023 bytes/millisecond possible with
               | isochronous.
               | 
               | You might be able to force the hardware to send
               | nonstandard packets, but then it's not really USB any
               | more.
        
               | the__alchemist wrote:
               | I appreciate the insight! That makes sense in context.
        
           | the__alchemist wrote:
           | G4 indeed! I think something in the RM implied it could go
           | higher, but I had trouble interpreting it. Thanks for the
           | explanation.
        
       | petabyt wrote:
       | I've been using https://github.com/xairy/raw-gadget to create a
       | virtual USB device on my raspberry pi I've got plugged into my
       | PC. I'm currently using It to emulate a MTP camera so I can spoof
       | some proprietary software.
        
         | worthless-trash wrote:
         | You gotta give us more details than that! Sounds like fun!
        
       | _spduchamp wrote:
       | I use ESP32 mostly but I have a cheap hack that fits a lot of
       | projects...
       | 
       | For super quick easy custom controllers, also consider pulling
       | the control board from discarded USB keyboards. Use conductive
       | glue instead of solder to attach wires to the contacts, and a
       | helping of hot glue to keep them secured. I've made cheap but
       | very robust 1-button game controllers with an arcade button that
       | sends a space bar click. You get all the debounce etc, no code.
        
       | mcshicks wrote:
       | I used to test devices for USB compliance a long time ago. One of
       | the things I often saw problems with was the inrush current test.
       | Basically too much bypass caps on the 5v. I didn't see it
       | mentioned in the article. It's really easy to get focused on the
       | high speed digital design but for compliance it's sometimes the
       | less sexy stuff that gets you. No idea how this stuff works with
       | newer versions of the standard but it seems like there still is a
       | test. Nice article though.
       | 
       | https://compliance.usb.org/index.asp?UpdateFile=Electrical#:....
        
         | amelius wrote:
         | What devices do people use to limit inrush current? You can
         | make a current limiter with a few transistors, but I'm guessing
         | there must be better integrated solutions (e.g. with
         | temperature protection, etc.)
        
           | mcshicks wrote:
           | You can use inductors. Some USB cables have a choke on them.
           | But basically the problem is when a large amount of circuitry
           | all powers up at one when you plug in. So everything
           | connected directly to USB 5v with a lot of large capacitors
           | to filter the power. If you really need that then you can
           | self power and avoid the problem.
        
       | AdamH12113 wrote:
       | Ive written bare-metal USB code on an MCU before, and I found it
       | to be quite a shock compared to simple digital protocols like SPI
       | or I2C. The physical and data link layers aren't much more
       | complicated than, say, CAN, but beyond that you immediately run
       | into a brick wall of descriptors, endpoints, and driver
       | configuration. USB was designed from the ground up to be a plug-
       | and-play ecosystem for PCs, and it really shows. Using the
       | vendor-provided software as much as possible is definitely the
       | way to go if you can.
       | 
       | Some half-remembered hints: You want bulk transfers for high
       | throughput (don't even look at isochronous). USB is a
       | master/slave protocol so if you're not getting peak throughput
       | it's usually due to something on the host (PC) side. If the
       | license (LGPL) is compatible with your needs, libusb is pretty
       | easy to use. If you're not using the vendor driver, a hardware
       | USB protocol analyzer is _really_ helpful. USB in a NutShell[1]
       | is a decent web reference for understanding the protocol.
       | 
       | [1] https://www.beyondlogic.org/usbnutshell/usb1.shtml
        
       ___________________________________________________________________
       (page generated 2024-06-03 23:01 UTC)