From 21d87c3afb3679880939b5977fdf007000fc0329 Mon Sep 17 00:00:00 2001 From: alexrayne Date: Sat, 4 Feb 2017 12:52:17 +0200 Subject: [PATCH 1/8] +common:regs:dwc - append some USB FS power and session control bits definition to DWC_OTG_GOTGINT, DWC_OTG_PCGCCTL --- include/unicore-mx/common/dwc_otg.ucd | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/unicore-mx/common/dwc_otg.ucd b/include/unicore-mx/common/dwc_otg.ucd index 2ce16e35..1c9bb653 100644 --- a/include/unicore-mx/common/dwc_otg.ucd +++ b/include/unicore-mx/common/dwc_otg.ucd @@ -56,6 +56,9 @@ bit SRQ 1 bit SRQSCS 0 reg GOTGINT 0x004 +% Session end detected. The core sets this bit to indicate that the level of the voltage +% on VBUS is no longer valid for a B-Peripheral session when VBUS < 0.8 V //STM32F4 +bit SEDET 2 % OTG AHB configuration register reg GAHBCFG 0x008 @@ -847,6 +850,16 @@ bits XFRSIZ 7 0 % Power and clock gating control and status register reg PCGCCTL 0xE00 +% Stop PHY clock. The application sets this bit to stop the PHY clock when the USB is suspended, the session +% is not valid, or the device is disconnected. +% The application clears this bit when the USB is resumed or a new session starts //STM32F4 +bit STPPCLK 0 +% Gate HCLK. The application sets this bit to gate HCLK to modules other than the AHB Slave and Master +% and wakeup logic when the USB is suspended or the session is not valid. +% The application clears this bit when the USB is resumed or a new session starts. //STM32F4 +bit GATEHCLK 1 +% Indicates that the PHY has been suspended. +bit PHYSUSP 4 % Data FIFO register From 84012d3afb78edd866ea3bec419948c68bf9e091 Mon Sep 17 00:00:00 2001 From: alexrayne Date: Sat, 4 Feb 2017 12:55:35 +0200 Subject: [PATCH 2/8] +usbd:session callback - add this handle on session start/stop events. it intends to handle cable connetion, Vbus powering + usbd_register_session_callback + :usbd_backend:is_vbus, power_control - add this methods to provide VBus status, and USBcore powering control + usbd_is_vbus, usbd_enable - this methods invokes backend power controls + usbd_stm32_otg_fs:otgfs_is_powered, otgfs_power_control - implements above controls of stm32f4xx FS core --- include/unicore-mx/usbd/usbd.h | 28 +++++++++++++++++++++++ lib/usbd/backend/dwc_otg_private.h | 1 + lib/usbd/backend/usbd_dwc_otg.c | 9 ++++++++ lib/usbd/backend/usbd_stm32_otg_fs.c | 34 ++++++++++++++++++++++++++-- lib/usbd/usbd.c | 21 +++++++++++++++++ lib/usbd/usbd_private.h | 22 ++++++++++++++++++ 6 files changed, 113 insertions(+), 2 deletions(-) diff --git a/include/unicore-mx/usbd/usbd.h b/include/unicore-mx/usbd/usbd.h index 53df4d99..95c0ff04 100644 --- a/include/unicore-mx/usbd/usbd.h +++ b/include/unicore-mx/usbd/usbd.h @@ -431,6 +431,8 @@ typedef void (*usbd_set_interface_callback)(usbd_device *dev, typedef void (*usbd_setup_callback)(usbd_device *dev, uint8_t addr, const struct usb_setup_data *setup_data); +typedef void (* usbd_session_callback)(usbd_device *dev, bool online); + typedef void (* usbd_generic_callback)(usbd_device *dev); /** @@ -515,6 +517,16 @@ void usbd_register_resume_callback(usbd_device *dev, void usbd_register_sof_callback(usbd_device *dev, usbd_generic_callback callback); +/** + * Register session connect/disconnect callback + * with USBD_VBUS_SENSE feature primary need for cable + * plug detection + * @param[in] dev USB Device + * @param[in] callback callback to be invoked + */ +void usbd_register_session_callback(usbd_device *dev, + usbd_session_callback callback); + /** * Register SET_CONFIGURATION callback \n * stack will invoke @a callback when ever SET_CONFIGURATION is received @@ -643,6 +655,22 @@ uint8_t usbd_get_address(usbd_device *dev); */ usbd_speed usbd_get_speed(usbd_device *dev); + +/** + * Get status of connected cable. + * @param[in] dev USB Device + * @return true - cable connected, and Vbus active + */ +bool usbd_is_vbus(usbd_device *dev); + +/** + * Controls power state of usb-core and PHY + * @param[in] dev USB Device + * @param[in] onoff - true turn on device in action, and power PHY + * false disable PHY and stops usb-core + */ +void usbd_enable(usbd_device *dev, bool onoff); + /** * Perform a transfer * diff --git a/lib/usbd/backend/dwc_otg_private.h b/lib/usbd/backend/dwc_otg_private.h index e1a1f247..2b181233 100644 --- a/lib/usbd/backend/dwc_otg_private.h +++ b/lib/usbd/backend/dwc_otg_private.h @@ -88,6 +88,7 @@ struct dwc_otg_private_data { #define USBD_DEVICE_EXTRA \ struct dwc_otg_private_data private_data; +//#include "../usbd_private.h" void dwc_otg_init(usbd_device *dev); void dwc_otg_set_address(usbd_device *dev, uint8_t addr); diff --git a/lib/usbd/backend/usbd_dwc_otg.c b/lib/usbd/backend/usbd_dwc_otg.c index ebb42f89..e3f1a8b3 100644 --- a/lib/usbd/backend/usbd_dwc_otg.c +++ b/lib/usbd/backend/usbd_dwc_otg.c @@ -1042,6 +1042,15 @@ void dwc_otg_poll(usbd_device *dev) REBASE(DWC_OTG_GINTSTS) = DWC_OTG_GINTSTS_SOF; usbd_handle_sof(dev); } + + if ( (REBASE(DWC_OTG_GINTSTS) & (DWC_OTG_GINTSTS_SRQINT)) != 0) { + REBASE(DWC_OTG_GINTSTS) = (DWC_OTG_GINTSTS_SRQINT); + usbd_handle_session(dev, true); + } + if ( (REBASE(DWC_OTG_GOTGINT) & (DWC_OTG_GOTGINT_SEDET)) != 0) { + REBASE(DWC_OTG_GOTGINT) = DWC_OTG_GOTGINT_SEDET; + usbd_handle_session(dev, false); + } } void dwc_otg_disconnect(usbd_device *dev, bool disconnected) diff --git a/lib/usbd/backend/usbd_stm32_otg_fs.c b/lib/usbd/backend/usbd_stm32_otg_fs.c index 24eb754f..a50d47e3 100644 --- a/lib/usbd/backend/usbd_stm32_otg_fs.c +++ b/lib/usbd/backend/usbd_stm32_otg_fs.c @@ -28,6 +28,8 @@ #include static usbd_device *init(const usbd_backend_config *config); +static bool otgfs_is_powered(usbd_device *dev); +static void otgfs_power_control(usbd_device *dev, usbd_power_action action); static struct usbd_device _usbd_dev; @@ -51,6 +53,8 @@ const struct usbd_backend usbd_stm32_otg_fs = { .get_speed = dwc_otg_get_speed, .set_address_before_status = true, .base_address = USB_OTG_FS_BASE, + .is_vbus = otgfs_is_powered + , .power_control = otgfs_power_control }; #define REBASE(REG, ...) REG(usbd_stm32_otg_fs.base_address, ##__VA_ARGS__) @@ -75,10 +79,10 @@ static usbd_device *init(const usbd_backend_config *config) _usbd_dev.config = config; if (config->feature & USBD_VBUS_SENSE) { - if (OTG_FS_CID >= 0x00002000) { /* 2.0 */ + if (OTG_FS_CID >= 0x00002000) { /* 2.0 HS core*/ /* Enable VBUS detection */ OTG_FS_GCCFG |= OTG_GCCFG_VBDEN; - } else { /* 1.x */ + } else { /* 1.x FS core*/ /* Enable VBUS sensing in device mode */ OTG_FS_GCCFG |= OTG_GCCFG_VBUSBSEN; } @@ -108,3 +112,29 @@ static usbd_device *init(const usbd_backend_config *config) return &_usbd_dev; } + +static +bool otgfs_is_powered(usbd_device *dev){ + uint32_t base = dev->backend->base_address; + return (DWC_OTG_GOTGCTL(base) & DWC_OTG_GOTGCTL_BSVLD) != 0; +} + +static +void otgfs_power_control(usbd_device *dev, usbd_power_action action){ + uint32_t base = dev->backend->base_address; + switch (action){ + case usbd_paActivate:{ + DWC_OTG_PCGCCTL(base) = 0; + OTG_FS_GCCFG |= OTG_GCCFG_PWRDWN; + break; + } + case usbd_paShutdown: { + /* Wait for AHB idle. */ + while (( (DWC_OTG_GRSTCTL(base) & DWC_OTG_GRSTCTL_AHBIDL) == 0) ); + //poser down PHY + OTG_FS_GCCFG &= ~OTG_GCCFG_PWRDWN; + DWC_OTG_PCGCCTL(base) = DWC_OTG_PCGCCTL_STPPCLK; //| DWC_OTG_PCGCCTL_GATEHCLK ; + break; + } + } +} diff --git a/lib/usbd/usbd.c b/lib/usbd/usbd.c index cd382b91..6bf7008d 100644 --- a/lib/usbd/usbd.c +++ b/lib/usbd/usbd.c @@ -128,6 +128,14 @@ void usbd_register_sof_callback(usbd_device *dev, } } +void usbd_register_session_callback(usbd_device *dev, + usbd_session_callback callback) +{ + dev->callback.session = callback; +} + + + /* Functions to be provided by the hardware abstraction layer */ void usbd_poll(usbd_device *dev, uint32_t us) { @@ -208,5 +216,18 @@ usbd_speed usbd_get_speed(usbd_device *dev) return dev->backend->get_speed(dev); } +bool usbd_is_vbus(usbd_device *dev){ + if (dev->backend->is_vbus) + return dev->backend->is_vbus(dev); + else + return true; +} + +void usbd_enable(usbd_device *dev, bool onoff){ + if (dev->backend->power_control) + dev->backend->power_control(dev, (onoff)? usbd_paActivate : usbd_paShutdown ); +} + + /**@}*/ diff --git a/lib/usbd/usbd_private.h b/lib/usbd/usbd_private.h index 6b7ddcfd..1ccf4fd9 100644 --- a/lib/usbd/usbd_private.h +++ b/lib/usbd/usbd_private.h @@ -41,6 +41,7 @@ #ifndef UNICOREMX_USBD_PRIVATE_H #define UNICOREMX_USBD_PRIVATE_H +#include #include /** @@ -109,6 +110,10 @@ struct usbd_device { /** invoked when sof received */ usbd_generic_callback sof; + + //* invoked on Session New / End + //* with USBD_VBUS_SENSE feature detects cable plug + usbd_session_callback session; /** invoked on SETUP packet */ usbd_setup_callback setup; @@ -174,6 +179,11 @@ struct usbd_device { #endif }; +typedef enum { + usbd_paShutdown + , usbd_paActivate +} usbd_power_action; + /* Functions provided by the hardware abstraction. */ struct usbd_backend { usbd_device * (*init)(const usbd_backend_config *config); @@ -197,6 +207,10 @@ struct usbd_backend { /* Frame number */ uint16_t (*frame_number)(usbd_device *dev); + //* power control + bool (*is_vbus)(usbd_device *dev); + void (*power_control)(usbd_device *dev, usbd_power_action action); + /* * this is to tell usb generic code * that address need to be set before status-stage. @@ -359,6 +373,14 @@ static inline void usbd_handle_sof(usbd_device *dev) } } +static inline +void usbd_handle_session(usbd_device *dev, bool onoff) +{ + if (dev->callback.session != NULL) { + dev->callback.session(dev, onoff); + } +} + /** * Called by backend to pass the setup data when a SETUP packet is recevied * on control endpoint. From 65231b03f0cc403a18579bd1d73be8d7407c0110 Mon Sep 17 00:00:00 2001 From: alexrayne Date: Mon, 20 Feb 2017 23:44:15 +0300 Subject: [PATCH 3/8] *usbd:session - fixed code style, linked disconnect and enablevia feature.USBD_USE_POWERDOWN * warns - fixed some compiler warnings about mixing enum as integer --- include/unicore-mx/usbd/usbd.h | 21 +++++++++++++-------- lib/usbd/usbd.c | 12 ++++++++++++ lib/usbd/usbd_private.h | 5 +++-- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/include/unicore-mx/usbd/usbd.h b/include/unicore-mx/usbd/usbd.h index 95c0ff04..956799e5 100644 --- a/include/unicore-mx/usbd/usbd.h +++ b/include/unicore-mx/usbd/usbd.h @@ -135,6 +135,16 @@ enum usbd_speed { typedef enum usbd_speed usbd_speed; + /** Optional features */ +enum usbd_backend_features{ + USBD_FEATURE_NONE = 0, + USBD_PHY_EXT = (1 << 0), + USBD_VBUS_SENSE = (1 << 1), + USBD_VBUS_EXT = (1 << 2) + //* provide usb-core auto power-up/down on connect/disconnect + , USBD_USE_POWERDOWN = (1<<3) +}; + struct usbd_backend_config { /** Number of endpoints. (Including control endpoint) */ uint8_t ep_count; @@ -145,13 +155,8 @@ struct usbd_backend_config { /** Device speed */ usbd_speed speed; - /** Optional features */ - enum { - USBD_FEATURE_NONE = 0, - USBD_PHY_EXT = (1 << 0), - USBD_VBUS_SENSE = (1 << 1), - USBD_VBUS_EXT = (1 << 2) - } feature; + /** Optional features see usbd_backend_features*/ + unsigned int feature; }; typedef struct usbd_backend_config usbd_backend_config; @@ -279,7 +284,7 @@ enum usbd_transfer_flags { USBD_FLAG_PACKET_PER_FRAME_MASK = (0x3 << 5) }; -typedef enum usbd_transfer_flags usbd_transfer_flags; +typedef unsigned char usbd_transfer_flags; /** * USB Transfer status diff --git a/lib/usbd/usbd.c b/lib/usbd/usbd.c index 6bf7008d..ffabd543 100644 --- a/lib/usbd/usbd.c +++ b/lib/usbd/usbd.c @@ -153,9 +153,19 @@ void usbd_poll(usbd_device *dev, uint32_t us) void usbd_disconnect(usbd_device *dev, bool disconnect) { + if (!disconnect) { + // power-up on connect + if ((dev->config->feature & USBD_USE_POWERDOWN) != 0) + usbd_enable(dev, true); + } if (dev->backend->disconnect) { dev->backend->disconnect(dev, disconnect); } + if (disconnect) { + // power-down after disconnect + if ((dev->config->feature & USBD_USE_POWERDOWN) != 0) + usbd_enable(dev, false); + } } void usbd_ep_prepare(usbd_device *dev, uint8_t addr, usbd_ep_type type, @@ -224,6 +234,8 @@ bool usbd_is_vbus(usbd_device *dev){ } void usbd_enable(usbd_device *dev, bool onoff){ + if (!onoff) + usbd_disconnect(dev, false); if (dev->backend->power_control) dev->backend->power_control(dev, (onoff)? usbd_paActivate : usbd_paShutdown ); } diff --git a/lib/usbd/usbd_private.h b/lib/usbd/usbd_private.h index 1ccf4fd9..1add1ac9 100644 --- a/lib/usbd/usbd_private.h +++ b/lib/usbd/usbd_private.h @@ -179,10 +179,11 @@ struct usbd_device { #endif }; -typedef enum { +enum _usbd_power_action{ usbd_paShutdown , usbd_paActivate -} usbd_power_action; +}; +typedef enum _usbd_power_action usbd_power_action; /* Functions provided by the hardware abstraction. */ struct usbd_backend { From 56241720032d1d0e587dacfb67a095f13cd7a9be Mon Sep 17 00:00:00 2001 From: alexrayne Date: Wed, 24 May 2017 12:46:00 +0200 Subject: [PATCH 4/8] !usbd:session:usbd_enable - fixed disconnection on disabling ! :otg init:HS detection - now valid detection of HS core stm32F4 and F7 ! - fixed code style --- include/unicore-mx/usbd/usbd.h | 10 +++++----- lib/usbd/backend/usbd_stm32_otg_fs.c | 8 ++++++-- lib/usbd/usbd.c | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/unicore-mx/usbd/usbd.h b/include/unicore-mx/usbd/usbd.h index 956799e5..65ecf015 100644 --- a/include/unicore-mx/usbd/usbd.h +++ b/include/unicore-mx/usbd/usbd.h @@ -137,12 +137,12 @@ typedef enum usbd_speed usbd_speed; /** Optional features */ enum usbd_backend_features{ - USBD_FEATURE_NONE = 0, - USBD_PHY_EXT = (1 << 0), - USBD_VBUS_SENSE = (1 << 1), - USBD_VBUS_EXT = (1 << 2) + USBD_FEATURE_NONE = 0 + , USBD_PHY_EXT = (1 << 0) + , USBD_VBUS_SENSE = (1 << 1) + , USBD_VBUS_EXT = (1 << 2) //* provide usb-core auto power-up/down on connect/disconnect - , USBD_USE_POWERDOWN = (1<<3) + , USBD_USE_POWERDOWN = (1 << 3) }; struct usbd_backend_config { diff --git a/lib/usbd/backend/usbd_stm32_otg_fs.c b/lib/usbd/backend/usbd_stm32_otg_fs.c index a50d47e3..1172f70e 100644 --- a/lib/usbd/backend/usbd_stm32_otg_fs.c +++ b/lib/usbd/backend/usbd_stm32_otg_fs.c @@ -78,8 +78,12 @@ static usbd_device *init(const usbd_backend_config *config) _usbd_dev.backend = &usbd_stm32_otg_fs; _usbd_dev.config = config; + //* stm32f4 use FS CID=0x1100, HS CID=0x02000600 + //* stm32f7 0x3000, CID=0x00003100 + const unsigned otg_hs_cid_boundary = 0x3000; + if (config->feature & USBD_VBUS_SENSE) { - if (OTG_FS_CID >= 0x00002000) { /* 2.0 HS core*/ + if (OTG_FS_CID >= otg_hs_cid_boundary) { /* 2.0 HS core*/ /* Enable VBUS detection */ OTG_FS_GCCFG |= OTG_GCCFG_VBDEN; } else { /* 1.x FS core*/ @@ -87,7 +91,7 @@ static usbd_device *init(const usbd_backend_config *config) OTG_FS_GCCFG |= OTG_GCCFG_VBUSBSEN; } } else { - if (OTG_FS_CID >= 0x00002000) { /* 2.0 */ + if (OTG_FS_CID >= otg_hs_cid_boundary) { /* 2.0 */ /* Disable VBUS detection. */ OTG_FS_GCCFG &= ~OTG_GCCFG_VBDEN; REBASE(DWC_OTG_GOTGCTL) |= DWC_OTG_GOTGCTL_BVALOEN | diff --git a/lib/usbd/usbd.c b/lib/usbd/usbd.c index ffabd543..6ad10685 100644 --- a/lib/usbd/usbd.c +++ b/lib/usbd/usbd.c @@ -235,7 +235,7 @@ bool usbd_is_vbus(usbd_device *dev){ void usbd_enable(usbd_device *dev, bool onoff){ if (!onoff) - usbd_disconnect(dev, false); + usbd_disconnect(dev, true); if (dev->backend->power_control) dev->backend->power_control(dev, (onoff)? usbd_paActivate : usbd_paShutdown ); } From c1cda4f605491ec580c0dfd05d7ffa2846cb8d80 Mon Sep 17 00:00:00 2001 From: alexrayne Date: Wed, 24 May 2017 13:06:40 +0200 Subject: [PATCH 5/8] =?UTF-8?q?+usbd:is=5Fenabled=20-=20enhanse=20usbd=5Fb?= =?UTF-8?q?ackend.power=5Fcontrol=20to=20allow=20core=20status=20check=20*?= =?UTF-8?q?dwc=5Fotg:poll=20-=20poll=20skips=20most=20work=20=D1=88=D0=B0?= =?UTF-8?q?=20core=20powered=20off?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/unicore-mx/usbd/usbd.h | 8 ++++++++ lib/usbd/backend/usbd_dwc_otg.c | 20 +++++++++++++++----- lib/usbd/backend/usbd_stm32_otg_fs.c | 20 ++++++++++++++++++-- lib/usbd/usbd.c | 7 +++++++ lib/usbd/usbd_private.h | 14 ++++++++++++-- 5 files changed, 60 insertions(+), 9 deletions(-) diff --git a/include/unicore-mx/usbd/usbd.h b/include/unicore-mx/usbd/usbd.h index 65ecf015..26810057 100644 --- a/include/unicore-mx/usbd/usbd.h +++ b/include/unicore-mx/usbd/usbd.h @@ -676,6 +676,14 @@ bool usbd_is_vbus(usbd_device *dev); */ void usbd_enable(usbd_device *dev, bool onoff); +/** + * Checks power state of usb-core and PHY + * @param[in] dev USB Device + * @param[in] \return true - device in action, and power PHY + * false - disabled PHY and stops usb-core + */ +bool usbd_is_enabled(usbd_device *dev); + /** * Perform a transfer * diff --git a/lib/usbd/backend/usbd_dwc_otg.c b/lib/usbd/backend/usbd_dwc_otg.c index e3f1a8b3..c2b21a3a 100644 --- a/lib/usbd/backend/usbd_dwc_otg.c +++ b/lib/usbd/backend/usbd_dwc_otg.c @@ -979,6 +979,8 @@ static inline void alloc_fifo_for_ep0_only(usbd_device *dev) void dwc_otg_poll(usbd_device *dev) { + if (usbd_is_enabled(dev)){ + if (REBASE(DWC_OTG_GINTSTS) & DWC_OTG_GINTSTS_ENUMDNE) { REBASE(DWC_OTG_DCFG) &= ~DWC_OTG_DCFG_DAD_MASK; disable_all_non_ep0(dev); @@ -1033,16 +1035,24 @@ void dwc_otg_poll(usbd_device *dev) usbd_handle_suspend(dev); } - if (REBASE(DWC_OTG_GINTSTS) & DWC_OTG_GINTSTS_WKUPINT) { - REBASE(DWC_OTG_GINTSTS) = DWC_OTG_GINTSTS_WKUPINT; - usbd_handle_resume(dev); - } - if (REBASE(DWC_OTG_GINTSTS) & DWC_OTG_GINTSTS_SOF) { REBASE(DWC_OTG_GINTSTS) = DWC_OTG_GINTSTS_SOF; usbd_handle_sof(dev); } + } //if (usbd_is_enabled(dev)) + else + REBASE(DWC_OTG_GINTSTS) = DWC_OTG_GINTSTS_ENUMDNE | DWC_OTG_GINTSTS_USBRST + | DWC_OTG_GINTSTS_RXFLVL + | DWC_OTG_GINTSTS_IEPINT | DWC_OTG_GINTSTS_OEPINT + | DWC_OTG_GINTSTS_SOF + | DWC_OTG_GINTSTS_USBSUSP | DWC_OTG_GINTSTS_ESUSP; + + if (REBASE(DWC_OTG_GINTSTS) & DWC_OTG_GINTSTS_WKUPINT) { + REBASE(DWC_OTG_GINTSTS) = DWC_OTG_GINTSTS_WKUPINT; + usbd_handle_resume(dev); + } + if ( (REBASE(DWC_OTG_GINTSTS) & (DWC_OTG_GINTSTS_SRQINT)) != 0) { REBASE(DWC_OTG_GINTSTS) = (DWC_OTG_GINTSTS_SRQINT); usbd_handle_session(dev, true); diff --git a/lib/usbd/backend/usbd_stm32_otg_fs.c b/lib/usbd/backend/usbd_stm32_otg_fs.c index 1172f70e..432aa8bd 100644 --- a/lib/usbd/backend/usbd_stm32_otg_fs.c +++ b/lib/usbd/backend/usbd_stm32_otg_fs.c @@ -29,7 +29,7 @@ static usbd_device *init(const usbd_backend_config *config); static bool otgfs_is_powered(usbd_device *dev); -static void otgfs_power_control(usbd_device *dev, usbd_power_action action); +static usbd_power_status otgfs_power_control(usbd_device *dev, usbd_power_action action); static struct usbd_device _usbd_dev; @@ -124,21 +124,37 @@ bool otgfs_is_powered(usbd_device *dev){ } static -void otgfs_power_control(usbd_device *dev, usbd_power_action action){ +usbd_power_status otgfs_power_control(usbd_device *dev, usbd_power_action action){ uint32_t base = dev->backend->base_address; switch (action){ case usbd_paActivate:{ DWC_OTG_PCGCCTL(base) = 0; OTG_FS_GCCFG |= OTG_GCCFG_PWRDWN; + REBASE(DWC_OTG_GINTMSK) |= DWC_OTG_GINTMSK_ENUMDNEM | DWC_OTG_GINTSTS_USBSUSP + | DWC_OTG_GINTMSK_RXFLVLM | DWC_OTG_GINTMSK_IEPINT ; break; } case usbd_paShutdown: { /* Wait for AHB idle. */ while (( (DWC_OTG_GRSTCTL(base) & DWC_OTG_GRSTCTL_AHBIDL) == 0) ); + //* drop ISRs, cause stoped Core cant handle them + REBASE(DWC_OTG_GINTSTS) = ~( DWC_OTG_GINTSTS_USBSUSP + | DWC_OTG_GINTSTS_WKUPINT + | DWC_OTG_GINTSTS_SRQINT + ); + REBASE(DWC_OTG_GINTMSK) &= ~( DWC_OTG_GINTMSK_ENUMDNEM + | DWC_OTG_GINTMSK_RXFLVLM | DWC_OTG_GINTMSK_IEPINT + ); //poser down PHY OTG_FS_GCCFG &= ~OTG_GCCFG_PWRDWN; DWC_OTG_PCGCCTL(base) = DWC_OTG_PCGCCTL_STPPCLK; //| DWC_OTG_PCGCCTL_GATEHCLK ; break; } } + usbd_power_status res = 0; + if ( (DWC_OTG_PCGCCTL(base) & DWC_OTG_PCGCCTL_PHYSUSP) == 0) + res |= usbd_psPHYOn; + if ((OTG_FS_GCCFG & OTG_GCCFG_PWRDWN) != 0) + res |= usbd_psCoreEnabled; + return res; } diff --git a/lib/usbd/usbd.c b/lib/usbd/usbd.c index 6ad10685..e3f67d82 100644 --- a/lib/usbd/usbd.c +++ b/lib/usbd/usbd.c @@ -240,6 +240,13 @@ void usbd_enable(usbd_device *dev, bool onoff){ dev->backend->power_control(dev, (onoff)? usbd_paActivate : usbd_paShutdown ); } +bool usbd_is_enabled(usbd_device *dev){ + if (dev->backend->power_control) + return dev->backend->power_control(dev, usbd_paCheck ) == usbd_psOn; + else + return true; +} + /**@}*/ diff --git a/lib/usbd/usbd_private.h b/lib/usbd/usbd_private.h index 1add1ac9..d0f99163 100644 --- a/lib/usbd/usbd_private.h +++ b/lib/usbd/usbd_private.h @@ -180,10 +180,20 @@ struct usbd_device { }; enum _usbd_power_action{ - usbd_paShutdown + usbd_paCheck + , usbd_paShutdown , usbd_paActivate }; +enum _usbd_power_status{ + usbd_psCoreDisabled = 0 + , usbd_psCoreEnabled = 1 + , usbd_psPHYOff = 0 + , usbd_psPHYOn = 2 + , usbd_psOff = 0 + , usbd_psOn = usbd_psCoreEnabled | usbd_psPHYOn // ~0 +}; typedef enum _usbd_power_action usbd_power_action; +typedef unsigned usbd_power_status; /* Functions provided by the hardware abstraction. */ struct usbd_backend { @@ -210,7 +220,7 @@ struct usbd_backend { //* power control bool (*is_vbus)(usbd_device *dev); - void (*power_control)(usbd_device *dev, usbd_power_action action); + usbd_power_status (*power_control)(usbd_device *dev, usbd_power_action action); /* * this is to tell usb generic code From 114158f8b90d16cd6ff840e1d4ce9353ca73a6af Mon Sep 17 00:00:00 2001 From: alexrayne Date: Wed, 24 May 2017 15:27:58 +0200 Subject: [PATCH 6/8] !usbd:otg init:HS detection - valid CID for stm32f7 --- lib/usbd/backend/usbd_stm32_otg_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/usbd/backend/usbd_stm32_otg_fs.c b/lib/usbd/backend/usbd_stm32_otg_fs.c index 432aa8bd..b3312573 100644 --- a/lib/usbd/backend/usbd_stm32_otg_fs.c +++ b/lib/usbd/backend/usbd_stm32_otg_fs.c @@ -80,7 +80,7 @@ static usbd_device *init(const usbd_backend_config *config) //* stm32f4 use FS CID=0x1100, HS CID=0x02000600 //* stm32f7 0x3000, CID=0x00003100 - const unsigned otg_hs_cid_boundary = 0x3000; + const unsigned otg_hs_cid_boundary = 0x3100; if (config->feature & USBD_VBUS_SENSE) { if (OTG_FS_CID >= otg_hs_cid_boundary) { /* 2.0 HS core*/ From d9d1cf90c532e68241f00f4f40f0ef4ee83fc27b Mon Sep 17 00:00:00 2001 From: alexrayne Date: Thu, 25 May 2017 00:48:44 +0200 Subject: [PATCH 7/8] !usbd:powerdown:enable, disconnect - recursion release --- include/unicore-mx/usbd/usbd.h | 5 ++++- lib/usbd/usbd.c | 11 +++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/unicore-mx/usbd/usbd.h b/include/unicore-mx/usbd/usbd.h index 26810057..c8467f69 100644 --- a/include/unicore-mx/usbd/usbd.h +++ b/include/unicore-mx/usbd/usbd.h @@ -672,7 +672,10 @@ bool usbd_is_vbus(usbd_device *dev); * Controls power state of usb-core and PHY * @param[in] dev USB Device * @param[in] onoff - true turn on device in action, and power PHY - * false disable PHY and stops usb-core + * false disconnects, disable PHY and stops usb-core + * !!! warning: enable(false) - sets core to disconnected state, but + * enable(true) - not automaticaly release disconnected status, + * it should be set by disconnect(false) */ void usbd_enable(usbd_device *dev, bool onoff); diff --git a/lib/usbd/usbd.c b/lib/usbd/usbd.c index e3f67d82..dafe2c62 100644 --- a/lib/usbd/usbd.c +++ b/lib/usbd/usbd.c @@ -155,16 +155,18 @@ void usbd_disconnect(usbd_device *dev, bool disconnect) { if (!disconnect) { // power-up on connect - if ((dev->config->feature & USBD_USE_POWERDOWN) != 0) - usbd_enable(dev, true); + if ( ((dev->config->feature & USBD_USE_POWERDOWN) != 0) + && (dev->backend->power_control) ) + dev->backend->power_control(dev, usbd_paActivate); } if (dev->backend->disconnect) { dev->backend->disconnect(dev, disconnect); } if (disconnect) { // power-down after disconnect - if ((dev->config->feature & USBD_USE_POWERDOWN) != 0) - usbd_enable(dev, false); + if ( ((dev->config->feature & USBD_USE_POWERDOWN) != 0) + && (dev->backend->power_control) ) + dev->backend->power_control(dev, usbd_paShutdown ); } } @@ -236,6 +238,7 @@ bool usbd_is_vbus(usbd_device *dev){ void usbd_enable(usbd_device *dev, bool onoff){ if (!onoff) usbd_disconnect(dev, true); + else if (dev->backend->power_control) dev->backend->power_control(dev, (onoff)? usbd_paActivate : usbd_paShutdown ); } From aff41057aae7a8f3e919f792ab4bf43467b375e7 Mon Sep 17 00:00:00 2001 From: alexrayne Date: Mon, 29 May 2017 00:39:42 +0200 Subject: [PATCH 8/8] !usbd:powedrown:disconnect -keep disconnection status during powerdown. therefore disconnection moved to background. background disconnects before PHY disabling, and restore disconnection status after. --- include/unicore-mx/usbd/usbd.h | 3 --- lib/usbd/backend/usbd_stm32_otg_fs.c | 5 +++++ lib/usbd/usbd.c | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/unicore-mx/usbd/usbd.h b/include/unicore-mx/usbd/usbd.h index c8467f69..c3efa343 100644 --- a/include/unicore-mx/usbd/usbd.h +++ b/include/unicore-mx/usbd/usbd.h @@ -673,9 +673,6 @@ bool usbd_is_vbus(usbd_device *dev); * @param[in] dev USB Device * @param[in] onoff - true turn on device in action, and power PHY * false disconnects, disable PHY and stops usb-core - * !!! warning: enable(false) - sets core to disconnected state, but - * enable(true) - not automaticaly release disconnected status, - * it should be set by disconnect(false) */ void usbd_enable(usbd_device *dev, bool onoff); diff --git a/lib/usbd/backend/usbd_stm32_otg_fs.c b/lib/usbd/backend/usbd_stm32_otg_fs.c index b3312573..06e2af8a 100644 --- a/lib/usbd/backend/usbd_stm32_otg_fs.c +++ b/lib/usbd/backend/usbd_stm32_otg_fs.c @@ -136,6 +136,9 @@ usbd_power_status otgfs_power_control(usbd_device *dev, usbd_power_action action } case usbd_paShutdown: { /* Wait for AHB idle. */ + uint32_t save_dis = REBASE(DWC_OTG_DCTL) & DWC_OTG_DCTL_SDIS; + //disable device connection before poweroff + REBASE(DWC_OTG_DCTL) |= DWC_OTG_DCTL_SDIS; while (( (DWC_OTG_GRSTCTL(base) & DWC_OTG_GRSTCTL_AHBIDL) == 0) ); //* drop ISRs, cause stoped Core cant handle them REBASE(DWC_OTG_GINTSTS) = ~( DWC_OTG_GINTSTS_USBSUSP @@ -148,6 +151,8 @@ usbd_power_status otgfs_power_control(usbd_device *dev, usbd_power_action action //poser down PHY OTG_FS_GCCFG &= ~OTG_GCCFG_PWRDWN; DWC_OTG_PCGCCTL(base) = DWC_OTG_PCGCCTL_STPPCLK; //| DWC_OTG_PCGCCTL_GATEHCLK ; + //destore connection disable state after PHY poweroff + REBASE(DWC_OTG_DCTL) |= save_dis; break; } } diff --git a/lib/usbd/usbd.c b/lib/usbd/usbd.c index dafe2c62..c69e19f0 100644 --- a/lib/usbd/usbd.c +++ b/lib/usbd/usbd.c @@ -236,11 +236,11 @@ bool usbd_is_vbus(usbd_device *dev){ } void usbd_enable(usbd_device *dev, bool onoff){ - if (!onoff) - usbd_disconnect(dev, true); - else if (dev->backend->power_control) dev->backend->power_control(dev, (onoff)? usbd_paActivate : usbd_paShutdown ); + else + // try emulate enable via disconnect + usbd_disconnect(dev, !onoff); } bool usbd_is_enabled(usbd_device *dev){