From 73790c1654c81a29946c7166cb4541072d445e50 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 15 Nov 2021 23:14:00 +0100 Subject: [PATCH] Use FreeRTOS stream buffers and task notifications --- radio/src/cli.cpp | 81 +++++++++-- radio/src/io/frsky_firmware_update.cpp | 21 ++- radio/src/io/multi_firmware_update.cpp | 9 +- radio/src/pulses/pulses.cpp | 128 ++++++++++++++++-- radio/src/pulses/pulses.h | 1 + .../common/arm/stm32/aux_serial_driver.cpp | 20 ++- .../arm/stm32/intmodule_serial_driver.cpp | 111 ++++++++------- .../arm/stm32/intmodule_serial_driver.h | 43 ++++++ .../src/targets/common/arm/stm32/usbd_cdc.cpp | 11 +- radio/src/targets/horus/board.h | 6 - radio/src/targets/nv14/board.h | 4 - radio/src/targets/taranis/board.h | 8 -- 12 files changed, 329 insertions(+), 114 deletions(-) create mode 100644 radio/src/targets/common/arm/stm32/intmodule_serial_driver.h diff --git a/radio/src/cli.cpp b/radio/src/cli.cpp index cd27740a0..3da3ad5c0 100644 --- a/radio/src/cli.cpp +++ b/radio/src/cli.cpp @@ -27,6 +27,10 @@ #include "cli_traces.h" +#if defined(INTMODULE_USART) +#include "intmodule_serial_driver.h" +#endif + #define CLI_COMMAND_MAX_ARGS 8 #define CLI_COMMAND_MAX_LEN 256 @@ -853,6 +857,20 @@ 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 ); +} + int cliSerialPassthrough(const char **argv) { const char* port_type = argv[1]; @@ -902,36 +920,69 @@ int cliSerialPassthrough(const char **argv) #if defined(HARDWARE_INTERNAL_MODULE) if (port_n == INTERNAL_MODULE) { - // TODO: check the stack level so we don't crash it - uint8_t* tmpBuf = (uint8_t*)malloc(256); + size_t rx_bytes = 0; + + // allocate quick & dirty a buffer on the heap + // to be able to send via DMA + constexpr size_t tmpBufSize = 128; + uint8_t* tmpBuf = (uint8_t*)malloc(tmpBufSize*2); + uint8_t* tmpBuf2 = tmpBuf + tmpBufSize; + + StaticStreamBuffer_t spIntRxBufferStatic; + // uses first half of 'tmpBuf' + spIntRxBuffer = xStreamBufferCreateStatic(tmpBufSize, 1, tmpBuf, &spIntRxBufferStatic); // setup serial com // TODO: // - '8n1' param - intmoduleSerialStart(baudrate, true, USART_Parity_No, USART_StopBits_1, - USART_WordLength_8b); - for (;;) { - /* Block for max 10ms. */ - const TickType_t xTimeout = 10 / RTOS_MS_PER_TICK; - size_t xReceivedBytes = - xStreamBufferReceive(cliRxBuffer, tmpBuf, sizeof(tmpBuf), xTimeout); + etx_serial_init params; + params.baudrate = baudrate; + params.rx_enable = true; + params.on_receive = spRx; + intmoduleSerialStart(¶ms); + // loop forever + for (;;) { + + /* Block for max 100ms. */ + const TickType_t xTimeout = 10 / RTOS_MS_PER_TICK; + BaseType_t notified = xTaskNotifyWait(0, 0, NULL, xTimeout); + // keep us up & running WDG_RESET(); - if (xReceivedBytes) { - // TODO: wait for previous buffer flushed + // Timeout ? + if (notified == pdFALSE) + continue; + + // use 2nd half of 'tmpBuf' + rx_bytes = xStreamBufferBytesAvailable(cliRxBuffer); + if (rx_bytes) { + // debug + GPIO_SetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); + + // wait for end of last transmission intmoduleWaitForTxCompleted(); - intmoduleSendBuffer(tmpBuf, xReceivedBytes); + + rx_bytes = xStreamBufferReceive(cliRxBuffer, tmpBuf2, tmpBufSize, 0); + intmoduleSendBuffer(tmpBuf2, rx_bytes); // sends asynchronously + + // debug + GPIO_ResetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); } // Let's hope this does not starve the other side - uint8_t inData; - while(intmoduleFifo.pop(inData)) { - serialPutc(inData); + uint8_t inData[tmpBufSize]; + rx_bytes = xStreamBufferReceive(spIntRxBuffer, inData, tmpBufSize, 0); + if (rx_bytes) { + for (uint8_t *tx_data = inData; rx_bytes > 0; tx_data++, rx_bytes--) { + serialPutc(*tx_data); // sends synchronously + } } } + intmoduleSerialStop(); + vStreamBufferDelete(spIntRxBuffer); free(tmpBuf); tmpBuf = nullptr; } diff --git a/radio/src/io/frsky_firmware_update.cpp b/radio/src/io/frsky_firmware_update.cpp index 253bab7c5..e48cc688e 100644 --- a/radio/src/io/frsky_firmware_update.cpp +++ b/radio/src/io/frsky_firmware_update.cpp @@ -29,6 +29,10 @@ #include "libopenui/src/libopenui_file.h" #endif +#if defined(INTMODULE_USART) +#include "intmodule_serial_driver.h" +#endif + #define PRIM_REQ_POWERUP 0 #define PRIM_REQ_VERSION 1 #define PRIM_CMD_DOWNLOAD 3 @@ -329,10 +333,16 @@ const char * FrskyDeviceFirmwareUpdate::doFlashFirmware(const char * filename, P if (module == INTERNAL_MODULE && information.productId == FIRMWARE_ID_MODULE_XJT) { INTERNAL_MODULE_ON(); RTOS_WAIT_MS(1); - intmoduleSerialStart(38400, true, USART_Parity_No, USART_StopBits_1, USART_WordLength_8b); + + etx_serial_init params; + params.baudrate = 38400; + params.rx_enable = true; + intmoduleSerialStart(¶ms); + GPIO_SetBits(INTMODULE_BOOTCMD_GPIO, INTMODULE_BOOTCMD_GPIO_PIN); result = uploadFileToHorusXJT(filename, &file, progressHandler); GPIO_ResetBits(INTMODULE_BOOTCMD_GPIO, INTMODULE_BOOTCMD_GPIO_PIN); + f_close(&file); return result; } @@ -340,9 +350,12 @@ const char * FrskyDeviceFirmwareUpdate::doFlashFirmware(const char * filename, P switch (module) { #if defined(INTERNAL_MODULE_PXX2) - case INTERNAL_MODULE: - intmoduleSerialStart(57600, true, USART_Parity_No, USART_StopBits_1, USART_WordLength_8b); - break; + case INTERNAL_MODULE: { + etx_serial_init params; + params.baudrate = 57600; + params.rx_enable = true; + intmoduleSerialStart(¶ms); + } break; #endif default: diff --git a/radio/src/io/multi_firmware_update.cpp b/radio/src/io/multi_firmware_update.cpp index c58b59abf..0edea6075 100644 --- a/radio/src/io/multi_firmware_update.cpp +++ b/radio/src/io/multi_firmware_update.cpp @@ -37,6 +37,10 @@ #include "io/multi_protolist.h" #endif +#if defined(INTMODULE_USART) +#include "intmodule_serial_driver.h" +#endif + #define UPDATE_MULTI_EXT_BIN ".bin" class MultiFirmwareUpdateDriver @@ -77,7 +81,10 @@ class MultiInternalUpdateDriver: public MultiFirmwareUpdateDriver void init(bool inverted) const override { - intmoduleSerialStart(57600, true, USART_Parity_No, USART_StopBits_1, USART_WordLength_8b); + etx_serial_init params; + params.baudrate = 57600; + params.rx_enable = true; + intmoduleSerialStart(¶ms); } bool getByte(uint8_t & byte) const override diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index 4b0bd347f..66bc01999 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -27,6 +27,10 @@ #include "pulses/pxx2.h" #include "pulses/flysky.h" +#if defined(INTMODULE_USART) +#include "intmodule_serial_driver.h" +#endif + uint8_t s_pulses_paused = 0; ModuleState moduleState[NUM_MODULES]; InternalModulePulsesData intmodulePulsesData __DMA; @@ -470,6 +474,24 @@ bool setupPulsesExternalModule(uint8_t protocol) #endif #if defined(HARDWARE_INTERNAL_MODULE) + +#if defined(INTERNAL_MODULE_CRSF) +static void intmoduleCRSF_rx(uint8_t data) +{ + intmoduleFifo.push(data); + + // wakeup mixer when rx buffer is quarter full (16 bytes) + if (intmoduleFifo.size() >= 16) { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xTaskNotifyFromISR(mixerTaskId.rtos_handle, 0, eNoAction, + &xHigherPriorityTaskWoken); + + // might effect a context switch on ISR exit + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } +} +#endif + static void enablePulsesInternalModule(uint8_t protocol) { // start new protocol hardware here @@ -496,8 +518,13 @@ static void enablePulsesInternalModule(uint8_t protocol) #endif #if defined(PXX2) - case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: - intmoduleSerialStart(PXX2_HIGHSPEED_BAUDRATE, true, USART_Parity_No, USART_StopBits_1, USART_WordLength_8b); + case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: { + etx_serial_init params; + params.baudrate = PXX2_HIGHSPEED_BAUDRATE; + params.rx_enable = true; + + intmoduleFifo.clear(); + intmoduleSerialStart(¶ms); resetAccessAuthenticationCount(); #if defined(INTMODULE_HEARTBEAT) @@ -505,30 +532,56 @@ static void enablePulsesInternalModule(uint8_t protocol) init_intmodule_heartbeat(); #endif mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD); - break; + } break; #endif #if defined(INTERNAL_MODULE_MULTI) - case PROTOCOL_CHANNELS_MULTIMODULE: + case PROTOCOL_CHANNELS_MULTIMODULE: { + + // serial port setup + etx_serial_init params; + params.baudrate = MULTIMODULE_BAUDRATE; + params.rx_enable = true; + params.parity = USART_Parity_Even; + params.stop_bits = USART_StopBits_2; + params.word_length = USART_WordLength_9b; + intmodulePulsesData.multi.initFrame(); - intmoduleSerialStart(MULTIMODULE_BAUDRATE, true, USART_Parity_Even, USART_StopBits_2, USART_WordLength_9b); + intmoduleFifo.clear(); + intmoduleSerialStart(¶ms); + + // mixer setup mixerSchedulerSetPeriod(INTERNAL_MODULE, MULTIMODULE_PERIOD); + + // reset status getMultiModuleStatus(INTERNAL_MODULE).failsafeChecked = false; getMultiModuleStatus(INTERNAL_MODULE).flags = 0; + #if defined(MULTI_PROTOLIST) TRACE("enablePulsesInternalModule(): trigger scan"); MultiRfProtocols::instance(INTERNAL_MODULE)->triggerScan(); TRACE("counter = %d", moduleState[INTERNAL_MODULE].counter); #endif - break; + } break; #endif #if defined(INTERNAL_MODULE_CRSF) - case PROTOCOL_CHANNELS_CROSSFIRE: - intmoduleSerialStart(CROSSFIRE_BAUDRATE, true, USART_Parity_No, - USART_StopBits_1, USART_WordLength_8b); + case PROTOCOL_CHANNELS_CROSSFIRE: { + + // serial port setup + etx_serial_init params; + params.baudrate = CROSSFIRE_BAUDRATE; + params.rx_enable = true; + + // wakeup mixer when rx buffer is quarter full (16 bytes) + params.on_receive = intmoduleCRSF_rx; + + intmoduleFifo.clear(); + intmoduleSerialStart(¶ms); + + // mixer setup mixerSchedulerSetPeriod(INTERNAL_MODULE, CROSSFIRE_PERIOD); - break; + } break; #endif #if defined(INTERNAL_MODULE_PPM) @@ -539,13 +592,20 @@ static void enablePulsesInternalModule(uint8_t protocol) #endif #if defined(AFHDS2) - case PROTOCOL_CHANNELS_AFHDS2A: + case PROTOCOL_CHANNELS_AFHDS2A: { + + // serial port setup + etx_serial_init params; + params.baudrate = INTMODULE_USART_AFHDS2_BAUDRATE; + params.rx_enable = true; + resetPulsesAFHDS2(); - intmoduleSerialStart(INTMODULE_USART_AFHDS2_BAUDRATE, true, - USART_Parity_No, USART_StopBits_1, - USART_WordLength_8b); + intmoduleFifo.clear(); + intmoduleSerialStart(¶ms); + + // mixer setup mixerSchedulerSetPeriod(INTERNAL_MODULE, AFHDS2_PERIOD); - break; + } break; #endif default: @@ -637,6 +697,44 @@ void stopPulsesInternalModule() } } +void intmoduleSendNextFrame() +{ + switch (moduleState[INTERNAL_MODULE].protocol) { +#if defined(PXX2) + case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: + intmoduleSendBuffer(intmodulePulsesData.pxx2.getData(), intmodulePulsesData.pxx2.getSize()); + break; +#endif + +#if defined(PXX1) + case PROTOCOL_CHANNELS_PXX1_SERIAL: + intmoduleSendBuffer(intmodulePulsesData.pxx_uart.getData(), intmodulePulsesData.pxx_uart.getSize()); + break; +#endif + +#if defined(INTERNAL_MODULE_MULTI) + case PROTOCOL_CHANNELS_MULTIMODULE: + intmoduleSendBuffer(intmodulePulsesData.multi.getData(), intmodulePulsesData.multi.getSize()); + break; +#endif + +#if defined(INTERNAL_MODULE_CRSF) + case PROTOCOL_CHANNELS_CROSSFIRE: + intmoduleSendBuffer(intmodulePulsesData.crossfire.pulses, + intmodulePulsesData.crossfire.length); + break; +#endif + +#if defined(AFHDS2) + case PROTOCOL_CHANNELS_AFHDS2A: { + uint8_t* data = (uint8_t*)intmodulePulsesData.flysky.pulses; + uint16_t size = intmodulePulsesData.flysky.ptr - data; + intmoduleSendBuffer(data, size); + } break; +#endif + } +} + bool setupPulsesInternalModule() { uint8_t protocol = getRequiredProtocol(INTERNAL_MODULE); diff --git a/radio/src/pulses/pulses.h b/radio/src/pulses/pulses.h index 50e5b85d2..1b25c353c 100644 --- a/radio/src/pulses/pulses.h +++ b/radio/src/pulses/pulses.h @@ -244,6 +244,7 @@ extern TrainerPulsesData trainerPulsesData; #if defined(HARDWARE_INTERNAL_MODULE) bool setupPulsesInternalModule(); void stopPulsesInternalModule(); +void intmoduleSendNextFrame(); #endif #if defined(HARDWARE_EXTERNAL_MODULE) bool setupPulsesExternalModule(); diff --git a/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp b/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp index 2a30e843d..32d317ab6 100644 --- a/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp +++ b/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp @@ -192,6 +192,8 @@ uint8_t auxSerialTracesEnabled() extern "C" void AUX_SERIAL_USART_IRQHandler(void) { DEBUG_INTERRUPT(INT_SER2); + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + // Send if (USART_GetITStatus(AUX_SERIAL_USART, USART_IT_TXE) != RESET) { uint8_t txchar; @@ -212,11 +214,10 @@ extern "C" void AUX_SERIAL_USART_IRQHandler(void) uint8_t data = AUX_SERIAL_USART->DR; if (!(status & USART_FLAG_ERRORS)) { switch (auxSerialMode) { - case UART_MODE_DEBUG: { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; + case UART_MODE_DEBUG: xStreamBufferSendFromISR(cliRxBuffer, &data, 1, &xHigherPriorityTaskWoken); - } break; + break; } } status = AUX_SERIAL_USART->SR; @@ -237,6 +238,9 @@ extern "C" void AUX_SERIAL_USART_IRQHandler(void) } status = AUX_SERIAL_USART->SR; } + + // might effect a context switch on ISR exit + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } #endif // AUX_SERIAL @@ -385,6 +389,8 @@ uint8_t aux2SerialTracesEnabled() extern "C" void AUX2_SERIAL_USART_IRQHandler(void) { DEBUG_INTERRUPT(INT_SER2); + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + // Send if (USART_GetITStatus(AUX2_SERIAL_USART, USART_IT_TXE) != RESET) { uint8_t txchar; @@ -405,11 +411,10 @@ extern "C" void AUX2_SERIAL_USART_IRQHandler(void) uint8_t data = AUX2_SERIAL_USART->DR; if (!(status & USART_FLAG_ERRORS)) { switch (aux2SerialMode) { - case UART_MODE_DEBUG: { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; + case UART_MODE_DEBUG: xStreamBufferSendFromISR(cliRxBuffer, &data, 1, &xHigherPriorityTaskWoken); - } break; + break; } } status = AUX2_SERIAL_USART->SR; @@ -431,5 +436,8 @@ extern "C" void AUX2_SERIAL_USART_IRQHandler(void) } status = AUX2_SERIAL_USART->SR; } + + // might effect a context switch on ISR exit + taskYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } #endif // AUX2_SERIAL diff --git a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp index bb0290aed..9ffb4c022 100755 --- a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp +++ b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp @@ -20,6 +20,7 @@ */ #include "opentx.h" +#include "intmodule_serial_driver.h" ModuleFifo intmoduleFifo; #if !defined(INTMODULE_DMA_STREAM) @@ -27,6 +28,36 @@ uint8_t * intmoduleTxBufferData; volatile uint8_t intmoduleTxBufferRemaining; #endif +struct etx_serial_driver { + void (*on_receive)(uint8_t data); + void (*on_error)(); +}; + +static etx_serial_driver intmodule_driver = { nullptr, nullptr }; + +// TODO: move this somewhere else +static void intmoduleFifoReceive(uint8_t data) +{ + intmoduleFifo.push(data); +} + +static void intmoduleFifoError() +{ + intmoduleFifo.errors++; +} + +etx_serial_init::etx_serial_init(): + baudrate(0), + parity(USART_Parity_No), + stop_bits(USART_StopBits_1), + word_length(USART_WordLength_8b), + rx_enable(false), + // TODO: this should not be needed + on_receive(intmoduleFifoReceive), + on_error(intmoduleFifoError) +{ +} + void intmoduleStop() { GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN); @@ -46,27 +77,38 @@ void intmoduleStop() USART_DeInit(INTMODULE_USART); GPIO_ResetBits(INTMODULE_GPIO, INTMODULE_TX_GPIO_PIN | INTMODULE_RX_GPIO_PIN); + + // reset callbacks + intmodule_driver.on_receive = nullptr; + intmodule_driver.on_error = nullptr; } void intmodulePxx1SerialStart() { - intmoduleSerialStart(INTMODULE_PXX1_SERIAL_BAUDRATE, false, USART_Parity_No, USART_StopBits_1, USART_WordLength_8b); + etx_serial_init params; + params.baudrate = INTMODULE_PXX1_SERIAL_BAUDRATE; + intmoduleSerialStart(¶ms); } -void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable, uint16_t parity, uint16_t stopBits, uint16_t wordLength) +void intmoduleSerialStart(const etx_serial_init* params) { + if (!params) return; + INTERNAL_MODULE_ON(); + // init callbacks + intmodule_driver.on_receive = params->on_receive; + intmodule_driver.on_error = params->on_error; + +#if !defined(INTMODULE_DMA_STREAM) + // IRQ based TX NVIC_InitTypeDef NVIC_InitStructure; -#if defined(INTMODULE_DMA_STREAM) - NVIC_InitStructure.NVIC_IRQChannel = INTMODULE_DMA_STREAM_IRQ; -#else NVIC_InitStructure.NVIC_IRQChannel = INTMODULE_USART_IRQn; -#endif NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pre-emption priority. */; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); +#endif GPIO_PinAFConfig(INTMODULE_GPIO, INTMODULE_GPIO_PinSource_TX, INTMODULE_GPIO_AF); GPIO_PinAFConfig(INTMODULE_GPIO, INTMODULE_GPIO_PinSource_RX, INTMODULE_GPIO_AF); @@ -81,16 +123,17 @@ void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable, uint16_t parity, USART_DeInit(INTMODULE_USART); USART_InitTypeDef USART_InitStructure; - USART_InitStructure.USART_BaudRate = baudrate; - USART_InitStructure.USART_Parity = parity; - USART_InitStructure.USART_StopBits = stopBits; - USART_InitStructure.USART_WordLength = wordLength; + USART_InitStructure.USART_BaudRate = params->baudrate; + USART_InitStructure.USART_Parity = params->parity; + USART_InitStructure.USART_StopBits = params->stop_bits; + USART_InitStructure.USART_WordLength = params->word_length; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_Init(INTMODULE_USART, &USART_InitStructure); USART_Cmd(INTMODULE_USART, ENABLE); - if (rxEnable) { + if (params->rx_enable) { + // TODO: move into the caller intmoduleFifo.clear(); USART_ITConfig(INTMODULE_USART, USART_IT_RXNE, ENABLE); NVIC_SetPriority(INTMODULE_USART_IRQn, 6); @@ -120,10 +163,12 @@ extern "C" void INTMODULE_USART_IRQHandler(void) while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) { uint8_t data = INTMODULE_USART->DR; if (status & USART_FLAG_ERRORS) { - intmoduleFifo.errors++; + if (intmodule_driver.on_error) + intmodule_driver.on_error(); } else { - intmoduleFifo.push(data); + if (intmodule_driver.on_receive) + intmodule_driver.on_receive(data); } status = INTMODULE_USART->SR; } @@ -168,44 +213,6 @@ void intmoduleSendBuffer(const uint8_t * data, uint8_t size) #endif } -void intmoduleSendNextFrame() -{ - switch (moduleState[INTERNAL_MODULE].protocol) { -#if defined(PXX2) - case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: - intmoduleSendBuffer(intmodulePulsesData.pxx2.getData(), intmodulePulsesData.pxx2.getSize()); - break; -#endif - -#if defined(PXX1) - case PROTOCOL_CHANNELS_PXX1_SERIAL: - intmoduleSendBuffer(intmodulePulsesData.pxx_uart.getData(), intmodulePulsesData.pxx_uart.getSize()); - break; -#endif - -#if defined(INTERNAL_MODULE_MULTI) - case PROTOCOL_CHANNELS_MULTIMODULE: - intmoduleSendBuffer(intmodulePulsesData.multi.getData(), intmodulePulsesData.multi.getSize()); - break; -#endif - -#if defined(INTERNAL_MODULE_CRSF) - case PROTOCOL_CHANNELS_CROSSFIRE: - intmoduleSendBuffer(intmodulePulsesData.crossfire.pulses, - intmodulePulsesData.crossfire.length); - break; -#endif - -#if defined(AFHDS2) - case PROTOCOL_CHANNELS_AFHDS2A: { - uint8_t* data = (uint8_t*)intmodulePulsesData.flysky.pulses; - uint16_t size = intmodulePulsesData.flysky.ptr - data; - intmoduleSendBuffer(data, size); - } break; -#endif - } -} - void intmoduleWaitForTxCompleted() { #if !defined(SIMU) diff --git a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.h b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.h new file mode 100644 index 000000000..a4f09d028 --- /dev/null +++ b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#include + +struct etx_serial_init { + uint32_t baudrate; + uint16_t parity; + uint16_t stop_bits; + uint16_t word_length; + bool rx_enable; + void (*on_receive)(uint8_t data); + void (*on_error)(); + + etx_serial_init(); +}; + +void intmoduleSerialStart(const etx_serial_init* params); +void intmoduleSerialStop(); + +void intmoduleSendByte(uint8_t byte); +void intmoduleSendBuffer(const uint8_t* data, uint8_t size); +void intmoduleWaitForTxCompleted(); diff --git a/radio/src/targets/common/arm/stm32/usbd_cdc.cpp b/radio/src/targets/common/arm/stm32/usbd_cdc.cpp index 609c61100..613f504e6 100644 --- a/radio/src/targets/common/arm/stm32/usbd_cdc.cpp +++ b/radio/src/targets/common/arm/stm32/usbd_cdc.cpp @@ -170,7 +170,9 @@ void usbSerialPutc(uint8_t c) if (txDataLen >= APP_RX_DATA_SIZE) { txDataLen -= APP_RX_DATA_SIZE; } - if (txDataLen > (APP_RX_DATA_SIZE - CDC_DATA_MAX_PACKET_SIZE)) return; // buffer is too full, skip this write + + // buffer is too full, skip this write + if (txDataLen > (APP_RX_DATA_SIZE - CDC_DATA_MAX_PACKET_SIZE)) return; ++charsWritten; @@ -215,13 +217,14 @@ static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len) // if the cliRxFifo does not have enough free space to receive all // available characters, return VCP_FAIL. Maybe that will throttle down // the sender and we will receive the same packet at a later time. + BaseType_t xHigherPriorityTaskWoken = pdFALSE; #if defined(CLI) //copy data to the application FIFO - BaseType_t xHigherPriorityTaskWoken = pdFALSE; xStreamBufferSendFromISR(cliRxBuffer, Buf, Len, &xHigherPriorityTaskWoken); - + xTaskNotifyFromISR(cliTaskId.rtos_handle, 0, eNoAction, + &xHigherPriorityTaskWoken); // Please note that we don't try to yield to the task that has // potentially been woken up, as this might effect a context switch // in place, whereby the ISR is not done yet handling the USB request @@ -240,6 +243,8 @@ static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len) #endif + // might effect a context switch on ISR exit + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); return USBD_OK; } diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index 4e8a1fb6e..f9e1873f3 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -198,12 +198,6 @@ void SDRAM_Init(); void init_intmodule_heartbeat(); void check_intmodule_heartbeat(); -void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable, uint16_t parity, uint16_t stopBits, uint16_t wordLength); -void intmoduleSendByte(uint8_t byte); -void intmoduleSendBuffer(const uint8_t * data, uint8_t size); -void intmoduleSendNextFrame(); -void intmoduleWaitForTxCompleted(); - void extmoduleSerialStart(); void extmoduleInvertedSerialStart(uint32_t baudrate); void extmoduleSendBuffer(const uint8_t * data, uint8_t size); diff --git a/radio/src/targets/nv14/board.h b/radio/src/targets/nv14/board.h index 02d97da72..c70100315 100644 --- a/radio/src/targets/nv14/board.h +++ b/radio/src/targets/nv14/board.h @@ -126,10 +126,6 @@ void EXTERNAL_MODULE_OFF(); void init_intmodule_heartbeat(); void check_intmodule_heartbeat(); -void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable, uint16_t parity, uint16_t stopBits, uint16_t wordLength); -void intmoduleSendBuffer(const uint8_t * data, uint8_t size); -void intmoduleSendNextFrame(); - //void extmoduleSerialStart(uint32_t baudrate, uint32_t period_half_us, bool inverted); void extmoduleSerialStart(); void extmoduleSendNextFrame(); diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 9aaec3e69..f9422faa6 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -136,14 +136,6 @@ uint32_t isBootloaderStart(const uint8_t * buffer); #define IS_INTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) == Bit_SET) #endif -void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable, uint16_t parity, uint16_t stopBits, uint16_t wordLength); -#if defined(INTERNAL_MODULE_MULTI) -void intmoduleTimerStart(uint32_t periodMs); -#endif -void intmoduleSendByte(uint8_t byte); -void intmoduleSendBuffer(const uint8_t * data, uint8_t size); -void intmoduleSendNextFrame(); - void extmoduleSerialStart(); void extmoduleInvertedSerialStart(uint32_t baudrate); void extmoduleSendBuffer(const uint8_t * data, uint8_t size);