From b1b34238442da7c45f43add0053e864112908669 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 14 Nov 2021 10:21:06 +0100 Subject: [PATCH] Use stream buffer for CLI --- radio/src/FreeRTOSConfig.h | 5 ++ radio/src/cli.cpp | 61 ++++++++++++++----- radio/src/cli.h | 21 ++++--- radio/src/main.cpp | 2 +- radio/src/targets/common/arm/CMakeLists.txt | 7 +++ radio/src/targets/common/arm/stm32/usb_bsp.c | 1 + .../src/targets/common/arm/stm32/usbd_cdc.cpp | 22 ++++--- radio/src/tasks.h | 10 ++- 8 files changed, 92 insertions(+), 37 deletions(-) diff --git a/radio/src/FreeRTOSConfig.h b/radio/src/FreeRTOSConfig.h index ef598e888..e63e03594 100644 --- a/radio/src/FreeRTOSConfig.h +++ b/radio/src/FreeRTOSConfig.h @@ -78,6 +78,11 @@ to exclude the API function. */ #define INCLUDE_xTaskGetSchedulerState 1 #endif +#if defined(CLI) +// required for stream buffers +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#endif + /* Cortex-M specific definitions. */ #ifdef __NVIC_PRIO_BITS /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ diff --git a/radio/src/cli.cpp b/radio/src/cli.cpp index b5db5a787..f23c1abb3 100644 --- a/radio/src/cli.cpp +++ b/radio/src/cli.cpp @@ -31,7 +31,11 @@ RTOS_TASK_HANDLE cliTaskId; RTOS_DEFINE_STACK(cliStack, CLI_STACK_SIZE); -Fifo cliRxFifo; +static uint8_t cliRxBufferStorage[CLI_RX_BUFFER_SIZE]; +static StaticStreamBuffer_t cliRxBufferStatic; + +StreamBufferHandle_t cliRxBuffer; + uint8_t cliTracesEnabled = true; char cliLastLine[CLI_COMMAND_MAX_LEN+1]; @@ -1337,6 +1341,11 @@ int cliExecLine(char * line) return cliExecCommand(argv); } +#define CHAR_LF 0x0A +#define CHAR_NEWPAGE 0x0C +#define CHAR_CR 0x0D +#define CHAR_BACKSPACE 0xFF + void cliTask(void * pdata) { char line[CLI_COMMAND_MAX_LEN+1]; @@ -1347,23 +1356,33 @@ void cliTask(void * pdata) for (;;) { uint8_t c; - while (!cliRxFifo.pop(c)) { - RTOS_WAIT_MS(20); // 20ms - } + // TODO: implement block read instead + // of going byte-by-byte. + + /* Block for max 100ms. */ + const TickType_t xTimeout = 100 / RTOS_MS_PER_TICK; + size_t xReceivedBytes = xStreamBufferReceive(cliRxBuffer, &c, 1, xTimeout); + if (!xReceivedBytes) continue; - if (c == 12) { + switch(c) { + case CHAR_NEWPAGE: // clear screen serialPrint("\033[2J\033[1;1H"); cliPrompt(); - } - else if (c == 127) { - // backspace + break; + + case CHAR_BACKSPACE: if (pos) { line[--pos] = '\0'; serialPutc(c); } - } - else if (c == '\r' || c == '\n') { + break; + + case CHAR_CR: + // ignore + break; + + case CHAR_LF: // enter serialCrlf(); line[pos] = '\0'; @@ -1378,16 +1397,26 @@ void cliTask(void * pdata) cliExecLine(line); pos = 0; cliPrompt(); - } - else if (isascii(c) && pos < CLI_COMMAND_MAX_LEN) { - line[pos++] = c; - serialPutc(c); + break; + + default: + if (isascii(c) && pos < CLI_COMMAND_MAX_LEN) { + line[pos++] = c; + serialPutc(c); + } + break; } } } void cliStart() { - RTOS_CREATE_TASK(cliTaskId, cliTask, "CLI", cliStack, - CLI_STACK_SIZE, CLI_TASK_PRIO); + // Init stream buffer + const size_t xTriggerLevel = 1; + cliRxBuffer = + xStreamBufferCreateStatic(sizeof(cliRxBufferStorage), xTriggerLevel, + cliRxBufferStorage, &cliRxBufferStatic); + + RTOS_CREATE_TASK(cliTaskId, cliTask, "CLI", cliStack, CLI_STACK_SIZE, + CLI_TASK_PRIO); } diff --git a/radio/src/cli.h b/radio/src/cli.h index 9a1b28c80..337be3f2b 100644 --- a/radio/src/cli.h +++ b/radio/src/cli.h @@ -22,18 +22,21 @@ #ifndef _CLI_H_ #define _CLI_H_ -#include "serial.h" +#include +#include +#include + +// 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; -#ifdef __cplusplus -#include "fifo.h" -extern Fifo cliRxFifo; -#include "tasks.h" -extern RTOS_TASK_HANDLE cliTaskId; -extern RTOS_DEFINE_STACK(cliStack, CLI_STACK_SIZE); -#endif - +// CLI task function void cliStart(); #endif // _CLI_H_ diff --git a/radio/src/main.cpp b/radio/src/main.cpp index e184cde8a..3f5c303c1 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -72,7 +72,7 @@ void openUsbMenu() TRACE("USB mass storage"); setSelectedUsbMode(USB_MASS_STORAGE_MODE); }); -#if defined(DEBUG) +#if defined(DEBUG) || defined(CLI) _usbMenu->addLine(STR_USB_SERIAL, [] { TRACE("USB serial"); setSelectedUsbMode(USB_SERIAL_MODE); diff --git a/radio/src/targets/common/arm/CMakeLists.txt b/radio/src/targets/common/arm/CMakeLists.txt index 1dcf23e91..929c56b36 100644 --- a/radio/src/targets/common/arm/CMakeLists.txt +++ b/radio/src/targets/common/arm/CMakeLists.txt @@ -252,6 +252,13 @@ set(FIRMWARE_SRC ${RTOS_DIR}/timers.c rtos.c) +if(CLI) + set(FIRMWARE_SRC + ${FIRMWARE_SRC} + ${RTOS_DIR}/stream_buffer.c) +endif() + + set(PULSES_SRC ${PULSES_SRC} pulses.cpp diff --git a/radio/src/targets/common/arm/stm32/usb_bsp.c b/radio/src/targets/common/arm/stm32/usb_bsp.c index 81b3277d6..1317a11a8 100644 --- a/radio/src/targets/common/arm/stm32/usb_bsp.c +++ b/radio/src/targets/common/arm/stm32/usb_bsp.c @@ -75,6 +75,7 @@ void USB_OTG_BSP_Deinit(USB_OTG_CORE_HANDLE *pdev) */ void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev) { + // FreeRTOS syscall prio is 5 NVIC_SetPriority(OTG_FS_IRQn, 11); // Lower priority interrupt NVIC_EnableIRQ(OTG_FS_IRQn); } diff --git a/radio/src/targets/common/arm/stm32/usbd_cdc.cpp b/radio/src/targets/common/arm/stm32/usbd_cdc.cpp index 272777de8..609c61100 100644 --- a/radio/src/targets/common/arm/stm32/usbd_cdc.cpp +++ b/radio/src/targets/common/arm/stm32/usbd_cdc.cpp @@ -152,7 +152,6 @@ uint16_t charsWritten = 0; void usbSerialPutc(uint8_t c) { - /* Apparently there is no reliable way to tell if the virtual serial port is opened or not. @@ -218,23 +217,30 @@ static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len) // the sender and we will receive the same packet at a later time. #if defined(CLI) + //copy data to the application FIFO - for (uint32_t i = 0; i < Len; i++) { - cliRxFifo.push(Buf[i]); - } -#endif -#if defined(LUA) && !defined(CLI) + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xStreamBufferSendFromISR(cliRxBuffer, Buf, Len, &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 + +#elif defined(LUA) + // TODO: find a better implementation to allow + // run-time selection of the USB CDC receiver + // (here either CLI or LUA) + // copy data to the LUA FIFO if (luaRxFifo) { for (uint32_t i = 0; i < Len; i++) { luaRxFifo->push(Buf[i]); } } + #endif return USBD_OK; } - - // /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/radio/src/tasks.h b/radio/src/tasks.h index bbdd60b2a..b1219b7dc 100644 --- a/radio/src/tasks.h +++ b/radio/src/tasks.h @@ -26,13 +26,13 @@ // stack sizes should be in multiples of 8 for better alignment #if defined (COLORLCD) - #define MENUS_STACK_SIZE 4000 + #define MENUS_STACK_SIZE (8 * 1024) #else #define MENUS_STACK_SIZE 2000 #endif #define MIXER_STACK_SIZE 400 #define AUDIO_STACK_SIZE 400 -#define CLI_STACK_SIZE 1000 // only consumed with CLI build option +#define CLI_STACK_SIZE 1024 // only consumed with CLI build option #if defined(FREE_RTOS) #define MIXER_TASK_PRIO (tskIDLE_PRIORITY + 4) @@ -49,13 +49,17 @@ extern RTOS_TASK_HANDLE menusTaskId; extern RTOS_DEFINE_STACK(menusStack, MENUS_STACK_SIZE); +extern RTOS_MUTEX_HANDLE mixerMutex; extern RTOS_TASK_HANDLE mixerTaskId; extern RTOS_DEFINE_STACK(mixerStack, MIXER_STACK_SIZE); extern RTOS_TASK_HANDLE audioTaskId; extern RTOS_DEFINE_STACK(audioStack, AUDIO_STACK_SIZE); -extern RTOS_MUTEX_HANDLE mixerMutex; +#if defined(CLI) +extern RTOS_TASK_HANDLE cliTaskId; +extern RTOS_DEFINE_STACK(cliStack, CLI_STACK_SIZE); +#endif void stackPaint(); void tasksStart();