This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit ec3355a5182db336f8d0be61cc48d46d6408ce59
Author: Denis Tolstov <[email protected]>
AuthorDate: Mon Apr 3 06:57:57 2023 +0300

    boards/stm32f411-minimum: Add support for USB mass storage (gadget)
    
    * Bind smartfs0 to LUN 0 instead of mmcsd0
    * Use USB composite code from similar boards
    * Pull in CDC/ACM code as well
    
    boards/stm32f411-minimum: composite: style refactor
    
    * Unalign `int strbase = ` text, use single spaces
    * Rename `int n` to `int dev_idx` like in newer `_composite.c` board code
    * Add composite defconfig with CDC/ACM and MSC for build-testing
---
 boards/arm/stm32/stm32f411-minimum/README.txt      |   4 +
 .../stm32f411-minimum/configs/composite/defconfig  |  66 +++++
 .../stm32f411-minimum/configs/usbmsc/defconfig     |  57 +++++
 boards/arm/stm32/stm32f411-minimum/src/Make.defs   |   8 +
 .../stm32/stm32f411-minimum/src/stm32_composite.c  | 276 +++++++++++++++++++++
 .../arm/stm32/stm32f411-minimum/src/stm32_usbmsc.c |  70 ++++++
 6 files changed, 481 insertions(+)

diff --git a/boards/arm/stm32/stm32f411-minimum/README.txt 
b/boards/arm/stm32/stm32f411-minimum/README.txt
index 20c98a6e1b..d7b9729d22 100644
--- a/boards/arm/stm32/stm32f411-minimum/README.txt
+++ b/boards/arm/stm32/stm32f411-minimum/README.txt
@@ -88,6 +88,10 @@ as well as 5k pull-downs on USB-C CC1/CC2 pins (not 
affecting USB-A adapters).
 Because of this we are not considering USBOTG-FS Host configurations and
 do not map OTG_VBUS, OTG_ID pins to FS PHY, also no OVER/PWRON GPIOs.
 
+If using USB and USART1 simultaneously, make sure to check
+CONFIG_OTG_ID_GPIO_DISABLE, else stm32_otgfsdev driver code remaps PA10 pin 
from
+USART1_RX to OTG_ID, and you'll lose keyboard/console input!
+
 SPI NOR Flash
 =============
 
