OP-1483 Added velocity filter to correct EKF's velocity estimate for static velocity...
[librepilot.git] / flight / pios / stm32f10x / pios_usb_cdc.c
blobe7c3c1fda2b0f5672270c3a4e4634c11a48e3e3b
1 /**
2 ******************************************************************************
3 * @addtogroup PIOS PIOS Core hardware abstraction layer
4 * @{
5 * @addtogroup PIOS_USB_COM USB COM Functions
6 * @brief PIOS USB COM implementation for CDC interfaces
7 * @notes This implements a CDC Serial Port
8 * @{
10 * @file pios_usb_com_cdc.c
11 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
12 * @brief USB COM functions (STM32 dependent code)
13 * @see The GNU Public License (GPL) Version 3
15 *****************************************************************************/
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.
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.
27 * You should have received a copy of the GNU General Public License along
28 * with this program; if not, write to the Free Software Foundation, Inc.,
29 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "pios.h"
34 #ifdef PIOS_INCLUDE_USB_CDC
36 #include "pios_usb_cdc_priv.h"
37 #include "pios_usb_board_data.h" /* PIOS_BOARD_*_DATA_LENGTH */
39 /* STM32 USB Library Definitions */
40 #include "usb_lib.h"
42 static void PIOS_USB_CDC_RegisterTxCallback(uint32_t usbcdc_id, pios_com_callback tx_out_cb, uint32_t context);
43 static void PIOS_USB_CDC_RegisterRxCallback(uint32_t usbcdc_id, pios_com_callback rx_in_cb, uint32_t context);
44 static void PIOS_USB_CDC_TxStart(uint32_t usbcdc_id, uint16_t tx_bytes_avail);
45 static void PIOS_USB_CDC_RxStart(uint32_t usbcdc_id, uint16_t rx_bytes_avail);
46 static bool PIOS_USB_CDC_Available(uint32_t usbcdc_id);
48 const struct pios_com_driver pios_usb_cdc_com_driver = {
49 .tx_start = PIOS_USB_CDC_TxStart,
50 .rx_start = PIOS_USB_CDC_RxStart,
51 .bind_tx_cb = PIOS_USB_CDC_RegisterTxCallback,
52 .bind_rx_cb = PIOS_USB_CDC_RegisterRxCallback,
53 .available = PIOS_USB_CDC_Available,
56 enum pios_usb_cdc_dev_magic {
57 PIOS_USB_CDC_DEV_MAGIC = 0xAABBCCDD,
60 struct pios_usb_cdc_dev {
61 enum pios_usb_cdc_dev_magic magic;
62 const struct pios_usb_cdc_cfg *cfg;
64 uint32_t lower_id;
66 pios_com_callback rx_in_cb;
67 uint32_t rx_in_context;
68 pios_com_callback tx_out_cb;
69 uint32_t tx_out_context;
71 uint8_t rx_packet_buffer[PIOS_USB_BOARD_CDC_DATA_LENGTH];
73 * NOTE: This is -1 as somewhat of a hack. It ensures that we always send packets
74 * that are strictly < maxPacketSize for this interface which means we never have
75 * to bother with zero length packets (ZLP).
77 uint8_t tx_packet_buffer[PIOS_USB_BOARD_CDC_DATA_LENGTH - 1];
79 uint32_t rx_dropped;
80 uint32_t rx_oversize;
83 static bool PIOS_USB_CDC_validate(struct pios_usb_cdc_dev *usb_cdc_dev)
85 return usb_cdc_dev->magic == PIOS_USB_CDC_DEV_MAGIC;
88 #if defined(PIOS_INCLUDE_FREERTOS)
89 static struct pios_usb_cdc_dev *PIOS_USB_CDC_alloc(void)
91 struct pios_usb_cdc_dev *usb_cdc_dev;
93 usb_cdc_dev = (struct pios_usb_cdc_dev *)pios_malloc(sizeof(struct pios_usb_cdc_dev));
94 if (!usb_cdc_dev) {
95 return NULL;
98 memset(usb_cdc_dev, 0, sizeof(struct pios_usb_cdc_dev));
99 usb_cdc_dev->magic = PIOS_USB_CDC_DEV_MAGIC;
100 return usb_cdc_dev;
102 #else
103 static struct pios_usb_cdc_dev pios_usb_cdc_devs[PIOS_USB_CDC_MAX_DEVS];
104 static uint8_t pios_usb_cdc_num_devs;
105 static struct pios_usb_cdc_dev *PIOS_USB_CDC_alloc(void)
107 struct pios_usb_cdc_dev *usb_cdc_dev;
109 if (pios_usb_cdc_num_devs >= PIOS_USB_CDC_MAX_DEVS) {
110 return NULL;
113 usb_cdc_dev = &pios_usb_cdc_devs[pios_usb_cdc_num_devs++];
115 memset(usb_cdc_dev, 0, sizeof(struct pios_usb_cdc_dev));
116 usb_cdc_dev->magic = PIOS_USB_CDC_DEV_MAGIC;
118 return usb_cdc_dev;
120 #endif /* if defined(PIOS_INCLUDE_FREERTOS) */
122 static void PIOS_USB_CDC_DATA_EP_IN_Callback(void);
123 static void PIOS_USB_CDC_DATA_EP_OUT_Callback(void);
124 static void PIOS_USB_CDC_CTRL_EP_IN_Callback(void);
126 static uint32_t pios_usb_cdc_id;
128 /* Need a better way to pull these in */
129 extern void(*pEpInt_IN[7]) (void);
130 extern void(*pEpInt_OUT[7]) (void);
132 int32_t PIOS_USB_CDC_Init(uint32_t *usbcdc_id, const struct pios_usb_cdc_cfg *cfg, uint32_t lower_id)
134 PIOS_Assert(usbcdc_id);
135 PIOS_Assert(cfg);
137 struct pios_usb_cdc_dev *usb_cdc_dev;
139 usb_cdc_dev = (struct pios_usb_cdc_dev *)PIOS_USB_CDC_alloc();
140 if (!usb_cdc_dev) {
141 goto out_fail;
144 /* Bind the configuration to the device instance */
145 usb_cdc_dev->cfg = cfg;
146 usb_cdc_dev->lower_id = lower_id;
148 pios_usb_cdc_id = (uint32_t)usb_cdc_dev;
150 /* Bind lower level callbacks into the USB infrastructure */
151 pEpInt_OUT[cfg->ctrl_tx_ep - 1] = PIOS_USB_CDC_CTRL_EP_IN_Callback;
152 pEpInt_IN[cfg->data_tx_ep - 1] = PIOS_USB_CDC_DATA_EP_IN_Callback;
153 pEpInt_OUT[cfg->data_rx_ep - 1] = PIOS_USB_CDC_DATA_EP_OUT_Callback;
155 *usbcdc_id = (uint32_t)usb_cdc_dev;
157 return 0;
159 out_fail:
160 return -1;
164 static void PIOS_USB_CDC_RegisterRxCallback(uint32_t usbcdc_id, pios_com_callback rx_in_cb, uint32_t context)
166 struct pios_usb_cdc_dev *usb_cdc_dev = (struct pios_usb_cdc_dev *)usbcdc_id;
168 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
170 PIOS_Assert(valid);
173 * Order is important in these assignments since ISR uses _cb
174 * field to determine if it's ok to dereference _cb and _context
176 usb_cdc_dev->rx_in_context = context;
177 usb_cdc_dev->rx_in_cb = rx_in_cb;
180 static void PIOS_USB_CDC_RegisterTxCallback(uint32_t usbcdc_id, pios_com_callback tx_out_cb, uint32_t context)
182 struct pios_usb_cdc_dev *usb_cdc_dev = (struct pios_usb_cdc_dev *)usbcdc_id;
184 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
186 PIOS_Assert(valid);
189 * Order is important in these assignments since ISR uses _cb
190 * field to determine if it's ok to dereference _cb and _context
192 usb_cdc_dev->tx_out_context = context;
193 usb_cdc_dev->tx_out_cb = tx_out_cb;
196 static void PIOS_USB_CDC_RxStart(uint32_t usbcdc_id, uint16_t rx_bytes_avail)
198 struct pios_usb_cdc_dev *usb_cdc_dev = (struct pios_usb_cdc_dev *)usbcdc_id;
200 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
202 PIOS_Assert(valid);
204 if (!PIOS_USB_CheckAvailable(usb_cdc_dev->lower_id)) {
205 return;
208 // If endpoint was stalled and there is now space make it valid
209 PIOS_IRQ_Disable();
210 if ((GetEPRxStatus(usb_cdc_dev->cfg->data_rx_ep) != EP_RX_VALID) &&
211 (rx_bytes_avail >= sizeof(usb_cdc_dev->rx_packet_buffer))) {
212 SetEPRxStatus(usb_cdc_dev->cfg->data_rx_ep, EP_RX_VALID);
214 PIOS_IRQ_Enable();
217 static void PIOS_USB_CDC_SendData(struct pios_usb_cdc_dev *usb_cdc_dev)
219 uint16_t bytes_to_tx;
221 if (!usb_cdc_dev->tx_out_cb) {
222 return;
225 bool need_yield = false;
226 bytes_to_tx = (usb_cdc_dev->tx_out_cb)(usb_cdc_dev->tx_out_context,
227 usb_cdc_dev->tx_packet_buffer,
228 sizeof(usb_cdc_dev->tx_packet_buffer),
229 NULL,
230 &need_yield);
231 if (bytes_to_tx == 0) {
232 return;
235 UserToPMABufferCopy(usb_cdc_dev->tx_packet_buffer,
236 GetEPTxAddr(usb_cdc_dev->cfg->data_tx_ep),
237 bytes_to_tx);
238 SetEPTxCount(usb_cdc_dev->cfg->data_tx_ep, bytes_to_tx);
239 SetEPTxValid(usb_cdc_dev->cfg->data_tx_ep);
241 #if defined(PIOS_INCLUDE_FREERTOS)
242 if (need_yield) {
243 vPortYield();
245 #endif /* PIOS_INCLUDE_FREERTOS */
248 static void PIOS_USB_CDC_TxStart(uint32_t usbcdc_id, __attribute__((unused)) uint16_t tx_bytes_avail)
250 struct pios_usb_cdc_dev *usb_cdc_dev = (struct pios_usb_cdc_dev *)usbcdc_id;
252 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
254 PIOS_Assert(valid);
256 if (!PIOS_USB_CheckAvailable(usb_cdc_dev->lower_id)) {
257 return;
260 if (GetEPTxStatus(usb_cdc_dev->cfg->data_tx_ep) == EP_TX_VALID) {
261 /* Endpoint is already transmitting */
262 return;
265 PIOS_USB_CDC_SendData(usb_cdc_dev);
268 static void PIOS_USB_CDC_DATA_EP_IN_Callback(void)
270 struct pios_usb_cdc_dev *usb_cdc_dev = (struct pios_usb_cdc_dev *)pios_usb_cdc_id;
272 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
274 PIOS_Assert(valid);
276 PIOS_USB_CDC_SendData(usb_cdc_dev);
279 static void PIOS_USB_CDC_DATA_EP_OUT_Callback(void)
281 struct pios_usb_cdc_dev *usb_cdc_dev = (struct pios_usb_cdc_dev *)pios_usb_cdc_id;
283 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
285 PIOS_Assert(valid);
287 uint32_t DataLength;
289 /* Get the number of received data on the selected Endpoint */
290 DataLength = GetEPRxCount(usb_cdc_dev->cfg->data_rx_ep);
291 if (DataLength > sizeof(usb_cdc_dev->rx_packet_buffer)) {
292 usb_cdc_dev->rx_oversize++;
293 DataLength = sizeof(usb_cdc_dev->rx_packet_buffer);
296 /* Use the memory interface function to read from the selected endpoint */
297 PMAToUserBufferCopy((uint8_t *)usb_cdc_dev->rx_packet_buffer,
298 GetEPRxAddr(usb_cdc_dev->cfg->data_rx_ep),
299 DataLength);
301 if (!usb_cdc_dev->rx_in_cb) {
302 /* No Rx call back registered, disable the receiver */
303 SetEPRxStatus(usb_cdc_dev->cfg->data_rx_ep, EP_RX_NAK);
304 return;
307 uint16_t headroom;
308 bool need_yield = false;
309 uint16_t rc;
310 rc = (usb_cdc_dev->rx_in_cb)(usb_cdc_dev->rx_in_context,
311 usb_cdc_dev->rx_packet_buffer,
312 DataLength,
313 &headroom,
314 &need_yield);
316 if (rc < DataLength) {
317 /* Lost bytes on rx */
318 usb_cdc_dev->rx_dropped += (DataLength - rc);
321 if (headroom >= sizeof(usb_cdc_dev->rx_packet_buffer)) {
322 /* We have room for a maximum length message */
323 SetEPRxStatus(usb_cdc_dev->cfg->data_rx_ep, EP_RX_VALID);
324 } else {
325 /* Not enough room left for a message, apply backpressure */
326 SetEPRxStatus(usb_cdc_dev->cfg->data_rx_ep, EP_RX_NAK);
329 #if defined(PIOS_INCLUDE_FREERTOS)
330 if (need_yield) {
331 vPortYield();
333 #endif /* PIOS_INCLUDE_FREERTOS */
336 static uint16_t control_line_state;
337 RESULT PIOS_USB_CDC_SetControlLineState(void)
339 struct pios_usb_cdc_dev *usb_cdc_dev = (struct pios_usb_cdc_dev *)pios_usb_cdc_id;
341 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
343 if (!valid) {
344 /* No CDC interface is configured */
345 return USB_UNSUPPORT;
348 uint8_t wValue0 = pInformation->USBwValue0;
349 uint8_t wValue1 = pInformation->USBwValue1;
351 control_line_state = wValue1 << 8 | wValue0;
353 return USB_SUCCESS;
356 static bool PIOS_USB_CDC_Available(uint32_t usbcdc_id)
358 struct pios_usb_cdc_dev *usb_cdc_dev = (struct pios_usb_cdc_dev *)usbcdc_id;
360 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
362 PIOS_Assert(valid);
364 return PIOS_USB_CheckAvailable(usb_cdc_dev->lower_id) &&
365 (control_line_state & USB_CDC_CONTROL_LINE_STATE_DTE_PRESENT);
368 static struct usb_cdc_line_coding line_coding = {
369 .dwDTERate = htousbl(57600),
370 .bCharFormat = USB_CDC_LINE_CODING_STOP_1,
371 .bParityType = USB_CDC_LINE_CODING_PARITY_NONE,
372 .bDataBits = 8,
375 uint8_t *PIOS_USB_CDC_SetLineCoding(uint16_t Length)
377 struct pios_usb_cdc_dev *usb_cdc_dev = (struct pios_usb_cdc_dev *)pios_usb_cdc_id;
379 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
381 if (!valid) {
382 /* No CDC interface is configured */
383 return NULL;
386 if (Length == 0) {
387 /* Report the number of bytes we're prepared to consume */
388 pInformation->Ctrl_Info.Usb_wLength = sizeof(line_coding);
389 pInformation->Ctrl_Info.Usb_rLength = sizeof(line_coding);
390 return NULL;
391 } else {
392 /* Give out a pointer to the data struct */
393 return (uint8_t *)&line_coding;
397 const uint8_t *PIOS_USB_CDC_GetLineCoding(uint16_t Length)
399 struct pios_usb_cdc_dev *usb_cdc_dev = (struct pios_usb_cdc_dev *)pios_usb_cdc_id;
401 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
403 if (!valid) {
404 /* No CDC interface is configured */
405 return NULL;
408 if (Length == 0) {
409 pInformation->Ctrl_Info.Usb_wLength = sizeof(line_coding);
410 return NULL;
411 } else {
412 return (uint8_t *)&line_coding;
416 struct usb_cdc_serial_state_report uart_state = {
417 .bmRequestType = 0xA1,
418 .bNotification = USB_CDC_NOTIFICATION_SERIAL_STATE,
419 .wValue = 0,
420 .wIndex = htousbs(1),
421 .wLength = htousbs(2),
422 .bmUartState = htousbs(0),
425 static void PIOS_USB_CDC_CTRL_EP_IN_Callback(void)
427 struct pios_usb_cdc_dev *usb_cdc_dev = (struct pios_usb_cdc_dev *)pios_usb_cdc_id;
429 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
431 PIOS_Assert(valid);
433 /* Give back UART State Bitmap */
434 /* UART State Bitmap
435 * 15-7: reserved
436 * 6: bOverRun overrun error
437 * 5: bParity parity error
438 * 4: bFraming framing error
439 * 3: bRingSignal RI
440 * 2: bBreak break reception
441 * 1: bTxCarrier DSR
442 * 0: bRxCarrier DCD
444 uart_state.bmUartState = htousbs(0x0003);
446 UserToPMABufferCopy((uint8_t *)&uart_state,
447 GetEPTxAddr(usb_cdc_dev->cfg->ctrl_tx_ep),
448 sizeof(uart_state));
449 SetEPTxCount(usb_cdc_dev->cfg->ctrl_tx_ep, PIOS_USB_BOARD_CDC_MGMT_LENGTH);
450 SetEPTxValid(usb_cdc_dev->cfg->ctrl_tx_ep);
453 #endif /* PIOS_INCLUDE_USB_CDC */