0
\$\begingroup\$

I want to design a prioritized reverse USB hub, where a USB flash drive is connected by default to a device but switches to another when a connection is present.

The setup of my product uses a Raspberry Pi and a USB flash drive inside a box. On the outside of the box I have 2 USB ports, one for power and the other for data, neither of them directly connect to the Raspberry.

By default, the USB flash drive is connected to the Raspberry, but I when I connect a USB cable to the data port of the box, the Raspberry notices it and switches the USB flash drive from it to the USB data port of the box. When I remove the cable, the Raspberry switches again the USB flash drive to one of its internal USB ports.

The schematic for this is the following:

automatic USB switch

So, I read here in stack exchange that the 4 USB pins must be switched and not only the D+ and D- pins. These are switched via a FSUSB30 USB switch IC, on the top of the schematic. By default, even if USB_SEL is a high impedance, the switch connects the D+D- pins of USB_PEN_DATA (Flash drive) to the D+D- pins of USB_INT_DATA (RPi USB).

For the power side (this is where I have my doupts), I use a two MOSFET IC to switch GROUNDS. Basically, I read that two computers may have slightly different 5V between the VCC and GND of its USBs, so two USB ports of different POWERED devices should not be connected together. Ok, so I just connected the positive terminals in a "VCC_USB_COMMON" net, and I switch the ground of the USB flash drive "MAGIC_USB_GROUND" to the RPi ground "GND" or to the computer ground "PE".

The grounds of the computer and the RPi are isolated through the use of a schmitt trigger output optocoupler that drives the MOSFET that switches the computer side PE ground. On the RPi side, the ground is switched directly with RPI_GPIO_PIN_OUT_X.

Finally, for the RPi to know if a USB cable is connected to the external data port, I've put a second optocoupler that has the IR LED powered by the computer and the schmitt trigger powered by the Raspberry and its output is read by an IO pin "RPI_GPIO_PIN_IN_X".

This all seems like overenginnering, but I think it gives me perfect controll over the timings of the switching of data and power lines. Somewhere I also read that the order mattered.

Is this circuit sound? I didn't check for the typical resistor values yet, I just put something that I thought would work as a ballpark value, but I will check that in detail if this circuit can do what I want. Also, decoupling caps aren't present but they will be on the final design. Are ferrite beads REALLY necessary? I'm only going to require USB2.0 at 480Mbps so...

EDIT: Ok, if I understood correctly from Ali Chen's answer, I am overthinking things and only D+ and D- should be switched. The updated circuit is as follows:

enter image description here

\$\endgroup\$
  • \$\begingroup\$ How are you powering the Pi when it is not plugged into the computer? \$\endgroup\$ – Bruce Abbott Sep 11 '17 at 15:52
  • \$\begingroup\$ Batteries connected to the GPIO, with the appropriate protection and charging circuit of corse. \$\endgroup\$ – rmarques Sep 11 '17 at 16:33
  • \$\begingroup\$ Is this circuit sound? No, it is unnecessary complicated, and quite wrong with regard of ground switching. See correct answer below. \$\endgroup\$ – Ale..chenski Sep 11 '17 at 18:49
  • \$\begingroup\$ I've implemented your suggestions, I figured this would be the correct way of doing this, but I read somewhere that power should also be switched. Now that I think about it... D+ and D- are differential pairs, the only reason power should be switched should be to "reset" the flash drive, but from your answer, even that is not necessary, or at least could be done using software... \$\endgroup\$ – rmarques Sep 11 '17 at 19:03
  • \$\begingroup\$ You might need to use a voltage divider before RPI_GPIO, to align +5V level with RPI 3.3V level, something like 10k/22k. Also, the CVV on USB_EXT_DATA should have about 1uF ceramic cap, to avoid possible flyback voltages upon cable disconnect if long cables are used. \$\endgroup\$ – Ale..chenski Sep 11 '17 at 19:09
2
\$\begingroup\$

This is a pretty standard idea to switch a device between two USB hosts. The implementation however is unnecessary convoluted.

As I understand, the Pi and Flash drive are contained in one box. In this application both Pi (inside the "box") and external cable are USB hosts. The flash drive needs to be switched between them.

The solution is simple, you need to start with upper part of your schematics (FSUSB30 switch and three USB connectors), but throw the bottom away, completely. Some fundamental modifications need to be made for ground and power.

First, all grounds MUST BE CONNECTED at all times, it is a very poor idea to have them switched. No "magic ground", ever.

