Clan up the structure

This commit is contained in:
Attila Body 2025-05-31 17:45:15 +02:00
parent 340f0329fa
commit 45141798d8
Signed by: abody
GPG key ID: BD0C6214E68FB5CF
42 changed files with 134 additions and 452 deletions

View file

@ -0,0 +1,10 @@
add_library(app STATIC
src/app.cpp
src/irq_bridge.cpp
)
target_include_directories(app PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/inc
)
target_link_libraries(app PUBLIC stm32cubemx platform f1ll)

11
components/app/inc/app.h Normal file
View file

@ -0,0 +1,11 @@
#pragma once
#if defined(__cplusplus)
extern "C" {
#endif
void app_main();
#if defined(__cplusplus)
}
#endif

View file

@ -0,0 +1,16 @@
#ifndef IRQ_BRIDGE_H_
#define IRQ_BRIDGE_H_
#if defined(__cplusplus)
extern "C" {
#endif
void usart1_tx_dma_isr();
void usart1_rx_dma_isr();
void usart1_isr();
#if defined(__cplusplus)
}
#endif
#endif // IRQ_BRIDGE_H_

View file

@ -0,0 +1,16 @@
#include <app.h>
#include <main.h>
#include <f1ll/console_handler.h>
void app_main()
{
f1ll::console_handler::init(USART1, DMA1, LL_DMA_CHANNEL_5, LL_DMA_CHANNEL_4);
while (true) {
f1ll::console_handler::instance().print("->> Hello <<-\r\n");
LL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
LL_mDelay(500);
}
}

View file

@ -0,0 +1,18 @@
#include <irq_bridge.h>
#include <f1ll/console_handler.h>
void usart1_tx_dma_isr() // DMA1 channel 4
{
f1ll::console_handler::instance().tx_dma_isr();
}
void usart1_rx_dma_isr() // DMA1 channel 5
{
f1ll::console_handler::instance().rx_dma_isr();
}
void usart1_isr()
{
f1ll::console_handler::instance().usart_isr();
}

View file

@ -0,0 +1,15 @@
add_library(f1ll STATIC
src/usart_core.cpp
src/dma_helper.cpp
src/str_util.cpp
src/console_handler.cpp
)
target_include_directories(f1ll PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/inc
)
target_link_libraries(f1ll PUBLIC platform stm32cubemx)
# ST code quality workaround - Suppres register storage class warning (C++17...)
target_compile_options(f1ll PRIVATE -Wno-register)

View file

@ -0,0 +1,47 @@
/*
* ll_consolehandler.h
*
* Created on: Nov 7, 2019
* Author: abody
*/
#ifndef LL_CONSOLEHANDLER_H_
#define LL_CONSOLEHANDLER_H_
#include "f1ll/usart_core.h"
#include "singleton.h"
namespace f1ll {
class console_handler : public usart_core, public singleton<console_handler>
{
friend class singleton<console_handler>;
public:
void print(char const *s);
void flush();
void append(char const *s);
private:
console_handler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t channelRx, uint32_t channelTx);
// LL_UsartCore pure virtual function implementations
virtual void receiver_idle(void) override;
virtual void transmission_complete(void) override;
virtual void framing_error(void) override;
virtual void overrun(void) override;
virtual void rx_dma_transfer_complete(void) override;
virtual void rx_dma_half_transfer(void) override;
virtual void rx_dma_error(void) override;
virtual void tx_dma_transfer_complete(void) override;
virtual void tx_dma_half_transfer(void) override;
virtual void tx_dma_error(void) override;
char m_buffer[128];
uint16_t m_used = 0;
volatile bool m_busy = false;
};
} // namespace f1ll
#endif /* LL_CONSOLEHANDLER_H_ */

View file

