|
10 | 10 | #include "usbd_if.h"
|
11 | 11 | #include "usbd_cdc_if.h"
|
12 | 12 |
|
| 13 | +#if !defined(USBD_REENUM_DISABLED) |
| 14 | + |
| 15 | +/* |
| 16 | + * Below, support for re-attaching to USB is handled. USB-attachment is |
| 17 | + * detected by the presence of a pullup on one of the USB datalines. |
| 18 | + * |
| 19 | + * To force the USB host to re-enumerate, we must detach (disable |
| 20 | + * pullup), wait a bit, and re-attach (enable pullup). This can be done |
| 21 | + * while running, but must also happen at startup (including the detach |
| 22 | + * and delay, since USB might have been active just before reset, so we |
| 23 | + * must force a re-enumeration). On a cold boot (e.g. USB just plugged |
| 24 | + * in), the forced detach might not be needed, but will not be harmful |
| 25 | + * either. |
| 26 | + * |
| 27 | + * For pullup control, a number of cases are supported: |
| 28 | + * 1. An external pullup controllable through a GPIO (e.g. using an |
| 29 | + * external transistor). The default output state (e.g. when the |
| 30 | + * GPIO is floating) can be enabled or disabled, and the output |
| 31 | + * polarity can be configured. |
| 32 | + * 2. A pullup built into the chip's USB core. This is automatically |
| 33 | + * enabled by hardware or USB HAL code, and can be manually |
| 34 | + * controlled using HAL functions. |
| 35 | + * 3. A fixed (always enabled) external pullup. To still allow detaching, |
| 36 | + * a bit of a hack is used: By setting the D+ to OUTPUT LOW, it |
| 37 | + * *looks* like the pullup is removed (the host has own, bigger, |
| 38 | + * pulldown, to detect detaching, so writing LOW looks the same). |
| 39 | + * This probably violates USB specifications, but does seem to work |
| 40 | + * well in practice. It probably also should only be used briefly, |
| 41 | + * keeping the pin OUTPUT LOW for longer might be problematic. |
| 42 | + * |
| 43 | + * These scenarios are considered in order: If the variant defines an |
| 44 | + * external pullup control pin, it is used, else if an internal pullup |
| 45 | + * is present, that is used, else the D+ trick is used. |
| 46 | + * |
| 47 | + * To configure #1, the variant should either define USBD_ATTACH_PIN and |
| 48 | + * USBD_ATTACH_LEVEL when the pullup is disabled by default and the pin |
| 49 | + * can be used to *attach*, or USBD_DETACH_PIN and USBD_DETACH_LEVEL |
| 50 | + * when the pullup is enabled by default and the pin can be used to |
| 51 | + * *detach*. |
| 52 | + */ |
| 53 | + |
| 54 | +/* Compatibility with the old way to specify this */ |
| 55 | +#if defined(USB_DISC_PIN) && !defined(USBD_ATTACH_PIN) |
| 56 | +#define USBD_ATTACH_PIN USB_DISC_PIN |
| 57 | +#define USBD_ATTACH_LEVEL LOW |
| 58 | +#warning "USB_DISC_PIN is deprecated, use USBD_ATTACH_PIN instead" |
| 59 | +#endif /* defined(USB_DISC_PIN) && !defined(USBD_ATTACH_PIN) */ |
| 60 | + |
| 61 | +/* Some sanity checks */ |
| 62 | +#if defined(USBD_ATTACH_PIN) && defined(USBD_DETACH_PIN) |
| 63 | +#error "Cannot define both USBD_ATTACH_PIN and USBD_DETACH_PIN" |
| 64 | +#endif /* defined(USBD_ATTACH_PIN) && defined(USBD_DETACH_PIN) */ |
| 65 | +#if defined(USBD_ATTACH_PIN) && !defined(USBD_ATTACH_LEVEL) |
| 66 | +#error "USBD_ATTACH_PIN also needs USBD_ATTACH_LEVEL defined" |
| 67 | +#endif /* defined(USBD_ATTACH_PIN) && !defined(USBD_ATTACH_LEVEL) */ |
| 68 | +#if defined(USBD_DETACH_PIN) && !defined(USBD_DETACH_LEVEL) |
| 69 | +#error "USBD_DETACH_PIN also needs USBD_DETACH_LEVEL defined" |
| 70 | +#endif /* defined(USBD_DETACH_PIN) && !defined(USBD_DETACH_LEVEL) */ |
| 71 | + |
| 72 | +/* Either of these bits indicate that there are internal pullups */ |
| 73 | +#if defined(USB_BCDR_DPPU) || defined(USB_OTG_DCTL_SDIS) |
| 74 | +#define USBD_HAVE_INTERNAL_PULLUPS |
| 75 | +#endif /* defined(USB_BCDR_DPPU) || defined(USB_OTG_DCTL_SDIS) */ |
| 76 | + |
| 77 | +/* Figure out which USB instance is used. This mirrors the decision made |
| 78 | + * in USBD_LL_Init in usbd_conf.c. */ |
| 79 | +#if defined(USE_USB_HS) |
| 80 | +#define USBD_USB_INSTANCE USB_OTG_HS |
| 81 | +#elif defined(USB_OTG_FS) |
| 82 | +#define USBD_USB_INSTANCE USB_OTG_FS |
| 83 | +#elif defined(USB) |
| 84 | +#define USBD_USB_INSTANCE USB |
| 85 | +#endif |
| 86 | + |
| 87 | +/* |
| 88 | + * Translate pin number to a pin name (using the same define for both |
| 89 | + * attach and detach pins) and also define the complementary level. This |
| 90 | + * allows using the same code for the default-enabled and |
| 91 | + * default-disabled case as well as for the D+ trick (which does not |
| 92 | + * know the pin number, only the pin name). |
| 93 | + */ |
| 94 | +#if defined(USBD_ATTACH_PIN) |
| 95 | +#define USBD_PULLUP_CONTROL_PINNAME digitalPinToPinName(USBD_ATTACH_PIN) |
| 96 | +#define USBD_DETACH_LEVEL !(USBD_ATTACH_LEVEL) |
| 97 | +#elif defined(USBD_DETACH_PIN) |
| 98 | +#define USBD_PULLUP_CONTROL_PINNAME digitalPinToPinName(USBD_DETACH_PIN) |
| 99 | +#define USBD_ATTACH_LEVEL !(USBD_DETACH_LEVEL) |
| 100 | +#elif !defined(USBD_HAVE_INTERNAL_PULLUPS) |
| 101 | +/* When no USB attach and detach pins were defined, and there are also |
| 102 | + * no internal pullups, assume there is a fixed external pullup and apply |
| 103 | + * the D+ trick. This should happen only for the USB peripheral, since |
| 104 | + * USB_OTG_HS and USB_OTG_FS always have internal pullups. */ |
| 105 | +#if !defined(USB) |
| 106 | +#error "Unexpected USB configuration" |
| 107 | +#endif |
| 108 | +#define USBD_PULLUP_CONTROL_PINNAME USB_DP |
| 109 | +#define USBD_DETACH_LEVEL LOW |
| 110 | +// USBD_ATTACH_LEVEL not needed. |
| 111 | +#define USBD_DP_TRICK |
| 112 | +#endif |
| 113 | + |
13 | 114 | /**
|
14 |
| - * @brief Force to re-enumerate USB |
| 115 | + * @brief Force to re-enumerate USB. |
| 116 | + * |
| 117 | + * This is intended to be called at startup by core code. It could be |
| 118 | + * used at runtime, while USB is connected, to force re-enumeration |
| 119 | + * too, but that does not work in all cases (when USB is enabled on an |
| 120 | + * F103C8, setting output mode on the DP pin no longer has any effect). |
| 121 | + * |
15 | 122 | * @param None
|
16 | 123 | * @retval None
|
17 | 124 | */
|
18 |
| - |
19 | 125 | WEAK void USBD_reenumerate(void)
|
20 | 126 | {
|
21 |
| -#ifndef USBD_REENUM_DISABLED |
22 |
| - /* Re-enumerate the USB */ |
23 |
| -#ifdef USB_DISC_PIN |
24 |
| - pinMode(USB_DISC_PIN, OUTPUT); |
25 |
| - digitalWrite(USB_DISC_PIN, LOW); |
| 127 | +#if defined(USBD_PULLUP_CONTROL_PINNAME) |
| 128 | + /* Detach */ |
| 129 | + pin_function(USBD_PULLUP_CONTROL_PINNAME, STM_PIN_DATA(STM_MODE_OUTPUT_PP, GPIO_NOPULL, 0)); |
| 130 | + digitalWriteFast(USBD_PULLUP_CONTROL_PINNAME, USBD_DETACH_LEVEL); |
| 131 | + |
| 132 | + /* Wait */ |
| 133 | + delay(USBD_ENUM_DELAY); |
| 134 | + |
| 135 | + /* Attach */ |
| 136 | +#if defined(USBD_DP_TRICK) |
| 137 | + /* Revert back to input (floating), needed for the D+ trick */ |
| 138 | + pin_function(USBD_PULLUP_CONTROL_PINNAME, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); |
26 | 139 | #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); |
| 140 | + digitalWriteFast(USBD_PULLUP_CONTROL_PINNAME, USBD_ATTACH_LEVEL); |
| 141 | +#endif /* defined(USBD_PULLUP_CONTROL_FLOATING) */ |
| 142 | +#elif defined(USBD_HAVE_INTERNAL_PULLUPS) |
| 143 | + USB_DevDisconnect(USBD_USB_INSTANCE); |
36 | 144 | 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 */ |
40 |
| -#endif /* USBD_REENUM_DISABLED */ |
| 145 | + USB_DevConnect(USBD_USB_INSTANCE); |
| 146 | +#else |
| 147 | +#warning "No USB attach/detach method, USB might not be reliable through system resets" |
| 148 | +#endif |
41 | 149 | }
|
42 | 150 |
|
| 151 | +#else /* !defined(USBD_REENUM_DISABLED) */ |
| 152 | +WEAK void USBD_reenumerate(void) { } |
| 153 | +#endif |
| 154 | + |
43 | 155 | #ifdef USBD_USE_CDC
|
44 | 156 | void USBD_CDC_init(void)
|
45 | 157 | {
|
|
0 commit comments