Add thread-safe (-ish) console output
This commit is contained in:
parent
7f5ef3de8a
commit
01807f47ab
6 changed files with 129 additions and 11 deletions
|
@ -94,7 +94,7 @@ int main(void)
|
||||||
MX_DMA_Init();
|
MX_DMA_Init();
|
||||||
MX_USART2_UART_Init();
|
MX_USART2_UART_Init();
|
||||||
/* USER CODE BEGIN 2 */
|
/* USER CODE BEGIN 2 */
|
||||||
// app_main();
|
|
||||||
/* USER CODE END 2 */
|
/* USER CODE END 2 */
|
||||||
|
|
||||||
/* Call init function for freertos objects (in cmsis_os2.c) */
|
/* Call init function for freertos objects (in cmsis_os2.c) */
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
add_library(app STATIC
|
add_library(app STATIC
|
||||||
src/app.cpp
|
src/app.cpp
|
||||||
src/irq_bridge.cpp
|
src/irq_bridge.cpp
|
||||||
|
src/thread_safe_console_output.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(app PUBLIC
|
target_include_directories(app PUBLIC
|
||||||
|
|
|
@ -7,34 +7,50 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <FreeRTOS.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <portmacro.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#include <f4ll/console_handler.h>
|
#include <f4ll/console_handler.h>
|
||||||
|
#include <task.h>
|
||||||
|
#include <thread_safe_console_output.h>
|
||||||
|
|
||||||
class app : public f4ll::initialized_singleton<app>
|
class app : public f4ll::initialized_singleton<app>, f4ll::console_handler::iconsole_input
|
||||||
{
|
{
|
||||||
friend class f4ll::initialized_singleton<app>;
|
friend class f4ll::initialized_singleton<app>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
app();
|
app(void const *param);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
__attribute__((noreturn)) void main();
|
__attribute__((noreturn)) void main();
|
||||||
|
void input_available(f4ll::console_handler::size_type len) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void cli_task_dispatch(void *param) { static_cast<app *>(param)->cli_task(); }
|
||||||
|
__attribute__((noreturn)) void cli_task();
|
||||||
|
static constexpr size_t const CLI_TASK_STACK_LEN = 128;
|
||||||
|
StackType_t m_cli_task_stack[CLI_TASK_STACK_LEN];
|
||||||
|
StaticTask_t m_cli_task_buffer;
|
||||||
|
TaskHandle_t m_cli_task_handle;
|
||||||
|
|
||||||
f4ll::console_handler &m_con;
|
f4ll::console_handler &m_con;
|
||||||
static constexpr size_t const TXBUF_LEN = 128;
|
static constexpr size_t const TXBUF_LEN = 128;
|
||||||
static constexpr size_t const RXBUF_LEN = 32;
|
static constexpr size_t const RXBUF_LEN = 32;
|
||||||
uint8_t m_tx_buf_mem[TXBUF_LEN];
|
uint8_t m_tx_buf_mem[TXBUF_LEN];
|
||||||
uint8_t m_rx_buf_mem[RXBUF_LEN];
|
uint8_t m_rx_buf_mem[RXBUF_LEN];
|
||||||
|
|
||||||
|
thread_safe_console_output m_safe_conout;
|
||||||
|
|
||||||
|
void queue_ts();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif // __cplusplus
|
||||||
|
|
||||||
void app_main(void const *param) __attribute__((noreturn));
|
void app_main(void const *param) __attribute__((noreturn));
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C" {
|
} // extern "C" {
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
23
components/app/inc/thread_safe_console_output.h
Normal file
23
components/app/inc/thread_safe_console_output.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <f4ll/console_handler.h>
|
||||||
|
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <semphr.h>
|
||||||
|
|
||||||
|
class thread_safe_console_output
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using size_type = f4ll::console_handler::size_type;
|
||||||
|
thread_safe_console_output(f4ll::console_handler &console);
|
||||||
|
|
||||||
|
void print(char const *s);
|
||||||
|
void flush();
|
||||||
|
size_type append(char const *s);
|
||||||
|
|
||||||
|
private:
|
||||||
|
f4ll::console_handler &m_con;
|
||||||
|
|
||||||
|
SemaphoreHandle_t m_sem;
|
||||||
|
StaticSemaphore_t m_sem_buf;
|
||||||
|
};
|
|
@ -5,11 +5,15 @@
|
||||||
* Author: abody
|
* Author: abody
|
||||||
*/
|
*/
|
||||||
#include <main.h>
|
#include <main.h>
|
||||||
|
#include <projdefs.h>
|
||||||
|
|
||||||
|
#include <cmsis_os.h>
|
||||||
|
|
||||||
#include <FreeRTOS.h>
|
#include <FreeRTOS.h>
|
||||||
#include <task.h>
|
#include <task.h>
|
||||||
|
|
||||||
#include <f4ll/console_handler.h>
|
#include <f4ll/console_handler.h>
|
||||||
|
#include <f4ll/str_util.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -18,24 +22,64 @@
|
||||||
|
|
||||||
void app_main(void const *param)
|
void app_main(void const *param)
|
||||||
{
|
{
|
||||||
(void)param;
|
|
||||||
app::init().main();
|
app::init(param).main();
|
||||||
}
|
}
|
||||||
|
|
||||||
app::app()
|
app::app(void const *param)
|
||||||
: m_con(
|
: m_con(
|
||||||
f4ll::console_handler::init(
|
f4ll::console_handler::init(
|
||||||
USART2, DMA1, LL_DMA_STREAM_5, LL_DMA_STREAM_6, m_rx_buf_mem, sizeof(m_rx_buf_mem), m_tx_buf_mem, sizeof(m_tx_buf_mem),
|
USART2, DMA1, LL_DMA_STREAM_5, LL_DMA_STREAM_6, m_rx_buf_mem, sizeof(m_rx_buf_mem), m_tx_buf_mem, sizeof(m_tx_buf_mem),
|
||||||
nullptr))
|
nullptr)),
|
||||||
|
m_safe_conout(m_con)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
(void)param;
|
||||||
}
|
}
|
||||||
|
|
||||||
void app::main()
|
void app::main()
|
||||||
{
|
{
|
||||||
m_con.print("-------------------------------------------\n");
|
m_cli_task_handle = xTaskCreateStatic(
|
||||||
|
cli_task_dispatch, "CLI_task", CLI_TASK_STACK_LEN, this, osPriorityAboveNormal, m_cli_task_stack, &m_cli_task_buffer);
|
||||||
|
|
||||||
|
queue_ts();
|
||||||
|
m_safe_conout.print("-------------------------------------------\n");
|
||||||
while (true) {
|
while (true) {
|
||||||
m_con.print("Hello woooooooooooooooooooooooooooooooorld!\n");
|
queue_ts();
|
||||||
|
m_safe_conout.print("Hello woooooooooooooooooooooooooooooooorld!\n");
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
vTaskDelay(pdMS_TO_TICKS(500));
|
||||||
LL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
|
LL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void app::input_available(f4ll::console_handler::size_type len)
|
||||||
|
{
|
||||||
|
// TODO: trigger a semaphore here and do the processing from a task. This is running in interrupt context
|
||||||
|
f4ll::iringbuffer &rb = f4ll::console_handler::instance().get_rx_buffer();
|
||||||
|
f4ll::console_handler::size_type chunk_len = 0;
|
||||||
|
uint8_t const *chunk = nullptr;
|
||||||
|
bool more = false;
|
||||||
|
do {
|
||||||
|
more = rb.get_chunk(chunk, chunk_len);
|
||||||
|
if (chunk_len) {
|
||||||
|
rb.consumed(chunk_len);
|
||||||
|
}
|
||||||
|
} while (more);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::cli_task()
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||||
|
queue_ts();
|
||||||
|
m_safe_conout.print(">>> TICK <<<\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::queue_ts()
|
||||||
|
{
|
||||||
|
char ts_buf[12];
|
||||||
|
uitodec(ts_buf, xTaskGetTickCount());
|
||||||
|
m_safe_conout.append(ts_buf);
|
||||||
|
m_safe_conout.append(" ");
|
||||||
|
}
|
34
components/app/src/thread_safe_console_output.cpp
Normal file
34
components/app/src/thread_safe_console_output.cpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#include <f4ll/console_handler.h>
|
||||||
|
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <portmacro.h>
|
||||||
|
|
||||||
|
#include <thread_safe_console_output.h>
|
||||||
|
|
||||||
|
thread_safe_console_output::thread_safe_console_output(f4ll::console_handler &con)
|
||||||
|
: m_con(con),
|
||||||
|
m_sem(xSemaphoreCreateMutexStatic(&m_sem_buf))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_safe_console_output::size_type thread_safe_console_output::append(char const *s)
|
||||||
|
{
|
||||||
|
xSemaphoreTake(m_sem, portMAX_DELAY);
|
||||||
|
auto ret = m_con.append(s);
|
||||||
|
xSemaphoreGive(m_sem);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_safe_console_output::flush()
|
||||||
|
{
|
||||||
|
xSemaphoreTake(m_sem, portMAX_DELAY);
|
||||||
|
m_con.flush();
|
||||||
|
xSemaphoreGive(m_sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_safe_console_output::print(const char *s)
|
||||||
|
{
|
||||||
|
xSemaphoreTake(m_sem, portMAX_DELAY);
|
||||||
|
m_con.print(s);
|
||||||
|
xSemaphoreGive(m_sem);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue