From 7445add2803bea10fa6ad6877944aee7f650401a Mon Sep 17 00:00:00 2001 From: Steve Evans Date: Sun, 26 Apr 2015 03:05:47 +0100 Subject: [PATCH] OP-1849 Hooks all in place for CDC line state changes to drive port GPIO for DTR --- flight/modules/ComUsbBridge/ComUsbBridge.c | 21 +++++++- flight/pios/common/pios_com.c | 50 +++++++++++++++++++ flight/pios/inc/pios_com.h | 1 + flight/pios/inc/pios_usart_priv.h | 1 + flight/pios/stm32f4xx/pios_usart.c | 49 ++++++------------ flight/pios/stm32f4xx/pios_usb_cdc.c | 26 ++++++++++ .../targets/boards/revolution/board_hw_defs.c | 10 ++++ 7 files changed, 123 insertions(+), 35 deletions(-) diff --git a/flight/modules/ComUsbBridge/ComUsbBridge.c b/flight/modules/ComUsbBridge/ComUsbBridge.c index ad3cad4ce..400b921ac 100644 --- a/flight/modules/ComUsbBridge/ComUsbBridge.c +++ b/flight/modules/ComUsbBridge/ComUsbBridge.c @@ -43,6 +43,7 @@ static void com2UsbBridgeTask(void *parameters); static void usb2ComBridgeTask(void *parameters); static void updateSettings(UAVObjEvent *ev); +static void usb2ComBridgeSetCtrlLine(uint32_t com_id, uint32_t mask, uint32_t state); // **************** // Private constants @@ -95,8 +96,16 @@ static int32_t comUsbBridgeStart(void) static int32_t comUsbBridgeInitialize(void) { // TODO: Get from settings object - usart_port = PIOS_COM_BRIDGE; - vcp_port = PIOS_COM_VCP; + usart_port = PIOS_COM_BRIDGE; + vcp_port = PIOS_COM_VCP; + + // Register the call back handler for USB control line changes to simply + // pass these onto any handler registered on the USART + if (vcp_port) { + PIOS_COM_RegisterCtrlLineCallback(vcp_port, + usb2ComBridgeSetCtrlLine, + usart_port); + } #ifdef MODULE_COMUSBBRIDGE_BUILTIN bridge_enabled = true; @@ -168,6 +177,14 @@ static void usb2ComBridgeTask(__attribute__((unused)) void *parameters) } } +/* This routine is registered with the USB driver and will be called in the + * event of a control line state change. It will then call down to the USART + * driver to drive the required control line state. + */ +static void usb2ComBridgeSetCtrlLine(uint32_t com_id, uint32_t mask, uint32_t state) +{ + PIOS_COM_SetCtrlLine(com_id, mask, state); +} static void updateSettings(__attribute__((unused)) UAVObjEvent *ev) { diff --git a/flight/pios/common/pios_com.c b/flight/pios/common/pios_com.c index 07e703ba2..9a4b83f60 100644 --- a/flight/pios/common/pios_com.c +++ b/flight/pios/common/pios_com.c @@ -283,6 +283,56 @@ int32_t PIOS_COM_ChangeBaud(uint32_t com_id, uint32_t baud) return 0; } +/** + * Set control lines associated with the port + * \param[in] port COM port + * \param[in] mask Lines to change + * \param[in] state New state for lines + * \return -1 if port not available + * \return 0 on success + */ +int32_t PIOS_COM_SetCtrlLine(uint32_t com_id, uint32_t mask, uint32_t state) +{ + struct pios_com_dev *com_dev = (struct pios_com_dev *)com_id; + + if (!PIOS_COM_validate(com_dev)) { + /* Undefined COM port for this board (see pios_board.c) */ + return -1; + } + + /* Invoke the driver function if it exists */ + if (com_dev->driver->set_ctrl_line) { + com_dev->driver->set_ctrl_line(com_dev->lower_id, mask, state); + } + + return 0; +} + +/** + * Set control lines associated with the port + * \param[in] port COM port + * \param[in] ctrl_line_cb Callback function + * \param[in] context context to pass to the callback function + * \return -1 if port not available + * \return 0 on success + */ +int32_t PIOS_COM_RegisterCtrlLineCallback(uint32_t com_id, pios_com_callback_ctrl_line ctrl_line_cb, uint32_t context) +{ + struct pios_com_dev *com_dev = (struct pios_com_dev *)com_id; + + if (!PIOS_COM_validate(com_dev)) { + /* Undefined COM port for this board (see pios_board.c) */ + return -1; + } + + /* Invoke the driver function if it exists */ + if (com_dev->driver->bind_ctrl_line_cb) { + com_dev->driver->bind_ctrl_line_cb(com_dev->lower_id, ctrl_line_cb, context); + } + + return 0; +} + static int32_t PIOS_COM_SendBufferNonBlockingInternal(struct pios_com_dev *com_dev, const uint8_t *buffer, uint16_t len) { diff --git a/flight/pios/inc/pios_com.h b/flight/pios/inc/pios_com.h index bf7fd6d84..b2591e4f0 100644 --- a/flight/pios/inc/pios_com.h +++ b/flight/pios/inc/pios_com.h @@ -58,6 +58,7 @@ struct pios_com_driver { extern int32_t PIOS_COM_Init(uint32_t *com_id, const struct pios_com_driver *driver, uint32_t lower_id, uint8_t *rx_buffer, uint16_t rx_buffer_len, uint8_t *tx_buffer, uint16_t tx_buffer_len); extern int32_t PIOS_COM_ChangeBaud(uint32_t com_id, uint32_t baud); extern int32_t PIOS_COM_SetCtrlLine(uint32_t com_id, uint32_t mask, uint32_t state); +extern int32_t PIOS_COM_RegisterCtrlLineCallback(uint32_t usart_id, pios_com_callback_ctrl_line ctrl_line_cb, uint32_t context); extern int32_t PIOS_COM_SendCharNonBlocking(uint32_t com_id, char c); extern int32_t PIOS_COM_SendChar(uint32_t com_id, char c); extern int32_t PIOS_COM_SendBufferNonBlocking(uint32_t com_id, const uint8_t *buffer, uint16_t len); diff --git a/flight/pios/inc/pios_usart_priv.h b/flight/pios/inc/pios_usart_priv.h index 52394e5f4..68a44bc9d 100644 --- a/flight/pios/inc/pios_usart_priv.h +++ b/flight/pios/inc/pios_usart_priv.h @@ -44,6 +44,7 @@ struct pios_usart_cfg { USART_InitTypeDef init; struct stm32_gpio rx; struct stm32_gpio tx; + struct stm32_gpio dtr; struct stm32_irq irq; }; diff --git a/flight/pios/stm32f4xx/pios_usart.c b/flight/pios/stm32f4xx/pios_usart.c index fa7fefa17..3f030131a 100644 --- a/flight/pios/stm32f4xx/pios_usart.c +++ b/flight/pios/stm32f4xx/pios_usart.c @@ -43,18 +43,16 @@ static void PIOS_USART_ChangeBaud(uint32_t usart_id, uint32_t baud); static void PIOS_USART_SetCtrlLine(uint32_t usart_id, uint32_t mask, uint32_t state); static void PIOS_USART_RegisterRxCallback(uint32_t usart_id, pios_com_callback rx_in_cb, uint32_t context); static void PIOS_USART_RegisterTxCallback(uint32_t usart_id, pios_com_callback tx_out_cb, uint32_t context); -static void PIOS_USART_RegisterCtrlLineCallback(uint32_t usart_id, pios_com_callback_ctrl_line ctrl_line_cb, uint32_t context); static void PIOS_USART_TxStart(uint32_t usart_id, uint16_t tx_bytes_avail); static void PIOS_USART_RxStart(uint32_t usart_id, uint16_t rx_bytes_avail); const struct pios_com_driver pios_usart_com_driver = { - .set_baud = PIOS_USART_ChangeBaud, - .set_ctrl_line = PIOS_USART_SetCtrlLine, - .tx_start = PIOS_USART_TxStart, - .rx_start = PIOS_USART_RxStart, - .bind_tx_cb = PIOS_USART_RegisterTxCallback, - .bind_rx_cb = PIOS_USART_RegisterRxCallback, - .bind_ctrl_line_cb = PIOS_USART_RegisterCtrlLineCallback, + .set_baud = PIOS_USART_ChangeBaud, + .set_ctrl_line = PIOS_USART_SetCtrlLine, + .tx_start = PIOS_USART_TxStart, + .rx_start = PIOS_USART_RxStart, + .bind_tx_cb = PIOS_USART_RegisterTxCallback, + .bind_rx_cb = PIOS_USART_RegisterRxCallback, }; enum pios_usart_dev_magic { @@ -69,8 +67,6 @@ struct pios_usart_dev { uint32_t rx_in_context; pios_com_callback tx_out_cb; uint32_t tx_out_context; - pios_com_callback_ctrl_line ctrl_line_cb; - uint32_t ctrl_line_context; }; static bool PIOS_USART_validate(struct pios_usart_dev *usart_dev) @@ -195,16 +191,16 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg) GPIO_Init(usart_dev->cfg->rx.gpio, (GPIO_InitTypeDef *)&usart_dev->cfg->rx.init); GPIO_Init(usart_dev->cfg->tx.gpio, (GPIO_InitTypeDef *)&usart_dev->cfg->tx.init); + /* If a DTR line is specified, initialize it */ + if (usart_dev->cfg->dtr.gpio) { + GPIO_Init(usart_dev->cfg->dtr.gpio, (GPIO_InitTypeDef *)&usart_dev->cfg->dtr.init); + } + /* Configure the USART */ USART_Init(usart_dev->cfg->regs, (USART_InitTypeDef *)&usart_dev->cfg->init); *usart_id = (uint32_t)usart_dev; - /* Set initial control line state */ - PIOS_USART_SetCtrlLine((uint32_t)usart_dev, - COM_CTRL_LINE_DTR_MASK | COM_CTRL_LINE_RTS_MASK, - COM_CTRL_LINE_DTR_MASK | COM_CTRL_LINE_RTS_MASK); - /* Configure USART Interrupts */ switch ((uint32_t)usart_dev->cfg->regs) { case (uint32_t)USART1: @@ -295,8 +291,11 @@ static void PIOS_USART_SetCtrlLine(uint32_t usart_id, uint32_t mask, uint32_t st PIOS_Assert(valid); - if (usart_dev->ctrl_line_cb) { - (usart_dev->ctrl_line_cb)(usart_dev->ctrl_line_context, mask, state); + /* Only attempt to drive DTR if this USART has a GPIO line defined */ + if (usart_dev->cfg->dtr.gpio && (mask & COM_CTRL_LINE_DTR_MASK)) { + GPIO_WriteBit(usart_dev->cfg->dtr.gpio, + usart_dev->cfg->dtr.init.GPIO_Pin, + state & COM_CTRL_LINE_DTR_MASK ? Bit_SET : Bit_RESET); } } @@ -332,22 +331,6 @@ static void PIOS_USART_RegisterTxCallback(uint32_t usart_id, pios_com_callback t usart_dev->tx_out_cb = tx_out_cb; } -static void PIOS_USART_RegisterCtrlLineCallback(uint32_t usart_id, pios_com_callback_ctrl_line ctrl_line_cb, uint32_t context) -{ - struct pios_usart_dev *usart_dev = (struct pios_usart_dev *)usart_id; - - bool valid = PIOS_USART_validate(usart_dev); - - PIOS_Assert(valid); - - /* - * Order is important in these assignments since ISR uses _cb - * field to determine if it's ok to dereference _cb and _context - */ - usart_dev->ctrl_line_context = context; - usart_dev->ctrl_line_cb = ctrl_line_cb; -} - static void PIOS_USART_generic_irq_handler(uint32_t usart_id) { struct pios_usart_dev *usart_dev = (struct pios_usart_dev *)usart_id; diff --git a/flight/pios/stm32f4xx/pios_usb_cdc.c b/flight/pios/stm32f4xx/pios_usb_cdc.c index 253295d94..277165af2 100644 --- a/flight/pios/stm32f4xx/pios_usb_cdc.c +++ b/flight/pios/stm32f4xx/pios_usb_cdc.c @@ -40,6 +40,7 @@ /* Implement COM layer driver API */ static void PIOS_USB_CDC_RegisterTxCallback(uint32_t usbcdc_id, pios_com_callback tx_out_cb, uint32_t context); static void PIOS_USB_CDC_RegisterRxCallback(uint32_t usbcdc_id, pios_com_callback rx_in_cb, uint32_t context); +static void PIOS_USB_CDC_RegisterCtrlLineCallback(uint32_t usbcdc_id, pios_com_callback_ctrl_line ctrl_line_cb, uint32_t context); static void PIOS_USB_CDC_TxStart(uint32_t usbcdc_id, uint16_t tx_bytes_avail); static void PIOS_USB_CDC_RxStart(uint32_t usbcdc_id, uint16_t rx_bytes_avail); static bool PIOS_USB_CDC_Available(uint32_t usbcdc_id); @@ -49,6 +50,7 @@ const struct pios_com_driver pios_usb_cdc_com_driver = { .rx_start = PIOS_USB_CDC_RxStart, .bind_tx_cb = PIOS_USB_CDC_RegisterTxCallback, .bind_rx_cb = PIOS_USB_CDC_RegisterRxCallback, + .bind_ctrl_line_cb = PIOS_USB_CDC_RegisterCtrlLineCallback, .available = PIOS_USB_CDC_Available, }; @@ -66,6 +68,8 @@ struct pios_usb_cdc_dev { uint32_t rx_in_context; pios_com_callback tx_out_cb; uint32_t tx_out_context; + pios_com_callback_ctrl_line ctrl_line_cb; + uint32_t ctrl_line_context; bool usb_ctrl_if_enabled; bool usb_data_if_enabled; @@ -323,6 +327,23 @@ static void PIOS_USB_CDC_RegisterTxCallback(uint32_t usbcdc_id, pios_com_callbac usb_cdc_dev->tx_out_cb = tx_out_cb; } +static void PIOS_USB_CDC_RegisterCtrlLineCallback(uint32_t usbcdc_id, pios_com_callback_ctrl_line ctrl_line_cb, uint32_t context) +{ + struct pios_usb_cdc_dev *usb_cdc_dev = (struct pios_usb_cdc_dev *)usbcdc_id; + + bool valid = PIOS_USB_CDC_validate(usb_cdc_dev); + + PIOS_Assert(valid); + + /* + * Order is important in these assignments since ISR uses _cb + * field to determine if it's ok to dereference _cb and _context + */ + usb_cdc_dev->ctrl_line_context = context; + usb_cdc_dev->ctrl_line_cb = ctrl_line_cb; +} + + static bool PIOS_USB_CDC_CTRL_EP_IN_Callback(uint32_t usb_cdc_id, uint8_t epnum, uint16_t len); static void PIOS_USB_CDC_CTRL_IF_Init(uint32_t usb_cdc_id) @@ -403,6 +424,11 @@ static bool PIOS_USB_CDC_CTRL_IF_Setup(uint32_t usb_cdc_id, struct usb_setup_req break; case USB_CDC_REQ_SET_CONTROL_LINE_STATE: control_line_state = req->wValue; + if (usb_cdc_dev->ctrl_line_cb) { + (usb_cdc_dev->ctrl_line_cb)(usb_cdc_dev->ctrl_line_context, + 0xff, + control_line_state); + } break; default: /* Unhandled class request */ diff --git a/flight/targets/boards/revolution/board_hw_defs.c b/flight/targets/boards/revolution/board_hw_defs.c index 4d5b8aa22..ea7f5fb92 100644 --- a/flight/targets/boards/revolution/board_hw_defs.c +++ b/flight/targets/boards/revolution/board_hw_defs.c @@ -1112,6 +1112,16 @@ static const struct pios_usart_cfg pios_usart_rcvrport_cfg = { }, }, + .dtr = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_13, // FlexIO pin 4 + .GPIO_Speed = GPIO_Speed_25MHz, + .GPIO_Mode = GPIO_Mode_OUT, + .GPIO_OType = GPIO_OType_PP, + }, + }, + .tx = { // * 7: PC6 = TIM8 CH1, USART6 TX .gpio = GPIOC,