diff --git a/boards/arm/stm32/stm32f411-minimum/configs/composite/defconfig 
b/boards/arm/stm32/stm32f411-minimum/configs/composite/defconfig
new file mode 100644
index 0000000000..df298c23ba
--- /dev/null
+++ b/boards/arm/stm32/stm32f411-minimum/configs/composite/defconfig
@@ -0,0 +1,66 @@
+#
+# 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_ARCH_FPU is not set
+# CONFIG_DISABLE_OS_API is not set
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+# CONFIG_NSH_DISABLE_IFCONFIG is not set
+# CONFIG_NSH_DISABLE_PS is not set
+# CONFIG_STM32_SYSCFG is not set
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="stm32f411-minimum"
+CONFIG_ARCH_BOARD_STM32F411_MINIMUM=y
+CONFIG_ARCH_CHIP="stm32"
+CONFIG_ARCH_CHIP_STM32=y
+CONFIG_ARCH_CHIP_STM32F411CE=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARD_LOOPSPERMSEC=8499
+CONFIG_BUILTIN=y
+CONFIG_CDCACM=y
+CONFIG_CDCACM_COMPOSITE=y
+CONFIG_COMPOSITE_IAD=y
+CONFIG_COMPOSITE_PRODUCTID=0x2022
+CONFIG_COMPOSITE_VENDORID=0x03eb
+CONFIG_HAVE_CXX=y
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INTELHEX_BINARY=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_DISABLE_LOSMART=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_OTG_ID_GPIO_DISABLE=y
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_RAM_SIZE=131072
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_START_DAY=02
+CONFIG_START_MONTH=04
+CONFIG_START_YEAR=2023
+CONFIG_STM32F411MINIMUM_FLASH=y
+CONFIG_STM32_FLASH_CONFIG_E=y
+CONFIG_STM32_FLASH_PREFETCH=y
+CONFIG_STM32_JTAG_SW_ENABLE=y
+CONFIG_STM32_OTGFS=y
+CONFIG_STM32_USART1=y
+CONFIG_SYSTEM_CDCACM=y
+CONFIG_SYSTEM_COMPOSITE=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_USBMSC=y
+CONFIG_SYSTEM_USBMSC_DEVPATH1="/dev/smart0"
+CONFIG_TASK_NAME_SIZE=15
+CONFIG_USART1_SERIAL_CONSOLE=y
+CONFIG_USBDEV=y
+CONFIG_USBDEV_BUSPOWERED=y
+CONFIG_USBDEV_COMPOSITE=y
+CONFIG_USBMSC=y
+CONFIG_USBMSC_COMPOSITE=y
diff --git a/boards/arm/stm32/stm32f411-minimum/configs/usbmsc/defconfig 
b/boards/arm/stm32/stm32f411-minimum/configs/usbmsc/defconfig
new file mode 100644
index 0000000000..3b7623cf2d
--- /dev/null
+++ b/boards/arm/stm32/stm32f411-minimum/configs/usbmsc/defconfig
@@ -0,0 +1,57 @@
+#
+# 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_ARCH_FPU is not set
+# CONFIG_DISABLE_OS_API is not set
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+# CONFIG_NSH_DISABLE_IFCONFIG is not set
+# CONFIG_NSH_DISABLE_PS is not set
+# CONFIG_STM32_SYSCFG is not set
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="stm32f411-minimum"
+CONFIG_ARCH_BOARD_STM32F411_MINIMUM=y
+CONFIG_ARCH_CHIP="stm32"
+CONFIG_ARCH_CHIP_STM32=y
+CONFIG_ARCH_CHIP_STM32F411CE=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARD_LOOPSPERMSEC=8499
+CONFIG_BUILTIN=y
+CONFIG_HAVE_CXX=y
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INTELHEX_BINARY=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_DISABLE_LOSMART=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_OTG_ID_GPIO_DISABLE=y
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_RAM_SIZE=131072
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_START_DAY=02
+CONFIG_START_MONTH=04
+CONFIG_START_YEAR=2023
+CONFIG_STM32F411MINIMUM_FLASH=y
+CONFIG_STM32_FLASH_CONFIG_E=y
+CONFIG_STM32_FLASH_PREFETCH=y
+CONFIG_STM32_JTAG_SW_ENABLE=y
+CONFIG_STM32_OTGFS=y
+CONFIG_STM32_USART1=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_USBMSC=y
+CONFIG_SYSTEM_USBMSC_DEVPATH1="/dev/smart0"
+CONFIG_TASK_NAME_SIZE=15
+CONFIG_USART1_SERIAL_CONSOLE=y
+CONFIG_USBDEV=y
+CONFIG_USBDEV_BUSPOWERED=y
+CONFIG_USBMSC=y
diff --git a/boards/arm/stm32/stm32f411-minimum/src/Make.defs 
b/boards/arm/stm32/stm32f411-minimum/src/Make.defs
index 1a310baf7a..2052579943 100644
--- a/boards/arm/stm32/stm32f411-minimum/src/Make.defs
+++ b/boards/arm/stm32/stm32f411-minimum/src/Make.defs
@@ -42,6 +42,14 @@ ifeq ($(CONFIG_STM32_OTGFS),y)
   CSRCS += stm32_usb.c
 endif
 
