Skip to content
13 changes: 13 additions & 0 deletions include/unicore-mx/common/dwc_otg.ucd
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
49 changes: 41 additions & 8 deletions include/unicore-mx/usbd/usbd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

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?

, USBD_USE_POWERDOWN = (1<<3)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(IHMO) ", USBD_USE_POWERDOWN" code consistancy. "," not placed there.
(IHMO) "(1<<3)" , "(1 << 2)", "(1 << 0)," space missing in "1" "<<" "3" code consistancy.

@brabo @danielinux Can you please give me a hand at code style / consistancy work.

};

struct usbd_backend_config {
/** Number of endpoints. (Including control endpoint) */
uint8_t ep_count;
Expand All @@ -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;
Expand Down Expand Up @@ -279,7 +284,7 @@ enum usbd_transfer_flags {
USBD_FLAG_PACKET_PER_FRAME_MASK = (0x3 << 5)
};

typedef enum usbd_transfer_flags usbd_transfer_flags;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

possibly ive got a warning here? enum and typedef - with same name. its confusing me, i newer see such trick.
i`ve saw overriding enum item name with macro definition, but override enum by typedef - is it vlalid practice for C?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

@alexrayne alexrayne May 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, i know about namespaces, and that code was compiled succesfully.
when i ask about "valid practice for C" i mean - is it good? is it helpful? can it lead to some errors?
the name "usbd_transfer_flags" imho nott very suitable for enum. such name also can be imagine for struct of a binary set of flags.
anyway, if you insist - let`s revert this typedef back to code.

Copy link
Author

@alexrayne alexrayne May 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you forgot to denote
+typedef unsigned char usbd_transfer_flags;
ARMCC compiler generates warning when we try to assign to enum variable integer value (with set of flags).
therefore i denote for usbd_transfer_flags as numeric type

typedef unsigned char usbd_transfer_flags;

/**
* USB Transfer status
Expand Down Expand Up @@ -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);

/**
Expand Down Expand Up @@ -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,
Copy link
Contributor

Choose a reason for hiding this comment

The 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
Expand Down Expand Up @@ -643,6 +660,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);
Copy link
Contributor

Choose a reason for hiding this comment

The 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 disable PHY and stops usb-core
*/
void usbd_enable(usbd_device *dev, bool onoff);

Copy link
Contributor

Choose a reason for hiding this comment

The 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);".

Copy link
Author

@alexrayne alexrayne Feb 4, 2017

Choose a reason for hiding this comment

The 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.

/**
* Perform a transfer
*
Expand Down
1 change: 1 addition & 0 deletions lib/usbd/backend/dwc_otg_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
9 changes: 9 additions & 0 deletions lib/usbd/backend/usbd_dwc_otg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
34 changes: 32 additions & 2 deletions lib/usbd/backend/usbd_stm32_otg_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 void otgfs_power_control(usbd_device *dev, usbd_power_action action);

static struct usbd_device _usbd_dev;

Expand All @@ -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__)
Expand All @@ -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*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to this comment, CID = 2.0+ and FS core should not exists right?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dow understand you. CID indicates an core version. according to RM0090 FS CID=0x0000 1100 and HS CID=0x0200 0600
what you ask about?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see RM0385.
OTG_CID = 0x00002000 for OTG_FS and OTG_HS

Copy link
Author

@alexrayne alexrayne Feb 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heh. my version of RM0385 says:
Reset value: 0x0000 3000 for USB OTG FS
Reset value: 0x0000 3100 for USB OTG HS
looks like this code need target MCU specification - it depends on MCU family. And even more - look like this code not aplicatable on stm32f7 family 8/ But for my stm32f4 - works ok 8)

/* 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;
}
Expand Down Expand Up @@ -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;
}
}
}
33 changes: 33 additions & 0 deletions lib/usbd/usbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -145,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,
Expand Down Expand Up @@ -208,5 +226,20 @@ 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, false);
if (dev->backend->power_control)
dev->backend->power_control(dev, (onoff)? usbd_paActivate : usbd_paShutdown );
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Application code
= usbd_disconnect(dev, true)
== dev->backend->disconnect(dev, true);
== usbd_enable(dev, false);
=== usbd_disconnect(dev, false);
==== usbd_enable(dev, true);
===== dev->backend->power_control(dev, usbd_paActivate);
==== dev->backend->disconnect(dev, false);
=== dev->backend->power_control(dev, usbd_paShutdown );

Look at the flow of control.
At the end, NOT disconnected with SHUTDOWN power control.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don`t understand you - enable(false) MUST not shutdown?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, i see, thank you

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for your new code.

=usbd_disconnect(dev, true)   <----------------\
==dev->backend->disconnect(dev, true);         | RECURSIVE CALL! STACK OVERFLOW!
==usbd_enable(dev, false);                     |
===usbd_disconnect(dev, true)   ---------------/
===dev->backend->power_control(dev, usbd_paShutdown);

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, see alredy. more trouble now bother me - cantt understand how to wake up FS from powerdown, cause it want normaly detect online and reset after ungating core clock

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, resolve it. but not preferable way - not like what i write

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When usbd_enable(dev, false) is called, it disconnect and shutdown. but when usbd_enable(dev, true) is called, it only power-up (it remove the disconnect condition).

Copy link
Author

@alexrayne alexrayne May 26, 2017

Choose a reason for hiding this comment

The 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.
i`ll change behaviour to restore disconnection state on powerdown complete.
i not sure, is it good to place disconnection before powerdown into backend->power_control, instead of botherig it on frontend?



/**@}*/

23 changes: 23 additions & 0 deletions lib/usbd/usbd_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#ifndef UNICOREMX_USBD_PRIVATE_H
#define UNICOREMX_USBD_PRIVATE_H

#include <stdbool.h>
#include <unicore-mx/usbd/usbd.h>

/**
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -174,6 +179,12 @@ struct usbd_device {
#endif
};

enum _usbd_power_action{
usbd_paShutdown
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Enum labels are uppercase. (see coding style for full information)
  • Without compelling reason, please dont use typedef. (see coding style for full information)
    If you really want, you can later do typedef enum usbd_power_action usbd_power_action.

, usbd_paActivate
};
typedef enum _usbd_power_action usbd_power_action;

/* Functions provided by the hardware abstraction. */
struct usbd_backend {
usbd_device * (*init)(const usbd_backend_config *config);
Expand All @@ -197,6 +208,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.
Expand Down Expand Up @@ -359,6 +374,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.
Expand Down