PoC: connect USB/serial ISR directly to the respective serial send

This assumes that USB IRQ has a lower logical prio as the UART IRQ so that it can be pre-empted by the USART ISR.
This commit is contained in:
Raphael Coeffic
2021-11-21 11:18:35 +01:00
committed by Raphael Coeffic
parent 3e390bd582
commit 96743a9fc4
4 changed files with 64 additions and 91 deletions
+51 -56
View File
@@ -25,7 +25,7 @@
#include <malloc.h>
#include <new>
#include "cli_traces.h"
#include "cli.h"
#if defined(INTMODULE_USART)
#include "intmodule_serial_driver.h"
@@ -34,13 +34,30 @@
#define CLI_COMMAND_MAX_ARGS 8
#define CLI_COMMAND_MAX_LEN 256
// CLI receive buffer size
#define CLI_RX_BUFFER_SIZE 256
RTOS_TASK_HANDLE cliTaskId;
RTOS_DEFINE_STACK(cliStack, CLI_STACK_SIZE);
static uint8_t cliRxBufferStorage[CLI_RX_BUFFER_SIZE];
static StaticStreamBuffer_t cliRxBufferStatic;
StreamBufferHandle_t cliRxBuffer;
// CLI receive stream buffer
static StreamBufferHandle_t cliRxBuffer;
static void cliDefaultRx(uint8_t* buf, uint32_t len)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xStreamBufferSendFromISR(cliRxBuffer, buf, len, &xHigherPriorityTaskWoken);
xTaskNotifyFromISR(cliTaskId.rtos_handle, 0, eNoAction,
&xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
void (*cliReceiveCallBack)(uint8_t* buf, uint32_t len) = cliDefaultRx;
uint8_t cliTracesEnabled = true;
char cliLastLine[CLI_COMMAND_MAX_LEN+1];
@@ -857,18 +874,29 @@ int cliSet(const char **argv)
}
#if defined(ENABLE_SERIAL_PASSTHROUGH)
static StreamBufferHandle_t spIntRxBuffer;
// static StreamBufferHandle_t spIntRxBuffer;
static void spRx(uint8_t data)
// 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)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xStreamBufferSendFromISR(spIntRxBuffer, &data, 1,
&xHigherPriorityTaskWoken);
xTaskNotifyFromISR(cliTaskId.rtos_handle, 0, eNoAction,
&xHigherPriorityTaskWoken);
intmoduleSendBuffer(buf, len);
intmoduleWaitForTxCompleted();
}
// might effect a context switch on ISR exit
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
static void spSerialTx(uint8_t data)
{
serialPutc(data);
}
int cliSerialPassthrough(const char **argv)
@@ -920,67 +948,27 @@ int cliSerialPassthrough(const char **argv)
#if defined(HARDWARE_INTERNAL_MODULE)
if (port_n == INTERNAL_MODULE) {
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
etx_serial_init params;
params.baudrate = baudrate;
params.rx_enable = true;
params.on_receive = spRx;
params.on_receive = spSerialTx;
intmoduleSerialStart(&params);
cliReceiveCallBack = spInternalModuleTx;
// 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();
// Timeout ?
if (notified == pdFALSE)
continue;
// use 2nd half of 'tmpBuf'
rx_bytes = xStreamBufferBytesAvailable(cliRxBuffer);
if (rx_bytes) {
// wait for end of last transmission
intmoduleWaitForTxCompleted();
rx_bytes = xStreamBufferReceive(cliRxBuffer, tmpBuf2, tmpBufSize, 0);
intmoduleSendBuffer(tmpBuf2, rx_bytes); // sends asynchronously
}
// Let's hope this does not starve the other side
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
}
}
RTOS_WAIT_MS(200);
}
intmoduleSerialStop();
vStreamBufferDelete(spIntRxBuffer);
free(tmpBuf);
tmpBuf = nullptr;
// TODO: reset cli rx callback
}
#endif
@@ -1585,6 +1573,13 @@ void cliTask(void * pdata)
}
}
// Called from receive ISR (either USB or UART)
void cliReceiveData(uint8_t* buf, uint32_t len)
{
if (cliReceiveCallBack)
cliReceiveCallBack(buf, len);
}
void cliStart()
{
// Init stream buffer
+4 -8
View File
@@ -27,16 +27,12 @@
#include <FreeRTOS.h>
#include <stream_buffer.h>
// CLI receive buffer size
#define CLI_RX_BUFFER_SIZE 256
// CLI receive stream buffer
extern StreamBufferHandle_t cliRxBuffer;
// Allows for switchable debug prints via CLI
extern uint8_t cliTracesEnabled;
#include "cli_traces.h"
// CLI task function
void cliStart();
// Called from receive ISR (either USB or UART)
void cliReceiveData(uint8_t* buf, uint32_t len);
#endif // _CLI_H_
@@ -22,10 +22,6 @@
#include "opentx.h"
#include "targets/horus/board.h"
#if defined(AUX_SERIAL) || defined(AUX2_SERIAL)
#include <FreeRTOS.h>
#endif
#if defined(AUX_SERIAL)
uint8_t auxSerialMode = UART_MODE_COUNT; // Prevent debug output before port is setup
Fifo<uint8_t, 512> auxSerialTxFifo;
@@ -196,7 +192,6 @@ 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) {
@@ -219,8 +214,7 @@ extern "C" void AUX_SERIAL_USART_IRQHandler(void)
if (!(status & USART_FLAG_ERRORS)) {
switch (auxSerialMode) {
case UART_MODE_DEBUG:
xStreamBufferSendFromISR(cliRxBuffer, &data, 1,
&xHigherPriorityTaskWoken);
cliReceiveData(&data, 1);
break;
}
}
@@ -242,9 +236,6 @@ 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
@@ -393,7 +384,6 @@ 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) {
@@ -416,8 +406,7 @@ extern "C" void AUX2_SERIAL_USART_IRQHandler(void)
if (!(status & USART_FLAG_ERRORS)) {
switch (aux2SerialMode) {
case UART_MODE_DEBUG:
xStreamBufferSendFromISR(cliRxBuffer, &data, 1,
&xHigherPriorityTaskWoken);
cliReceiveData(&data, 1);
break;
}
}
@@ -440,8 +429,5 @@ extern "C" void AUX2_SERIAL_USART_IRQHandler(void)
}
status = AUX2_SERIAL_USART->SR;
}
// might effect a context switch on ISR exit
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
#endif // AUX2_SERIAL
@@ -149,6 +149,7 @@ static uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len)
// some debug vars
uint16_t usbWraps = 0;
uint16_t charsWritten = 0;
uint16_t usbTxErrors = 0;
void usbSerialPutc(uint8_t c)
{
@@ -172,7 +173,10 @@ void usbSerialPutc(uint8_t c)
}
// buffer is too full, skip this write
if (txDataLen > (APP_RX_DATA_SIZE - CDC_DATA_MAX_PACKET_SIZE)) return;
if (txDataLen > (APP_RX_DATA_SIZE - CDC_DATA_MAX_PACKET_SIZE)) {
usbTxErrors++;
return;
}
++charsWritten;
@@ -217,17 +221,11 @@ 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
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
// pass data to CLI
cliReceiveData(Buf, Len);
#elif defined(LUA)
// TODO: find a better implementation to allow
@@ -243,8 +241,6 @@ 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;
}