Photon - USB Host Mode

Hey all,

I noticed USB host mode is not currently enabled in the firmware for the Photon, so I thought I would do a little research myself to figure out how all this worked. Over the past few days I’ve been familiarizing myself with the different USB modes offered on the STM32F2XX micro controller (mostly by the means of this document and these examples). Comparing this information and code to the Photon firmware, I noticed the following things:

  1. Only USB_DEVICE_MODE is defined in the Photon firmware, USB_HOST_MODE is currently commented out in usb_conf.h.
  2. None of the source files defined under the USB Host Driver (STM32_USB_Host_Driver) are set to be compiled by the firmware in sources.mk.

Naturally, I had to see what would happen if I uncommented the define for USB_HOST_MODE. Upon firmware compilation, an error occurs towards the end stating an ‘SRAM’ overflow by 276 bytes. Did the new code make the firmware too big?

I’m sure there are plenty of other things that need to happen for a successful implementation of host mode. I could also see this presenting many new challenges with the fact that the Photon needs to support both host and device mode at the same time, but I would love to see this feature implemented soon and will gladly help in any way possible! Does anyone else have a similar interest?

1 Like

For host mode to be successful you would first need to add hardware support for it, which at a minimum is a 5V source and a switch (@BDub will surely have much advice for you there.)

The compiler error you got sounds like you’re trying to build the bootloader. I’d skip that for now since I don’t think you’ll get any useful host mode functionality. Instead, change to the modules directory and run the build from there. This will build the system modules and your application module.

I hope that helps you get started! :smile:
Cheers,
mat.

I’d love to see someone do a how to on building out host-mode and a schematic on simple hw support required.

@deftio, I think I have the cable set up correctly, maybe @BDub can confirm… Micro USB is the power input, while the female connector is for the host device:

@mdma - as for the build, I double checked and I am building from the modules directory (make PLATFORM=photon clean all). I only get the error when I try to turn on USB_HOST_MODE by uncommenting line 162 (#define USE_HOST_MODE) in the usbconf.h file located at “\platform\MCU\STM32F2xx\SPARK_Firmware_Driver\inc”. According to examples for the STM32, this definition needs to be enabled for the microcontroller to support host functionality. Can you see if the same thing happens on your end?

2 Likes

This is awexome, keep working at it! From my recollection, you may need to actively switch the power to the OTG port.

Made a decent amount of progress on this, here’s an update:

  • Turned on host mode in the firmware and modified sources.mk file to build all host driver files at platform/MCU/STM32F2xx/STM32_USB_Host_Driver/src .
  • Successfully reallocated the memory map to allow the firmware to build with the new driver code (there was an overflow error of 276 bytes)
  • Exposed 2 main functions of USB host through usb_hal and spark_wiring (USBH_Init and USBH_Process).
  • USBH_Init takes callbacks parameter from user application for system events such as Init, DeviceConnected, USBEnumerationComplete, etc

My test consists of trying to connect a keyboard and use the built-in HID driver to send keystrokes over a TCPClient. I’m also sending information over TCP for all USB events. This is where I hit a roadblock. A simple program calling USBH_Init demonstrates the following behavior:

  1. While connected to a PC directly: System picks up virtual COM initially, but then drops device as soon as program initializes. I’m confident USBH_Init is getting called and switching the device into host mode. USBH_Init callback is completed over TCP.
  2. While connected to nothing: Again, confident USBH_Init is getting called and switching device into host mode. USBH_Init callback is completed. If I connect a keyboard after power up, no other callback gets called.
  3. While connected to a keyboard using circuit from my previous post: If I power on the photon with a device connected, the USBH_Init callback never completes. Seems to be getting stuck somewhere.

For case #3, I’ve tracked the code to a function in platform/MCU/STM32F2xx/STM32_USB_OTG_Driver/src/usb_hcd.c, specifically the call to USB_OTG_EnableGlobalInt on line 119. If I comment this line, the USBH_Init completes successfully for case #3, but I still don’t receive any other callbacks for the USB device.

At this point I’m not sure what to try next. @BDub, you mention an active power supply. Is the 5V coming from the micro connector enough to power the device and the photon board? Most of the driver code is untouched, however there is some custom configuration in the usb_conf.h, platform_config.h, and usb_bsp.c files that the USB Host driver relies on. Also, for the photon, currently USE_USB_OTG_HS is getting defined to signify USB High-Speed.

Any ideas from the team? I’ll post a fork of my firmwire on Github later this week.

Here is the fork if anyone is interested.

Notable changes:

  • usb_conf.h - had to add some defines to get it to compile, I used the defaults from ST.
  • usb_bsp.c - had to add some functions here for it to compile. I don’t think these functions impact USB_HS (the default setting set in platform_config.h for the Photon)
  • additions to various sources.mk to include files in firmware build
1 Like

Great work @rac146! I wish I had more time to help you out with this, but I can cheer you on :slight_smile: Have you seen this STM32 document: http://www.st.com/st-web-ui/static/active/en/resource/technical/document/user_manual/DM00105256.pdf

1 Like

Hey all,

I’ve been tinkering with the debugger over the past few days and finally have some success to report!!! Turns out I was specifically missing this piece of code in usb_hal.c:

OLD:

void OTG_HS_irq(void)
{

		USBD_OTG_ISR_Handler(&USB_OTG_dev);
}

NEW:

void OTG_HS_irq(void)
{
	if (USB_OTG_IsHostMode(&USB_OTG_dev))
	{
		USBH_OTG_ISR_Handler(&USB_OTG_dev);
	}
	else
	{
		USBD_OTG_ISR_Handler(&USB_OTG_dev);
	}
}

Latest firmware branch is on Git: https://github.com/rac146/firmware/

Besides the usb.hal change, I also currently have commented out all user callbacks in platform/MCU/STM32F2xx/STM32_USB_Host_Driver/src/usbh_core.c. With these callbacks on, the Photon will crash whenever a USB device is connected. Anyone have an idea why this might be happening? I have a sample app called usbHID in the user application directory that has an example of what the callbacks look like.

Currently I’ve been able to test and verify keyboards and mice through the debugger by placing breakpoints in various parts of the driver code and pressing buttons/moving the mouse.

Once the callbacks get implemented correctly, and more devices get tested, I think we’ll be one step closer to having USB Host on the Photon!

2 Likes

This is great to hear - I’m excitedly following your progress!

One more update - I updated my branch once more and moved the callbacks from my application file back on to the firmware side inside the usb_hal.c file. This resulted in all callbacks functioning normally. I’m still pretty stumped on why the callbacks fail if they’re inside the application file.

Biggest bug so far: The Wifi seems to keep dropping randomly. Not sure if it’s my code or the Photon. I’ll flash back normal firmware later and see if the issue persists.

I also updated the keyboard decode function to output data onto Serial 1. Here’s a little video to get everyone excited ;):

