diff --git a/arch/arm/src/stm32f7/stm32_otgdev.c b/arch/arm/src/stm32f7/stm32_otgdev.c index f2f8289042..6a776976e2 100644 --- a/arch/arm/src/stm32f7/stm32_otgdev.c +++ b/arch/arm/src/stm32f7/stm32_otgdev.c @@ -2,7 +2,8 @@ * arch/arm/src/stm32f7/stm32_otgdev.c * * Copyright (C) 2012-2014, 2016 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Authors: Gregory Nutt + * David Sidrane * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -1276,7 +1277,7 @@ static void stm32_epin_request(FAR struct stm32_usbdev_s *priv, return; } - ullinfo("EP%d req=%p: len=%d xfrd=%d zlp=%d\n", + uinfo("EP%d req=%p: len=%d xfrd=%d zlp=%d\n", privep->epphy, privreq, privreq->req.len, privreq->req.xfrd, privep->zlp); @@ -1542,7 +1543,7 @@ static void stm32_epout_complete(FAR struct stm32_usbdev_s *priv, return; } - ullinfo("EP%d: len=%d xfrd=%d\n", + uinfo("EP%d: len=%d xfrd=%d\n", privep->epphy, privreq->req.len, privreq->req.xfrd); /* Return the completed read request to the class driver and mark the state @@ -1577,7 +1578,7 @@ static inline void stm32_ep0out_receive(FAR struct stm32_ep_s *privep, int bcnt) DEBUGASSERT(privep && privep->ep.priv); priv = (FAR struct stm32_usbdev_s *)privep->ep.priv; - ullinfo("EP0: bcnt=%d\n", bcnt); + uinfo("EP0: bcnt=%d\n", bcnt); usbtrace(TRACE_READ(EP0), bcnt); /* Verify that an OUT SETUP request as received before this data was @@ -1670,7 +1671,7 @@ static inline void stm32_epout_receive(FAR struct stm32_ep_s *privep, int bcnt) return; } - ullinfo("EP%d: len=%d xfrd=%d\n", privep->epphy, privreq->req.len, privreq->req.xfrd); + uinfo("EP%d: len=%d xfrd=%d\n", privep->epphy, privreq->req.len, privreq->req.xfrd); usbtrace(TRACE_READ(privep->epphy), bcnt); /* Get the number of bytes to transfer from the RxFIFO */ @@ -1754,7 +1755,7 @@ static void stm32_epout_request(FAR struct stm32_usbdev_s *priv, return; } - ullinfo("EP%d: len=%d\n", privep->epphy, privreq->req.len); + uinfo("EP%d: len=%d\n", privep->epphy, privreq->req.len); /* Ignore any attempt to receive a zero length packet (this really * should not happen. @@ -2548,7 +2549,7 @@ static inline void stm32_ep0out_setup(struct stm32_usbdev_s *priv) ctrlreq.index = GETUINT16(priv->ctrlreq.index); ctrlreq.len = GETUINT16(priv->ctrlreq.len); - ullinfo("type=%02x req=%02x value=%04x index=%04x len=%04x\n", + uinfo("type=%02x req=%02x value=%04x index=%04x len=%04x\n", ctrlreq.type, ctrlreq.req, ctrlreq.value, ctrlreq.index, ctrlreq.len); /* Check for a standard request */ @@ -2683,7 +2684,7 @@ static inline void stm32_epout_interrupt(FAR struct stm32_usbdev_s *priv) if ((daint & 1) != 0) { regval = stm32_getreg(STM32_OTG_DOEPINT(epno)); - ullerr("DOEPINT(%d) = %08x\n", epno, regval); + uerr("DOEPINT(%d) = %08x\n", epno, regval); stm32_putreg(0xFF, STM32_OTG_DOEPINT(epno)); } @@ -2913,7 +2914,7 @@ static inline void stm32_epin_interrupt(FAR struct stm32_usbdev_s *priv) { if ((daint & 1) != 0) { - ullerr("DIEPINT(%d) = %08x\n", + uerr("DIEPINT(%d) = %08x\n", epno, stm32_getreg(STM32_OTG_DIEPINT(epno))); stm32_putreg(0xFF, STM32_OTG_DIEPINT(epno)); } @@ -4393,7 +4394,7 @@ static int stm32_ep_submit(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s * if (!req || !req->callback || !req->buf || !ep) { usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDPARMS), 0); - ullinfo("req=%p callback=%p buf=%p ep=%p\n", req, req->callback, req->buf, ep); + uinfo("req=%p callback=%p buf=%p ep=%p\n", req, req->callback, req->buf, ep); return -EINVAL; } #endif diff --git a/arch/arm/src/stm32f7/stm32_otghost.c b/arch/arm/src/stm32f7/stm32_otghost.c index c6f25c6769..69ac3fbe68 100644 --- a/arch/arm/src/stm32f7/stm32_otghost.c +++ b/arch/arm/src/stm32f7/stm32_otghost.c @@ -3,6 +3,7 @@ * * Copyright (C) 2012-2016 Gregory Nutt. All rights reserved. * Authors: Gregory Nutt + * David Sidrane * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -2368,7 +2369,7 @@ static inline void stm32_gint_hcinisr(FAR struct stm32_usbhost_s *priv, /* AND the two to get the set of enabled, pending HC interrupts */ pending &= regval; - ullinfo("HCINTMSK%d: %08x pending: %08x\n", chidx, regval, pending); + uinfo("HCINTMSK%d: %08x pending: %08x\n", chidx, regval, pending); /* Check for a pending ACK response received/transmitted (ACK) interrupt */ @@ -2629,7 +2630,7 @@ static inline void stm32_gint_hcoutisr(FAR struct stm32_usbhost_s *priv, /* AND the two to get the set of enabled, pending HC interrupts */ pending &= regval; - ullinfo("HCINTMSK%d: %08x pending: %08x\n", chidx, regval, pending); + uinfo("HCINTMSK%d: %08x pending: %08x\n", chidx, regval, pending); /* Check for a pending ACK response received/transmitted (ACK) interrupt */ @@ -2947,7 +2948,7 @@ static inline void stm32_gint_rxflvlisr(FAR struct stm32_usbhost_s *priv) /* Read and pop the next status from the Rx FIFO */ grxsts = stm32_getreg(STM32_OTG_GRXSTSP); - ullinfo("GRXSTS: %08x\n", grxsts); + uinfo("GRXSTS: %08x\n", grxsts); /* Isolate the channel number/index in the status word */ @@ -3100,7 +3101,7 @@ static inline void stm32_gint_nptxfeisr(FAR struct stm32_usbhost_s *priv) /* Write the next group of packets into the Tx FIFO */ - ullinfo("HNPTXSTS: %08x chidx: %d avail: %d buflen: %d xfrd: %d wrsize: %d\n", + uinfo("HNPTXSTS: %08x chidx: %d avail: %d buflen: %d xfrd: %d wrsize: %d\n", regval, chidx, avail, chan->buflen, chan->xfrd, wrsize); stm32_gint_wrpacket(priv, chan->buffer, chidx, wrsize); @@ -3188,7 +3189,7 @@ static inline void stm32_gint_ptxfeisr(FAR struct stm32_usbhost_s *priv) /* Write the next group of packets into the Tx FIFO */ - ullinfo("HPTXSTS: %08x chidx: %d avail: %d buflen: %d xfrd: %d wrsize: %d\n", + uinfo("HPTXSTS: %08x chidx: %d avail: %d buflen: %d xfrd: %d wrsize: %d\n", regval, chidx, avail, chan->buflen, chan->xfrd, wrsize); stm32_gint_wrpacket(priv, chan->buffer, chidx, wrsize); @@ -4724,7 +4725,7 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr, /* Set the connected/disconnected flag */ hport->connected = connected; - ullinfo("Hub port %d connected: %s\n", hport->port, connected ? "YES" : "NO"); + uinfo("Hub port %d connected: %s\n", hport->port, connected ? "YES" : "NO"); /* Report the connection event */ diff --git a/arch/arm/src/stm32f7/stm32_sdmmc.c b/arch/arm/src/stm32f7/stm32_sdmmc.c index cf78614e41..e05523e46b 100644 --- a/arch/arm/src/stm32f7/stm32_sdmmc.c +++ b/arch/arm/src/stm32f7/stm32_sdmmc.c @@ -2,7 +2,8 @@ * arch/arm/src/stm32f7/stm32_sdmmc.c * * Copyright (C) 2009, 2011-2016 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Authors: Gregory Nutt + * David Sidrane * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/configs/nucleo-144/src/Makefile b/configs/nucleo-144/src/Makefile index ca3ede019c..452465e256 100644 --- a/configs/nucleo-144/src/Makefile +++ b/configs/nucleo-144/src/Makefile @@ -64,4 +64,8 @@ ifeq ($(CONFIG_MMCSD),y) CSRCS += stm32_sdio.c endif +ifeq ($(CONFIG_STM32F7_OTGFS),y) +CSRCS += stm32_usb.c +endif + include $(TOPDIR)/configs/Board.mk diff --git a/configs/nucleo-144/src/nucleo-144.h b/configs/nucleo-144/src/nucleo-144.h index e5fa337340..5aa52e4073 100644 --- a/configs/nucleo-144/src/nucleo-144.h +++ b/configs/nucleo-144/src/nucleo-144.h @@ -169,6 +169,29 @@ # endif #endif +/* USB OTG FS + * + * PA9 OTG_FS_VBUS VBUS sensing (also connected to the green LED) + * PC0 OTG_FS_PowerSwitchOn + * PD5 OTG_FS_Overcurrent + */ + +#define GPIO_OTGFS_VBUS (GPIO_INPUT|GPIO_FLOAT|GPIO_SPEED_100MHz|\ + GPIO_OPENDRAIN|GPIO_PORTA|GPIO_PIN9) + +#define GPIO_OTGFS_PWRON (GPIO_OUTPUT|GPIO_FLOAT|GPIO_SPEED_100MHz|\ + GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN6) + +#ifdef CONFIG_USBHOST +# define GPIO_OTGFS_OVER (GPIO_INPUT|GPIO_EXTI|GPIO_FLOAT|\ + GPIO_SPEED_100MHz|GPIO_PUSHPULL|\ + GPIO_PORTG|GPIO_PIN7) + +#else +# define GPIO_OTGFS_OVER (GPIO_INPUT|GPIO_FLOAT|GPIO_SPEED_100MHz|\ + GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN7) +#endif + /************************************************************************************ * Public data ************************************************************************************/ @@ -245,5 +268,19 @@ int board_adc_initialize(void); int stm32_sdio_initialize(void); #endif +/************************************************************************************ + * Name: stm32_usbinitialize + * + * Description: + * Called from stm32_usbinitialize very early in inialization to setup USB-related + * GPIO pins for the nucleo-144 board. + * + ************************************************************************************/ + + +#ifdef CONFIG_STM32F7_OTGFS +void stm32_usbinitialize(void); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __CONFIGS_NUCLEO_144_SRC_NUCLEO_144_H */ diff --git a/configs/nucleo-144/src/stm32_boot.c b/configs/nucleo-144/src/stm32_boot.c index 6e767a2975..684ade8176 100644 --- a/configs/nucleo-144/src/stm32_boot.c +++ b/configs/nucleo-144/src/stm32_boot.c @@ -70,6 +70,10 @@ void stm32_boardinitialize(void) board_autoled_initialize(); #endif +#if defined(CONFIG_STM32F7_OTGFS) || defined(CONFIG_STM32F7_HOST) + stm32_usbinitialize(); +#endif + #if defined(CONFIG_SPI) /* Configure SPI chip selects */ diff --git a/configs/nucleo-144/src/stm32_usb.c b/configs/nucleo-144/src/stm32_usb.c new file mode 100644 index 0000000000..1cb422a78c --- /dev/null +++ b/configs/nucleo-144/src/stm32_usb.c @@ -0,0 +1,329 @@ +/************************************************************************************ + * configs//nucleo-144/src/stm32_usb.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * David Sidrane + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "up_arch.h" +#include "chip.h" +#include "stm32_gpio.h" +#include "stm32_otg.h" +#include "nucleo-144.h" + +#ifdef CONFIG_STM32F7_OTGFS + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#if defined(CONFIG_USBDEV) || defined(CONFIG_USBHOST) +# define HAVE_USB 1 +#else +# warning "CONFIG_STM32_OTGFS is enabled but neither CONFIG_USBDEV nor CONFIG_USBHOST" +# undef HAVE_USB +#endif + +#ifndef CONFIG_NUCLEO144_USBHOST_PRIO +# define CONFIG_NUCLEO144_USBHOST_PRIO 100 +#endif + +#ifndef CONFIG_NUCLEO_USBHOST_STACKSIZE +# define CONFIG_NUCLEO_USBHOST_STACKSIZE 1024 +#endif + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +#ifdef CONFIG_USBHOST +static struct usbhost_connection_s *g_usbconn; +#endif + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: usbhost_waiter + * + * Description: + * Wait for USB devices to be connected. + * + ************************************************************************************/ + +#ifdef CONFIG_USBHOST +static int usbhost_waiter(int argc, char *argv[]) +{ + struct usbhost_hubport_s *hport; + + uinfo("Running\n"); + for (;;) + { + /* Wait for the device to change state */ + + DEBUGVERIFY(CONN_WAIT(g_usbconn, &hport)); + uinfo("%s\n", hport->connected ? "connected" : "disconnected"); + + /* Did we just become connected? */ + + if (hport->connected) + { + /* Yes.. enumerate the newly connected device */ + + (void)CONN_ENUMERATE(g_usbconn, hport); + } + } + + /* Keep the compiler from complaining */ + + return 0; +} +#endif + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_usbinitialize + * + * Description: + * Called from stm32_usbinitialize very early in inialization to setup USB-related + * GPIO pins for the nucleo-144 board. + * + ************************************************************************************/ + +void stm32_usbinitialize(void) +{ + /* The OTG FS has an internal soft pull-up. No GPIO configuration is required */ + + /* Configure the OTG FS VBUS sensing GPIO, Power On, and Overcurrent GPIOs */ + +#ifdef CONFIG_STM32F7_OTGFS + stm32_configgpio(GPIO_OTGFS_VBUS); + stm32_configgpio(GPIO_OTGFS_PWRON); + stm32_configgpio(GPIO_OTGFS_OVER); +#endif +} + +/*********************************************************************************** + * Name: stm32_usbhost_initialize + * + * Description: + * Called at application startup time to initialize the USB host functionality. + * This function will start a thread that will monitor for device + * connection/disconnection events. + * + ***********************************************************************************/ + +#ifdef CONFIG_USBHOST +int stm32_usbhost_initialize(void) +{ + int pid; +#if defined(CONFIG_USBHOST_HUB) || defined(CONFIG_USBHOST_MSC) || \ + defined(CONFIG_USBHOST_HIDKBD) || defined(CONFIG_USBHOST_HIDMOUSE) + int ret; +#endif + + /* First, register all of the class drivers needed to support the drivers + * that we care about: + */ + + uinfo("Register class drivers\n"); + +#ifdef CONFIG_USBHOST_HUB + /* Initialize USB hub class support */ + + ret = usbhost_hub_initialize(); + if (ret < 0) + { + uerr("ERROR: usbhost_hub_initialize failed: %d\n", ret); + } +#endif + +#ifdef CONFIG_USBHOST_MSC + /* Register the USB mass storage class class */ + + ret = usbhost_msc_initialize(); + if (ret != OK) + { + uerr("ERROR: Failed to register the mass storage class: %d\n", ret); + } +#endif + +#ifdef CONFIG_USBHOST_CDCACM + /* Register the CDC/ACM serial class */ + + ret = usbhost_cdcacm_initialize(); + if (ret != OK) + { + uerr("ERROR: Failed to register the CDC/ACM serial class: %d\n", ret); + } +#endif + +#ifdef CONFIG_USBHOST_HIDKBD + /* Initialize the HID keyboard class */ + + ret = usbhost_kbdinit(); + if (ret != OK) + { + uerr("ERROR: Failed to register the HID keyboard class\n"); + } +#endif + +#ifdef CONFIG_USBHOST_HIDMOUSE + /* Initialize the HID mouse class */ + + ret = usbhost_mouse_init(); + if (ret != OK) + { + uerr("ERROR: Failed to register the HID mouse class\n"); + } +#endif + + /* Then get an instance of the USB host interface */ + + uinfo("Initialize USB host\n"); + g_usbconn = stm32_otgfshost_initialize(0); + if (g_usbconn) + { + /* Start a thread to handle device connection. */ + + uinfo("Start usbhost_waiter\n"); + + pid = task_create("usbhost", CONFIG_STM32F4DISCO_USBHOST_PRIO, + CONFIG_STM32F4DISCO_USBHOST_STACKSIZE, + (main_t)usbhost_waiter, (FAR char * const *)NULL); + return pid < 0 ? -ENOEXEC : OK; + } + + return -ENODEV; +} +#endif + +/*********************************************************************************** + * Name: stm32_usbhost_vbusdrive + * + * Description: + * Enable/disable driving of VBUS 5V output. This function must be provided be + * each platform that implements the STM32 OTG FS host interface + * + * "On-chip 5 V VBUS generation is not supported. For this reason, a charge pump + * or, if 5 V are available on the application board, a basic power switch, must + * be added externally to drive the 5 V VBUS line. The external charge pump can + * be driven by any GPIO output. When the application decides to power on VBUS + * using the chosen GPIO, it must also set the port power bit in the host port + * control and status register (PPWR bit in OTG_FS_HPRT). + * + * "The application uses this field to control power to this port, and the core + * clears this bit on an overcurrent condition." + * + * Input Parameters: + * iface - For future growth to handle multiple USB host interface. Should be zero. + * enable - true: enable VBUS power; false: disable VBUS power + * + * Returned Value: + * None + * + ***********************************************************************************/ + +#ifdef CONFIG_USBHOST +void stm32_usbhost_vbusdrive(int iface, bool enable) +{ + DEBUGASSERT(iface == 0); + + /* Set the Power Switch by driving the active low enable pin */ + + stm32_gpiowrite(GPIO_OTGFS_PWRON, !enable); +} +#endif + +/************************************************************************************ + * Name: stm32_setup_overcurrent + * + * Description: + * Setup to receive an interrupt-level callback if an overcurrent condition is + * detected. + * + * Input Parameter: + * handler - New overcurrent interrupt handler + * + * Returned value: + * Old overcurrent interrupt handler + * + ************************************************************************************/ + +#ifdef CONFIG_USBHOST +xcpt_t stm32_setup_overcurrent(xcpt_t handler) +{ + return stm32_gpiosetevent(GPIO_OTGFS_OVER, true, true, true, handler); +} +#endif + +/************************************************************************************ + * Name: stm32_usbsuspend + * + * Description: + * Board logic must provide the stm32_usbsuspend logic if the USBDEV driver is + * used. This function is called whenever the USB enters or leaves suspend mode. + * This is an opportunity for the board logic to shutdown clocks, power, etc. + * while the USB is suspended. + * + ************************************************************************************/ + +#ifdef CONFIG_USBDEV +void stm32_usbsuspend(FAR struct usbdev_s *dev, bool resume) +{ + uinfo("resume: %d\n", resume); +} +#endif + +#endif /* CONFIG_STM32_OTGFS */