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:
committed by
Raphael Coeffic
parent
3e390bd582
commit
96743a9fc4
+51
-56
@@ -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(¶ms);
|
||||
|
||||
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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user