diff --git a/radio/src/cli.cpp b/radio/src/cli.cpp index 54985b4df..bfafee823 100644 --- a/radio/src/cli.cpp +++ b/radio/src/cli.cpp @@ -874,30 +874,14 @@ int cliSet(const char **argv) } #if defined(ENABLE_SERIAL_PASSTHROUGH) -// static StreamBufferHandle_t spIntRxBuffer; - -// static void spRx(uint8_t data) -// { -// BaseType_t xHigherPriorityTaskWoken = pdFALSE; -// xStreamBufferSendFromISR(spIntRxBuffer, &data, 1, -// &xHigherPriorityTaskWoken); -// xTaskNotifyFromISR(cliTaskId.rtos_handle, 0, eNoAction, -// &xHigherPriorityTaskWoken); - -// // might effect a context switch on ISR exit -// portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); -// } - static void spInternalModuleTx(uint8_t* buf, uint32_t len) { intmoduleSendBuffer(buf, len); intmoduleWaitForTxCompleted(); } -static void spSerialTx(uint8_t data) -{ - serialPutc(data); -} +extern bool cdcConnected; +uint32_t usbSerialFreeSpace(); int cliSerialPassthrough(const char **argv) { @@ -945,6 +929,9 @@ int cliSerialPassthrough(const char **argv) stopPulsesExternalModule(); #endif + // suspend RTOS scheduler + vTaskSuspendAll(); + #if defined(HARDWARE_INTERNAL_MODULE) if (port_n == INTERNAL_MODULE) { @@ -954,20 +941,31 @@ int cliSerialPassthrough(const char **argv) etx_serial_init params; params.baudrate = baudrate; params.rx_enable = true; - params.on_receive = spSerialTx; - intmoduleSerialStart(¶ms); + intmoduleSerialStart(¶ms); cliReceiveCallBack = spInternalModuleTx; - - // loop forever - for (;;) { + + // loop until cable disconnected + while (cdcConnected) { + + uint8_t data; + if (intmoduleFifo.pop(data)) { + uint8_t timeout = 10; // 10 ms + while(!usbSerialFreeSpace() && (timeout > 0)) { + delay_ms(1); + timeout--; + } + + usbSerialPutc(data); + } + + // RTOS_WAIT_MS(200); // keep us up & running WDG_RESET(); - RTOS_WAIT_MS(200); } - intmoduleSerialStop(); + intmoduleStop(); // TODO: reset cli rx callback } #endif @@ -975,6 +973,12 @@ int cliSerialPassthrough(const char **argv) // TODO: // - external module (S.PORT?) // - how to exit this mode ??? USB exit ? + + watchdogSuspend(200/*2s*/); + resumePulses(); + + // suspend RTOS scheduler + xTaskResumeAll(); } else { serialPrint("%s: invalid port type '%s'", port_type); diff --git a/radio/src/targets/common/arm/stm32/usbd_cdc.cpp b/radio/src/targets/common/arm/stm32/usbd_cdc.cpp index b8f48581a..332600e5d 100644 --- a/radio/src/targets/common/arm/stm32/usbd_cdc.cpp +++ b/radio/src/targets/common/arm/stm32/usbd_cdc.cpp @@ -151,6 +151,21 @@ uint16_t usbWraps = 0; uint16_t charsWritten = 0; uint16_t usbTxErrors = 0; +// return the bytes free in the circular buffer +uint32_t usbSerialFreeSpace() +{ + // functionally equivalent to: + // + // (APP_Rx_ptr_out > APP_Rx_ptr_in ? APP_Rx_ptr_out - APP_Rx_ptr_in : + // APP_RX_DATA_SIZE - APP_Rx_ptr_in + APP_Rx_ptr_in) + // + // but without the impact of the condition check. + + return ((APP_Rx_ptr_out - APP_Rx_ptr_in) + + (-((int)(APP_Rx_ptr_out <= APP_Rx_ptr_in)) & APP_RX_DATA_SIZE)) - + 1; +} + void usbSerialPutc(uint8_t c) { /* @@ -172,14 +187,6 @@ void usbSerialPutc(uint8_t c) txDataLen -= APP_RX_DATA_SIZE; } - // buffer is too full, skip this write - if (txDataLen > (APP_RX_DATA_SIZE - CDC_DATA_MAX_PACKET_SIZE)) { - usbTxErrors++; - return; - } - - ++charsWritten; - /* APP_Rx_Buffer and associated variables must be modified atomically, because they are used from the interrupt diff --git a/radio/src/targets/common/arm/stm32/usbd_conf.h b/radio/src/targets/common/arm/stm32/usbd_conf.h index 28e830242..39b663734 100644 --- a/radio/src/targets/common/arm/stm32/usbd_conf.h +++ b/radio/src/targets/common/arm/stm32/usbd_conf.h @@ -59,8 +59,13 @@ #define CDC_DATA_MAX_PACKET_SIZE 64 /* Endpoint IN & OUT Packet size */ #define CDC_CMD_PACKET_SZE 8 /* Control Endpoint Packet size */ +#if defined(STM32F2) #define CDC_IN_FRAME_INTERVAL 4 /* Number of frames between IN transfers */ #define APP_RX_DATA_SIZE 512 /* Total size of IN buffer: APP_RX_DATA_SIZE*8/MAX_BAUDARATE*1000 should be > CDC_IN_FRAME_INTERVAL */ +#else +#define CDC_IN_FRAME_INTERVAL 15 /* Number of frames between IN transfers */ +#define APP_RX_DATA_SIZE 2048 /* Total size of IN buffer: APP_RX_DATA_SIZE*8/MAX_BAUDARATE*1000 should be > CDC_IN_FRAME_INTERVAL */ +#endif #define APP_FOPS VCP_fops #endif // _USBD_CONF_H_ diff --git a/radio/src/thirdparty/STM32_USB-Host-Device_Lib_V2.2.0/Libraries/STM32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c b/radio/src/thirdparty/STM32_USB-Host-Device_Lib_V2.2.0/Libraries/STM32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c index 87fbf3fd0..5df0ac77f 100644 --- a/radio/src/thirdparty/STM32_USB-Host-Device_Lib_V2.2.0/Libraries/STM32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c +++ b/radio/src/thirdparty/STM32_USB-Host-Device_Lib_V2.2.0/Libraries/STM32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c @@ -186,14 +186,14 @@ __ALIGN_BEGIN uint8_t APP_Rx_Buffer [APP_RX_DATA_SIZE] __ALIGN_END ; #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ __ALIGN_BEGIN uint8_t CmdBuff[CDC_CMD_PACKET_SZE] __ALIGN_END ; -volatile uint32_t APP_Rx_ptr_in = 0; // modified by OpenTX -volatile uint32_t APP_Rx_ptr_out = 0; // modified by OpenTX +uint32_t APP_Rx_ptr_in = 0; +uint32_t APP_Rx_ptr_out = 0; uint32_t APP_Rx_length = 0; uint8_t USB_Tx_State = USB_CDC_IDLE; static uint32_t cdcCmd = 0xFF; -static uint8_t cdcLen = 0; // modified by OpenTX +static uint32_t cdcLen = 0; // modified by OpenTX /* CDC interface class callbacks structure */ const USBD_Class_cb_TypeDef USBD_CDC_cb = // modified by OpenTX