@ -0,0 +1,49 @@
/*
* ll_dmahelper.h
*
* Created on: Oct 25, 2019
* Author: abody
*/
#ifndef LL_DMAHELPER_H_
#define LL_DMAHELPER_H_
#include <inttypes.h>
#include <platform/dma_ll.h>
namespace f1ll {
class dma_helper
{
public:
dma_helper(DMA_TypeDef *dma, uint32_t channel);
dma_helper(dma_helper const &base) = default;
inline DMA_TypeDef *get_dma() const { return m_dma; }
inline uint32_t get_channel() const { return m_channel; }
inline volatile uint32_t *get_is_reg() const { return m_is_reg; }
inline volatile uint32_t *get_ifc_reg() const { return m_ifc_reg; }
inline uint32_t get_te_mask() const { return m_te_masks[m_channel - 1]; }
inline uint32_t get_ht_mask() const { return m_ht_masks[m_channel - 1]; }
inline uint32_t get_tc_mask() const { return m_tc_masks[m_channel - 1]; }
inline uint32_t get_gi_mask() const { return m_gi_masks[m_channel - 1]; }
inline bool is_enabled_it_te() { return LL_DMA_IsEnabledIT_TE(m_dma, m_channel) != 0; }
inline bool is_enabled_it_ht() { return LL_DMA_IsEnabledIT_HT(m_dma, m_channel) != 0; }
inline bool is_enabled_it_tc() { return LL_DMA_IsEnabledIT_TC(m_dma, m_channel) != 0; }
private:
DMA_TypeDef *m_dma;
uint32_t m_channel;
volatile uint32_t *m_is_reg;
volatile uint32_t *m_ifc_reg;
static const uint32_t m_te_masks[7];
static const uint32_t m_ht_masks[7];
static const uint32_t m_tc_masks[7];
static const uint32_t m_gi_masks[7];
};
} /* namespace f4ll */
#endif /* LL_DMAHELPER_H_ */

View file

@ -0,0 +1,30 @@
#ifndef SINGLETON_H_
#define SINGLETON_H_
#include <utility>
namespace f1ll {
template <typename T> class singleton
{
public:
static T &instance() { return *m_instance; }
template <typename... args_t> static T &init(args_t &&...args)
{
static T instance{std::forward<args_t>(args)...};
m_instance = &instance;
return instance;
}
protected:
singleton() = default;
singleton(const singleton &) = delete;
singleton &operator=(const singleton &) = delete;
static T *m_instance;
};
template <typename T> T *singleton<T>::m_instance = nullptr;
} // namespace f1ll {
#endif /* SINGLETON_H_ */

View file

@ -0,0 +1,31 @@
/*
* strutil.h
*
* Created on: Feb 11, 2017
* Author: compi
*/
#ifndef _STM32PLUS_STRUTIL_H_
#define _STM32PLUS_STRUTIL_H_
#include <stddef.h>
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {
#endif
//////////////////////////////////////////////////////////////////////////////
size_t strcpy_ex(char *dst, char const *src);
size_t uitodec(char* buffer, uint32_t data);
size_t uitohex(char* buffer, uint32_t data, uint8_t chars);
size_t itodec(char* buffer, int data);
size_t itohex(char* buffer, int data);
void strrev(char *first, char *last);
char tochr(const uint8_t in, const uint8_t upper);
#ifdef __cplusplus
}
#endif
#endif /* _STM32PLUS_STRUTIL_H_ */

View file

@ -0,0 +1,55 @@
/*
* ll_dmadrivenusartcore.h
*
* Created on: Nov 4, 2019
* Author: abody
*/
#ifndef LL_USARTCORE_H_
#define LL_USARTCORE_H_
#include <platform/usart_ll.h>
#include "f1ll/dma_helper.h"
namespace f1ll {
class usart_core
{
public:
static inline void usart_irq(usart_core *_this) { _this->usart_isr(); }
static inline void rx_dma_irq(usart_core *_this) { _this->rx_dma_isr(); }
static inline void tx_dma_irq(usart_core *_this) { _this->tx_dma_isr(); }
void setup_transmit(void const *buffer, uint16_t length);
void setup_receive(void *buffer, uint16_t length);
protected:
usart_core(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t channel_rx, uint32_t stream_tx);
USART_TypeDef *m_usart;
dma_helper m_rxDma;
dma_helper m_txDma;
private:
virtual void receiver_idle(void) = 0;
virtual void transmission_complete(void) = 0;
virtual void framing_error(void) = 0;
virtual void overrun(void) = 0;
virtual void rx_dma_transfer_complete(void) = 0;
virtual void rx_dma_half_transfer(void) = 0;
virtual void rx_dma_error(void) = 0;
virtual void tx_dma_transfer_complete(void) = 0;
virtual void tx_dma_half_transfer(void) = 0;
virtual void tx_dma_error(void) = 0;
public:
void usart_isr();
void rx_dma_isr();
void tx_dma_isr();
};
} // namespace f1ll
#endif /* LL_USARTCORE_H_ */

