dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_usb.c
Go to the documentation of this file.
1 
16 /*
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 3 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful, but
23  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25  * for more details.
26  *
27  * You should have received a copy of the GNU General Public License along
28  * with this program; if not, see <http://www.gnu.org/licenses/>
29  */
30 
31 /* Project Includes */
32 #include "pios.h"
33 #include "usb_lib.h"
34 #include "pios_usb_board_data.h"
35 
36 #include "pios_usb.h"
37 #include "pios_usb_priv.h"
38 
39 #if defined(PIOS_INCLUDE_USB_HID)
40 
41 /* Rx/Tx status */
42 static bool transfer_possible = false;
43 
44 /* USB activity detection */
45 static volatile bool sof_seen_since_reset = false;
46 
47 enum pios_usb_dev_magic {
48  PIOS_USB_DEV_MAGIC = 0x17365904,
49 };
50 
51 struct pios_usb_dev {
52  enum pios_usb_dev_magic magic;
53  const struct pios_usb_cfg * cfg;
54 };
55 
60 static int32_t PIOS_USB_validate(struct pios_usb_dev * usb_dev)
61 {
62  if(usb_dev == NULL)
63  return -1;
64 
65  if (usb_dev->magic != PIOS_USB_DEV_MAGIC)
66  return -1;
67 
68  return 0;
69 }
70 
71 static struct pios_usb_dev * PIOS_USB_alloc(void)
72 {
73  struct pios_usb_dev * usb_dev;
74 
75  usb_dev = (struct pios_usb_dev *)PIOS_malloc(sizeof(*usb_dev));
76  if (!usb_dev) return(NULL);
77 
78  usb_dev->magic = PIOS_USB_DEV_MAGIC;
79  return(usb_dev);
80 }
81 
87 static uintptr_t pios_usb_com_id;
88 int32_t PIOS_USB_Init(uintptr_t * usb_id, const struct pios_usb_cfg * cfg)
89 {
90  PIOS_Assert(usb_id);
91  PIOS_Assert(cfg);
92 
93  struct pios_usb_dev * usb_dev;
94 
95  usb_dev = (struct pios_usb_dev *) PIOS_USB_alloc();
96  if (!usb_dev) goto out_fail;
97 
98  /* Bind the configuration to the device instance */
99  usb_dev->cfg = cfg;
100 
102 
103  /*
104  * This is a horrible hack to make this available to
105  * the interrupt callbacks. This should go away ASAP.
106  */
107  pios_usb_com_id = (uintptr_t) usb_dev;
108 
109  /* Enable the USB Interrupts */
110  NVIC_Init((NVIC_InitTypeDef*)&usb_dev->cfg->irq.init);
111 
112  /* Configure USB D-/D+ (DM/DP) pins */
113  GPIO_InitTypeDef GPIO_InitStructure;
114  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
115  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
116  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
117  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
118  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
119  GPIO_Init(GPIOA, &GPIO_InitStructure);
120 
121  GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_14);
122  GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_14);
123 
124  /* Configure VBUS sense pin */
125  if (usb_dev->cfg->vsense.gpio)
126  GPIO_Init(usb_dev->cfg->vsense.gpio, (GPIO_InitTypeDef*)&usb_dev->cfg->vsense.init);
127 
128  /* Select USBCLK source */
129  RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);
130  /* Enable the USB clock */
131  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
132 
133  USB_Init();
134  USB_SIL_Init();
135 
136  *usb_id = (uintptr_t) usb_dev;
137 
138  return 0; /* No error */
139 
140 out_fail:
141  return(-1);
142 }
143 
150 int32_t PIOS_USB_ChangeConnectionState(bool Connected)
151 {
152  // In all cases: re-initialise USB HID driver
153  if (Connected) {
154  transfer_possible = true;
155 
156  //TODO: Check SetEPRxValid(ENDP1);
157 
158 #if defined(USB_LED_ON)
159  USB_LED_ON; // turn the USB led on
160 #endif
161  } else {
162  // Cable disconnected: disable transfers
163  transfer_possible = false;
164 
165 #if defined(USB_LED_OFF)
166  USB_LED_OFF; // turn the USB led off
167 #endif
168  }
169 
170  return 0;
171 }
172 
173 int32_t PIOS_USB_Reenumerate()
174 {
175  /* Force USB reset and power-down (this will also release the USB pins for direct GPIO control) */
176  _SetCNTR(CNTR_FRES | CNTR_PDWN);
177 
178  /* Using a "dirty" method to force a re-enumeration: */
179  /* Force DPM (Pin PA12) low for ca. 10 mS before USB Tranceiver will be enabled */
180  /* This overrules the external Pull-Up at PA12, and at least Windows & MacOS will enumerate again */
181  GPIO_InitTypeDef GPIO_InitStructure;
182  GPIO_StructInit(&GPIO_InitStructure);
183  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
184  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
185  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
186  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
187  GPIO_Init(GPIOA, &GPIO_InitStructure);
188 
189  PIOS_DELAY_WaitmS(50);
190 
191  /* Release power-down, still hold reset */
192  _SetCNTR(CNTR_PDWN);
194 
195  /* CNTR_FRES = 0 */
196  _SetCNTR(0);
197 
198  /* Clear pending interrupts */
199  _SetISTR(0);
200 
201  /* set back to alternate function */
202  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
203  GPIO_Init(GPIOA, &GPIO_InitStructure);
204 
205  /* Configure USB clock */
206  /* USBCLK = PLLCLK / 1.5 */
207  RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);
208  /* Enable USB clock */
209  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
210 
211  return 0;
212 }
213 
214 bool PIOS_USB_CableConnected(uintptr_t id)
215 {
216  struct pios_usb_dev * usb_dev = (struct pios_usb_dev *) pios_usb_com_id;
217 
218  if (PIOS_USB_validate(usb_dev) != 0)
219  return false;
220 
221  // If board is configured to have a VSENSE pin, use that
222  if (usb_dev->cfg->vsense.gpio != NULL)
223  return GPIO_ReadInputDataBit(usb_dev->cfg->vsense.gpio, usb_dev->cfg->vsense.init.GPIO_Pin) == Bit_SET;
224 
225  return sof_seen_since_reset;
226 }
227 
228 bool PIOS_USB_HaveVSense(uintptr_t id)
229 {
230  struct pios_usb_dev * usb_dev = (struct pios_usb_dev *) pios_usb_com_id;
231 
232  if (PIOS_USB_validate(usb_dev) != 0)
233  return false;
234 
235  return usb_dev->cfg->vsense.gpio != NULL;
236 }
237 
244 bool PIOS_USB_CheckAvailable(uintptr_t id)
245 {
246  struct pios_usb_dev * usb_dev = (struct pios_usb_dev *) pios_usb_com_id;
247 
248  if (PIOS_USB_validate(usb_dev) != 0)
249  return false;
250 
251  return PIOS_USB_CableConnected(id) && transfer_possible;
252 }
253 
254 void SOF_Callback(void)
255 {
256  sof_seen_since_reset = true;
257 }
258 
259 void SUSP_Callback(void)
260 {
261  sof_seen_since_reset = false;
262 }
263 
264 #endif
265 
Main PiOS header to include all the compiled in PiOS options.
int32_t PIOS_USB_Reenumerate()
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
bool PIOS_USB_CheckAvailable(uintptr_t id)
static struct flyingpicmd_cfg_fa cfg
Definition: main.c:49
#define USB_LED_OFF
Definition: pios_board.h:103
USB private definitions.
int32_t PIOS_USB_ChangeConnectionState(bool connected)
USB HID layer functions header.
uint32_t magic
bool PIOS_USB_HaveVSense(uintptr_t id)
int32_t PIOS_USB_Init(uintptr_t *usb_id, const struct pios_usb_cfg *cfg)
#define USB_LED_ON
Definition: pios_board.h:102
bool PIOS_USB_CableConnected(uintptr_t id)
#define PIOS_Assert(test)
Definition: pios_debug.h:52
int32_t PIOS_DELAY_WaitmS(uint32_t mS)
Definition: pios_delay.c:140
int32_t PIOS_DELAY_WaituS(uint32_t uS)
Definition: pios_delay.c:116