Skip to content

Commit 9029509

Browse files
Refactor USB pullup handling
Previously, variants could define USB_DISC_PIN when they had an USB attach pullup that was disabled by default and needed a pin to be written LOW to enable it. Other hardware configurations could only overwrite the USBD_reenumerate function, like the M200 board did. This commit makes the pullup configuration more flexible. By defining the appropriate macros, enabled-by-default and disabled-by-default pullups are both supported. The output level of the pin can also be configured. Finally, for disabled-by-default, the output mode for the enabled state can also be configured (INPUT to leave the pin floating and let any external transistor gate pullup enable the USB pullup, or OUTPUT to keep the pin as OUTPUT an actively drive the transistor gate). The new macros also take PinName constants rather than pin numbers. This allows merging the code that controls an external pullup with the code that writes directly to the USB DP pin to fake a disabled pullup (this code only knows the pin name of the DP pin, not the number). Finally, for CPUs that have internal USB pullup (as indicated by the presence of a SDIS config bit), the write-to-DP-trick is now not performed (since the pullup is automatically managed by the USB hardware already). This fixes stm32duino#885, also see that issue for discussion leading up to this change.
1 parent df6b4f7 commit 9029509

File tree

5 files changed

+82
-38
lines changed

5 files changed

+82
-38
lines changed

cores/arduino/stm32/usb/usbd_if.c

+60-17
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,76 @@
1010
#include "usbd_if.h"
1111
#include "usbd_cdc_if.h"
1212

