Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions Documentation/components/drivers/special/usbhost.rst
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,37 @@ USB Host-Side Drivers
**Examples**: See the call to ``register_blockdriver()`` in
the function ``usbhost_initvolume()`` in the file
``drivers/usbhost/usbhost_storage.c``.

CDC-ECM Host Class Driver
=========================

The CDC-ECM (Ethernet Control Model) host class driver
(``drivers/usbhost/usbhost_cdcecm.c``) supports USB devices that expose
a network interface using the USB Communications Device Class Ethernet
Control Model. Common device types include:

- **USB-to-Ethernet adapters** that implement CDC-ECM, providing wired
Ethernet connectivity over a USB port.

- **Cellular modems and similar devices** that expose a CDC-ECM
interface for IP connectivity, such as LTE modems operating in USB
tethering mode.

When a compatible device is connected and enumerated, the driver
registers a standard NuttX Ethernet network interface — for example
``eth0`` — and integrates with the NuttX networking stack in exactly the
same way as any on-board Ethernet driver. Normal network configuration
can then be applied to the interface using standard NSH commands::

ifup eth0
ifconfig eth0 192.168.1.10 netmask 255.255.255.0

Or with DHCP via the ``netinit`` daemon when
``CONFIG_NETINIT_DHCPC=y`` is selected.

The driver is registered by calling ``usbhost_cdcecm_initialize()``
during board initialization, before the USB host waiter thread begins
enumerating devices.

**Examples**: ``drivers/usbhost/usbhost_cdcecm.c``,
``boards/arm/stm32h5/nucleo-h563zi/configs/nshusbnet/defconfig``.
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,75 @@ This configuration configures the digital temperature sensor (DTS)
at /dev/uorb/sensor_temp0 and provides the test application
sensortest. E.g. sensortest -n 10 temp0

usbmsc:
--------

This configuration enables USB Host support with the Mass Storage Class
(MSC) driver. It is intended to test USB Host operation by connecting a
USB mass-storage device (e.g. a USB flash drive) to the board's USB-C
connector. Key options enabled:

- ``CONFIG_STM32H5_USBFS_HOST`` — STM32H5 USB full-speed host controller
- ``CONFIG_USBHOST_MSC`` — USB Mass Storage Class host driver
- ``CONFIG_USBHOST_HUB`` — USB hub support
- ``CONFIG_FS_FAT`` — FAT filesystem for mounting the storage device

The serial console remains on USART3 (ST-Link VCOM). NSH
``ifup``/``ifdown`` commands are disabled because no network interface is
configured in this build.

.. note::

USB Host requires a stable 48 MHz clock. HSI48 is not accurate enough
for reliable USB operation, so this configuration uses the external
high-speed oscillator (HSE) as the USB clock source
(``CONFIG_STM32H5_USE_HSE=y``). On the Nucleo-H563ZI development board
HSE is not connected by default; to enable it you must:

- **Connect** solder bridges **SB3** and **SB4**
- **Disconnect** solder bridge **SB49**

The board also does not support software control of VBUS power. To
supply power to the USB host port, fit a second jumper on the **PWR SEL**
header that bridges the **STLK** and **USB USER** pins together.

nshusbnet:
-----------

This configuration is based on the standard ``nsh`` configuration but adds
full networking support and the CDC-ECM USB Ethernet host driver. It is
intended to test USB Host operation with a USB-to-Ethernet adapter that
uses the CDC-ECM (Ethernet Control Model) protocol. Key options enabled:

- ``CONFIG_STM32H5_USBFS_HOST`` — STM32H5 USB full-speed host controller
- ``CONFIG_USBHOST_CDCECM`` — USB CDC-ECM Ethernet host driver
- ``CONFIG_USBHOST_COMPOSITE`` — composite USB device support
- ``CONFIG_USBHOST_HUB`` — USB hub support
- ``CONFIG_NET``, ``CONFIG_NET_TCP``, ``CONFIG_NET_UDP`` — IPv4 networking stack
- ``CONFIG_NETINIT_DHCPC`` / ``CONFIG_NETUTILS_DHCPC`` — DHCP client for automatic IP configuration
- ``CONFIG_NETUTILS_TELNETD`` — Telnet daemon for remote NSH access
- ``CONFIG_SYSTEM_PING`` — ping utility for connectivity testing

