Use FreeRTOS stream buffers and task notifications

This commit is contained in:
Raphael Coeffic
2021-11-21 11:18:35 +01:00
committed by Raphael Coeffic
parent 59f2b5e8b0
commit 73790c1654
12 changed files with 329 additions and 114 deletions
+66 -15
View File
@@ -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(&params);
// 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;
}