-
Notifications
You must be signed in to change notification settings - Fork 8
USBD add core-power and Vbus handle #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 7 commits
21d87c3
84012d3
65231b0
5624172
c1cda4f
114158f
d9d1cf9
aff4105
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. possibly i There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep, i know about namespaces, and that code was compiled succesfully. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you forgot to denote |
||
typedef unsigned char usbd_transfer_flags; | ||
|
||
/** | ||
* USB Transfer status | ||
|
@@ -431,6 +436,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 +522,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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. session callback facility look like a good idea. |
||
usbd_session_callback callback); | ||
|
||
/** | ||
* Register SET_CONFIGURATION callback \n | ||
* stack will invoke @a callback when ever SET_CONFIGURATION is received | ||
|
@@ -643,6 +660,33 @@ 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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ability to know VBUS state also look like a good idea too. |
||
|
||
/** | ||
* 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 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); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is already a function, see "void usbd_disconnect(usbd_device *dev, bool disconnected);". There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. usbd_disconnect stops session, it is not control power mode of core or phy. |
||
/** | ||
* 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 | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,8 @@ | |
#include <unicore-mx/usbd/usbd.h> | ||
|
||
static usbd_device *init(const usbd_backend_config *config); | ||
static bool otgfs_is_powered(usbd_device *dev); | ||
static usbd_power_status 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__) | ||
|
@@ -74,16 +78,20 @@ 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 = 0x3100; | ||
|
||
if (config->feature & USBD_VBUS_SENSE) { | ||
if (OTG_FS_CID >= 0x00002000) { /* 2.0 */ | ||
if (OTG_FS_CID >= otg_hs_cid_boundary) { /* 2.0 HS core*/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
/* 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; | ||
} | ||
} 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 | | ||
|
@@ -108,3 +116,45 @@ 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 | ||
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; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) | ||
{ | ||
|
@@ -145,9 +153,21 @@ 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) | ||
&& (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) | ||
&& (dev->backend->power_control) ) | ||
dev->backend->power_control(dev, usbd_paShutdown ); | ||
} | ||
} | ||
|
||
void usbd_ep_prepare(usbd_device *dev, uint8_t addr, usbd_ep_type type, | ||
|
@@ -208,5 +228,28 @@ 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 (!onoff) | ||
usbd_disconnect(dev, true); | ||
else | ||
if (dev->backend->power_control) | ||
dev->backend->power_control(dev, (onoff)? usbd_paActivate : usbd_paShutdown ); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Look at the flow of control. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don`t understand you - enable(false) MUST not shutdown? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh, i see, thank you There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for your new code.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, see alredy. more trouble now bother me - cant There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. well, resolve it. but not preferable way - not like what i write There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, this was confused me too. disconnection MUST be provided before powerdown. but fro stm DWC core it is mean that USB enter to non-connectable state. imho, name 'disconnect' - not very suitable for this operation. |
||
|
||
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; | ||
} | ||
|
||
|
||
/**@}*/ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"//*" (IMO) Please C style comment only (code consistancy).
@danielinux @brabo what do you think?