13+
#if defined(USB_DISC_PIN)
14+
// Compatibility with the old way to specify this
15+
#define USBD_ATTACH_PIN digitalPinToPinName(USB_DISC_PIN)
16+
#define USBD_ATTACH_LEVEL LOW
17+
#warning "USB_DISC_PIN is deprecated, use USBD_ATTACH_PINNAME instead"
18+
#endif /* USB_DISC_PIN */
19+
20+
// When no USB attach and detach pins were defined, and the USB module
21+
// also does not have any builtin autocontrolled pullups (indicated by
22+
// the SDIS bit), assume there are fixed external pullups. This uses a
23+
// bit of a hack by using the DP pin as a DETACH pin, so it will be
24+
// driven low very briefly, which looks like a missing pullup to the
25+
// host. Probably violates USB specs, but works properly in practice.
26+
#if !defined(USBD_ATTACH_PINNAME) && !defined(USBD_DETACH_PIN) && !defined(USB_OTG_DCTL_SDIS)
27+
#if defined(USE_USB_HS_IN_FS)
28+
#define USBD_DETACH_PINNAME USB_OTG_HS_DP
29+
#elif defined(USB_OTG_FS)
30+
#define USBD_DETACH_PINNAME USB_OTG_FS_DP
31+
#else /* USB */
32+
#define USBD_DETACH_PINNAME USB_DP
33+
#endif
34+
#define USBD_DETACH_LEVEL LOW
35+
// Make sure to revert to INPUT (instead of OUTPUT HIGH) after the
36+
// detach "pulse" to restore normal operation.
37+
#define USBD_ATTACH_MODE INPUT
38+
#endif /* !defined(USBD_ATTACH_PINNAME) && !defined(USBD_DETACH_PIN) && !defined(USB_OTG_DCTL_SDIS) */
39+
40+
#if defined(USBD_ATTACH_PINNAME) && !defined(USBD_ATTACH_MODE)
41+
// Normally (e.g. when controlling a transistor), keep the pin in
42+
// OUTPUT mode after the detach "pulse" to actively drive the
43+
// transistor.
44+
#define USBD_ATTACH_MODE OUTPUT
45+
#endif /* defined(USBD_ATTACH_PINNAME) && !defined(USBD_ATTACH_MODE) */
46+
47+
// Some sanity checks
48+
#if defined(USBD_ATTACH_PINNAME) && defined(USBD_DETACH_PIN)
49+
#error "Cannot define both USBD_ATTACH_PINNAME and USBD_DETACH_PIN"
50+
#endif /* defined(USBD_ATTACH_PINNAME) && defined(USBD_DETACH_PIN) */
51+
#if defined(USBD_ATTACH_PINNAME) && !defined(USBD_ATTACH_LEVEL)
52+
#error "USBD_ATTACH_PINNAME also needs USBD_ATTACH_LEVEL defined"
53+
#endif /* defined(USBD_ATTACH_PINNAME) && !defined(USBD_ATTACH_LEVEL) */
54+
#if defined(USBD_DETACH_PINNAME) && !defined(USBD_DETACH_LEVEL)
55+
#error "USBD_DETACH_PINNAME also needs USBD_DETACH_LEVEL defined"
56+
#endif /* defined(USBD_DETACH_PINNAME) && !defined(USBD_DETACH_LEVEL) */
57+
1358
/**
1459
* @brief Force to re-enumerate USB
1560
* @param None
1661
* @retval None
1762
*/
18-
1963
WEAK void USBD_reenumerate(void)
2064
{
2165
#ifndef USBD_REENUM_DISABLED
2266
/* Re-enumerate the USB */
23-
#ifdef USB_DISC_PIN
24-
pinMode(USB_DISC_PIN, OUTPUT);
25-
digitalWrite(USB_DISC_PIN, LOW);
26-
#else
27-
#ifdef USE_USB_HS_IN_FS
28-
PinName pinDP = USB_OTG_HS_DP;
29-
#elif defined(USB_OTG_FS)
30-
PinName pinDP = USB_OTG_FS_DP;
31-
#else /* USB */
32-
PinName pinDP = USB_DP;
33-
#endif
34-
pin_function(pinDP, STM_PIN_DATA(STM_MODE_OUTPUT_PP, GPIO_NOPULL, 0));
35-
digitalWriteFast(pinDP, LOW);
67+
#ifdef USBD_DETACH_PINNAME
68+
// Default is attached, so detach, wait, and reattach.
69+
pin_function(USBD_DETACH_PINNAME, STM_PIN_DATA(STM_MODE_OUTPUT_PP, GPIO_NOPULL, 0));
70+
digitalWriteFast(USBD_DETACH_PINNAME, USBD_DETACH_LEVEL);
3671
delay(USBD_ENUM_DELAY);
37-
pin_function(pinDP, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
38-
/*delay(USBD_ENUM_DELAY);*/
39-
#endif /* USB_DISC_PIN */
72+
if (USBD_ATTACH_MODE_INPUT == OUTPUT)
73+
digitalWriteFast(USBD_DETACH_PINNAME, !USBD_DETACH_LEVEL);
74+
else
75+
pin_function(USBD_DETACH_PINNAME, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
76+
#elif USBD_ATTACH_PINNAME
77+
// Default is detached, so just attach
78+
pin_function(USBD_ATTACH_PINNAME, STM_PIN_DATA(STM_MODE_OUTPUT_PP, GPIO_NOPULL, 0));
79+
digitalWriteFast(USBD_ATTACH_PINNAME, USBD_ATTACH_LEVEL);
80+
#elif !defined(USB_OTG_DCTL_SDIS)
81+
#warning "No USB attac/detach method, USB might not be reliable through system resets"
82+
#endif
4083
#endif /* USBD_REENUM_DISABLED */
4184
}
4285

variants/MALYANM200_F103CB/variant.cpp

-19
Original file line numberDiff line numberDiff line change
@@ -86,25 +86,6 @@ const PinName digitalPin[] = {
8686
extern "C" {
8787
#endif
8888

89-
/**
90-
* Initialize the variant. Turn on PB9 for USB.
91-
*/
92-
void initVariant()
93-
{
94-
pinMode(PB9, OUTPUT);
95-
digitalWrite(PB9, 1);
96-
}
97-
98-
void USBD_reenumerate(void)
99-
{
100-
pinMode(PB9, OUTPUT);
101-
digitalWrite(PB9, HIGH);
102-
delay(10);
103-
digitalWrite(PB9, LOW);
104-
delay(10);
105-
digitalWrite(PB9, HIGH);
106-
}
107-
10889
/**
10990
* @brief System Clock Configuration
11091
* The system Clock is configured as follow :

variants/MALYANM200_F103CB/variant.h

+4
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ extern "C" {
105105
#define PIN_SERIAL_RX PA10
106106
#define PIN_SERIAL_TX PA9
107107

108+
// USB, pull this pin low to *disable* the USB attach pullup
109+
#define USBD_DETACH_PINNAME PB_9
110+
#define USBD_DETACH_LEVEL LOW
111+
108112
/* Dedicated definitions */
109113
#ifndef MAX_PRIORITY
110114
#define MAX_PRIORITY 15

variants/MAPLEMINI_F103CB/variant.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,9 @@ extern "C" {
108108
#define PIN_SERIAL_RX PA10
109109
#define PIN_SERIAL_TX PA9
110110

111-
// USB
112-
#define USB_DISC_PIN PB9
111+
// USB, pull this pin low to enable the USB attach pullup
112+
#define USBD_ATTACH_PINNAME PB_9
113+
#define USBD_ATTACH_LEVEL LOW
113114

114115
#ifdef __cplusplus
115116
} // extern "C"

variants/board_template/variant.h

+15
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,21 @@ extern "C" {
162162
// See AN4879 https://www.st.com/content/st_com/en/search.html#q=AN4879-t=resources-page=1
163163
//#define USBD_VBUS_DETECTION_ENABLE
164164

165+
// If the board has external USB pullup (on DP/DM depending on speed)
166+
// that can be controlled using a GPIO pin, define these:
167+
// - If the the pullup is disabled (USB detached) by default, define
168+
// USBD_ATTACH_PINNAME to the pin that, when written to
169+
// USBD_ATTACH_LEVEL, attaches the pullup.
170+
// - If the the pullup is enabled (attached) by default, define
171+
// USBD_DETACH_PINNAME to the pin that, when written to
172+
// USBD_DETACH_LEVEL, detaches the pullup.
173+
// Note that these constants need PinName values (e.g. PB_5) not pin
174+
// numbers (e.g. PB5).
175+
//#define USBD_ATTACH_PINNAME x
176+
//#define USBD_ATTACH_LEVEL LOW
177+
//#define USBD_DETACH_PINNAME NAMEx
178+
//#define USBD_DETACH_LEVEL LOW
179+
165180
#ifdef __cplusplus
166181
} // extern "C"
167182
#endif

0 commit comments

Comments
 (0)