New logging interfaces
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Erki 2021-04-02 00:50:59 +03:00
parent 77178a21c9
commit ce4f8eb8f5
14 changed files with 243 additions and 302 deletions

View File

@ -21,6 +21,22 @@ namespace Hal
namespace St
{
template<typename Origin>
using IsrCallbackFn = void(*)(Origin*);
template<typename Origin, typename Handler, void (Handler::*func)(), typename Tag>
IsrCallbackFn<Origin> createCallback(Handler& h_in)
{
static Handler* h = &h_in;
printf("Set handler: %p\n", h);
return +[](Origin*)
{
printf("Into callback we go.\n");
(h->*func)();
printf("And we're out.\n");
};
}
struct StaticHal
{
static void Initialize()
@ -48,6 +64,16 @@ struct StaticHal
(void)micros;
#endif
}
static void enableInterrupts()
{
__enable_irq();
}
static void disableInterrupts()
{
__disable_irq();
}
};
#ifdef HAL_GPIO_MODULE_ENABLED
@ -101,7 +127,31 @@ struct SerialInterface
bool Receive(std::uint8_t* data, const std::uint32_t data_len)
{
return transmit(handle, data, data_len, 100) == HAL_StatusTypeDef::HAL_OK;
return receive(handle, data, data_len, 100) == HAL_StatusTypeDef::HAL_OK;
}
};
template<typename T,
HAL_StatusTypeDef (*transmit)(T*, std::uint8_t* data, std::uint16_t data_len),
HAL_StatusTypeDef (*receive)(T*, std::uint8_t* data, std::uint16_t data_len)>
struct SerialInterfaceAsync
{
using underlying_handle_type = T;
underlying_handle_type* handle;
SerialInterfaceAsync() = delete;
explicit SerialInterfaceAsync(underlying_handle_type* handle)
: handle(handle)
{ }
bool Transmit(std::uint8_t* data, const std::uint32_t data_len)
{
return transmit(handle, data, data_len) == HAL_StatusTypeDef::HAL_OK;
}
bool Receive(std::uint8_t* data, const std::uint32_t data_len)
{
return receive(handle, data, data_len) == HAL_StatusTypeDef::HAL_OK;
}
};
@ -178,6 +228,7 @@ struct SpiRegisters
#ifdef HAL_UART_MODULE_ENABLED
using UartInterface = SerialInterface<UART_HandleTypeDef, HAL_UART_Transmit, HAL_UART_Receive>;
using UartInterfaceDMA = SerialInterfaceAsync<UART_HandleTypeDef, HAL_UART_Transmit_DMA, HAL_UART_Receive_DMA>;
#endif // HAL_UART_MODULE_ENABLED
@ -217,6 +268,18 @@ struct PwmChannel
#endif // HAL_TIM_MODULE_ENABLED
struct ItmSerialInterface
{
bool Transmit(std::uint8_t* data, const std::uint32_t data_len)
{
for (std::uint32_t i = 0; i < data_len; i++)
{
ITM_SendChar(char(data[i]));
}
return true;
}
};
}
}
}

View File

@ -11,8 +11,6 @@
#include <array>
#include <limits>
#include "spi.h"
#include "peripherals_imu.hpp"
#include "peripherals_utility.hpp"

View File

