Add async UART logger (running on DMA).
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
b7789064fa
commit
faa1685e18
49
Utility/Inc/utility_asyncaurtlogger.hpp
Normal file
49
Utility/Inc/utility_asyncaurtlogger.hpp
Normal file
@ -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<char, 255> 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_ */
|
||||
31
Utility/Inc/utility_atomicscopeguard.hpp
Normal file
31
Utility/Inc/utility_atomicscopeguard.hpp
Normal file
@ -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 <cstdint>
|
||||
|
||||
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_ */
|
||||
73
Utility/Src/utility_asynchuartlogger.cpp
Normal file
73
Utility/Src/utility_asynchuartlogger.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* utility_asynchuartlogger.cpp
|
||||
*
|
||||
* Created on: Mar 20, 2021
|
||||
* Author: erki
|
||||
*/
|
||||
|
||||
#include "utility_asyncaurtlogger.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
#include <cassert>
|
||||
|
||||
#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<char, 255>& 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<uint8_t*>(head.buffer.data()), head.length);
|
||||
_buffer_queue.pop_front();
|
||||
}
|
||||
|
||||
}
|
||||
32
Utility/Src/utility_atomicscopeguard.cpp
Normal file
32
Utility/Src/utility_atomicscopeguard.cpp
Normal file
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user