View file

@ -0,0 +1,65 @@
/*
* ll_consolehandler.cpp
*
* Created on: Nov 7, 2019
* Author: abody
*/
#include <f1ll/console_handler.h>
#include <string.h>
namespace f1ll {
console_handler::console_handler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t channelRx, uint32_t channelTx)
: usart_core(usart, dma, channelRx, channelTx)
{
}
void console_handler::receiver_idle(void) {}
void console_handler::transmission_complete(void)
{
m_busy = false;
m_used = 0;
}
void console_handler::framing_error(void) {}
void console_handler::overrun(void) {}
void console_handler::rx_dma_transfer_complete(void) {}
void console_handler::rx_dma_half_transfer(void) {}
void console_handler::rx_dma_error(void) {}
void console_handler::tx_dma_transfer_complete(void)
{
LL_USART_EnableIT_TC(m_usart);
LL_DMA_DisableChannel(m_txDma.get_dma(), m_txDma.get_channel());
}
void console_handler::tx_dma_half_transfer(void) {}
void console_handler::tx_dma_error(void) {}
void console_handler::append(char const *s)
{
while (m_busy)
;
size_t len = strlen(s);
size_t max_len = sizeof(m_buffer) - m_used;
strncpy(m_buffer + m_used, s, max_len);
m_used += len < max_len ? len : max_len;
}
void console_handler::flush()
{
while (m_busy)
;
if (m_used) {
m_busy = true;
setup_transmit(m_buffer, m_used);
}
}
void console_handler::print(char const *s)
{
append(s);
flush();
}
} // namespace f1ll

View file

@ -0,0 +1,38 @@
/*
q * ll_dmahelper.cpp
*
* Created on: Oct 25, 2019
* Author: abody
*/
#include <f1ll/dma_helper.h>
namespace f1ll {
const uint32_t dma_helper::m_te_masks[7] = {
DMA_ISR_TEIF1, DMA_ISR_TEIF2, DMA_ISR_TEIF3, DMA_ISR_TEIF4,
DMA_ISR_TEIF5, DMA_ISR_TEIF6, DMA_ISR_TEIF7};
const uint32_t dma_helper::m_ht_masks[7] = {
DMA_ISR_HTIF1, DMA_ISR_HTIF2, DMA_ISR_HTIF3, DMA_ISR_HTIF4,
DMA_ISR_HTIF5, DMA_ISR_HTIF6, DMA_ISR_HTIF7};
const uint32_t dma_helper::m_tc_masks[7] = {
DMA_ISR_TCIF1, DMA_ISR_TCIF2, DMA_ISR_TCIF3, DMA_ISR_TCIF4,
DMA_ISR_TCIF5, DMA_ISR_TCIF6, DMA_ISR_TCIF7};
const uint32_t dma_helper::m_gi_masks[7] = {
DMA_ISR_GIF1, DMA_ISR_GIF2, DMA_ISR_GIF3, DMA_ISR_GIF4,
DMA_ISR_GIF5, DMA_ISR_GIF6, DMA_ISR_GIF7};
dma_helper::dma_helper(DMA_TypeDef *dma, uint32_t channel)
: m_dma(dma), m_channel(channel)
#ifdef DMA2
,
m_is_reg(dma == DMA1 ? &DMA1->ISR : &DMA2->ISR),
m_ifc_reg(dma == DMA1 ? &DMA1->IFCR : &DMA2->IFCR)
#else
,
m_is_reg(&DMA1->ISR), m_ifc_reg(&DMA1->IFCR)
#endif
{
}
} // namespace f1ll

View file

