New logging interfaces
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
77178a21c9
commit
ce4f8eb8f5
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,8 +11,6 @@
|
||||
#include <array>
|
||||
#include <limits>
|
||||
|
||||
#include "spi.h"
|
||||
|
||||
#include "peripherals_imu.hpp"
|
||||
#include "peripherals_utility.hpp"
|
||||
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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_ */
|
||||
97
Utility/Inc/utility_asynclogger.hpp
Normal file
97
Utility/Inc/utility_asynclogger.hpp
Normal 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_ */
|
||||
@ -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_ */
|
||||
|
||||
@ -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_
|
||||
52
Utility/Inc/utility_seriallogger.hpp
Normal file
52
Utility/Inc/utility_seriallogger.hpp
Normal 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_ */
|
||||
@ -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_ */
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user