+ifeq ($(CONFIG_USBDEV_COMPOSITE),y)
+  CSRCS += stm32_composite.c
+endif
+
+ifeq ($(CONFIG_USBMSC),y)
+CSRCS += stm32_usbmsc.c
+endif
+
 DEPPATH += --dep-path board
 VPATH += :board
 CFLAGS += $(shell $(INCDIR) "$(CC)" 
$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board)
diff --git a/boards/arm/stm32/stm32f411-minimum/src/stm32_composite.c 
b/boards/arm/stm32/stm32f411-minimum/src/stm32_composite.c
new file mode 100644
index 0000000000..107b1a4ad7
--- /dev/null
+++ b/boards/arm/stm32/stm32f411-minimum/src/stm32_composite.c
@@ -0,0 +1,276 @@
+/****************************************************************************
+ * boards/arm/stm32/stm32f411-minimum/src/stm32_composite.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <debug.h>
+#include <assert.h>
+
+#include <nuttx/usb/usbdev.h>
+#include <nuttx/usb/cdcacm.h>
+#include <nuttx/usb/usbmsc.h>
+#include <nuttx/usb/composite.h>
+
+#if defined(CONFIG_BOARDCTL_USBDEVCTRL) && defined(CONFIG_USBDEV_COMPOSITE)
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef CONFIG_USBMSC_COMPOSITE
+static void *g_mschandle;
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_mscclassobject
+ *
+ * Description:
+ *   If the mass storage class driver is part of composite device, then
+ *   its instantiation and configuration is a multi-step, board-specific,
+ *   process (See comments for usbmsc_configure below).  In this case,
+ *   board-specific logic must provide board_mscclassobject().
+ *
+ *   board_mscclassobject() is called from the composite driver.  It must
+ *   encapsulate the instantiation and configuration of the mass storage
+ *   class and the return the mass storage device's class driver instance
+ *   to the composite driver.
+ *
+ * Input Parameters:
+ *   classdev - The location to return the mass storage class' device
+ *     instance.
+ *
+ * Returned Value:
+ *   0 on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_USBMSC_COMPOSITE
+static int board_mscclassobject(int minor,
+                                struct usbdev_devinfo_s *devinfo,
+                                struct usbdevclass_driver_s **classdev)
+{
+  int ret;
+
+  DEBUGASSERT(g_mschandle == NULL);
+
+  /* Configure the mass storage device */
+
+  uinfo("Configuring with NLUNS=1\n");
+  ret = usbmsc_configure(1, &g_mschandle);
+  if (ret < 0)
+    {
+      uerr("ERROR: usbmsc_configure failed: %d\n", -ret);
+      return ret;
+    }
+
+  uinfo("MSC handle=%p\n", g_mschandle);
+
+  /* Bind the LUN(s) */
+
+  uinfo("Bind LUN=0 to /dev/smart0\n");
+  ret = usbmsc_bindlun(g_mschandle, "/dev/smart0", 0, 0, 0, false);
+  if (ret < 0)
+    {
+      uerr("ERROR: usbmsc_bindlun failed for LUN 1 at /dev/smart0: %d\n",
+           ret);
+      usbmsc_uninitialize(g_mschandle);
+      g_mschandle = NULL;
+      return ret;
+    }
+
+  /* Get the mass storage device's class object */
+
+  ret = usbmsc_classobject(g_mschandle, devinfo, classdev);
+  if (ret < 0)
+    {
+      uerr("ERROR: usbmsc_classobject failed: %d\n", -ret);
+      usbmsc_uninitialize(g_mschandle);
+      g_mschandle = NULL;
+    }
+
+  return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: board_mscuninitialize
+ *
+ * Description:
+ *   Un-initialize the USB storage class driver.
+ *   This is just an application specific wrapper for usbmsc_unitialize()
+ *   that is called form the composite device logic.
+ *
+ * Input Parameters:
+ *   classdev - The class driver instrance previously give to the composite
+ *     driver by board_mscclassobject().
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_USBMSC_COMPOSITE
+static void board_mscuninitialize(struct usbdevclass_driver_s *classdev)
+{
+  if (g_mschandle)
+    {
+      usbmsc_uninitialize(g_mschandle);
+    }
+
+  g_mschandle = NULL;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_composite_initialize
+ *
+ * Description:
+ *   Perform architecture specific initialization of a composite USB device.
+ *
+ ****************************************************************************/
+
+int board_composite_initialize(int port)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name:  board_composite_connect
+ *
+ * Description:
+ *   Connect the USB composite device on the specified USB device port using
+ *   the specified configuration.  The interpretation of the configid is
+ *   board specific.
+ *
+ * Input Parameters:
+ *   port     - The USB device port.
+ *   configid - The USB composite configuration
+ *
+ * Returned Value:
+ *   A non-NULL handle value is returned on success.  NULL is returned on
+ *   any failure.
+ *
+ ****************************************************************************/
+
+void *board_composite_connect(int port, int configid)
+{
+  /* Here we are composing the configuration of the usb composite device.
+   *
+   * The standard is to use one CDC/ACM and one USB mass storage device.
+   */
+
+  if (configid == 0)
+    {
+      struct composite_devdesc_s dev[2];
+      int ifnobase = 0;
+      int strbase = COMPOSITE_NSTRIDS;
+      int dev_idx = 0;
+
+#ifdef CONFIG_USBMSC_COMPOSITE
+      /* Configure the mass storage device device */
+
+      /* Ask the usbmsc driver to fill in the constants we didn't
+       * know here.
+       */
+
+      usbmsc_get_composite_devdesc(&dev[dev_idx]);
+
+      /* Overwrite and correct some values... */
+
+      /* The callback functions for the USBMSC class */
+
+      dev[dev_idx].classobject  = board_mscclassobject;
+      dev[dev_idx].uninitialize = board_mscuninitialize;
+
+      /* Interfaces */
+
+      dev[dev_idx].devinfo.ifnobase = ifnobase; /* Offset to Interface-IDs */
+      dev[dev_idx].minor = 0;                   /* The minor interface number 
*/
+
+      /* Strings */
+
+      dev[dev_idx].devinfo.strbase = strbase;   /* Offset to String Numbers */
+
+      /* Endpoints */
+
+      dev[dev_idx].devinfo.epno[USBMSC_EP_BULKIN_IDX]  = 3;
+      dev[dev_idx].devinfo.epno[USBMSC_EP_BULKOUT_IDX] = 3;
+
+      /* Count up the base numbers */
+
+      ifnobase += dev[dev_idx].devinfo.ninterfaces;
+      strbase  += dev[dev_idx].devinfo.nstrings;
+      dev_idx++;
+#endif
+
+#ifdef CONFIG_CDCACM_COMPOSITE
+      /* Configure the CDC/ACM device */
+
+      /* Ask the cdcacm driver to fill in the constants we didn't
+       * know here.
+       */
+
+      cdcacm_get_composite_devdesc(&dev[dev_idx]);
+
+      /* Overwrite and correct some values... */
+
+      /* The callback functions for the CDC/ACM class */
+
+      dev[dev_idx].classobject  = cdcacm_classobject;
+      dev[dev_idx].uninitialize = cdcacm_uninitialize;
+
+      /* Interfaces */
+
+      dev[dev_idx].devinfo.ifnobase = ifnobase; /* Offset to Interface-IDs */
+      dev[dev_idx].minor = 0;                   /* The minor interface number 
*/
+
+      /* Strings */
+
+      dev[dev_idx].devinfo.strbase = strbase;   /* Offset to String Numbers */
+
+      /* Endpoints */
+
+      dev[dev_idx].devinfo.epno[CDCACM_EP_INTIN_IDX]   = 1;
+      dev[dev_idx].devinfo.epno[CDCACM_EP_BULKIN_IDX]  = 2;
+      dev[dev_idx].devinfo.epno[CDCACM_EP_BULKOUT_IDX] = 2;
+      dev_idx++;
+#endif
+
+      return composite_initialize(dev_idx, dev);
+    }
+  else
+    {
+      return NULL;
+    }
+}
+
+#endif /* CONFIG_BOARDCTL_USBDEVCTRL && CONFIG_USBDEV_COMPOSITE */
diff --git a/boards/arm/stm32/stm32f411-minimum/src/stm32_usbmsc.c 
b/boards/arm/stm32/stm32f411-minimum/src/stm32_usbmsc.c
new file mode 100644
index 0000000000..bf742e7f9a
--- /dev/null
+++ b/boards/arm/stm32/stm32f411-minimum/src/stm32_usbmsc.c
@@ -0,0 +1,70 @@
+/****************************************************************************
+ * boards/arm/stm32/stm32f411-minimum/src/stm32_usbmsc.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdio.h>
+#include <syslog.h>
+#include <errno.h>
+
+#include <nuttx/board.h>
+
+#include "stm32.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_SYSTEM_USBMSC_DEVMINOR1
+#  define CONFIG_SYSTEM_USBMSC_DEVMINOR1 0
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_usbmsc_initialize
+ *
+ * Description:
+ *   Perform architecture specific initialization of the USB MSC device.
+ *
+ ****************************************************************************/
+
+int board_usbmsc_initialize(int port)
+{
+  /* If system/usbmsc is built as an NSH command, then SD slot should
+   * already have been initialized in board_app_initialize()
+   * (see stm32_appinit.c).
+   * In this case, there is nothing further to be done here.
+   */
+
+#ifndef CONFIG_NSH_BUILTIN_APPS
+  return stm32_w25initialize(CONFIG_SYSTEM_USBMSC_DEVMINOR1);
+#else
+  return OK;
+#endif
+}

Reply via email to