2 Likes

This looks awesome! I’m in need of USB host mode, I had no idea the STM32 family supported it natively. I hope the issues get sorted out and this can eventually make it into the official firmware.

2 Likes

Nice! Made any more progress @rac146? i’m curious about the WiFi dropping out. I would love to be able to use USB host to communicate with a greater variety of hardware, also looking forward to seeing it in the official firmware!

1 Like

Hey @kbecks13, no recent progress, been fooling around with some other things lately. I’ll pick this back up soon and could definitely use some help! If you get a chance and want to play around with the keyboard example, flash the test firmware on my github (it’s a little dated now, i’ll update soon). You’ll need to create and adapter to turn the micro USB port on the photon to a USB type A, along with a way to supply power. Refer to the image above for an example (I used a second micro USB port for power only). Once you have that you should be able to send keystrokes from a USB keyboard. As for other USB devices, it would totally be possible w/ a custom driver implementation and would have to be flashed w/ the firmware.

1 Like

I went ahead and updated the firmware on my fork, so it’s updated with the latest firmware files. Everything still works! Also, the wireless seems stable all of a sudden, still not sure if this is an actual issue or not (using the develop branch), but i’ll keep my eye on it.

Hoping to solve one of the biggest problems with this implementation - the HAL. In order to create custom drivers, it would be nice to not have to touch the existing firmware and develop the driver solely in the application layer, however I’m not sure if this is possible. Currently i’m trying to expose the USB_HOST typedef structure from usbh_core.h into my application (through the HAL, specifically usb_hal.h), but by doing so I need to include usbh_core.h in usb_hal.h. When I do this the firmware is no longer compiling. Does anybody have an idea why this would happen? Maybe there is some circular dependency somewhere?

1 Like

What’s the error message?
You might need “forward declaration” if you run into circular depenency issues.

It’s a pretty odd error that’s occurring in an unrelated file (usbd_reg.c). If I remove the usbh_core.h reference from usb_hal.h and move it into usb_hal.c, the error goes away.

Hi @rac146, thanks for the PM.

I’ve checked out your repo and built the develop branch. I don’t see the error you mention. Is there another branch I should be using?

Thanks,
mat.

If you move the include of usbh_core.h from usb_hal.c to usb_hal.h you will get the error. My idea is to create a prototype function that accepts pointers of usbh_core.h objects (specifically the USB_HOST object) so in an application we can create an empty USB_HOST and pass it to the HAL functions to get initialized. Make sense?

I get a different error: MIN redefined. Please push your code as it is so we are certain to be testing the same thing.

EDIT: ok I get the same error in system-part1, and the error above in system-part2.

Exposing usbd_conf.h to the HAL layer isn’t recommended since those files are not platform neutral. It’s best to find a platform neutral way to expose the functionality that you need, or alternatively use a void* for any special platform-specific types.