Plug a CDC-ECM USB Ethernet adapter into the board's USB-C host port.
NuttX will enumerate the device, assign it a network interface, and obtain
an IP address via DHCP. The ``ping`` application can then be used to
verify network connectivity.

.. note::

USB Host requires a stable 48 MHz clock. HSI48 is not accurate enough
for reliable USB operation, so this configuration uses the external
high-speed oscillator (HSE) as the USB clock source
(``CONFIG_STM32H5_USE_HSE=y``). On the Nucleo-H563ZI development board
HSE is not connected by default; to enable it you must:

- **Connect** solder bridges **SB3** and **SB4**
- **Disconnect** solder bridge **SB49**

The board also does not support software control of VBUS power. To
supply power to the USB host port, fit a second jumper on the **PWR SEL**
header that bridges the **STLK** and **USB USER** pins together.

References
===========

Expand Down
2 changes: 1 addition & 1 deletion arch/arm/src/stm32h5/hardware/stm32_usbfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@
#define USB_ISTR_PMAOVRN (1 << 14) /* Bit 14: Packet Memory Area Over / Underrun */
#define USB_ISTR_CTR (1 << 15) /* Bit 15: Correct Transfer */
#define USB_ISTR_THR512 (1 << 16) /* Bit 16: 512byte threshold interrupt */
#define USB_ISTR_DDISC (1 << 17) /* Bit 17: Device disconnection */
#define USB_ISTR_DDISC (1 << 17) /* Bit 17: Device connection */
#define USB_ISTR_DCON_STAT (1 << 29) /* Bit 29: Device connection status */
#define USB_ISTR_LS_DCONN (1 << 30) /* Bit 30: Low-speed device connected */

Expand Down
32 changes: 29 additions & 3 deletions arch/arm/src/stm32h5/stm32_usbdrdhost.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,10 @@ static int stm32_chan_wait(struct stm32_usbhost_s *priv,
int timeout_ms);
static void stm32_chan_wakeup(struct stm32_usbhost_s *priv,
struct stm32_chan_s *chan);
static void stm32_set_chep_rx_status(struct stm32_usbhost_s *priv,
int chidx, uint32_t status);
static void stm32_set_chep_tx_status(struct stm32_usbhost_s *priv,
int chidx, uint32_t status);

/* Control endpoint helpers */

