Paparazzi UAS  v5.10_stable-5-g83a0da5-dirty
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
usbStorage.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014-2015 Gautier Hattenberger, Alexandre Bustico
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
22 /*
23  * @file modules/loggers/sdlog_chibios/usbStorage.c
24  *
25  */
26 
27 #include <ch.h>
28 #include <hal.h>
29 #include "usb_msd.h"
30 #include "usbStorage.h"
32 #include <stdio.h>
33 #include <string.h>
34 #include "main_chibios.h"
35 #include "mcu_periph/sdio.h"
36 
37 static uint8_t nibbleToHex(uint8_t nibble);
38 static void populateSerialNumberDescriptorData(void);
39 static void thdUsbStorage(void *arg);
40 static thread_t *usbStorageThreadPtr = NULL;
41 /* USB mass storage driver */
43 static bool isRunning = false;
44 
45 /* endpoint index */
46 #define USB_MS_DATA_EP 1
47 // cortex_m4 specific
48 #define MCU_RESTART() {*((unsigned long *)0x0E000ED0C) = 0x05FA0004;}
49 
50 /* USB device descriptor */
51 static const uint8_t deviceDescriptorData[] = {
52  USB_DESC_DEVICE
53  (
54  0x0200, /* supported USB version (2.0) */
55  0x00, /* device class (none, specified in interface) */
56  0x00, /* device sub-class (none, specified in interface) */
57  0x00, /* device protocol (none, specified in interface) */
58  64, /* max packet size of control end-point */
59  0x0483, /* vendor ID (STMicroelectronics!) */
60  0x5740, /* product ID (STM32F407) */
61  0x0100, /* device release number */
62  1, /* index of manufacturer string descriptor */
63  2, /* index of product string descriptor */
64  3, /* index of serial number string descriptor */
65  1 /* number of possible configurations */
66  )
67 };
68 static const USBDescriptor deviceDescriptor = {
69  sizeof(deviceDescriptorData),
71 };
72 
73 /* configuration descriptor */
75  /* configuration descriptor */
76  USB_DESC_CONFIGURATION
77  (
78  32, /* total length */
79  1, /* number of interfaces */
80  1, /* value that selects this configuration */
81  0, /* index of string descriptor describing this configuration */
82  0xC0, /* attributes (self-powered) */
83  50 /* max power (100 mA) */
84  ),
85 
86  /* interface descriptor */
87  USB_DESC_INTERFACE
88  (
89  0, /* interface number */
90  0, /* value used to select alternative setting */
91  2, /* number of end-points used by this interface */
92  0x08, /* interface class (Mass Storage) */
93  0x06, /* interface sub-class (SCSI Transparent Storage) */
94  0x50, /* interface protocol (Bulk Only) */
95  0 /* index of string descriptor describing this interface */
96  ),
97 
98  /* end-point descriptor */
99  USB_DESC_ENDPOINT
100  (
101  USB_MS_DATA_EP | 0x80, /* address (end point index | OUT direction) */
102  USB_EP_MODE_TYPE_BULK, /* attributes (bulk) */
103  64, /* max packet size */
104  0x05 /* polling interval (ignored for bulk end-points) */
105  ),
106 
107  /* end-point descriptor */
108  USB_DESC_ENDPOINT
109  (
110  USB_MS_DATA_EP | 0x00, /* address (end point index | IN direction) */
111  USB_EP_MODE_TYPE_BULK, /* attributes (bulk) */
112  64, /* max packet size */
113  0x05 /* polling interval (ignored for bulk end-points) */
114  )
115 };
116 static const USBDescriptor configurationDescriptor = {
118  configurationDescriptorData
119 };
120 
121 /* Language descriptor */
122 static const uint8_t languageDescriptorData[] = {
123  USB_DESC_BYTE(4),
124  USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
125  USB_DESC_WORD(0x0409) /* U.S. english */
126 };
127 static const USBDescriptor languageDescriptor = {
128  sizeof(languageDescriptorData),
129  languageDescriptorData
130 };
131 
132 /* Vendor descriptor */
133 static const uint8_t vendorDescriptorData[] = {
134  USB_DESC_BYTE(20),
135  USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
136  'P', 0, 'a', 0, 'p', 0, 'a', 0, 'r', 0, 'a', 0, 'z', 0, 'z', 0, 'i', 0
137 };
138 static const USBDescriptor vendorDescriptor = {
139  sizeof(vendorDescriptorData),
140  vendorDescriptorData
141 };
142 
143 /* Product descriptor */
144 static const uint8_t productDescriptorData[] = {
145  USB_DESC_BYTE(20),
146  USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
147  'A', 0, 'u', 0, 't', 0, 'o', 0, 'p', 0, 'i', 0, 'l', 0, 'o', 0, 't', 0
148 };
149 static const USBDescriptor productDescriptor = {
150  sizeof(productDescriptorData),
151  productDescriptorData
152 };
153 
154 /* Serial number descriptor from stm32 uniq id */
155 /* uniq id is 12 bytes which gives 24 char which require 50 bytes for usb description */
156 /* this array is the only one in ram (others in flash), and should be populated before */
157 /* usb initialisation */
159  USB_DESC_BYTE(50),
160  USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
161  0
162 };
163 static const USBDescriptor serialNumberDescriptor = {
165  serialNumberDescriptorData
166 };
167 
168 /* Handles GET_DESCRIPTOR requests from the USB host */
169 static const USBDescriptor *getDescriptor(USBDriver *usbp, uint8_t type, uint8_t index, uint16_t lang)
170 {
171  (void)usbp;
172  (void)lang;
173 
174  switch (type) {
175  case USB_DESCRIPTOR_DEVICE:
176  return &deviceDescriptor;
177 
178  case USB_DESCRIPTOR_CONFIGURATION:
179  return &configurationDescriptor;
180 
181  case USB_DESCRIPTOR_STRING:
182  switch (index) {
183  case 0: return &languageDescriptor;
184  case 1: return &vendorDescriptor;
185  case 2: return &productDescriptor;
186  case 3: return &serialNumberDescriptor;
187  }
188  }
189 
190  return 0;
191 }
192 
193 /* Handles global events of the USB driver */
194 static void usbEvent(USBDriver *usbp, usbevent_t event)
195 {
196  (void) usbp;
197 
198  switch (event) {
199  case USB_EVENT_CONFIGURED:
200  chSysLockFromISR();
201  msdConfigureHookI(&UMSD1);
202  chSysUnlockFromISR();
203  break;
204 
205  case USB_EVENT_RESET:
206  case USB_EVENT_ADDRESS:
207  case USB_EVENT_SUSPEND:
208  case USB_EVENT_WAKEUP:
209  case USB_EVENT_STALLED:
210  default:
211  break;
212  }
213 }
214 
215 /* Configuration of the USB driver */
216 const USBConfig usbConfig = {
217  usbEvent,
220  0
221 };
222 
223 /* Turns on a LED when there is I/O activity on the USB port */
224 static void usbActivity(bool active)
225 {
226  palWritePad(GPIOC, GPIOC_LED4, active);
227 }
228 
229 /* USB mass storage configuration */
231  &USBD1,
232  (BaseBlockDevice *) &SDCD1,
234  &usbActivity,
235  "DPprz_sd",
236  "DApogee",
237  "0.1"
238 };
239 
240 
241 static THD_WORKING_AREA(waThdUsbStorage, 1024);
243 {
245  usbStorageThreadPtr = chThdCreateStatic(waThdUsbStorage, sizeof(waThdUsbStorage),
246  NORMALPRIO + 2, thdUsbStorage, NULL);
247 
248 }
249 
250 
252 {
253  if (usbStorageThreadPtr != NULL) {
254  chThdWait(usbStorageThreadPtr);
255  }
256  usbStorageThreadPtr = NULL;
257 }
258 
259 void usbStorageStop(void)
260 {
261  if (usbStorageThreadPtr != NULL) {
262  chThdTerminate(usbStorageThreadPtr);
263  }
264 }
265 
266 
267 
268 
269 static void thdUsbStorage(void *arg)
270 {
271  (void) arg;
272 
273  chRegSetThreadName("UsbStorage:polling");
274  uint antiBounce = 5;
275  event_listener_t connected;
276 
277  // Should use EXTI interrupt instead of active polling,
278  // but in the chibios_opencm3 implementation, since EXTI is
279  // used via libopencm3, ISR are routed on pprz/opencm3 and cannot
280  // be used concurrently by chibios api
281  // Should be fixed when using chibios-rt branch
282  while (!chThdShouldTerminateX() && antiBounce) {
283  const bool usbConnected = palReadPad(GPIOA, GPIOA_OTG_FS_VBUS);
284  if (usbConnected) {
285  antiBounce--;
286  } else {
287  antiBounce = 5;
288  }
289 
290  chThdSleepMilliseconds(20);
291  }
292  isRunning = true;
293  chRegSetThreadName("UsbStorage:connected");
294 
295  /* Stop the logs*/
296  sdlog_chibios_finish(false);
297 
298 
299  /* connect sdcard sdc interface sdio */
300  if (sdio_connect() == false) {
301  chThdExit(MSG_TIMEOUT);
302  }
303 
304  /* initialize the USB mass storage driver */
305  msdInit(&UMSD1);
306 
307  /* start the USB mass storage service */
308  msdStart(&UMSD1, &msdConfig);
309 
310  /* start the USB driver */
311  usbDisconnectBus(&USBD1);
312  chThdSleepMilliseconds(1000);
313  usbStart(&USBD1, &usbConfig);
314  usbConnectBus(&USBD1);
315 
316  /* wait for a real usb storage connexion before shutting down autopilot */
317  chEvtRegisterMask(&UMSD1.evt_connected, &connected, EVENT_MASK(1));
318  chEvtWaitOne(EVENT_MASK(1));
319 
320  /* stop autopilot */
322 
323  /* wait until usb-storage is unmount and usb cable is unplugged*/
324  while (!chThdShouldTerminateX() && palReadPad(GPIOA, GPIOA_OTG_FS_VBUS)) {
325  chThdSleepMilliseconds(10);
326  }
327 
328 
329  /* then close open descriptors and reboot autopilot */
330  usbDisconnectBus(&USBD1);
331  chThdSleepMilliseconds(500);
332  msdStop(&UMSD1);
333  sdio_disconnect();
334 
335  MCU_RESTART();
336  return;
337 }
338 
340 {
341  return isRunning;
342 }
343 
345 {
346  nibble &= 0x0F;
347  return nibble < 10 ? nibble + '0' : nibble + 'A' - 10;
348 }
349 
350 
352 {
353  const uint8_t *UniqProcessorId = (uint8_t *) 0x1FFF7A10;
354  const uint8_t UniqProcessorIdLen = 12;
355 
356  uint8_t *baseDdPtr = &serialNumberDescriptorData[2];
357  for (uint32_t i = 0; i < UniqProcessorIdLen; i++) {
358  *baseDdPtr++ = nibbleToHex(UniqProcessorId[i] >> 4);
359  *baseDdPtr++ = 0;
360  *baseDdPtr++ = nibbleToHex(UniqProcessorId[i]);
361  *baseDdPtr++ = 0;
362  }
363 }
364 
unsigned short uint16_t
Definition: types.h:16
void msdStop(USBMassStorageDriver *msdp)
Stops a USB mass storage driver.
Definition: usb_msd.c:866
#define GPIOA
Definition: gpio_arch.h:34
static void usbActivity(bool active)
Definition: usbStorage.c:224
void msdConfigureHookI(USBMassStorageDriver *msdp)
USB device configured handler.
Definition: usb_msd.c:173
arch independent SDIO API
static bool isRunning
Definition: usbStorage.c:43
static uint8_t nibbleToHex(uint8_t nibble)
Definition: usbStorage.c:344
#define GPIOC
Definition: gpio_arch.h:34
void msdInit(USBMassStorageDriver *msdp)
Initializse a USB mass storage driver.
Definition: usb_msd.c:782
static void usbEvent(USBDriver *usbp, usbevent_t event)
Definition: usbStorage.c:194
bool sdio_disconnect(void)
Disconnect a SD card on SDIO peripheral.
Definition: sdio_arch.c:85
static const USBDescriptor languageDescriptor
Definition: usbStorage.c:127
event_source_t evt_connected
Definition: usb_msd.h:157
static const USBDescriptor deviceDescriptor
Definition: usbStorage.c:68
static const uint8_t productDescriptorData[]
Definition: usbStorage.c:144
static const USBDescriptor serialNumberDescriptor
Definition: usbStorage.c:163
static thread_t * usbStorageThreadPtr
Definition: usbStorage.c:40
bool sdio_connect(void)
Connect a SD card on SDIO peripheral.
Definition: sdio_arch.c:46
static const uint8_t languageDescriptorData[]
Definition: usbStorage.c:122
static const USBDescriptor configurationDescriptor
Definition: usbStorage.c:116
USB mass storage driver structure.
Definition: usb_msd.h:153
static void thdUsbStorage(void *arg)
Definition: usbStorage.c:269
Driver configuration structure.
Definition: usb_msd.h:104
void usbStorageStartPolling(void)
Definition: usbStorage.c:242
unsigned long uint32_t
Definition: types.h:18
static void populateSerialNumberDescriptorData(void)
Definition: usbStorage.c:351
#define USB_MS_DATA_EP
Definition: usbStorage.c:46
static USBMassStorageConfig msdConfig
Definition: usbStorage.c:230
uint8_t serialNumberDescriptorData[50]
Definition: usbStorage.c:158
static const uint8_t vendorDescriptorData[]
Definition: usbStorage.c:133
#define MCU_RESTART()
Definition: usbStorage.c:48
unsigned char uint8_t
Definition: types.h:14
static USBMassStorageDriver UMSD1
Definition: usbStorage.c:42
void usbStorageWaitForDeconnexion(void)
Definition: usbStorage.c:251
#define GPIOC_LED4
Definition: board.h:96
static const USBDescriptor * getDescriptor(USBDriver *usbp, uint8_t type, uint8_t index, uint16_t lang)
Definition: usbStorage.c:169
bool usbStorageIsItRunning(void)
Definition: usbStorage.c:339
void sdlog_chibios_finish(bool flush)
void usbStorageStop(void)
Definition: usbStorage.c:259
static THD_WORKING_AREA(waThdUsbStorage, 1024)
static const USBDescriptor vendorDescriptor
Definition: usbStorage.c:138
static const USBDescriptor productDescriptor
Definition: usbStorage.c:149
void msdStart(USBMassStorageDriver *msdp, const USBMassStorageConfig *config)
Starts a USB mass storage driver.
Definition: usb_msd.c:820
void pprz_terminate_autopilot_threads(void)
Terminate all autopilot threads Wait until proper stop.
Definition: main_chibios.c:151
const USBConfig usbConfig
Definition: usbStorage.c:216
bool msdRequestsHook(USBDriver *usbp)
Default requests hook.
Definition: usb_msd.c:188
static const uint8_t configurationDescriptorData[]
Definition: usbStorage.c:74
static const uint8_t deviceDescriptorData[]
Definition: usbStorage.c:51
#define GPIOA_OTG_FS_VBUS
Definition: board.h:68