This application note explains how to configure the STM32H7 running uClinux as the composite USB Gadget. As an example of how the composite USB Gadget can be used, the application note shows how an USB Ethernet Gadget and a USB Mass Storage Gadget are configured over the USB OTG High-Speed link.
In practical embedded applications:
- The Ethernet Gadget can be used for TCP/IP-based communications between the USB host and the STM32H7 over the USB physical link.
- The Mass Storage Gadget can be used to share data on a physical or virtual storage of the IMXRT with the USB host. To give an example of a practical use of this functionality, the SD Card or a Flash partition of the STM32H7 can be mounted as a disk from the USB host.
Note that other USB Gadget functions can be enabled on the STM32H7 in a similar manner.
Configuration and Build
To enable the USB Gadgets functionality in the uClinux rootfs project, do the following:
- On the development host, activate the cross-development environment:
$ . ./ACTIVATE.sh
$ cd projects/rootfs
- Select the appropriate USB gadgets in the Linux configuration menu. To do so for the Ethernet and Mass Storage gadgets, go to the Device Drivers -> USB support -> USB Gadget Support -> USB Gadget functions configurable through configfs menu. Select the RNDIS and Mass storage options):
$ make kmenuconfig
- Build the project:
$ make
- Boot the resultant rootfs.uImage on the target.
- Configure the USB gadgets on the target board from the Linux shell, at the run time. Note that while the sample session below makes uses of the interactive shell commands to configure the USB gadgets, in a practical application, such configuration commands can be taken into a shell script (which could then be a part of the Linux start-up scripts):
- Mount the configfs file system:
/ # mount -t configfs configfs /sys/kernel/config/
- Create a new composite USB gadget:
/ # mkdir /sys/kernel/config/usb_gadget/g1
- Add a description for the newly created gadget:
/ # cd /sys/kernel/config/usb_gadget/g1
/sys/kernel/config/usb_gadget/g1 # echo 0x525 > idVendor
/sys/kernel/config/usb_gadget/g1 # echo 0xa4a7 > idProduct
/sys/kernel/config/usb_gadget/g1 # mkdir strings/0x409
/sys/kernel/config/usb_gadget/g1 # echo 00001 > strings/0x409/serialnumber
/sys/kernel/config/usb_gadget/g1 # echo user > strings/0x409/manufacturer
/sys/kernel/config/usb_gadget/g1 # echo mygadget > strings/0x409/product
- Create the configuration for the composite device:
/sys/kernel/config/usb_gadget/g1 # mkdir configs/c.1
/sys/kernel/config/usb_gadget/g1 # mkdir configs/c.1/strings/0x409
/sys/kernel/config/usb_gadget/g1 # echo composite > configs/c.1/strings/0x409/configuration
/sys/kernel/config/usb_gadget/g1 # echo 120 > configs/c.1/MaxPower
- Define the Mass Storage function:
/sys/kernel/config/usb_gadget/g1 # mkdir functions/mass_storage.0
Mass Storage Function, version: 2009/09/11
LUN: removable file: (no medium)
- Link the entire SD card to the Mass Storage gadget:
/sys/kernel/config/usb_gadget/g1 # echo /dev/mmcblk0 > functions/mass_storage.0/lun.0/file
- Define the Ethernet gadget (RNDIS) function:
/sys/kernel/config/usb_gadget/g1 # mkdir functions/rndis.usb0
using random self ethernet address
using random host ethernet address
- Link the Gadget functions to the composite device:
/sys/kernel/config/usb_gadget/g1 # ln -s functions/mass_storage.0/ configs/c.1/
/sys/kernel/config/usb_gadget/g1 # ln -s functions/rndis.usb0 configs/c.1
- Enable the USB Gadget on the high speed USB port of the STM32H7:
/sys/kernel/config/usb_gadget/g1 # echo 40040000.usb > UDC
Connect to the Linux Host
Given the configuration above, the USB host will detect the STM32H7 as 2 USB devices:
- RNDIS Ethernet
- USB Mass Storage.
Run the following command on the USB host (assuming a Linux host PC or a notebook), to verify availability of the STM32H7-based USB devices:
$ dmesg | tail -n 30
...
[ 499.279916] usb 1-3: new high-speed USB device number 5 using xhci_hcd
[ 499.411186] usb 1-3: New USB device found, idVendor=0525, idProduct=a4a7, bcdDevice= 6.01
[ 499.411202] usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 499.411207] usb 1-3: Product: mygadget
[ 499.411212] usb 1-3: Manufacturer: user
[ 499.411216] usb 1-3: SerialNumber: 00001
[ 499.490632] usb-storage 1-3:1.0: USB Mass Storage device detected
[ 499.491178] scsi host1: usb-storage 1-3:1.0
[ 499.491468] usbcore: registered new interface driver usb-storage
[ 499.501347] usbcore: registered new interface driver uas
[ 499.519036] usbcore: registered new interface driver cdc_ether
[ 499.533056] rndis_host 1-3:1.1 usb0: register 'rndis_host' at usb-0000:00:14.0-3, RNDIS device,
b6:11:01:e2:76:b4
[ 499.533151] usbcore: registered new interface driver rndis_host
[ 499.556593] usbcore: registered new interface driver rndis_wlan
[ 499.567862] rndis_host 1-3:1.1 enp0s20f0u3i1: renamed from usb0
[ 500.553099] scsi 1:0:0:0: Direct-Access Linux File-Stor Gadget 0601 PQ: 0 ANSI: 2
[ 500.554005] sd 1:0:0:0: Attached scsi generic sg1 type 0
[ 500.554341] sd 1:0:0:0: Power-on or device reset occurred
[ 500.555002] sd 1:0:0:0: [sdb] 996352 512-byte logical blocks: (510 MB/487 MiB)
[ 500.555310] sd 1:0:0:0: [sdb] Write Protect is off
[ 500.555318] sd 1:0:0:0: [sdb] Mode Sense: 0f 00 00 00
[ 500.555587] sd 1:0:0:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 500.564886] sdb: sdb1
[ 500.565369] sd 1:0:0:0: [sdb] Attached SCSI removable disk
Using the Ethernet Gadget Interface
Step through the following procedure to configure the Ethernet Gadget interface:
- Set up an IP address of the USB Ethernet interface on the STM32H7 side. Make sure to select an address that will not conflict with the other network sub nets in the system (if any are present):
/ # ifconfig usb0 192.168.2.2
- Set up an IP address of the USB Ethernet interface on the USB host side. Obviously, select an address from the same sub-net as the gadget:
$ sudo ifconfig enp0s20f0u3i1 192.168.2.1
- Check the TCP/IP link between STM32H7 and the USB host:
- On the STM32H7:
/ # ping 192.168.2.1 -c 3
PING 192.168.2.1 (192.168.2.1): 56 data bytes
64 bytes from 192.168.2.1: seq=0 ttl=64 time=0.798 ms
64 bytes from 192.168.2.1: seq=1 ttl=64 time=0.428 ms
64 bytes from 192.168.2.1: seq=2 ttl=64 time=0.389 ms
--- 192.168.2.1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.389/0.538/0.798 ms
/ #
- On the USB host:
$ ping 192.168.2.2 -c 3
PING 192.168.2.2 (192.168.2.2) 56(84) bytes of data.
64 bytes from 192.168.2.2: icmp_seq=1 ttl=64 time=0.339 ms
64 bytes from 192.168.2.2: icmp_seq=2 ttl=64 time=0.280 ms
64 bytes from 192.168.2.2: icmp_seq=3 ttl=64 time=0.292 ms
--- 192.168.2.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2030ms
rtt min/avg/max/mdev = 0.280/0.303/0.339/0.025 ms
Using the Mass Storage Interface
Step through the following procedure to configure the Mass Storage interface:
- On the Linux host check the Mass Storage gadget has been automatically mounted:
$ mount | grep "/dev/sd"
/dev/sd1 on /media/user/C11B-9AA7 type vfat
(rw,nosuid,nodev,relatime,uid=1000,gid=1000,fmask=0022,dmask=0022,
codepage=437,iocharset=iso8859-1,shortname=mixed,showexec,utf8,flush,
errors=remount-ro,uhelper=udisks2)
- Verify that the mounted media (which is the SD Card on the STM32H7, in the above example) contains the uClinux boot image:
$ ls /media/user/C11B-9AA7
rootfs.uImage