Expand Down Expand Up @@ -579,6 +583,7 @@ static int stm32_chan_alloc(struct stm32_usbhost_s *priv)
priv->chan[chidx].inuse = true;
priv->chan[chidx].pmabufno = (uint8_t)bufno;
priv->chan[chidx].pmaaddr = STM32H5_PMA_BUFNO2ADDR(bufno);
uinfo("Channel allocated: chidx=%d\n", chidx);
return chidx;
}
}
Expand Down Expand Up @@ -607,9 +612,12 @@ static inline void stm32_chan_free(struct stm32_usbhost_s *priv,

if (chan->pmabufno != STM32H5_PMA_BUFFER_NONE)
{
stm32_set_chep_rx_status(priv, chidx, USB_CHEP_RX_STRX_DIS);
stm32_set_chep_tx_status(priv, chidx, USB_CHEP_TX_STTX_DIS);
stm32_pma_free_buffer(priv, chan->pmabufno);
chan->pmabufno = STM32H5_PMA_BUFFER_NONE;
chan->pmaaddr = 0;
uinfo("Channel freed: chidx=%d\n", chidx);
}

chan->inuse = false;
Expand Down Expand Up @@ -1534,9 +1542,19 @@ static void stm32_hc_in_irq(struct stm32_usbhost_s *priv, int chidx)

if (!transfer_complete && (chan->waiter || chan->callback))
{
/* Clear VTRX by writing 0 to it
* (toggle bit, write 1 keeps, write 0 clears)
*/

chepval = stm32_getreg(STM32H5_USB_CHEP(chidx));
chepval = (chepval &
(0xffff7fff & USB_CHEP_REG_MASK)) | USB_CHEP_VTTX;
stm32_putreg(STM32H5_USB_CHEP(chidx), chepval);

/* More data expected - reactivate channel for next packet */

stm32_transfer_start(priv, chidx);
return;
}
else
{
Expand Down Expand Up @@ -1737,23 +1755,31 @@ static int stm32_usbdrd_interrupt(int irq, void *context, void *arg)

istr = stm32_getreg(STM32_USB_ISTR);

/* Device connection */
/* Device connection/Disconnection. The STM32H5 has both USB_ISTR_DDISC
* and USB_ISTR_RESET to detect a connected device. Use USB_ISTR_RESET
* since it is signaled after 22 cycles (debounced)
*/

if ((istr & USB_ISTR_RESET) != 0)
{
if ((istr & USB_ISTR_DCON_STAT) != 0)
{
stm32_gint_connected(priv);
}
else
{
stm32_gint_disconnected(priv);
}

stm32_putreg(STM32_USB_ISTR, ~USB_ISTR_RESET);
}

/* Device disconnection */
/* Device connection */

if ((istr & USB_ISTR_DDISC) != 0)
{
stm32_gint_disconnected(priv);
/* Not used. USB_ISTR_RESET used instead */

stm32_putreg(STM32_USB_ISTR, ~USB_ISTR_DDISC);
}

Expand Down
72 changes: 72 additions & 0 deletions boards/arm/stm32h5/nucleo-h563zi/configs/nshusbnet/defconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_NSH_ARGCAT is not set
# CONFIG_STANDARD_SERIAL is not set
CONFIG_ARCH="arm"
CONFIG_ARCH_BOARD="nucleo-h563zi"
CONFIG_ARCH_BOARD_NUCLEO_H563ZI=y
CONFIG_ARCH_BUTTONS=y
CONFIG_ARCH_CHIP="stm32h5"
CONFIG_ARCH_CHIP_STM32H563ZI=y
CONFIG_ARCH_CHIP_STM32H5=y
CONFIG_ARCH_INTERRUPTSTACK=2048
CONFIG_ARCH_STACKDUMP=y
CONFIG_BOARD_LOOPSPERMSEC=9251
CONFIG_BUILTIN=y
CONFIG_DEBUG_ASSERTIONS=y
CONFIG_DEBUG_FEATURES=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEBUG_USB=y
CONFIG_DEBUG_USB_ERROR=y
CONFIG_DEBUG_USB_WARN=y
CONFIG_FS_PROCFS=y
CONFIG_FS_PROCFS_REGISTER=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_IDLETHREAD_STACKSIZE=2048
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INIT_STACKSIZE=4096
CONFIG_LINE_MAX=64
CONFIG_NET=y
CONFIG_NETDB_DNSCLIENT=y
CONFIG_NETDEV_LATEINIT=y
CONFIG_NETINIT_DHCPC=y
CONFIG_NETUTILS_DHCPC=y
CONFIG_NETUTILS_TELNETD=y
CONFIG_NET_ETH_PKTSIZE=1514
CONFIG_NET_ICMP_SOCKET=y
CONFIG_NET_PKT=y
CONFIG_NET_ROUTE=y
CONFIG_NET_TCP=y
CONFIG_NET_UDP=y
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_READLINE=y
CONFIG_PREALLOC_TIMERS=4
CONFIG_RAM_SIZE=655360
CONFIG_RAM_START=0x20000000
CONFIG_RAW_BINARY=y
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_LPWORK=y
CONFIG_SCHED_LPWORKSTACKSIZE=4096
CONFIG_SCHED_WAITPID=y
CONFIG_STACK_COLORATION=y
CONFIG_STM32H5_USART3=y
CONFIG_STM32H5_USBFS_HOST=y
CONFIG_STM32H5_USE_HSE=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_PING=y
CONFIG_TASK_NAME_SIZE=0
CONFIG_USART3_SERIAL_CONSOLE=y
CONFIG_USBHOST_CDCECM=y
CONFIG_USBHOST_COMPOSITE=y
CONFIG_USBHOST_CONFIGURATION_SELECTION=y
CONFIG_USBHOST_HUB=y
36 changes: 34 additions & 2 deletions boards/arm/stm32h5/nucleo-h563zi/src/stm32_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,17 @@ int stm32_usbhost_initialize(void)
}
#endif

#ifdef CONFIG_USBHOST_CDCECM
/* Register the CDC-ECM class driver */

ret = usbhost_cdcecm_initialize();
if (ret < 0)
{
uerr("ERROR: Failed to register CDC-ACM class: %d\n", ret);
return ret;
}
#endif

/* Then get an instance of the USB host interface */

uinfo("Initialize USB host\n");
Expand Down Expand Up @@ -226,11 +237,32 @@ void stm32h5_usbhost_vbusdrive(int port, bool enable)
/* The Nucleo-h563zi doesn't have hardware for a vbus drive.
* Instead to get host working, you need to put an extra jumper
* on the "PWR SEL" to jump "STLK" and "USB USER".
* This effectively supplies 5V power form the STLink to the USB device.
* The power output is limited so only relatively low power
* This effectively supplies 5V power from the STLink to the USB device.
* The power output is limited, so only relatively low power
* devices can work.
*/
}
#endif