@ -0,0 +1,98 @@
#include <f1ll/str_util.h>
#include <stdint.h>
//////////////////////////////////////////////////////////////////////////////
size_t strcpy_ex(char *dst, char const *src) {
size_t ret = 0;
do {
*dst++ = *src;
++ret;
} while (*src++);
return ret - 1;
}
//////////////////////////////////////////////////////////////////////////////
void strrev(char *first, char *last) {
char tmp;
while (last > first) {
tmp = *first;
*first++ = *last;
*last-- = tmp;
}
}
//////////////////////////////////////////////////////////////////////////////
char tochr(const uint8_t in, const uint8_t upper) {
return in + ((in < 10) ? '0' : (upper ? 'A' : 'a') - 10);
}
//////////////////////////////////////////////////////////////////////////////
size_t uitodec(char *buffer, uint32_t data) {
char *b2 = buffer;
if (!data) {
*b2++ = '0';
*b2 = '\0';
return 1;
}
while (data) {
*b2++ = (data % 10) + '0';
data /= 10;
}
size_t ret = b2 - buffer;
*b2-- = 0;
strrev(buffer, b2);
return ret;
}
//////////////////////////////////////////////////////////////////////////////
size_t uitohex(char *buffer, uint32_t data, uint8_t chars) {
char *b2 = buffer;
size_t ret = 0;
if (chars == 0xff || !chars) {
if (!data) {
*b2++ = '0';
*b2 = '\0';
return 1;
}
while (data) {
uint8_t curval = data & 0x0f;
*b2++ = tochr(curval, 1);
data >>= 4;
}
ret = b2 - buffer;
} else {
ret = chars;
for (uint8_t pos = 0; pos < (uint8_t)ret; ++pos) {
*b2++ = tochr(data & 0x0f, 1);
data >>= 4;
}
}
*b2-- = 0;
strrev(buffer, b2);
return ret;
}
//////////////////////////////////////////////////////////////////////////////
size_t itodec(char *buffer, int data) {
if (data < 0) {
*buffer++ = '-';
return uitodec(buffer, -data) + 1;
}
return uitodec(buffer, data);
}
//////////////////////////////////////////////////////////////////////////////
size_t itohex(char *buffer, int data) {
if (data < 0) {
*buffer++ = '-';
return uitohex(buffer, -data, 0) + 1;
}
return uitohex(buffer, data, 0);
}

View file