Second, the VBUS to "USB_PEN_DATA" port can be permanently connected to +5V from box power, for simplicity.

The USB_INT_DATA can be wired permanently to Pi data port, and VBUS ("VCC") from Pi side (USB_INT_DATA) must be disconnected from VCC_USB_COMMON. There should no "common VCC_USB" because the VCC from USB_EXT_DATA port will conflict with internal +5V power rail.

The switch should be controlled by VCC that will come (or will not come) from the "USB_EXT_DATA" port in the following way:

  1. when the "external" cable is not plugged, VCC on USB_EXT_DATA will be zero (some pull-down would be needed here). The switch should be controlled (by Pi) in direction from Flash to USB_INT_DATA.

  2. When an external host is connected, it will apply VBUS (VCC) high. This will signal logically to Pi to stop what it was doing with flash, gracefully unmount it, and then to put the USUSB30 switch to connect the Flash with USB_EXT_DATA port. A good idea would be to put the Pi port into SUSPEND before making the switch. That's it.

The following events will occur on host side after the switch: since the USB traffic from Pi will cease, the Flash will go into SUSPEND, which will result in D+ = high. The host will see the "connect event", and since it was a fresh connect, it will issue USB_RESET, erasing all previous configuration to defaults. Then the host will enumerate the Flash in a normal way, and get access to its file system (if it is correct).

When the EXT cable is removed, the opposite process will happen: in 3 ms the Flash will go into suspend, D+ will go HIGH, the Pi side will sense a new connect event, and enumerate the Flash from its side. You might need to wait 5-10 ms before making the switch back after VBUS disappears. Job done.

\$\endgroup\$
  • \$\begingroup\$ Let me see if I understood correctly: I don't need to switch VCC and GND of the flash drive? The flash is always powered by the "box"? The only thing I need to worry about is signalling the Pi with the 5V that come when a cable is connected, unmount the flash gracefully and switch D+ and D- to the external connector. Is that it? (I will have to look into that SUSPEND thing) \$\endgroup\$ – rmarques Sep 11 '17 at 18:47
  • \$\begingroup\$ @rmarques, yes, pretty much this is it. If you don't switch too fast, the SUSPEND might happen naturally. \$\endgroup\$ – Ale..chenski Sep 11 '17 at 18:57
  • \$\begingroup\$ Question updated, I think that's it then. \$\endgroup\$ – rmarques Sep 11 '17 at 19:00
1
\$\begingroup\$

This is a Really Bad Idea in so many ways...

To start with, connecting all the VUSB together and switching the grounds is not going to work the way you think. How will you be able to detect the connection or disconnection of the external host? How will you be able to switch between powering the flash drive from the RPi and powering it from the external host? Instead, you would have to tie the grounds together and sense/switch the VUSB as needed.

But a hardware solution should not be needed at all. You should just leave the flash drive plugged into a host port on the RPi, and when an external host is connected to a device/OTG port on the RPi, a software driver on the RPi should be used to present a virtual filesystem to that host whose contents are the contents of the actual flash drive (or some subset thereof).

This is exactly equivalent to what happens when you plug a camera/iPod/smartphone into a PC in order to transfer pictures, sound files, etc. to/from the device.

\$\endgroup\$
  • 1
    \$\begingroup\$ The only advantage I can think of of doing the switching in hardware would be that you could sense Vcc on the external port and do the switch in hardware with no need for any software on the Pi or any other target device. \$\endgroup\$ – Andrew Sep 11 '17 at 12:04
  • \$\begingroup\$ @Andrew: No, you can't avoid software issues. If the RPi is accessing the flash drive, it must first unmount it before switching it to the external host. \$\endgroup\$ – Dave Tweed Sep 11 '17 at 12:08
  • 1
    \$\begingroup\$ I'd view this as much the same as any normal USB flash drive usage, if the user is stupid enough to pull it out half way through a write then that's their problem. \$\endgroup\$ – Andrew Sep 11 '17 at 13:40
  • \$\begingroup\$ Before any switching I was planning to unmount the flash drive via software and then switch. I don't think it is possible for the Raspberry to present anything to a computer connected to USB, not for the RPi3 model at least. It is possible on the RPi0 though. Why is connecting all the VUSB together a bad idea? Can you add those details in the answer? Thanks. \$\endgroup\$ – rmarques Sep 11 '17 at 14:49
  • \$\begingroup\$ OK, details added. \$\endgroup\$ – Dave Tweed Sep 11 '17 at 15:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.