#ifdef CONFIG_USBHOST_CONFIGURATION_SELECTION
int board_usbhost_select_configuration(FAR struct usbhost_hubport_s *hport,
FAR const struct usb_devdesc_s *devdesc,
FAR const struct usbhost_id_s *id)
{
if (id->vid == 0x0bda && id->pid == 0x8153)
Comment thread
xiaoxiang781216 marked this conversation as resolved.
{
/* Use interface 1 (CDC-ECM) for this ethernet adapter.
* vid - Realtek Semiconductor Corp
* pid - RTL8153 Gigabit Ethernet Adapter
*/

return 1;
}

/* All other USB deices use configurion 0 */

return 0;
}
#endif

#endif /* CONFIG_STM32H5_USBFS_HOST */
4 changes: 4 additions & 0 deletions drivers/usbhost/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ if(CONFIG_USBHOST)
list(APPEND SRCS usbhost_cdcacm.c)
endif()

if(CONFIG_USBHOST_CDCECM)
list(APPEND SRCS usbhost_cdcecm.c)
endif()

if(CONFIG_USBHOST_CDCMBIM)
list(APPEND SRCS usbhost_cdcmbim.c)
endif()
Expand Down
30 changes: 30 additions & 0 deletions drivers/usbhost/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ config USBHOST_ASYNCH
I/O transfer. This may be required, for example, to receive
infrequent, asynchronous input from an interrupt pipe.

config USBHOST_CONFIGURATION_SELECTION
bool "Per device configuration selection"
default n
---help---
Some devices have multiple USB configuration. By default the enumeration
selects the first configuration which may not be the desired configuration.
This features enables a board specific callback where it may choose which
configuration to apply based on the USB device descriptor. The callback may
choose by VID/PID or any other info it can acquire from a USB descriptor.
Board file must supply board_usbhost_select_configuration().

config USBHOST_WAITER
bool "USB Host Waiter Support"
default n
Expand Down Expand Up @@ -293,6 +304,25 @@ config USBHOST_CDCACM_TXBUFSIZE

endif # USBHOST_CDCACM

config USBHOST_CDCECM
bool "CDC/ECM support"
default n
depends on USBHOST_HAVE_ASYNCH && !USBHOST_BULK_DISABLE && !USBHOST_INT_DISABLE
select USBHOST_ASYNCH
select NET_ETHERNET
---help---
Select this option to build in host support for CDC/ECM serial
devices.

config USBHOST_CDCECM_PACKET_PRINT
bool "Print raw CDC/ECM packets"
default n
depends on DEBUG_USB_INFO
---help---
Print all raw RX and TX packets send and received in the CDC/ECM driver.
This can be useful for analysing with programs such as wireshark.


config USBHOST_CDCMBIM
bool "CDC/MBIM support"
default n
Expand Down
Loading
Loading