@ -0,0 +1,119 @@
/*
* ll_dmadrivenusartcore.cpp
*
* Created on: Nov 4, 2019
* Author: abody
*/
#include <f1ll/usart_core.h>
namespace f1ll {
usart_core::usart_core(USART_TypeDef *usart, DMA_TypeDef *dma,
uint32_t channelRx, uint32_t channelTx)
: m_usart(usart), m_rxDma(dma, channelRx), m_txDma(dma, channelTx) {
uint32_t status = usart->SR;
volatile uint32_t tmpreg =
usart->DR; // clearing some of the error/status bits in the USART
(void)tmpreg;
(void)status;
*m_txDma.get_ifc_reg() = m_txDma.get_gi_mask();
*m_rxDma.get_ifc_reg() = m_rxDma.get_gi_mask();
LL_DMA_EnableIT_HT(dma, channelRx);
LL_DMA_EnableIT_TC(dma, channelRx);
LL_DMA_EnableIT_TE(dma, channelRx);
LL_DMA_EnableIT_HT(dma, channelTx);
LL_DMA_EnableIT_TC(dma, channelTx);
LL_DMA_EnableIT_TE(dma, channelTx);
}
void usart_core::usart_isr() {
uint32_t status = m_usart->SR;
volatile uint32_t tmpreg =
m_usart->DR; // clearing some of the error/status bits in the HW
(void)tmpreg;
if (LL_USART_IsEnabledIT_TC(m_usart) &&
LL_USART_IsActiveFlag_TC(m_usart)) { // transmission complete
LL_USART_DisableIT_TC(m_usart);
transmission_complete();
}
if (LL_USART_IsEnabledIT_IDLE(m_usart) && (status & USART_SR_IDLE)) {
receiver_idle();
}
if (LL_USART_IsEnabledIT_ERROR(m_usart)) {
if (status & USART_SR_FE) {
framing_error();
}
if (status & USART_SR_ORE) {
overrun();
}
}
}
void usart_core::rx_dma_isr() {
if (*m_rxDma.get_is_reg() & m_rxDma.get_tc_mask()) {
*m_rxDma.get_ifc_reg() = m_rxDma.get_tc_mask();
if (m_rxDma.is_enabled_it_tc()) {
rx_dma_transfer_complete();
}
}
if (*m_rxDma.get_is_reg() & m_rxDma.get_ht_mask()) {
*m_rxDma.get_ifc_reg() = m_rxDma.get_ht_mask();
if (m_rxDma.is_enabled_it_ht()) {
rx_dma_half_transfer();
}
}
if (*m_rxDma.get_is_reg() & m_rxDma.get_te_mask()) {
*m_rxDma.get_ifc_reg() = m_rxDma.get_te_mask();
if (m_rxDma.is_enabled_it_te()) {
rx_dma_error();
}
}
}
void usart_core::tx_dma_isr() {
if (*m_txDma.get_is_reg() & m_txDma.get_tc_mask()) { // DMA transfer complete
*m_txDma.get_ifc_reg() = m_txDma.get_tc_mask();
if (m_txDma.is_enabled_it_tc()) {
tx_dma_transfer_complete();
}
}
if (*m_txDma.get_is_reg() & m_txDma.get_ht_mask()) {
*m_txDma.get_ifc_reg() = m_txDma.get_ht_mask();
if (m_txDma.is_enabled_it_ht()) {
tx_dma_half_transfer();
}
}
if (*m_txDma.get_is_reg() & m_txDma.get_te_mask()) {
*m_txDma.get_ifc_reg() = m_txDma.get_te_mask();
if (m_txDma.is_enabled_it_te()) {
tx_dma_error();
}
}
}
void usart_core::setup_transmit(void const *buffer, uint16_t length) {
LL_DMA_ConfigAddresses(m_txDma.get_dma(), m_txDma.get_channel(),
reinterpret_cast<uint32_t>(buffer),
LL_USART_DMA_GetRegAddr(m_usart),
LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetDataLength(m_txDma.get_dma(), m_txDma.get_channel(), length);
LL_USART_EnableDMAReq_TX(m_usart);
LL_DMA_EnableChannel(m_txDma.get_dma(), m_txDma.get_channel());
}
void usart_core::setup_receive(void *buffer, uint16_t length) {
LL_DMA_ConfigAddresses(m_rxDma.get_dma(), m_rxDma.get_channel(),
LL_USART_DMA_GetRegAddr(m_usart),
reinterpret_cast<uint32_t>(buffer),
LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
LL_DMA_SetDataLength(m_rxDma.get_dma(), m_rxDma.get_channel(), length);
LL_USART_EnableDMAReq_RX(m_usart);
LL_USART_ClearFlag_ORE(m_usart);
LL_DMA_EnableChannel(m_rxDma.get_dma(), m_rxDma.get_channel());
}
} // namespace f1ll

View file

@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.22)
add_library(platform INTERFACE)
# Enable CMake support for ASM and C languages
enable_language(C CXX ASM)
target_include_directories(platform INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(platform INTERFACE)

View file

@ -0,0 +1,6 @@
#ifndef __PLATFORM_CRC_LL_H_INCLUDED
#define __PLATFORM_CRC_LL_H_INCLUDED
#include "crc.h"
#endif // __PLATFORM_CRC_LL_H_INCLUDED

View file

@ -0,0 +1,6 @@
#ifndef __PLATFORM_DMA_LL_H_INCLUDED
#define __PLATFORM_DMA_LL_H_INCLUDED
#include "stm32f1xx_ll_dma.h"
#endif // __PLATFORM_DMA_LL_H_INCLUDED

View file

@ -0,0 +1,6 @@
#ifndef __PLATFORM_USART_LL_H_INCLUDED
#define __PLATFORM_USART_LL_H_INCLUDED
#include <stm32f1xx_ll_gpio.h>
#endif // __PLATFORM_USART_LL_H_INCLUDED

View file

@ -0,0 +1,6 @@
#ifndef __PLATFORM_USART_LL_H_INCLUDED
#define __PLATFORM_USART_LL_H_INCLUDED
#include <stm32f1xx_ll_usart.h>
#endif // __PLATFORM_USART_LL_H_INCLUDED

View file

@ -0,0 +1,6 @@
#ifndef __PLATFORM_USART_LL_H_INCLUDED
#define __PLATFORM_USART_LL_H_INCLUDED
#include <stm32f1xx_ll_utils.h>
#endif // __PLATFORM_USART_LL_H_INCLUDED