From faa1685e183476a1db1f2e21e70319ee20115101 Mon Sep 17 00:00:00 2001 From: Erki Date: Sun, 21 Mar 2021 17:03:06 +0200 Subject: [PATCH] Add async UART logger (running on DMA). --- Utility/Inc/utility_asyncaurtlogger.hpp | 49 ++++++++++++++++ Utility/Inc/utility_atomicscopeguard.hpp | 31 ++++++++++ Utility/Src/utility_asynchuartlogger.cpp | 73 ++++++++++++++++++++++++ Utility/Src/utility_atomicscopeguard.cpp | 32 +++++++++++ 4 files changed, 185 insertions(+) create mode 100644 Utility/Inc/utility_asyncaurtlogger.hpp create mode 100644 Utility/Inc/utility_atomicscopeguard.hpp create mode 100644 Utility/Src/utility_asynchuartlogger.cpp create mode 100644 Utility/Src/utility_atomicscopeguard.cpp diff --git a/Utility/Inc/utility_asyncaurtlogger.hpp b/Utility/Inc/utility_asyncaurtlogger.hpp new file mode 100644 index 0000000..58d2353 --- /dev/null +++ b/Utility/Inc/utility_asyncaurtlogger.hpp @@ -0,0 +1,49 @@ +/* + * utility_asyncaurtlogger.hpp + * + * Created on: Mar 20, 2021 + * Author: erki + */ + +#ifndef SKULLC_UTILITY_ASYNCAURTLOGGER_HPP_ +#define SKULLC_UTILITY_ASYNCAURTLOGGER_HPP_ + +#include "utility_ilogger.hpp" +#include "utility_ringbuffer.hpp" + +#include "usart.h" + +namespace Utility +{ + +class AsyncUARTLogger : public ILogger +{ +public: + explicit AsyncUARTLogger(UART_HandleTypeDef* huart); + AsyncUARTLogger() = delete; + AsyncUARTLogger(const AsyncUARTLogger&) = delete; + AsyncUARTLogger(AsyncUARTLogger&&) = delete; + + void log(const char* format, ...); + +private: + struct _Data + { + std::array buffer; + std::int32_t length; + }; + + Ringbuffer<_Data, 10> _buffer_queue; + UART_HandleTypeDef* _huart; + bool _in_flight = false; + + static AsyncUARTLogger* _this; + static void _txCompleteCallback(UART_HandleTypeDef* huart); + + void _sendNextLog(); +}; + +} + + +#endif /* SKULLC_UTILITY_ASYNCAURTLOGGER_HPP_ */ diff --git a/Utility/Inc/utility_atomicscopeguard.hpp b/Utility/Inc/utility_atomicscopeguard.hpp new file mode 100644 index 0000000..beef132 --- /dev/null +++ b/Utility/Inc/utility_atomicscopeguard.hpp @@ -0,0 +1,31 @@ +/* + * utility_atomicscopeguard.hpp + * + * Created on: Mar 21, 2021 + * Author: erki + */ + +#ifndef UTILITY_INC_UTILITY_ATOMICSCOPEGUARD_HPP_ +#define UTILITY_INC_UTILITY_ATOMICSCOPEGUARD_HPP_ + +#include + +namespace Utility +{ + +class AtomicScopeGuard +{ +public: + AtomicScopeGuard(); + AtomicScopeGuard(const AtomicScopeGuard&) = delete; + AtomicScopeGuard(AtomicScopeGuard&&) = delete; + + ~AtomicScopeGuard(); + +private: + static std::int32_t _reentrancy_counter; +}; + +} + +#endif /* UTILITY_INC_UTILITY_ATOMICSCOPEGUARD_HPP_ */ diff --git a/Utility/Src/utility_asynchuartlogger.cpp b/Utility/Src/utility_asynchuartlogger.cpp new file mode 100644 index 0000000..a529789 --- /dev/null +++ b/Utility/Src/utility_asynchuartlogger.cpp @@ -0,0 +1,73 @@ +/* + * utility_asynchuartlogger.cpp + * + * Created on: Mar 20, 2021 + * Author: erki + */ + +#include "utility_asyncaurtlogger.hpp" + +#include +#include +#include + +#include "utility_atomicscopeguard.hpp" + +namespace Utility +{ + +AsyncUARTLogger* AsyncUARTLogger::_this = nullptr; + +AsyncUARTLogger::AsyncUARTLogger(UART_HandleTypeDef* huart) + : _huart(huart) +{ + assert(!_this); + + _this = this; + _huart->TxCpltCallback = &AsyncUARTLogger::_txCompleteCallback; +} + +void AsyncUARTLogger::log(const char* format, ...) +{ + { + AtomicScopeGuard s; + + if (_buffer_queue.size() == _buffer_queue.max_size()) + return; + } + + std::va_list args; + va_start(args, format); + + auto tail = _buffer_queue.end(); + std::array& buffer = tail->buffer; + + tail->length = vsnprintf(buffer.data(), buffer.size(), format, args); + + { + AtomicScopeGuard s; + _buffer_queue.increment_tail(); + + if (!_in_flight) + _sendNextLog(); + } +} + +void AsyncUARTLogger::_txCompleteCallback(UART_HandleTypeDef*) +{ + if (!AsyncUARTLogger::_this->_buffer_queue.empty()) + AsyncUARTLogger::_this->_sendNextLog(); + else + AsyncUARTLogger::_this->_in_flight = false; +} + +void AsyncUARTLogger::_sendNextLog() +{ + _in_flight = true; + + _Data& head = _buffer_queue.front(); + HAL_UART_Transmit_DMA(_huart, reinterpret_cast(head.buffer.data()), head.length); + _buffer_queue.pop_front(); +} + +} diff --git a/Utility/Src/utility_atomicscopeguard.cpp b/Utility/Src/utility_atomicscopeguard.cpp new file mode 100644 index 0000000..17ca0b6 --- /dev/null +++ b/Utility/Src/utility_atomicscopeguard.cpp @@ -0,0 +1,32 @@ +/* + * utility_atomicscopeguard.cpp + * + * Created on: Mar 21, 2021 + * Author: erki + */ + +#include "utility_atomicscopeguard.hpp" + +#include "cmsis_gcc.h" + +namespace Utility +{ + +std::int32_t AtomicScopeGuard::_reentrancy_counter; + +AtomicScopeGuard::AtomicScopeGuard() +{ + __disable_irq(); + _reentrancy_counter++; +} + +AtomicScopeGuard::~AtomicScopeGuard() +{ + _reentrancy_counter--; + + if (!_reentrancy_counter) + __enable_irq(); +} + +} +