@ -13,6 +13,10 @@
namespace Peripherals
{
#define SKULLC_CONCAT_IMPL(x, y) x ## y
#define SKULLC_CONCAT(x, y) SKULLC_CONCAT_IMPL(x, y)
#define SKULLC_TAG struct SKULLC_CONCAT(SkullCTag_, __COUNTER__)
template<typename T>
constexpr const T& Clamp(const T& v, const T& lo, const T& hi)
{

View File

@ -1,12 +1,9 @@
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
if(WITH_HAL)
set(additional_sources
Src/utility_asynchuartlogger.cpp
Src/utility_atomicscopeguard.cpp
Src/utility_itmlogger.cpp
Src/utility_uartlogger.cpp)
endif()
#if(WITH_HAL)
# set(additional_sources
# )
#endif()
add_library(utility STATIC
Src/utility_logging.cpp

View File

@ -1,49 +0,0 @@
/*
* 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_ */

View File

@ -0,0 +1,97 @@
/*
* utility_asynclogger.hpp
*
* Created on: Apr 1, 2021
* Author: erki
*/
#ifndef UTILITY_INC_UTILITY_ASYNCLOGGER_HPP_
#define UTILITY_INC_UTILITY_ASYNCLOGGER_HPP_
#include "utility_atomicscopeguard.hpp"
#include "utility_ringbuffer.hpp"
#include "utility_ilogger.hpp"
#include <array>
#include <cstdarg>
#include <cstdio>
namespace Utility
{
template<typename T, typename H, std::size_t BufferCount, std::size_t BufferSize>
class AsyncLogger : public ILogger
{
public:
using serial_interface = T;
using hal = H;
AsyncLogger() = delete;
explicit AsyncLogger(const serial_interface& serial)
: _serial(serial)
{ }
AsyncLogger(const AsyncLogger&) = delete;
AsyncLogger(AsyncLogger&&) = delete;
AsyncLogger& operator=(const AsyncLogger&) = delete;
AsyncLogger& operator=(AsyncLogger&&) = delete;
void log(const char* format, ...)
{
{
AtomicScopeGuard<hal> 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<hal> s;
_buffer_queue.increment_tail();
if (!_in_flight)
_sendNextLog();
}
}
void txCompleteCallback()
{
if (!_buffer_queue.empty())
_sendNextLog();
else
_in_flight = false;
}
private:
struct _Data
{
std::array<char, BufferSize> buffer;
std::int32_t length = 0;
};
Ringbuffer<_Data, BufferCount> _buffer_queue;
serial_interface _serial;
bool _in_flight = false;
void _sendNextLog()
{
_in_flight = true;
_Data& head = _buffer_queue.front();
_serial.Transmit(reinterpret_cast<uint8_t*>(head.buffer.data()), head.length);
_buffer_queue.pop_front();
}
};
}
#endif /* UTILITY_INC_UTILITY_ASYNCLOGGER_HPP_ */

View File

@ -13,19 +13,37 @@
namespace Utility
{
class AtomicScopeGuard
template<typename H>
struct AtomicScopeGuard
{
public:
AtomicScopeGuard();
using hal = H;
AtomicScopeGuard()
{
hal::disableInterrupts();
_reentrancy_counter++;
}
AtomicScopeGuard(const AtomicScopeGuard&) = delete;
AtomicScopeGuard(AtomicScopeGuard&&) = delete;
AtomicScopeGuard& operator=(const AtomicScopeGuard&) = delete;
AtomicScopeGuard& operator=(AtomicScopeGuard&&) = delete;
~AtomicScopeGuard()
{
_reentrancy_counter--;
if (!_reentrancy_counter)
hal::enableInterrupts();
}
~AtomicScopeGuard();
private:
static std::int32_t _reentrancy_counter;
};
template<typename H>
std::int32_t AtomicScopeGuard<H>::_reentrancy_counter = 0;
}
#endif /* UTILITY_INC_UTILITY_ATOMICSCOPEGUARD_HPP_ */

View File

@ -1,30 +0,0 @@
//
// Created by erki on 14.03.21.
//
#ifndef SKULLC_UTILITY_ITMLOGGER_HPP_
#define SKULLC_UTILITY_ITMLOGGER_HPP_
#include "utility_logging.hpp"
#include <array>
namespace Utility
{
class ITMLogger : public ILogger
{
public:
ITMLogger() = default;
ITMLogger(const ITMLogger&) = delete;
ITMLogger(ITMLogger&&) = delete;
void log(const char* format, ...) override;
private:
std::array<char, 255> _buffer;
};
}
#endif //SKULLC_UTILITY_ITMLOGGER_HPP_

View File

@ -0,0 +1,52 @@
/*
* utility_seriallogger.hpp
*
* Created on: Apr 1, 2021
* Author: erki
*/
#ifndef UTILITY_INC_UTILITY_SERIALLOGGER_HPP_
#define UTILITY_INC_UTILITY_SERIALLOGGER_HPP_
#include <array>
#include <cstdarg>
#include <cstdio>
#include "utility_ilogger.hpp"
namespace Utility
{
template<typename T, std::size_t N>
class SerialLogger : public ILogger
{
public:
using serial_interface = T;
SerialLogger() = delete;
explicit SerialLogger(const serial_interface& serial)
: _serial(serial)
{ }
void log(const char* format, ...) override
{
std::va_list args;
va_start(args, format);
const std::int32_t len = vsnprintf(_buffer.data(), _buffer.size(), format, args);
if (len > 0)
_serial.Transmit(reinterpret_cast<std::uint8_t*>(_buffer.data()), len);
va_end(args);
}
private:
serial_interface _serial;
std::array<char, N> _buffer;
};
}
#endif /* UTILITY_INC_UTILITY_SERIALLOGGER_HPP_ */

View File

@ -1,39 +0,0 @@
/*
* utility_uartlogger.hpp
*
* Created on: Mar 20, 2021
* Author: erki
*/
#ifndef SKULLC_UTILITY_UARTLOGGER_HPP_
#define SKULLC_UTILITY_UARTLOGGER_HPP_
#include "utility_logging.hpp"
#include "usart.h"
#include <array>
namespace Utility
{
class UARTLogger : public ILogger
{
public:
explicit UARTLogger(UART_HandleTypeDef* huart);
UARTLogger() = delete;
UARTLogger(const UARTLogger&) = delete;
UARTLogger(UARTLogger&&) = delete;
void log(const char* format, ...) override;
private:
UART_HandleTypeDef* _huart;
std::array<char, 255> _buffer;
};
}
#endif /* SKULLC_UTILITY_UARTLOGGER_HPP_ */

View File

@ -1,73 +0,0 @@
/*
* 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();
}
}

View File

@ -1,32 +0,0 @@
/*
* 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();
}
}

View File

@ -1,33 +0,0 @@
/*
* utility_logger.cpp
*
* Created on: Mar 13, 2021
* Author: erki
*/
#include "utility_itmlogger.hpp"
#include <cstdarg>
#include <cstdio>
#include "main.h"
namespace Utility
{
void ITMLogger::log(const char* format, ...)
{
std::va_list args;
va_start(args, format);
const std::int32_t len = vsnprintf(_buffer.data(), _buffer.size(), format, args);
for (std::int32_t i = 0; i < len; i++)
{
ITM_SendChar(_buffer[i]);
}
va_end(args);
}
}

View File

@ -1,32 +0,0 @@
/*
* utility_uartlogger.cpp
*
* Created on: Mar 20, 2021
* Author: erki
*/
#include "utility_uartlogger.hpp"
#include <cstdarg>
#include <cstdio>
namespace Utility
{
UARTLogger::UARTLogger(UART_HandleTypeDef* huart)
: _huart(huart)
{ }
void UARTLogger::log(const char* format, ...)
{
std::va_list args;
va_start(args, format);
const std::int32_t len = vsnprintf(_buffer.data(), _buffer.size(), format, args);
HAL_UART_Transmit(_huart, reinterpret_cast<std::uint8_t*>(_buffer.data()), len, 10);
va_end(args);
}
}