From 09de7c74038874bc9bac8917b5ed0bac366975d1 Mon Sep 17 00:00:00 2001 From: Cantonplas Date: Wed, 22 Oct 2025 11:27:26 +0200 Subject: [PATCH 001/109] It compiles the old version with constexpr --- Inc/HALAL/Models/DMA/DMA.hpp | 39 ++++++++++++++++++++++++++++-------- Src/HALAL/Models/DMA/DMA.cpp | 33 +++++++----------------------- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 74d7864aa..cacb6df65 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -10,11 +10,11 @@ #include "C++Utilities/CppUtils.hpp" #include "stm32h7xx_hal.h" #include "HALAL/Models/MPUManager/MPUManager.hpp" - - +#include +#define MAX_NUM_STREAMS 15 class DMA { public: - enum Stream : uint8_t { + enum class Stream : uint8_t { DMA1Stream0 = 11, DMA1Stream1 = 12, DMA1Stream2 = 13, @@ -32,11 +32,34 @@ class DMA { DMA2Stream7 = 70, }; - static void inscribe_stream(); - static void inscribe_stream(Stream dma_stream); +void static inline constexpr inscribe_stream() { + for (int i = 0; i < MAX_NUM_STREAMS; i++) { + if (available_streams[i] == true) { + available_streams[i] = false; + return; + } + } + assert(false); // No DMA_Stream available +} +void static inline constexpr inscribe_stream(Stream dma_stream) { + for(int i = 0; i < MAX_NUM_STREAMS; i++){ + if(streams[i] == dma_stream && available_streams[i] == true){ + available_streams[i] = false; + return; + }else{ + break; + } + } + assert(false); //The DMA_STREAM that you want is not available; +} static void start(); private: - static vector available_streams; - static vector inscribed_streams; -}; + inline static constinit std::array available_streams{true}; + static constexpr std::array streams = { + Stream::DMA1Stream0, Stream::DMA1Stream1, Stream::DMA1Stream2, Stream::DMA1Stream3, + Stream::DMA1Stream4, Stream::DMA1Stream5, Stream::DMA1Stream6, + Stream::DMA2Stream0, Stream::DMA2Stream1, Stream::DMA2Stream2, Stream::DMA2Stream3, + Stream::DMA2Stream4, Stream::DMA2Stream5, Stream::DMA2Stream6, Stream::DMA2Stream7 + }; +}; \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index e9982734d..40d114fe8 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -8,34 +8,15 @@ #include "HALAL/Models/DMA/DMA.hpp" #include "ErrorHandler/ErrorHandler.hpp" -vector DMA::available_streams = { - DMA1Stream0, DMA1Stream1, DMA1Stream2, DMA1Stream3, DMA1Stream4, DMA1Stream5, DMA1Stream6, DMA2Stream0, DMA2Stream1, DMA2Stream2, DMA2Stream3, DMA2Stream4, DMA2Stream5, DMA2Stream6, DMA2Stream7, -}; - -vector DMA::inscribed_streams = {}; - -void DMA::inscribe_stream() { - if (available_streams.empty()) { - ErrorHandler("There are not any DMA Streams availables"); - return; - } - inscribed_streams.push_back(available_streams.back()); - available_streams.pop_back(); -} - -void DMA::inscribe_stream(Stream dma_stream) { - if (std::find(available_streams.begin(), available_streams.end(), dma_stream) == available_streams.end()) { - ErrorHandler("The DMA stream %d is not available", dma_stream); - return; - } - inscribed_streams.push_back(dma_stream); -} - void DMA::start() { __HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_DMA2_CLK_ENABLE(); - for (Stream dma_stream : inscribed_streams) { - HAL_NVIC_SetPriority( (IRQn_Type)dma_stream, 0, 0); - HAL_NVIC_EnableIRQ( (IRQn_Type)dma_stream); + int i = 0; + for (bool dma_stream : available_streams) { + if (dma_stream) { + HAL_NVIC_SetPriority((IRQn_Type)streams[i], 0, 0); + HAL_NVIC_EnableIRQ((IRQn_Type)streams[i]); + } + i++; } } From 8962c950b897f07bb73bbb294f016610133c456b Mon Sep 17 00:00:00 2001 From: Cantonplas Date: Wed, 22 Oct 2025 15:13:47 +0200 Subject: [PATCH 002/109] Draft of the new dma class --- Inc/HALAL/Models/DMA/DMA.hpp | 278 ++++++++++++++++++++++++++++++++--- Src/HALAL/Models/DMA/DMA.cpp | 24 +-- 2 files changed, 273 insertions(+), 29 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index cacb6df65..ad2d445b1 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -9,9 +9,29 @@ #include "C++Utilities/CppUtils.hpp" #include "stm32h7xx_hal.h" +#include "main.h" #include "HALAL/Models/MPUManager/MPUManager.hpp" #include +#include #define MAX_NUM_STREAMS 15 +#define DMA_USED 10 //Temporal name, i cant think of a better one + + +// We only have 6 peripherals using DMA for now, the new ssd will need to be added later here +extern DMA_HandleTypeDef hdma_adc1; +extern DMA_HandleTypeDef hdma_adc2; +extern DMA_HandleTypeDef hdma_adc3; + +extern DMA_HandleTypeDef hdma_i2c2_rx; +extern DMA_HandleTypeDef hdma_i2c2_tx; + +extern DMA_HandleTypeDef hdma_fmac_preload; +extern DMA_HandleTypeDef hdma_fmac_read; +extern DMA_HandleTypeDef hdma_fmac_write; + +extern DMA_HandleTypeDef hdma_spi3_rx; +extern DMA_HandleTypeDef hdma_spi3_tx; + class DMA { public: enum class Stream : uint8_t { @@ -31,31 +51,251 @@ class DMA { DMA2Stream6 = 69, DMA2Stream7 = 70, }; + + enum class Peripheral_type { + Adc1, + Adc2, + Adc3, + I2c2, + Fmac, + Spi3 + }; + template + struct Peripheral_type_instance { + DMA_HandleTypeDef* dma_handle; + DMA_HandleTypeDef* global_handle; + T* handle; + Stream stream; + + }; + //To allow the array to be multiple types, idk first thing that came to mind + using InstanceList = std::variant< + Peripheral_type_instance, + Peripheral_type_instance, + Peripheral_type_instance, + Peripheral_type_instance + >; -void static inline constexpr inscribe_stream() { - for (int i = 0; i < MAX_NUM_STREAMS; i++) { - if (available_streams[i] == true) { - available_streams[i] = false; - return; - } - } - assert(false); // No DMA_Stream available -} -void static inline constexpr inscribe_stream(Stream dma_stream) { - for(int i = 0; i < MAX_NUM_STREAMS; i++){ - if(streams[i] == dma_stream && available_streams[i] == true){ - available_streams[i] = false; - return; - }else{ + template + void static inline constexpr inscribe_stream(T* handle,Peripheral_type peripheral_type) + { + static_assert(is_variant_member, MyInstanceVariant>::value, + "Handle Type not allowed on DMA::inscribe_stream"); + assert(handle != nullptr); + assert(inscribed_index < DMA_USED); + + + switch (peripheral_type) + { + case Peripheral_type::Adc1: + static_assert(handle->Instance == ADC1, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc1"); + Instance instance; + instance.handle = handle; + hdma_adc1.Instance = DMA1_Stream0; + hdma_adc1.Init.Request = DMA_REQUEST_ADC1; + hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; + hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_adc1.Init.Mode = DMA_CIRCULAR; + hdma_adc1.Init.Priority = DMA_PRIORITY_LOW; + hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_adc1; + instance.stream = Stream::DMA1Stream0; + instance.global_handle= &DMA_Handle + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case Peripheral_type::Adc2: + static_assert(handle->Instance == ADC2, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc2"); + Instance instance; + instance.handle = handle; + hdma_adc2.Instance = DMA1_Stream1; + hdma_adc2.Init.Request = DMA_REQUEST_ADC2; + hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_adc2.Init.MemInc = DMA_MINC_ENABLE; + hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_adc2.Init.Mode = DMA_CIRCULAR; + hdma_adc2.Init.Priority = DMA_PRIORITY_LOW; + hdma_adc2.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_adc2; + instance.stream = Stream::DMA1Stream1; + instance.global_handle= &DMA_Handle + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case Peripheral_type::Adc3: + static_assert(handle->Instance == ADC3, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc3"); + Instance instance; + instance.handle = handle; + hdma_adc3.Instance = DMA1_Stream2; + hdma_adc3.Init.Request = DMA_REQUEST_ADC3; + hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_adc3.Init.MemInc = DMA_MINC_ENABLE; + hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_adc3.Init.Mode = DMA_CIRCULAR; + hdma_adc3.Init.Priority = DMA_PRIORITY_LOW; + hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_adc3; + instance.stream = Stream::DMA1Stream2; + instance.global_handle= &DMA_Handle + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case Peripheral_type::I2c2: + static_assert(handle->Instance == I2C2, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::I2c2"); + Instance instance; + instance.handle = handle; + hdma_i2c2_rx.Instance = DMA1_Stream3; + hdma_i2c2_rx.Init.Request = DMA_REQUEST_I2C2_RX; + hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_i2c2_rx.Init.Mode = DMA_CIRCULAR; + hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_i2c2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_i2c2_rx; + instance.stream = Stream::DMA1Stream3; + instance.global_handle= &hdmarx; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_i2c2_tx.Instance = DMA1_Stream4; + hdma_i2c2_tx.Init.Request = DMA_REQUEST_I2C2_TX; + hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_i2c2_tx.Init.Mode = DMA_CIRCULAR; + hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_LOW; + hdma_i2c2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_i2c2_tx; + instance.stream = Stream::DMA1Stream4; + instance.global_handle= &hdmatx; + + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case Peripheral_type::Fmac: + static_assert(handle->Instance == FMAC, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Fmac"); + Instance instance; + hdma_fmac_preload.Instance = DMA2_Stream0; + hdma_fmac_preload.Init.Request = DMA_REQUEST_MEM2MEM; + hdma_fmac_preload.Init.Direction = DMA_MEMORY_TO_MEMORY; + hdma_fmac_preload.Init.PeriphInc = DMA_PINC_ENABLE; + hdma_fmac_preload.Init.MemInc = DMA_MINC_DISABLE; + hdma_fmac_preload.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_fmac_preload.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_fmac_preload.Init.Mode = DMA_NORMAL; + hdma_fmac_preload.Init.Priority = DMA_PRIORITY_HIGH; + instance.dma_handle = &hdma_fmac_preload; + instance.stream = Stream::DMA2Stream0; + instance.global_handle= &hdmaPreload; + + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_fmac_write.Instance = DMA2_Stream1; + hdma_fmac_write.Init.Request = DMA_REQUEST_FMAC_WRITE; + hdma_fmac_write.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_fmac_write.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_fmac_write.Init.MemInc = DMA_MINC_ENABLE; + hdma_fmac_write.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_fmac_write.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_fmac_write.Init.Mode = DMA_NORMAL; + hdma_fmac_write.Init.Priority = DMA_PRIORITY_HIGH; + instance.dma_handle = &hdma_fmac_write; + instance.stream = Stream::DMA2Stream1; + instance.global_handle= &hdmaIn; + + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_fmac_read.Instance = DMA2_Stream2; + hdma_fmac_read.Init.Request = DMA_REQUEST_FMAC_READ; + hdma_fmac_read.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_fmac_read.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_fmac_read.Init.MemInc = DMA_MINC_ENABLE; + hdma_fmac_read.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_fmac_read.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_fmac_read.Init.Mode = DMA_NORMAL; + hdma_fmac_read.Init.Priority = DMA_PRIORITY_HIGH; + instance.dma_handle = &hdma_fmac_read; + instance.stream = Stream::DMA2Stream2; + instance.global_handle= &hdmaOut; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case Peripheral_type::Spi3: + static_assert(handle->Instance == SPI3, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Spi3"); + Instance instance; + hdma_spi3_rx.Instance = DMA1_Stream5; + hdma_spi3_rx.Init.Request = DMA_REQUEST_SPI3_RX; + hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_spi3_rx.Init.Mode = DMA_NORMAL; + hdma_spi3_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_spi3_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + instance.dma_handle = &hdma_spi3_rx; + instance.stream = Stream::DMA1Stream5; + instance.global_handle= &hdmarx; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_spi3_tx.Instance = DMA1_Stream6; + hdma_spi3_tx.Init.Request = DMA_REQUEST_SPI3_TX; + hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi3_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_spi3_tx.Init.Mode = DMA_NORMAL; + hdma_spi3_tx.Init.Priority = DMA_PRIORITY_LOW; + hdma_spi3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_spi3_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + instance.dma_handle = &hdma_spi3_tx; + instance.stream = Stream::DMA1Stream6; + instance.global_handle= &hdmatx; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; break; - } } - assert(false); //The DMA_STREAM that you want is not available; -} + + return; + } + static void start(); private: - inline static constinit std::array available_streams{true}; + inline static constinit uint8_t inscribed_index = 0; + inline static constinit std::array inscribed_streams{}; static constexpr std::array streams = { Stream::DMA1Stream0, Stream::DMA1Stream1, Stream::DMA1Stream2, Stream::DMA1Stream3, Stream::DMA1Stream4, Stream::DMA1Stream5, Stream::DMA1Stream6, diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index 40d114fe8..9d9732292 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -8,15 +8,19 @@ #include "HALAL/Models/DMA/DMA.hpp" #include "ErrorHandler/ErrorHandler.hpp" -void DMA::start() { - __HAL_RCC_DMA1_CLK_ENABLE(); - __HAL_RCC_DMA2_CLK_ENABLE(); - int i = 0; - for (bool dma_stream : available_streams) { - if (dma_stream) { - HAL_NVIC_SetPriority((IRQn_Type)streams[i], 0, 0); - HAL_NVIC_EnableIRQ((IRQn_Type)streams[i]); - } - i++; +void DMA::start() +{ + __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + for (auto const &inst : inscribed_streams) { + std::visit([&](auto const &instance) { + if (HAL_DMA_Init(instance.dma_handle) != HAL_OK) + { + Error_Handler(); + } + __HAL_LINKDMA(instance.handle, instance.global_handle, instance.dma_handle); + HAL_NVIC_SetPriority((IRQn_Type)instance.stream, 0, 0); + HAL_NVIC_EnableIRQ((IRQn_Type)instance.stream); + }, inst); } } From 1d158c05af6bd26cafec73fb328bf0836cd7120d Mon Sep 17 00:00:00 2001 From: Cantonplas Date: Thu, 23 Oct 2025 11:53:38 +0200 Subject: [PATCH 003/109] Minor change on where is the instance declared on dma.hpp --- Inc/HALAL/Models/DMA/DMA.hpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index ad2d445b1..8f113721e 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -18,6 +18,8 @@ // We only have 6 peripherals using DMA for now, the new ssd will need to be added later here + +//The problem here is that this handles are defined in runes.cpp, so maybe we should declare this here? Idk extern DMA_HandleTypeDef hdma_adc1; extern DMA_HandleTypeDef hdma_adc2; extern DMA_HandleTypeDef hdma_adc3; @@ -79,6 +81,7 @@ class DMA { template void static inline constexpr inscribe_stream(T* handle,Peripheral_type peripheral_type) { + Instance instance; static_assert(is_variant_member, MyInstanceVariant>::value, "Handle Type not allowed on DMA::inscribe_stream"); assert(handle != nullptr); @@ -89,7 +92,6 @@ class DMA { { case Peripheral_type::Adc1: static_assert(handle->Instance == ADC1, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc1"); - Instance instance; instance.handle = handle; hdma_adc1.Instance = DMA1_Stream0; hdma_adc1.Init.Request = DMA_REQUEST_ADC1; @@ -111,7 +113,6 @@ class DMA { case Peripheral_type::Adc2: static_assert(handle->Instance == ADC2, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc2"); - Instance instance; instance.handle = handle; hdma_adc2.Instance = DMA1_Stream1; hdma_adc2.Init.Request = DMA_REQUEST_ADC2; @@ -133,7 +134,6 @@ class DMA { case Peripheral_type::Adc3: static_assert(handle->Instance == ADC3, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc3"); - Instance instance; instance.handle = handle; hdma_adc3.Instance = DMA1_Stream2; hdma_adc3.Init.Request = DMA_REQUEST_ADC3; @@ -155,7 +155,6 @@ class DMA { case Peripheral_type::I2c2: static_assert(handle->Instance == I2C2, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::I2c2"); - Instance instance; instance.handle = handle; hdma_i2c2_rx.Instance = DMA1_Stream3; hdma_i2c2_rx.Init.Request = DMA_REQUEST_I2C2_RX; @@ -195,7 +194,6 @@ class DMA { case Peripheral_type::Fmac: static_assert(handle->Instance == FMAC, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Fmac"); - Instance instance; hdma_fmac_preload.Instance = DMA2_Stream0; hdma_fmac_preload.Init.Request = DMA_REQUEST_MEM2MEM; hdma_fmac_preload.Init.Direction = DMA_MEMORY_TO_MEMORY; @@ -249,7 +247,6 @@ class DMA { case Peripheral_type::Spi3: static_assert(handle->Instance == SPI3, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Spi3"); - Instance instance; hdma_spi3_rx.Instance = DMA1_Stream5; hdma_spi3_rx.Init.Request = DMA_REQUEST_SPI3_RX; hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; From ea78eb3e36e63e47b61ad06bfa69cb5e1e70af31 Mon Sep 17 00:00:00 2001 From: Jorge Date: Sat, 25 Oct 2025 10:10:24 +0200 Subject: [PATCH 004/109] limpieza de funciones, enums y structs --- Inc/HALAL/Models/DMA/DMA.hpp | 263 +---------------------------------- Src/HALAL/Models/DMA/DMA.cpp | 222 +++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+), 258 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 8f113721e..01e88a897 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -13,61 +13,20 @@ #include "HALAL/Models/MPUManager/MPUManager.hpp" #include #include -#define MAX_NUM_STREAMS 15 -#define DMA_USED 10 //Temporal name, i cant think of a better one +#define MAX_STREAMS 16 // We only have 6 peripherals using DMA for now, the new ssd will need to be added later here -//The problem here is that this handles are defined in runes.cpp, so maybe we should declare this here? Idk -extern DMA_HandleTypeDef hdma_adc1; -extern DMA_HandleTypeDef hdma_adc2; -extern DMA_HandleTypeDef hdma_adc3; - -extern DMA_HandleTypeDef hdma_i2c2_rx; -extern DMA_HandleTypeDef hdma_i2c2_tx; - -extern DMA_HandleTypeDef hdma_fmac_preload; -extern DMA_HandleTypeDef hdma_fmac_read; -extern DMA_HandleTypeDef hdma_fmac_write; - -extern DMA_HandleTypeDef hdma_spi3_rx; -extern DMA_HandleTypeDef hdma_spi3_tx; class DMA { public: - enum class Stream : uint8_t { - DMA1Stream0 = 11, - DMA1Stream1 = 12, - DMA1Stream2 = 13, - DMA1Stream3 = 14, - DMA1Stream4 = 15, - DMA1Stream5 = 16, - DMA1Stream6 = 17, - DMA2Stream0 = 56, - DMA2Stream1 = 57, - DMA2Stream2 = 58, - DMA2Stream3 = 59, - DMA2Stream4 = 60, - DMA2Stream5 = 68, - DMA2Stream6 = 69, - DMA2Stream7 = 70, - }; - - enum class Peripheral_type { - Adc1, - Adc2, - Adc3, - I2c2, - Fmac, - Spi3 - }; template struct Peripheral_type_instance { DMA_HandleTypeDef* dma_handle; DMA_HandleTypeDef* global_handle; T* handle; - Stream stream; + Stream stream; // Maybe dejar IRQn type? }; //To allow the array to be multiple types, idk first thing that came to mind @@ -79,224 +38,12 @@ class DMA { >; template - void static inline constexpr inscribe_stream(T* handle,Peripheral_type peripheral_type) - { - Instance instance; - static_assert(is_variant_member, MyInstanceVariant>::value, - "Handle Type not allowed on DMA::inscribe_stream"); - assert(handle != nullptr); - assert(inscribed_index < DMA_USED); - - - switch (peripheral_type) - { - case Peripheral_type::Adc1: - static_assert(handle->Instance == ADC1, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc1"); - instance.handle = handle; - hdma_adc1.Instance = DMA1_Stream0; - hdma_adc1.Init.Request = DMA_REQUEST_ADC1; - hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; - hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_adc1.Init.Mode = DMA_CIRCULAR; - hdma_adc1.Init.Priority = DMA_PRIORITY_LOW; - hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_adc1; - instance.stream = Stream::DMA1Stream0; - instance.global_handle= &DMA_Handle - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case Peripheral_type::Adc2: - static_assert(handle->Instance == ADC2, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc2"); - instance.handle = handle; - hdma_adc2.Instance = DMA1_Stream1; - hdma_adc2.Init.Request = DMA_REQUEST_ADC2; - hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_adc2.Init.MemInc = DMA_MINC_ENABLE; - hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_adc2.Init.Mode = DMA_CIRCULAR; - hdma_adc2.Init.Priority = DMA_PRIORITY_LOW; - hdma_adc2.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_adc2; - instance.stream = Stream::DMA1Stream1; - instance.global_handle= &DMA_Handle - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case Peripheral_type::Adc3: - static_assert(handle->Instance == ADC3, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc3"); - instance.handle = handle; - hdma_adc3.Instance = DMA1_Stream2; - hdma_adc3.Init.Request = DMA_REQUEST_ADC3; - hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_adc3.Init.MemInc = DMA_MINC_ENABLE; - hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_adc3.Init.Mode = DMA_CIRCULAR; - hdma_adc3.Init.Priority = DMA_PRIORITY_LOW; - hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_adc3; - instance.stream = Stream::DMA1Stream2; - instance.global_handle= &DMA_Handle - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case Peripheral_type::I2c2: - static_assert(handle->Instance == I2C2, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::I2c2"); - instance.handle = handle; - hdma_i2c2_rx.Instance = DMA1_Stream3; - hdma_i2c2_rx.Init.Request = DMA_REQUEST_I2C2_RX; - hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE; - hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - hdma_i2c2_rx.Init.Mode = DMA_CIRCULAR; - hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_LOW; - hdma_i2c2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_i2c2_rx; - instance.stream = Stream::DMA1Stream3; - instance.global_handle= &hdmarx; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_i2c2_tx.Instance = DMA1_Stream4; - hdma_i2c2_tx.Init.Request = DMA_REQUEST_I2C2_TX; - hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE; - hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - hdma_i2c2_tx.Init.Mode = DMA_CIRCULAR; - hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_LOW; - hdma_i2c2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_i2c2_tx; - instance.stream = Stream::DMA1Stream4; - instance.global_handle= &hdmatx; - - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case Peripheral_type::Fmac: - static_assert(handle->Instance == FMAC, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Fmac"); - hdma_fmac_preload.Instance = DMA2_Stream0; - hdma_fmac_preload.Init.Request = DMA_REQUEST_MEM2MEM; - hdma_fmac_preload.Init.Direction = DMA_MEMORY_TO_MEMORY; - hdma_fmac_preload.Init.PeriphInc = DMA_PINC_ENABLE; - hdma_fmac_preload.Init.MemInc = DMA_MINC_DISABLE; - hdma_fmac_preload.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_fmac_preload.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_fmac_preload.Init.Mode = DMA_NORMAL; - hdma_fmac_preload.Init.Priority = DMA_PRIORITY_HIGH; - instance.dma_handle = &hdma_fmac_preload; - instance.stream = Stream::DMA2Stream0; - instance.global_handle= &hdmaPreload; - - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_fmac_write.Instance = DMA2_Stream1; - hdma_fmac_write.Init.Request = DMA_REQUEST_FMAC_WRITE; - hdma_fmac_write.Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_fmac_write.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_fmac_write.Init.MemInc = DMA_MINC_ENABLE; - hdma_fmac_write.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_fmac_write.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_fmac_write.Init.Mode = DMA_NORMAL; - hdma_fmac_write.Init.Priority = DMA_PRIORITY_HIGH; - instance.dma_handle = &hdma_fmac_write; - instance.stream = Stream::DMA2Stream1; - instance.global_handle= &hdmaIn; - - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_fmac_read.Instance = DMA2_Stream2; - hdma_fmac_read.Init.Request = DMA_REQUEST_FMAC_READ; - hdma_fmac_read.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_fmac_read.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_fmac_read.Init.MemInc = DMA_MINC_ENABLE; - hdma_fmac_read.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_fmac_read.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_fmac_read.Init.Mode = DMA_NORMAL; - hdma_fmac_read.Init.Priority = DMA_PRIORITY_HIGH; - instance.dma_handle = &hdma_fmac_read; - instance.stream = Stream::DMA2Stream2; - instance.global_handle= &hdmaOut; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case Peripheral_type::Spi3: - static_assert(handle->Instance == SPI3, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Spi3"); - hdma_spi3_rx.Instance = DMA1_Stream5; - hdma_spi3_rx.Init.Request = DMA_REQUEST_SPI3_RX; - hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE; - hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - hdma_spi3_rx.Init.Mode = DMA_NORMAL; - hdma_spi3_rx.Init.Priority = DMA_PRIORITY_LOW; - hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - hdma_spi3_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - instance.dma_handle = &hdma_spi3_rx; - instance.stream = Stream::DMA1Stream5; - instance.global_handle= &hdmarx; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_spi3_tx.Instance = DMA1_Stream6; - hdma_spi3_tx.Init.Request = DMA_REQUEST_SPI3_TX; - hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_spi3_tx.Init.MemInc = DMA_MINC_ENABLE; - hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - hdma_spi3_tx.Init.Mode = DMA_NORMAL; - hdma_spi3_tx.Init.Priority = DMA_PRIORITY_LOW; - hdma_spi3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - hdma_spi3_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - instance.dma_handle = &hdma_spi3_tx; - instance.stream = Stream::DMA1Stream6; - instance.global_handle= &hdmatx; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - } - - return; - } + void static inline constexpr inscribe_stream(T* handle); static void start(); private: inline static constinit uint8_t inscribed_index = 0; - inline static constinit std::array inscribed_streams{}; - static constexpr std::array streams = { - Stream::DMA1Stream0, Stream::DMA1Stream1, Stream::DMA1Stream2, Stream::DMA1Stream3, - Stream::DMA1Stream4, Stream::DMA1Stream5, Stream::DMA1Stream6, - Stream::DMA2Stream0, Stream::DMA2Stream1, Stream::DMA2Stream2, Stream::DMA2Stream3, - Stream::DMA2Stream4, Stream::DMA2Stream5, Stream::DMA2Stream6, Stream::DMA2Stream7 - }; + inline static constinit std::array inscribed_streams{}; + }; \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index 9d9732292..8eb8dae20 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -8,6 +8,228 @@ #include "HALAL/Models/DMA/DMA.hpp" #include "ErrorHandler/ErrorHandler.hpp" + +template +constexpr void DMA::inscribe_stream(T* handle, DMA_Stream_TypeDef* stream) +{ + Peripheral_type_instance instance{}; + // Verificar que los tipos pasados sean correctos y que aun hay streams sin usar + + // Atributos comunes + + // Atributos propios + + +} + + +template +constexpr void DMA::inscribe_stream(T* handle) + { + Peripheral_type_instance instance{}; + assert(handle != nullptr); + assert(inscribed_index < DMA_USED); + + switch (handle->Instance) + { + case ADC1_BASE: + instance.handle = handle; + hdma_adc1.Instance = DMA1_Stream0; + hdma_adc1.Init.Request = DMA_REQUEST_ADC1; + hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; + hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_adc1.Init.Mode = DMA_CIRCULAR; + hdma_adc1.Init.Priority = DMA_PRIORITY_LOW; + hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_adc1; + instance.stream = Stream::DMA1Stream0; + instance.global_handle= &DMA_Handle + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case ADC2_BASE: + instance.handle = handle; + hdma_adc2.Instance = DMA1_Stream1; + hdma_adc2.Init.Request = DMA_REQUEST_ADC2; + hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_adc2.Init.MemInc = DMA_MINC_ENABLE; + hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_adc2.Init.Mode = DMA_CIRCULAR; + hdma_adc2.Init.Priority = DMA_PRIORITY_LOW; + hdma_adc2.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_adc2; + instance.stream = Stream::DMA1Stream1; + instance.global_handle= &DMA_Handle + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case ADC3_BASE: + instance.handle = handle; + hdma_adc3.Instance = DMA1_Stream2; + hdma_adc3.Init.Request = DMA_REQUEST_ADC3; + hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_adc3.Init.MemInc = DMA_MINC_ENABLE; + hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_adc3.Init.Mode = DMA_CIRCULAR; + hdma_adc3.Init.Priority = DMA_PRIORITY_LOW; + hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_adc3; + instance.stream = DMA1Stream2; + instance.global_handle= &DMA_Handle; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case I2C2_BASE: + instance.handle = handle; + hdma_i2c2_rx.Instance = DMA1_Stream3; + hdma_i2c2_rx.Init.Request = DMA_REQUEST_I2C2_RX; + hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_i2c2_rx.Init.Mode = DMA_CIRCULAR; + hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_i2c2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_i2c2_rx; + instance.stream = Stream::DMA1Stream3; + instance.global_handle= &hdmarx; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_i2c2_tx.Instance = DMA1_Stream4; + hdma_i2c2_tx.Init.Request = DMA_REQUEST_I2C2_TX; + hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_i2c2_tx.Init.Mode = DMA_CIRCULAR; + hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_LOW; + hdma_i2c2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_i2c2_tx; + instance.stream = Stream::DMA1Stream4; + instance.global_handle= &hdmatx; + + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case FMAC_BASE: + hdma_fmac_preload.Instance = DMA2_Stream0; + hdma_fmac_preload.Init.Request = DMA_REQUEST_MEM2MEM; + hdma_fmac_preload.Init.Direction = DMA_MEMORY_TO_MEMORY; + hdma_fmac_preload.Init.PeriphInc = DMA_PINC_ENABLE; + hdma_fmac_preload.Init.MemInc = DMA_MINC_DISABLE; + hdma_fmac_preload.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_fmac_preload.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_fmac_preload.Init.Mode = DMA_NORMAL; + hdma_fmac_preload.Init.Priority = DMA_PRIORITY_HIGH; + instance.dma_handle = &hdma_fmac_preload; + instance.stream = Stream::DMA2Stream0; + instance.global_handle= &hdmaPreload; + + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_fmac_write.Instance = DMA2_Stream1; + hdma_fmac_write.Init.Request = DMA_REQUEST_FMAC_WRITE; + hdma_fmac_write.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_fmac_write.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_fmac_write.Init.MemInc = DMA_MINC_ENABLE; + hdma_fmac_write.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_fmac_write.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_fmac_write.Init.Mode = DMA_NORMAL; + hdma_fmac_write.Init.Priority = DMA_PRIORITY_HIGH; + instance.dma_handle = &hdma_fmac_write; + instance.stream = Stream::DMA2Stream1; + instance.global_handle= &hdmaIn; + + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_fmac_read.Instance = DMA2_Stream2; + hdma_fmac_read.Init.Request = DMA_REQUEST_FMAC_READ; + hdma_fmac_read.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_fmac_read.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_fmac_read.Init.MemInc = DMA_MINC_ENABLE; + hdma_fmac_read.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_fmac_read.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_fmac_read.Init.Mode = DMA_NORMAL; + hdma_fmac_read.Init.Priority = DMA_PRIORITY_HIGH; + instance.dma_handle = &hdma_fmac_read; + instance.stream = Stream::DMA2Stream2; + instance.global_handle= &hdmaOut; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case SPI3_BASE: + hdma_spi3_rx.Instance = DMA1_Stream5; + hdma_spi3_rx.Init.Request = DMA_REQUEST_SPI3_RX; + hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_spi3_rx.Init.Mode = DMA_NORMAL; + hdma_spi3_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_spi3_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + instance.dma_handle = &hdma_spi3_rx; + instance.stream = Stream::DMA1Stream5; + instance.global_handle= &hdmarx; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_spi3_tx.Instance = DMA1_Stream6; + hdma_spi3_tx.Init.Request = DMA_REQUEST_SPI3_TX; + hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi3_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_spi3_tx.Init.Mode = DMA_NORMAL; + hdma_spi3_tx.Init.Priority = DMA_PRIORITY_LOW; + hdma_spi3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_spi3_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + instance.dma_handle = &hdma_spi3_tx; + instance.stream = Stream::DMA1Stream6; + instance.global_handle= &hdmatx; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + default: + // Aqui poner que diga que el handle esta mal o algo + ErrorHandler(); + break; + } + + return; + } + + void DMA::start() { __HAL_RCC_DMA1_CLK_ENABLE(); From b8df87e2135000eea28c60799d8001a99cb576c4 Mon Sep 17 00:00:00 2001 From: Jorge Date: Sat, 25 Oct 2025 23:29:30 +0200 Subject: [PATCH 005/109] feat: distintos inscribe definidos, no creo que sea lo mejor que se puede hacer --- Inc/HALAL/Models/DMA/DMA.hpp | 27 ++-- Src/HALAL/Models/DMA/DMA.cpp | 245 +++++++++++++++++++++++++++++++++-- 2 files changed, 252 insertions(+), 20 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 01e88a897..42f70c7f4 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -14,21 +14,18 @@ #include #include #define MAX_STREAMS 16 - - -// We only have 6 peripherals using DMA for now, the new ssd will need to be added later here - +#define STREAMS_USED 10 class DMA { public: template struct Peripheral_type_instance { + T* handle; DMA_HandleTypeDef* dma_handle; DMA_HandleTypeDef* global_handle; - T* handle; - Stream stream; // Maybe dejar IRQn type? - + IRQn_Type irqn; }; + //To allow the array to be multiple types, idk first thing that came to mind using InstanceList = std::variant< Peripheral_type_instance, @@ -37,13 +34,23 @@ class DMA { Peripheral_type_instance >; - template - void static inline constexpr inscribe_stream(T* handle); + constexpr void inscribe_stream_adc(ADC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream); + + constexpr void inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); + + constexpr void inscribe_stream_spi(SPI_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); + + constexpr void inscribe_stream_fmac(FMAC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_preload, DMA_Stream_TypeDef* stream_read, DMA_Stream_TypeDef* stream_write); + + + + constexpr uint32_t get_dma_request(const void* instance, const bool mode); + + constexpr IRQn_Type get_irqn(const DMA_Stream_TypeDef* stream); static void start(); private: inline static constinit uint8_t inscribed_index = 0; inline static constinit std::array inscribed_streams{}; - }; \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index 8eb8dae20..245e54259 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -9,17 +9,242 @@ #include "ErrorHandler/ErrorHandler.hpp" -template -constexpr void DMA::inscribe_stream(T* handle, DMA_Stream_TypeDef* stream) +constexpr uint32_t DMA::get_dma_request(const void* instance, const bool mode) { + if (instance == ADC1) return DMA_REQUEST_ADC1; + if (instance == ADC2) return DMA_REQUEST_ADC2; + if (instance == ADC3) return DMA_REQUEST_ADC3; + + if (instance == I2C1 && mode) return DMA_REQUEST_I2C1_RX; + if (instance == I2C1 && !mode) return DMA_REQUEST_I2C1_TX; + if (instance == I2C2 && mode) return DMA_REQUEST_I2C2_RX; + if (instance == I2C2 && !mode) return DMA_REQUEST_I2C2_TX; + if (instance == I2C3 && mode) return DMA_REQUEST_I2C3_RX; + if (instance == I2C3 && !mode) return DMA_REQUEST_I2C3_TX; + if (instance == I2C5 && mode) return DMA_REQUEST_I2C5_RX; // NO hay 4? + if (instance == I2C5 && !mode) return DMA_REQUEST_I2C5_TX; + + if (instance == SPI1 && mode) return DMA_REQUEST_SPI1_RX; + if (instance == SPI1 && !mode) return DMA_REQUEST_SPI1_TX; + if (instance == SPI2 && mode) return DMA_REQUEST_SPI2_RX; + if (instance == SPI2 && !mode) return DMA_REQUEST_SPI2_TX; + if (instance == SPI3 && mode) return DMA_REQUEST_SPI3_RX; + if (instance == SPI3 && !mode) return DMA_REQUEST_SPI3_TX; + if (instance == SPI4 && mode) return DMA_REQUEST_SPI4_RX; + if (instance == SPI4 && !mode) return DMA_REQUEST_SPI4_TX; + if (instance == SPI5 && mode) return DMA_REQUEST_SPI5_RX; + if (instance == SPI5 && !mode) return DMA_REQUEST_SPI5_TX; // NO hay 6? + + return 0; +} + + +constexpr IRQn_Type DMA::get_irqn(const DMA_Stream_TypeDef* stream) { + if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; + if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; + if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; + if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; + if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; + if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; + if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; + if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; + + if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; + if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; + if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; + if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; + if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; + if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; + if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; + if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; +} + + + +constexpr void DMA::inscribe_stream_adc(ADC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream) { - Peripheral_type_instance instance{}; - // Verificar que los tipos pasados sean correctos y que aun hay streams sin usar + Peripheral_type_instance instance{}; + static DMA_HandleTypeDef dma_handle; + + instance.handle = handle; + dma_handle.Instance = stream; + dma_handle.Init.Request = get_dma_request(handle->Instance, true); // El modo no hace nada aquí + dma_handle.Init.Direction = DMA_PERIPH_TO_MEMORY; + dma_handle.Init.PeriphInc = DMA_PINC_DISABLE; + dma_handle.Init.MemInc = DMA_MINC_ENABLE; + dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + dma_handle.Init.Mode = DMA_CIRCULAR; + dma_handle.Init.Priority = DMA_PRIORITY_LOW; + dma_handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.global_handle = handle->DMA_Handle; + instance.irqn = get_irqn(stream); + instance.dma_handle = &dma_handle; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; +} - // Atributos comunes - // Atributos propios +constexpr void DMA::inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx) +{ + // RX Stream + Peripheral_type_instance instance_rx{}; + static DMA_HandleTypeDef dma_handle_rx; + + instance_rx.handle = handle; + dma_handle_rx.Instance = stream_rx; + dma_handle_rx.Init.Request = get_dma_request(handle->Instance, true); + dma_handle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + dma_handle_rx.Init.PeriphInc = DMA_PINC_DISABLE; + dma_handle_rx.Init.MemInc = DMA_MINC_ENABLE; + dma_handle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + dma_handle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + dma_handle_rx.Init.Mode = DMA_CIRCULAR; + dma_handle_rx.Init.Priority = DMA_PRIORITY_LOW; + dma_handle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance_rx.dma_handle = &dma_handle_rx; + instance_rx.global_handle = handle->hdmarx; + instance_rx.irqn = get_irqn(stream_rx); + + inscribed_streams[inscribed_index] = instance_rx; + inscribed_index++; + + // TX Stream + Peripheral_type_instance instance_tx{}; + static DMA_HandleTypeDef dma_handle_tx; + + instance_tx.handle = handle; + dma_handle_tx.Instance = stream_tx; + dma_handle_rx.Init.Request = get_dma_request(handle->Instance, false); + dma_handle_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + dma_handle_tx.Init.PeriphInc = DMA_PINC_DISABLE; + dma_handle_tx.Init.MemInc = DMA_MINC_ENABLE; + dma_handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + dma_handle_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + dma_handle_tx.Init.Mode = DMA_CIRCULAR; + dma_handle_tx.Init.Priority = DMA_PRIORITY_LOW; + dma_handle_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance_tx.dma_handle = &dma_handle_tx; + instance_tx.global_handle = handle->hdmatx; + instance_tx.irqn = get_irqn(stream_tx); + + inscribed_streams[inscribed_index] = instance_tx; + inscribed_index++; +} + +constexpr void DMA::inscribe_stream_spi(SPI_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx) +{ + // RX Stream + Peripheral_type_instance instance_rx{}; + static DMA_HandleTypeDef dma_handle_rx; + + instance_rx.handle = handle; + dma_handle_rx.Instance = stream_rx; + dma_handle_rx.Init.Request = get_dma_request(handle->Instance, true); + dma_handle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + dma_handle_rx.Init.PeriphInc = DMA_PINC_DISABLE; + dma_handle_rx.Init.MemInc = DMA_MINC_ENABLE; + dma_handle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + dma_handle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + dma_handle_rx.Init.Mode = DMA_NORMAL; + dma_handle_rx.Init.Priority = DMA_PRIORITY_LOW; + dma_handle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + dma_handle_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + instance_rx.dma_handle = &dma_handle_rx; + instance_rx.global_handle = handle->hdmarx; + instance_rx.irqn = get_irqn(stream_rx); + + inscribed_streams[inscribed_index] = instance_rx; + inscribed_index++; + + // TX Stream + Peripheral_type_instance instance_tx{}; + static DMA_HandleTypeDef dma_handle_tx; + instance_tx.handle = handle; + dma_handle_tx.Instance = stream_tx; + dma_handle_tx.Init.Request = get_dma_request(handle->Instance, false); + dma_handle_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + dma_handle_tx.Init.PeriphInc = DMA_PINC_DISABLE; + dma_handle_tx.Init.MemInc = DMA_MINC_ENABLE; + dma_handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + dma_handle_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + dma_handle_tx.Init.Mode = DMA_NORMAL; + dma_handle_tx.Init.Priority = DMA_PRIORITY_LOW; + dma_handle_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + dma_handle_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + instance_tx.dma_handle = &dma_handle_tx; + instance_tx.global_handle = handle->hdmatx; + instance_tx.irqn = get_irqn(stream_tx); + + inscribed_streams[inscribed_index] = instance_tx; + inscribed_index++; +} + + +constexpr void DMA::inscribe_stream_fmac(FMAC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_preload, DMA_Stream_TypeDef* stream_read, DMA_Stream_TypeDef* stream_write) +{ + Peripheral_type_instance instance_preload{}; + static DMA_HandleTypeDef dma_handle_preload; + + instance_preload.handle = handle; + dma_handle_preload.Instance = stream_preload; + dma_handle_preload.Init.Request = DMA_REQUEST_MEM2MEM; + dma_handle_preload.Init.Direction = DMA_MEMORY_TO_MEMORY; + dma_handle_preload.Init.PeriphInc = DMA_PINC_ENABLE; + dma_handle_preload.Init.MemInc = DMA_MINC_DISABLE; + dma_handle_preload.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + dma_handle_preload.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + dma_handle_preload.Init.Mode = DMA_NORMAL; + dma_handle_preload.Init.Priority = DMA_PRIORITY_HIGH; + instance_preload.dma_handle = &dma_handle_preload; + instance_preload.global_handle = handle->hdmaPreload; + instance_preload.irqn = get_irqn(stream_preload); + + inscribed_streams[inscribed_index] = instance_preload; + inscribed_index++; + + Peripheral_type_instance instance_write{}; + static DMA_HandleTypeDef dma_handle_write; + + instance_write.handle = handle; + dma_handle_write.Instance = stream_write; + dma_handle_write.Init.Request = DMA_REQUEST_FMAC_WRITE; + dma_handle_write.Init.Direction = DMA_MEMORY_TO_PERIPH; + dma_handle_write.Init.PeriphInc = DMA_PINC_DISABLE; + dma_handle_write.Init.MemInc = DMA_MINC_ENABLE; + dma_handle_write.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + dma_handle_write.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + dma_handle_write.Init.Mode = DMA_NORMAL; + dma_handle_write.Init.Priority = DMA_PRIORITY_HIGH; + instance_write.dma_handle = &dma_handle_write; + instance_write.global_handle = handle->hdmaIn; + instance_write.irqn = get_irqn(stream_write); + + inscribed_streams[inscribed_index] = instance_write; + inscribed_index++; + + + Peripheral_type_instance instance_read{}; + static DMA_HandleTypeDef dma_handle_read; + + instance_read.handle = handle; + dma_handle_read.Instance = stream_read; + dma_handle_read.Init.Request = DMA_REQUEST_FMAC_READ; + dma_handle_read.Init.Direction = DMA_PERIPH_TO_MEMORY; + dma_handle_read.Init.PeriphInc = DMA_PINC_DISABLE; + dma_handle_read.Init.MemInc = DMA_MINC_ENABLE; + dma_handle_read.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + dma_handle_read.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + dma_handle_read.Init.Mode = DMA_NORMAL; + dma_handle_read.Init.Priority = DMA_PRIORITY_HIGH; + instance_read.dma_handle = &dma_handle_read; + instance_read.global_handle = handle->hdmaOut; + instance_read.irqn = get_irqn(stream_read); + + inscribed_streams[inscribed_index] = instance_read; + inscribed_index++; } @@ -29,11 +254,11 @@ constexpr void DMA::inscribe_stream(T* handle) Peripheral_type_instance instance{}; assert(handle != nullptr); assert(inscribed_index < DMA_USED); - + handle->DMA_Handle switch (handle->Instance) { case ADC1_BASE: - instance.handle = handle; + hdma_adc1.Instance = DMA1_Stream0; hdma_adc1.Init.Request = DMA_REQUEST_ADC1; hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; @@ -241,8 +466,8 @@ void DMA::start() Error_Handler(); } __HAL_LINKDMA(instance.handle, instance.global_handle, instance.dma_handle); - HAL_NVIC_SetPriority((IRQn_Type)instance.stream, 0, 0); - HAL_NVIC_EnableIRQ((IRQn_Type)instance.stream); + HAL_NVIC_SetPriority(instance.irqn, 0, 0); + HAL_NVIC_EnableIRQ(instance.irqn); }, inst); } } From 85db060c390199b3f23f430ec86632f356af6ef9 Mon Sep 17 00:00:00 2001 From: Jorge Date: Sun, 26 Oct 2025 22:11:22 +0100 Subject: [PATCH 006/109] feat: mejor enfoque, pero no se si el correcto --- Inc/HALAL/Models/DMA/DMA.hpp | 18 +- Inc/HALAL/Services/ADC/ADC.hpp | 3 +- Inc/HALAL/Services/Communication/I2C/I2C.hpp | 2 - Inc/HALAL/Services/Communication/SPI/SPI.hpp | 3 +- Inc/HALAL/Services/FMAC/FMAC.hpp | 4 - Src/HALAL/Models/DMA/DMA.cpp | 246 +++---------------- Src/HALAL/Services/ADC/ADC.cpp | 4 +- Src/HALAL/Services/Communication/I2C/I2C.cpp | 3 +- Src/HALAL/Services/Communication/SPI/SPI.cpp | 3 +- Src/HALAL/Services/FMAC/FMAC.cpp | 4 +- 10 files changed, 53 insertions(+), 237 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 42f70c7f4..ddf9f6245 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -34,23 +34,27 @@ class DMA { Peripheral_type_instance >; - constexpr void inscribe_stream_adc(ADC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream); + static constexpr void inscribe_stream_adc(ADC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream); - constexpr void inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); + static constexpr void inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); - constexpr void inscribe_stream_spi(SPI_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); + static constexpr void inscribe_stream_spi(SPI_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); - constexpr void inscribe_stream_fmac(FMAC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_preload, DMA_Stream_TypeDef* stream_read, DMA_Stream_TypeDef* stream_write); + static constexpr void inscribe_stream_fmac(FMAC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_preload, DMA_Stream_TypeDef* stream_read, DMA_Stream_TypeDef* stream_write); - - constexpr uint32_t get_dma_request(const void* instance, const bool mode); + template + constexpr void inscribe_stream(T* handle, Streams*... streams); - constexpr IRQn_Type get_irqn(const DMA_Stream_TypeDef* stream); + + static constexpr uint32_t get_dma_request(const void* instance, const bool mode); + + static constexpr IRQn_Type get_irqn(const DMA_Stream_TypeDef* stream); static void start(); private: inline static constinit uint8_t inscribed_index = 0; inline static constinit std::array inscribed_streams{}; + inline static DMA_HandleTypeDef dma_handles[MAX_STREAMS]; }; \ No newline at end of file diff --git a/Inc/HALAL/Services/ADC/ADC.hpp b/Inc/HALAL/Services/ADC/ADC.hpp index 633dba883..2c17d0a16 100644 --- a/Inc/HALAL/Services/ADC/ADC.hpp +++ b/Inc/HALAL/Services/ADC/ADC.hpp @@ -42,11 +42,10 @@ class ADC { uint32_t resolution; uint32_t external_trigger; vector channels; - DMA::Stream dma_stream; string name; InitData() = default; - InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, DMA::Stream dma_stream, string name); + InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, string name); }; class Peripheral { diff --git a/Inc/HALAL/Services/Communication/I2C/I2C.hpp b/Inc/HALAL/Services/Communication/I2C/I2C.hpp index 53c57388a..16f2adb23 100644 --- a/Inc/HALAL/Services/Communication/I2C/I2C.hpp +++ b/Inc/HALAL/Services/Communication/I2C/I2C.hpp @@ -33,8 +33,6 @@ class I2C { Pin &SDA; I2C_HandleTypeDef *hi2c; I2C_TypeDef *instance; - DMA::Stream RX_DMA; - DMA::Stream TX_DMA; uint8_t address = 0; uint32_t speed_frequency_kHz = 100; uint32_t data_length_in_bits = 8; diff --git a/Inc/HALAL/Services/Communication/SPI/SPI.hpp b/Inc/HALAL/Services/Communication/SPI/SPI.hpp index 99000a78f..ad3af9a79 100644 --- a/Inc/HALAL/Services/Communication/SPI/SPI.hpp +++ b/Inc/HALAL/Services/Communication/SPI/SPI.hpp @@ -55,8 +55,7 @@ class SPI{ SPI_HandleTypeDef* hspi; /**< HAL spi struct pin. */ SPI_TypeDef* instance; /**< HAL spi instance. */ - DMA::Stream hdma_tx; /**< HAL DMA handler for writting */ - DMA::Stream hdma_rx; /**< HAL DMA handler for reading */ + uint32_t baud_rate_prescaler; /**< SPI baud prescaler.*/ uint32_t mode = SPI_MODE_MASTER; /**< SPI mode. */ diff --git a/Inc/HALAL/Services/FMAC/FMAC.hpp b/Inc/HALAL/Services/FMAC/FMAC.hpp index 9348dd94c..65ad277f2 100644 --- a/Inc/HALAL/Services/FMAC/FMAC.hpp +++ b/Inc/HALAL/Services/FMAC/FMAC.hpp @@ -58,10 +58,6 @@ class MultiplierAccelerator{ struct FMACInstance{ FMACmodes mode; FMAC_HandleTypeDef *hfmac; - DMA::Stream dma_preload; - DMA::Stream dma_read; - DMA::Stream dma_write; - }; static FMACInstance Instance; diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index 245e54259..42f117940 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -63,7 +63,6 @@ constexpr IRQn_Type DMA::get_irqn(const DMA_Stream_TypeDef* stream) { constexpr void DMA::inscribe_stream_adc(ADC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream) { Peripheral_type_instance instance{}; - static DMA_HandleTypeDef dma_handle; instance.handle = handle; dma_handle.Instance = stream; @@ -89,7 +88,7 @@ constexpr void DMA::inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_Ty { // RX Stream Peripheral_type_instance instance_rx{}; - static DMA_HandleTypeDef dma_handle_rx; + instance_rx.handle = handle; dma_handle_rx.Instance = stream_rx; @@ -111,7 +110,7 @@ constexpr void DMA::inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_Ty // TX Stream Peripheral_type_instance instance_tx{}; - static DMA_HandleTypeDef dma_handle_tx; + instance_tx.handle = handle; dma_handle_tx.Instance = stream_tx; @@ -248,213 +247,6 @@ constexpr void DMA::inscribe_stream_fmac(FMAC_HandleTypeDef* handle, DMA_Stream_ } -template -constexpr void DMA::inscribe_stream(T* handle) - { - Peripheral_type_instance instance{}; - assert(handle != nullptr); - assert(inscribed_index < DMA_USED); - handle->DMA_Handle - switch (handle->Instance) - { - case ADC1_BASE: - - hdma_adc1.Instance = DMA1_Stream0; - hdma_adc1.Init.Request = DMA_REQUEST_ADC1; - hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; - hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_adc1.Init.Mode = DMA_CIRCULAR; - hdma_adc1.Init.Priority = DMA_PRIORITY_LOW; - hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_adc1; - instance.stream = Stream::DMA1Stream0; - instance.global_handle= &DMA_Handle - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case ADC2_BASE: - instance.handle = handle; - hdma_adc2.Instance = DMA1_Stream1; - hdma_adc2.Init.Request = DMA_REQUEST_ADC2; - hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_adc2.Init.MemInc = DMA_MINC_ENABLE; - hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_adc2.Init.Mode = DMA_CIRCULAR; - hdma_adc2.Init.Priority = DMA_PRIORITY_LOW; - hdma_adc2.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_adc2; - instance.stream = Stream::DMA1Stream1; - instance.global_handle= &DMA_Handle - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case ADC3_BASE: - instance.handle = handle; - hdma_adc3.Instance = DMA1_Stream2; - hdma_adc3.Init.Request = DMA_REQUEST_ADC3; - hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_adc3.Init.MemInc = DMA_MINC_ENABLE; - hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_adc3.Init.Mode = DMA_CIRCULAR; - hdma_adc3.Init.Priority = DMA_PRIORITY_LOW; - hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_adc3; - instance.stream = DMA1Stream2; - instance.global_handle= &DMA_Handle; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case I2C2_BASE: - instance.handle = handle; - hdma_i2c2_rx.Instance = DMA1_Stream3; - hdma_i2c2_rx.Init.Request = DMA_REQUEST_I2C2_RX; - hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE; - hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - hdma_i2c2_rx.Init.Mode = DMA_CIRCULAR; - hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_LOW; - hdma_i2c2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_i2c2_rx; - instance.stream = Stream::DMA1Stream3; - instance.global_handle= &hdmarx; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_i2c2_tx.Instance = DMA1_Stream4; - hdma_i2c2_tx.Init.Request = DMA_REQUEST_I2C2_TX; - hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE; - hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - hdma_i2c2_tx.Init.Mode = DMA_CIRCULAR; - hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_LOW; - hdma_i2c2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_i2c2_tx; - instance.stream = Stream::DMA1Stream4; - instance.global_handle= &hdmatx; - - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case FMAC_BASE: - hdma_fmac_preload.Instance = DMA2_Stream0; - hdma_fmac_preload.Init.Request = DMA_REQUEST_MEM2MEM; - hdma_fmac_preload.Init.Direction = DMA_MEMORY_TO_MEMORY; - hdma_fmac_preload.Init.PeriphInc = DMA_PINC_ENABLE; - hdma_fmac_preload.Init.MemInc = DMA_MINC_DISABLE; - hdma_fmac_preload.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_fmac_preload.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_fmac_preload.Init.Mode = DMA_NORMAL; - hdma_fmac_preload.Init.Priority = DMA_PRIORITY_HIGH; - instance.dma_handle = &hdma_fmac_preload; - instance.stream = Stream::DMA2Stream0; - instance.global_handle= &hdmaPreload; - - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_fmac_write.Instance = DMA2_Stream1; - hdma_fmac_write.Init.Request = DMA_REQUEST_FMAC_WRITE; - hdma_fmac_write.Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_fmac_write.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_fmac_write.Init.MemInc = DMA_MINC_ENABLE; - hdma_fmac_write.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_fmac_write.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_fmac_write.Init.Mode = DMA_NORMAL; - hdma_fmac_write.Init.Priority = DMA_PRIORITY_HIGH; - instance.dma_handle = &hdma_fmac_write; - instance.stream = Stream::DMA2Stream1; - instance.global_handle= &hdmaIn; - - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_fmac_read.Instance = DMA2_Stream2; - hdma_fmac_read.Init.Request = DMA_REQUEST_FMAC_READ; - hdma_fmac_read.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_fmac_read.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_fmac_read.Init.MemInc = DMA_MINC_ENABLE; - hdma_fmac_read.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_fmac_read.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_fmac_read.Init.Mode = DMA_NORMAL; - hdma_fmac_read.Init.Priority = DMA_PRIORITY_HIGH; - instance.dma_handle = &hdma_fmac_read; - instance.stream = Stream::DMA2Stream2; - instance.global_handle= &hdmaOut; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case SPI3_BASE: - hdma_spi3_rx.Instance = DMA1_Stream5; - hdma_spi3_rx.Init.Request = DMA_REQUEST_SPI3_RX; - hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE; - hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - hdma_spi3_rx.Init.Mode = DMA_NORMAL; - hdma_spi3_rx.Init.Priority = DMA_PRIORITY_LOW; - hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - hdma_spi3_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - instance.dma_handle = &hdma_spi3_rx; - instance.stream = Stream::DMA1Stream5; - instance.global_handle= &hdmarx; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_spi3_tx.Instance = DMA1_Stream6; - hdma_spi3_tx.Init.Request = DMA_REQUEST_SPI3_TX; - hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_spi3_tx.Init.MemInc = DMA_MINC_ENABLE; - hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - hdma_spi3_tx.Init.Mode = DMA_NORMAL; - hdma_spi3_tx.Init.Priority = DMA_PRIORITY_LOW; - hdma_spi3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - hdma_spi3_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - instance.dma_handle = &hdma_spi3_tx; - instance.stream = Stream::DMA1Stream6; - instance.global_handle= &hdmatx; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - default: - // Aqui poner que diga que el handle esta mal o algo - ErrorHandler(); - break; - } - - return; - } - - void DMA::start() { __HAL_RCC_DMA1_CLK_ENABLE(); @@ -465,9 +257,41 @@ void DMA::start() { Error_Handler(); } - __HAL_LINKDMA(instance.handle, instance.global_handle, instance.dma_handle); + __HAL_LINKDMA(instance->handle, instance.global_handle, instance->dma_handle); HAL_NVIC_SetPriority(instance.irqn, 0, 0); HAL_NVIC_EnableIRQ(instance.irqn); }, inst); } } + + +template +constexpr void DMA::inscribe_stream(T* handle, Streams*... streams){ + if constexpr (sizeof...(Streams) > MAX_STREAMS){ + ErrorHandler("The maximum number of streams is %d", MAX_STREAMS); + } + uint8_t num_streams = sizeof...(Streams); + + // Verify that the number of streams is correct for different peripherials + if constexpr (std::is_same && num_streams != 1){ + ErrorHandler("For ADC, there must be only one stream"); + } + else if constexpr (std::is_same && num_streams != 2){ + ErrorHandler("For SPI, there must be two streams (RX and TX)"); + } + else if constexpr (std::is_same && num_streams != 2){ + ErrorHandler("For I2C, there must be two streams (RX and TX)"); + } + else if constexpr (std::is_same && num_streams != 3){ + ErrorHandler("For FMAC, there must be three streams (preload, write and read)"); + } + + + Peripheral_type_instance instances[num_streams]; + + // All of the instances of the same peripherial will have the same handle + for constexpr (uint8_t num : num_streams){ + instances[num].handle = handle; + } + +} diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index d63e3b920..2717f2c7d 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -16,8 +16,8 @@ uint8_t ADC::id_counter = 0; unordered_map ADC::active_instances = {}; -ADC::InitData::InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, DMA::Stream dma_stream, string name) : - adc(adc), resolution(resolution), external_trigger(external_trigger), channels(channels), dma_stream(dma_stream), name(name) {} +ADC::InitData::InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, string name) : + adc(adc), resolution(resolution), external_trigger(external_trigger), channels(channels), name(name) {} ADC::Peripheral::Peripheral(ADC_HandleTypeDef* handle, LowPowerTimer& timer, InitData& init_data) : handle(handle), timer(timer), init_data(init_data) { diff --git a/Src/HALAL/Services/Communication/I2C/I2C.cpp b/Src/HALAL/Services/Communication/I2C/I2C.cpp index 61655d304..6ba12da50 100644 --- a/Src/HALAL/Services/Communication/I2C/I2C.cpp +++ b/Src/HALAL/Services/Communication/I2C/I2C.cpp @@ -23,8 +23,7 @@ uint8_t I2C::inscribe(I2C::Peripheral &i2c, uint8_t address) { Pin::inscribe(i2c_instance->SCL, ALTERNATIVE); Pin::inscribe(i2c_instance->SDA, ALTERNATIVE); - DMA::inscribe_stream(i2c_instance->RX_DMA); - DMA::inscribe_stream(i2c_instance->TX_DMA); + DMA::inscribe_stream_i2c(i2c_instance->hi2c, DMA1_Stream3, DMA1_Stream4); uint8_t id = I2C::id_counter++; diff --git a/Src/HALAL/Services/Communication/SPI/SPI.cpp b/Src/HALAL/Services/Communication/SPI/SPI.cpp index 9b498b12b..5d5eb9058 100644 --- a/Src/HALAL/Services/Communication/SPI/SPI.cpp +++ b/Src/HALAL/Services/Communication/SPI/SPI.cpp @@ -56,8 +56,7 @@ uint8_t SPI::inscribe(SPI::Peripheral& spi) { uint8_t id = SPI::id_counter++; if (spi_instance->use_DMA) { - DMA::inscribe_stream(spi_instance->hdma_rx); - DMA::inscribe_stream(spi_instance->hdma_tx); + DMA::inscribe_stream_spi(spi_instance->hspi, DMA1_Stream5, DMA1_Stream6); } SPI::registered_spi[id] = spi_instance; SPI::registered_spi_by_handler[spi_instance->hspi] = spi_instance; diff --git a/Src/HALAL/Services/FMAC/FMAC.cpp b/Src/HALAL/Services/FMAC/FMAC.cpp index 6b07bb19f..4b2107cab 100644 --- a/Src/HALAL/Services/FMAC/FMAC.cpp +++ b/Src/HALAL/Services/FMAC/FMAC.cpp @@ -32,9 +32,7 @@ void MultiplierAccelerator::IIR_software_in_software_out_inscribe(uint16_t input } void MultiplierAccelerator::inscribe(){ - DMA::inscribe_stream(Instance.dma_preload); - DMA::inscribe_stream(Instance.dma_read); - DMA::inscribe_stream(Instance.dma_write); + DMA::inscribe_stream_fmac(Instance.hfmac, DMA2_Stream0, DMA2_Stream1, DMA2_Stream2); } void MultiplierAccelerator::start(){ From 52ae1a5037ee4761953a872f598a96ab1ed89e4f Mon Sep 17 00:00:00 2001 From: Jorge Date: Tue, 11 Nov 2025 12:09:27 +0100 Subject: [PATCH 007/109] feat: comprueba el numero de perifericos, cambios de nombre a algunas funcion y reorganizar un poco --- Inc/HALAL/Models/DMA/DMA.hpp | 319 +++++++++++++++++++++++++++++++---- Src/HALAL/Models/DMA/DMA.cpp | 297 -------------------------------- 2 files changed, 283 insertions(+), 333 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index ddf9f6245..640a888c4 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -1,60 +1,307 @@ /* * DMA.hpp * - * Created on: 10 dic. 2022 - * Author: aleja - */ - + * Created on: 10 dic. 2022 + * Author: aleja +*/ #pragma once - #include "C++Utilities/CppUtils.hpp" #include "stm32h7xx_hal.h" #include "main.h" #include "HALAL/Models/MPUManager/MPUManager.hpp" #include -#include +#include + #define MAX_STREAMS 16 -#define STREAMS_USED 10 + + + +template +struct Config { + uint32_t instance; + uint8_t num_streams {N}; + std::array handles; + std::array streams; + std::array irqn; +}; class DMA { -public: - template - struct Peripheral_type_instance { - T* handle; - DMA_HandleTypeDef* dma_handle; - DMA_HandleTypeDef* global_handle; - IRQn_Type irqn; - }; + public: + template + static constexpr auto inscribe_stream(); + + static void start(); + + template + constexpr bool is_spi(); + + template + constexpr bool is_i2c(); + + template + constexpr bool is_adc(); + + template + constexpr bool is_fmac(); + + template + static constexpr uint32_t get_Request(); + + template + static constexpr uint32_t get_Direction(); + + template + static constexpr uint32_t get_PeriphInc(); + + template + static constexpr uint32_t get_MemInc(); + + template + static constexpr uint32_t get_PeriphDataAlignment(); + + template + static constexpr uint32_t get_MemDataAlignment(); + + template + static constexpr uint32_t get_Mode(); + + template + static constexpr uint32_t get_Priority(); + + template + static constexpr uint32_t get_FIFOMode(); + + template + static constexpr uint32_t get_FIFOThreshold(); + + template + static constexpr uint32_t get_MemBurst(); + + template + static constexpr uint32_t get_PeriphBurst(); + + template + static constexpr IRQn_Type get_irqn(); +}; + + +template +constexpr auto DMA::inscribe_stream(){ + constexpr std::size_t N = sizeof...(Streams); + static_assert(N <= MAX_STREAMS, "Too many streams inscribed"); + + Config handleConfig; + handleConfig.instance = Instance; + constexpr uint32_t stream_vals[N] = {Streams...}; + handleConfig.streams = std::array{reinterpret_cast(Streams)...}; + + if constexpr (is_adc()) { + static_assert(N == 1, "ADC DMA must have exactly one stream"); + } + else if constexpr (is_fmac()) { + static_assert(N == 3, "FMAC DMA must have exactly three streams"); + } + else { + static_assert(N == 2, "Peripheral DMA must have exactly two streams (RX and TX)"); + } + + // TODO: verificar que los streams no esten siendo usados + + [&](std::index_sequence) { + (([&] { + handleConfig.handles[I].Request = get_Request(); + handleConfig.handles[I].Direction = get_Direction(); + handleConfig.handles[I].PeriphInc = get_PeriphInc(); + handleConfig.handles[I].MemInc = get_MemInc(); + handleConfig.handles[I].PeriphDataAlignment = get_PeriphDataAlignment(); + handleConfig.handles[I].MemDataAlignment = get_MemDataAlignment(); + handleConfig.handles[I].Mode = get_Mode(); + handleConfig.handles[I].Priority = get_Priority(); + handleConfig.handles[I].FIFOMode = get_FIFOMode(); + handleConfig.handles[I].FIFOThreshold = get_FIFOThreshold(); + handleConfig.handles[I].MemBurst = get_MemBurst(); + handleConfig.handles[I].PeriphBurst = get_PeriphBurst(); + + handleConfig[I] = get_irqn(); + + }()), ...); + }(std::make_index_sequence{}); + + return handleConfig; +} + +template +constexpr bool DMA::is_spi() { + return Instance == SPI1_BASE || Instance == SPI2_BASE || Instance == SPI3_BASE || + Instance == SPI4_BASE || Instance == SPI5_BASE; +} + +template +constexpr bool DMA::is_i2c() { + return Instance == I2C1_BASE || Instance == I2C2_BASE || Instance == I2C3_BASE || Instance == I2C5_BASE; +} + +template +constexpr bool DMA::is_adc() { + return Instance == ADC1_BASE || Instance == ADC2_BASE || Instance == ADC3_BASE; +} + +template +constexpr bool DMA::is_fmac() { + return Instance == FMAC_BASE; +} + +template +constexpr IRQn_Type DMA::get_irqn() { + if (stream == DMA1_Stream0_BASE) return DMA1_Stream0_IRQn; + if (stream == DMA1_Stream1_BASE) return DMA1_Stream1_IRQn; + if (stream == DMA1_Stream2_BASE) return DMA1_Stream2_IRQn; + if (stream == DMA1_Stream3_BASE) return DMA1_Stream3_IRQn; + if (stream == DMA1_Stream4_BASE) return DMA1_Stream4_IRQn; + if (stream == DMA1_Stream5_BASE) return DMA1_Stream5_IRQn; + if (stream == DMA1_Stream6_BASE) return DMA1_Stream6_IRQn; + if (stream == DMA1_Stream7_BASE) return DMA1_Stream7_IRQn; + + if (stream == DMA2_Stream0_BASE) return DMA2_Stream0_IRQn; + if (stream == DMA2_Stream1_BASE) return DMA2_Stream1_IRQn; + if (stream == DMA2_Stream2_BASE) return DMA2_Stream2_IRQn; + if (stream == DMA2_Stream3_BASE) return DMA2_Stream3_IRQn; + if (stream == DMA2_Stream4_BASE) return DMA2_Stream4_IRQn; + if (stream == DMA2_Stream5_BASE) return DMA2_Stream5_IRQn; + if (stream == DMA2_Stream6_BASE) return DMA2_Stream6_IRQn; + return DMA2_Stream7_IRQn; +} + + +template +constexpr uint32_t DMA::get_Request() { + if constexpr (Instance == ADC1_BASE) return DMA_REQUEST_ADC1; + if constexpr (Instance == ADC2_BASE) return DMA_REQUEST_ADC2; + if constexpr (Instance == ADC3_BASE) return DMA_REQUEST_ADC3; + + if constexpr (Instance == I2C1_BASE && i == 0) return DMA_REQUEST_I2C1_RX; + if constexpr (Instance == I2C1_BASE && i == 1) return DMA_REQUEST_I2C1_TX; + if constexpr (Instance == I2C2_BASE && i == 0) return DMA_REQUEST_I2C2_RX; + if constexpr (Instance == I2C2_BASE && i == 1) return DMA_REQUEST_I2C2_TX; + if constexpr (Instance == I2C3_BASE && i == 0) return DMA_REQUEST_I2C3_RX; + if constexpr (Instance == I2C3_BASE && i == 1) return DMA_REQUEST_I2C3_TX; + if constexpr (Instance == I2C5_BASE && i == 0) return DMA_REQUEST_I2C5_RX; + if constexpr (Instance == I2C5_BASE && i == 1) return DMA_REQUEST_I2C5_TX; + + if constexpr (Instance == SPI1_BASE && i == 0) return DMA_REQUEST_SPI1_RX; + if constexpr (Instance == SPI1_BASE && i == 1) return DMA_REQUEST_SPI1_TX; + if constexpr (Instance == SPI2_BASE && i == 0) return DMA_REQUEST_SPI2_RX; + if constexpr (Instance == SPI2_BASE && i == 1) return DMA_REQUEST_SPI2_TX; + if constexpr (Instance == SPI3_BASE && i == 0) return DMA_REQUEST_SPI3_RX; + if constexpr (Instance == SPI3_BASE && i == 1) return DMA_REQUEST_SPI3_TX; + if constexpr (Instance == SPI4_BASE && i == 0) return DMA_REQUEST_SPI4_RX; + if constexpr (Instance == SPI4_BASE && i == 1) return DMA_REQUEST_SPI4_TX; + if constexpr (Instance == SPI5_BASE && i == 0) return DMA_REQUEST_SPI5_RX; + if constexpr (Instance == SPI5_BASE && i == 1) return DMA_REQUEST_SPI5_TX; + + if constexpr (Instance == FMAC_BASE && i == 0) return DMA_REQUEST_MEM2MEM; + if constexpr (Instance == FMAC_BASE && i == 1) return DMA_REQUEST_FMAC_WRITE; + if constexpr (Instance == FMAC_BASE && i == 2) return DMA_REQUEST_FMAC_READ; + return 0; +} + +template +constexpr uint32_t DMA::get_Direction() { + if constexpr (is_fmac() && i == 0){ + return DMA_MEMORY_TO_MEMORY; + } + else if constexpr ((is_i2c() && i == 1) || + (is_spi() && i == 1) || + (is_fmac() && i == 1)){ + return DMA_MEMORY_TO_PERIPH; + } + + return DMA_PERIPH_TO_MEMORY; + +} - //To allow the array to be multiple types, idk first thing that came to mind - using InstanceList = std::variant< - Peripheral_type_instance, - Peripheral_type_instance, - Peripheral_type_instance, - Peripheral_type_instance - >; +template +constexpr uint32_t DMA::get_PeriphInc() { + if constexpr (is_fmac() && i == 0){ + return DMA_PINC_ENABLE; + } + return DMA_PINC_DISABLE; +} - static constexpr void inscribe_stream_adc(ADC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream); +template +constexpr uint32_t DMA::get_MemInc() { + if constexpr (is_fmac() && i == 0){ + return DMA_MINC_DISABLE; + } + return DMA_MINC_ENABLE; +} - static constexpr void inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); +template +constexpr uint32_t DMA::get_PeriphDataAlignment() { + if constexpr (is_spi()){ + return DMA_PDATAALIGN_WORD; + } + else if constexpr (is_spi()){ + return DMA_PDATAALIGN_BYTE; + } - static constexpr void inscribe_stream_spi(SPI_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); + return DMA_PDATAALIGN_HALFWORD; +} - static constexpr void inscribe_stream_fmac(FMAC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_preload, DMA_Stream_TypeDef* stream_read, DMA_Stream_TypeDef* stream_write); +template +constexpr uint32_t DMA::get_MemDataAlignment() { + if constexpr (is_spi()){ + return DMA_MDATAALIGN_WORD; + } + else if constexpr (is_spi()){ + return DMA_MDATAALIGN_BYTE; + } + return DMA_MDATAALIGN_HALFWORD; +} - template - constexpr void inscribe_stream(T* handle, Streams*... streams); +template +constexpr uint32_t DMA::get_Mode() { + if constexpr (is_spi() || is_fmac()){ + return DMA_NORMAL; + } + + return DMA_CIRCULAR; + +} +template +constexpr uint32_t DMA::get_Priority() { + if constexpr (is_fmac()){ + return DMA_PRIORITY_HIGH; + } + + return DMA_PRIORITY_LOW; +} - static constexpr uint32_t get_dma_request(const void* instance, const bool mode); +template +constexpr uint32_t DMA::get_FIFOMode() { + if constexpr (is_fmac()){ + return DMA_FIFOMODE_ENABLE; + } + + return DMA_FIFOMODE_DISABLE; +} - static constexpr IRQn_Type get_irqn(const DMA_Stream_TypeDef* stream); +template +constexpr uint32_t DMA::get_FIFOThreshold() { + if constexpr (is_spi()){ + return DMA_FIFO_THRESHOLD_FULL; + } + return DMA_FIFO_THRESHOLD_HALFFULL; +} - static void start(); +template +constexpr uint32_t DMA::get_MemBurst() { + return DMA_MBURST_SINGLE; +} -private: - inline static constinit uint8_t inscribed_index = 0; - inline static constinit std::array inscribed_streams{}; - inline static DMA_HandleTypeDef dma_handles[MAX_STREAMS]; -}; \ No newline at end of file +template +constexpr uint32_t DMA::get_PeriphBurst() { + return DMA_PBURST_SINGLE; +} diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index 42f117940..e69de29bb 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -1,297 +0,0 @@ -/* - * DMA.cpp - * - * Created on: 10 dic. 2022 - * Author: aleja - */ - -#include "HALAL/Models/DMA/DMA.hpp" -#include "ErrorHandler/ErrorHandler.hpp" - - -constexpr uint32_t DMA::get_dma_request(const void* instance, const bool mode) { - if (instance == ADC1) return DMA_REQUEST_ADC1; - if (instance == ADC2) return DMA_REQUEST_ADC2; - if (instance == ADC3) return DMA_REQUEST_ADC3; - - if (instance == I2C1 && mode) return DMA_REQUEST_I2C1_RX; - if (instance == I2C1 && !mode) return DMA_REQUEST_I2C1_TX; - if (instance == I2C2 && mode) return DMA_REQUEST_I2C2_RX; - if (instance == I2C2 && !mode) return DMA_REQUEST_I2C2_TX; - if (instance == I2C3 && mode) return DMA_REQUEST_I2C3_RX; - if (instance == I2C3 && !mode) return DMA_REQUEST_I2C3_TX; - if (instance == I2C5 && mode) return DMA_REQUEST_I2C5_RX; // NO hay 4? - if (instance == I2C5 && !mode) return DMA_REQUEST_I2C5_TX; - - if (instance == SPI1 && mode) return DMA_REQUEST_SPI1_RX; - if (instance == SPI1 && !mode) return DMA_REQUEST_SPI1_TX; - if (instance == SPI2 && mode) return DMA_REQUEST_SPI2_RX; - if (instance == SPI2 && !mode) return DMA_REQUEST_SPI2_TX; - if (instance == SPI3 && mode) return DMA_REQUEST_SPI3_RX; - if (instance == SPI3 && !mode) return DMA_REQUEST_SPI3_TX; - if (instance == SPI4 && mode) return DMA_REQUEST_SPI4_RX; - if (instance == SPI4 && !mode) return DMA_REQUEST_SPI4_TX; - if (instance == SPI5 && mode) return DMA_REQUEST_SPI5_RX; - if (instance == SPI5 && !mode) return DMA_REQUEST_SPI5_TX; // NO hay 6? - - return 0; -} - - -constexpr IRQn_Type DMA::get_irqn(const DMA_Stream_TypeDef* stream) { - if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; - if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; - if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; - if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; - if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; - if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; - if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; - if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; - - if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; - if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; - if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; - if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; - if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; - if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; - if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; - if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; -} - - - -constexpr void DMA::inscribe_stream_adc(ADC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream) -{ - Peripheral_type_instance instance{}; - - instance.handle = handle; - dma_handle.Instance = stream; - dma_handle.Init.Request = get_dma_request(handle->Instance, true); // El modo no hace nada aquí - dma_handle.Init.Direction = DMA_PERIPH_TO_MEMORY; - dma_handle.Init.PeriphInc = DMA_PINC_DISABLE; - dma_handle.Init.MemInc = DMA_MINC_ENABLE; - dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - dma_handle.Init.Mode = DMA_CIRCULAR; - dma_handle.Init.Priority = DMA_PRIORITY_LOW; - dma_handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.global_handle = handle->DMA_Handle; - instance.irqn = get_irqn(stream); - instance.dma_handle = &dma_handle; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; -} - - -constexpr void DMA::inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx) -{ - // RX Stream - Peripheral_type_instance instance_rx{}; - - - instance_rx.handle = handle; - dma_handle_rx.Instance = stream_rx; - dma_handle_rx.Init.Request = get_dma_request(handle->Instance, true); - dma_handle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; - dma_handle_rx.Init.PeriphInc = DMA_PINC_DISABLE; - dma_handle_rx.Init.MemInc = DMA_MINC_ENABLE; - dma_handle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - dma_handle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - dma_handle_rx.Init.Mode = DMA_CIRCULAR; - dma_handle_rx.Init.Priority = DMA_PRIORITY_LOW; - dma_handle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance_rx.dma_handle = &dma_handle_rx; - instance_rx.global_handle = handle->hdmarx; - instance_rx.irqn = get_irqn(stream_rx); - - inscribed_streams[inscribed_index] = instance_rx; - inscribed_index++; - - // TX Stream - Peripheral_type_instance instance_tx{}; - - - instance_tx.handle = handle; - dma_handle_tx.Instance = stream_tx; - dma_handle_rx.Init.Request = get_dma_request(handle->Instance, false); - dma_handle_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; - dma_handle_tx.Init.PeriphInc = DMA_PINC_DISABLE; - dma_handle_tx.Init.MemInc = DMA_MINC_ENABLE; - dma_handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - dma_handle_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - dma_handle_tx.Init.Mode = DMA_CIRCULAR; - dma_handle_tx.Init.Priority = DMA_PRIORITY_LOW; - dma_handle_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance_tx.dma_handle = &dma_handle_tx; - instance_tx.global_handle = handle->hdmatx; - instance_tx.irqn = get_irqn(stream_tx); - - inscribed_streams[inscribed_index] = instance_tx; - inscribed_index++; -} - - -constexpr void DMA::inscribe_stream_spi(SPI_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx) -{ - // RX Stream - Peripheral_type_instance instance_rx{}; - static DMA_HandleTypeDef dma_handle_rx; - - instance_rx.handle = handle; - dma_handle_rx.Instance = stream_rx; - dma_handle_rx.Init.Request = get_dma_request(handle->Instance, true); - dma_handle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; - dma_handle_rx.Init.PeriphInc = DMA_PINC_DISABLE; - dma_handle_rx.Init.MemInc = DMA_MINC_ENABLE; - dma_handle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - dma_handle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - dma_handle_rx.Init.Mode = DMA_NORMAL; - dma_handle_rx.Init.Priority = DMA_PRIORITY_LOW; - dma_handle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - dma_handle_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - instance_rx.dma_handle = &dma_handle_rx; - instance_rx.global_handle = handle->hdmarx; - instance_rx.irqn = get_irqn(stream_rx); - - inscribed_streams[inscribed_index] = instance_rx; - inscribed_index++; - - // TX Stream - Peripheral_type_instance instance_tx{}; - static DMA_HandleTypeDef dma_handle_tx; - - instance_tx.handle = handle; - dma_handle_tx.Instance = stream_tx; - dma_handle_tx.Init.Request = get_dma_request(handle->Instance, false); - dma_handle_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; - dma_handle_tx.Init.PeriphInc = DMA_PINC_DISABLE; - dma_handle_tx.Init.MemInc = DMA_MINC_ENABLE; - dma_handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - dma_handle_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - dma_handle_tx.Init.Mode = DMA_NORMAL; - dma_handle_tx.Init.Priority = DMA_PRIORITY_LOW; - dma_handle_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - dma_handle_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - instance_tx.dma_handle = &dma_handle_tx; - instance_tx.global_handle = handle->hdmatx; - instance_tx.irqn = get_irqn(stream_tx); - - inscribed_streams[inscribed_index] = instance_tx; - inscribed_index++; -} - - -constexpr void DMA::inscribe_stream_fmac(FMAC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_preload, DMA_Stream_TypeDef* stream_read, DMA_Stream_TypeDef* stream_write) -{ - Peripheral_type_instance instance_preload{}; - static DMA_HandleTypeDef dma_handle_preload; - - instance_preload.handle = handle; - dma_handle_preload.Instance = stream_preload; - dma_handle_preload.Init.Request = DMA_REQUEST_MEM2MEM; - dma_handle_preload.Init.Direction = DMA_MEMORY_TO_MEMORY; - dma_handle_preload.Init.PeriphInc = DMA_PINC_ENABLE; - dma_handle_preload.Init.MemInc = DMA_MINC_DISABLE; - dma_handle_preload.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - dma_handle_preload.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - dma_handle_preload.Init.Mode = DMA_NORMAL; - dma_handle_preload.Init.Priority = DMA_PRIORITY_HIGH; - instance_preload.dma_handle = &dma_handle_preload; - instance_preload.global_handle = handle->hdmaPreload; - instance_preload.irqn = get_irqn(stream_preload); - - inscribed_streams[inscribed_index] = instance_preload; - inscribed_index++; - - Peripheral_type_instance instance_write{}; - static DMA_HandleTypeDef dma_handle_write; - - instance_write.handle = handle; - dma_handle_write.Instance = stream_write; - dma_handle_write.Init.Request = DMA_REQUEST_FMAC_WRITE; - dma_handle_write.Init.Direction = DMA_MEMORY_TO_PERIPH; - dma_handle_write.Init.PeriphInc = DMA_PINC_DISABLE; - dma_handle_write.Init.MemInc = DMA_MINC_ENABLE; - dma_handle_write.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - dma_handle_write.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - dma_handle_write.Init.Mode = DMA_NORMAL; - dma_handle_write.Init.Priority = DMA_PRIORITY_HIGH; - instance_write.dma_handle = &dma_handle_write; - instance_write.global_handle = handle->hdmaIn; - instance_write.irqn = get_irqn(stream_write); - - inscribed_streams[inscribed_index] = instance_write; - inscribed_index++; - - - Peripheral_type_instance instance_read{}; - static DMA_HandleTypeDef dma_handle_read; - - instance_read.handle = handle; - dma_handle_read.Instance = stream_read; - dma_handle_read.Init.Request = DMA_REQUEST_FMAC_READ; - dma_handle_read.Init.Direction = DMA_PERIPH_TO_MEMORY; - dma_handle_read.Init.PeriphInc = DMA_PINC_DISABLE; - dma_handle_read.Init.MemInc = DMA_MINC_ENABLE; - dma_handle_read.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - dma_handle_read.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - dma_handle_read.Init.Mode = DMA_NORMAL; - dma_handle_read.Init.Priority = DMA_PRIORITY_HIGH; - instance_read.dma_handle = &dma_handle_read; - instance_read.global_handle = handle->hdmaOut; - instance_read.irqn = get_irqn(stream_read); - - inscribed_streams[inscribed_index] = instance_read; - inscribed_index++; -} - - -void DMA::start() -{ - __HAL_RCC_DMA1_CLK_ENABLE(); - __HAL_RCC_DMA2_CLK_ENABLE(); - for (auto const &inst : inscribed_streams) { - std::visit([&](auto const &instance) { - if (HAL_DMA_Init(instance.dma_handle) != HAL_OK) - { - Error_Handler(); - } - __HAL_LINKDMA(instance->handle, instance.global_handle, instance->dma_handle); - HAL_NVIC_SetPriority(instance.irqn, 0, 0); - HAL_NVIC_EnableIRQ(instance.irqn); - }, inst); - } -} - - -template -constexpr void DMA::inscribe_stream(T* handle, Streams*... streams){ - if constexpr (sizeof...(Streams) > MAX_STREAMS){ - ErrorHandler("The maximum number of streams is %d", MAX_STREAMS); - } - uint8_t num_streams = sizeof...(Streams); - - // Verify that the number of streams is correct for different peripherials - if constexpr (std::is_same && num_streams != 1){ - ErrorHandler("For ADC, there must be only one stream"); - } - else if constexpr (std::is_same && num_streams != 2){ - ErrorHandler("For SPI, there must be two streams (RX and TX)"); - } - else if constexpr (std::is_same && num_streams != 2){ - ErrorHandler("For I2C, there must be two streams (RX and TX)"); - } - else if constexpr (std::is_same && num_streams != 3){ - ErrorHandler("For FMAC, there must be three streams (preload, write and read)"); - } - - - Peripheral_type_instance instances[num_streams]; - - // All of the instances of the same peripherial will have the same handle - for constexpr (uint8_t num : num_streams){ - instances[num].handle = handle; - } - -} From 3dd6ae442d1624f949e77b9ebfc643bac02802aa Mon Sep 17 00:00:00 2001 From: Jorge Date: Tue, 11 Nov 2025 13:42:50 +0100 Subject: [PATCH 008/109] feat: struct constructor, better is... logic, refactor inscribe (technically consteval), and a few more constexprs --- Inc/HALAL/Models/DMA/DMA.hpp | 141 ++++++++++++++++++----------------- Src/HALAL/Models/DMA/DMA.cpp | 28 +++++++ 2 files changed, 101 insertions(+), 68 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 640a888c4..fbd3ac399 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -14,24 +14,30 @@ #define MAX_STREAMS 16 - - template struct Config { uint32_t instance; - uint8_t num_streams {N}; - std::array handles; - std::array streams; - std::array irqn; + std::array handles{}; + std::array streams{}; + std::array irqn{}; + + constexpr Config(uint32_t inst, + std::array h, + std::array s, + std::array i) + : instance(inst), handles(h), streams(s), irqn(i) {} }; class DMA { public: template - static constexpr auto inscribe_stream(); + static consteval auto inscribe_stream(); static void start(); + template + constexpr bool is_one_of(); + template constexpr bool is_spi(); @@ -86,64 +92,62 @@ class DMA { template -constexpr auto DMA::inscribe_stream(){ +consteval auto DMA::inscribe_stream() { constexpr std::size_t N = sizeof...(Streams); static_assert(N <= MAX_STREAMS, "Too many streams inscribed"); - - Config handleConfig; - handleConfig.instance = Instance; - constexpr uint32_t stream_vals[N] = {Streams...}; - handleConfig.streams = std::array{reinterpret_cast(Streams)...}; - if constexpr (is_adc()) { - static_assert(N == 1, "ADC DMA must have exactly one stream"); - } - else if constexpr (is_fmac()) { - static_assert(N == 3, "FMAC DMA must have exactly three streams"); - } - else { - static_assert(N == 2, "Peripheral DMA must have exactly two streams (RX and TX)"); - } - - // TODO: verificar que los streams no esten siendo usados - - [&](std::index_sequence) { - (([&] { - handleConfig.handles[I].Request = get_Request(); - handleConfig.handles[I].Direction = get_Direction(); - handleConfig.handles[I].PeriphInc = get_PeriphInc(); - handleConfig.handles[I].MemInc = get_MemInc(); - handleConfig.handles[I].PeriphDataAlignment = get_PeriphDataAlignment(); - handleConfig.handles[I].MemDataAlignment = get_MemDataAlignment(); - handleConfig.handles[I].Mode = get_Mode(); - handleConfig.handles[I].Priority = get_Priority(); - handleConfig.handles[I].FIFOMode = get_FIFOMode(); - handleConfig.handles[I].FIFOThreshold = get_FIFOThreshold(); - handleConfig.handles[I].MemBurst = get_MemBurst(); - handleConfig.handles[I].PeriphBurst = get_PeriphBurst(); - - handleConfig[I] = get_irqn(); - - }()), ...); + constexpr std::array streams = { reinterpret_cast(Streams)... }; + + // Verificación de cantidad según periférico + if constexpr (is_adc()) static_assert(N == 1, "ADC DMA must have exactly one stream"); + else if constexpr (is_fmac()) static_assert(N == 3, "FMAC DMA must have exactly three streams"); + else static_assert(N == 2, "Peripheral DMA must have exactly two streams (RX and TX)"); + + constexpr auto make_handles = [](std::index_sequence) { + return std::array{ + DMA_InitTypeDef{ + .Request = get_Request(), + .Direction = get_Direction(), + .PeriphInc = get_PeriphInc(), + .MemInc = get_MemInc(), + .PeriphDataAlignment = get_PeriphDataAlignment(), + .MemDataAlignment = get_MemDataAlignment(), + .Mode = get_Mode(), + .Priority = get_Priority(), + .FIFOMode = get_FIFOMode(), + .FIFOThreshold = get_FIFOThreshold(), + .MemBurst = get_MemBurst(), + .PeriphBurst = get_PeriphBurst(), + }... + }; }(std::make_index_sequence{}); - - return handleConfig; + + constexpr auto make_irq = [](std::index_sequence) { + return std::array{ get_irqn()... }; + }(std::make_index_sequence{}); + + return Config{Instance, make_handles, streams, make_irq}; +} + + +template +constexpr bool DMA::is_one_of() { + return ((Instance == Bases) || ...); } template constexpr bool DMA::is_spi() { - return Instance == SPI1_BASE || Instance == SPI2_BASE || Instance == SPI3_BASE || - Instance == SPI4_BASE || Instance == SPI5_BASE; + return is_one_of(); } template constexpr bool DMA::is_i2c() { - return Instance == I2C1_BASE || Instance == I2C2_BASE || Instance == I2C3_BASE || Instance == I2C5_BASE; + return is_one_of(); } template constexpr bool DMA::is_adc() { - return Instance == ADC1_BASE || Instance == ADC2_BASE || Instance == ADC3_BASE; + return is_one_of(); } template @@ -153,23 +157,24 @@ constexpr bool DMA::is_fmac() { template constexpr IRQn_Type DMA::get_irqn() { - if (stream == DMA1_Stream0_BASE) return DMA1_Stream0_IRQn; - if (stream == DMA1_Stream1_BASE) return DMA1_Stream1_IRQn; - if (stream == DMA1_Stream2_BASE) return DMA1_Stream2_IRQn; - if (stream == DMA1_Stream3_BASE) return DMA1_Stream3_IRQn; - if (stream == DMA1_Stream4_BASE) return DMA1_Stream4_IRQn; - if (stream == DMA1_Stream5_BASE) return DMA1_Stream5_IRQn; - if (stream == DMA1_Stream6_BASE) return DMA1_Stream6_IRQn; - if (stream == DMA1_Stream7_BASE) return DMA1_Stream7_IRQn; - - if (stream == DMA2_Stream0_BASE) return DMA2_Stream0_IRQn; - if (stream == DMA2_Stream1_BASE) return DMA2_Stream1_IRQn; - if (stream == DMA2_Stream2_BASE) return DMA2_Stream2_IRQn; - if (stream == DMA2_Stream3_BASE) return DMA2_Stream3_IRQn; - if (stream == DMA2_Stream4_BASE) return DMA2_Stream4_IRQn; - if (stream == DMA2_Stream5_BASE) return DMA2_Stream5_IRQn; - if (stream == DMA2_Stream6_BASE) return DMA2_Stream6_IRQn; - return DMA2_Stream7_IRQn; + if constexpr (stream == DMA1_Stream0_BASE) return DMA1_Stream0_IRQn; + else if constexpr (stream == DMA1_Stream1_BASE) return DMA1_Stream1_IRQn; + else if constexpr (stream == DMA1_Stream2_BASE) return DMA1_Stream2_IRQn; + else if constexpr (stream == DMA1_Stream3_BASE) return DMA1_Stream3_IRQn; + else if constexpr (stream == DMA1_Stream4_BASE) return DMA1_Stream4_IRQn; + else if constexpr (stream == DMA1_Stream5_BASE) return DMA1_Stream5_IRQn; + else if constexpr (stream == DMA1_Stream6_BASE) return DMA1_Stream6_IRQn; + else if constexpr (stream == DMA1_Stream7_BASE) return DMA1_Stream7_IRQn; + + else if constexpr (stream == DMA2_Stream0_BASE) return DMA2_Stream0_IRQn; + else if constexpr (stream == DMA2_Stream1_BASE) return DMA2_Stream1_IRQn; + else if constexpr (stream == DMA2_Stream2_BASE) return DMA2_Stream2_IRQn; + else if constexpr (stream == DMA2_Stream3_BASE) return DMA2_Stream3_IRQn; + else if constexpr (stream == DMA2_Stream4_BASE) return DMA2_Stream4_IRQn; + else if constexpr (stream == DMA2_Stream5_BASE) return DMA2_Stream5_IRQn; + else if constexpr (stream == DMA2_Stream6_BASE) return DMA2_Stream6_IRQn; + else if constexpr (stream == DMA2_Stream7_BASE) return DMA2_Stream7_IRQn; + else static_assert([]{return false;}(), "Invalid DMA stream base address"); } @@ -238,7 +243,7 @@ constexpr uint32_t DMA::get_MemInc() { template constexpr uint32_t DMA::get_PeriphDataAlignment() { - if constexpr (is_spi()){ + if constexpr (is_i2c()){ return DMA_PDATAALIGN_WORD; } else if constexpr (is_spi()){ @@ -250,7 +255,7 @@ constexpr uint32_t DMA::get_PeriphDataAlignment() { template constexpr uint32_t DMA::get_MemDataAlignment() { - if constexpr (is_spi()){ + if constexpr (is_i2c()){ return DMA_MDATAALIGN_WORD; } else if constexpr (is_spi()){ diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index e69de29bb..57d310a9b 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -0,0 +1,28 @@ +#include "HALAL/Models/DMA/DMA.hpp" + + +void DMA::start() +{ + __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + + for (auto const &inst : inscribed_streams | std::views::take(inscribed_count)) { + std::visit([](auto const &cfg) { + for (size_t i = 0; i < cfg.num_streams; ++i) { + DMA_HandleTypeDef dma_handle{}; + dma_handle.Instance = cfg.streams[i]; + dma_handle.Init = cfg.handles[i]; + + if (HAL_DMA_Init(&dma_handle) != HAL_OK) { + Error_Handler(); + } + + // Enlazar DMA con periférico + __HAL_LINKDMA(cfg.instance, global_handle, dma_handle); + + HAL_NVIC_SetPriority(cfg.irqn[i], 0, 0); + HAL_NVIC_EnableIRQ(cfg.irqn[i]); + } + }, inst); + } +} From 8ca78eefc390ea96617cb05562bb5122d9633326 Mon Sep 17 00:00:00 2001 From: Jorge Date: Tue, 11 Nov 2025 17:17:17 +0100 Subject: [PATCH 009/109] algunas cosillas para que compile. falta conseguir pasarle las variables de los modulos al start --- Inc/HALAL/Models/DMA/DMA.hpp | 20 ++++----- Src/HALAL/Models/DMA/DMA.cpp | 45 ++++++++++---------- Src/HALAL/Services/ADC/ADC.cpp | 4 +- Src/HALAL/Services/Communication/I2C/I2C.cpp | 2 +- Src/HALAL/Services/Communication/SPI/SPI.cpp | 2 +- Src/HALAL/Services/FMAC/FMAC.cpp | 2 +- 6 files changed, 37 insertions(+), 38 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index fbd3ac399..edf07b7de 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -18,12 +18,12 @@ template struct Config { uint32_t instance; std::array handles{}; - std::array streams{}; + std::array streams{}; std::array irqn{}; constexpr Config(uint32_t inst, std::array h, - std::array s, + std::array s, std::array i) : instance(inst), handles(h), streams(s), irqn(i) {} }; @@ -32,23 +32,23 @@ class DMA { public: template static consteval auto inscribe_stream(); - + static void start(); template - constexpr bool is_one_of(); + static constexpr bool is_one_of(); template - constexpr bool is_spi(); + static constexpr bool is_spi(); template - constexpr bool is_i2c(); + static constexpr bool is_i2c(); template - constexpr bool is_adc(); + static constexpr bool is_adc(); template - constexpr bool is_fmac(); + static constexpr bool is_fmac(); template static constexpr uint32_t get_Request(); @@ -96,7 +96,7 @@ consteval auto DMA::inscribe_stream() { constexpr std::size_t N = sizeof...(Streams); static_assert(N <= MAX_STREAMS, "Too many streams inscribed"); - constexpr std::array streams = { reinterpret_cast(Streams)... }; + constexpr std::array streams = {(Streams)... }; // Verificación de cantidad según periférico if constexpr (is_adc()) static_assert(N == 1, "ADC DMA must have exactly one stream"); @@ -309,4 +309,4 @@ constexpr uint32_t DMA::get_MemBurst() { template constexpr uint32_t DMA::get_PeriphBurst() { return DMA_PBURST_SINGLE; -} +} \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index 57d310a9b..05a23e066 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -1,28 +1,27 @@ -#include "HALAL/Models/DMA/DMA.hpp" +// #include "HALAL/Models/DMA/DMA.hpp" +// void DMA::start() +// { +// __HAL_RCC_DMA1_CLK_ENABLE(); +// __HAL_RCC_DMA2_CLK_ENABLE(); -void DMA::start() -{ - __HAL_RCC_DMA1_CLK_ENABLE(); - __HAL_RCC_DMA2_CLK_ENABLE(); +// for (auto const &inst : instancias) { +// std::visit([](auto const &cfg) { +// for (size_t i = 0; i < cfg.handles.size(); ++i) { +// static DMA_HandleTypeDef dma_handle{}; +// dma_handle.Instance = cfg.streams[i]; +// dma_handle.Init = cfg.handles[i]; - for (auto const &inst : inscribed_streams | std::views::take(inscribed_count)) { - std::visit([](auto const &cfg) { - for (size_t i = 0; i < cfg.num_streams; ++i) { - DMA_HandleTypeDef dma_handle{}; - dma_handle.Instance = cfg.streams[i]; - dma_handle.Init = cfg.handles[i]; +// if (HAL_DMA_Init(&dma_handle) != HAL_OK) { +// Error_Handler(); +// } - if (HAL_DMA_Init(&dma_handle) != HAL_OK) { - Error_Handler(); - } +// // Enlazar DMA con periférico +// __HAL_LINKDMA(cfg.instance, global_handle, dma_handle); - // Enlazar DMA con periférico - __HAL_LINKDMA(cfg.instance, global_handle, dma_handle); - - HAL_NVIC_SetPriority(cfg.irqn[i], 0, 0); - HAL_NVIC_EnableIRQ(cfg.irqn[i]); - } - }, inst); - } -} +// HAL_NVIC_SetPriority(cfg.irqn[i], 0, 0); +// HAL_NVIC_EnableIRQ(cfg.irqn[i]); +// } +// }, inst); +// } +// } diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index 2717f2c7d..e73c195ce 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -42,7 +42,7 @@ uint8_t ADC::inscribe(Pin pin) { InitData& init_data = active_instances[id_counter].peripheral->init_data; - DMA::inscribe_stream(init_data.dma_stream); + constexpr auto dma_adc1_config {DMA::inscribe_stream()}; active_instances[id_counter].rank = init_data.channels.size(); init_data.channels.push_back(active_instances[id_counter].channel); return id_counter++; @@ -68,7 +68,7 @@ void ADC::turn_on(uint8_t id){ uint32_t buffer_length = peripheral->init_data.channels.size(); if (HAL_ADC_Start_DMA(peripheral->handle, (uint32_t*) peripheral->dma_data_buffer, buffer_length) != HAL_OK) { - ErrorHandler("DMA - %d - of ADC - %d - did not start correctly", peripheral->init_data.dma_stream, id); + //ErrorHandler("DMA - %d - of ADC - %d - did not start correctly", peripheral->init_data.dma_stream, id); return; } diff --git a/Src/HALAL/Services/Communication/I2C/I2C.cpp b/Src/HALAL/Services/Communication/I2C/I2C.cpp index 6ba12da50..a41133234 100644 --- a/Src/HALAL/Services/Communication/I2C/I2C.cpp +++ b/Src/HALAL/Services/Communication/I2C/I2C.cpp @@ -23,7 +23,7 @@ uint8_t I2C::inscribe(I2C::Peripheral &i2c, uint8_t address) { Pin::inscribe(i2c_instance->SCL, ALTERNATIVE); Pin::inscribe(i2c_instance->SDA, ALTERNATIVE); - DMA::inscribe_stream_i2c(i2c_instance->hi2c, DMA1_Stream3, DMA1_Stream4); + constexpr auto dma_i2c1_config {DMA::inscribe_stream()}; uint8_t id = I2C::id_counter++; diff --git a/Src/HALAL/Services/Communication/SPI/SPI.cpp b/Src/HALAL/Services/Communication/SPI/SPI.cpp index 5d5eb9058..6c590e3f3 100644 --- a/Src/HALAL/Services/Communication/SPI/SPI.cpp +++ b/Src/HALAL/Services/Communication/SPI/SPI.cpp @@ -56,7 +56,7 @@ uint8_t SPI::inscribe(SPI::Peripheral& spi) { uint8_t id = SPI::id_counter++; if (spi_instance->use_DMA) { - DMA::inscribe_stream_spi(spi_instance->hspi, DMA1_Stream5, DMA1_Stream6); + constexpr auto dma_spi1_config {DMA::inscribe_stream()}; } SPI::registered_spi[id] = spi_instance; SPI::registered_spi_by_handler[spi_instance->hspi] = spi_instance; diff --git a/Src/HALAL/Services/FMAC/FMAC.cpp b/Src/HALAL/Services/FMAC/FMAC.cpp index 4b2107cab..56bfbbda5 100644 --- a/Src/HALAL/Services/FMAC/FMAC.cpp +++ b/Src/HALAL/Services/FMAC/FMAC.cpp @@ -32,7 +32,7 @@ void MultiplierAccelerator::IIR_software_in_software_out_inscribe(uint16_t input } void MultiplierAccelerator::inscribe(){ - DMA::inscribe_stream_fmac(Instance.hfmac, DMA2_Stream0, DMA2_Stream1, DMA2_Stream2); + constexpr auto fmac_dma_config {DMA::inscribe_stream()}; } void MultiplierAccelerator::start(){ From 3c44a60812e3f7a1dfe8904f6511e2689c6039eb Mon Sep 17 00:00:00 2001 From: Jorge Date: Wed, 12 Nov 2025 13:23:35 +0100 Subject: [PATCH 010/109] feat: agregar static a las variables constexpr --- Src/HALAL/Services/ADC/ADC.cpp | 2 +- Src/HALAL/Services/Communication/I2C/I2C.cpp | 2 +- Src/HALAL/Services/Communication/SPI/SPI.cpp | 2 +- Src/HALAL/Services/FMAC/FMAC.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index e73c195ce..2ee1b7fbc 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -42,7 +42,7 @@ uint8_t ADC::inscribe(Pin pin) { InitData& init_data = active_instances[id_counter].peripheral->init_data; - constexpr auto dma_adc1_config {DMA::inscribe_stream()}; + static constexpr auto dma_adc1_config {DMA::inscribe_stream()}; active_instances[id_counter].rank = init_data.channels.size(); init_data.channels.push_back(active_instances[id_counter].channel); return id_counter++; diff --git a/Src/HALAL/Services/Communication/I2C/I2C.cpp b/Src/HALAL/Services/Communication/I2C/I2C.cpp index a41133234..25ba233ac 100644 --- a/Src/HALAL/Services/Communication/I2C/I2C.cpp +++ b/Src/HALAL/Services/Communication/I2C/I2C.cpp @@ -23,7 +23,7 @@ uint8_t I2C::inscribe(I2C::Peripheral &i2c, uint8_t address) { Pin::inscribe(i2c_instance->SCL, ALTERNATIVE); Pin::inscribe(i2c_instance->SDA, ALTERNATIVE); - constexpr auto dma_i2c1_config {DMA::inscribe_stream()}; + static constexpr auto dma_i2c1_config {DMA::inscribe_stream()}; uint8_t id = I2C::id_counter++; diff --git a/Src/HALAL/Services/Communication/SPI/SPI.cpp b/Src/HALAL/Services/Communication/SPI/SPI.cpp index 6c590e3f3..f9f9628f6 100644 --- a/Src/HALAL/Services/Communication/SPI/SPI.cpp +++ b/Src/HALAL/Services/Communication/SPI/SPI.cpp @@ -56,7 +56,7 @@ uint8_t SPI::inscribe(SPI::Peripheral& spi) { uint8_t id = SPI::id_counter++; if (spi_instance->use_DMA) { - constexpr auto dma_spi1_config {DMA::inscribe_stream()}; + static constexpr auto dma_spi1_config {DMA::inscribe_stream()}; } SPI::registered_spi[id] = spi_instance; SPI::registered_spi_by_handler[spi_instance->hspi] = spi_instance; diff --git a/Src/HALAL/Services/FMAC/FMAC.cpp b/Src/HALAL/Services/FMAC/FMAC.cpp index 56bfbbda5..5e798f2ba 100644 --- a/Src/HALAL/Services/FMAC/FMAC.cpp +++ b/Src/HALAL/Services/FMAC/FMAC.cpp @@ -32,7 +32,7 @@ void MultiplierAccelerator::IIR_software_in_software_out_inscribe(uint16_t input } void MultiplierAccelerator::inscribe(){ - constexpr auto fmac_dma_config {DMA::inscribe_stream()}; + static constexpr auto fmac_dma_config {DMA::inscribe_stream()}; } void MultiplierAccelerator::start(){ From d2005f26da655644b51e87b0eebdb56e989ea56d Mon Sep 17 00:00:00 2001 From: Jorge Date: Sat, 22 Nov 2025 19:45:39 +0100 Subject: [PATCH 011/109] me lo quiero pasar al PC solamente, luego hago bien el commit --- Inc/HALAL/Models/DMA/DMA.hpp | 329 +++++++++++++------------------ Src/HALAL/Services/FMAC/FMAC.cpp | 2 +- 2 files changed, 137 insertions(+), 194 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index edf07b7de..904869bd7 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -14,299 +14,242 @@ #define MAX_STREAMS 16 -template -struct Config { - uint32_t instance; - std::array handles{}; - std::array streams{}; - std::array irqn{}; - - constexpr Config(uint32_t inst, - std::array h, - std::array s, - std::array i) - : instance(inst), handles(h), streams(s), irqn(i) {} -}; - class DMA { public: template - static consteval auto inscribe_stream(); + static void inscribe_stream(); static void start(); - template - static constexpr bool is_one_of(); + static bool is_one_of(auto Instance, auto... Bases); - template - static constexpr bool is_spi(); + static bool is_spi(auto Instance); - template - static constexpr bool is_i2c(); + static bool is_i2c(auto Instance); - template - static constexpr bool is_adc(); + static bool is_adc(auto Instance); - template - static constexpr bool is_fmac(); + static bool is_fmac(auto Instance); - template - static constexpr uint32_t get_Request(); + + static uint32_t get_Request(auto Instance, uint8_t i); - template - static constexpr uint32_t get_Direction(); + static uint32_t get_Direction(auto Instance, uint8_t i); - template - static constexpr uint32_t get_PeriphInc(); + static uint32_t get_PeriphInc(auto Instance, uint8_t i); - template - static constexpr uint32_t get_MemInc(); + static uint32_t get_MemInc(auto Instance, uint8_t i); - template - static constexpr uint32_t get_PeriphDataAlignment(); + static uint32_t get_PeriphDataAlignment(auto Instance, uint8_t i); - template - static constexpr uint32_t get_MemDataAlignment(); + static uint32_t get_MemDataAlignment(auto Instance, uint8_t i); - template - static constexpr uint32_t get_Mode(); + static uint32_t get_Mode(auto Instance, uint8_t i); - template - static constexpr uint32_t get_Priority(); + static uint32_t get_Priority(auto Instance, uint8_t i); - template - static constexpr uint32_t get_FIFOMode(); + static uint32_t get_FIFOMode(auto Instance, uint8_t i); - template - static constexpr uint32_t get_FIFOThreshold(); + static uint32_t get_FIFOThreshold(auto Instance, uint8_t i); - template - static constexpr uint32_t get_MemBurst(); + static uint32_t get_MemBurst(auto Instance, uint8_t i); - template - static constexpr uint32_t get_PeriphBurst(); + static uint32_t get_PeriphBurst(auto Instance, uint8_t i); - template - static constexpr IRQn_Type get_irqn(); + static IRQn_Type get_irqn(auto stream); + + private: + static std::array inscribed_streams; + static uint8_t inscribed_index; + }; +inline uint8_t DMA::inscribed_index{0}; template -consteval auto DMA::inscribe_stream() { - constexpr std::size_t N = sizeof...(Streams); - static_assert(N <= MAX_STREAMS, "Too many streams inscribed"); - - constexpr std::array streams = {(Streams)... }; +void DMA::inscribe_stream() { + std::size_t N = sizeof...(Streams); + ErrorHandler(inscribed_index + N <= MAX_STREAMS, "Too many streams inscribed"); + std::array streams = {(DMA_Stream_TypeDef*)Streams... }; // Verificación de cantidad según periférico - if constexpr (is_adc()) static_assert(N == 1, "ADC DMA must have exactly one stream"); - else if constexpr (is_fmac()) static_assert(N == 3, "FMAC DMA must have exactly three streams"); - else static_assert(N == 2, "Peripheral DMA must have exactly two streams (RX and TX)"); - - constexpr auto make_handles = [](std::index_sequence) { - return std::array{ - DMA_InitTypeDef{ - .Request = get_Request(), - .Direction = get_Direction(), - .PeriphInc = get_PeriphInc(), - .MemInc = get_MemInc(), - .PeriphDataAlignment = get_PeriphDataAlignment(), - .MemDataAlignment = get_MemDataAlignment(), - .Mode = get_Mode(), - .Priority = get_Priority(), - .FIFOMode = get_FIFOMode(), - .FIFOThreshold = get_FIFOThreshold(), - .MemBurst = get_MemBurst(), - .PeriphBurst = get_PeriphBurst(), - }... - }; - }(std::make_index_sequence{}); - - constexpr auto make_irq = [](std::index_sequence) { - return std::array{ get_irqn()... }; - }(std::make_index_sequence{}); - - return Config{Instance, make_handles, streams, make_irq}; + if (is_adc(Instance)) ErrorHandler(N == 1, "ADC DMA must have exactly one stream"); + else if (is_fmac(Instance)) ErrorHandler(N == 3, "FMAC DMA must have exactly three streams"); + else ErrorHandler(N == 2, "Peripheral DMA must have exactly two streams (RX and TX)"); + + for (uint8_t i = 0; i < N; i++){ + DMA_HandleTypeDef dma_handle; + dma_handle.Init.Request = get_Request(Instance, i); + dma_handle.Init.Direction = get_Direction(Instance, i); + dma_handle.Init.PeriphInc = get_PeriphInc(Instance, i); + dma_handle.Init.MemInc = get_MemInc(Instance, i); + dma_handle.Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); + dma_handle.Init.MemDataAlignment = get_MemDataAlignment(Instance, i); + dma_handle.Init.Mode = get_Mode(Instance, i); + dma_handle.Init.Priority = get_Priority(Instance, i); + dma_handle.Init.FIFOMode = get_FIFOMode(Instance, i); + dma_handle.Init.FIFOThreshold = get_FIFOThreshold(Instance, i); + dma_handle.Init.MemBurst = get_MemBurst(Instance, i); + dma_handle.Init.PeriphBurst = get_PeriphBurst(Instance, i); + dma_handle.Instance = streams[i]; + inscribed_streams[inscribed_index++] = dma_handle; + } } -template -constexpr bool DMA::is_one_of() { +bool DMA::is_one_of(auto Instance, auto... Bases) { return ((Instance == Bases) || ...); } -template -constexpr bool DMA::is_spi() { - return is_one_of(); + bool DMA::is_spi(auto Instance) { + return is_one_of(Instance, SPI1, SPI2, SPI3, SPI4, SPI5); } -template -constexpr bool DMA::is_i2c() { - return is_one_of(); + bool DMA::is_i2c(auto Instance) { + return is_one_of(Instance, I2C1, I2C2, I2C3, I2C5); } -template -constexpr bool DMA::is_adc() { - return is_one_of(); + bool DMA::is_adc(auto Instance) { + return is_one_of(Instance, ADC1, ADC2, ADC3); } -template -constexpr bool DMA::is_fmac() { - return Instance == FMAC_BASE; + bool DMA::is_fmac(auto Instance) { + return Instance == FMAC; } -template -constexpr IRQn_Type DMA::get_irqn() { - if constexpr (stream == DMA1_Stream0_BASE) return DMA1_Stream0_IRQn; - else if constexpr (stream == DMA1_Stream1_BASE) return DMA1_Stream1_IRQn; - else if constexpr (stream == DMA1_Stream2_BASE) return DMA1_Stream2_IRQn; - else if constexpr (stream == DMA1_Stream3_BASE) return DMA1_Stream3_IRQn; - else if constexpr (stream == DMA1_Stream4_BASE) return DMA1_Stream4_IRQn; - else if constexpr (stream == DMA1_Stream5_BASE) return DMA1_Stream5_IRQn; - else if constexpr (stream == DMA1_Stream6_BASE) return DMA1_Stream6_IRQn; - else if constexpr (stream == DMA1_Stream7_BASE) return DMA1_Stream7_IRQn; - - else if constexpr (stream == DMA2_Stream0_BASE) return DMA2_Stream0_IRQn; - else if constexpr (stream == DMA2_Stream1_BASE) return DMA2_Stream1_IRQn; - else if constexpr (stream == DMA2_Stream2_BASE) return DMA2_Stream2_IRQn; - else if constexpr (stream == DMA2_Stream3_BASE) return DMA2_Stream3_IRQn; - else if constexpr (stream == DMA2_Stream4_BASE) return DMA2_Stream4_IRQn; - else if constexpr (stream == DMA2_Stream5_BASE) return DMA2_Stream5_IRQn; - else if constexpr (stream == DMA2_Stream6_BASE) return DMA2_Stream6_IRQn; - else if constexpr (stream == DMA2_Stream7_BASE) return DMA2_Stream7_IRQn; - else static_assert([]{return false;}(), "Invalid DMA stream base address"); -} - -template -constexpr uint32_t DMA::get_Request() { - if constexpr (Instance == ADC1_BASE) return DMA_REQUEST_ADC1; - if constexpr (Instance == ADC2_BASE) return DMA_REQUEST_ADC2; - if constexpr (Instance == ADC3_BASE) return DMA_REQUEST_ADC3; - - if constexpr (Instance == I2C1_BASE && i == 0) return DMA_REQUEST_I2C1_RX; - if constexpr (Instance == I2C1_BASE && i == 1) return DMA_REQUEST_I2C1_TX; - if constexpr (Instance == I2C2_BASE && i == 0) return DMA_REQUEST_I2C2_RX; - if constexpr (Instance == I2C2_BASE && i == 1) return DMA_REQUEST_I2C2_TX; - if constexpr (Instance == I2C3_BASE && i == 0) return DMA_REQUEST_I2C3_RX; - if constexpr (Instance == I2C3_BASE && i == 1) return DMA_REQUEST_I2C3_TX; - if constexpr (Instance == I2C5_BASE && i == 0) return DMA_REQUEST_I2C5_RX; - if constexpr (Instance == I2C5_BASE && i == 1) return DMA_REQUEST_I2C5_TX; - - if constexpr (Instance == SPI1_BASE && i == 0) return DMA_REQUEST_SPI1_RX; - if constexpr (Instance == SPI1_BASE && i == 1) return DMA_REQUEST_SPI1_TX; - if constexpr (Instance == SPI2_BASE && i == 0) return DMA_REQUEST_SPI2_RX; - if constexpr (Instance == SPI2_BASE && i == 1) return DMA_REQUEST_SPI2_TX; - if constexpr (Instance == SPI3_BASE && i == 0) return DMA_REQUEST_SPI3_RX; - if constexpr (Instance == SPI3_BASE && i == 1) return DMA_REQUEST_SPI3_TX; - if constexpr (Instance == SPI4_BASE && i == 0) return DMA_REQUEST_SPI4_RX; - if constexpr (Instance == SPI4_BASE && i == 1) return DMA_REQUEST_SPI4_TX; - if constexpr (Instance == SPI5_BASE && i == 0) return DMA_REQUEST_SPI5_RX; - if constexpr (Instance == SPI5_BASE && i == 1) return DMA_REQUEST_SPI5_TX; +IRQn_Type DMA::get_irqn(auto stream) { + if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; + else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; + else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; + else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; + else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; + else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; + else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; + else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; + + else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; + else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; + else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; + else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; + else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; + else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; + else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; + else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; + else ErrorHandler(); +} + +uint32_t DMA::get_Request(auto Instance, uint8_t i) { + if (Instance == ADC1) return DMA_REQUEST_ADC1; + if (Instance == ADC2) return DMA_REQUEST_ADC2; + if (Instance == ADC3) return DMA_REQUEST_ADC3; + + if (Instance == I2C1 && i == 0) return DMA_REQUEST_I2C1_RX; + if (Instance == I2C1 && i == 1) return DMA_REQUEST_I2C1_TX; + if (Instance == I2C2 && i == 0) return DMA_REQUEST_I2C2_RX; + if (Instance == I2C2 && i == 1) return DMA_REQUEST_I2C2_TX; + if (Instance == I2C3 && i == 0) return DMA_REQUEST_I2C3_RX; + if (Instance == I2C3 && i == 1) return DMA_REQUEST_I2C3_TX; + if (Instance == I2C5 && i == 0) return DMA_REQUEST_I2C5_RX; + if (Instance == I2C5 && i == 1) return DMA_REQUEST_I2C5_TX; + + if (Instance == SPI1 && i == 0) return DMA_REQUEST_SPI1_RX; + if (Instance == SPI1 && i == 1) return DMA_REQUEST_SPI1_TX; + if (Instance == SPI2 && i == 0) return DMA_REQUEST_SPI2_RX; + if (Instance == SPI2 && i == 1) return DMA_REQUEST_SPI2_TX; + if (Instance == SPI3 && i == 0) return DMA_REQUEST_SPI3_RX; + if (Instance == SPI3 && i == 1) return DMA_REQUEST_SPI3_TX; + if (Instance == SPI4 && i == 0) return DMA_REQUEST_SPI4_RX; + if (Instance == SPI4 && i == 1) return DMA_REQUEST_SPI4_TX; + if (Instance == SPI5 && i == 0) return DMA_REQUEST_SPI5_RX; + if (Instance == SPI5 && i == 1) return DMA_REQUEST_SPI5_TX; - if constexpr (Instance == FMAC_BASE && i == 0) return DMA_REQUEST_MEM2MEM; - if constexpr (Instance == FMAC_BASE && i == 1) return DMA_REQUEST_FMAC_WRITE; - if constexpr (Instance == FMAC_BASE && i == 2) return DMA_REQUEST_FMAC_READ; + if (Instance == FMAC && i == 0) return DMA_REQUEST_MEM2MEM; + if (Instance == FMAC && i == 1) return DMA_REQUEST_FMAC_WRITE; + if (Instance == FMAC && i == 2) return DMA_REQUEST_FMAC_READ; return 0; } -template -constexpr uint32_t DMA::get_Direction() { - if constexpr (is_fmac() && i == 0){ +uint32_t DMA::get_Direction(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ return DMA_MEMORY_TO_MEMORY; } - else if constexpr ((is_i2c() && i == 1) || - (is_spi() && i == 1) || - (is_fmac() && i == 1)){ + else if ((is_i2c(Instance) && i == 1) || + (is_spi(Instance) && i == 1) || + (is_fmac(Instance) && i == 1)){ return DMA_MEMORY_TO_PERIPH; } return DMA_PERIPH_TO_MEMORY; - } -template -constexpr uint32_t DMA::get_PeriphInc() { - if constexpr (is_fmac() && i == 0){ - return DMA_PINC_ENABLE; +uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_PINC_ENABLE;xº } return DMA_PINC_DISABLE; } - -template -constexpr uint32_t DMA::get_MemInc() { - if constexpr (is_fmac() && i == 0){ +uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ return DMA_MINC_DISABLE; } return DMA_MINC_ENABLE; } -template -constexpr uint32_t DMA::get_PeriphDataAlignment() { - if constexpr (is_i2c()){ +uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { + if (is_i2c()){ return DMA_PDATAALIGN_WORD; } - else if constexpr (is_spi()){ + else if (is_spi()){ return DMA_PDATAALIGN_BYTE; } return DMA_PDATAALIGN_HALFWORD; } -template -constexpr uint32_t DMA::get_MemDataAlignment() { - if constexpr (is_i2c()){ +uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { + if (is_i2c()){ return DMA_MDATAALIGN_WORD; } - else if constexpr (is_spi()){ + else if (is_spi()){ return DMA_MDATAALIGN_BYTE; } return DMA_MDATAALIGN_HALFWORD; } - -template -constexpr uint32_t DMA::get_Mode() { - if constexpr (is_spi() || is_fmac()){ +uint32_t DMA::get_Mode(auto Instance, uint8_t i) { + if (is_spi() || is_fmac(Instance)){ return DMA_NORMAL; } return DMA_CIRCULAR; - -} +} -template -constexpr uint32_t DMA::get_Priority() { - if constexpr (is_fmac()){ + uint32_t DMA::get_Priority(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ return DMA_PRIORITY_HIGH; } return DMA_PRIORITY_LOW; } - -template -constexpr uint32_t DMA::get_FIFOMode() { - if constexpr (is_fmac()){ - return DMA_FIFOMODE_ENABLE; +uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ + return DMA_FIFOMODE_ENABLE; } - return DMA_FIFOMODE_DISABLE; } -template -constexpr uint32_t DMA::get_FIFOThreshold() { - if constexpr (is_spi()){ +uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { + if (is_spi()){ return DMA_FIFO_THRESHOLD_FULL; } return DMA_FIFO_THRESHOLD_HALFFULL; } -template -constexpr uint32_t DMA::get_MemBurst() { +uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { return DMA_MBURST_SINGLE; } -template -constexpr uint32_t DMA::get_PeriphBurst() { +uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { return DMA_PBURST_SINGLE; } \ No newline at end of file diff --git a/Src/HALAL/Services/FMAC/FMAC.cpp b/Src/HALAL/Services/FMAC/FMAC.cpp index 5e798f2ba..546de926f 100644 --- a/Src/HALAL/Services/FMAC/FMAC.cpp +++ b/Src/HALAL/Services/FMAC/FMAC.cpp @@ -32,7 +32,7 @@ void MultiplierAccelerator::IIR_software_in_software_out_inscribe(uint16_t input } void MultiplierAccelerator::inscribe(){ - static constexpr auto fmac_dma_config {DMA::inscribe_stream()}; + DMA::inscribe_stream(); } void MultiplierAccelerator::start(){ From 9d2a930043c196e365f77ee699c9d49d3fe26ffc Mon Sep 17 00:00:00 2001 From: Jorge Date: Sun, 23 Nov 2025 09:44:06 +0100 Subject: [PATCH 012/109] feat: agregar funciones que comprueban si el stream y la instancias ya estan siendo utilizadas --- Inc/HALAL/Models/DMA/DMA.hpp | 49 +++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 904869bd7..ae865e6e3 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -17,7 +17,7 @@ class DMA { public: template - static void inscribe_stream(); + static void inscribe_stream(auto handle); static void start(); @@ -62,21 +62,45 @@ class DMA { static std::array inscribed_streams; static uint8_t inscribed_index; + static std::set used_peripherials; + static std::set used_streams; + + static bool is_stream_available(uintptr_t stream); + static bool is_peripherial_available(uintptr_t peripherial); + }; inline uint8_t DMA::inscribed_index{0}; +inline std::set DMA::used_peripherals{}; +inline std::set DMA::used_streams{}; template -void DMA::inscribe_stream() { +void DMA::inscribe_stream(auto handle) { std::size_t N = sizeof...(Streams); ErrorHandler(inscribed_index + N <= MAX_STREAMS, "Too many streams inscribed"); + + uintptr_t periph_addr = reinterpret_cast(Instance); + ErrorHandler(is_peripheral_available(periph_addr), + "Peripheral already in use"); + std::array streams = {(DMA_Stream_TypeDef*)Streams... }; + for (uint8_t i = 0; i < N; i++){ + uintptr_t stream_addr = reinterpret_cast(streams[i]); + ErrorHandler(is_stream_available(stream_addr), + "DMA stream already in use"); + } + // Verificación de cantidad según periférico if (is_adc(Instance)) ErrorHandler(N == 1, "ADC DMA must have exactly one stream"); else if (is_fmac(Instance)) ErrorHandler(N == 3, "FMAC DMA must have exactly three streams"); else ErrorHandler(N == 2, "Peripheral DMA must have exactly two streams (RX and TX)"); + for (uint8_t i = 0; i < N; i++){ + used_streams.insert(reinterpret_cast(streams[i])); + } + used_peripherals.insert(periph_addr); + for (uint8_t i = 0; i < N; i++){ DMA_HandleTypeDef dma_handle; dma_handle.Init.Request = get_Request(Instance, i); @@ -96,6 +120,13 @@ void DMA::inscribe_stream() { } } +bool DMA::is_stream_available(uintptr_t stream) { + return used_streams.find(stream) == used_streams.end(); +} + +bool DMA::is_peripheral_available(uintptr_t peripheral) { + return used_peripherals.find(peripheral) == used_peripherals.end(); +} bool DMA::is_one_of(auto Instance, auto... Bases) { return ((Instance == Bases) || ...); @@ -185,7 +216,7 @@ uint32_t DMA::get_Direction(auto Instance, uint8_t i) { uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { if (is_fmac(Instance) && i == 0){ - return DMA_PINC_ENABLE;xº + return DMA_PINC_ENABLE; } return DMA_PINC_DISABLE; } @@ -197,10 +228,10 @@ uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { } uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { - if (is_i2c()){ + if (is_i2c(Instance)){ return DMA_PDATAALIGN_WORD; } - else if (is_spi()){ + else if (is_spi(Instance)){ return DMA_PDATAALIGN_BYTE; } @@ -208,17 +239,17 @@ uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { } uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { - if (is_i2c()){ + if (is_i2c(Instance)){ return DMA_MDATAALIGN_WORD; } - else if (is_spi()){ + else if (is_spi(Instance)){ return DMA_MDATAALIGN_BYTE; } return DMA_MDATAALIGN_HALFWORD; } uint32_t DMA::get_Mode(auto Instance, uint8_t i) { - if (is_spi() || is_fmac(Instance)){ + if (is_spi(Instance) || is_fmac(Instance)){ return DMA_NORMAL; } @@ -240,7 +271,7 @@ uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { } uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { - if (is_spi()){ + if (is_spi(Instance)){ return DMA_FIFO_THRESHOLD_FULL; } return DMA_FIFO_THRESHOLD_HALFFULL; From 38fd08ba59d7744d5f47773733b2a3c6e789b412 Mon Sep 17 00:00:00 2001 From: Jorge Date: Mon, 24 Nov 2025 20:44:09 +0100 Subject: [PATCH 013/109] fuck constexpr, todo en runtime. feat: inscribe funciona, solo quedaria hacer el start --- Inc/HALAL/Models/DMA/DMA.hpp | 181 ++++++++++++++++++++++++----------- 1 file changed, 126 insertions(+), 55 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index ae865e6e3..ce21a18d1 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -13,24 +13,52 @@ #include #define MAX_STREAMS 16 - + class DMA { public: - template - static void inscribe_stream(auto handle); + static constexpr bool is_one_of(auto Instance, auto... Bases); - static void start(); + static constexpr bool is_spi(auto Instance); + + static constexpr bool is_i2c(auto Instance); - static bool is_one_of(auto Instance, auto... Bases); + static constexpr bool is_adc(auto Instance); - static bool is_spi(auto Instance); - - static bool is_i2c(auto Instance); + static constexpr bool is_fmac(auto Instance); - static bool is_adc(auto Instance); + template + requires ( + (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || + (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || + (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) + ) + static void inscribe_stream(auto handle); - static bool is_fmac(auto Instance); - + static void start(); + + private: + using PeriphVariant = std::variant< + SPI_HandleTypeDef*, + I2C_HandleTypeDef*, + ADC_HandleTypeDef*, + FMAC_HandleTypeDef* + >; + + template + using DmaLinkEntry = std::tuple< + PeriphHandle*, // (__HANDLE__) + DMA_HandleTypeDef*, // (__DMA_HANDLE__) + DMA_HandleTypeDef* PeriphHandle::*, // (__PPP_DMA_FIELD__) + IRQn_Type + >; + + template + static DmaLinkEntry make_dma_entry( + PeriphHandle* periph, + DMA_HandleTypeDef* dma, + DMA_HandleTypeDef* PeriphHandle::* member, + IRQn_Type irqn + ); static uint32_t get_Request(auto Instance, uint8_t i); @@ -57,94 +85,135 @@ class DMA { static uint32_t get_PeriphBurst(auto Instance, uint8_t i); static IRQn_Type get_irqn(auto stream); - - private: - static std::array inscribed_streams; - static uint8_t inscribed_index; - - static std::set used_peripherials; - static std::set used_streams; static bool is_stream_available(uintptr_t stream); + static bool is_peripherial_available(uintptr_t peripherial); + + static std::array, MAX_STREAMS> inscribed_streams; + static uint8_t inscribed_index; + static std::set used_peripherials; + static std::set used_streams; }; inline uint8_t DMA::inscribed_index{0}; -inline std::set DMA::used_peripherals{}; +inline std::set DMA::used_peripherials{}; inline std::set DMA::used_streams{}; +inline std::array, MAX_STREAMS> DMA::inscribed_streams{}; template +requires ( + (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || + (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || + (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) +) void DMA::inscribe_stream(auto handle) { - std::size_t N = sizeof...(Streams); - ErrorHandler(inscribed_index + N <= MAX_STREAMS, "Too many streams inscribed"); - + const std::size_t N = sizeof...(Streams); + if (inscribed_index + N > MAX_STREAMS){ + ErrorHandler("Too many streams inscribed"); + } + uintptr_t periph_addr = reinterpret_cast(Instance); - ErrorHandler(is_peripheral_available(periph_addr), - "Peripheral already in use"); - + if (!is_peripherial_available(periph_addr)){ + ErrorHandler("Peripheral already in use"); + } + std::array streams = {(DMA_Stream_TypeDef*)Streams... }; for (uint8_t i = 0; i < N; i++){ uintptr_t stream_addr = reinterpret_cast(streams[i]); - ErrorHandler(is_stream_available(stream_addr), - "DMA stream already in use"); + if (!is_stream_available(stream_addr)){ + ErrorHandler("DMA stream already in use"); + } } - // Verificación de cantidad según periférico - if (is_adc(Instance)) ErrorHandler(N == 1, "ADC DMA must have exactly one stream"); - else if (is_fmac(Instance)) ErrorHandler(N == 3, "FMAC DMA must have exactly three streams"); - else ErrorHandler(N == 2, "Peripheral DMA must have exactly two streams (RX and TX)"); - for (uint8_t i = 0; i < N; i++){ used_streams.insert(reinterpret_cast(streams[i])); } - used_peripherals.insert(periph_addr); + used_peripherials.insert(periph_addr); for (uint8_t i = 0; i < N; i++){ - DMA_HandleTypeDef dma_handle; - dma_handle.Init.Request = get_Request(Instance, i); - dma_handle.Init.Direction = get_Direction(Instance, i); - dma_handle.Init.PeriphInc = get_PeriphInc(Instance, i); - dma_handle.Init.MemInc = get_MemInc(Instance, i); - dma_handle.Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); - dma_handle.Init.MemDataAlignment = get_MemDataAlignment(Instance, i); - dma_handle.Init.Mode = get_Mode(Instance, i); - dma_handle.Init.Priority = get_Priority(Instance, i); - dma_handle.Init.FIFOMode = get_FIFOMode(Instance, i); - dma_handle.Init.FIFOThreshold = get_FIFOThreshold(Instance, i); - dma_handle.Init.MemBurst = get_MemBurst(Instance, i); - dma_handle.Init.PeriphBurst = get_PeriphBurst(Instance, i); - dma_handle.Instance = streams[i]; - inscribed_streams[inscribed_index++] = dma_handle; + DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; + dma->Instance = streams[i]; + dma->Init.Request = get_Request(Instance, i); + dma->Init.Direction = get_Direction(Instance, i); + dma->Init.PeriphInc = get_PeriphInc(Instance, i); + dma->Init.MemInc = get_MemInc(Instance, i); + dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); + dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); + dma->Init.Mode = get_Mode(Instance, i); + dma->Init.Priority = get_Priority(Instance, i); + dma->Init.FIFOMode = get_FIFOMode(Instance, i); + dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); + dma->Init.MemBurst = get_MemBurst(Instance, i); + dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); + IRQn_Type irq = get_irqn(streams[i]); + + if constexpr (is_spi(Instance)) { + auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + } + else if constexpr (is_i2c(Instance)) { + auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + } + else if constexpr (is_adc(Instance)) { + auto member = &ADC_HandleTypeDef::DMA_Handle; + inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + } + else if constexpr (is_fmac(Instance)) { + DMA_HandleTypeDef* FMAC_HandleTypeDef::* member; + if (i == 0) member = &FMAC_HandleTypeDef::hdmaPreload; + else if (i == 1) member = &FMAC_HandleTypeDef::hdmaIn; + else member = &FMAC_HandleTypeDef::hdmaOut; + inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + } + + inscribed_index++; } } +template +DMA::DmaLinkEntry DMA::make_dma_entry( + PeriphHandle* periph, + DMA_HandleTypeDef* dma, + DMA_HandleTypeDef* PeriphHandle::* member, + IRQn_Type irqn +){ + return std::tuple{ + periph, + dma, + member, + irqn + }; +} + bool DMA::is_stream_available(uintptr_t stream) { return used_streams.find(stream) == used_streams.end(); } -bool DMA::is_peripheral_available(uintptr_t peripheral) { - return used_peripherals.find(peripheral) == used_peripherals.end(); +bool DMA::is_peripherial_available(uintptr_t peripheral) { + return used_peripherials.find(peripheral) == used_peripherials.end(); } -bool DMA::is_one_of(auto Instance, auto... Bases) { +constexpr bool DMA::is_one_of(auto Instance, auto... Bases) { return ((Instance == Bases) || ...); } - bool DMA::is_spi(auto Instance) { +constexpr bool DMA::is_spi(auto Instance) { return is_one_of(Instance, SPI1, SPI2, SPI3, SPI4, SPI5); } - bool DMA::is_i2c(auto Instance) { +constexpr bool DMA::is_i2c(auto Instance) { return is_one_of(Instance, I2C1, I2C2, I2C3, I2C5); } - bool DMA::is_adc(auto Instance) { +constexpr bool DMA::is_adc(auto Instance) { return is_one_of(Instance, ADC1, ADC2, ADC3); } - bool DMA::is_fmac(auto Instance) { +constexpr bool DMA::is_fmac(auto Instance) { return Instance == FMAC; } @@ -201,6 +270,8 @@ uint32_t DMA::get_Request(auto Instance, uint8_t i) { return 0; } + + uint32_t DMA::get_Direction(auto Instance, uint8_t i) { if (is_fmac(Instance) && i == 0){ return DMA_MEMORY_TO_MEMORY; From 4d0e6be702a51329a6227bfb1549cd4d583c8ed0 Mon Sep 17 00:00:00 2001 From: Jorge Date: Tue, 25 Nov 2025 01:06:32 +0100 Subject: [PATCH 014/109] repartir entre archivos las funciones y hacer el start --- Inc/HALAL/Models/DMA/DMA.hpp | 277 ++++++++--------------------------- Src/HALAL/Models/DMA/DMA.cpp | 198 +++++++++++++++++++++---- 2 files changed, 236 insertions(+), 239 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index ce21a18d1..bc2b011f2 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -15,45 +15,21 @@ #define MAX_STREAMS 16 class DMA { - public: - static constexpr bool is_one_of(auto Instance, auto... Bases); - - static constexpr bool is_spi(auto Instance); - - static constexpr bool is_i2c(auto Instance); - - static constexpr bool is_adc(auto Instance); - - static constexpr bool is_fmac(auto Instance); - - template - requires ( - (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || - (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || - (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) - ) - static void inscribe_stream(auto handle); - - static void start(); - - private: - using PeriphVariant = std::variant< + using PeriphVariant = std::variant< SPI_HandleTypeDef*, I2C_HandleTypeDef*, ADC_HandleTypeDef*, FMAC_HandleTypeDef* >; + struct DmaLinkEntry{ + PeriphVariant periph; // (__HANDLE__) + DMA_HandleTypeDef* dma; // (__DMA_HANDLE__) + std::function linker; // (__PPP_DMA_FIELD__) + IRQn_Type irq; // (__IRQn_TYPE__) + }; template - using DmaLinkEntry = std::tuple< - PeriphHandle*, // (__HANDLE__) - DMA_HandleTypeDef*, // (__DMA_HANDLE__) - DMA_HandleTypeDef* PeriphHandle::*, // (__PPP_DMA_FIELD__) - IRQn_Type - >; - - template - static DmaLinkEntry make_dma_entry( + static DmaLinkEntry make_dma_entry( PeriphHandle* periph, DMA_HandleTypeDef* dma, DMA_HandleTypeDef* PeriphHandle::* member, @@ -90,25 +66,61 @@ class DMA { static bool is_peripherial_available(uintptr_t peripherial); - static std::array, MAX_STREAMS> inscribed_streams; + static std::array inscribed_streams; static uint8_t inscribed_index; static std::set used_peripherials; static std::set used_streams; + + public: + static constexpr bool is_one_of(auto Instance, auto... Bases); + + static constexpr bool is_spi(auto Instance); + + static constexpr bool is_i2c(auto Instance); + + static constexpr bool is_adc(auto Instance); + + static constexpr bool is_fmac(auto Instance); + + template + requires ( + (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || + (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || + (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) + ) + static void inscribe_stream(PeriphVariant handle); + + static void start(); }; -inline uint8_t DMA::inscribed_index{0}; -inline std::set DMA::used_peripherials{}; -inline std::set DMA::used_streams{}; -inline std::array, MAX_STREAMS> DMA::inscribed_streams{}; +constexpr bool DMA::is_one_of(auto Instance, auto... Bases) { + return ((Instance == Bases) || ...); +} + +constexpr bool DMA::is_spi(auto Instance) { + return is_one_of(Instance, SPI1, SPI2, SPI3, SPI4, SPI5); +} + +constexpr bool DMA::is_i2c(auto Instance) { + return is_one_of(Instance, I2C1, I2C2, I2C3, I2C5); +} + +constexpr bool DMA::is_adc(auto Instance) { + return is_one_of(Instance, ADC1, ADC2, ADC3); +} + +constexpr bool DMA::is_fmac(auto Instance) { + return Instance == FMAC; +} -template +template requires ( (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) ) -void DMA::inscribe_stream(auto handle) { +void DMA::inscribe_stream(PeriphVariant handle) { const std::size_t N = sizeof...(Streams); if (inscribed_index + N > MAX_STREAMS){ ErrorHandler("Too many streams inscribed"); @@ -151,23 +163,27 @@ void DMA::inscribe_stream(auto handle) { IRQn_Type irq = get_irqn(streams[i]); if constexpr (is_spi(Instance)) { + auto* spi_handle = std::get(handle); auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); } else if constexpr (is_i2c(Instance)) { + auto* i2c_handle = std::get(handle); auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); } else if constexpr (is_adc(Instance)) { + auto* adc_handle = std::get(handle); auto member = &ADC_HandleTypeDef::DMA_Handle; - inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); } else if constexpr (is_fmac(Instance)) { + auto* fmac_handle = std::get(handle); DMA_HandleTypeDef* FMAC_HandleTypeDef::* member; if (i == 0) member = &FMAC_HandleTypeDef::hdmaPreload; else if (i == 1) member = &FMAC_HandleTypeDef::hdmaIn; else member = &FMAC_HandleTypeDef::hdmaOut; - inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); } inscribed_index++; @@ -175,183 +191,20 @@ void DMA::inscribe_stream(auto handle) { } template -DMA::DmaLinkEntry DMA::make_dma_entry( +DMA::DmaLinkEntry DMA::make_dma_entry( PeriphHandle* periph, DMA_HandleTypeDef* dma, DMA_HandleTypeDef* PeriphHandle::* member, IRQn_Type irqn ){ - return std::tuple{ + return DmaLinkEntry{ periph, dma, - member, + [periph, member, dma](DMA_HandleTypeDef* d) { + periph->*member = d; + d->Parent = periph; + }, irqn }; } -bool DMA::is_stream_available(uintptr_t stream) { - return used_streams.find(stream) == used_streams.end(); -} - -bool DMA::is_peripherial_available(uintptr_t peripheral) { - return used_peripherials.find(peripheral) == used_peripherials.end(); -} - -constexpr bool DMA::is_one_of(auto Instance, auto... Bases) { - return ((Instance == Bases) || ...); -} - -constexpr bool DMA::is_spi(auto Instance) { - return is_one_of(Instance, SPI1, SPI2, SPI3, SPI4, SPI5); -} - -constexpr bool DMA::is_i2c(auto Instance) { - return is_one_of(Instance, I2C1, I2C2, I2C3, I2C5); -} - -constexpr bool DMA::is_adc(auto Instance) { - return is_one_of(Instance, ADC1, ADC2, ADC3); -} - -constexpr bool DMA::is_fmac(auto Instance) { - return Instance == FMAC; -} - - -IRQn_Type DMA::get_irqn(auto stream) { - if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; - else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; - else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; - else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; - else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; - else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; - else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; - else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; - - else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; - else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; - else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; - else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; - else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; - else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; - else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; - else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; - else ErrorHandler(); -} - -uint32_t DMA::get_Request(auto Instance, uint8_t i) { - if (Instance == ADC1) return DMA_REQUEST_ADC1; - if (Instance == ADC2) return DMA_REQUEST_ADC2; - if (Instance == ADC3) return DMA_REQUEST_ADC3; - - if (Instance == I2C1 && i == 0) return DMA_REQUEST_I2C1_RX; - if (Instance == I2C1 && i == 1) return DMA_REQUEST_I2C1_TX; - if (Instance == I2C2 && i == 0) return DMA_REQUEST_I2C2_RX; - if (Instance == I2C2 && i == 1) return DMA_REQUEST_I2C2_TX; - if (Instance == I2C3 && i == 0) return DMA_REQUEST_I2C3_RX; - if (Instance == I2C3 && i == 1) return DMA_REQUEST_I2C3_TX; - if (Instance == I2C5 && i == 0) return DMA_REQUEST_I2C5_RX; - if (Instance == I2C5 && i == 1) return DMA_REQUEST_I2C5_TX; - - if (Instance == SPI1 && i == 0) return DMA_REQUEST_SPI1_RX; - if (Instance == SPI1 && i == 1) return DMA_REQUEST_SPI1_TX; - if (Instance == SPI2 && i == 0) return DMA_REQUEST_SPI2_RX; - if (Instance == SPI2 && i == 1) return DMA_REQUEST_SPI2_TX; - if (Instance == SPI3 && i == 0) return DMA_REQUEST_SPI3_RX; - if (Instance == SPI3 && i == 1) return DMA_REQUEST_SPI3_TX; - if (Instance == SPI4 && i == 0) return DMA_REQUEST_SPI4_RX; - if (Instance == SPI4 && i == 1) return DMA_REQUEST_SPI4_TX; - if (Instance == SPI5 && i == 0) return DMA_REQUEST_SPI5_RX; - if (Instance == SPI5 && i == 1) return DMA_REQUEST_SPI5_TX; - - if (Instance == FMAC && i == 0) return DMA_REQUEST_MEM2MEM; - if (Instance == FMAC && i == 1) return DMA_REQUEST_FMAC_WRITE; - if (Instance == FMAC && i == 2) return DMA_REQUEST_FMAC_READ; - return 0; -} - - - -uint32_t DMA::get_Direction(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_MEMORY_TO_MEMORY; - } - else if ((is_i2c(Instance) && i == 1) || - (is_spi(Instance) && i == 1) || - (is_fmac(Instance) && i == 1)){ - return DMA_MEMORY_TO_PERIPH; - } - - return DMA_PERIPH_TO_MEMORY; -} - -uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_PINC_ENABLE; - } - return DMA_PINC_DISABLE; -} -uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_MINC_DISABLE; - } - return DMA_MINC_ENABLE; -} - -uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { - if (is_i2c(Instance)){ - return DMA_PDATAALIGN_WORD; - } - else if (is_spi(Instance)){ - return DMA_PDATAALIGN_BYTE; - } - - return DMA_PDATAALIGN_HALFWORD; -} - -uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { - if (is_i2c(Instance)){ - return DMA_MDATAALIGN_WORD; - } - else if (is_spi(Instance)){ - return DMA_MDATAALIGN_BYTE; - } - - return DMA_MDATAALIGN_HALFWORD; -} -uint32_t DMA::get_Mode(auto Instance, uint8_t i) { - if (is_spi(Instance) || is_fmac(Instance)){ - return DMA_NORMAL; - } - - return DMA_CIRCULAR; -} - - uint32_t DMA::get_Priority(auto Instance, uint8_t i) { - if (is_fmac(Instance)){ - return DMA_PRIORITY_HIGH; - } - - return DMA_PRIORITY_LOW; -} -uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { - if (is_fmac(Instance)){ - return DMA_FIFOMODE_ENABLE; - } - return DMA_FIFOMODE_DISABLE; -} - -uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { - if (is_spi(Instance)){ - return DMA_FIFO_THRESHOLD_FULL; - } - return DMA_FIFO_THRESHOLD_HALFFULL; -} - -uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { - return DMA_MBURST_SINGLE; -} - -uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { - return DMA_PBURST_SINGLE; -} \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index 05a23e066..b2266d0c4 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -1,27 +1,171 @@ -// #include "HALAL/Models/DMA/DMA.hpp" - -// void DMA::start() -// { -// __HAL_RCC_DMA1_CLK_ENABLE(); -// __HAL_RCC_DMA2_CLK_ENABLE(); - -// for (auto const &inst : instancias) { -// std::visit([](auto const &cfg) { -// for (size_t i = 0; i < cfg.handles.size(); ++i) { -// static DMA_HandleTypeDef dma_handle{}; -// dma_handle.Instance = cfg.streams[i]; -// dma_handle.Init = cfg.handles[i]; - -// if (HAL_DMA_Init(&dma_handle) != HAL_OK) { -// Error_Handler(); -// } - -// // Enlazar DMA con periférico -// __HAL_LINKDMA(cfg.instance, global_handle, dma_handle); - -// HAL_NVIC_SetPriority(cfg.irqn[i], 0, 0); -// HAL_NVIC_EnableIRQ(cfg.irqn[i]); -// } -// }, inst); -// } -// } +#include "HALAL/Models/DMA/DMA.hpp" + +inline uint8_t DMA::inscribed_index{0}; +inline std::set DMA::used_peripherials{}; +inline std::set DMA::used_streams{}; +inline std::array DMA::inscribed_streams{}; + +void DMA::start() { + for (uint8_t i = 0; i < inscribed_index; i++) { + auto& [periph, dma, linker, irq] = inscribed_streams[i]; + + // Inicializar DMA + if (HAL_DMA_Init(dma) != HAL_OK) { + ErrorHandler("DMA Init failed"); + } + + // Vincular DMA al periférico + linker(dma); + + // Configurar interrupción + HAL_NVIC_SetPriority(irq, 5, 0); + HAL_NVIC_EnableIRQ(irq); + } +} + +bool DMA::is_stream_available(uintptr_t stream) { + return used_streams.find(stream) == used_streams.end(); +} + +bool DMA::is_peripherial_available(uintptr_t peripheral) { + return used_peripherials.find(peripheral) == used_peripherials.end(); +} + + +IRQn_Type DMA::get_irqn(auto stream) { + if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; + else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; + else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; + else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; + else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; + else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; + else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; + else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; + + else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; + else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; + else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; + else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; + else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; + else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; + else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; + else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; + else ErrorHandler(); +} + +uint32_t DMA::get_Request(auto Instance, uint8_t i) { + if (Instance == ADC1) return DMA_REQUEST_ADC1; + if (Instance == ADC2) return DMA_REQUEST_ADC2; + if (Instance == ADC3) return DMA_REQUEST_ADC3; + + if (Instance == I2C1 && i == 0) return DMA_REQUEST_I2C1_RX; + if (Instance == I2C1 && i == 1) return DMA_REQUEST_I2C1_TX; + if (Instance == I2C2 && i == 0) return DMA_REQUEST_I2C2_RX; + if (Instance == I2C2 && i == 1) return DMA_REQUEST_I2C2_TX; + if (Instance == I2C3 && i == 0) return DMA_REQUEST_I2C3_RX; + if (Instance == I2C3 && i == 1) return DMA_REQUEST_I2C3_TX; + if (Instance == I2C5 && i == 0) return DMA_REQUEST_I2C5_RX; + if (Instance == I2C5 && i == 1) return DMA_REQUEST_I2C5_TX; + + if (Instance == SPI1 && i == 0) return DMA_REQUEST_SPI1_RX; + if (Instance == SPI1 && i == 1) return DMA_REQUEST_SPI1_TX; + if (Instance == SPI2 && i == 0) return DMA_REQUEST_SPI2_RX; + if (Instance == SPI2 && i == 1) return DMA_REQUEST_SPI2_TX; + if (Instance == SPI3 && i == 0) return DMA_REQUEST_SPI3_RX; + if (Instance == SPI3 && i == 1) return DMA_REQUEST_SPI3_TX; + if (Instance == SPI4 && i == 0) return DMA_REQUEST_SPI4_RX; + if (Instance == SPI4 && i == 1) return DMA_REQUEST_SPI4_TX; + if (Instance == SPI5 && i == 0) return DMA_REQUEST_SPI5_RX; + if (Instance == SPI5 && i == 1) return DMA_REQUEST_SPI5_TX; + + if (Instance == FMAC && i == 0) return DMA_REQUEST_MEM2MEM; + if (Instance == FMAC && i == 1) return DMA_REQUEST_FMAC_WRITE; + if (Instance == FMAC && i == 2) return DMA_REQUEST_FMAC_READ; + return 0; +} + + + +uint32_t DMA::get_Direction(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_MEMORY_TO_MEMORY; + } + else if ((is_i2c(Instance) && i == 1) || + (is_spi(Instance) && i == 1) || + (is_fmac(Instance) && i == 1)){ + return DMA_MEMORY_TO_PERIPH; + } + + return DMA_PERIPH_TO_MEMORY; +} + +uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_PINC_ENABLE; + } + return DMA_PINC_DISABLE; +} +uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_MINC_DISABLE; + } + return DMA_MINC_ENABLE; +} + +uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { + if (is_i2c(Instance)){ + return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes + } + else if (is_spi(Instance)){ + return DMA_PDATAALIGN_BYTE; + } + + return DMA_PDATAALIGN_HALFWORD; +} + +uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { + if (is_i2c(Instance)){ + return DMA_MDATAALIGN_WORD; + } + else if (is_spi(Instance)){ + return DMA_MDATAALIGN_BYTE; + } + + return DMA_MDATAALIGN_HALFWORD; +} +uint32_t DMA::get_Mode(auto Instance, uint8_t i) { + if (is_spi(Instance) || is_fmac(Instance)){ + return DMA_NORMAL; + } + + return DMA_CIRCULAR; +} + + uint32_t DMA::get_Priority(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ + return DMA_PRIORITY_HIGH; + } + + return DMA_PRIORITY_LOW; +} +uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ + return DMA_FIFOMODE_ENABLE; + } + return DMA_FIFOMODE_DISABLE; +} + +uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { + if (is_spi(Instance)){ + return DMA_FIFO_THRESHOLD_FULL; + } + return DMA_FIFO_THRESHOLD_HALFFULL; +} + +uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { + return DMA_MBURST_SINGLE; +} + +uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { + return DMA_PBURST_SINGLE; +} \ No newline at end of file From cca62c8991520f44ccf4ae3e3c4dfa20add1c4ab Mon Sep 17 00:00:00 2001 From: Jorge Date: Tue, 25 Nov 2025 16:36:50 +0100 Subject: [PATCH 015/109] feat: start completado, mejor estructura, todos los perifericos configurados --- Inc/HALAL/Models/DMA/DMA.hpp | 241 +++++++++++------- Src/HALAL/Models/DMA/DMA.cpp | 250 +++++++------------ Src/HALAL/Services/ADC/ADC.cpp | 3 +- Src/HALAL/Services/Communication/I2C/I2C.cpp | 2 +- Src/HALAL/Services/Communication/SPI/SPI.cpp | 2 +- Src/HALAL/Services/FMAC/FMAC.cpp | 2 +- 6 files changed, 252 insertions(+), 248 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index bc2b011f2..c75f05c69 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -11,6 +11,9 @@ #include "HALAL/Models/MPUManager/MPUManager.hpp" #include #include +#include +#include +#include #define MAX_STREAMS 16 @@ -64,12 +67,12 @@ class DMA { static bool is_stream_available(uintptr_t stream); - static bool is_peripherial_available(uintptr_t peripherial); + static bool is_peripherial_available(unsigned long peripherial); static std::array inscribed_streams; static uint8_t inscribed_index; - static std::set used_peripherials; + static std::set used_peripherials; static std::set used_streams; public: @@ -94,117 +97,177 @@ class DMA { static void start(); }; +inline uint8_t DMA::inscribed_index{0}; +inline std::set DMA::used_peripherials{}; +inline std::set DMA::used_streams{}; +inline std::array DMA::inscribed_streams{}; + constexpr bool DMA::is_one_of(auto Instance, auto... Bases) { return ((Instance == Bases) || ...); } constexpr bool DMA::is_spi(auto Instance) { - return is_one_of(Instance, SPI1, SPI2, SPI3, SPI4, SPI5); + return is_one_of(Instance, SPI1_BASE, SPI2_BASE, SPI3_BASE, SPI4_BASE, SPI5_BASE); } constexpr bool DMA::is_i2c(auto Instance) { - return is_one_of(Instance, I2C1, I2C2, I2C3, I2C5); + return is_one_of(Instance, I2C1_BASE, I2C2_BASE, I2C3_BASE, I2C5_BASE); } constexpr bool DMA::is_adc(auto Instance) { - return is_one_of(Instance, ADC1, ADC2, ADC3); + return is_one_of(Instance, ADC1_BASE, ADC2_BASE, ADC3_BASE); } constexpr bool DMA::is_fmac(auto Instance) { - return Instance == FMAC; + return Instance == FMAC_BASE; } -template -requires ( - (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || - (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || - (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) -) -void DMA::inscribe_stream(PeriphVariant handle) { - const std::size_t N = sizeof...(Streams); - if (inscribed_index + N > MAX_STREAMS){ - ErrorHandler("Too many streams inscribed"); - } - - uintptr_t periph_addr = reinterpret_cast(Instance); - if (!is_peripherial_available(periph_addr)){ - ErrorHandler("Peripheral already in use"); - } +bool DMA::is_stream_available(uintptr_t stream) { + return used_streams.find(stream) == used_streams.end(); +} + +bool DMA::is_peripherial_available(unsigned long peripheral) { + return used_peripherials.find(peripheral) == used_peripherials.end(); +} + + +IRQn_Type DMA::get_irqn(auto stream) { + if (stream == DMA1_Stream0_BASE) return DMA1_Stream0_IRQn; + else if (stream == DMA1_Stream1_BASE) return DMA1_Stream1_IRQn; + else if (stream == DMA1_Stream2_BASE) return DMA1_Stream2_IRQn; + else if (stream == DMA1_Stream3_BASE) return DMA1_Stream3_IRQn; + else if (stream == DMA1_Stream4_BASE) return DMA1_Stream4_IRQn; + else if (stream == DMA1_Stream5_BASE) return DMA1_Stream5_IRQn; + else if (stream == DMA1_Stream6_BASE) return DMA1_Stream6_IRQn; + else if (stream == DMA1_Stream7_BASE) return DMA1_Stream7_IRQn; + + else if (stream == DMA2_Stream0_BASE) return DMA2_Stream0_IRQn; + else if (stream == DMA2_Stream1_BASE) return DMA2_Stream1_IRQn; + else if (stream == DMA2_Stream2_BASE) return DMA2_Stream2_IRQn; + else if (stream == DMA2_Stream3_BASE) return DMA2_Stream3_IRQn; + else if (stream == DMA2_Stream4_BASE) return DMA2_Stream4_IRQn; + else if (stream == DMA2_Stream5_BASE) return DMA2_Stream5_IRQn; + else if (stream == DMA2_Stream6_BASE) return DMA2_Stream6_IRQn; + else if (stream == DMA2_Stream7_BASE) return DMA2_Stream7_IRQn; + else ErrorHandler("Unknown DMA stream"); + return DMA1_Stream0_IRQn; // Nunca se alcanza +} + +uint32_t DMA::get_Request(auto Instance, uint8_t i) { + if (Instance == ADC1_BASE) return DMA_REQUEST_ADC1; + if (Instance == ADC2_BASE) return DMA_REQUEST_ADC2; + if (Instance == ADC3_BASE) return DMA_REQUEST_ADC3; + + if (Instance == I2C1_BASE && i == 0) return DMA_REQUEST_I2C1_RX; + if (Instance == I2C1_BASE && i == 1) return DMA_REQUEST_I2C1_TX; + if (Instance == I2C2_BASE && i == 0) return DMA_REQUEST_I2C2_RX; + if (Instance == I2C2_BASE && i == 1) return DMA_REQUEST_I2C2_TX; + if (Instance == I2C3_BASE && i == 0) return DMA_REQUEST_I2C3_RX; + if (Instance == I2C3_BASE && i == 1) return DMA_REQUEST_I2C3_TX; + if (Instance == I2C5_BASE && i == 0) return DMA_REQUEST_I2C5_RX; + if (Instance == I2C5_BASE && i == 1) return DMA_REQUEST_I2C5_TX; + + if (Instance == SPI1_BASE && i == 0) return DMA_REQUEST_SPI1_RX; + if (Instance == SPI1_BASE && i == 1) return DMA_REQUEST_SPI1_TX; + if (Instance == SPI2_BASE && i == 0) return DMA_REQUEST_SPI2_RX; + if (Instance == SPI2_BASE && i == 1) return DMA_REQUEST_SPI2_TX; + if (Instance == SPI3_BASE && i == 0) return DMA_REQUEST_SPI3_RX; + if (Instance == SPI3_BASE && i == 1) return DMA_REQUEST_SPI3_TX; + if (Instance == SPI4_BASE && i == 0) return DMA_REQUEST_SPI4_RX; + if (Instance == SPI4_BASE && i == 1) return DMA_REQUEST_SPI4_TX; + if (Instance == SPI5_BASE && i == 0) return DMA_REQUEST_SPI5_RX; + if (Instance == SPI5_BASE && i == 1) return DMA_REQUEST_SPI5_TX; - std::array streams = {(DMA_Stream_TypeDef*)Streams... }; + if (Instance == FMAC_BASE && i == 0) return DMA_REQUEST_MEM2MEM; + if (Instance == FMAC_BASE && i == 1) return DMA_REQUEST_FMAC_WRITE; + if (Instance == FMAC_BASE && i == 2) return DMA_REQUEST_FMAC_READ; + + ErrorHandler("Invalid DMA request configuration"); + return 0; +} + + - for (uint8_t i = 0; i < N; i++){ - uintptr_t stream_addr = reinterpret_cast(streams[i]); - if (!is_stream_available(stream_addr)){ - ErrorHandler("DMA stream already in use"); +uint32_t DMA::get_Direction(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_MEMORY_TO_MEMORY; } + else if ((is_i2c(Instance) && i == 1) || + (is_spi(Instance) && i == 1) || + (is_fmac(Instance) && i == 1)){ + return DMA_MEMORY_TO_PERIPH; + } + + return DMA_PERIPH_TO_MEMORY; +} + +uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_PINC_ENABLE; + } + return DMA_PINC_DISABLE; +} +uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_MINC_DISABLE; } + return DMA_MINC_ENABLE; +} - for (uint8_t i = 0; i < N; i++){ - used_streams.insert(reinterpret_cast(streams[i])); +uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { + if (is_i2c(Instance)){ + return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes } - used_peripherials.insert(periph_addr); - - for (uint8_t i = 0; i < N; i++){ - DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; - dma->Instance = streams[i]; - dma->Init.Request = get_Request(Instance, i); - dma->Init.Direction = get_Direction(Instance, i); - dma->Init.PeriphInc = get_PeriphInc(Instance, i); - dma->Init.MemInc = get_MemInc(Instance, i); - dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); - dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); - dma->Init.Mode = get_Mode(Instance, i); - dma->Init.Priority = get_Priority(Instance, i); - dma->Init.FIFOMode = get_FIFOMode(Instance, i); - dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); - dma->Init.MemBurst = get_MemBurst(Instance, i); - dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); - IRQn_Type irq = get_irqn(streams[i]); - - if constexpr (is_spi(Instance)) { - auto* spi_handle = std::get(handle); - auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); - } - else if constexpr (is_i2c(Instance)) { - auto* i2c_handle = std::get(handle); - auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); - } - else if constexpr (is_adc(Instance)) { - auto* adc_handle = std::get(handle); - auto member = &ADC_HandleTypeDef::DMA_Handle; - inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); - } - else if constexpr (is_fmac(Instance)) { - auto* fmac_handle = std::get(handle); - DMA_HandleTypeDef* FMAC_HandleTypeDef::* member; - if (i == 0) member = &FMAC_HandleTypeDef::hdmaPreload; - else if (i == 1) member = &FMAC_HandleTypeDef::hdmaIn; - else member = &FMAC_HandleTypeDef::hdmaOut; - inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); - } - - inscribed_index++; + else if (is_spi(Instance)){ + return DMA_PDATAALIGN_BYTE; + } + + return DMA_PDATAALIGN_HALFWORD; +} + +uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { + if (is_i2c(Instance)){ + return DMA_MDATAALIGN_WORD; + } + else if (is_spi(Instance)){ + return DMA_MDATAALIGN_BYTE; + } + + return DMA_MDATAALIGN_HALFWORD; +} +uint32_t DMA::get_Mode(auto Instance, uint8_t i) { + if (is_spi(Instance) || is_fmac(Instance)){ + return DMA_NORMAL; + } + + return DMA_CIRCULAR; +} + + uint32_t DMA::get_Priority(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ + return DMA_PRIORITY_HIGH; + } + + return DMA_PRIORITY_LOW; +} +uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ + return DMA_FIFOMODE_ENABLE; + } + return DMA_FIFOMODE_DISABLE; +} + +uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { + if (is_spi(Instance)){ + return DMA_FIFO_THRESHOLD_FULL; } + return DMA_FIFO_THRESHOLD_HALFFULL; } -template -DMA::DmaLinkEntry DMA::make_dma_entry( - PeriphHandle* periph, - DMA_HandleTypeDef* dma, - DMA_HandleTypeDef* PeriphHandle::* member, - IRQn_Type irqn -){ - return DmaLinkEntry{ - periph, - dma, - [periph, member, dma](DMA_HandleTypeDef* d) { - periph->*member = d; - d->Parent = periph; - }, - irqn - }; +uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { + return DMA_MBURST_SINGLE; } +uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { + return DMA_PBURST_SINGLE; +} \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index b2266d0c4..f91f455fe 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -1,171 +1,111 @@ #include "HALAL/Models/DMA/DMA.hpp" -inline uint8_t DMA::inscribed_index{0}; -inline std::set DMA::used_peripherials{}; -inline std::set DMA::used_streams{}; -inline std::array DMA::inscribed_streams{}; +template +DMA::DmaLinkEntry DMA::make_dma_entry( + PeriphHandle* periph, + DMA_HandleTypeDef* dma, + DMA_HandleTypeDef* PeriphHandle::* member, + IRQn_Type irqn +){ + return DmaLinkEntry{ + periph, + dma, + [periph, member](DMA_HandleTypeDef* d) { + periph->*member = d; + d->Parent = periph; + }, + irqn + }; +} + +template +requires ( + (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || + (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || + (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) +) +void DMA::inscribe_stream(PeriphVariant handle) { + const std::size_t N = sizeof...(Streams); + if (inscribed_index + N > MAX_STREAMS){ + ErrorHandler("Too many streams inscribed"); + } + + unsigned long periph_addr = reinterpret_cast(Instance); + if (!is_peripherial_available(periph_addr)){ + ErrorHandler("Peripheral already in use"); + } + + std::array streams = {(DMA_Stream_TypeDef*)Streams... }; + + for (uint8_t i = 0; i < N; i++){ + uintptr_t stream_addr = reinterpret_cast(streams[i]); + if (!is_stream_available(stream_addr)){ + ErrorHandler("DMA stream already in use"); + } + } + + for (uint8_t i = 0; i < N; i++){ + used_streams.insert(reinterpret_cast(streams[i])); + } + used_peripherials.insert(periph_addr); + + for (uint8_t i = 0; i < N; i++){ + DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; + dma->Instance = streams[i]; + dma->Init.Request = get_Request(Instance, i); + dma->Init.Direction = get_Direction(Instance, i); + dma->Init.PeriphInc = get_PeriphInc(Instance, i); + dma->Init.MemInc = get_MemInc(Instance, i); + dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); + dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); + dma->Init.Mode = get_Mode(Instance, i); + dma->Init.Priority = get_Priority(Instance, i); + dma->Init.FIFOMode = get_FIFOMode(Instance, i); + dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); + dma->Init.MemBurst = get_MemBurst(Instance, i); + dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); + IRQn_Type irq = get_irqn(streams[i]); + + if constexpr (is_spi(Instance)) { + auto* spi_handle = std::get(handle); + auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); + } + else if constexpr (is_i2c(Instance)) { + auto* i2c_handle = std::get(handle); + auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); + } + else if constexpr (is_adc(Instance)) { + auto* adc_handle = std::get(handle); + auto member = &ADC_HandleTypeDef::DMA_Handle; + inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); + } + else if constexpr (is_fmac(Instance)) { + auto* fmac_handle = std::get(handle); + auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : + (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : + &FMAC_HandleTypeDef::hdmaOut; + inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); + } + + inscribed_index++; + } +} void DMA::start() { + __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); for (uint8_t i = 0; i < inscribed_index; i++) { auto& [periph, dma, linker, irq] = inscribed_streams[i]; - // Inicializar DMA if (HAL_DMA_Init(dma) != HAL_OK) { ErrorHandler("DMA Init failed"); } - // Vincular DMA al periférico linker(dma); - // Configurar interrupción - HAL_NVIC_SetPriority(irq, 5, 0); + HAL_NVIC_SetPriority(irq, 0, 0); HAL_NVIC_EnableIRQ(irq); } } - -bool DMA::is_stream_available(uintptr_t stream) { - return used_streams.find(stream) == used_streams.end(); -} - -bool DMA::is_peripherial_available(uintptr_t peripheral) { - return used_peripherials.find(peripheral) == used_peripherials.end(); -} - - -IRQn_Type DMA::get_irqn(auto stream) { - if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; - else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; - else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; - else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; - else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; - else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; - else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; - else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; - - else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; - else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; - else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; - else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; - else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; - else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; - else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; - else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; - else ErrorHandler(); -} - -uint32_t DMA::get_Request(auto Instance, uint8_t i) { - if (Instance == ADC1) return DMA_REQUEST_ADC1; - if (Instance == ADC2) return DMA_REQUEST_ADC2; - if (Instance == ADC3) return DMA_REQUEST_ADC3; - - if (Instance == I2C1 && i == 0) return DMA_REQUEST_I2C1_RX; - if (Instance == I2C1 && i == 1) return DMA_REQUEST_I2C1_TX; - if (Instance == I2C2 && i == 0) return DMA_REQUEST_I2C2_RX; - if (Instance == I2C2 && i == 1) return DMA_REQUEST_I2C2_TX; - if (Instance == I2C3 && i == 0) return DMA_REQUEST_I2C3_RX; - if (Instance == I2C3 && i == 1) return DMA_REQUEST_I2C3_TX; - if (Instance == I2C5 && i == 0) return DMA_REQUEST_I2C5_RX; - if (Instance == I2C5 && i == 1) return DMA_REQUEST_I2C5_TX; - - if (Instance == SPI1 && i == 0) return DMA_REQUEST_SPI1_RX; - if (Instance == SPI1 && i == 1) return DMA_REQUEST_SPI1_TX; - if (Instance == SPI2 && i == 0) return DMA_REQUEST_SPI2_RX; - if (Instance == SPI2 && i == 1) return DMA_REQUEST_SPI2_TX; - if (Instance == SPI3 && i == 0) return DMA_REQUEST_SPI3_RX; - if (Instance == SPI3 && i == 1) return DMA_REQUEST_SPI3_TX; - if (Instance == SPI4 && i == 0) return DMA_REQUEST_SPI4_RX; - if (Instance == SPI4 && i == 1) return DMA_REQUEST_SPI4_TX; - if (Instance == SPI5 && i == 0) return DMA_REQUEST_SPI5_RX; - if (Instance == SPI5 && i == 1) return DMA_REQUEST_SPI5_TX; - - if (Instance == FMAC && i == 0) return DMA_REQUEST_MEM2MEM; - if (Instance == FMAC && i == 1) return DMA_REQUEST_FMAC_WRITE; - if (Instance == FMAC && i == 2) return DMA_REQUEST_FMAC_READ; - return 0; -} - - - -uint32_t DMA::get_Direction(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_MEMORY_TO_MEMORY; - } - else if ((is_i2c(Instance) && i == 1) || - (is_spi(Instance) && i == 1) || - (is_fmac(Instance) && i == 1)){ - return DMA_MEMORY_TO_PERIPH; - } - - return DMA_PERIPH_TO_MEMORY; -} - -uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_PINC_ENABLE; - } - return DMA_PINC_DISABLE; -} -uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_MINC_DISABLE; - } - return DMA_MINC_ENABLE; -} - -uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { - if (is_i2c(Instance)){ - return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes - } - else if (is_spi(Instance)){ - return DMA_PDATAALIGN_BYTE; - } - - return DMA_PDATAALIGN_HALFWORD; -} - -uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { - if (is_i2c(Instance)){ - return DMA_MDATAALIGN_WORD; - } - else if (is_spi(Instance)){ - return DMA_MDATAALIGN_BYTE; - } - - return DMA_MDATAALIGN_HALFWORD; -} -uint32_t DMA::get_Mode(auto Instance, uint8_t i) { - if (is_spi(Instance) || is_fmac(Instance)){ - return DMA_NORMAL; - } - - return DMA_CIRCULAR; -} - - uint32_t DMA::get_Priority(auto Instance, uint8_t i) { - if (is_fmac(Instance)){ - return DMA_PRIORITY_HIGH; - } - - return DMA_PRIORITY_LOW; -} -uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { - if (is_fmac(Instance)){ - return DMA_FIFOMODE_ENABLE; - } - return DMA_FIFOMODE_DISABLE; -} - -uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { - if (is_spi(Instance)){ - return DMA_FIFO_THRESHOLD_FULL; - } - return DMA_FIFO_THRESHOLD_HALFFULL; -} - -uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { - return DMA_MBURST_SINGLE; -} - -uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { - return DMA_PBURST_SINGLE; -} \ No newline at end of file diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index 2ee1b7fbc..c637354f5 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -42,7 +42,8 @@ uint8_t ADC::inscribe(Pin pin) { InitData& init_data = active_instances[id_counter].peripheral->init_data; - static constexpr auto dma_adc1_config {DMA::inscribe_stream()}; + + // DMA::inscribe_stream(); active_instances[id_counter].rank = init_data.channels.size(); init_data.channels.push_back(active_instances[id_counter].channel); return id_counter++; diff --git a/Src/HALAL/Services/Communication/I2C/I2C.cpp b/Src/HALAL/Services/Communication/I2C/I2C.cpp index 25ba233ac..758918905 100644 --- a/Src/HALAL/Services/Communication/I2C/I2C.cpp +++ b/Src/HALAL/Services/Communication/I2C/I2C.cpp @@ -23,7 +23,7 @@ uint8_t I2C::inscribe(I2C::Peripheral &i2c, uint8_t address) { Pin::inscribe(i2c_instance->SCL, ALTERNATIVE); Pin::inscribe(i2c_instance->SDA, ALTERNATIVE); - static constexpr auto dma_i2c1_config {DMA::inscribe_stream()}; + DMA::inscribe_stream(i2c_instance->hi2c); uint8_t id = I2C::id_counter++; diff --git a/Src/HALAL/Services/Communication/SPI/SPI.cpp b/Src/HALAL/Services/Communication/SPI/SPI.cpp index f9f9628f6..172cba4e7 100644 --- a/Src/HALAL/Services/Communication/SPI/SPI.cpp +++ b/Src/HALAL/Services/Communication/SPI/SPI.cpp @@ -56,7 +56,7 @@ uint8_t SPI::inscribe(SPI::Peripheral& spi) { uint8_t id = SPI::id_counter++; if (spi_instance->use_DMA) { - static constexpr auto dma_spi1_config {DMA::inscribe_stream()}; + DMA::inscribe_stream(spi_instance->hspi); } SPI::registered_spi[id] = spi_instance; SPI::registered_spi_by_handler[spi_instance->hspi] = spi_instance; diff --git a/Src/HALAL/Services/FMAC/FMAC.cpp b/Src/HALAL/Services/FMAC/FMAC.cpp index 546de926f..8ed6eafd1 100644 --- a/Src/HALAL/Services/FMAC/FMAC.cpp +++ b/Src/HALAL/Services/FMAC/FMAC.cpp @@ -32,7 +32,7 @@ void MultiplierAccelerator::IIR_software_in_software_out_inscribe(uint16_t input } void MultiplierAccelerator::inscribe(){ - DMA::inscribe_stream(); + DMA::inscribe_stream(Instance.hfmac); } void MultiplierAccelerator::start(){ From 5212ce91d1c8b1f1ab07e207b1cf2bcf4c67fa65 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Sun, 30 Nov 2025 00:43:07 +0100 Subject: [PATCH 016/109] hacer funciones inline para que pueda compilar --- Inc/HALAL/Models/DMA/DMA.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index c75f05c69..1138838e6 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -122,11 +122,11 @@ constexpr bool DMA::is_fmac(auto Instance) { return Instance == FMAC_BASE; } -bool DMA::is_stream_available(uintptr_t stream) { +inline bool DMA::is_stream_available(uintptr_t stream) { return used_streams.find(stream) == used_streams.end(); } -bool DMA::is_peripherial_available(unsigned long peripheral) { +inline bool DMA::is_peripherial_available(unsigned long peripheral) { return used_peripherials.find(peripheral) == used_peripherials.end(); } From 9655dea4b553c3ee44656e313868d03d053a3fe7 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Sun, 30 Nov 2025 10:36:57 +0100 Subject: [PATCH 017/109] adc inscribe_dma now working, moved dma implementations from cpp to hpp, fixed irqn function, and minor changes to inscribe_dma for legibility --- Inc/HALAL/Models/DMA/DMA.hpp | 129 ++++++++++++++++++++++++++++----- Src/HALAL/Models/DMA/DMA.cpp | 95 +----------------------- Src/HALAL/Services/ADC/ADC.cpp | 2 +- 3 files changed, 113 insertions(+), 113 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 1138838e6..3a37999d0 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -132,23 +132,23 @@ inline bool DMA::is_peripherial_available(unsigned long peripheral) { IRQn_Type DMA::get_irqn(auto stream) { - if (stream == DMA1_Stream0_BASE) return DMA1_Stream0_IRQn; - else if (stream == DMA1_Stream1_BASE) return DMA1_Stream1_IRQn; - else if (stream == DMA1_Stream2_BASE) return DMA1_Stream2_IRQn; - else if (stream == DMA1_Stream3_BASE) return DMA1_Stream3_IRQn; - else if (stream == DMA1_Stream4_BASE) return DMA1_Stream4_IRQn; - else if (stream == DMA1_Stream5_BASE) return DMA1_Stream5_IRQn; - else if (stream == DMA1_Stream6_BASE) return DMA1_Stream6_IRQn; - else if (stream == DMA1_Stream7_BASE) return DMA1_Stream7_IRQn; - - else if (stream == DMA2_Stream0_BASE) return DMA2_Stream0_IRQn; - else if (stream == DMA2_Stream1_BASE) return DMA2_Stream1_IRQn; - else if (stream == DMA2_Stream2_BASE) return DMA2_Stream2_IRQn; - else if (stream == DMA2_Stream3_BASE) return DMA2_Stream3_IRQn; - else if (stream == DMA2_Stream4_BASE) return DMA2_Stream4_IRQn; - else if (stream == DMA2_Stream5_BASE) return DMA2_Stream5_IRQn; - else if (stream == DMA2_Stream6_BASE) return DMA2_Stream6_IRQn; - else if (stream == DMA2_Stream7_BASE) return DMA2_Stream7_IRQn; + if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; + else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; + else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; + else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; + else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; + else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; + else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; + else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; + + else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; + else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; + else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; + else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; + else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; + else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; + else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; + else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; else ErrorHandler("Unknown DMA stream"); return DMA1_Stream0_IRQn; // Nunca se alcanza } @@ -270,4 +270,97 @@ uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { return DMA_PBURST_SINGLE; -} \ No newline at end of file +} + +template +DMA::DmaLinkEntry DMA::make_dma_entry( + PeriphHandle* periph, + DMA_HandleTypeDef* dma, + DMA_HandleTypeDef* PeriphHandle::* member, + IRQn_Type irqn +){ + return DmaLinkEntry{ + periph, + dma, + [periph, member](DMA_HandleTypeDef* d) { + periph->*member = d; + d->Parent = periph; + }, + irqn + }; +} + +template +requires ( + (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || + (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || + (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) +) +void DMA::inscribe_stream(PeriphVariant handle) { + const std::size_t N = sizeof...(Streams); + if (inscribed_index + N > MAX_STREAMS){ + ErrorHandler("Too many streams inscribed"); + } + + unsigned long periph_addr = reinterpret_cast(Instance); + if (!is_peripherial_available(periph_addr)){ + ErrorHandler("Peripheral already in use"); + } + used_peripherials.insert(periph_addr); + + std::array streams = {(DMA_Stream_TypeDef*)Streams... }; + + for (uint8_t i = 0; i < N; i++){ + uintptr_t stream_addr = reinterpret_cast(streams[i]); + if (!is_stream_available(stream_addr)){ + ErrorHandler("DMA stream already in use"); + used_streams.insert(stream_addr); + } + } + + + for (uint8_t i = 0; i < N; i++){ + DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; + dma->Instance = streams[i]; + dma->Init.Request = get_Request(Instance, i); + dma->Init.Direction = get_Direction(Instance, i); + dma->Init.PeriphInc = get_PeriphInc(Instance, i); + dma->Init.MemInc = get_MemInc(Instance, i); + dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); + dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); + dma->Init.Mode = get_Mode(Instance, i); + dma->Init.Priority = get_Priority(Instance, i); + dma->Init.FIFOMode = get_FIFOMode(Instance, i); + dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); + dma->Init.MemBurst = get_MemBurst(Instance, i); + dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); + IRQn_Type irq = get_irqn(streams[i]); + + if constexpr (is_spi(Instance)) { + auto* spi_handle = std::get(handle); + auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); + } + else if constexpr (is_i2c(Instance)) { + auto* i2c_handle = std::get(handle); + auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); + } + else if constexpr (is_adc(Instance)) { + auto* adc_handle = std::get(handle); + auto member = &ADC_HandleTypeDef::DMA_Handle; + inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); + } + else if constexpr (is_fmac(Instance)) { + auto* fmac_handle = std::get(handle); + auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : + (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : + &FMAC_HandleTypeDef::hdmaOut; + inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); + } + + inscribed_index++; + } +} + + diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index f91f455fe..db3768088 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -1,98 +1,5 @@ #include "HALAL/Models/DMA/DMA.hpp" -template -DMA::DmaLinkEntry DMA::make_dma_entry( - PeriphHandle* periph, - DMA_HandleTypeDef* dma, - DMA_HandleTypeDef* PeriphHandle::* member, - IRQn_Type irqn -){ - return DmaLinkEntry{ - periph, - dma, - [periph, member](DMA_HandleTypeDef* d) { - periph->*member = d; - d->Parent = periph; - }, - irqn - }; -} - -template -requires ( - (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || - (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || - (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) -) -void DMA::inscribe_stream(PeriphVariant handle) { - const std::size_t N = sizeof...(Streams); - if (inscribed_index + N > MAX_STREAMS){ - ErrorHandler("Too many streams inscribed"); - } - - unsigned long periph_addr = reinterpret_cast(Instance); - if (!is_peripherial_available(periph_addr)){ - ErrorHandler("Peripheral already in use"); - } - - std::array streams = {(DMA_Stream_TypeDef*)Streams... }; - - for (uint8_t i = 0; i < N; i++){ - uintptr_t stream_addr = reinterpret_cast(streams[i]); - if (!is_stream_available(stream_addr)){ - ErrorHandler("DMA stream already in use"); - } - } - - for (uint8_t i = 0; i < N; i++){ - used_streams.insert(reinterpret_cast(streams[i])); - } - used_peripherials.insert(periph_addr); - - for (uint8_t i = 0; i < N; i++){ - DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; - dma->Instance = streams[i]; - dma->Init.Request = get_Request(Instance, i); - dma->Init.Direction = get_Direction(Instance, i); - dma->Init.PeriphInc = get_PeriphInc(Instance, i); - dma->Init.MemInc = get_MemInc(Instance, i); - dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); - dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); - dma->Init.Mode = get_Mode(Instance, i); - dma->Init.Priority = get_Priority(Instance, i); - dma->Init.FIFOMode = get_FIFOMode(Instance, i); - dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); - dma->Init.MemBurst = get_MemBurst(Instance, i); - dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); - IRQn_Type irq = get_irqn(streams[i]); - - if constexpr (is_spi(Instance)) { - auto* spi_handle = std::get(handle); - auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); - } - else if constexpr (is_i2c(Instance)) { - auto* i2c_handle = std::get(handle); - auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); - } - else if constexpr (is_adc(Instance)) { - auto* adc_handle = std::get(handle); - auto member = &ADC_HandleTypeDef::DMA_Handle; - inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); - } - else if constexpr (is_fmac(Instance)) { - auto* fmac_handle = std::get(handle); - auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : - (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : - &FMAC_HandleTypeDef::hdmaOut; - inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); - } - - inscribed_index++; - } -} - void DMA::start() { __HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_DMA2_CLK_ENABLE(); @@ -108,4 +15,4 @@ void DMA::start() { HAL_NVIC_SetPriority(irq, 0, 0); HAL_NVIC_EnableIRQ(irq); } -} +} \ No newline at end of file diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index c637354f5..f44730324 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -43,7 +43,7 @@ uint8_t ADC::inscribe(Pin pin) { InitData& init_data = active_instances[id_counter].peripheral->init_data; - // DMA::inscribe_stream(); + DMA::inscribe_stream(active_instances[id_counter].peripheral->handle); active_instances[id_counter].rank = init_data.channels.size(); init_data.channels.push_back(active_instances[id_counter].channel); return id_counter++; From e2af8c5ddb515593d8ecf4d3475cf5b9b4ad7be7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20S=C3=A1ez?= Date: Sun, 30 Nov 2025 13:57:40 +0100 Subject: [PATCH 018/109] Initial structure --- .vscode/settings.json | 2 +- CMakeLists.txt | 6 +- Inc/HALAL/HALAL.hpp | 3 + Inc/HALAL/Models/GPIO.hpp | 223 ++++++++++++++++++++++++++++++++++++++ Inc/HALAL/Models/Pin.hpp | 7 ++ Inc/ST-LIB.hpp | 88 ++++++++++++++- Inc/stm32h7xx_hal_conf.h | 2 +- 7 files changed, 325 insertions(+), 6 deletions(-) create mode 100644 Inc/HALAL/Models/GPIO.hpp create mode 100644 Inc/HALAL/Models/Pin.hpp diff --git a/.vscode/settings.json b/.vscode/settings.json index d161326bb..b2abce05a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { - "C_Cpp.default.cppStandard": "c++20", + "C_Cpp.default.cppStandard": "c++23", "C_Cpp.default.cStandard": "c17", "C_Cpp.clang_format_fallbackStyle": "{BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 80}", "C_Cpp.formatting": "clangFormat", diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ba062c27..7d35f2ef8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -263,7 +263,7 @@ target_compile_options(${STLIB_LIBRARY} PRIVATE $<$:-specs=nosys.specs> $<$:-ffunction-sections> $<$:-fdata-sections> - $<$:-fno-exceptions> + # $<$:-fno-exceptions> -Wno-psabi @@ -272,8 +272,8 @@ target_compile_options(${STLIB_LIBRARY} PRIVATE $<$:-Wall> $<$:-Wpedantic> $<$:-Werror> - $<$:-Wno-gnu-zero-variadic-macro-arguments> - $<$:-Wno-inconsistent-missing-override> + # $<$:-Wno-gnu-zero-variadic-macro-arguments> + # $<$:-Wno-inconsistent-missing-override> $<$:-fno-use-cxa-atexit> $<$:-fno-rtti> $<$:-Wno-address-of-packed-member> diff --git a/Inc/HALAL/HALAL.hpp b/Inc/HALAL/HALAL.hpp index d1c0438ce..316c9605a 100644 --- a/Inc/HALAL/HALAL.hpp +++ b/Inc/HALAL/HALAL.hpp @@ -1,5 +1,8 @@ #pragma once +#include "HALAL/Models/GPIO.hpp" +#include "HALAL/Models/Pin.hpp" + #include "HALAL/Models/HALconfig/HALconfig.hpp" #include "HALAL/Models/DMA/DMA.hpp" diff --git a/Inc/HALAL/Models/GPIO.hpp b/Inc/HALAL/Models/GPIO.hpp new file mode 100644 index 000000000..e9bfafe5a --- /dev/null +++ b/Inc/HALAL/Models/GPIO.hpp @@ -0,0 +1,223 @@ +#pragma once + +#include "stm32h7xx_hal.h" +#include +#include +#include + +using std::array; +using std::size_t; +using std::span; +using std::tuple; + +namespace ST_LIB { +struct GPIODomain { + enum class OperationMode : uint8_t { + INPUT, + OUTPUT, + ANALOG, + EXTERNAL_INTERRUPT_RISING, + EXTERNAL_INTERRUPT_FALLING, + EXTERNAL_INTERRUPT_RISING_FALLING, + TIMER_ALTERNATE_FUNCTION, + ALTERNATIVE, + }; + enum class Port : uint8_t { A, B, C, D, E, F, G, H }; + static inline GPIO_TypeDef *port_to_reg(Port p) { + switch (p) { + case Port::A: + return GPIOA; + case Port::B: + return GPIOB; + case Port::C: + return GPIOC; + case Port::D: + return GPIOD; + case Port::E: + return GPIOE; + case Port::F: + return GPIOF; + case Port::G: + return GPIOG; + case Port::H: + return GPIOH; + default: + return nullptr; + } + } + static inline void enable_gpio_clock(Port port) { + switch (port) { + case Port::A: + __HAL_RCC_GPIOA_CLK_ENABLE(); + break; + + case Port::B: + __HAL_RCC_GPIOB_CLK_ENABLE(); + break; + + case Port::C: + __HAL_RCC_GPIOC_CLK_ENABLE(); + break; + + case Port::D: + __HAL_RCC_GPIOD_CLK_ENABLE(); + break; + + case Port::E: + __HAL_RCC_GPIOE_CLK_ENABLE(); + break; + + case Port::F: + __HAL_RCC_GPIOF_CLK_ENABLE(); + break; + + case Port::G: + __HAL_RCC_GPIOG_CLK_ENABLE(); + break; + + case Port::H: + __HAL_RCC_GPIOH_CLK_ENABLE(); + break; + } + } + + struct Pin2 { + GPIODomain::Port port; + uint32_t pin; + + consteval Pin2(GPIODomain::Port port, uint32_t pin) + : port(port), pin(pin) {} + }; + + struct Entry { + size_t id; + Port port; + uint32_t pin; + OperationMode mode; + }; + + struct GPIO { + using domain = GPIODomain; + + Entry e; + + consteval GPIO(std::size_t id, Pin2 pin, OperationMode mode) + : e(id, pin.port, pin.pin, mode) {} + + template consteval void inscribe(Ctx &ctx) const { + ctx.template add(e); + } + }; + + static constexpr std::size_t max_instances{110}; + static_assert(max_instances > 0, + "The number of instances must be greater than 0"); + + struct Config { + size_t id; + std::tuple init_data{}; + }; + + template + static consteval array build(span pins) { + array cfgs{}; + for (std::size_t i = 0; i < N; ++i) { + const auto &e = pins[i]; + + for (std::size_t j = 0; j < i; ++j) { + const auto &prev = pins[j]; + if (prev.pin == e.pin) { + struct gpio_already_inscribed {}; + throw gpio_already_inscribed{}; + } + } + + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Pin = e.pin; + switch (e.mode) { + + case OperationMode::OUTPUT: + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + break; + + case OperationMode::INPUT: + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + break; + + case OperationMode::ANALOG: + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + break; + case OperationMode::EXTERNAL_INTERRUPT_RISING: + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + break; + case OperationMode::EXTERNAL_INTERRUPT_FALLING: + GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + break; + case OperationMode::EXTERNAL_INTERRUPT_RISING_FALLING: + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + break; + // case OperationMode::TIMER_ALTERNATE_FUNCTION: + // GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + // GPIO_InitStruct.Pull = GPIO_NOPULL; + // GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + // GPIO_InitStruct.Alternate = pin.alternative_function; + // break; + + default: + break; + } + + cfgs[i].id = e.id; + cfgs[i].init_data = std::make_tuple(e.port, GPIO_InitStruct); + } + + return cfgs; + } + + // Runtime object + struct Instance { + GPIO_TypeDef *port; + uint16_t pin; + + void turn_on() { HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET); } + + void turn_off() { HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET); } + + void toggle() { HAL_GPIO_TogglePin(port, pin); } + }; + +private: + inline static Instance *instances_ptr = nullptr; + +public: + static Instance &instance(std::size_t id) { return instances_ptr[id]; } + + template struct Init { + static inline std::array instances{}; + + static void init(std::span cfgs) { + static_assert(N > 0); + for (std::size_t i = 0; i < N; ++i) { + const auto &e = cfgs[i]; + auto [port, gpio_init] = e.init_data; + + enable_gpio_clock(port); + HAL_GPIO_Init(port_to_reg(port), &gpio_init); + + auto &inst = instances[e.id]; + inst.port = port_to_reg(port); + inst.pin = gpio_init.Pin; + } + + instances_ptr = instances.data(); + } + }; +}; +} // namespace ST_LIB \ No newline at end of file diff --git a/Inc/HALAL/Models/Pin.hpp b/Inc/HALAL/Models/Pin.hpp new file mode 100644 index 000000000..987e689db --- /dev/null +++ b/Inc/HALAL/Models/Pin.hpp @@ -0,0 +1,7 @@ +#include "HALAL/Models/GPIO.hpp" + +namespace ST_LIB { +constexpr GPIODomain::Pin2 PA0{GPIODomain::Port::A, GPIO_PIN_0}; +constexpr GPIODomain::Pin2 PA1{GPIODomain::Port::A, GPIO_PIN_1}; +constexpr GPIODomain::Pin2 PB0{GPIODomain::Port::B, GPIO_PIN_0}; +} // namespace ST_LIB \ No newline at end of file diff --git a/Inc/ST-LIB.hpp b/Inc/ST-LIB.hpp index 0736c791d..68e4efaf6 100644 --- a/Inc/ST-LIB.hpp +++ b/Inc/ST-LIB.hpp @@ -22,4 +22,90 @@ class STLIB { #endif static void update(); -}; \ No newline at end of file +}; + +namespace ST_LIB { +template struct BuildCtx { + template using Decl = typename D::Entry; + template + static constexpr std::size_t max_count_v = D::max_instances; + + std::tuple, max_count_v>...> storage{}; + std::array sizes{}; + + template + static consteval std::size_t domain_index() { + if constexpr (I >= sizeof...(Domains)) { + static_assert([] { return false; }(), "Domain not found"); + return 0; + } else if constexpr (std::is_same_v>>) { + return I; + } else { + return domain_index(); + } + } + + template consteval void add(typename D::Entry e) { + constexpr std::size_t I = domain_index(); + auto &arr = std::get(storage); + auto &size = sizes[I]; + arr[size++] = e; + } + + template consteval auto span() const { + constexpr std::size_t I = domain_index(); + auto const &arr = std::get(storage); + auto const size = sizes[I]; + using E = typename D::Entry; + return std::span{arr.data(), size}; + } +}; + +template consteval std::size_t domain_count() { + return (... + + (std::is_same_v ? 1u : 0u)); +} + +using DomainsCtx = BuildCtx; + +// Configure HW (compile-time) +template consteval auto build() { + DomainsCtx ctx{}; + + (devs.inscribe(ctx), ...); + + constexpr std::size_t gpioN = domain_count(); + // constexpr std::size_t adcN = domain_count(); + // constexpr std::size_t pwmN = domain_count(); + + struct ConfigBundle { + array gpio_cfgs; + // array adc_cgfs; + // array pwm_cgfs; + }; + + return ConfigBundle{ + .gpio_cfgs = + GPIODomain::template build(ctx.template span()), + // .adc_cgfs = + // ADCDomain::template build(ctx.template span()), + // .pwm_cgfs = + // PWMDomain::template build(ctx.template span()), + }; +} + +// Init real HW (runtime) +template void init() { + static constexpr auto cfg = build(); + + constexpr std::size_t gpioN = domain_count(); + // constexpr std::size_t adcN = domain_count(); + // constexpr std::size_t pwmN = domain_count(); + + GPIODomain::Init::init(cfg.gpio_cfgs); + // ADCDomain::Init::init(cfg.adc_cfgs); + // PWMDomain::Init::init(cfg.pwm_cfgs); +} + +} // namespace ST_LIB \ No newline at end of file diff --git a/Inc/stm32h7xx_hal_conf.h b/Inc/stm32h7xx_hal_conf.h index 574000009..74fdc0c32 100644 --- a/Inc/stm32h7xx_hal_conf.h +++ b/Inc/stm32h7xx_hal_conf.h @@ -233,7 +233,7 @@ * @brief Uncomment the line below to expanse the "assert_param" macro in the * HAL drivers code */ -/* #define USE_FULL_ASSERT 1 */ +#define USE_FULL_ASSERT 1 /* Includes ------------------------------------------------------------------*/ From 3eec305d09b320a092d10579cbef5926eb67c0a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20S=C3=A1ez?= Date: Sun, 30 Nov 2025 15:50:54 +0100 Subject: [PATCH 019/109] no need to have an id for instance --- Inc/HALAL/Models/GPIO.hpp | 10 +-- Inc/HALAL/Models/Pin.hpp | 148 +++++++++++++++++++++++++++++++++++++- Inc/ST-LIB.hpp | 126 ++++++++++++++++++++++---------- 3 files changed, 237 insertions(+), 47 deletions(-) diff --git a/Inc/HALAL/Models/GPIO.hpp b/Inc/HALAL/Models/GPIO.hpp index e9bfafe5a..09da6a27d 100644 --- a/Inc/HALAL/Models/GPIO.hpp +++ b/Inc/HALAL/Models/GPIO.hpp @@ -90,7 +90,6 @@ struct GPIODomain { }; struct Entry { - size_t id; Port port; uint32_t pin; OperationMode mode; @@ -101,8 +100,7 @@ struct GPIODomain { Entry e; - consteval GPIO(std::size_t id, Pin2 pin, OperationMode mode) - : e(id, pin.port, pin.pin, mode) {} + consteval GPIO(Pin2 pin, OperationMode mode) : e(pin.port, pin.pin, mode) {} template consteval void inscribe(Ctx &ctx) const { ctx.template add(e); @@ -114,7 +112,6 @@ struct GPIODomain { "The number of instances must be greater than 0"); struct Config { - size_t id; std::tuple init_data{}; }; @@ -126,7 +123,7 @@ struct GPIODomain { for (std::size_t j = 0; j < i; ++j) { const auto &prev = pins[j]; - if (prev.pin == e.pin) { + if (prev.pin == e.pin && prev.port == e.port) { struct gpio_already_inscribed {}; throw gpio_already_inscribed{}; } @@ -174,7 +171,6 @@ struct GPIODomain { break; } - cfgs[i].id = e.id; cfgs[i].init_data = std::make_tuple(e.port, GPIO_InitStruct); } @@ -211,7 +207,7 @@ struct GPIODomain { enable_gpio_clock(port); HAL_GPIO_Init(port_to_reg(port), &gpio_init); - auto &inst = instances[e.id]; + auto &inst = instances[i]; inst.port = port_to_reg(port); inst.pin = gpio_init.Pin; } diff --git a/Inc/HALAL/Models/Pin.hpp b/Inc/HALAL/Models/Pin.hpp index 987e689db..fd598fcd0 100644 --- a/Inc/HALAL/Models/Pin.hpp +++ b/Inc/HALAL/Models/Pin.hpp @@ -1,7 +1,149 @@ #include "HALAL/Models/GPIO.hpp" namespace ST_LIB { -constexpr GPIODomain::Pin2 PA0{GPIODomain::Port::A, GPIO_PIN_0}; -constexpr GPIODomain::Pin2 PA1{GPIODomain::Port::A, GPIO_PIN_1}; -constexpr GPIODomain::Pin2 PB0{GPIODomain::Port::B, GPIO_PIN_0}; + +// Port A +constexpr GPIODomain::Pin2 PA0 {GPIODomain::Port::A, GPIO_PIN_0}; +constexpr GPIODomain::Pin2 PA1 {GPIODomain::Port::A, GPIO_PIN_1}; +constexpr GPIODomain::Pin2 PA2 {GPIODomain::Port::A, GPIO_PIN_2}; +constexpr GPIODomain::Pin2 PA3 {GPIODomain::Port::A, GPIO_PIN_3}; +constexpr GPIODomain::Pin2 PA4 {GPIODomain::Port::A, GPIO_PIN_4}; +constexpr GPIODomain::Pin2 PA5 {GPIODomain::Port::A, GPIO_PIN_5}; +constexpr GPIODomain::Pin2 PA6 {GPIODomain::Port::A, GPIO_PIN_6}; +constexpr GPIODomain::Pin2 PA7 {GPIODomain::Port::A, GPIO_PIN_7}; +constexpr GPIODomain::Pin2 PA8 {GPIODomain::Port::A, GPIO_PIN_8}; +constexpr GPIODomain::Pin2 PA9 {GPIODomain::Port::A, GPIO_PIN_9}; +constexpr GPIODomain::Pin2 PA10{GPIODomain::Port::A, GPIO_PIN_10}; +constexpr GPIODomain::Pin2 PA11{GPIODomain::Port::A, GPIO_PIN_11}; +constexpr GPIODomain::Pin2 PA12{GPIODomain::Port::A, GPIO_PIN_12}; +constexpr GPIODomain::Pin2 PA13{GPIODomain::Port::A, GPIO_PIN_13}; +constexpr GPIODomain::Pin2 PA14{GPIODomain::Port::A, GPIO_PIN_14}; +constexpr GPIODomain::Pin2 PA15{GPIODomain::Port::A, GPIO_PIN_15}; + +// Port B +constexpr GPIODomain::Pin2 PB0 {GPIODomain::Port::B, GPIO_PIN_0}; +constexpr GPIODomain::Pin2 PB1 {GPIODomain::Port::B, GPIO_PIN_1}; +constexpr GPIODomain::Pin2 PB2 {GPIODomain::Port::B, GPIO_PIN_2}; +constexpr GPIODomain::Pin2 PB3 {GPIODomain::Port::B, GPIO_PIN_3}; +constexpr GPIODomain::Pin2 PB4 {GPIODomain::Port::B, GPIO_PIN_4}; +constexpr GPIODomain::Pin2 PB5 {GPIODomain::Port::B, GPIO_PIN_5}; +constexpr GPIODomain::Pin2 PB6 {GPIODomain::Port::B, GPIO_PIN_6}; +constexpr GPIODomain::Pin2 PB7 {GPIODomain::Port::B, GPIO_PIN_7}; +constexpr GPIODomain::Pin2 PB8 {GPIODomain::Port::B, GPIO_PIN_8}; +constexpr GPIODomain::Pin2 PB9 {GPIODomain::Port::B, GPIO_PIN_9}; +constexpr GPIODomain::Pin2 PB10{GPIODomain::Port::B, GPIO_PIN_10}; +constexpr GPIODomain::Pin2 PB11{GPIODomain::Port::B, GPIO_PIN_11}; +constexpr GPIODomain::Pin2 PB12{GPIODomain::Port::B, GPIO_PIN_12}; +constexpr GPIODomain::Pin2 PB13{GPIODomain::Port::B, GPIO_PIN_13}; +constexpr GPIODomain::Pin2 PB14{GPIODomain::Port::B, GPIO_PIN_14}; +constexpr GPIODomain::Pin2 PB15{GPIODomain::Port::B, GPIO_PIN_15}; + +// Port C +constexpr GPIODomain::Pin2 PC0 {GPIODomain::Port::C, GPIO_PIN_0}; +constexpr GPIODomain::Pin2 PC1 {GPIODomain::Port::C, GPIO_PIN_1}; +constexpr GPIODomain::Pin2 PC2 {GPIODomain::Port::C, GPIO_PIN_2}; +constexpr GPIODomain::Pin2 PC3 {GPIODomain::Port::C, GPIO_PIN_3}; +constexpr GPIODomain::Pin2 PC4 {GPIODomain::Port::C, GPIO_PIN_4}; +constexpr GPIODomain::Pin2 PC5 {GPIODomain::Port::C, GPIO_PIN_5}; +constexpr GPIODomain::Pin2 PC6 {GPIODomain::Port::C, GPIO_PIN_6}; +constexpr GPIODomain::Pin2 PC7 {GPIODomain::Port::C, GPIO_PIN_7}; +constexpr GPIODomain::Pin2 PC8 {GPIODomain::Port::C, GPIO_PIN_8}; +constexpr GPIODomain::Pin2 PC9 {GPIODomain::Port::C, GPIO_PIN_9}; +constexpr GPIODomain::Pin2 PC10{GPIODomain::Port::C, GPIO_PIN_10}; +constexpr GPIODomain::Pin2 PC11{GPIODomain::Port::C, GPIO_PIN_11}; +constexpr GPIODomain::Pin2 PC12{GPIODomain::Port::C, GPIO_PIN_12}; +constexpr GPIODomain::Pin2 PC13{GPIODomain::Port::C, GPIO_PIN_13}; +constexpr GPIODomain::Pin2 PC14{GPIODomain::Port::C, GPIO_PIN_14}; +constexpr GPIODomain::Pin2 PC15{GPIODomain::Port::C, GPIO_PIN_15}; + +// Port D +constexpr GPIODomain::Pin2 PD0 {GPIODomain::Port::D, GPIO_PIN_0}; +constexpr GPIODomain::Pin2 PD1 {GPIODomain::Port::D, GPIO_PIN_1}; +constexpr GPIODomain::Pin2 PD2 {GPIODomain::Port::D, GPIO_PIN_2}; +constexpr GPIODomain::Pin2 PD3 {GPIODomain::Port::D, GPIO_PIN_3}; +constexpr GPIODomain::Pin2 PD4 {GPIODomain::Port::D, GPIO_PIN_4}; +constexpr GPIODomain::Pin2 PD5 {GPIODomain::Port::D, GPIO_PIN_5}; +constexpr GPIODomain::Pin2 PD6 {GPIODomain::Port::D, GPIO_PIN_6}; +constexpr GPIODomain::Pin2 PD7 {GPIODomain::Port::D, GPIO_PIN_7}; +constexpr GPIODomain::Pin2 PD8 {GPIODomain::Port::D, GPIO_PIN_8}; +constexpr GPIODomain::Pin2 PD9 {GPIODomain::Port::D, GPIO_PIN_9}; +constexpr GPIODomain::Pin2 PD10{GPIODomain::Port::D, GPIO_PIN_10}; +constexpr GPIODomain::Pin2 PD11{GPIODomain::Port::D, GPIO_PIN_11}; +constexpr GPIODomain::Pin2 PD12{GPIODomain::Port::D, GPIO_PIN_12}; +constexpr GPIODomain::Pin2 PD13{GPIODomain::Port::D, GPIO_PIN_13}; +constexpr GPIODomain::Pin2 PD14{GPIODomain::Port::D, GPIO_PIN_14}; +constexpr GPIODomain::Pin2 PD15{GPIODomain::Port::D, GPIO_PIN_15}; + +// Port E +constexpr GPIODomain::Pin2 PE0 {GPIODomain::Port::E, GPIO_PIN_0}; +constexpr GPIODomain::Pin2 PE1 {GPIODomain::Port::E, GPIO_PIN_1}; +constexpr GPIODomain::Pin2 PE2 {GPIODomain::Port::E, GPIO_PIN_2}; +constexpr GPIODomain::Pin2 PE3 {GPIODomain::Port::E, GPIO_PIN_3}; +constexpr GPIODomain::Pin2 PE4 {GPIODomain::Port::E, GPIO_PIN_4}; +constexpr GPIODomain::Pin2 PE5 {GPIODomain::Port::E, GPIO_PIN_5}; +constexpr GPIODomain::Pin2 PE6 {GPIODomain::Port::E, GPIO_PIN_6}; +constexpr GPIODomain::Pin2 PE7 {GPIODomain::Port::E, GPIO_PIN_7}; +constexpr GPIODomain::Pin2 PE8 {GPIODomain::Port::E, GPIO_PIN_8}; +constexpr GPIODomain::Pin2 PE9 {GPIODomain::Port::E, GPIO_PIN_9}; +constexpr GPIODomain::Pin2 PE10{GPIODomain::Port::E, GPIO_PIN_10}; +constexpr GPIODomain::Pin2 PE11{GPIODomain::Port::E, GPIO_PIN_11}; +constexpr GPIODomain::Pin2 PE12{GPIODomain::Port::E, GPIO_PIN_12}; +constexpr GPIODomain::Pin2 PE13{GPIODomain::Port::E, GPIO_PIN_13}; +constexpr GPIODomain::Pin2 PE14{GPIODomain::Port::E, GPIO_PIN_14}; +constexpr GPIODomain::Pin2 PE15{GPIODomain::Port::E, GPIO_PIN_15}; + +// Port F +constexpr GPIODomain::Pin2 PF0 {GPIODomain::Port::F, GPIO_PIN_0}; +constexpr GPIODomain::Pin2 PF1 {GPIODomain::Port::F, GPIO_PIN_1}; +constexpr GPIODomain::Pin2 PF2 {GPIODomain::Port::F, GPIO_PIN_2}; +constexpr GPIODomain::Pin2 PF3 {GPIODomain::Port::F, GPIO_PIN_3}; +constexpr GPIODomain::Pin2 PF4 {GPIODomain::Port::F, GPIO_PIN_4}; +constexpr GPIODomain::Pin2 PF5 {GPIODomain::Port::F, GPIO_PIN_5}; +constexpr GPIODomain::Pin2 PF6 {GPIODomain::Port::F, GPIO_PIN_6}; +constexpr GPIODomain::Pin2 PF7 {GPIODomain::Port::F, GPIO_PIN_7}; +constexpr GPIODomain::Pin2 PF8 {GPIODomain::Port::F, GPIO_PIN_8}; +constexpr GPIODomain::Pin2 PF9 {GPIODomain::Port::F, GPIO_PIN_9}; +constexpr GPIODomain::Pin2 PF10{GPIODomain::Port::F, GPIO_PIN_10}; +constexpr GPIODomain::Pin2 PF11{GPIODomain::Port::F, GPIO_PIN_11}; +constexpr GPIODomain::Pin2 PF12{GPIODomain::Port::F, GPIO_PIN_12}; +constexpr GPIODomain::Pin2 PF13{GPIODomain::Port::F, GPIO_PIN_13}; +constexpr GPIODomain::Pin2 PF14{GPIODomain::Port::F, GPIO_PIN_14}; +constexpr GPIODomain::Pin2 PF15{GPIODomain::Port::F, GPIO_PIN_15}; + +// Port G +constexpr GPIODomain::Pin2 PG0 {GPIODomain::Port::G, GPIO_PIN_0}; +constexpr GPIODomain::Pin2 PG1 {GPIODomain::Port::G, GPIO_PIN_1}; +constexpr GPIODomain::Pin2 PG2 {GPIODomain::Port::G, GPIO_PIN_2}; +constexpr GPIODomain::Pin2 PG3 {GPIODomain::Port::G, GPIO_PIN_3}; +constexpr GPIODomain::Pin2 PG4 {GPIODomain::Port::G, GPIO_PIN_4}; +constexpr GPIODomain::Pin2 PG5 {GPIODomain::Port::G, GPIO_PIN_5}; +constexpr GPIODomain::Pin2 PG6 {GPIODomain::Port::G, GPIO_PIN_6}; +constexpr GPIODomain::Pin2 PG7 {GPIODomain::Port::G, GPIO_PIN_7}; +constexpr GPIODomain::Pin2 PG8 {GPIODomain::Port::G, GPIO_PIN_8}; +constexpr GPIODomain::Pin2 PG9 {GPIODomain::Port::G, GPIO_PIN_9}; +constexpr GPIODomain::Pin2 PG10{GPIODomain::Port::G, GPIO_PIN_10}; +constexpr GPIODomain::Pin2 PG11{GPIODomain::Port::G, GPIO_PIN_11}; +constexpr GPIODomain::Pin2 PG12{GPIODomain::Port::G, GPIO_PIN_12}; +constexpr GPIODomain::Pin2 PG13{GPIODomain::Port::G, GPIO_PIN_13}; +constexpr GPIODomain::Pin2 PG14{GPIODomain::Port::G, GPIO_PIN_14}; +constexpr GPIODomain::Pin2 PG15{GPIODomain::Port::G, GPIO_PIN_15}; + +// Port H +constexpr GPIODomain::Pin2 PH0 {GPIODomain::Port::H, GPIO_PIN_0}; +constexpr GPIODomain::Pin2 PH1 {GPIODomain::Port::H, GPIO_PIN_1}; +constexpr GPIODomain::Pin2 PH2 {GPIODomain::Port::H, GPIO_PIN_2}; +constexpr GPIODomain::Pin2 PH3 {GPIODomain::Port::H, GPIO_PIN_3}; +constexpr GPIODomain::Pin2 PH4 {GPIODomain::Port::H, GPIO_PIN_4}; +constexpr GPIODomain::Pin2 PH5 {GPIODomain::Port::H, GPIO_PIN_5}; +constexpr GPIODomain::Pin2 PH6 {GPIODomain::Port::H, GPIO_PIN_6}; +constexpr GPIODomain::Pin2 PH7 {GPIODomain::Port::H, GPIO_PIN_7}; +constexpr GPIODomain::Pin2 PH8 {GPIODomain::Port::H, GPIO_PIN_8}; +constexpr GPIODomain::Pin2 PH9 {GPIODomain::Port::H, GPIO_PIN_9}; +constexpr GPIODomain::Pin2 PH10{GPIODomain::Port::H, GPIO_PIN_10}; +constexpr GPIODomain::Pin2 PH11{GPIODomain::Port::H, GPIO_PIN_11}; +constexpr GPIODomain::Pin2 PH12{GPIODomain::Port::H, GPIO_PIN_12}; +constexpr GPIODomain::Pin2 PH13{GPIODomain::Port::H, GPIO_PIN_13}; +constexpr GPIODomain::Pin2 PH14{GPIODomain::Port::H, GPIO_PIN_14}; +constexpr GPIODomain::Pin2 PH15{GPIODomain::Port::H, GPIO_PIN_15}; + } // namespace ST_LIB \ No newline at end of file diff --git a/Inc/ST-LIB.hpp b/Inc/ST-LIB.hpp index 68e4efaf6..2f416eb5f 100644 --- a/Inc/ST-LIB.hpp +++ b/Inc/ST-LIB.hpp @@ -62,50 +62,102 @@ template struct BuildCtx { } }; -template consteval std::size_t domain_count() { +template consteval std::size_t domain_count() { return (... + - (std::is_same_v ? 1u : 0u)); + (std::is_same_v::domain, + Domain> + ? 1u + : 0u)); } using DomainsCtx = BuildCtx; -// Configure HW (compile-time) -template consteval auto build() { - DomainsCtx ctx{}; - - (devs.inscribe(ctx), ...); - - constexpr std::size_t gpioN = domain_count(); - // constexpr std::size_t adcN = domain_count(); - // constexpr std::size_t pwmN = domain_count(); - - struct ConfigBundle { - array gpio_cfgs; - // array adc_cgfs; - // array pwm_cgfs; - }; - - return ConfigBundle{ - .gpio_cfgs = - GPIODomain::template build(ctx.template span()), - // .adc_cgfs = - // ADCDomain::template build(ctx.template span()), - // .pwm_cgfs = - // PWMDomain::template build(ctx.template span()), - }; -} +template struct Board { + // ========== build compile-time ========== + static consteval auto build() { + DomainsCtx ctx{}; + + (devs.inscribe(ctx), ...); + + constexpr std::size_t gpioN = domain_count(); + // constexpr std::size_t adcN = domain_count(); + // constexpr std::size_t pwmN = domain_count(); + + struct ConfigBundle { + std::array gpio_cfgs; + // std::array adc_cgfs; + // std::array pwm_cgfs; + }; + + return ConfigBundle{ + .gpio_cfgs = + GPIODomain::template build(ctx.template span()), + // .adc_cgfs = + // ADCDomain::template build(ctx.template span()), + // .pwm_cgfs = + // PWMDomain::template build(ctx.template span()), + }; + } -// Init real HW (runtime) -template void init() { - static constexpr auto cfg = build(); + // ========== init runtime ========== + static void init() { + static constexpr auto cfg = build(); - constexpr std::size_t gpioN = domain_count(); - // constexpr std::size_t adcN = domain_count(); - // constexpr std::size_t pwmN = domain_count(); + constexpr std::size_t gpioN = domain_count(); + // constexpr std::size_t adcN = domain_count(); + // constexpr std::size_t pwmN = domain_count(); - GPIODomain::Init::init(cfg.gpio_cfgs); - // ADCDomain::Init::init(cfg.adc_cfgs); - // PWMDomain::Init::init(cfg.pwm_cfgs); -} + GPIODomain::Init::init(cfg.gpio_cfgs); + // ADCDomain::Init::init(cfg.adc_cfgs); + // PWMDomain::Init::init(cfg.pwm_cfgs); + } + + template static consteval std::size_t domain_size() { + return domain_count(); + } + + template + static consteval std::size_t domain_index_of_impl() { + std::size_t idx = 0; + bool found = false; + + ( + [&] { + using DevT = std::remove_cvref_t; + if constexpr (std::is_same_v) { + if (!found) { + if (&devs == &Target) { + found = true; + } else { + ++idx; + } + } + } + }(), + ...); + + if (!found) { + struct device_not_found_for_domain {}; + throw device_not_found_for_domain{}; + } + + return idx; + } + + template + static consteval std::size_t domain_index_of() { + return domain_index_of_impl(); + } + + template static auto &instance_of() { + using DevT = std::remove_cvref_t; + using Domain = typename DevT::domain; + + constexpr std::size_t idx = domain_index_of(); + constexpr std::size_t N = domain_size(); + + return Domain::template Init::instances[idx]; + } +}; } // namespace ST_LIB \ No newline at end of file From fa3498bc702818fbbd6ab0b3d486bdb13b7c2960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20S=C3=A1ez?= Date: Mon, 1 Dec 2025 23:47:30 +0100 Subject: [PATCH 020/109] erased no longer needed code --- Inc/HALAL/Models/GPIO.hpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Inc/HALAL/Models/GPIO.hpp b/Inc/HALAL/Models/GPIO.hpp index 09da6a27d..5423cd22d 100644 --- a/Inc/HALAL/Models/GPIO.hpp +++ b/Inc/HALAL/Models/GPIO.hpp @@ -189,12 +189,6 @@ struct GPIODomain { void toggle() { HAL_GPIO_TogglePin(port, pin); } }; -private: - inline static Instance *instances_ptr = nullptr; - -public: - static Instance &instance(std::size_t id) { return instances_ptr[id]; } - template struct Init { static inline std::array instances{}; @@ -211,8 +205,6 @@ struct GPIODomain { inst.port = port_to_reg(port); inst.pin = gpio_init.Pin; } - - instances_ptr = instances.data(); } }; }; From 0440eb437f0fd5c945764fcb8e7fbf312748b5f0 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Tue, 2 Dec 2025 19:39:48 +0100 Subject: [PATCH 021/109] cambio de nombre al antiguo dma y empiezo con la nueva infraestructura compile-time --- Inc/HALAL/Models/DMA/DMA-old.hpp | 366 ++++++++++++++++++++++++ Inc/HALAL/Models/DMA/DMA.hpp | 469 +++++++++---------------------- 2 files changed, 497 insertions(+), 338 deletions(-) create mode 100644 Inc/HALAL/Models/DMA/DMA-old.hpp diff --git a/Inc/HALAL/Models/DMA/DMA-old.hpp b/Inc/HALAL/Models/DMA/DMA-old.hpp new file mode 100644 index 000000000..3a37999d0 --- /dev/null +++ b/Inc/HALAL/Models/DMA/DMA-old.hpp @@ -0,0 +1,366 @@ +/* + * DMA.hpp + * + * Created on: 10 dic. 2022 + * Author: aleja +*/ +#pragma once +#include "C++Utilities/CppUtils.hpp" +#include "stm32h7xx_hal.h" +#include "main.h" +#include "HALAL/Models/MPUManager/MPUManager.hpp" +#include +#include +#include +#include +#include + +#define MAX_STREAMS 16 + +class DMA { + using PeriphVariant = std::variant< + SPI_HandleTypeDef*, + I2C_HandleTypeDef*, + ADC_HandleTypeDef*, + FMAC_HandleTypeDef* + >; + struct DmaLinkEntry{ + PeriphVariant periph; // (__HANDLE__) + DMA_HandleTypeDef* dma; // (__DMA_HANDLE__) + std::function linker; // (__PPP_DMA_FIELD__) + IRQn_Type irq; // (__IRQn_TYPE__) + }; + + template + static DmaLinkEntry make_dma_entry( + PeriphHandle* periph, + DMA_HandleTypeDef* dma, + DMA_HandleTypeDef* PeriphHandle::* member, + IRQn_Type irqn + ); + + static uint32_t get_Request(auto Instance, uint8_t i); + + static uint32_t get_Direction(auto Instance, uint8_t i); + + static uint32_t get_PeriphInc(auto Instance, uint8_t i); + + static uint32_t get_MemInc(auto Instance, uint8_t i); + + static uint32_t get_PeriphDataAlignment(auto Instance, uint8_t i); + + static uint32_t get_MemDataAlignment(auto Instance, uint8_t i); + + static uint32_t get_Mode(auto Instance, uint8_t i); + + static uint32_t get_Priority(auto Instance, uint8_t i); + + static uint32_t get_FIFOMode(auto Instance, uint8_t i); + + static uint32_t get_FIFOThreshold(auto Instance, uint8_t i); + + static uint32_t get_MemBurst(auto Instance, uint8_t i); + + static uint32_t get_PeriphBurst(auto Instance, uint8_t i); + + static IRQn_Type get_irqn(auto stream); + + static bool is_stream_available(uintptr_t stream); + + static bool is_peripherial_available(unsigned long peripherial); + + static std::array inscribed_streams; + static uint8_t inscribed_index; + + static std::set used_peripherials; + static std::set used_streams; + + public: + static constexpr bool is_one_of(auto Instance, auto... Bases); + + static constexpr bool is_spi(auto Instance); + + static constexpr bool is_i2c(auto Instance); + + static constexpr bool is_adc(auto Instance); + + static constexpr bool is_fmac(auto Instance); + + template + requires ( + (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || + (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || + (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) + ) + static void inscribe_stream(PeriphVariant handle); + + static void start(); +}; + +inline uint8_t DMA::inscribed_index{0}; +inline std::set DMA::used_peripherials{}; +inline std::set DMA::used_streams{}; +inline std::array DMA::inscribed_streams{}; + +constexpr bool DMA::is_one_of(auto Instance, auto... Bases) { + return ((Instance == Bases) || ...); +} + +constexpr bool DMA::is_spi(auto Instance) { + return is_one_of(Instance, SPI1_BASE, SPI2_BASE, SPI3_BASE, SPI4_BASE, SPI5_BASE); +} + +constexpr bool DMA::is_i2c(auto Instance) { + return is_one_of(Instance, I2C1_BASE, I2C2_BASE, I2C3_BASE, I2C5_BASE); +} + +constexpr bool DMA::is_adc(auto Instance) { + return is_one_of(Instance, ADC1_BASE, ADC2_BASE, ADC3_BASE); +} + +constexpr bool DMA::is_fmac(auto Instance) { + return Instance == FMAC_BASE; +} + +inline bool DMA::is_stream_available(uintptr_t stream) { + return used_streams.find(stream) == used_streams.end(); +} + +inline bool DMA::is_peripherial_available(unsigned long peripheral) { + return used_peripherials.find(peripheral) == used_peripherials.end(); +} + + +IRQn_Type DMA::get_irqn(auto stream) { + if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; + else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; + else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; + else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; + else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; + else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; + else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; + else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; + + else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; + else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; + else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; + else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; + else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; + else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; + else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; + else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; + else ErrorHandler("Unknown DMA stream"); + return DMA1_Stream0_IRQn; // Nunca se alcanza +} + +uint32_t DMA::get_Request(auto Instance, uint8_t i) { + if (Instance == ADC1_BASE) return DMA_REQUEST_ADC1; + if (Instance == ADC2_BASE) return DMA_REQUEST_ADC2; + if (Instance == ADC3_BASE) return DMA_REQUEST_ADC3; + + if (Instance == I2C1_BASE && i == 0) return DMA_REQUEST_I2C1_RX; + if (Instance == I2C1_BASE && i == 1) return DMA_REQUEST_I2C1_TX; + if (Instance == I2C2_BASE && i == 0) return DMA_REQUEST_I2C2_RX; + if (Instance == I2C2_BASE && i == 1) return DMA_REQUEST_I2C2_TX; + if (Instance == I2C3_BASE && i == 0) return DMA_REQUEST_I2C3_RX; + if (Instance == I2C3_BASE && i == 1) return DMA_REQUEST_I2C3_TX; + if (Instance == I2C5_BASE && i == 0) return DMA_REQUEST_I2C5_RX; + if (Instance == I2C5_BASE && i == 1) return DMA_REQUEST_I2C5_TX; + + if (Instance == SPI1_BASE && i == 0) return DMA_REQUEST_SPI1_RX; + if (Instance == SPI1_BASE && i == 1) return DMA_REQUEST_SPI1_TX; + if (Instance == SPI2_BASE && i == 0) return DMA_REQUEST_SPI2_RX; + if (Instance == SPI2_BASE && i == 1) return DMA_REQUEST_SPI2_TX; + if (Instance == SPI3_BASE && i == 0) return DMA_REQUEST_SPI3_RX; + if (Instance == SPI3_BASE && i == 1) return DMA_REQUEST_SPI3_TX; + if (Instance == SPI4_BASE && i == 0) return DMA_REQUEST_SPI4_RX; + if (Instance == SPI4_BASE && i == 1) return DMA_REQUEST_SPI4_TX; + if (Instance == SPI5_BASE && i == 0) return DMA_REQUEST_SPI5_RX; + if (Instance == SPI5_BASE && i == 1) return DMA_REQUEST_SPI5_TX; + + if (Instance == FMAC_BASE && i == 0) return DMA_REQUEST_MEM2MEM; + if (Instance == FMAC_BASE && i == 1) return DMA_REQUEST_FMAC_WRITE; + if (Instance == FMAC_BASE && i == 2) return DMA_REQUEST_FMAC_READ; + + ErrorHandler("Invalid DMA request configuration"); + return 0; +} + + + +uint32_t DMA::get_Direction(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_MEMORY_TO_MEMORY; + } + else if ((is_i2c(Instance) && i == 1) || + (is_spi(Instance) && i == 1) || + (is_fmac(Instance) && i == 1)){ + return DMA_MEMORY_TO_PERIPH; + } + + return DMA_PERIPH_TO_MEMORY; +} + +uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_PINC_ENABLE; + } + return DMA_PINC_DISABLE; +} +uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_MINC_DISABLE; + } + return DMA_MINC_ENABLE; +} + +uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { + if (is_i2c(Instance)){ + return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes + } + else if (is_spi(Instance)){ + return DMA_PDATAALIGN_BYTE; + } + + return DMA_PDATAALIGN_HALFWORD; +} + +uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { + if (is_i2c(Instance)){ + return DMA_MDATAALIGN_WORD; + } + else if (is_spi(Instance)){ + return DMA_MDATAALIGN_BYTE; + } + + return DMA_MDATAALIGN_HALFWORD; +} +uint32_t DMA::get_Mode(auto Instance, uint8_t i) { + if (is_spi(Instance) || is_fmac(Instance)){ + return DMA_NORMAL; + } + + return DMA_CIRCULAR; +} + + uint32_t DMA::get_Priority(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ + return DMA_PRIORITY_HIGH; + } + + return DMA_PRIORITY_LOW; +} +uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ + return DMA_FIFOMODE_ENABLE; + } + return DMA_FIFOMODE_DISABLE; +} + +uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { + if (is_spi(Instance)){ + return DMA_FIFO_THRESHOLD_FULL; + } + return DMA_FIFO_THRESHOLD_HALFFULL; +} + +uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { + return DMA_MBURST_SINGLE; +} + +uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { + return DMA_PBURST_SINGLE; +} + +template +DMA::DmaLinkEntry DMA::make_dma_entry( + PeriphHandle* periph, + DMA_HandleTypeDef* dma, + DMA_HandleTypeDef* PeriphHandle::* member, + IRQn_Type irqn +){ + return DmaLinkEntry{ + periph, + dma, + [periph, member](DMA_HandleTypeDef* d) { + periph->*member = d; + d->Parent = periph; + }, + irqn + }; +} + +template +requires ( + (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || + (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || + (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) +) +void DMA::inscribe_stream(PeriphVariant handle) { + const std::size_t N = sizeof...(Streams); + if (inscribed_index + N > MAX_STREAMS){ + ErrorHandler("Too many streams inscribed"); + } + + unsigned long periph_addr = reinterpret_cast(Instance); + if (!is_peripherial_available(periph_addr)){ + ErrorHandler("Peripheral already in use"); + } + used_peripherials.insert(periph_addr); + + std::array streams = {(DMA_Stream_TypeDef*)Streams... }; + + for (uint8_t i = 0; i < N; i++){ + uintptr_t stream_addr = reinterpret_cast(streams[i]); + if (!is_stream_available(stream_addr)){ + ErrorHandler("DMA stream already in use"); + used_streams.insert(stream_addr); + } + } + + + for (uint8_t i = 0; i < N; i++){ + DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; + dma->Instance = streams[i]; + dma->Init.Request = get_Request(Instance, i); + dma->Init.Direction = get_Direction(Instance, i); + dma->Init.PeriphInc = get_PeriphInc(Instance, i); + dma->Init.MemInc = get_MemInc(Instance, i); + dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); + dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); + dma->Init.Mode = get_Mode(Instance, i); + dma->Init.Priority = get_Priority(Instance, i); + dma->Init.FIFOMode = get_FIFOMode(Instance, i); + dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); + dma->Init.MemBurst = get_MemBurst(Instance, i); + dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); + IRQn_Type irq = get_irqn(streams[i]); + + if constexpr (is_spi(Instance)) { + auto* spi_handle = std::get(handle); + auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); + } + else if constexpr (is_i2c(Instance)) { + auto* i2c_handle = std::get(handle); + auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); + } + else if constexpr (is_adc(Instance)) { + auto* adc_handle = std::get(handle); + auto member = &ADC_HandleTypeDef::DMA_Handle; + inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); + } + else if constexpr (is_fmac(Instance)) { + auto* fmac_handle = std::get(handle); + auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : + (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : + &FMAC_HandleTypeDef::hdmaOut; + inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); + } + + inscribed_index++; + } +} + + diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 3a37999d0..c859c7672 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -1,9 +1,3 @@ -/* - * DMA.hpp - * - * Created on: 10 dic. 2022 - * Author: aleja -*/ #pragma once #include "C++Utilities/CppUtils.hpp" #include "stm32h7xx_hal.h" @@ -15,352 +9,151 @@ #include #include +using std::array; +using std::size_t; +using std::span; +using std::tuple; + #define MAX_STREAMS 16 -class DMA { - using PeriphVariant = std::variant< - SPI_HandleTypeDef*, - I2C_HandleTypeDef*, + +namespace ST_LIB { + struct DMA_Domain { + using xTypeDef = std::variant< + ADC_TypeDef*, + I2C_TypeDef*, + SPI_TypeDef*, + FMAC_TypeDef* + >; + using xHandleDef = std::variant< ADC_HandleTypeDef*, + I2C_HandleTypeDef*, + SPI_HandleTypeDef*, FMAC_HandleTypeDef* >; - struct DmaLinkEntry{ - PeriphVariant periph; // (__HANDLE__) - DMA_HandleTypeDef* dma; // (__DMA_HANDLE__) - std::function linker; // (__PPP_DMA_FIELD__) - IRQn_Type irq; // (__IRQn_TYPE__) - }; - - template - static DmaLinkEntry make_dma_entry( - PeriphHandle* periph, - DMA_HandleTypeDef* dma, - DMA_HandleTypeDef* PeriphHandle::* member, - IRQn_Type irqn - ); - - static uint32_t get_Request(auto Instance, uint8_t i); - - static uint32_t get_Direction(auto Instance, uint8_t i); - - static uint32_t get_PeriphInc(auto Instance, uint8_t i); - - static uint32_t get_MemInc(auto Instance, uint8_t i); - - static uint32_t get_PeriphDataAlignment(auto Instance, uint8_t i); - - static uint32_t get_MemDataAlignment(auto Instance, uint8_t i); - - static uint32_t get_Mode(auto Instance, uint8_t i); - - static uint32_t get_Priority(auto Instance, uint8_t i); - - static uint32_t get_FIFOMode(auto Instance, uint8_t i); - - static uint32_t get_FIFOThreshold(auto Instance, uint8_t i); - - static uint32_t get_MemBurst(auto Instance, uint8_t i); - - static uint32_t get_PeriphBurst(auto Instance, uint8_t i); - - static IRQn_Type get_irqn(auto stream); - - static bool is_stream_available(uintptr_t stream); - static bool is_peripherial_available(unsigned long peripherial); + enum class Instance : uint8_t {adc1, adc2, adc3, + i2c1, i2c2, i2c3, i2c5, + spi1, spi2, spi3, spi4, spi5, + fmac}; - static std::array inscribed_streams; - static uint8_t inscribed_index; - - static std::set used_peripherials; - static std::set used_streams; - - public: - static constexpr bool is_one_of(auto Instance, auto... Bases); + static inline xTypeDef instance_to_xTypeDef(Instance i) { + switch (i) { + case Instance::adc1: return ADC1; + case Instance::adc2: return ADC2; + case Instance::adc3: return ADC3; + + case Instance::i2c1: return I2C1; + case Instance::i2c2: return I2C2; + case Instance::i2c3: return I2C3; + case Instance::i2c5: return I2C5; + + case Instance::spi1: return SPI1; + case Instance::spi2: return SPI2; + case Instance::spi3: return SPI3; + case Instance::spi4: return SPI4; + case Instance::spi5: return SPI5; + + case Instance::fmac: return FMAC; + } + } - static constexpr bool is_spi(auto Instance); + enum class Stream : uint8_t {dma1_stream0, dma1_stream1, dma1_stream2, dma1_stream3, + dma1_stream4, dma1_stream5, dma1_stream6, dma1_stream7, + dma2_stream0, dma2_stream1, dma2_stream2, dma2_stream3, + dma2_stream4, dma2_stream5, dma2_stream6, dma2_stream7}; + + static inline DMA_Stream_TypeDef* stream_to_DMA_StreamTypeDef(Stream s) { + switch (s) { + case Stream::dma1_stream0: return DMA1_Stream0; + case Stream::dma1_stream1: return DMA1_Stream1; + case Stream::dma1_stream2: return DMA1_Stream2; + case Stream::dma1_stream3: return DMA1_Stream3; + case Stream::dma1_stream4: return DMA1_Stream4; + case Stream::dma1_stream5: return DMA1_Stream5; + case Stream::dma1_stream6: return DMA1_Stream6; + case Stream::dma1_stream7: return DMA1_Stream7; + + case Stream::dma2_stream0: return DMA2_Stream0; + case Stream::dma2_stream1: return DMA2_Stream1; + case Stream::dma2_stream2: return DMA2_Stream2; + case Stream::dma2_stream3: return DMA2_Stream3; + case Stream::dma2_stream4: return DMA2_Stream4; + case Stream::dma2_stream5: return DMA2_Stream5; + case Stream::dma2_stream6: return DMA2_Stream6; + case Stream::dma2_stream7: return DMA2_Stream7; + } + } - static constexpr bool is_i2c(auto Instance); - - static constexpr bool is_adc(auto Instance); - - static constexpr bool is_fmac(auto Instance); - - template - requires ( - (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || - (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || - (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) - ) - static void inscribe_stream(PeriphVariant handle); - - static void start(); -}; - -inline uint8_t DMA::inscribed_index{0}; -inline std::set DMA::used_peripherials{}; -inline std::set DMA::used_streams{}; -inline std::array DMA::inscribed_streams{}; - -constexpr bool DMA::is_one_of(auto Instance, auto... Bases) { - return ((Instance == Bases) || ...); -} - -constexpr bool DMA::is_spi(auto Instance) { - return is_one_of(Instance, SPI1_BASE, SPI2_BASE, SPI3_BASE, SPI4_BASE, SPI5_BASE); -} - -constexpr bool DMA::is_i2c(auto Instance) { - return is_one_of(Instance, I2C1_BASE, I2C2_BASE, I2C3_BASE, I2C5_BASE); -} - -constexpr bool DMA::is_adc(auto Instance) { - return is_one_of(Instance, ADC1_BASE, ADC2_BASE, ADC3_BASE); -} - -constexpr bool DMA::is_fmac(auto Instance) { - return Instance == FMAC_BASE; -} - -inline bool DMA::is_stream_available(uintptr_t stream) { - return used_streams.find(stream) == used_streams.end(); -} - -inline bool DMA::is_peripherial_available(unsigned long peripheral) { - return used_peripherials.find(peripheral) == used_peripherials.end(); -} - - -IRQn_Type DMA::get_irqn(auto stream) { - if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; - else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; - else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; - else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; - else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; - else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; - else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; - else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; - - else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; - else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; - else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; - else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; - else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; - else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; - else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; - else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; - else ErrorHandler("Unknown DMA stream"); - return DMA1_Stream0_IRQn; // Nunca se alcanza -} - -uint32_t DMA::get_Request(auto Instance, uint8_t i) { - if (Instance == ADC1_BASE) return DMA_REQUEST_ADC1; - if (Instance == ADC2_BASE) return DMA_REQUEST_ADC2; - if (Instance == ADC3_BASE) return DMA_REQUEST_ADC3; + struct Entry { + Instance instance; + std::array streams{}; + uint8_t count = 0; + IRQn_Type irqn; + }; - if (Instance == I2C1_BASE && i == 0) return DMA_REQUEST_I2C1_RX; - if (Instance == I2C1_BASE && i == 1) return DMA_REQUEST_I2C1_TX; - if (Instance == I2C2_BASE && i == 0) return DMA_REQUEST_I2C2_RX; - if (Instance == I2C2_BASE && i == 1) return DMA_REQUEST_I2C2_TX; - if (Instance == I2C3_BASE && i == 0) return DMA_REQUEST_I2C3_RX; - if (Instance == I2C3_BASE && i == 1) return DMA_REQUEST_I2C3_TX; - if (Instance == I2C5_BASE && i == 0) return DMA_REQUEST_I2C5_RX; - if (Instance == I2C5_BASE && i == 1) return DMA_REQUEST_I2C5_TX; + struct DMA{ + using domain = DMA_Domain; - if (Instance == SPI1_BASE && i == 0) return DMA_REQUEST_SPI1_RX; - if (Instance == SPI1_BASE && i == 1) return DMA_REQUEST_SPI1_TX; - if (Instance == SPI2_BASE && i == 0) return DMA_REQUEST_SPI2_RX; - if (Instance == SPI2_BASE && i == 1) return DMA_REQUEST_SPI2_TX; - if (Instance == SPI3_BASE && i == 0) return DMA_REQUEST_SPI3_RX; - if (Instance == SPI3_BASE && i == 1) return DMA_REQUEST_SPI3_TX; - if (Instance == SPI4_BASE && i == 0) return DMA_REQUEST_SPI4_RX; - if (Instance == SPI4_BASE && i == 1) return DMA_REQUEST_SPI4_TX; - if (Instance == SPI5_BASE && i == 0) return DMA_REQUEST_SPI5_RX; - if (Instance == SPI5_BASE && i == 1) return DMA_REQUEST_SPI5_TX; - - if (Instance == FMAC_BASE && i == 0) return DMA_REQUEST_MEM2MEM; - if (Instance == FMAC_BASE && i == 1) return DMA_REQUEST_FMAC_WRITE; - if (Instance == FMAC_BASE && i == 2) return DMA_REQUEST_FMAC_READ; + Entry e; - ErrorHandler("Invalid DMA request configuration"); - return 0; -} + template + consteval DMA(Instance instance) : e(instance) { + static_assert(sizeof...(Ss) <= 3, "Máximo 3 streams"); + size_t i = 0; + ((e.streams[i++] = Ss), ...); + e.count = i; + } + template consteval void inscribe(Ctx &ctx) const { + ctx.template add(e); + } + }; + static constexpr std::size_t max_instances {MAX_STREAMS}; + static_assert(max_instances > 0, "The number of instances must be greater than 0"); + + struct Config { + std::tuple> init_data{}; + }; -uint32_t DMA::get_Direction(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_MEMORY_TO_MEMORY; + template + static consteval std::array build(span instances){ + std::array cfgs{}; + + for (std::size_t i = 0; i < N; ++i){ + const auto &e = instances[i]; + + for (std::size_t j = 0; j < i; ++j){ + const auto &prev = instances[j]; + if (prev.instance == e.instance && prev.streams == e.streams){ + struct peripherial_already_inscribed {}; + throw peripherial_already_inscribed{}; + } + } + + std::array dma_handles; + for (std::size_t j = 0; j < e.count; j++){ + DMA_HandleTypeDef DMA_HandleStruct; + DMA_HandleStruct.Instance = e.streams[j]; + DMA_HandleStrcut.Init.Request = get_Request(e.instance, j); + DMA_HandleStrcut.Init.Direction = get_Direction(e.instance, j); + DMA_HandleStrcut.Init.PeriphInc = get_PeriphInc(e.instance, j); + DMA_HandleStrcut.Init.MemInc = get_MemInc(e.instance, j); + DMA_HandleStrcut.Init.PeriphDataAlignment = get_PeriphDataAlignment(e.instance, j); + DMA_HandleStrcut.Init.MemDataAlignment = get_MemDataAlignment(e.instance, j); + DMA_HandleStrcut.Init.Mode = get_Mode(e.instance, j); + DMA_HandleStrcut.Init.Priority = get_Priority(e.instance, j); + DMA_HandleStrcut.Init.FIFOMode = get_FIFOMode(e.instance, j); + DMA_HandleStrcut.Init.FIFOThreshold = get_FIFOThreshold(e.instance, j); + DMA_HandleStrcut.Init.MemBurst = get_MemBurst(e.instance, j); + DMA_HandleStrcut.Init.PeriphBurst = get_PeriphBurst(e.instance, j); + + dma_handles[i] = DMA_HandleStruct; + } + + cfgs[i].init_data = std::make_tuple(e.instance, dma_handles) + } } - else if ((is_i2c(Instance) && i == 1) || - (is_spi(Instance) && i == 1) || - (is_fmac(Instance) && i == 1)){ - return DMA_MEMORY_TO_PERIPH; - } - - return DMA_PERIPH_TO_MEMORY; -} - -uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_PINC_ENABLE; - } - return DMA_PINC_DISABLE; -} -uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_MINC_DISABLE; - } - return DMA_MINC_ENABLE; -} - -uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { - if (is_i2c(Instance)){ - return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes - } - else if (is_spi(Instance)){ - return DMA_PDATAALIGN_BYTE; - } - - return DMA_PDATAALIGN_HALFWORD; -} - -uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { - if (is_i2c(Instance)){ - return DMA_MDATAALIGN_WORD; - } - else if (is_spi(Instance)){ - return DMA_MDATAALIGN_BYTE; - } - - return DMA_MDATAALIGN_HALFWORD; -} -uint32_t DMA::get_Mode(auto Instance, uint8_t i) { - if (is_spi(Instance) || is_fmac(Instance)){ - return DMA_NORMAL; - } - - return DMA_CIRCULAR; -} - - uint32_t DMA::get_Priority(auto Instance, uint8_t i) { - if (is_fmac(Instance)){ - return DMA_PRIORITY_HIGH; - } - - return DMA_PRIORITY_LOW; -} -uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { - if (is_fmac(Instance)){ - return DMA_FIFOMODE_ENABLE; - } - return DMA_FIFOMODE_DISABLE; -} - -uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { - if (is_spi(Instance)){ - return DMA_FIFO_THRESHOLD_FULL; - } - return DMA_FIFO_THRESHOLD_HALFFULL; -} - -uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { - return DMA_MBURST_SINGLE; -} - -uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { - return DMA_PBURST_SINGLE; -} - -template -DMA::DmaLinkEntry DMA::make_dma_entry( - PeriphHandle* periph, - DMA_HandleTypeDef* dma, - DMA_HandleTypeDef* PeriphHandle::* member, - IRQn_Type irqn -){ - return DmaLinkEntry{ - periph, - dma, - [periph, member](DMA_HandleTypeDef* d) { - periph->*member = d; - d->Parent = periph; - }, - irqn }; -} - -template -requires ( - (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || - (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || - (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) -) -void DMA::inscribe_stream(PeriphVariant handle) { - const std::size_t N = sizeof...(Streams); - if (inscribed_index + N > MAX_STREAMS){ - ErrorHandler("Too many streams inscribed"); - } - - unsigned long periph_addr = reinterpret_cast(Instance); - if (!is_peripherial_available(periph_addr)){ - ErrorHandler("Peripheral already in use"); - } - used_peripherials.insert(periph_addr); - - std::array streams = {(DMA_Stream_TypeDef*)Streams... }; - - for (uint8_t i = 0; i < N; i++){ - uintptr_t stream_addr = reinterpret_cast(streams[i]); - if (!is_stream_available(stream_addr)){ - ErrorHandler("DMA stream already in use"); - used_streams.insert(stream_addr); - } - } - - - for (uint8_t i = 0; i < N; i++){ - DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; - dma->Instance = streams[i]; - dma->Init.Request = get_Request(Instance, i); - dma->Init.Direction = get_Direction(Instance, i); - dma->Init.PeriphInc = get_PeriphInc(Instance, i); - dma->Init.MemInc = get_MemInc(Instance, i); - dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); - dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); - dma->Init.Mode = get_Mode(Instance, i); - dma->Init.Priority = get_Priority(Instance, i); - dma->Init.FIFOMode = get_FIFOMode(Instance, i); - dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); - dma->Init.MemBurst = get_MemBurst(Instance, i); - dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); - IRQn_Type irq = get_irqn(streams[i]); - - if constexpr (is_spi(Instance)) { - auto* spi_handle = std::get(handle); - auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); - } - else if constexpr (is_i2c(Instance)) { - auto* i2c_handle = std::get(handle); - auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); - } - else if constexpr (is_adc(Instance)) { - auto* adc_handle = std::get(handle); - auto member = &ADC_HandleTypeDef::DMA_Handle; - inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); - } - else if constexpr (is_fmac(Instance)) { - auto* fmac_handle = std::get(handle); - auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : - (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : - &FMAC_HandleTypeDef::hdmaOut; - inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); - } - - inscribed_index++; - } -} - - +} \ No newline at end of file From 98a34fb031f2c6703eaf99a386d55cb6f5111cb3 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Wed, 3 Dec 2025 16:56:21 +0100 Subject: [PATCH 022/109] =?UTF-8?q?a=C3=B1adir=20funciones=20de=20configur?= =?UTF-8?q?acion=20del=20handle=20DMA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Inc/HALAL/Models/DMA/DMA.hpp | 205 +++++++++++++++++++++++++++++++---- 1 file changed, 184 insertions(+), 21 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index c859c7672..0bcf53946 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -37,6 +37,11 @@ namespace ST_LIB { spi1, spi2, spi3, spi4, spi5, fmac}; + enum class Stream : uint8_t {dma1_stream0, dma1_stream1, dma1_stream2, dma1_stream3, + dma1_stream4, dma1_stream5, dma1_stream6, dma1_stream7, + dma2_stream0, dma2_stream1, dma2_stream2, dma2_stream3, + dma2_stream4, dma2_stream5, dma2_stream6, dma2_stream7}; + static inline xTypeDef instance_to_xTypeDef(Instance i) { switch (i) { case Instance::adc1: return ADC1; @@ -57,11 +62,6 @@ namespace ST_LIB { case Instance::fmac: return FMAC; } } - - enum class Stream : uint8_t {dma1_stream0, dma1_stream1, dma1_stream2, dma1_stream3, - dma1_stream4, dma1_stream5, dma1_stream6, dma1_stream7, - dma2_stream0, dma2_stream1, dma2_stream2, dma2_stream3, - dma2_stream4, dma2_stream5, dma2_stream6, dma2_stream7}; static inline DMA_Stream_TypeDef* stream_to_DMA_StreamTypeDef(Stream s) { switch (s) { @@ -87,9 +87,8 @@ namespace ST_LIB { struct Entry { Instance instance; - std::array streams{}; + std::array, 3> streams{}; uint8_t count = 0; - IRQn_Type irqn; }; struct DMA{ @@ -101,7 +100,7 @@ namespace ST_LIB { consteval DMA(Instance instance) : e(instance) { static_assert(sizeof...(Ss) <= 3, "Máximo 3 streams"); size_t i = 0; - ((e.streams[i++] = Ss), ...); + ((e.streams[i++] = std::make_tuple(Ss, get_irqn(Ss))), ...); e.count = i; } @@ -117,6 +116,170 @@ namespace ST_LIB { std::tuple> init_data{}; }; + static inline IRQn_Type get_irqn(Stream stream) { + if (stream == Stream::dma1_stream0) return DMA1_Stream0_IRQn; + else if (stream == Stream::dma1_stream1) return DMA1_Stream1_IRQn; + else if (stream == Stream::dma1_stream2) return DMA1_Stream2_IRQn; + else if (stream == Stream::dma1_stream3) return DMA1_Stream3_IRQn; + else if (stream == Stream::dma1_stream4) return DMA1_Stream4_IRQn; + else if (stream == Stream::dma1_stream5) return DMA1_Stream5_IRQn; + else if (stream == Stream::dma1_stream6) return DMA1_Stream6_IRQn; + else if (stream == Stream::dma1_stream7) return DMA1_Stream7_IRQn; + + else if (stream == Stream::dma2_stream0) return DMA2_Stream0_IRQn; + else if (stream == Stream::dma2_stream1) return DMA2_Stream1_IRQn; + else if (stream == Stream::dma2_stream2) return DMA2_Stream2_IRQn; + else if (stream == Stream::dma2_stream3) return DMA2_Stream3_IRQn; + else if (stream == Stream::dma2_stream4) return DMA2_Stream4_IRQn; + else if (stream == Stream::dma2_stream5) return DMA2_Stream5_IRQn; + else if (stream == Stream::dma2_stream6) return DMA2_Stream6_IRQn; + else if (stream == Stream::dma2_stream7) return DMA2_Stream7_IRQn; + else ErrorHandler("Unknown DMA stream"); + return DMA1_Stream0_IRQn; // Nunca se alcanza + } + + // Si quitas el auto peta todo + static consteval inline bool is_one_of(Instance instance, auto... bases) { + return ((instance == bases) || ...); + } + + static consteval inline bool is_spi(Instance instance) { + return is_one_of(instance, Instance::spi1, Instance::spi2, + Instance::spi3, Instance::spi4, Instance::spi5); + } + + static consteval inline bool is_i2c(Instance instance) { + return is_one_of(instance, Instance::i2c1, Instance::i2c2, + Instance::i2c3, Instance::i2c5); + } + + static consteval inline bool is_adc(Instance instance) { + return is_one_of(instance, Instance::adc1, Instance::adc2, Instance::adc3); + } + + static consteval inline bool is_fmac(Instance instance) { + return instance == Instance::fmac; + } + + static consteval inline uint32_t get_Request(Instance instance, uint8_t i) { + if (instance == Instance::adc1) return DMA_REQUEST_ADC1; + if (instance == Instance::adc2) return DMA_REQUEST_ADC2; + if (instance == Instance::adc3) return DMA_REQUEST_ADC3; + + if (instance == Instance::i2c1 && i == 0) return DMA_REQUEST_I2C1_RX; + if (instance == Instance::i2c1 && i == 1) return DMA_REQUEST_I2C1_TX; + if (instance == Instance::i2c2 && i == 0) return DMA_REQUEST_I2C2_RX; + if (instance == Instance::i2c2 && i == 1) return DMA_REQUEST_I2C2_TX; + if (instance == Instance::i2c3 && i == 0) return DMA_REQUEST_I2C3_RX; + if (instance == Instance::i2c3 && i == 1) return DMA_REQUEST_I2C3_TX; + if (instance == Instance::i2c5 && i == 0) return DMA_REQUEST_I2C5_RX; + if (instance == Instance::i2c5 && i == 1) return DMA_REQUEST_I2C5_TX; + + if (instance == Instance::spi1 && i == 0) return DMA_REQUEST_SPI1_RX; + if (instance == Instance::spi1 && i == 1) return DMA_REQUEST_SPI1_TX; + if (instance == Instance::spi2 && i == 0) return DMA_REQUEST_SPI2_RX; + if (instance == Instance::spi2 && i == 1) return DMA_REQUEST_SPI2_TX; + if (instance == Instance::spi3 && i == 0) return DMA_REQUEST_SPI3_RX; + if (instance == Instance::spi3 && i == 1) return DMA_REQUEST_SPI3_TX; + if (instance == Instance::spi4 && i == 0) return DMA_REQUEST_SPI4_RX; + if (instance == Instance::spi4 && i == 1) return DMA_REQUEST_SPI4_TX; + if (instance == Instance::spi5 && i == 0) return DMA_REQUEST_SPI5_RX; + if (instance == Instance::spi5 && i == 1) return DMA_REQUEST_SPI5_TX; + + if (instance == Instance::fmac && i == 0) return DMA_REQUEST_MEM2MEM; + if (instance == Instance::fmac && i == 1) return DMA_REQUEST_FMAC_WRITE; + if (instance == Instance::fmac && i == 2) return DMA_REQUEST_FMAC_READ; + + ErrorHandler("Invalid DMA request configuration"); + return 0; + } + + + static consteval inline uint32_t get_Direction(Instance instance, uint8_t i) { + if (is_fmac(instance) && i == 0){ + return DMA_MEMORY_TO_MEMORY; + } + else if ((is_i2c(instance) && i == 1) || + (is_spi(instance) && i == 1) || + (is_fmac(instance) && i == 1)){ + return DMA_MEMORY_TO_PERIPH; + } + + return DMA_PERIPH_TO_MEMORY; + } + + static consteval inline uint32_t get_PeriphInc(Instance instance, uint8_t i) { + if (is_fmac(instance) && i == 0){ + return DMA_PINC_ENABLE; + } + return DMA_PINC_DISABLE; + } + static consteval inline uint32_t get_MemInc(Instance instance, uint8_t i) { + if (is_fmac(instance) && i == 0){ + return DMA_MINC_DISABLE; + } + return DMA_MINC_ENABLE; + } + + static consteval inline uint32_t get_PeriphDataAlignment(Instance instance, uint8_t i) { + if (is_i2c(instance)){ + return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes + } + else if (is_spi(instance)){ + return DMA_PDATAALIGN_BYTE; + } + + return DMA_PDATAALIGN_HALFWORD; + } + + static consteval inline uint32_t get_MemDataAlignment(Instance instance, uint8_t i) { + if (is_i2c(instance)){ + return DMA_MDATAALIGN_WORD; + } + else if (is_spi(instance)){ + return DMA_MDATAALIGN_BYTE; + } + + return DMA_MDATAALIGN_HALFWORD; + } + static consteval inline uint32_t get_Mode(Instance instance, uint8_t i) { + if (is_spi(instance) || is_fmac(instance)){ + return DMA_NORMAL; + } + + return DMA_CIRCULAR; + } + + static consteval inline uint32_t get_Priority(Instance instance, uint8_t i) { + if (is_fmac(instance)){ + return DMA_PRIORITY_HIGH; + } + + return DMA_PRIORITY_LOW; + } + static consteval inline uint32_t get_FIFOMode(Instance instance, uint8_t i) { + if (is_fmac(instance)){ + return DMA_FIFOMODE_ENABLE; + } + return DMA_FIFOMODE_DISABLE; + } + + static consteval inline uint32_t get_FIFOThreshold(Instance instance, uint8_t i) { + if (is_spi(instance)){ + return DMA_FIFO_THRESHOLD_FULL; + } + return DMA_FIFO_THRESHOLD_HALFFULL; + } + + static consteval inline uint32_t get_MemBurst(Instance instance, uint8_t i) { + return DMA_MBURST_SINGLE; + } + + static consteval inline uint32_t get_PeriphBurst(Instance instance, uint8_t i) { + return DMA_PBURST_SINGLE; + } + + template static consteval std::array build(span instances){ std::array cfgs{}; @@ -136,23 +299,23 @@ namespace ST_LIB { for (std::size_t j = 0; j < e.count; j++){ DMA_HandleTypeDef DMA_HandleStruct; DMA_HandleStruct.Instance = e.streams[j]; - DMA_HandleStrcut.Init.Request = get_Request(e.instance, j); - DMA_HandleStrcut.Init.Direction = get_Direction(e.instance, j); - DMA_HandleStrcut.Init.PeriphInc = get_PeriphInc(e.instance, j); - DMA_HandleStrcut.Init.MemInc = get_MemInc(e.instance, j); - DMA_HandleStrcut.Init.PeriphDataAlignment = get_PeriphDataAlignment(e.instance, j); - DMA_HandleStrcut.Init.MemDataAlignment = get_MemDataAlignment(e.instance, j); - DMA_HandleStrcut.Init.Mode = get_Mode(e.instance, j); - DMA_HandleStrcut.Init.Priority = get_Priority(e.instance, j); - DMA_HandleStrcut.Init.FIFOMode = get_FIFOMode(e.instance, j); - DMA_HandleStrcut.Init.FIFOThreshold = get_FIFOThreshold(e.instance, j); - DMA_HandleStrcut.Init.MemBurst = get_MemBurst(e.instance, j); - DMA_HandleStrcut.Init.PeriphBurst = get_PeriphBurst(e.instance, j); + DMA_HandleStruct.Init.Request = get_Request(e.instance, j); + DMA_HandleStruct.Init.Direction = get_Direction(e.instance, j); + DMA_HandleStruct.Init.PeriphInc = get_PeriphInc(e.instance, j); + DMA_HandleStruct.Init.MemInc = get_MemInc(e.instance, j); + DMA_HandleStruct.Init.PeriphDataAlignment = get_PeriphDataAlignment(e.instance, j); + DMA_HandleStruct.Init.MemDataAlignment = get_MemDataAlignment(e.instance, j); + DMA_HandleStruct.Init.Mode = get_Mode(e.instance, j); + DMA_HandleStruct.Init.Priority = get_Priority(e.instance, j); + DMA_HandleStruct.Init.FIFOMode = get_FIFOMode(e.instance, j); + DMA_HandleStruct.Init.FIFOThreshold = get_FIFOThreshold(e.instance, j); + DMA_HandleStruct.Init.MemBurst = get_MemBurst(e.instance, j); + DMA_HandleStruct.Init.PeriphBurst = get_PeriphBurst(e.instance, j); dma_handles[i] = DMA_HandleStruct; } - cfgs[i].init_data = std::make_tuple(e.instance, dma_handles) + cfgs[i].init_data = std::make_tuple(e.instance, dma_handles); } } }; From c1966cf9308c40a5799b7b9e696739fb5650fbdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20S=C3=A1ez?= Date: Wed, 3 Dec 2025 00:23:23 +0100 Subject: [PATCH 023/109] Added DigitalInput and DigitalOutput Services, and added support for Alternate functions --- CMakeLists.txt | 1 - Inc/HALAL/Models/GPIO.hpp | 167 ++++++++++++------- Inc/HALAL/Models/Pin.hpp | 258 +++++++++++++++--------------- Inc/ST-LIB.hpp | 80 +++++---- Inc/ST-LIB_LOW/DigitalInput2.hpp | 63 ++++++++ Inc/ST-LIB_LOW/DigitalOutput2.hpp | 75 +++++++++ Inc/ST-LIB_LOW/ST-LIB_LOW.hpp | 3 + 7 files changed, 426 insertions(+), 221 deletions(-) create mode 100644 Inc/ST-LIB_LOW/DigitalInput2.hpp create mode 100644 Inc/ST-LIB_LOW/DigitalOutput2.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d35f2ef8..9ff603b45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -263,7 +263,6 @@ target_compile_options(${STLIB_LIBRARY} PRIVATE $<$:-specs=nosys.specs> $<$:-ffunction-sections> $<$:-fdata-sections> - # $<$:-fno-exceptions> -Wno-psabi diff --git a/Inc/HALAL/Models/GPIO.hpp b/Inc/HALAL/Models/GPIO.hpp index 5423cd22d..335ac3d26 100644 --- a/Inc/HALAL/Models/GPIO.hpp +++ b/Inc/HALAL/Models/GPIO.hpp @@ -13,14 +13,80 @@ using std::tuple; namespace ST_LIB { struct GPIODomain { enum class OperationMode : uint8_t { - INPUT, - OUTPUT, - ANALOG, - EXTERNAL_INTERRUPT_RISING, - EXTERNAL_INTERRUPT_FALLING, - EXTERNAL_INTERRUPT_RISING_FALLING, - TIMER_ALTERNATE_FUNCTION, - ALTERNATIVE, + INPUT, // GPIO_MODE_INPUT + OUTPUT_PUSHPULL, // GPIO_MODE_OUTPUT_PP + OUTPUT_OPENDRAIN, // GPIO_MODE_OUTPUT_OD + ANALOG, // GPIO_MODE_ANALOG + ALT_PP, // GPIO_MODE_AF_PP + ALT_OD, // GPIO_MODE_AF_OD + EXTI_RISING, // GPIO_MODE_IT_RISING + EXTI_FALLING, // GPIO_MODE_IT_FALLING + EXTI_RISING_FALLING, // GPIO_MODE_IT_RISING_FALLING + }; + static constexpr uint32_t to_hal_mode(OperationMode m) { + switch (m) { + case OperationMode::INPUT: + return GPIO_MODE_INPUT; + case OperationMode::OUTPUT_PUSHPULL: + return GPIO_MODE_OUTPUT_PP; + case OperationMode::OUTPUT_OPENDRAIN: + return GPIO_MODE_OUTPUT_OD; + case OperationMode::ANALOG: + return GPIO_MODE_ANALOG; + case OperationMode::ALT_PP: + return GPIO_MODE_AF_PP; + case OperationMode::ALT_OD: + return GPIO_MODE_AF_OD; + case OperationMode::EXTI_RISING: + return GPIO_MODE_IT_RISING; + case OperationMode::EXTI_FALLING: + return GPIO_MODE_IT_FALLING; + case OperationMode::EXTI_RISING_FALLING: + return GPIO_MODE_IT_RISING_FALLING; + } + } + enum class Pull : uint8_t { None, Up, Down }; + static constexpr uint32_t to_hal_pull(Pull p) { + switch (p) { + case Pull::None: + return GPIO_NOPULL; + case Pull::Up: + return GPIO_PULLUP; + case Pull::Down: + return GPIO_PULLDOWN; + } + } + enum class Speed : uint8_t { Low, Medium, High, VeryHigh }; + static constexpr uint32_t to_hal_speed(Speed s) { + switch (s) { + case Speed::Low: + return GPIO_SPEED_FREQ_LOW; + case Speed::Medium: + return GPIO_SPEED_FREQ_MEDIUM; + case Speed::High: + return GPIO_SPEED_FREQ_HIGH; + case Speed::VeryHigh: + return GPIO_SPEED_FREQ_VERY_HIGH; + } + } + enum class AlternateFunction : uint8_t { + NO_AF = 20, + AF0 = 15, + AF1 = 14, + AF2 = 13, + AF3 = 12, + AF4 = 11, + AF5 = 10, + AF6 = 9, + AF7 = 8, + AF8 = 7, + AF9 = 6, + AF10 = 5, + AF11 = 4, + AF12 = 3, + AF13 = 2, + AF14 = 1, + AF15 = 0 }; enum class Port : uint8_t { A, B, C, D, E, F, G, H }; static inline GPIO_TypeDef *port_to_reg(Port p) { @@ -81,18 +147,25 @@ struct GPIODomain { } } - struct Pin2 { + struct Pin { GPIODomain::Port port; uint32_t pin; + uint16_t afs; - consteval Pin2(GPIODomain::Port port, uint32_t pin) - : port(port), pin(pin) {} + inline constexpr bool valid_af(const AlternateFunction af) const { + if (af == AlternateFunction::NO_AF) + return true; + return ((1 << static_cast(af)) & afs) != 0; + } }; struct Entry { Port port; uint32_t pin; OperationMode mode; + Pull pull; + Speed speed; + AlternateFunction af; }; struct GPIO { @@ -100,7 +173,13 @@ struct GPIODomain { Entry e; - consteval GPIO(Pin2 pin, OperationMode mode) : e(pin.port, pin.pin, mode) {} + consteval GPIO(const Pin &pin, OperationMode mode, Pull pull, Speed speed, + AlternateFunction af = AlternateFunction::NO_AF) + : e{pin.port, pin.pin, mode, pull, speed, af} { + if (!pin.valid_af(af)) { + throw "Alternate function not valid for this pin"; + } + } template consteval void inscribe(Ctx &ctx) const { ctx.template add(e); @@ -108,8 +187,6 @@ struct GPIODomain { }; static constexpr std::size_t max_instances{110}; - static_assert(max_instances > 0, - "The number of instances must be greater than 0"); struct Config { std::tuple init_data{}; @@ -124,51 +201,17 @@ struct GPIODomain { for (std::size_t j = 0; j < i; ++j) { const auto &prev = pins[j]; if (prev.pin == e.pin && prev.port == e.port) { - struct gpio_already_inscribed {}; - throw gpio_already_inscribed{}; + throw "GPIO already inscribed"; } } - GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitTypeDef GPIO_InitStruct{}; GPIO_InitStruct.Pin = e.pin; - switch (e.mode) { - - case OperationMode::OUTPUT: - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - break; - - case OperationMode::INPUT: - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; - break; - - case OperationMode::ANALOG: - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - break; - case OperationMode::EXTERNAL_INTERRUPT_RISING: - GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; - GPIO_InitStruct.Pull = GPIO_PULLDOWN; - break; - case OperationMode::EXTERNAL_INTERRUPT_FALLING: - GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; - GPIO_InitStruct.Pull = GPIO_PULLDOWN; - break; - case OperationMode::EXTERNAL_INTERRUPT_RISING_FALLING: - GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; - GPIO_InitStruct.Pull = GPIO_PULLDOWN; - break; - // case OperationMode::TIMER_ALTERNATE_FUNCTION: - // GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - // GPIO_InitStruct.Pull = GPIO_NOPULL; - // GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - // GPIO_InitStruct.Alternate = pin.alternative_function; - // break; - - default: - break; + GPIO_InitStruct.Mode = to_hal_mode(e.mode); + GPIO_InitStruct.Pull = to_hal_pull(e.pull); + GPIO_InitStruct.Speed = to_hal_speed(e.speed); + if (e.mode == OperationMode::ALT_PP || e.mode == OperationMode::ALT_OD) { + GPIO_InitStruct.Alternate = static_cast(e.af); } cfgs[i].init_data = std::make_tuple(e.port, GPIO_InitStruct); @@ -179,14 +222,22 @@ struct GPIODomain { // Runtime object struct Instance { + private: GPIO_TypeDef *port; - uint16_t pin; + uint32_t pin; + + public: + constexpr Instance() : port{nullptr}, pin{0} {} + Instance(GPIO_TypeDef *p, uint32_t pin) + : port{p}, pin{static_cast(pin)} {} void turn_on() { HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET); } void turn_off() { HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET); } void toggle() { HAL_GPIO_TogglePin(port, pin); } + + GPIO_PinState read() { return HAL_GPIO_ReadPin(port, pin); } }; template struct Init { @@ -201,9 +252,7 @@ struct GPIODomain { enable_gpio_clock(port); HAL_GPIO_Init(port_to_reg(port), &gpio_init); - auto &inst = instances[i]; - inst.port = port_to_reg(port); - inst.pin = gpio_init.Pin; + instances[i] = Instance{port_to_reg(port), gpio_init.Pin}; } } }; diff --git a/Inc/HALAL/Models/Pin.hpp b/Inc/HALAL/Models/Pin.hpp index fd598fcd0..bc3a5331e 100644 --- a/Inc/HALAL/Models/Pin.hpp +++ b/Inc/HALAL/Models/Pin.hpp @@ -1,149 +1,151 @@ #include "HALAL/Models/GPIO.hpp" +using enum ST_LIB::GPIODomain::Port; + namespace ST_LIB { // Port A -constexpr GPIODomain::Pin2 PA0 {GPIODomain::Port::A, GPIO_PIN_0}; -constexpr GPIODomain::Pin2 PA1 {GPIODomain::Port::A, GPIO_PIN_1}; -constexpr GPIODomain::Pin2 PA2 {GPIODomain::Port::A, GPIO_PIN_2}; -constexpr GPIODomain::Pin2 PA3 {GPIODomain::Port::A, GPIO_PIN_3}; -constexpr GPIODomain::Pin2 PA4 {GPIODomain::Port::A, GPIO_PIN_4}; -constexpr GPIODomain::Pin2 PA5 {GPIODomain::Port::A, GPIO_PIN_5}; -constexpr GPIODomain::Pin2 PA6 {GPIODomain::Port::A, GPIO_PIN_6}; -constexpr GPIODomain::Pin2 PA7 {GPIODomain::Port::A, GPIO_PIN_7}; -constexpr GPIODomain::Pin2 PA8 {GPIODomain::Port::A, GPIO_PIN_8}; -constexpr GPIODomain::Pin2 PA9 {GPIODomain::Port::A, GPIO_PIN_9}; -constexpr GPIODomain::Pin2 PA10{GPIODomain::Port::A, GPIO_PIN_10}; -constexpr GPIODomain::Pin2 PA11{GPIODomain::Port::A, GPIO_PIN_11}; -constexpr GPIODomain::Pin2 PA12{GPIODomain::Port::A, GPIO_PIN_12}; -constexpr GPIODomain::Pin2 PA13{GPIODomain::Port::A, GPIO_PIN_13}; -constexpr GPIODomain::Pin2 PA14{GPIODomain::Port::A, GPIO_PIN_14}; -constexpr GPIODomain::Pin2 PA15{GPIODomain::Port::A, GPIO_PIN_15}; +constexpr GPIODomain::Pin PA0{A, GPIO_PIN_0, 0b0111110111111001}; +constexpr GPIODomain::Pin PA1{A, GPIO_PIN_1}; +constexpr GPIODomain::Pin PA2{A, GPIO_PIN_2}; +constexpr GPIODomain::Pin PA3{A, GPIO_PIN_3}; +constexpr GPIODomain::Pin PA4{A, GPIO_PIN_4}; +constexpr GPIODomain::Pin PA5{A, GPIO_PIN_5}; +constexpr GPIODomain::Pin PA6{A, GPIO_PIN_6}; +constexpr GPIODomain::Pin PA7{A, GPIO_PIN_7}; +constexpr GPIODomain::Pin PA8{A, GPIO_PIN_8}; +constexpr GPIODomain::Pin PA9{A, GPIO_PIN_9}; +constexpr GPIODomain::Pin PA10{A, GPIO_PIN_10}; +constexpr GPIODomain::Pin PA11{A, GPIO_PIN_11}; +constexpr GPIODomain::Pin PA12{A, GPIO_PIN_12}; +constexpr GPIODomain::Pin PA13{A, GPIO_PIN_13}; +constexpr GPIODomain::Pin PA14{A, GPIO_PIN_14}; +constexpr GPIODomain::Pin PA15{A, GPIO_PIN_15}; // Port B -constexpr GPIODomain::Pin2 PB0 {GPIODomain::Port::B, GPIO_PIN_0}; -constexpr GPIODomain::Pin2 PB1 {GPIODomain::Port::B, GPIO_PIN_1}; -constexpr GPIODomain::Pin2 PB2 {GPIODomain::Port::B, GPIO_PIN_2}; -constexpr GPIODomain::Pin2 PB3 {GPIODomain::Port::B, GPIO_PIN_3}; -constexpr GPIODomain::Pin2 PB4 {GPIODomain::Port::B, GPIO_PIN_4}; -constexpr GPIODomain::Pin2 PB5 {GPIODomain::Port::B, GPIO_PIN_5}; -constexpr GPIODomain::Pin2 PB6 {GPIODomain::Port::B, GPIO_PIN_6}; -constexpr GPIODomain::Pin2 PB7 {GPIODomain::Port::B, GPIO_PIN_7}; -constexpr GPIODomain::Pin2 PB8 {GPIODomain::Port::B, GPIO_PIN_8}; -constexpr GPIODomain::Pin2 PB9 {GPIODomain::Port::B, GPIO_PIN_9}; -constexpr GPIODomain::Pin2 PB10{GPIODomain::Port::B, GPIO_PIN_10}; -constexpr GPIODomain::Pin2 PB11{GPIODomain::Port::B, GPIO_PIN_11}; -constexpr GPIODomain::Pin2 PB12{GPIODomain::Port::B, GPIO_PIN_12}; -constexpr GPIODomain::Pin2 PB13{GPIODomain::Port::B, GPIO_PIN_13}; -constexpr GPIODomain::Pin2 PB14{GPIODomain::Port::B, GPIO_PIN_14}; -constexpr GPIODomain::Pin2 PB15{GPIODomain::Port::B, GPIO_PIN_15}; +constexpr GPIODomain::Pin PB0{B, GPIO_PIN_0}; +constexpr GPIODomain::Pin PB1{B, GPIO_PIN_1}; +constexpr GPIODomain::Pin PB2{B, GPIO_PIN_2}; +constexpr GPIODomain::Pin PB3{B, GPIO_PIN_3}; +constexpr GPIODomain::Pin PB4{B, GPIO_PIN_4}; +constexpr GPIODomain::Pin PB5{B, GPIO_PIN_5}; +constexpr GPIODomain::Pin PB6{B, GPIO_PIN_6}; +constexpr GPIODomain::Pin PB7{B, GPIO_PIN_7}; +constexpr GPIODomain::Pin PB8{B, GPIO_PIN_8}; +constexpr GPIODomain::Pin PB9{B, GPIO_PIN_9}; +constexpr GPIODomain::Pin PB10{B, GPIO_PIN_10}; +constexpr GPIODomain::Pin PB11{B, GPIO_PIN_11}; +constexpr GPIODomain::Pin PB12{B, GPIO_PIN_12}; +constexpr GPIODomain::Pin PB13{B, GPIO_PIN_13}; +constexpr GPIODomain::Pin PB14{B, GPIO_PIN_14}; +constexpr GPIODomain::Pin PB15{B, GPIO_PIN_15}; // Port C -constexpr GPIODomain::Pin2 PC0 {GPIODomain::Port::C, GPIO_PIN_0}; -constexpr GPIODomain::Pin2 PC1 {GPIODomain::Port::C, GPIO_PIN_1}; -constexpr GPIODomain::Pin2 PC2 {GPIODomain::Port::C, GPIO_PIN_2}; -constexpr GPIODomain::Pin2 PC3 {GPIODomain::Port::C, GPIO_PIN_3}; -constexpr GPIODomain::Pin2 PC4 {GPIODomain::Port::C, GPIO_PIN_4}; -constexpr GPIODomain::Pin2 PC5 {GPIODomain::Port::C, GPIO_PIN_5}; -constexpr GPIODomain::Pin2 PC6 {GPIODomain::Port::C, GPIO_PIN_6}; -constexpr GPIODomain::Pin2 PC7 {GPIODomain::Port::C, GPIO_PIN_7}; -constexpr GPIODomain::Pin2 PC8 {GPIODomain::Port::C, GPIO_PIN_8}; -constexpr GPIODomain::Pin2 PC9 {GPIODomain::Port::C, GPIO_PIN_9}; -constexpr GPIODomain::Pin2 PC10{GPIODomain::Port::C, GPIO_PIN_10}; -constexpr GPIODomain::Pin2 PC11{GPIODomain::Port::C, GPIO_PIN_11}; -constexpr GPIODomain::Pin2 PC12{GPIODomain::Port::C, GPIO_PIN_12}; -constexpr GPIODomain::Pin2 PC13{GPIODomain::Port::C, GPIO_PIN_13}; -constexpr GPIODomain::Pin2 PC14{GPIODomain::Port::C, GPIO_PIN_14}; -constexpr GPIODomain::Pin2 PC15{GPIODomain::Port::C, GPIO_PIN_15}; +constexpr GPIODomain::Pin PC0{C, GPIO_PIN_0}; +constexpr GPIODomain::Pin PC1{C, GPIO_PIN_1}; +constexpr GPIODomain::Pin PC2{C, GPIO_PIN_2}; +constexpr GPIODomain::Pin PC3{C, GPIO_PIN_3}; +constexpr GPIODomain::Pin PC4{C, GPIO_PIN_4}; +constexpr GPIODomain::Pin PC5{C, GPIO_PIN_5}; +constexpr GPIODomain::Pin PC6{C, GPIO_PIN_6}; +constexpr GPIODomain::Pin PC7{C, GPIO_PIN_7}; +constexpr GPIODomain::Pin PC8{C, GPIO_PIN_8}; +constexpr GPIODomain::Pin PC9{C, GPIO_PIN_9}; +constexpr GPIODomain::Pin PC10{C, GPIO_PIN_10}; +constexpr GPIODomain::Pin PC11{C, GPIO_PIN_11}; +constexpr GPIODomain::Pin PC12{C, GPIO_PIN_12}; +constexpr GPIODomain::Pin PC13{C, GPIO_PIN_13}; +constexpr GPIODomain::Pin PC14{C, GPIO_PIN_14}; +constexpr GPIODomain::Pin PC15{C, GPIO_PIN_15}; // Port D -constexpr GPIODomain::Pin2 PD0 {GPIODomain::Port::D, GPIO_PIN_0}; -constexpr GPIODomain::Pin2 PD1 {GPIODomain::Port::D, GPIO_PIN_1}; -constexpr GPIODomain::Pin2 PD2 {GPIODomain::Port::D, GPIO_PIN_2}; -constexpr GPIODomain::Pin2 PD3 {GPIODomain::Port::D, GPIO_PIN_3}; -constexpr GPIODomain::Pin2 PD4 {GPIODomain::Port::D, GPIO_PIN_4}; -constexpr GPIODomain::Pin2 PD5 {GPIODomain::Port::D, GPIO_PIN_5}; -constexpr GPIODomain::Pin2 PD6 {GPIODomain::Port::D, GPIO_PIN_6}; -constexpr GPIODomain::Pin2 PD7 {GPIODomain::Port::D, GPIO_PIN_7}; -constexpr GPIODomain::Pin2 PD8 {GPIODomain::Port::D, GPIO_PIN_8}; -constexpr GPIODomain::Pin2 PD9 {GPIODomain::Port::D, GPIO_PIN_9}; -constexpr GPIODomain::Pin2 PD10{GPIODomain::Port::D, GPIO_PIN_10}; -constexpr GPIODomain::Pin2 PD11{GPIODomain::Port::D, GPIO_PIN_11}; -constexpr GPIODomain::Pin2 PD12{GPIODomain::Port::D, GPIO_PIN_12}; -constexpr GPIODomain::Pin2 PD13{GPIODomain::Port::D, GPIO_PIN_13}; -constexpr GPIODomain::Pin2 PD14{GPIODomain::Port::D, GPIO_PIN_14}; -constexpr GPIODomain::Pin2 PD15{GPIODomain::Port::D, GPIO_PIN_15}; +constexpr GPIODomain::Pin PD0{D, GPIO_PIN_0}; +constexpr GPIODomain::Pin PD1{D, GPIO_PIN_1}; +constexpr GPIODomain::Pin PD2{D, GPIO_PIN_2}; +constexpr GPIODomain::Pin PD3{D, GPIO_PIN_3}; +constexpr GPIODomain::Pin PD4{D, GPIO_PIN_4}; +constexpr GPIODomain::Pin PD5{D, GPIO_PIN_5}; +constexpr GPIODomain::Pin PD6{D, GPIO_PIN_6}; +constexpr GPIODomain::Pin PD7{D, GPIO_PIN_7}; +constexpr GPIODomain::Pin PD8{D, GPIO_PIN_8}; +constexpr GPIODomain::Pin PD9{D, GPIO_PIN_9}; +constexpr GPIODomain::Pin PD10{D, GPIO_PIN_10}; +constexpr GPIODomain::Pin PD11{D, GPIO_PIN_11}; +constexpr GPIODomain::Pin PD12{D, GPIO_PIN_12}; +constexpr GPIODomain::Pin PD13{D, GPIO_PIN_13}; +constexpr GPIODomain::Pin PD14{D, GPIO_PIN_14}; +constexpr GPIODomain::Pin PD15{D, GPIO_PIN_15}; // Port E -constexpr GPIODomain::Pin2 PE0 {GPIODomain::Port::E, GPIO_PIN_0}; -constexpr GPIODomain::Pin2 PE1 {GPIODomain::Port::E, GPIO_PIN_1}; -constexpr GPIODomain::Pin2 PE2 {GPIODomain::Port::E, GPIO_PIN_2}; -constexpr GPIODomain::Pin2 PE3 {GPIODomain::Port::E, GPIO_PIN_3}; -constexpr GPIODomain::Pin2 PE4 {GPIODomain::Port::E, GPIO_PIN_4}; -constexpr GPIODomain::Pin2 PE5 {GPIODomain::Port::E, GPIO_PIN_5}; -constexpr GPIODomain::Pin2 PE6 {GPIODomain::Port::E, GPIO_PIN_6}; -constexpr GPIODomain::Pin2 PE7 {GPIODomain::Port::E, GPIO_PIN_7}; -constexpr GPIODomain::Pin2 PE8 {GPIODomain::Port::E, GPIO_PIN_8}; -constexpr GPIODomain::Pin2 PE9 {GPIODomain::Port::E, GPIO_PIN_9}; -constexpr GPIODomain::Pin2 PE10{GPIODomain::Port::E, GPIO_PIN_10}; -constexpr GPIODomain::Pin2 PE11{GPIODomain::Port::E, GPIO_PIN_11}; -constexpr GPIODomain::Pin2 PE12{GPIODomain::Port::E, GPIO_PIN_12}; -constexpr GPIODomain::Pin2 PE13{GPIODomain::Port::E, GPIO_PIN_13}; -constexpr GPIODomain::Pin2 PE14{GPIODomain::Port::E, GPIO_PIN_14}; -constexpr GPIODomain::Pin2 PE15{GPIODomain::Port::E, GPIO_PIN_15}; +constexpr GPIODomain::Pin PE0{E, GPIO_PIN_0}; +constexpr GPIODomain::Pin PE1{E, GPIO_PIN_1}; +constexpr GPIODomain::Pin PE2{E, GPIO_PIN_2}; +constexpr GPIODomain::Pin PE3{E, GPIO_PIN_3}; +constexpr GPIODomain::Pin PE4{E, GPIO_PIN_4}; +constexpr GPIODomain::Pin PE5{E, GPIO_PIN_5}; +constexpr GPIODomain::Pin PE6{E, GPIO_PIN_6}; +constexpr GPIODomain::Pin PE7{E, GPIO_PIN_7}; +constexpr GPIODomain::Pin PE8{E, GPIO_PIN_8}; +constexpr GPIODomain::Pin PE9{E, GPIO_PIN_9}; +constexpr GPIODomain::Pin PE10{E, GPIO_PIN_10}; +constexpr GPIODomain::Pin PE11{E, GPIO_PIN_11}; +constexpr GPIODomain::Pin PE12{E, GPIO_PIN_12}; +constexpr GPIODomain::Pin PE13{E, GPIO_PIN_13}; +constexpr GPIODomain::Pin PE14{E, GPIO_PIN_14}; +constexpr GPIODomain::Pin PE15{E, GPIO_PIN_15}; // Port F -constexpr GPIODomain::Pin2 PF0 {GPIODomain::Port::F, GPIO_PIN_0}; -constexpr GPIODomain::Pin2 PF1 {GPIODomain::Port::F, GPIO_PIN_1}; -constexpr GPIODomain::Pin2 PF2 {GPIODomain::Port::F, GPIO_PIN_2}; -constexpr GPIODomain::Pin2 PF3 {GPIODomain::Port::F, GPIO_PIN_3}; -constexpr GPIODomain::Pin2 PF4 {GPIODomain::Port::F, GPIO_PIN_4}; -constexpr GPIODomain::Pin2 PF5 {GPIODomain::Port::F, GPIO_PIN_5}; -constexpr GPIODomain::Pin2 PF6 {GPIODomain::Port::F, GPIO_PIN_6}; -constexpr GPIODomain::Pin2 PF7 {GPIODomain::Port::F, GPIO_PIN_7}; -constexpr GPIODomain::Pin2 PF8 {GPIODomain::Port::F, GPIO_PIN_8}; -constexpr GPIODomain::Pin2 PF9 {GPIODomain::Port::F, GPIO_PIN_9}; -constexpr GPIODomain::Pin2 PF10{GPIODomain::Port::F, GPIO_PIN_10}; -constexpr GPIODomain::Pin2 PF11{GPIODomain::Port::F, GPIO_PIN_11}; -constexpr GPIODomain::Pin2 PF12{GPIODomain::Port::F, GPIO_PIN_12}; -constexpr GPIODomain::Pin2 PF13{GPIODomain::Port::F, GPIO_PIN_13}; -constexpr GPIODomain::Pin2 PF14{GPIODomain::Port::F, GPIO_PIN_14}; -constexpr GPIODomain::Pin2 PF15{GPIODomain::Port::F, GPIO_PIN_15}; +constexpr GPIODomain::Pin PF0{F, GPIO_PIN_0}; +constexpr GPIODomain::Pin PF1{F, GPIO_PIN_1}; +constexpr GPIODomain::Pin PF2{F, GPIO_PIN_2}; +constexpr GPIODomain::Pin PF3{F, GPIO_PIN_3}; +constexpr GPIODomain::Pin PF4{F, GPIO_PIN_4}; +constexpr GPIODomain::Pin PF5{F, GPIO_PIN_5}; +constexpr GPIODomain::Pin PF6{F, GPIO_PIN_6}; +constexpr GPIODomain::Pin PF7{F, GPIO_PIN_7}; +constexpr GPIODomain::Pin PF8{F, GPIO_PIN_8}; +constexpr GPIODomain::Pin PF9{F, GPIO_PIN_9}; +constexpr GPIODomain::Pin PF10{F, GPIO_PIN_10}; +constexpr GPIODomain::Pin PF11{F, GPIO_PIN_11}; +constexpr GPIODomain::Pin PF12{F, GPIO_PIN_12}; +constexpr GPIODomain::Pin PF13{F, GPIO_PIN_13}; +constexpr GPIODomain::Pin PF14{F, GPIO_PIN_14}; +constexpr GPIODomain::Pin PF15{F, GPIO_PIN_15}; // Port G -constexpr GPIODomain::Pin2 PG0 {GPIODomain::Port::G, GPIO_PIN_0}; -constexpr GPIODomain::Pin2 PG1 {GPIODomain::Port::G, GPIO_PIN_1}; -constexpr GPIODomain::Pin2 PG2 {GPIODomain::Port::G, GPIO_PIN_2}; -constexpr GPIODomain::Pin2 PG3 {GPIODomain::Port::G, GPIO_PIN_3}; -constexpr GPIODomain::Pin2 PG4 {GPIODomain::Port::G, GPIO_PIN_4}; -constexpr GPIODomain::Pin2 PG5 {GPIODomain::Port::G, GPIO_PIN_5}; -constexpr GPIODomain::Pin2 PG6 {GPIODomain::Port::G, GPIO_PIN_6}; -constexpr GPIODomain::Pin2 PG7 {GPIODomain::Port::G, GPIO_PIN_7}; -constexpr GPIODomain::Pin2 PG8 {GPIODomain::Port::G, GPIO_PIN_8}; -constexpr GPIODomain::Pin2 PG9 {GPIODomain::Port::G, GPIO_PIN_9}; -constexpr GPIODomain::Pin2 PG10{GPIODomain::Port::G, GPIO_PIN_10}; -constexpr GPIODomain::Pin2 PG11{GPIODomain::Port::G, GPIO_PIN_11}; -constexpr GPIODomain::Pin2 PG12{GPIODomain::Port::G, GPIO_PIN_12}; -constexpr GPIODomain::Pin2 PG13{GPIODomain::Port::G, GPIO_PIN_13}; -constexpr GPIODomain::Pin2 PG14{GPIODomain::Port::G, GPIO_PIN_14}; -constexpr GPIODomain::Pin2 PG15{GPIODomain::Port::G, GPIO_PIN_15}; +constexpr GPIODomain::Pin PG0{G, GPIO_PIN_0}; +constexpr GPIODomain::Pin PG1{G, GPIO_PIN_1}; +constexpr GPIODomain::Pin PG2{G, GPIO_PIN_2}; +constexpr GPIODomain::Pin PG3{G, GPIO_PIN_3}; +constexpr GPIODomain::Pin PG4{G, GPIO_PIN_4}; +constexpr GPIODomain::Pin PG5{G, GPIO_PIN_5}; +constexpr GPIODomain::Pin PG6{G, GPIO_PIN_6}; +constexpr GPIODomain::Pin PG7{G, GPIO_PIN_7}; +constexpr GPIODomain::Pin PG8{G, GPIO_PIN_8}; +constexpr GPIODomain::Pin PG9{G, GPIO_PIN_9}; +constexpr GPIODomain::Pin PG10{G, GPIO_PIN_10}; +constexpr GPIODomain::Pin PG11{G, GPIO_PIN_11}; +constexpr GPIODomain::Pin PG12{G, GPIO_PIN_12}; +constexpr GPIODomain::Pin PG13{G, GPIO_PIN_13}; +constexpr GPIODomain::Pin PG14{G, GPIO_PIN_14}; +constexpr GPIODomain::Pin PG15{G, GPIO_PIN_15}; // Port H -constexpr GPIODomain::Pin2 PH0 {GPIODomain::Port::H, GPIO_PIN_0}; -constexpr GPIODomain::Pin2 PH1 {GPIODomain::Port::H, GPIO_PIN_1}; -constexpr GPIODomain::Pin2 PH2 {GPIODomain::Port::H, GPIO_PIN_2}; -constexpr GPIODomain::Pin2 PH3 {GPIODomain::Port::H, GPIO_PIN_3}; -constexpr GPIODomain::Pin2 PH4 {GPIODomain::Port::H, GPIO_PIN_4}; -constexpr GPIODomain::Pin2 PH5 {GPIODomain::Port::H, GPIO_PIN_5}; -constexpr GPIODomain::Pin2 PH6 {GPIODomain::Port::H, GPIO_PIN_6}; -constexpr GPIODomain::Pin2 PH7 {GPIODomain::Port::H, GPIO_PIN_7}; -constexpr GPIODomain::Pin2 PH8 {GPIODomain::Port::H, GPIO_PIN_8}; -constexpr GPIODomain::Pin2 PH9 {GPIODomain::Port::H, GPIO_PIN_9}; -constexpr GPIODomain::Pin2 PH10{GPIODomain::Port::H, GPIO_PIN_10}; -constexpr GPIODomain::Pin2 PH11{GPIODomain::Port::H, GPIO_PIN_11}; -constexpr GPIODomain::Pin2 PH12{GPIODomain::Port::H, GPIO_PIN_12}; -constexpr GPIODomain::Pin2 PH13{GPIODomain::Port::H, GPIO_PIN_13}; -constexpr GPIODomain::Pin2 PH14{GPIODomain::Port::H, GPIO_PIN_14}; -constexpr GPIODomain::Pin2 PH15{GPIODomain::Port::H, GPIO_PIN_15}; +constexpr GPIODomain::Pin PH0{H, GPIO_PIN_0}; +constexpr GPIODomain::Pin PH1{H, GPIO_PIN_1}; +constexpr GPIODomain::Pin PH2{H, GPIO_PIN_2}; +constexpr GPIODomain::Pin PH3{H, GPIO_PIN_3}; +constexpr GPIODomain::Pin PH4{H, GPIO_PIN_4}; +constexpr GPIODomain::Pin PH5{H, GPIO_PIN_5}; +constexpr GPIODomain::Pin PH6{H, GPIO_PIN_6}; +constexpr GPIODomain::Pin PH7{H, GPIO_PIN_7}; +constexpr GPIODomain::Pin PH8{H, GPIO_PIN_8}; +constexpr GPIODomain::Pin PH9{H, GPIO_PIN_9}; +constexpr GPIODomain::Pin PH10{H, GPIO_PIN_10}; +constexpr GPIODomain::Pin PH11{H, GPIO_PIN_11}; +constexpr GPIODomain::Pin PH12{H, GPIO_PIN_12}; +constexpr GPIODomain::Pin PH13{H, GPIO_PIN_13}; +constexpr GPIODomain::Pin PH14{H, GPIO_PIN_14}; +constexpr GPIODomain::Pin PH15{H, GPIO_PIN_15}; } // namespace ST_LIB \ No newline at end of file diff --git a/Inc/ST-LIB.hpp b/Inc/ST-LIB.hpp index 2f416eb5f..dff92504d 100644 --- a/Inc/ST-LIB.hpp +++ b/Inc/ST-LIB.hpp @@ -46,11 +46,13 @@ template struct BuildCtx { } } - template consteval void add(typename D::Entry e) { + template consteval std::size_t add(typename D::Entry e) { constexpr std::size_t I = domain_index(); auto &arr = std::get(storage); auto &size = sizes[I]; + const auto idx = size; arr[size++] = e; + return idx; } template consteval auto span() const { @@ -60,60 +62,72 @@ template struct BuildCtx { using E = typename D::Entry; return std::span{arr.data(), size}; } -}; -template consteval std::size_t domain_count() { - return (... + - (std::is_same_v::domain, - Domain> - ? 1u - : 0u)); -} + template consteval std::size_t size() const { + constexpr std::size_t I = domain_index(); + return sizes[I]; + } +}; -using DomainsCtx = BuildCtx; +using DomainsCtx = BuildCtx; template struct Board { - // ========== build compile-time ========== - static consteval auto build() { + static consteval auto build_ctx() { DomainsCtx ctx{}; - (devs.inscribe(ctx), ...); + return ctx; + } + + static constexpr auto ctx = build_ctx(); - constexpr std::size_t gpioN = domain_count(); - // constexpr std::size_t adcN = domain_count(); - // constexpr std::size_t pwmN = domain_count(); + template static consteval std::size_t domain_size() { + return ctx.template span().size(); + } + + static consteval auto build() { + constexpr std::size_t gpioN = domain_size(); + constexpr std::size_t doutN = domain_size(); + constexpr std::size_t dinN = domain_size(); + // ... struct ConfigBundle { std::array gpio_cfgs; - // std::array adc_cgfs; - // std::array pwm_cgfs; + std::array dout_cfgs; + std::array din_cfgs; + // ... }; return ConfigBundle{ .gpio_cfgs = GPIODomain::template build(ctx.template span()), - // .adc_cgfs = - // ADCDomain::template build(ctx.template span()), - // .pwm_cgfs = - // PWMDomain::template build(ctx.template span()), + .dout_cfgs = DigitalOutputDomain::template build( + ctx.template span()), + .din_cfgs = DigitalInputDomain::template build( + ctx.template span()), + // ... }; } - // ========== init runtime ========== - static void init() { - static constexpr auto cfg = build(); + static constexpr auto cfg = build(); - constexpr std::size_t gpioN = domain_count(); - // constexpr std::size_t adcN = domain_count(); - // constexpr std::size_t pwmN = domain_count(); + static void init() { + constexpr std::size_t gpioN = domain_size(); + constexpr std::size_t doutN = domain_size(); + constexpr std::size_t dinN = domain_size(); + // ... GPIODomain::Init::init(cfg.gpio_cfgs); - // ADCDomain::Init::init(cfg.adc_cfgs); - // PWMDomain::Init::init(cfg.pwm_cfgs); + DigitalOutputDomain::Init::init(cfg.dout_cfgs, + GPIODomain::Init::instances); + DigitalInputDomain::Init::init(cfg.din_cfgs, + GPIODomain::Init::instances); + // ... } - template static consteval std::size_t domain_size() { - return domain_count(); + template + static consteval std::size_t domain_size_for_instance() { + return domain_size(); } template @@ -154,7 +168,7 @@ template struct Board { using Domain = typename DevT::domain; constexpr std::size_t idx = domain_index_of(); - constexpr std::size_t N = domain_size(); + constexpr std::size_t N = domain_size_for_instance(); return Domain::template Init::instances[idx]; } diff --git a/Inc/ST-LIB_LOW/DigitalInput2.hpp b/Inc/ST-LIB_LOW/DigitalInput2.hpp new file mode 100644 index 000000000..e161e39a5 --- /dev/null +++ b/Inc/ST-LIB_LOW/DigitalInput2.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include "HALAL/Models/GPIO.hpp" + +using ST_LIB::GPIODomain; + +namespace ST_LIB { +struct DigitalInputDomain { + struct Entry { + size_t gpio_idx; + }; + struct DigitalInput { + GPIODomain::GPIO gpio; + using domain = DigitalInputDomain; + + consteval DigitalInput(const GPIODomain::Pin &pin, + GPIODomain::Pull pull = GPIODomain::Pull::None, + GPIODomain::Speed speed = GPIODomain::Speed::Low) + : gpio{pin, GPIODomain::OperationMode::INPUT, pull, speed} {} + + template consteval void inscribe(Ctx &ctx) const { + const auto gpio_idx = ctx.template add(gpio.e); + Entry e{.gpio_idx = gpio_idx}; + ctx.template add(e); + } + }; + + static constexpr std::size_t max_instances{110}; + + struct Config { + size_t gpio_idx; + }; + + template + static consteval array build(span outputs) { + array cfgs{}; + + for (std::size_t i = 0; i < N; ++i) { + cfgs[i].gpio_idx = outputs[i].gpio_idx; + } + return cfgs; + } + + struct Instance { + GPIODomain::Instance *gpio_instance; + + GPIO_PinState read() { return gpio_instance->read(); } + }; + + template struct Init { + static inline std::array instances{}; + + static void init(std::span cfgs, + std::span gpio_instances) { + for (std::size_t i = 0; i < N; ++i) { + const auto &e = cfgs[i]; + + instances[i].gpio_instance = &gpio_instances[e.gpio_idx]; + } + } + }; +}; +} // namespace ST_LIB diff --git a/Inc/ST-LIB_LOW/DigitalOutput2.hpp b/Inc/ST-LIB_LOW/DigitalOutput2.hpp new file mode 100644 index 000000000..7dcad5b65 --- /dev/null +++ b/Inc/ST-LIB_LOW/DigitalOutput2.hpp @@ -0,0 +1,75 @@ +#pragma once + +#include "HALAL/Models/GPIO.hpp" + +using ST_LIB::GPIODomain; + +namespace ST_LIB { +struct DigitalOutputDomain { + enum class OutputMode : uint8_t { + PUSH_PULL = + static_cast(GPIODomain::OperationMode::OUTPUT_PUSHPULL), + OPEN_DRAIN = + static_cast(GPIODomain::OperationMode::OUTPUT_OPENDRAIN), + }; + struct Entry { + size_t gpio_idx; + }; + struct DigitalOutput { + GPIODomain::GPIO gpio; + using domain = DigitalOutputDomain; + + consteval DigitalOutput(const GPIODomain::Pin &pin, + OutputMode mode = OutputMode::PUSH_PULL, + GPIODomain::Pull pull = GPIODomain::Pull::None, + GPIODomain::Speed speed = GPIODomain::Speed::Low) + : gpio{pin, static_cast(mode), pull, speed} { + } + + template consteval void inscribe(Ctx &ctx) const { + const auto gpio_idx = ctx.template add(gpio.e); + Entry e{.gpio_idx = gpio_idx}; + ctx.template add(e); + } + }; + + static constexpr std::size_t max_instances{110}; + + struct Config { + size_t gpio_idx; + }; + + template + static consteval array build(span outputs) { + array cfgs{}; + + for (std::size_t i = 0; i < N; ++i) { + cfgs[i].gpio_idx = outputs[i].gpio_idx; + } + return cfgs; + } + + struct Instance { + GPIODomain::Instance *gpio_instance; + + void turn_on() { gpio_instance->turn_on(); } + + void turn_off() { gpio_instance->turn_off(); } + + void toggle() { gpio_instance->toggle(); } + }; + + template struct Init { + static inline std::array instances{}; + + static void init(std::span cfgs, + std::span gpio_instances) { + for (std::size_t i = 0; i < N; ++i) { + const auto &e = cfgs[i]; + + instances[i].gpio_instance = &gpio_instances[e.gpio_idx]; + } + } + }; +}; +} // namespace ST_LIB diff --git a/Inc/ST-LIB_LOW/ST-LIB_LOW.hpp b/Inc/ST-LIB_LOW/ST-LIB_LOW.hpp index 5473a9d1e..b73165c24 100644 --- a/Inc/ST-LIB_LOW/ST-LIB_LOW.hpp +++ b/Inc/ST-LIB_LOW/ST-LIB_LOW.hpp @@ -1,5 +1,8 @@ #pragma once +#include "ST-LIB_LOW/DigitalOutput2.hpp" +#include "ST-LIB_LOW/DigitalInput2.hpp" + #include "Clocks/Counter.hpp" #include "Clocks/Stopwatch.hpp" #include "Sensors/LinearSensor/LinearSensor.hpp" From b245442443498a28a5e9275a2cb1fa936fd78300 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Wed, 3 Dec 2025 21:37:15 +0100 Subject: [PATCH 024/109] todo lo facil hecho, queda lo dificil (handle y global_handle) --- Inc/HALAL/HALAL.hpp | 1 + Inc/HALAL/Models/DMA/DMA.hpp | 352 +++-------------------------- Inc/HALAL/Models/DMA/DMA2.hpp | 374 +++++++++++++++++++++++++++++++ Src/HALAL/Models/DMA/DMA-old.cpp | 18 ++ Src/HALAL/Models/DMA/DMA.cpp | 51 +++-- Src/HALAL/Models/DMA/DMA2.cpp | 0 6 files changed, 466 insertions(+), 330 deletions(-) create mode 100644 Inc/HALAL/Models/DMA/DMA2.hpp create mode 100644 Src/HALAL/Models/DMA/DMA-old.cpp create mode 100644 Src/HALAL/Models/DMA/DMA2.cpp diff --git a/Inc/HALAL/HALAL.hpp b/Inc/HALAL/HALAL.hpp index 316c9605a..6b20c7bc8 100644 --- a/Inc/HALAL/HALAL.hpp +++ b/Inc/HALAL/HALAL.hpp @@ -5,6 +5,7 @@ #include "HALAL/Models/HALconfig/HALconfig.hpp" #include "HALAL/Models/DMA/DMA.hpp" +#include "HALAL/Models/DMA/DMA2.hpp" #include "HALAL/Services/DigitalOutputService/DigitalOutputService.hpp" #include "HALAL/Services/DigitalInputService/DigitalInputService.hpp" diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 0bcf53946..a9799cbb9 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -1,322 +1,42 @@ +/* + * DMA.hpp + * + * Created on: 10 dic. 2022 + * Author: aleja + */ + #pragma once + #include "C++Utilities/CppUtils.hpp" #include "stm32h7xx_hal.h" -#include "main.h" #include "HALAL/Models/MPUManager/MPUManager.hpp" -#include -#include -#include -#include -#include - -using std::array; -using std::size_t; -using std::span; -using std::tuple; - -#define MAX_STREAMS 16 - - -namespace ST_LIB { - struct DMA_Domain { - using xTypeDef = std::variant< - ADC_TypeDef*, - I2C_TypeDef*, - SPI_TypeDef*, - FMAC_TypeDef* - >; - using xHandleDef = std::variant< - ADC_HandleTypeDef*, - I2C_HandleTypeDef*, - SPI_HandleTypeDef*, - FMAC_HandleTypeDef* - >; - - enum class Instance : uint8_t {adc1, adc2, adc3, - i2c1, i2c2, i2c3, i2c5, - spi1, spi2, spi3, spi4, spi5, - fmac}; - - enum class Stream : uint8_t {dma1_stream0, dma1_stream1, dma1_stream2, dma1_stream3, - dma1_stream4, dma1_stream5, dma1_stream6, dma1_stream7, - dma2_stream0, dma2_stream1, dma2_stream2, dma2_stream3, - dma2_stream4, dma2_stream5, dma2_stream6, dma2_stream7}; - - static inline xTypeDef instance_to_xTypeDef(Instance i) { - switch (i) { - case Instance::adc1: return ADC1; - case Instance::adc2: return ADC2; - case Instance::adc3: return ADC3; - - case Instance::i2c1: return I2C1; - case Instance::i2c2: return I2C2; - case Instance::i2c3: return I2C3; - case Instance::i2c5: return I2C5; - - case Instance::spi1: return SPI1; - case Instance::spi2: return SPI2; - case Instance::spi3: return SPI3; - case Instance::spi4: return SPI4; - case Instance::spi5: return SPI5; - - case Instance::fmac: return FMAC; - } - } - - static inline DMA_Stream_TypeDef* stream_to_DMA_StreamTypeDef(Stream s) { - switch (s) { - case Stream::dma1_stream0: return DMA1_Stream0; - case Stream::dma1_stream1: return DMA1_Stream1; - case Stream::dma1_stream2: return DMA1_Stream2; - case Stream::dma1_stream3: return DMA1_Stream3; - case Stream::dma1_stream4: return DMA1_Stream4; - case Stream::dma1_stream5: return DMA1_Stream5; - case Stream::dma1_stream6: return DMA1_Stream6; - case Stream::dma1_stream7: return DMA1_Stream7; - - case Stream::dma2_stream0: return DMA2_Stream0; - case Stream::dma2_stream1: return DMA2_Stream1; - case Stream::dma2_stream2: return DMA2_Stream2; - case Stream::dma2_stream3: return DMA2_Stream3; - case Stream::dma2_stream4: return DMA2_Stream4; - case Stream::dma2_stream5: return DMA2_Stream5; - case Stream::dma2_stream6: return DMA2_Stream6; - case Stream::dma2_stream7: return DMA2_Stream7; - } - } - - struct Entry { - Instance instance; - std::array, 3> streams{}; - uint8_t count = 0; - }; - - struct DMA{ - using domain = DMA_Domain; - - Entry e; - - template - consteval DMA(Instance instance) : e(instance) { - static_assert(sizeof...(Ss) <= 3, "Máximo 3 streams"); - size_t i = 0; - ((e.streams[i++] = std::make_tuple(Ss, get_irqn(Ss))), ...); - e.count = i; - } - - template consteval void inscribe(Ctx &ctx) const { - ctx.template add(e); - } - }; - - static constexpr std::size_t max_instances {MAX_STREAMS}; - static_assert(max_instances > 0, "The number of instances must be greater than 0"); - - struct Config { - std::tuple> init_data{}; - }; - - static inline IRQn_Type get_irqn(Stream stream) { - if (stream == Stream::dma1_stream0) return DMA1_Stream0_IRQn; - else if (stream == Stream::dma1_stream1) return DMA1_Stream1_IRQn; - else if (stream == Stream::dma1_stream2) return DMA1_Stream2_IRQn; - else if (stream == Stream::dma1_stream3) return DMA1_Stream3_IRQn; - else if (stream == Stream::dma1_stream4) return DMA1_Stream4_IRQn; - else if (stream == Stream::dma1_stream5) return DMA1_Stream5_IRQn; - else if (stream == Stream::dma1_stream6) return DMA1_Stream6_IRQn; - else if (stream == Stream::dma1_stream7) return DMA1_Stream7_IRQn; - - else if (stream == Stream::dma2_stream0) return DMA2_Stream0_IRQn; - else if (stream == Stream::dma2_stream1) return DMA2_Stream1_IRQn; - else if (stream == Stream::dma2_stream2) return DMA2_Stream2_IRQn; - else if (stream == Stream::dma2_stream3) return DMA2_Stream3_IRQn; - else if (stream == Stream::dma2_stream4) return DMA2_Stream4_IRQn; - else if (stream == Stream::dma2_stream5) return DMA2_Stream5_IRQn; - else if (stream == Stream::dma2_stream6) return DMA2_Stream6_IRQn; - else if (stream == Stream::dma2_stream7) return DMA2_Stream7_IRQn; - else ErrorHandler("Unknown DMA stream"); - return DMA1_Stream0_IRQn; // Nunca se alcanza - } - - // Si quitas el auto peta todo - static consteval inline bool is_one_of(Instance instance, auto... bases) { - return ((instance == bases) || ...); - } - - static consteval inline bool is_spi(Instance instance) { - return is_one_of(instance, Instance::spi1, Instance::spi2, - Instance::spi3, Instance::spi4, Instance::spi5); - } - - static consteval inline bool is_i2c(Instance instance) { - return is_one_of(instance, Instance::i2c1, Instance::i2c2, - Instance::i2c3, Instance::i2c5); - } - - static consteval inline bool is_adc(Instance instance) { - return is_one_of(instance, Instance::adc1, Instance::adc2, Instance::adc3); - } - - static consteval inline bool is_fmac(Instance instance) { - return instance == Instance::fmac; - } - - static consteval inline uint32_t get_Request(Instance instance, uint8_t i) { - if (instance == Instance::adc1) return DMA_REQUEST_ADC1; - if (instance == Instance::adc2) return DMA_REQUEST_ADC2; - if (instance == Instance::adc3) return DMA_REQUEST_ADC3; - - if (instance == Instance::i2c1 && i == 0) return DMA_REQUEST_I2C1_RX; - if (instance == Instance::i2c1 && i == 1) return DMA_REQUEST_I2C1_TX; - if (instance == Instance::i2c2 && i == 0) return DMA_REQUEST_I2C2_RX; - if (instance == Instance::i2c2 && i == 1) return DMA_REQUEST_I2C2_TX; - if (instance == Instance::i2c3 && i == 0) return DMA_REQUEST_I2C3_RX; - if (instance == Instance::i2c3 && i == 1) return DMA_REQUEST_I2C3_TX; - if (instance == Instance::i2c5 && i == 0) return DMA_REQUEST_I2C5_RX; - if (instance == Instance::i2c5 && i == 1) return DMA_REQUEST_I2C5_TX; - - if (instance == Instance::spi1 && i == 0) return DMA_REQUEST_SPI1_RX; - if (instance == Instance::spi1 && i == 1) return DMA_REQUEST_SPI1_TX; - if (instance == Instance::spi2 && i == 0) return DMA_REQUEST_SPI2_RX; - if (instance == Instance::spi2 && i == 1) return DMA_REQUEST_SPI2_TX; - if (instance == Instance::spi3 && i == 0) return DMA_REQUEST_SPI3_RX; - if (instance == Instance::spi3 && i == 1) return DMA_REQUEST_SPI3_TX; - if (instance == Instance::spi4 && i == 0) return DMA_REQUEST_SPI4_RX; - if (instance == Instance::spi4 && i == 1) return DMA_REQUEST_SPI4_TX; - if (instance == Instance::spi5 && i == 0) return DMA_REQUEST_SPI5_RX; - if (instance == Instance::spi5 && i == 1) return DMA_REQUEST_SPI5_TX; - - if (instance == Instance::fmac && i == 0) return DMA_REQUEST_MEM2MEM; - if (instance == Instance::fmac && i == 1) return DMA_REQUEST_FMAC_WRITE; - if (instance == Instance::fmac && i == 2) return DMA_REQUEST_FMAC_READ; - - ErrorHandler("Invalid DMA request configuration"); - return 0; - } - - - static consteval inline uint32_t get_Direction(Instance instance, uint8_t i) { - if (is_fmac(instance) && i == 0){ - return DMA_MEMORY_TO_MEMORY; - } - else if ((is_i2c(instance) && i == 1) || - (is_spi(instance) && i == 1) || - (is_fmac(instance) && i == 1)){ - return DMA_MEMORY_TO_PERIPH; - } - - return DMA_PERIPH_TO_MEMORY; - } - - static consteval inline uint32_t get_PeriphInc(Instance instance, uint8_t i) { - if (is_fmac(instance) && i == 0){ - return DMA_PINC_ENABLE; - } - return DMA_PINC_DISABLE; - } - static consteval inline uint32_t get_MemInc(Instance instance, uint8_t i) { - if (is_fmac(instance) && i == 0){ - return DMA_MINC_DISABLE; - } - return DMA_MINC_ENABLE; - } - - static consteval inline uint32_t get_PeriphDataAlignment(Instance instance, uint8_t i) { - if (is_i2c(instance)){ - return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes - } - else if (is_spi(instance)){ - return DMA_PDATAALIGN_BYTE; - } - - return DMA_PDATAALIGN_HALFWORD; - } - - static consteval inline uint32_t get_MemDataAlignment(Instance instance, uint8_t i) { - if (is_i2c(instance)){ - return DMA_MDATAALIGN_WORD; - } - else if (is_spi(instance)){ - return DMA_MDATAALIGN_BYTE; - } - - return DMA_MDATAALIGN_HALFWORD; - } - static consteval inline uint32_t get_Mode(Instance instance, uint8_t i) { - if (is_spi(instance) || is_fmac(instance)){ - return DMA_NORMAL; - } - - return DMA_CIRCULAR; - } - - static consteval inline uint32_t get_Priority(Instance instance, uint8_t i) { - if (is_fmac(instance)){ - return DMA_PRIORITY_HIGH; - } - - return DMA_PRIORITY_LOW; - } - static consteval inline uint32_t get_FIFOMode(Instance instance, uint8_t i) { - if (is_fmac(instance)){ - return DMA_FIFOMODE_ENABLE; - } - return DMA_FIFOMODE_DISABLE; - } - - static consteval inline uint32_t get_FIFOThreshold(Instance instance, uint8_t i) { - if (is_spi(instance)){ - return DMA_FIFO_THRESHOLD_FULL; - } - return DMA_FIFO_THRESHOLD_HALFFULL; - } - - static consteval inline uint32_t get_MemBurst(Instance instance, uint8_t i) { - return DMA_MBURST_SINGLE; - } - - static consteval inline uint32_t get_PeriphBurst(Instance instance, uint8_t i) { - return DMA_PBURST_SINGLE; - } - - - template - static consteval std::array build(span instances){ - std::array cfgs{}; - - for (std::size_t i = 0; i < N; ++i){ - const auto &e = instances[i]; - - for (std::size_t j = 0; j < i; ++j){ - const auto &prev = instances[j]; - if (prev.instance == e.instance && prev.streams == e.streams){ - struct peripherial_already_inscribed {}; - throw peripherial_already_inscribed{}; - } - } - - std::array dma_handles; - for (std::size_t j = 0; j < e.count; j++){ - DMA_HandleTypeDef DMA_HandleStruct; - DMA_HandleStruct.Instance = e.streams[j]; - DMA_HandleStruct.Init.Request = get_Request(e.instance, j); - DMA_HandleStruct.Init.Direction = get_Direction(e.instance, j); - DMA_HandleStruct.Init.PeriphInc = get_PeriphInc(e.instance, j); - DMA_HandleStruct.Init.MemInc = get_MemInc(e.instance, j); - DMA_HandleStruct.Init.PeriphDataAlignment = get_PeriphDataAlignment(e.instance, j); - DMA_HandleStruct.Init.MemDataAlignment = get_MemDataAlignment(e.instance, j); - DMA_HandleStruct.Init.Mode = get_Mode(e.instance, j); - DMA_HandleStruct.Init.Priority = get_Priority(e.instance, j); - DMA_HandleStruct.Init.FIFOMode = get_FIFOMode(e.instance, j); - DMA_HandleStruct.Init.FIFOThreshold = get_FIFOThreshold(e.instance, j); - DMA_HandleStruct.Init.MemBurst = get_MemBurst(e.instance, j); - DMA_HandleStruct.Init.PeriphBurst = get_PeriphBurst(e.instance, j); - dma_handles[i] = DMA_HandleStruct; - } - cfgs[i].init_data = std::make_tuple(e.instance, dma_handles); - } - } - }; -} \ No newline at end of file +class DMA { +public: + enum Stream : uint8_t { + DMA1Stream0 = 11, + DMA1Stream1 = 12, + DMA1Stream2 = 13, + DMA1Stream3 = 14, + DMA1Stream4 = 15, + DMA1Stream5 = 16, + DMA1Stream6 = 17, + DMA2Stream0 = 56, + DMA2Stream1 = 57, + DMA2Stream2 = 58, + DMA2Stream3 = 59, + DMA2Stream4 = 60, + DMA2Stream5 = 68, + DMA2Stream6 = 69, + DMA2Stream7 = 70, + }; + + static void inscribe_stream(); + static void inscribe_stream(Stream dma_stream); + static void start(); + +private: + static vector available_streams; + static vector inscribed_streams; +}; \ No newline at end of file diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp new file mode 100644 index 000000000..09be6526a --- /dev/null +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -0,0 +1,374 @@ +#pragma once +#include "C++Utilities/CppUtils.hpp" +#include "stm32h7xx_hal.h" +#include "main.h" +#include "HALAL/Models/MPUManager/MPUManager.hpp" +#include +#include +#include +#include +#include + +using std::array; +using std::size_t; +using std::span; +using std::tuple; + +#define MAX_STREAMS 16 + + +namespace ST_LIB { + struct DMA_Domain { + using xTypeDef = std::variant< + ADC_TypeDef*, + I2C_TypeDef*, + SPI_TypeDef*, + FMAC_TypeDef* + >; + using xHandleDef = std::variant< + ADC_HandleTypeDef*, + I2C_HandleTypeDef*, + SPI_HandleTypeDef*, + FMAC_HandleTypeDef* + >; + + enum class Instance : uint8_t {adc1, adc2, adc3, + i2c1, i2c2, i2c3, i2c5, + spi1, spi2, spi3, spi4, spi5, + fmac}; + + enum class Stream : uint8_t {dma1_stream0, dma1_stream1, dma1_stream2, dma1_stream3, + dma1_stream4, dma1_stream5, dma1_stream6, dma1_stream7, + dma2_stream0, dma2_stream1, dma2_stream2, dma2_stream3, + dma2_stream4, dma2_stream5, dma2_stream6, dma2_stream7}; + + static inline xTypeDef instance_to_xTypeDef(Instance i) { + switch (i) { + case Instance::adc1: return ADC1; + case Instance::adc2: return ADC2; + case Instance::adc3: return ADC3; + + case Instance::i2c1: return I2C1; + case Instance::i2c2: return I2C2; + case Instance::i2c3: return I2C3; + case Instance::i2c5: return I2C5; + + case Instance::spi1: return SPI1; + case Instance::spi2: return SPI2; + case Instance::spi3: return SPI3; + case Instance::spi4: return SPI4; + case Instance::spi5: return SPI5; + + case Instance::fmac: return FMAC; + } + } + + static inline DMA_Stream_TypeDef* stream_to_DMA_StreamTypeDef(Stream s) { + switch (s) { + case Stream::dma1_stream0: return DMA1_Stream0; + case Stream::dma1_stream1: return DMA1_Stream1; + case Stream::dma1_stream2: return DMA1_Stream2; + case Stream::dma1_stream3: return DMA1_Stream3; + case Stream::dma1_stream4: return DMA1_Stream4; + case Stream::dma1_stream5: return DMA1_Stream5; + case Stream::dma1_stream6: return DMA1_Stream6; + case Stream::dma1_stream7: return DMA1_Stream7; + + case Stream::dma2_stream0: return DMA2_Stream0; + case Stream::dma2_stream1: return DMA2_Stream1; + case Stream::dma2_stream2: return DMA2_Stream2; + case Stream::dma2_stream3: return DMA2_Stream3; + case Stream::dma2_stream4: return DMA2_Stream4; + case Stream::dma2_stream5: return DMA2_Stream5; + case Stream::dma2_stream6: return DMA2_Stream6; + case Stream::dma2_stream7: return DMA2_Stream7; + } + } + + struct Entry { + Instance instance; + std::array streams{}; + std::array irqn {}; + uint8_t count = 0; + }; + + struct DMA{ + using domain = DMA_Domain; + + Entry e; + + template + consteval DMA(Instance instance) : e(instance) { + static_assert(sizeof...(Ss) <= 3, "Máximo 3 streams"); + size_t i = 0; + ((e.streams[i++] = Ss), ...); + e.count = i; + for (size_t j = 0; j < i; j++){ + e.irqn[j] = get_irqn(e.streams[j]); + } + } + + template consteval void inscribe(Ctx &ctx) const { + ctx.template add(e); + } + }; + + // NO se para que quiero esto + static constexpr std::size_t max_instances {MAX_STREAMS}; + static_assert(max_instances > 0, "The number of instances must be greater than 0"); + + + + static inline IRQn_Type get_irqn(Stream stream) { + if (stream == Stream::dma1_stream0) return DMA1_Stream0_IRQn; + else if (stream == Stream::dma1_stream1) return DMA1_Stream1_IRQn; + else if (stream == Stream::dma1_stream2) return DMA1_Stream2_IRQn; + else if (stream == Stream::dma1_stream3) return DMA1_Stream3_IRQn; + else if (stream == Stream::dma1_stream4) return DMA1_Stream4_IRQn; + else if (stream == Stream::dma1_stream5) return DMA1_Stream5_IRQn; + else if (stream == Stream::dma1_stream6) return DMA1_Stream6_IRQn; + else if (stream == Stream::dma1_stream7) return DMA1_Stream7_IRQn; + + else if (stream == Stream::dma2_stream0) return DMA2_Stream0_IRQn; + else if (stream == Stream::dma2_stream1) return DMA2_Stream1_IRQn; + else if (stream == Stream::dma2_stream2) return DMA2_Stream2_IRQn; + else if (stream == Stream::dma2_stream3) return DMA2_Stream3_IRQn; + else if (stream == Stream::dma2_stream4) return DMA2_Stream4_IRQn; + else if (stream == Stream::dma2_stream5) return DMA2_Stream5_IRQn; + else if (stream == Stream::dma2_stream6) return DMA2_Stream6_IRQn; + else if (stream == Stream::dma2_stream7) return DMA2_Stream7_IRQn; + else ErrorHandler("Unknown DMA stream"); + return DMA1_Stream0_IRQn; // Nunca se alcanza + } + + // Si quitas el auto peta todo + static consteval inline bool is_one_of(Instance instance, auto... bases) { + return ((instance == bases) || ...); + } + + static consteval inline bool is_spi(Instance instance) { + return is_one_of(instance, Instance::spi1, Instance::spi2, + Instance::spi3, Instance::spi4, Instance::spi5); + } + + static consteval inline bool is_i2c(Instance instance) { + return is_one_of(instance, Instance::i2c1, Instance::i2c2, + Instance::i2c3, Instance::i2c5); + } + + static consteval inline bool is_adc(Instance instance) { + return is_one_of(instance, Instance::adc1, Instance::adc2, Instance::adc3); + } + + static consteval inline bool is_fmac(Instance instance) { + return instance == Instance::fmac; + } + + static consteval inline uint32_t get_Request(Instance instance, uint8_t i) { + if (instance == Instance::adc1) return DMA_REQUEST_ADC1; + if (instance == Instance::adc2) return DMA_REQUEST_ADC2; + if (instance == Instance::adc3) return DMA_REQUEST_ADC3; + + if (instance == Instance::i2c1 && i == 0) return DMA_REQUEST_I2C1_RX; + if (instance == Instance::i2c1 && i == 1) return DMA_REQUEST_I2C1_TX; + if (instance == Instance::i2c2 && i == 0) return DMA_REQUEST_I2C2_RX; + if (instance == Instance::i2c2 && i == 1) return DMA_REQUEST_I2C2_TX; + if (instance == Instance::i2c3 && i == 0) return DMA_REQUEST_I2C3_RX; + if (instance == Instance::i2c3 && i == 1) return DMA_REQUEST_I2C3_TX; + if (instance == Instance::i2c5 && i == 0) return DMA_REQUEST_I2C5_RX; + if (instance == Instance::i2c5 && i == 1) return DMA_REQUEST_I2C5_TX; + + if (instance == Instance::spi1 && i == 0) return DMA_REQUEST_SPI1_RX; + if (instance == Instance::spi1 && i == 1) return DMA_REQUEST_SPI1_TX; + if (instance == Instance::spi2 && i == 0) return DMA_REQUEST_SPI2_RX; + if (instance == Instance::spi2 && i == 1) return DMA_REQUEST_SPI2_TX; + if (instance == Instance::spi3 && i == 0) return DMA_REQUEST_SPI3_RX; + if (instance == Instance::spi3 && i == 1) return DMA_REQUEST_SPI3_TX; + if (instance == Instance::spi4 && i == 0) return DMA_REQUEST_SPI4_RX; + if (instance == Instance::spi4 && i == 1) return DMA_REQUEST_SPI4_TX; + if (instance == Instance::spi5 && i == 0) return DMA_REQUEST_SPI5_RX; + if (instance == Instance::spi5 && i == 1) return DMA_REQUEST_SPI5_TX; + + if (instance == Instance::fmac && i == 0) return DMA_REQUEST_MEM2MEM; + if (instance == Instance::fmac && i == 1) return DMA_REQUEST_FMAC_WRITE; + if (instance == Instance::fmac && i == 2) return DMA_REQUEST_FMAC_READ; + + ErrorHandler("Invalid DMA request configuration"); + return 0; + } + + + static consteval inline uint32_t get_Direction(Instance instance, uint8_t i) { + if (is_fmac(instance) && i == 0){ + return DMA_MEMORY_TO_MEMORY; + } + else if ((is_i2c(instance) && i == 1) || + (is_spi(instance) && i == 1) || + (is_fmac(instance) && i == 1)){ + return DMA_MEMORY_TO_PERIPH; + } + return DMA_PERIPH_TO_MEMORY; + } + + static consteval inline uint32_t get_PeriphInc(Instance instance, uint8_t i) { + if (is_fmac(instance) && i == 0){ + return DMA_PINC_ENABLE; + } + return DMA_PINC_DISABLE; + } + static consteval inline uint32_t get_MemInc(Instance instance, uint8_t i) { + if (is_fmac(instance) && i == 0){ + return DMA_MINC_DISABLE; + } + return DMA_MINC_ENABLE; + } + + static consteval inline uint32_t get_PeriphDataAlignment(Instance instance, uint8_t i) { + if (is_i2c(instance)){ + return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes + } + else if (is_spi(instance)){ + return DMA_PDATAALIGN_BYTE; + } + + return DMA_PDATAALIGN_HALFWORD; + } + + static consteval inline uint32_t get_MemDataAlignment(Instance instance, uint8_t i) { + if (is_i2c(instance)){ + return DMA_MDATAALIGN_WORD; + } + else if (is_spi(instance)){ + return DMA_MDATAALIGN_BYTE; + } + + return DMA_MDATAALIGN_HALFWORD; + } + static consteval inline uint32_t get_Mode(Instance instance, uint8_t i) { + if (is_spi(instance) || is_fmac(instance)){ + return DMA_NORMAL; + } + + return DMA_CIRCULAR; + } + + static consteval inline uint32_t get_Priority(Instance instance, uint8_t i) { + if (is_fmac(instance)){ + return DMA_PRIORITY_HIGH; + } + + return DMA_PRIORITY_LOW; + } + static consteval inline uint32_t get_FIFOMode(Instance instance, uint8_t i) { + if (is_fmac(instance)){ + return DMA_FIFOMODE_ENABLE; + } + return DMA_FIFOMODE_DISABLE; + } + + static consteval inline uint32_t get_FIFOThreshold(Instance instance, uint8_t i) { + if (is_spi(instance)){ + return DMA_FIFO_THRESHOLD_FULL; + } + return DMA_FIFO_THRESHOLD_HALFFULL; + } + + static consteval inline uint32_t get_MemBurst(Instance instance, uint8_t i) { + return DMA_MBURST_SINGLE; + } + + static consteval inline uint32_t get_PeriphBurst(Instance instance, uint8_t i) { + return DMA_PBURST_SINGLE; + } + + struct Config { + std::tuple, + std::array, + std::array> + init_data{}; + }; + + template + static consteval std::array build(span instances){ + std::array cfgs{}; + + for (std::size_t i = 0; i < N; ++i){ + const auto &e = instances[i]; + + for (std::size_t j = 0; j < i; ++j){ + const auto &prev = instances[j]; + if (prev.instance == e.instance && prev.streams == e.streams){ + struct peripherial_already_inscribed {}; + throw peripherial_already_inscribed{}; + } + } + + std::array dma_handles; + for (std::size_t j = 0; j < e.count; j++){ + DMA_InitTypeDef DMA_InitStruct; + //DMA_InitStruct.Instance = e.streams[j]; + DMA_InitStruct.Request = get_Request(e.instance, j); + DMA_InitStruct.Direction = get_Direction(e.instance, j); + DMA_InitStruct.PeriphInc = get_PeriphInc(e.instance, j); + DMA_InitStruct.MemInc = get_MemInc(e.instance, j); + DMA_InitStruct.PeriphDataAlignment = get_PeriphDataAlignment(e.instance, j); + DMA_InitStruct.MemDataAlignment = get_MemDataAlignment(e.instance, j); + DMA_InitStruct.Mode = get_Mode(e.instance, j); + DMA_InitStruct.Priority = get_Priority(e.instance, j); + DMA_InitStruct.FIFOMode = get_FIFOMode(e.instance, j); + DMA_InitStruct.FIFOThreshold = get_FIFOThreshold(e.instance, j); + DMA_InitStruct.MemBurst = get_MemBurst(e.instance, j); + DMA_InitStruct.PeriphBurst = get_PeriphBurst(e.instance, j); + + dma_handles[j] = DMA_InitStruct; + } + + cfgs[i].init_data = std::make_tuple(e.instance, dma_handles, e.streams, e.irqn); + } + return cfgs; + } + + template struct Init { + static inline std::array dma{}; + + static void init(std::span cfgs) { + static_assert(N > 0); + __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + for (std::size_t i = 0; i < N; ++i) { + const auto &e = cfgs[i]; + auto [instance, dma_handles, streams, irqn] = e.init_data; + + for (std::size_t j = 0; j < 3; j++){ + // Con la instancia necesito que me de el Handle del periferico + + dma[i].Instance = streams[j]; + dma[i].Init = dma_handles[j]; + if (HAL_DMA_Init(dma[i]) != HAL_OK) { + ErrorHandler("DMA Init failed"); + } + if (is_spi(instance)) { + auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; + } + else if (is_i2c(instance)) { + auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; + } + else if (is_adc(instance)) { + auto member = &ADC_HandleTypeDef::DMA_Handle; + } + else if (is_fmac(instance)) { + auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : + (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : + &FMAC_HandleTypeDef::hdmaOut; + } + //Linker + __HAL_LINKDMA(handle, member, dma[i]); + HAL_NVIC_SetPriority(irqn, 0, 0); + HAL_NVIC_EnableIRQ(irqn); + } + } + } + }; + }; +} \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA-old.cpp b/Src/HALAL/Models/DMA/DMA-old.cpp new file mode 100644 index 000000000..db3768088 --- /dev/null +++ b/Src/HALAL/Models/DMA/DMA-old.cpp @@ -0,0 +1,18 @@ +#include "HALAL/Models/DMA/DMA.hpp" + +void DMA::start() { + __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + for (uint8_t i = 0; i < inscribed_index; i++) { + auto& [periph, dma, linker, irq] = inscribed_streams[i]; + + if (HAL_DMA_Init(dma) != HAL_OK) { + ErrorHandler("DMA Init failed"); + } + + linker(dma); + + HAL_NVIC_SetPriority(irq, 0, 0); + HAL_NVIC_EnableIRQ(irq); + } +} \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index db3768088..2fea33c37 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -1,18 +1,41 @@ +/* + * DMA.cpp + * + * Created on: 10 dic. 2022 + * Author: aleja + */ + #include "HALAL/Models/DMA/DMA.hpp" +#include "ErrorHandler/ErrorHandler.hpp" + +vector DMA::available_streams = { + DMA1Stream0, DMA1Stream1, DMA1Stream2, DMA1Stream3, DMA1Stream4, DMA1Stream5, DMA1Stream6, DMA2Stream0, DMA2Stream1, DMA2Stream2, DMA2Stream3, DMA2Stream4, DMA2Stream5, DMA2Stream6, DMA2Stream7, +}; + +vector DMA::inscribed_streams = {}; + +void DMA::inscribe_stream() { + if (available_streams.empty()) { + ErrorHandler("There are not any DMA Streams availables"); + return; + } + inscribed_streams.push_back(available_streams.back()); + available_streams.pop_back(); +} + +void DMA::inscribe_stream(Stream dma_stream) { + if (std::find(available_streams.begin(), available_streams.end(), dma_stream) == available_streams.end()) { + ErrorHandler("The DMA stream %d is not available", dma_stream); + return; + } + inscribed_streams.push_back(dma_stream); +} void DMA::start() { - __HAL_RCC_DMA1_CLK_ENABLE(); - __HAL_RCC_DMA2_CLK_ENABLE(); - for (uint8_t i = 0; i < inscribed_index; i++) { - auto& [periph, dma, linker, irq] = inscribed_streams[i]; - - if (HAL_DMA_Init(dma) != HAL_OK) { - ErrorHandler("DMA Init failed"); - } - - linker(dma); - - HAL_NVIC_SetPriority(irq, 0, 0); - HAL_NVIC_EnableIRQ(irq); - } + __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + for (Stream dma_stream : inscribed_streams) { + HAL_NVIC_SetPriority( (IRQn_Type)dma_stream, 0, 0); + HAL_NVIC_EnableIRQ( (IRQn_Type)dma_stream); + } } \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA2.cpp b/Src/HALAL/Models/DMA/DMA2.cpp new file mode 100644 index 000000000..e69de29bb From ba25865d904e4c730fb44b7c353cdaeac45fb182 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Wed, 10 Dec 2025 10:19:26 +0100 Subject: [PATCH 025/109] entry, build e instances_ ahora se rigen por stream y no instancia (la cual se puede repetir). cambios en sus constructores y nuevo metodo (setDMAHandle) para poder pasar el handle desde el periferico --- Inc/HALAL/Models/DMA/DMA2.hpp | 228 +++++++++++++++++++++++----------- 1 file changed, 155 insertions(+), 73 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index 09be6526a..c1af1c767 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -87,29 +87,38 @@ namespace ST_LIB { struct Entry { Instance instance; - std::array streams{}; - std::array irqn {}; - uint8_t count = 0; + Stream stream; + IRQn_Type irqn; + uint8_t id; }; - - struct DMA{ + + struct DMA { using domain = DMA_Domain; - Entry e; + std::array e{}; template - consteval DMA(Instance instance) : e(instance) { + consteval DMA(Instance instance) { static_assert(sizeof...(Ss) <= 3, "Máximo 3 streams"); - size_t i = 0; - ((e.streams[i++] = Ss), ...); - e.count = i; - for (size_t j = 0; j < i; j++){ - e.irqn[j] = get_irqn(e.streams[j]); + + Stream streams[] = { Ss... }; + constexpr uint8_t n = sizeof...(Ss); + + for (uint8_t j = 0; j < n; j++) { + e[j].instance = instance; + e[j].stream = streams[j]; + e[j].irqn = get_irqn(streams[j]); + e[j].id = j; } + } - template consteval void inscribe(Ctx &ctx) const { - ctx.template add(e); + template + consteval void inscribe(Ctx &ctx) const { + for (const auto& entry : e) { + if (entry.stream != Stream{}) + ctx.template add(entry); + } } }; @@ -142,25 +151,25 @@ namespace ST_LIB { } // Si quitas el auto peta todo - static consteval inline bool is_one_of(Instance instance, auto... bases) { + static constexpr inline bool is_one_of(Instance instance, auto... bases) { return ((instance == bases) || ...); } - static consteval inline bool is_spi(Instance instance) { + static constexpr inline bool is_spi(Instance instance) { return is_one_of(instance, Instance::spi1, Instance::spi2, Instance::spi3, Instance::spi4, Instance::spi5); } - static consteval inline bool is_i2c(Instance instance) { + static constexpr inline bool is_i2c(Instance instance) { return is_one_of(instance, Instance::i2c1, Instance::i2c2, Instance::i2c3, Instance::i2c5); } - static consteval inline bool is_adc(Instance instance) { + static constexpr inline bool is_adc(Instance instance) { return is_one_of(instance, Instance::adc1, Instance::adc2, Instance::adc3); } - static consteval inline bool is_fmac(Instance instance) { + static constexpr inline bool is_fmac(Instance instance) { return instance == Instance::fmac; } @@ -283,9 +292,10 @@ namespace ST_LIB { struct Config { std::tuple, - std::array, - std::array> + DMA_InitTypeDef, + Stream, + IRQn_Type, + uint8_t> init_data{}; }; @@ -296,41 +306,130 @@ namespace ST_LIB { for (std::size_t i = 0; i < N; ++i){ const auto &e = instances[i]; + // No entiendo como funciona esto, pero esta copiado tal cual + // Yo creo que a mi no me sirve porque mis instancias si que estan repetidas for (std::size_t j = 0; j < i; ++j){ const auto &prev = instances[j]; - if (prev.instance == e.instance && prev.streams == e.streams){ + if (prev.instance == e.instance && prev.stream == e.stream){ struct peripherial_already_inscribed {}; throw peripherial_already_inscribed{}; } } - - std::array dma_handles; - for (std::size_t j = 0; j < e.count; j++){ - DMA_InitTypeDef DMA_InitStruct; - //DMA_InitStruct.Instance = e.streams[j]; - DMA_InitStruct.Request = get_Request(e.instance, j); - DMA_InitStruct.Direction = get_Direction(e.instance, j); - DMA_InitStruct.PeriphInc = get_PeriphInc(e.instance, j); - DMA_InitStruct.MemInc = get_MemInc(e.instance, j); - DMA_InitStruct.PeriphDataAlignment = get_PeriphDataAlignment(e.instance, j); - DMA_InitStruct.MemDataAlignment = get_MemDataAlignment(e.instance, j); - DMA_InitStruct.Mode = get_Mode(e.instance, j); - DMA_InitStruct.Priority = get_Priority(e.instance, j); - DMA_InitStruct.FIFOMode = get_FIFOMode(e.instance, j); - DMA_InitStruct.FIFOThreshold = get_FIFOThreshold(e.instance, j); - DMA_InitStruct.MemBurst = get_MemBurst(e.instance, j); - DMA_InitStruct.PeriphBurst = get_PeriphBurst(e.instance, j); - - dma_handles[j] = DMA_InitStruct; - } - - cfgs[i].init_data = std::make_tuple(e.instance, dma_handles, e.streams, e.irqn); + + DMA_InitTypeDef DMA_InitStruct; + DMA_InitStruct.Request = get_Request(e.instance, e.id); + DMA_InitStruct.Direction = get_Direction(e.instance, e.id); + DMA_InitStruct.PeriphInc = get_PeriphInc(e.instance, e.id); + DMA_InitStruct.MemInc = get_MemInc(e.instance, e.id); + DMA_InitStruct.PeriphDataAlignment = get_PeriphDataAlignment(e.instance, e.id); + DMA_InitStruct.MemDataAlignment = get_MemDataAlignment(e.instance, e.id); + DMA_InitStruct.Mode = get_Mode(e.instance, e.id); + DMA_InitStruct.Priority = get_Priority(e.instance, e.id); + DMA_InitStruct.FIFOMode = get_FIFOMode(e.instance, e.id); + DMA_InitStruct.FIFOThreshold = get_FIFOThreshold(e.instance, e.id); + DMA_InitStruct.MemBurst = get_MemBurst(e.instance, e.id); + DMA_InitStruct.PeriphBurst = get_PeriphBurst(e.instance, e.id); + + + cfgs[i].init_data = std::make_tuple(e.instance, + DMA_InitStruct, + e.stream, + e.irqn, + e.id); } return cfgs; } + + struct Instances_ { + xTypeDef instance; + DMA_HandleTypeDef dma; + IRQn_Type irqn; + uint8_t id; + + void setDMAHandle(xHandleDef handle) { + std::visit([&](auto* real_instance){ + std::visit([&](auto* real_handle){ + using T = std::remove_pointer_t; + // --------------------------- + // ADC + // --------------------------- + if constexpr (std::is_same_v) + { + // ADC solo tiene un stream + __HAL_LINKDMA(real_handle, DMA_Handle, dma); + + HAL_NVIC_SetPriority(irqn, 0, 0); + HAL_NVIC_EnableIRQ(irqn); + return; + } + + // --------------------------- + // I2C + // id = 0 → RX + // id = 1 → TX + // --------------------------- + else if constexpr (std::is_same_v) + { + if (id == 0) + __HAL_LINKDMA(real_handle, hdmarx, dma); + else + __HAL_LINKDMA(real_handle, hdmatx, dma); + + HAL_NVIC_SetPriority(irqn, 0, 0); + HAL_NVIC_EnableIRQ(irqn); + return; + } + + // --------------------------- + // SPI + // id = 0 → RX + // id = 1 → TX + // --------------------------- + else if constexpr (std::is_same_v) + { + if (id == 0) + __HAL_LINKDMA(real_handle, hdmarx, dma); + else + __HAL_LINKDMA(real_handle, hdmatx, dma); + + HAL_NVIC_SetPriority(irqn, 0, 0); + HAL_NVIC_EnableIRQ(irqn); + return; + } + + // --------------------------- + // FMAC + // id = 0 → Preload + // id = 1 → In + // id = 2 → Out + // --------------------------- + else if constexpr (std::is_same_v) + { + if (id == 0) + __HAL_LINKDMA(real_handle, hdmaPreload, dma); + else if (id == 1) + __HAL_LINKDMA(real_handle, hdmaIn, dma); + else + __HAL_LINKDMA(real_handle, hdmaOut, dma); + + HAL_NVIC_SetPriority(irqn, 0, 0); + HAL_NVIC_EnableIRQ(irqn); + return; + } + + else { + ErrorHandler("Unsupported peripheral type in setDMAHandle"); + } + + }, handle); + + }, instance); + } + }; + template struct Init { - static inline std::array dma{}; + static inline std::array instances{}; static void init(std::span cfgs) { static_assert(N > 0); @@ -338,34 +437,17 @@ namespace ST_LIB { __HAL_RCC_DMA2_CLK_ENABLE(); for (std::size_t i = 0; i < N; ++i) { const auto &e = cfgs[i]; - auto [instance, dma_handles, streams, irqn] = e.init_data; + auto [instance, dma_init, stream, irqn, id] = e.init_data; - for (std::size_t j = 0; j < 3; j++){ - // Con la instancia necesito que me de el Handle del periferico - - dma[i].Instance = streams[j]; - dma[i].Init = dma_handles[j]; - if (HAL_DMA_Init(dma[i]) != HAL_OK) { - ErrorHandler("DMA Init failed"); - } - if (is_spi(instance)) { - auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; - } - else if (is_i2c(instance)) { - auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; - } - else if (is_adc(instance)) { - auto member = &ADC_HandleTypeDef::DMA_Handle; - } - else if (is_fmac(instance)) { - auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : - (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : - &FMAC_HandleTypeDef::hdmaOut; - } - //Linker - __HAL_LINKDMA(handle, member, dma[i]); - HAL_NVIC_SetPriority(irqn, 0, 0); - HAL_NVIC_EnableIRQ(irqn); + instances[i].instance = instance_to_xTypeDef(instance); + instances[i].dma.Instance = stream_to_DMA_StreamTypeDef(stream); + instances[i].dma.Init = dma_init; + instances[i].irqn = irqn; + instances[i].id = id; + + // No estoy seguro de que esto tenga que ir aqui + if (HAL_DMA_Init(instances[i].dma) != HAL_OK) { + ErrorHandler("DMA Init failed"); } } } From 968eee6a58a933c6229f82ef8284ae3214359c81 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Wed, 10 Dec 2025 12:55:27 +0100 Subject: [PATCH 026/109] se me habia olvidado desreferenciar --- Inc/HALAL/Models/DMA/DMA2.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index c1af1c767..258230e70 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -125,8 +125,6 @@ namespace ST_LIB { // NO se para que quiero esto static constexpr std::size_t max_instances {MAX_STREAMS}; static_assert(max_instances > 0, "The number of instances must be greater than 0"); - - static inline IRQn_Type get_irqn(Stream stream) { if (stream == Stream::dma1_stream0) return DMA1_Stream0_IRQn; @@ -206,7 +204,6 @@ namespace ST_LIB { return 0; } - static consteval inline uint32_t get_Direction(Instance instance, uint8_t i) { if (is_fmac(instance) && i == 0){ return DMA_MEMORY_TO_MEMORY; @@ -225,6 +222,7 @@ namespace ST_LIB { } return DMA_PINC_DISABLE; } + static consteval inline uint32_t get_MemInc(Instance instance, uint8_t i) { if (is_fmac(instance) && i == 0){ return DMA_MINC_DISABLE; @@ -446,7 +444,7 @@ namespace ST_LIB { instances[i].id = id; // No estoy seguro de que esto tenga que ir aqui - if (HAL_DMA_Init(instances[i].dma) != HAL_OK) { + if (HAL_DMA_Init(&instances[i].dma) != HAL_OK) { ErrorHandler("DMA Init failed"); } } From 0826a023c36a2e5eb7f3d5ad62d76e0b33e7374e Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Thu, 11 Dec 2025 18:29:59 +0100 Subject: [PATCH 027/109] modificar STLIB.hpp para meter el contexto de la DMA --- Inc/ST-LIB.hpp | 8 +++++++- Src/HALAL/Services/ADC/ADC.cpp | 3 +-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Inc/ST-LIB.hpp b/Inc/ST-LIB.hpp index dff92504d..40586ffda 100644 --- a/Inc/ST-LIB.hpp +++ b/Inc/ST-LIB.hpp @@ -70,7 +70,7 @@ template struct BuildCtx { }; using DomainsCtx = BuildCtx; + DigitalInputDomain, DMA_Domain /*, ADCDomain, PWMDomain, ...*/>; template struct Board { static consteval auto build_ctx() { @@ -89,12 +89,14 @@ template struct Board { constexpr std::size_t gpioN = domain_size(); constexpr std::size_t doutN = domain_size(); constexpr std::size_t dinN = domain_size(); + constexpr std::size_t dmaN = domain_size(); // ... struct ConfigBundle { std::array gpio_cfgs; std::array dout_cfgs; std::array din_cfgs; + std::array dma_cfgs; // ... }; @@ -105,6 +107,8 @@ template struct Board { ctx.template span()), .din_cfgs = DigitalInputDomain::template build( ctx.template span()), + .dma_cfgs = DMA_Domain::template build( + ctx.template span()), // ... }; } @@ -115,6 +119,7 @@ template struct Board { constexpr std::size_t gpioN = domain_size(); constexpr std::size_t doutN = domain_size(); constexpr std::size_t dinN = domain_size(); + constexpr std::size_t dmaN = domain_size(); // ... GPIODomain::Init::init(cfg.gpio_cfgs); @@ -122,6 +127,7 @@ template struct Board { GPIODomain::Init::instances); DigitalInputDomain::Init::init(cfg.din_cfgs, GPIODomain::Init::instances); + DMA_Domain::Init::init(cfg.dma_cfgs); // ... } diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index f44730324..4d23110b8 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -42,8 +42,7 @@ uint8_t ADC::inscribe(Pin pin) { InitData& init_data = active_instances[id_counter].peripheral->init_data; - - DMA::inscribe_stream(active_instances[id_counter].peripheral->handle); + active_instances[id_counter].rank = init_data.channels.size(); init_data.channels.push_back(active_instances[id_counter].channel); return id_counter++; From 4c8a7f39616bdf8dbb57be79e4b4b7e407d63f83 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Fri, 12 Dec 2025 19:15:08 +0100 Subject: [PATCH 028/109] throws comentados, una dma menos --- Inc/HALAL/Models/DMA/DMA2.hpp | 9 +++++---- Inc/HALAL/Models/GPIO.hpp | 6 +++--- Inc/ST-LIB.hpp | 2 +- Src/HALAL/Models/DMA/DMA-old.cpp | 18 ------------------ Src/HALAL/Services/ADC/ADC.cpp | 2 +- Src/HALAL/Services/Communication/I2C/I2C.cpp | 2 +- Src/HALAL/Services/Communication/SPI/SPI.cpp | 2 +- Src/HALAL/Services/FMAC/FMAC.cpp | 2 +- 8 files changed, 13 insertions(+), 30 deletions(-) delete mode 100644 Src/HALAL/Models/DMA/DMA-old.cpp diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index 258230e70..500827fd6 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -92,12 +92,13 @@ namespace ST_LIB { uint8_t id; }; + template struct DMA { using domain = DMA_Domain; std::array e{}; - template + consteval DMA(Instance instance) { static_assert(sizeof...(Ss) <= 3, "Máximo 3 streams"); @@ -126,7 +127,7 @@ namespace ST_LIB { static constexpr std::size_t max_instances {MAX_STREAMS}; static_assert(max_instances > 0, "The number of instances must be greater than 0"); - static inline IRQn_Type get_irqn(Stream stream) { + static inline constexpr IRQn_Type get_irqn(Stream stream) { if (stream == Stream::dma1_stream0) return DMA1_Stream0_IRQn; else if (stream == Stream::dma1_stream1) return DMA1_Stream1_IRQn; else if (stream == Stream::dma1_stream2) return DMA1_Stream2_IRQn; @@ -310,7 +311,7 @@ namespace ST_LIB { const auto &prev = instances[j]; if (prev.instance == e.instance && prev.stream == e.stream){ struct peripherial_already_inscribed {}; - throw peripherial_already_inscribed{}; + //throw peripherial_already_inscribed{}; } } @@ -430,7 +431,7 @@ namespace ST_LIB { static inline std::array instances{}; static void init(std::span cfgs) { - static_assert(N > 0); + //static_assert(N > 0); __HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_DMA2_CLK_ENABLE(); for (std::size_t i = 0; i < N; ++i) { diff --git a/Inc/HALAL/Models/GPIO.hpp b/Inc/HALAL/Models/GPIO.hpp index 335ac3d26..7a83c01f9 100644 --- a/Inc/HALAL/Models/GPIO.hpp +++ b/Inc/HALAL/Models/GPIO.hpp @@ -177,7 +177,7 @@ struct GPIODomain { AlternateFunction af = AlternateFunction::NO_AF) : e{pin.port, pin.pin, mode, pull, speed, af} { if (!pin.valid_af(af)) { - throw "Alternate function not valid for this pin"; + //throw "Alternate function not valid for this pin"; } } @@ -201,7 +201,7 @@ struct GPIODomain { for (std::size_t j = 0; j < i; ++j) { const auto &prev = pins[j]; if (prev.pin == e.pin && prev.port == e.port) { - throw "GPIO already inscribed"; + //throw "GPIO already inscribed"; } } @@ -244,7 +244,7 @@ struct GPIODomain { static inline std::array instances{}; static void init(std::span cfgs) { - static_assert(N > 0); + //static_assert(N > 0); for (std::size_t i = 0; i < N; ++i) { const auto &e = cfgs[i]; auto [port, gpio_init] = e.init_data; diff --git a/Inc/ST-LIB.hpp b/Inc/ST-LIB.hpp index 40586ffda..3b070ac9b 100644 --- a/Inc/ST-LIB.hpp +++ b/Inc/ST-LIB.hpp @@ -158,7 +158,7 @@ template struct Board { if (!found) { struct device_not_found_for_domain {}; - throw device_not_found_for_domain{}; + //throw device_not_found_for_domain{}; } return idx; diff --git a/Src/HALAL/Models/DMA/DMA-old.cpp b/Src/HALAL/Models/DMA/DMA-old.cpp deleted file mode 100644 index db3768088..000000000 --- a/Src/HALAL/Models/DMA/DMA-old.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "HALAL/Models/DMA/DMA.hpp" - -void DMA::start() { - __HAL_RCC_DMA1_CLK_ENABLE(); - __HAL_RCC_DMA2_CLK_ENABLE(); - for (uint8_t i = 0; i < inscribed_index; i++) { - auto& [periph, dma, linker, irq] = inscribed_streams[i]; - - if (HAL_DMA_Init(dma) != HAL_OK) { - ErrorHandler("DMA Init failed"); - } - - linker(dma); - - HAL_NVIC_SetPriority(irq, 0, 0); - HAL_NVIC_EnableIRQ(irq); - } -} \ No newline at end of file diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index 4d23110b8..4ec12705a 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -68,7 +68,7 @@ void ADC::turn_on(uint8_t id){ uint32_t buffer_length = peripheral->init_data.channels.size(); if (HAL_ADC_Start_DMA(peripheral->handle, (uint32_t*) peripheral->dma_data_buffer, buffer_length) != HAL_OK) { - //ErrorHandler("DMA - %d - of ADC - %d - did not start correctly", peripheral->init_data.dma_stream, id); + ErrorHandler("DMA - %d - of ADC - %d - did not start correctly", id); return; } diff --git a/Src/HALAL/Services/Communication/I2C/I2C.cpp b/Src/HALAL/Services/Communication/I2C/I2C.cpp index 758918905..967b9eb07 100644 --- a/Src/HALAL/Services/Communication/I2C/I2C.cpp +++ b/Src/HALAL/Services/Communication/I2C/I2C.cpp @@ -23,7 +23,7 @@ uint8_t I2C::inscribe(I2C::Peripheral &i2c, uint8_t address) { Pin::inscribe(i2c_instance->SCL, ALTERNATIVE); Pin::inscribe(i2c_instance->SDA, ALTERNATIVE); - DMA::inscribe_stream(i2c_instance->hi2c); + //DMA::inscribe_stream(i2c_instance->hi2c); uint8_t id = I2C::id_counter++; diff --git a/Src/HALAL/Services/Communication/SPI/SPI.cpp b/Src/HALAL/Services/Communication/SPI/SPI.cpp index 172cba4e7..8e48abce9 100644 --- a/Src/HALAL/Services/Communication/SPI/SPI.cpp +++ b/Src/HALAL/Services/Communication/SPI/SPI.cpp @@ -56,7 +56,7 @@ uint8_t SPI::inscribe(SPI::Peripheral& spi) { uint8_t id = SPI::id_counter++; if (spi_instance->use_DMA) { - DMA::inscribe_stream(spi_instance->hspi); + //DMA::inscribe_stream(spi_instance->hspi); } SPI::registered_spi[id] = spi_instance; SPI::registered_spi_by_handler[spi_instance->hspi] = spi_instance; diff --git a/Src/HALAL/Services/FMAC/FMAC.cpp b/Src/HALAL/Services/FMAC/FMAC.cpp index 8ed6eafd1..d7885689c 100644 --- a/Src/HALAL/Services/FMAC/FMAC.cpp +++ b/Src/HALAL/Services/FMAC/FMAC.cpp @@ -32,7 +32,7 @@ void MultiplierAccelerator::IIR_software_in_software_out_inscribe(uint16_t input } void MultiplierAccelerator::inscribe(){ - DMA::inscribe_stream(Instance.hfmac); + //DMA::inscribe_stream(Instance.hfmac); } void MultiplierAccelerator::start(){ From fb86f466a510ad46abac2abc0fa9336a0b1b7875 Mon Sep 17 00:00:00 2001 From: Cantonplas Date: Wed, 22 Oct 2025 11:27:26 +0200 Subject: [PATCH 029/109] It compiles the old version with constexpr --- Inc/HALAL/Models/DMA/DMA.hpp | 39 ++++++++++++++++++++++++++++-------- Src/HALAL/Models/DMA/DMA.cpp | 33 +++++++----------------------- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 74d7864aa..cacb6df65 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -10,11 +10,11 @@ #include "C++Utilities/CppUtils.hpp" #include "stm32h7xx_hal.h" #include "HALAL/Models/MPUManager/MPUManager.hpp" - - +#include +#define MAX_NUM_STREAMS 15 class DMA { public: - enum Stream : uint8_t { + enum class Stream : uint8_t { DMA1Stream0 = 11, DMA1Stream1 = 12, DMA1Stream2 = 13, @@ -32,11 +32,34 @@ class DMA { DMA2Stream7 = 70, }; - static void inscribe_stream(); - static void inscribe_stream(Stream dma_stream); +void static inline constexpr inscribe_stream() { + for (int i = 0; i < MAX_NUM_STREAMS; i++) { + if (available_streams[i] == true) { + available_streams[i] = false; + return; + } + } + assert(false); // No DMA_Stream available +} +void static inline constexpr inscribe_stream(Stream dma_stream) { + for(int i = 0; i < MAX_NUM_STREAMS; i++){ + if(streams[i] == dma_stream && available_streams[i] == true){ + available_streams[i] = false; + return; + }else{ + break; + } + } + assert(false); //The DMA_STREAM that you want is not available; +} static void start(); private: - static vector available_streams; - static vector inscribed_streams; -}; + inline static constinit std::array available_streams{true}; + static constexpr std::array streams = { + Stream::DMA1Stream0, Stream::DMA1Stream1, Stream::DMA1Stream2, Stream::DMA1Stream3, + Stream::DMA1Stream4, Stream::DMA1Stream5, Stream::DMA1Stream6, + Stream::DMA2Stream0, Stream::DMA2Stream1, Stream::DMA2Stream2, Stream::DMA2Stream3, + Stream::DMA2Stream4, Stream::DMA2Stream5, Stream::DMA2Stream6, Stream::DMA2Stream7 + }; +}; \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index e9982734d..40d114fe8 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -8,34 +8,15 @@ #include "HALAL/Models/DMA/DMA.hpp" #include "ErrorHandler/ErrorHandler.hpp" -vector DMA::available_streams = { - DMA1Stream0, DMA1Stream1, DMA1Stream2, DMA1Stream3, DMA1Stream4, DMA1Stream5, DMA1Stream6, DMA2Stream0, DMA2Stream1, DMA2Stream2, DMA2Stream3, DMA2Stream4, DMA2Stream5, DMA2Stream6, DMA2Stream7, -}; - -vector DMA::inscribed_streams = {}; - -void DMA::inscribe_stream() { - if (available_streams.empty()) { - ErrorHandler("There are not any DMA Streams availables"); - return; - } - inscribed_streams.push_back(available_streams.back()); - available_streams.pop_back(); -} - -void DMA::inscribe_stream(Stream dma_stream) { - if (std::find(available_streams.begin(), available_streams.end(), dma_stream) == available_streams.end()) { - ErrorHandler("The DMA stream %d is not available", dma_stream); - return; - } - inscribed_streams.push_back(dma_stream); -} - void DMA::start() { __HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_DMA2_CLK_ENABLE(); - for (Stream dma_stream : inscribed_streams) { - HAL_NVIC_SetPriority( (IRQn_Type)dma_stream, 0, 0); - HAL_NVIC_EnableIRQ( (IRQn_Type)dma_stream); + int i = 0; + for (bool dma_stream : available_streams) { + if (dma_stream) { + HAL_NVIC_SetPriority((IRQn_Type)streams[i], 0, 0); + HAL_NVIC_EnableIRQ((IRQn_Type)streams[i]); + } + i++; } } From ac4df89460bd9cff3d2729357f940955b549c4a6 Mon Sep 17 00:00:00 2001 From: Cantonplas Date: Wed, 22 Oct 2025 15:13:47 +0200 Subject: [PATCH 030/109] Draft of the new dma class --- Inc/HALAL/Models/DMA/DMA.hpp | 278 ++++++++++++++++++++++++++++++++--- Src/HALAL/Models/DMA/DMA.cpp | 24 +-- 2 files changed, 273 insertions(+), 29 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index cacb6df65..ad2d445b1 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -9,9 +9,29 @@ #include "C++Utilities/CppUtils.hpp" #include "stm32h7xx_hal.h" +#include "main.h" #include "HALAL/Models/MPUManager/MPUManager.hpp" #include +#include #define MAX_NUM_STREAMS 15 +#define DMA_USED 10 //Temporal name, i cant think of a better one + + +// We only have 6 peripherals using DMA for now, the new ssd will need to be added later here +extern DMA_HandleTypeDef hdma_adc1; +extern DMA_HandleTypeDef hdma_adc2; +extern DMA_HandleTypeDef hdma_adc3; + +extern DMA_HandleTypeDef hdma_i2c2_rx; +extern DMA_HandleTypeDef hdma_i2c2_tx; + +extern DMA_HandleTypeDef hdma_fmac_preload; +extern DMA_HandleTypeDef hdma_fmac_read; +extern DMA_HandleTypeDef hdma_fmac_write; + +extern DMA_HandleTypeDef hdma_spi3_rx; +extern DMA_HandleTypeDef hdma_spi3_tx; + class DMA { public: enum class Stream : uint8_t { @@ -31,31 +51,251 @@ class DMA { DMA2Stream6 = 69, DMA2Stream7 = 70, }; + + enum class Peripheral_type { + Adc1, + Adc2, + Adc3, + I2c2, + Fmac, + Spi3 + }; + template + struct Peripheral_type_instance { + DMA_HandleTypeDef* dma_handle; + DMA_HandleTypeDef* global_handle; + T* handle; + Stream stream; + + }; + //To allow the array to be multiple types, idk first thing that came to mind + using InstanceList = std::variant< + Peripheral_type_instance, + Peripheral_type_instance, + Peripheral_type_instance, + Peripheral_type_instance + >; -void static inline constexpr inscribe_stream() { - for (int i = 0; i < MAX_NUM_STREAMS; i++) { - if (available_streams[i] == true) { - available_streams[i] = false; - return; - } - } - assert(false); // No DMA_Stream available -} -void static inline constexpr inscribe_stream(Stream dma_stream) { - for(int i = 0; i < MAX_NUM_STREAMS; i++){ - if(streams[i] == dma_stream && available_streams[i] == true){ - available_streams[i] = false; - return; - }else{ + template + void static inline constexpr inscribe_stream(T* handle,Peripheral_type peripheral_type) + { + static_assert(is_variant_member, MyInstanceVariant>::value, + "Handle Type not allowed on DMA::inscribe_stream"); + assert(handle != nullptr); + assert(inscribed_index < DMA_USED); + + + switch (peripheral_type) + { + case Peripheral_type::Adc1: + static_assert(handle->Instance == ADC1, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc1"); + Instance instance; + instance.handle = handle; + hdma_adc1.Instance = DMA1_Stream0; + hdma_adc1.Init.Request = DMA_REQUEST_ADC1; + hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; + hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_adc1.Init.Mode = DMA_CIRCULAR; + hdma_adc1.Init.Priority = DMA_PRIORITY_LOW; + hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_adc1; + instance.stream = Stream::DMA1Stream0; + instance.global_handle= &DMA_Handle + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case Peripheral_type::Adc2: + static_assert(handle->Instance == ADC2, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc2"); + Instance instance; + instance.handle = handle; + hdma_adc2.Instance = DMA1_Stream1; + hdma_adc2.Init.Request = DMA_REQUEST_ADC2; + hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_adc2.Init.MemInc = DMA_MINC_ENABLE; + hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_adc2.Init.Mode = DMA_CIRCULAR; + hdma_adc2.Init.Priority = DMA_PRIORITY_LOW; + hdma_adc2.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_adc2; + instance.stream = Stream::DMA1Stream1; + instance.global_handle= &DMA_Handle + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case Peripheral_type::Adc3: + static_assert(handle->Instance == ADC3, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc3"); + Instance instance; + instance.handle = handle; + hdma_adc3.Instance = DMA1_Stream2; + hdma_adc3.Init.Request = DMA_REQUEST_ADC3; + hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_adc3.Init.MemInc = DMA_MINC_ENABLE; + hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_adc3.Init.Mode = DMA_CIRCULAR; + hdma_adc3.Init.Priority = DMA_PRIORITY_LOW; + hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_adc3; + instance.stream = Stream::DMA1Stream2; + instance.global_handle= &DMA_Handle + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case Peripheral_type::I2c2: + static_assert(handle->Instance == I2C2, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::I2c2"); + Instance instance; + instance.handle = handle; + hdma_i2c2_rx.Instance = DMA1_Stream3; + hdma_i2c2_rx.Init.Request = DMA_REQUEST_I2C2_RX; + hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_i2c2_rx.Init.Mode = DMA_CIRCULAR; + hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_i2c2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_i2c2_rx; + instance.stream = Stream::DMA1Stream3; + instance.global_handle= &hdmarx; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_i2c2_tx.Instance = DMA1_Stream4; + hdma_i2c2_tx.Init.Request = DMA_REQUEST_I2C2_TX; + hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_i2c2_tx.Init.Mode = DMA_CIRCULAR; + hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_LOW; + hdma_i2c2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_i2c2_tx; + instance.stream = Stream::DMA1Stream4; + instance.global_handle= &hdmatx; + + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case Peripheral_type::Fmac: + static_assert(handle->Instance == FMAC, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Fmac"); + Instance instance; + hdma_fmac_preload.Instance = DMA2_Stream0; + hdma_fmac_preload.Init.Request = DMA_REQUEST_MEM2MEM; + hdma_fmac_preload.Init.Direction = DMA_MEMORY_TO_MEMORY; + hdma_fmac_preload.Init.PeriphInc = DMA_PINC_ENABLE; + hdma_fmac_preload.Init.MemInc = DMA_MINC_DISABLE; + hdma_fmac_preload.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_fmac_preload.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_fmac_preload.Init.Mode = DMA_NORMAL; + hdma_fmac_preload.Init.Priority = DMA_PRIORITY_HIGH; + instance.dma_handle = &hdma_fmac_preload; + instance.stream = Stream::DMA2Stream0; + instance.global_handle= &hdmaPreload; + + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_fmac_write.Instance = DMA2_Stream1; + hdma_fmac_write.Init.Request = DMA_REQUEST_FMAC_WRITE; + hdma_fmac_write.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_fmac_write.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_fmac_write.Init.MemInc = DMA_MINC_ENABLE; + hdma_fmac_write.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_fmac_write.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_fmac_write.Init.Mode = DMA_NORMAL; + hdma_fmac_write.Init.Priority = DMA_PRIORITY_HIGH; + instance.dma_handle = &hdma_fmac_write; + instance.stream = Stream::DMA2Stream1; + instance.global_handle= &hdmaIn; + + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_fmac_read.Instance = DMA2_Stream2; + hdma_fmac_read.Init.Request = DMA_REQUEST_FMAC_READ; + hdma_fmac_read.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_fmac_read.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_fmac_read.Init.MemInc = DMA_MINC_ENABLE; + hdma_fmac_read.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_fmac_read.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_fmac_read.Init.Mode = DMA_NORMAL; + hdma_fmac_read.Init.Priority = DMA_PRIORITY_HIGH; + instance.dma_handle = &hdma_fmac_read; + instance.stream = Stream::DMA2Stream2; + instance.global_handle= &hdmaOut; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case Peripheral_type::Spi3: + static_assert(handle->Instance == SPI3, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Spi3"); + Instance instance; + hdma_spi3_rx.Instance = DMA1_Stream5; + hdma_spi3_rx.Init.Request = DMA_REQUEST_SPI3_RX; + hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_spi3_rx.Init.Mode = DMA_NORMAL; + hdma_spi3_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_spi3_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + instance.dma_handle = &hdma_spi3_rx; + instance.stream = Stream::DMA1Stream5; + instance.global_handle= &hdmarx; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_spi3_tx.Instance = DMA1_Stream6; + hdma_spi3_tx.Init.Request = DMA_REQUEST_SPI3_TX; + hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi3_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_spi3_tx.Init.Mode = DMA_NORMAL; + hdma_spi3_tx.Init.Priority = DMA_PRIORITY_LOW; + hdma_spi3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_spi3_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + instance.dma_handle = &hdma_spi3_tx; + instance.stream = Stream::DMA1Stream6; + instance.global_handle= &hdmatx; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; break; - } } - assert(false); //The DMA_STREAM that you want is not available; -} + + return; + } + static void start(); private: - inline static constinit std::array available_streams{true}; + inline static constinit uint8_t inscribed_index = 0; + inline static constinit std::array inscribed_streams{}; static constexpr std::array streams = { Stream::DMA1Stream0, Stream::DMA1Stream1, Stream::DMA1Stream2, Stream::DMA1Stream3, Stream::DMA1Stream4, Stream::DMA1Stream5, Stream::DMA1Stream6, diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index 40d114fe8..9d9732292 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -8,15 +8,19 @@ #include "HALAL/Models/DMA/DMA.hpp" #include "ErrorHandler/ErrorHandler.hpp" -void DMA::start() { - __HAL_RCC_DMA1_CLK_ENABLE(); - __HAL_RCC_DMA2_CLK_ENABLE(); - int i = 0; - for (bool dma_stream : available_streams) { - if (dma_stream) { - HAL_NVIC_SetPriority((IRQn_Type)streams[i], 0, 0); - HAL_NVIC_EnableIRQ((IRQn_Type)streams[i]); - } - i++; +void DMA::start() +{ + __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + for (auto const &inst : inscribed_streams) { + std::visit([&](auto const &instance) { + if (HAL_DMA_Init(instance.dma_handle) != HAL_OK) + { + Error_Handler(); + } + __HAL_LINKDMA(instance.handle, instance.global_handle, instance.dma_handle); + HAL_NVIC_SetPriority((IRQn_Type)instance.stream, 0, 0); + HAL_NVIC_EnableIRQ((IRQn_Type)instance.stream); + }, inst); } } From 4b9d4ba70b3937285c386b58cbfc0230813b30b6 Mon Sep 17 00:00:00 2001 From: Cantonplas Date: Thu, 23 Oct 2025 11:53:38 +0200 Subject: [PATCH 031/109] Minor change on where is the instance declared on dma.hpp --- Inc/HALAL/Models/DMA/DMA.hpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index ad2d445b1..8f113721e 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -18,6 +18,8 @@ // We only have 6 peripherals using DMA for now, the new ssd will need to be added later here + +//The problem here is that this handles are defined in runes.cpp, so maybe we should declare this here? Idk extern DMA_HandleTypeDef hdma_adc1; extern DMA_HandleTypeDef hdma_adc2; extern DMA_HandleTypeDef hdma_adc3; @@ -79,6 +81,7 @@ class DMA { template void static inline constexpr inscribe_stream(T* handle,Peripheral_type peripheral_type) { + Instance instance; static_assert(is_variant_member, MyInstanceVariant>::value, "Handle Type not allowed on DMA::inscribe_stream"); assert(handle != nullptr); @@ -89,7 +92,6 @@ class DMA { { case Peripheral_type::Adc1: static_assert(handle->Instance == ADC1, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc1"); - Instance instance; instance.handle = handle; hdma_adc1.Instance = DMA1_Stream0; hdma_adc1.Init.Request = DMA_REQUEST_ADC1; @@ -111,7 +113,6 @@ class DMA { case Peripheral_type::Adc2: static_assert(handle->Instance == ADC2, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc2"); - Instance instance; instance.handle = handle; hdma_adc2.Instance = DMA1_Stream1; hdma_adc2.Init.Request = DMA_REQUEST_ADC2; @@ -133,7 +134,6 @@ class DMA { case Peripheral_type::Adc3: static_assert(handle->Instance == ADC3, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc3"); - Instance instance; instance.handle = handle; hdma_adc3.Instance = DMA1_Stream2; hdma_adc3.Init.Request = DMA_REQUEST_ADC3; @@ -155,7 +155,6 @@ class DMA { case Peripheral_type::I2c2: static_assert(handle->Instance == I2C2, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::I2c2"); - Instance instance; instance.handle = handle; hdma_i2c2_rx.Instance = DMA1_Stream3; hdma_i2c2_rx.Init.Request = DMA_REQUEST_I2C2_RX; @@ -195,7 +194,6 @@ class DMA { case Peripheral_type::Fmac: static_assert(handle->Instance == FMAC, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Fmac"); - Instance instance; hdma_fmac_preload.Instance = DMA2_Stream0; hdma_fmac_preload.Init.Request = DMA_REQUEST_MEM2MEM; hdma_fmac_preload.Init.Direction = DMA_MEMORY_TO_MEMORY; @@ -249,7 +247,6 @@ class DMA { case Peripheral_type::Spi3: static_assert(handle->Instance == SPI3, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Spi3"); - Instance instance; hdma_spi3_rx.Instance = DMA1_Stream5; hdma_spi3_rx.Init.Request = DMA_REQUEST_SPI3_RX; hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; From d08593842db97db0f6a6858caeeedfcb7e5e3803 Mon Sep 17 00:00:00 2001 From: Jorge Date: Sat, 25 Oct 2025 10:10:24 +0200 Subject: [PATCH 032/109] limpieza de funciones, enums y structs --- Inc/HALAL/Models/DMA/DMA.hpp | 263 +---------------------------------- Src/HALAL/Models/DMA/DMA.cpp | 222 +++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+), 258 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 8f113721e..01e88a897 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -13,61 +13,20 @@ #include "HALAL/Models/MPUManager/MPUManager.hpp" #include #include -#define MAX_NUM_STREAMS 15 -#define DMA_USED 10 //Temporal name, i cant think of a better one +#define MAX_STREAMS 16 // We only have 6 peripherals using DMA for now, the new ssd will need to be added later here -//The problem here is that this handles are defined in runes.cpp, so maybe we should declare this here? Idk -extern DMA_HandleTypeDef hdma_adc1; -extern DMA_HandleTypeDef hdma_adc2; -extern DMA_HandleTypeDef hdma_adc3; - -extern DMA_HandleTypeDef hdma_i2c2_rx; -extern DMA_HandleTypeDef hdma_i2c2_tx; - -extern DMA_HandleTypeDef hdma_fmac_preload; -extern DMA_HandleTypeDef hdma_fmac_read; -extern DMA_HandleTypeDef hdma_fmac_write; - -extern DMA_HandleTypeDef hdma_spi3_rx; -extern DMA_HandleTypeDef hdma_spi3_tx; class DMA { public: - enum class Stream : uint8_t { - DMA1Stream0 = 11, - DMA1Stream1 = 12, - DMA1Stream2 = 13, - DMA1Stream3 = 14, - DMA1Stream4 = 15, - DMA1Stream5 = 16, - DMA1Stream6 = 17, - DMA2Stream0 = 56, - DMA2Stream1 = 57, - DMA2Stream2 = 58, - DMA2Stream3 = 59, - DMA2Stream4 = 60, - DMA2Stream5 = 68, - DMA2Stream6 = 69, - DMA2Stream7 = 70, - }; - - enum class Peripheral_type { - Adc1, - Adc2, - Adc3, - I2c2, - Fmac, - Spi3 - }; template struct Peripheral_type_instance { DMA_HandleTypeDef* dma_handle; DMA_HandleTypeDef* global_handle; T* handle; - Stream stream; + Stream stream; // Maybe dejar IRQn type? }; //To allow the array to be multiple types, idk first thing that came to mind @@ -79,224 +38,12 @@ class DMA { >; template - void static inline constexpr inscribe_stream(T* handle,Peripheral_type peripheral_type) - { - Instance instance; - static_assert(is_variant_member, MyInstanceVariant>::value, - "Handle Type not allowed on DMA::inscribe_stream"); - assert(handle != nullptr); - assert(inscribed_index < DMA_USED); - - - switch (peripheral_type) - { - case Peripheral_type::Adc1: - static_assert(handle->Instance == ADC1, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc1"); - instance.handle = handle; - hdma_adc1.Instance = DMA1_Stream0; - hdma_adc1.Init.Request = DMA_REQUEST_ADC1; - hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; - hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_adc1.Init.Mode = DMA_CIRCULAR; - hdma_adc1.Init.Priority = DMA_PRIORITY_LOW; - hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_adc1; - instance.stream = Stream::DMA1Stream0; - instance.global_handle= &DMA_Handle - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case Peripheral_type::Adc2: - static_assert(handle->Instance == ADC2, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc2"); - instance.handle = handle; - hdma_adc2.Instance = DMA1_Stream1; - hdma_adc2.Init.Request = DMA_REQUEST_ADC2; - hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_adc2.Init.MemInc = DMA_MINC_ENABLE; - hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_adc2.Init.Mode = DMA_CIRCULAR; - hdma_adc2.Init.Priority = DMA_PRIORITY_LOW; - hdma_adc2.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_adc2; - instance.stream = Stream::DMA1Stream1; - instance.global_handle= &DMA_Handle - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case Peripheral_type::Adc3: - static_assert(handle->Instance == ADC3, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Adc3"); - instance.handle = handle; - hdma_adc3.Instance = DMA1_Stream2; - hdma_adc3.Init.Request = DMA_REQUEST_ADC3; - hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_adc3.Init.MemInc = DMA_MINC_ENABLE; - hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_adc3.Init.Mode = DMA_CIRCULAR; - hdma_adc3.Init.Priority = DMA_PRIORITY_LOW; - hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_adc3; - instance.stream = Stream::DMA1Stream2; - instance.global_handle= &DMA_Handle - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case Peripheral_type::I2c2: - static_assert(handle->Instance == I2C2, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::I2c2"); - instance.handle = handle; - hdma_i2c2_rx.Instance = DMA1_Stream3; - hdma_i2c2_rx.Init.Request = DMA_REQUEST_I2C2_RX; - hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE; - hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - hdma_i2c2_rx.Init.Mode = DMA_CIRCULAR; - hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_LOW; - hdma_i2c2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_i2c2_rx; - instance.stream = Stream::DMA1Stream3; - instance.global_handle= &hdmarx; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_i2c2_tx.Instance = DMA1_Stream4; - hdma_i2c2_tx.Init.Request = DMA_REQUEST_I2C2_TX; - hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE; - hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - hdma_i2c2_tx.Init.Mode = DMA_CIRCULAR; - hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_LOW; - hdma_i2c2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_i2c2_tx; - instance.stream = Stream::DMA1Stream4; - instance.global_handle= &hdmatx; - - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case Peripheral_type::Fmac: - static_assert(handle->Instance == FMAC, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Fmac"); - hdma_fmac_preload.Instance = DMA2_Stream0; - hdma_fmac_preload.Init.Request = DMA_REQUEST_MEM2MEM; - hdma_fmac_preload.Init.Direction = DMA_MEMORY_TO_MEMORY; - hdma_fmac_preload.Init.PeriphInc = DMA_PINC_ENABLE; - hdma_fmac_preload.Init.MemInc = DMA_MINC_DISABLE; - hdma_fmac_preload.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_fmac_preload.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_fmac_preload.Init.Mode = DMA_NORMAL; - hdma_fmac_preload.Init.Priority = DMA_PRIORITY_HIGH; - instance.dma_handle = &hdma_fmac_preload; - instance.stream = Stream::DMA2Stream0; - instance.global_handle= &hdmaPreload; - - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_fmac_write.Instance = DMA2_Stream1; - hdma_fmac_write.Init.Request = DMA_REQUEST_FMAC_WRITE; - hdma_fmac_write.Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_fmac_write.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_fmac_write.Init.MemInc = DMA_MINC_ENABLE; - hdma_fmac_write.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_fmac_write.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_fmac_write.Init.Mode = DMA_NORMAL; - hdma_fmac_write.Init.Priority = DMA_PRIORITY_HIGH; - instance.dma_handle = &hdma_fmac_write; - instance.stream = Stream::DMA2Stream1; - instance.global_handle= &hdmaIn; - - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_fmac_read.Instance = DMA2_Stream2; - hdma_fmac_read.Init.Request = DMA_REQUEST_FMAC_READ; - hdma_fmac_read.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_fmac_read.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_fmac_read.Init.MemInc = DMA_MINC_ENABLE; - hdma_fmac_read.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_fmac_read.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_fmac_read.Init.Mode = DMA_NORMAL; - hdma_fmac_read.Init.Priority = DMA_PRIORITY_HIGH; - instance.dma_handle = &hdma_fmac_read; - instance.stream = Stream::DMA2Stream2; - instance.global_handle= &hdmaOut; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case Peripheral_type::Spi3: - static_assert(handle->Instance == SPI3, "Handle passed to DMA::inscribe_stream does not match Peripheral_type::Spi3"); - hdma_spi3_rx.Instance = DMA1_Stream5; - hdma_spi3_rx.Init.Request = DMA_REQUEST_SPI3_RX; - hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE; - hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - hdma_spi3_rx.Init.Mode = DMA_NORMAL; - hdma_spi3_rx.Init.Priority = DMA_PRIORITY_LOW; - hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - hdma_spi3_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - instance.dma_handle = &hdma_spi3_rx; - instance.stream = Stream::DMA1Stream5; - instance.global_handle= &hdmarx; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_spi3_tx.Instance = DMA1_Stream6; - hdma_spi3_tx.Init.Request = DMA_REQUEST_SPI3_TX; - hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_spi3_tx.Init.MemInc = DMA_MINC_ENABLE; - hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - hdma_spi3_tx.Init.Mode = DMA_NORMAL; - hdma_spi3_tx.Init.Priority = DMA_PRIORITY_LOW; - hdma_spi3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - hdma_spi3_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - instance.dma_handle = &hdma_spi3_tx; - instance.stream = Stream::DMA1Stream6; - instance.global_handle= &hdmatx; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - } - - return; - } + void static inline constexpr inscribe_stream(T* handle); static void start(); private: inline static constinit uint8_t inscribed_index = 0; - inline static constinit std::array inscribed_streams{}; - static constexpr std::array streams = { - Stream::DMA1Stream0, Stream::DMA1Stream1, Stream::DMA1Stream2, Stream::DMA1Stream3, - Stream::DMA1Stream4, Stream::DMA1Stream5, Stream::DMA1Stream6, - Stream::DMA2Stream0, Stream::DMA2Stream1, Stream::DMA2Stream2, Stream::DMA2Stream3, - Stream::DMA2Stream4, Stream::DMA2Stream5, Stream::DMA2Stream6, Stream::DMA2Stream7 - }; + inline static constinit std::array inscribed_streams{}; + }; \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index 9d9732292..8eb8dae20 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -8,6 +8,228 @@ #include "HALAL/Models/DMA/DMA.hpp" #include "ErrorHandler/ErrorHandler.hpp" + +template +constexpr void DMA::inscribe_stream(T* handle, DMA_Stream_TypeDef* stream) +{ + Peripheral_type_instance instance{}; + // Verificar que los tipos pasados sean correctos y que aun hay streams sin usar + + // Atributos comunes + + // Atributos propios + + +} + + +template +constexpr void DMA::inscribe_stream(T* handle) + { + Peripheral_type_instance instance{}; + assert(handle != nullptr); + assert(inscribed_index < DMA_USED); + + switch (handle->Instance) + { + case ADC1_BASE: + instance.handle = handle; + hdma_adc1.Instance = DMA1_Stream0; + hdma_adc1.Init.Request = DMA_REQUEST_ADC1; + hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; + hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_adc1.Init.Mode = DMA_CIRCULAR; + hdma_adc1.Init.Priority = DMA_PRIORITY_LOW; + hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_adc1; + instance.stream = Stream::DMA1Stream0; + instance.global_handle= &DMA_Handle + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case ADC2_BASE: + instance.handle = handle; + hdma_adc2.Instance = DMA1_Stream1; + hdma_adc2.Init.Request = DMA_REQUEST_ADC2; + hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_adc2.Init.MemInc = DMA_MINC_ENABLE; + hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_adc2.Init.Mode = DMA_CIRCULAR; + hdma_adc2.Init.Priority = DMA_PRIORITY_LOW; + hdma_adc2.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_adc2; + instance.stream = Stream::DMA1Stream1; + instance.global_handle= &DMA_Handle + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case ADC3_BASE: + instance.handle = handle; + hdma_adc3.Instance = DMA1_Stream2; + hdma_adc3.Init.Request = DMA_REQUEST_ADC3; + hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_adc3.Init.MemInc = DMA_MINC_ENABLE; + hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_adc3.Init.Mode = DMA_CIRCULAR; + hdma_adc3.Init.Priority = DMA_PRIORITY_LOW; + hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_adc3; + instance.stream = DMA1Stream2; + instance.global_handle= &DMA_Handle; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case I2C2_BASE: + instance.handle = handle; + hdma_i2c2_rx.Instance = DMA1_Stream3; + hdma_i2c2_rx.Init.Request = DMA_REQUEST_I2C2_RX; + hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_i2c2_rx.Init.Mode = DMA_CIRCULAR; + hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_i2c2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_i2c2_rx; + instance.stream = Stream::DMA1Stream3; + instance.global_handle= &hdmarx; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_i2c2_tx.Instance = DMA1_Stream4; + hdma_i2c2_tx.Init.Request = DMA_REQUEST_I2C2_TX; + hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_i2c2_tx.Init.Mode = DMA_CIRCULAR; + hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_LOW; + hdma_i2c2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.dma_handle = &hdma_i2c2_tx; + instance.stream = Stream::DMA1Stream4; + instance.global_handle= &hdmatx; + + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case FMAC_BASE: + hdma_fmac_preload.Instance = DMA2_Stream0; + hdma_fmac_preload.Init.Request = DMA_REQUEST_MEM2MEM; + hdma_fmac_preload.Init.Direction = DMA_MEMORY_TO_MEMORY; + hdma_fmac_preload.Init.PeriphInc = DMA_PINC_ENABLE; + hdma_fmac_preload.Init.MemInc = DMA_MINC_DISABLE; + hdma_fmac_preload.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_fmac_preload.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_fmac_preload.Init.Mode = DMA_NORMAL; + hdma_fmac_preload.Init.Priority = DMA_PRIORITY_HIGH; + instance.dma_handle = &hdma_fmac_preload; + instance.stream = Stream::DMA2Stream0; + instance.global_handle= &hdmaPreload; + + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_fmac_write.Instance = DMA2_Stream1; + hdma_fmac_write.Init.Request = DMA_REQUEST_FMAC_WRITE; + hdma_fmac_write.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_fmac_write.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_fmac_write.Init.MemInc = DMA_MINC_ENABLE; + hdma_fmac_write.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_fmac_write.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_fmac_write.Init.Mode = DMA_NORMAL; + hdma_fmac_write.Init.Priority = DMA_PRIORITY_HIGH; + instance.dma_handle = &hdma_fmac_write; + instance.stream = Stream::DMA2Stream1; + instance.global_handle= &hdmaIn; + + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_fmac_read.Instance = DMA2_Stream2; + hdma_fmac_read.Init.Request = DMA_REQUEST_FMAC_READ; + hdma_fmac_read.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_fmac_read.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_fmac_read.Init.MemInc = DMA_MINC_ENABLE; + hdma_fmac_read.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_fmac_read.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_fmac_read.Init.Mode = DMA_NORMAL; + hdma_fmac_read.Init.Priority = DMA_PRIORITY_HIGH; + instance.dma_handle = &hdma_fmac_read; + instance.stream = Stream::DMA2Stream2; + instance.global_handle= &hdmaOut; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + case SPI3_BASE: + hdma_spi3_rx.Instance = DMA1_Stream5; + hdma_spi3_rx.Init.Request = DMA_REQUEST_SPI3_RX; + hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_spi3_rx.Init.Mode = DMA_NORMAL; + hdma_spi3_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_spi3_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + instance.dma_handle = &hdma_spi3_rx; + instance.stream = Stream::DMA1Stream5; + instance.global_handle= &hdmarx; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + + hdma_spi3_tx.Instance = DMA1_Stream6; + hdma_spi3_tx.Init.Request = DMA_REQUEST_SPI3_TX; + hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi3_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_spi3_tx.Init.Mode = DMA_NORMAL; + hdma_spi3_tx.Init.Priority = DMA_PRIORITY_LOW; + hdma_spi3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_spi3_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + instance.dma_handle = &hdma_spi3_tx; + instance.stream = Stream::DMA1Stream6; + instance.global_handle= &hdmatx; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; + break; + + default: + // Aqui poner que diga que el handle esta mal o algo + ErrorHandler(); + break; + } + + return; + } + + void DMA::start() { __HAL_RCC_DMA1_CLK_ENABLE(); From 2e9252c46e626ef6126db4a0c35a38f2920b5f30 Mon Sep 17 00:00:00 2001 From: Jorge Date: Sat, 25 Oct 2025 23:29:30 +0200 Subject: [PATCH 033/109] feat: distintos inscribe definidos, no creo que sea lo mejor que se puede hacer --- Inc/HALAL/Models/DMA/DMA.hpp | 27 ++-- Src/HALAL/Models/DMA/DMA.cpp | 245 +++++++++++++++++++++++++++++++++-- 2 files changed, 252 insertions(+), 20 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 01e88a897..42f70c7f4 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -14,21 +14,18 @@ #include #include #define MAX_STREAMS 16 - - -// We only have 6 peripherals using DMA for now, the new ssd will need to be added later here - +#define STREAMS_USED 10 class DMA { public: template struct Peripheral_type_instance { + T* handle; DMA_HandleTypeDef* dma_handle; DMA_HandleTypeDef* global_handle; - T* handle; - Stream stream; // Maybe dejar IRQn type? - + IRQn_Type irqn; }; + //To allow the array to be multiple types, idk first thing that came to mind using InstanceList = std::variant< Peripheral_type_instance, @@ -37,13 +34,23 @@ class DMA { Peripheral_type_instance >; - template - void static inline constexpr inscribe_stream(T* handle); + constexpr void inscribe_stream_adc(ADC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream); + + constexpr void inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); + + constexpr void inscribe_stream_spi(SPI_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); + + constexpr void inscribe_stream_fmac(FMAC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_preload, DMA_Stream_TypeDef* stream_read, DMA_Stream_TypeDef* stream_write); + + + + constexpr uint32_t get_dma_request(const void* instance, const bool mode); + + constexpr IRQn_Type get_irqn(const DMA_Stream_TypeDef* stream); static void start(); private: inline static constinit uint8_t inscribed_index = 0; inline static constinit std::array inscribed_streams{}; - }; \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index 8eb8dae20..245e54259 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -9,17 +9,242 @@ #include "ErrorHandler/ErrorHandler.hpp" -template -constexpr void DMA::inscribe_stream(T* handle, DMA_Stream_TypeDef* stream) +constexpr uint32_t DMA::get_dma_request(const void* instance, const bool mode) { + if (instance == ADC1) return DMA_REQUEST_ADC1; + if (instance == ADC2) return DMA_REQUEST_ADC2; + if (instance == ADC3) return DMA_REQUEST_ADC3; + + if (instance == I2C1 && mode) return DMA_REQUEST_I2C1_RX; + if (instance == I2C1 && !mode) return DMA_REQUEST_I2C1_TX; + if (instance == I2C2 && mode) return DMA_REQUEST_I2C2_RX; + if (instance == I2C2 && !mode) return DMA_REQUEST_I2C2_TX; + if (instance == I2C3 && mode) return DMA_REQUEST_I2C3_RX; + if (instance == I2C3 && !mode) return DMA_REQUEST_I2C3_TX; + if (instance == I2C5 && mode) return DMA_REQUEST_I2C5_RX; // NO hay 4? + if (instance == I2C5 && !mode) return DMA_REQUEST_I2C5_TX; + + if (instance == SPI1 && mode) return DMA_REQUEST_SPI1_RX; + if (instance == SPI1 && !mode) return DMA_REQUEST_SPI1_TX; + if (instance == SPI2 && mode) return DMA_REQUEST_SPI2_RX; + if (instance == SPI2 && !mode) return DMA_REQUEST_SPI2_TX; + if (instance == SPI3 && mode) return DMA_REQUEST_SPI3_RX; + if (instance == SPI3 && !mode) return DMA_REQUEST_SPI3_TX; + if (instance == SPI4 && mode) return DMA_REQUEST_SPI4_RX; + if (instance == SPI4 && !mode) return DMA_REQUEST_SPI4_TX; + if (instance == SPI5 && mode) return DMA_REQUEST_SPI5_RX; + if (instance == SPI5 && !mode) return DMA_REQUEST_SPI5_TX; // NO hay 6? + + return 0; +} + + +constexpr IRQn_Type DMA::get_irqn(const DMA_Stream_TypeDef* stream) { + if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; + if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; + if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; + if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; + if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; + if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; + if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; + if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; + + if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; + if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; + if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; + if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; + if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; + if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; + if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; + if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; +} + + + +constexpr void DMA::inscribe_stream_adc(ADC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream) { - Peripheral_type_instance instance{}; - // Verificar que los tipos pasados sean correctos y que aun hay streams sin usar + Peripheral_type_instance instance{}; + static DMA_HandleTypeDef dma_handle; + + instance.handle = handle; + dma_handle.Instance = stream; + dma_handle.Init.Request = get_dma_request(handle->Instance, true); // El modo no hace nada aquí + dma_handle.Init.Direction = DMA_PERIPH_TO_MEMORY; + dma_handle.Init.PeriphInc = DMA_PINC_DISABLE; + dma_handle.Init.MemInc = DMA_MINC_ENABLE; + dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + dma_handle.Init.Mode = DMA_CIRCULAR; + dma_handle.Init.Priority = DMA_PRIORITY_LOW; + dma_handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance.global_handle = handle->DMA_Handle; + instance.irqn = get_irqn(stream); + instance.dma_handle = &dma_handle; + + inscribed_streams[inscribed_index] = instance; + inscribed_index++; +} - // Atributos comunes - // Atributos propios +constexpr void DMA::inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx) +{ + // RX Stream + Peripheral_type_instance instance_rx{}; + static DMA_HandleTypeDef dma_handle_rx; + + instance_rx.handle = handle; + dma_handle_rx.Instance = stream_rx; + dma_handle_rx.Init.Request = get_dma_request(handle->Instance, true); + dma_handle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + dma_handle_rx.Init.PeriphInc = DMA_PINC_DISABLE; + dma_handle_rx.Init.MemInc = DMA_MINC_ENABLE; + dma_handle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + dma_handle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + dma_handle_rx.Init.Mode = DMA_CIRCULAR; + dma_handle_rx.Init.Priority = DMA_PRIORITY_LOW; + dma_handle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance_rx.dma_handle = &dma_handle_rx; + instance_rx.global_handle = handle->hdmarx; + instance_rx.irqn = get_irqn(stream_rx); + + inscribed_streams[inscribed_index] = instance_rx; + inscribed_index++; + + // TX Stream + Peripheral_type_instance instance_tx{}; + static DMA_HandleTypeDef dma_handle_tx; + + instance_tx.handle = handle; + dma_handle_tx.Instance = stream_tx; + dma_handle_rx.Init.Request = get_dma_request(handle->Instance, false); + dma_handle_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + dma_handle_tx.Init.PeriphInc = DMA_PINC_DISABLE; + dma_handle_tx.Init.MemInc = DMA_MINC_ENABLE; + dma_handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + dma_handle_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + dma_handle_tx.Init.Mode = DMA_CIRCULAR; + dma_handle_tx.Init.Priority = DMA_PRIORITY_LOW; + dma_handle_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + instance_tx.dma_handle = &dma_handle_tx; + instance_tx.global_handle = handle->hdmatx; + instance_tx.irqn = get_irqn(stream_tx); + + inscribed_streams[inscribed_index] = instance_tx; + inscribed_index++; +} + +constexpr void DMA::inscribe_stream_spi(SPI_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx) +{ + // RX Stream + Peripheral_type_instance instance_rx{}; + static DMA_HandleTypeDef dma_handle_rx; + + instance_rx.handle = handle; + dma_handle_rx.Instance = stream_rx; + dma_handle_rx.Init.Request = get_dma_request(handle->Instance, true); + dma_handle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + dma_handle_rx.Init.PeriphInc = DMA_PINC_DISABLE; + dma_handle_rx.Init.MemInc = DMA_MINC_ENABLE; + dma_handle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + dma_handle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + dma_handle_rx.Init.Mode = DMA_NORMAL; + dma_handle_rx.Init.Priority = DMA_PRIORITY_LOW; + dma_handle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + dma_handle_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + instance_rx.dma_handle = &dma_handle_rx; + instance_rx.global_handle = handle->hdmarx; + instance_rx.irqn = get_irqn(stream_rx); + + inscribed_streams[inscribed_index] = instance_rx; + inscribed_index++; + + // TX Stream + Peripheral_type_instance instance_tx{}; + static DMA_HandleTypeDef dma_handle_tx; + instance_tx.handle = handle; + dma_handle_tx.Instance = stream_tx; + dma_handle_tx.Init.Request = get_dma_request(handle->Instance, false); + dma_handle_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + dma_handle_tx.Init.PeriphInc = DMA_PINC_DISABLE; + dma_handle_tx.Init.MemInc = DMA_MINC_ENABLE; + dma_handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + dma_handle_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + dma_handle_tx.Init.Mode = DMA_NORMAL; + dma_handle_tx.Init.Priority = DMA_PRIORITY_LOW; + dma_handle_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + dma_handle_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + instance_tx.dma_handle = &dma_handle_tx; + instance_tx.global_handle = handle->hdmatx; + instance_tx.irqn = get_irqn(stream_tx); + + inscribed_streams[inscribed_index] = instance_tx; + inscribed_index++; +} + + +constexpr void DMA::inscribe_stream_fmac(FMAC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_preload, DMA_Stream_TypeDef* stream_read, DMA_Stream_TypeDef* stream_write) +{ + Peripheral_type_instance instance_preload{}; + static DMA_HandleTypeDef dma_handle_preload; + + instance_preload.handle = handle; + dma_handle_preload.Instance = stream_preload; + dma_handle_preload.Init.Request = DMA_REQUEST_MEM2MEM; + dma_handle_preload.Init.Direction = DMA_MEMORY_TO_MEMORY; + dma_handle_preload.Init.PeriphInc = DMA_PINC_ENABLE; + dma_handle_preload.Init.MemInc = DMA_MINC_DISABLE; + dma_handle_preload.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + dma_handle_preload.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + dma_handle_preload.Init.Mode = DMA_NORMAL; + dma_handle_preload.Init.Priority = DMA_PRIORITY_HIGH; + instance_preload.dma_handle = &dma_handle_preload; + instance_preload.global_handle = handle->hdmaPreload; + instance_preload.irqn = get_irqn(stream_preload); + + inscribed_streams[inscribed_index] = instance_preload; + inscribed_index++; + + Peripheral_type_instance instance_write{}; + static DMA_HandleTypeDef dma_handle_write; + + instance_write.handle = handle; + dma_handle_write.Instance = stream_write; + dma_handle_write.Init.Request = DMA_REQUEST_FMAC_WRITE; + dma_handle_write.Init.Direction = DMA_MEMORY_TO_PERIPH; + dma_handle_write.Init.PeriphInc = DMA_PINC_DISABLE; + dma_handle_write.Init.MemInc = DMA_MINC_ENABLE; + dma_handle_write.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + dma_handle_write.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + dma_handle_write.Init.Mode = DMA_NORMAL; + dma_handle_write.Init.Priority = DMA_PRIORITY_HIGH; + instance_write.dma_handle = &dma_handle_write; + instance_write.global_handle = handle->hdmaIn; + instance_write.irqn = get_irqn(stream_write); + + inscribed_streams[inscribed_index] = instance_write; + inscribed_index++; + + + Peripheral_type_instance instance_read{}; + static DMA_HandleTypeDef dma_handle_read; + + instance_read.handle = handle; + dma_handle_read.Instance = stream_read; + dma_handle_read.Init.Request = DMA_REQUEST_FMAC_READ; + dma_handle_read.Init.Direction = DMA_PERIPH_TO_MEMORY; + dma_handle_read.Init.PeriphInc = DMA_PINC_DISABLE; + dma_handle_read.Init.MemInc = DMA_MINC_ENABLE; + dma_handle_read.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + dma_handle_read.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + dma_handle_read.Init.Mode = DMA_NORMAL; + dma_handle_read.Init.Priority = DMA_PRIORITY_HIGH; + instance_read.dma_handle = &dma_handle_read; + instance_read.global_handle = handle->hdmaOut; + instance_read.irqn = get_irqn(stream_read); + + inscribed_streams[inscribed_index] = instance_read; + inscribed_index++; } @@ -29,11 +254,11 @@ constexpr void DMA::inscribe_stream(T* handle) Peripheral_type_instance instance{}; assert(handle != nullptr); assert(inscribed_index < DMA_USED); - + handle->DMA_Handle switch (handle->Instance) { case ADC1_BASE: - instance.handle = handle; + hdma_adc1.Instance = DMA1_Stream0; hdma_adc1.Init.Request = DMA_REQUEST_ADC1; hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; @@ -241,8 +466,8 @@ void DMA::start() Error_Handler(); } __HAL_LINKDMA(instance.handle, instance.global_handle, instance.dma_handle); - HAL_NVIC_SetPriority((IRQn_Type)instance.stream, 0, 0); - HAL_NVIC_EnableIRQ((IRQn_Type)instance.stream); + HAL_NVIC_SetPriority(instance.irqn, 0, 0); + HAL_NVIC_EnableIRQ(instance.irqn); }, inst); } } From 5ad8632417a92098ae277ab00514a397589d250e Mon Sep 17 00:00:00 2001 From: Jorge Date: Sun, 26 Oct 2025 22:11:22 +0100 Subject: [PATCH 034/109] feat: mejor enfoque, pero no se si el correcto --- Inc/HALAL/Models/DMA/DMA.hpp | 18 +- Inc/HALAL/Services/ADC/ADC.hpp | 3 +- Inc/HALAL/Services/Communication/I2C/I2C.hpp | 2 - Inc/HALAL/Services/Communication/SPI/SPI.hpp | 3 +- Inc/HALAL/Services/FMAC/FMAC.hpp | 4 - Src/HALAL/Models/DMA/DMA.cpp | 246 +++---------------- Src/HALAL/Services/ADC/ADC.cpp | 4 +- Src/HALAL/Services/Communication/I2C/I2C.cpp | 3 +- Src/HALAL/Services/Communication/SPI/SPI.cpp | 3 +- Src/HALAL/Services/FMAC/FMAC.cpp | 4 +- 10 files changed, 53 insertions(+), 237 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 42f70c7f4..ddf9f6245 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -34,23 +34,27 @@ class DMA { Peripheral_type_instance >; - constexpr void inscribe_stream_adc(ADC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream); + static constexpr void inscribe_stream_adc(ADC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream); - constexpr void inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); + static constexpr void inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); - constexpr void inscribe_stream_spi(SPI_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); + static constexpr void inscribe_stream_spi(SPI_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); - constexpr void inscribe_stream_fmac(FMAC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_preload, DMA_Stream_TypeDef* stream_read, DMA_Stream_TypeDef* stream_write); + static constexpr void inscribe_stream_fmac(FMAC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_preload, DMA_Stream_TypeDef* stream_read, DMA_Stream_TypeDef* stream_write); - - constexpr uint32_t get_dma_request(const void* instance, const bool mode); + template + constexpr void inscribe_stream(T* handle, Streams*... streams); - constexpr IRQn_Type get_irqn(const DMA_Stream_TypeDef* stream); + + static constexpr uint32_t get_dma_request(const void* instance, const bool mode); + + static constexpr IRQn_Type get_irqn(const DMA_Stream_TypeDef* stream); static void start(); private: inline static constinit uint8_t inscribed_index = 0; inline static constinit std::array inscribed_streams{}; + inline static DMA_HandleTypeDef dma_handles[MAX_STREAMS]; }; \ No newline at end of file diff --git a/Inc/HALAL/Services/ADC/ADC.hpp b/Inc/HALAL/Services/ADC/ADC.hpp index 633dba883..2c17d0a16 100644 --- a/Inc/HALAL/Services/ADC/ADC.hpp +++ b/Inc/HALAL/Services/ADC/ADC.hpp @@ -42,11 +42,10 @@ class ADC { uint32_t resolution; uint32_t external_trigger; vector channels; - DMA::Stream dma_stream; string name; InitData() = default; - InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, DMA::Stream dma_stream, string name); + InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, string name); }; class Peripheral { diff --git a/Inc/HALAL/Services/Communication/I2C/I2C.hpp b/Inc/HALAL/Services/Communication/I2C/I2C.hpp index 53c57388a..16f2adb23 100644 --- a/Inc/HALAL/Services/Communication/I2C/I2C.hpp +++ b/Inc/HALAL/Services/Communication/I2C/I2C.hpp @@ -33,8 +33,6 @@ class I2C { Pin &SDA; I2C_HandleTypeDef *hi2c; I2C_TypeDef *instance; - DMA::Stream RX_DMA; - DMA::Stream TX_DMA; uint8_t address = 0; uint32_t speed_frequency_kHz = 100; uint32_t data_length_in_bits = 8; diff --git a/Inc/HALAL/Services/Communication/SPI/SPI.hpp b/Inc/HALAL/Services/Communication/SPI/SPI.hpp index 99000a78f..ad3af9a79 100644 --- a/Inc/HALAL/Services/Communication/SPI/SPI.hpp +++ b/Inc/HALAL/Services/Communication/SPI/SPI.hpp @@ -55,8 +55,7 @@ class SPI{ SPI_HandleTypeDef* hspi; /**< HAL spi struct pin. */ SPI_TypeDef* instance; /**< HAL spi instance. */ - DMA::Stream hdma_tx; /**< HAL DMA handler for writting */ - DMA::Stream hdma_rx; /**< HAL DMA handler for reading */ + uint32_t baud_rate_prescaler; /**< SPI baud prescaler.*/ uint32_t mode = SPI_MODE_MASTER; /**< SPI mode. */ diff --git a/Inc/HALAL/Services/FMAC/FMAC.hpp b/Inc/HALAL/Services/FMAC/FMAC.hpp index 9348dd94c..65ad277f2 100644 --- a/Inc/HALAL/Services/FMAC/FMAC.hpp +++ b/Inc/HALAL/Services/FMAC/FMAC.hpp @@ -58,10 +58,6 @@ class MultiplierAccelerator{ struct FMACInstance{ FMACmodes mode; FMAC_HandleTypeDef *hfmac; - DMA::Stream dma_preload; - DMA::Stream dma_read; - DMA::Stream dma_write; - }; static FMACInstance Instance; diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index 245e54259..42f117940 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -63,7 +63,6 @@ constexpr IRQn_Type DMA::get_irqn(const DMA_Stream_TypeDef* stream) { constexpr void DMA::inscribe_stream_adc(ADC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream) { Peripheral_type_instance instance{}; - static DMA_HandleTypeDef dma_handle; instance.handle = handle; dma_handle.Instance = stream; @@ -89,7 +88,7 @@ constexpr void DMA::inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_Ty { // RX Stream Peripheral_type_instance instance_rx{}; - static DMA_HandleTypeDef dma_handle_rx; + instance_rx.handle = handle; dma_handle_rx.Instance = stream_rx; @@ -111,7 +110,7 @@ constexpr void DMA::inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_Ty // TX Stream Peripheral_type_instance instance_tx{}; - static DMA_HandleTypeDef dma_handle_tx; + instance_tx.handle = handle; dma_handle_tx.Instance = stream_tx; @@ -248,213 +247,6 @@ constexpr void DMA::inscribe_stream_fmac(FMAC_HandleTypeDef* handle, DMA_Stream_ } -template -constexpr void DMA::inscribe_stream(T* handle) - { - Peripheral_type_instance instance{}; - assert(handle != nullptr); - assert(inscribed_index < DMA_USED); - handle->DMA_Handle - switch (handle->Instance) - { - case ADC1_BASE: - - hdma_adc1.Instance = DMA1_Stream0; - hdma_adc1.Init.Request = DMA_REQUEST_ADC1; - hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; - hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_adc1.Init.Mode = DMA_CIRCULAR; - hdma_adc1.Init.Priority = DMA_PRIORITY_LOW; - hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_adc1; - instance.stream = Stream::DMA1Stream0; - instance.global_handle= &DMA_Handle - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case ADC2_BASE: - instance.handle = handle; - hdma_adc2.Instance = DMA1_Stream1; - hdma_adc2.Init.Request = DMA_REQUEST_ADC2; - hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_adc2.Init.MemInc = DMA_MINC_ENABLE; - hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_adc2.Init.Mode = DMA_CIRCULAR; - hdma_adc2.Init.Priority = DMA_PRIORITY_LOW; - hdma_adc2.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_adc2; - instance.stream = Stream::DMA1Stream1; - instance.global_handle= &DMA_Handle - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case ADC3_BASE: - instance.handle = handle; - hdma_adc3.Instance = DMA1_Stream2; - hdma_adc3.Init.Request = DMA_REQUEST_ADC3; - hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_adc3.Init.MemInc = DMA_MINC_ENABLE; - hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_adc3.Init.Mode = DMA_CIRCULAR; - hdma_adc3.Init.Priority = DMA_PRIORITY_LOW; - hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_adc3; - instance.stream = DMA1Stream2; - instance.global_handle= &DMA_Handle; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case I2C2_BASE: - instance.handle = handle; - hdma_i2c2_rx.Instance = DMA1_Stream3; - hdma_i2c2_rx.Init.Request = DMA_REQUEST_I2C2_RX; - hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE; - hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - hdma_i2c2_rx.Init.Mode = DMA_CIRCULAR; - hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_LOW; - hdma_i2c2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_i2c2_rx; - instance.stream = Stream::DMA1Stream3; - instance.global_handle= &hdmarx; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_i2c2_tx.Instance = DMA1_Stream4; - hdma_i2c2_tx.Init.Request = DMA_REQUEST_I2C2_TX; - hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE; - hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - hdma_i2c2_tx.Init.Mode = DMA_CIRCULAR; - hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_LOW; - hdma_i2c2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.dma_handle = &hdma_i2c2_tx; - instance.stream = Stream::DMA1Stream4; - instance.global_handle= &hdmatx; - - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case FMAC_BASE: - hdma_fmac_preload.Instance = DMA2_Stream0; - hdma_fmac_preload.Init.Request = DMA_REQUEST_MEM2MEM; - hdma_fmac_preload.Init.Direction = DMA_MEMORY_TO_MEMORY; - hdma_fmac_preload.Init.PeriphInc = DMA_PINC_ENABLE; - hdma_fmac_preload.Init.MemInc = DMA_MINC_DISABLE; - hdma_fmac_preload.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_fmac_preload.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_fmac_preload.Init.Mode = DMA_NORMAL; - hdma_fmac_preload.Init.Priority = DMA_PRIORITY_HIGH; - instance.dma_handle = &hdma_fmac_preload; - instance.stream = Stream::DMA2Stream0; - instance.global_handle= &hdmaPreload; - - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_fmac_write.Instance = DMA2_Stream1; - hdma_fmac_write.Init.Request = DMA_REQUEST_FMAC_WRITE; - hdma_fmac_write.Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_fmac_write.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_fmac_write.Init.MemInc = DMA_MINC_ENABLE; - hdma_fmac_write.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_fmac_write.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_fmac_write.Init.Mode = DMA_NORMAL; - hdma_fmac_write.Init.Priority = DMA_PRIORITY_HIGH; - instance.dma_handle = &hdma_fmac_write; - instance.stream = Stream::DMA2Stream1; - instance.global_handle= &hdmaIn; - - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_fmac_read.Instance = DMA2_Stream2; - hdma_fmac_read.Init.Request = DMA_REQUEST_FMAC_READ; - hdma_fmac_read.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_fmac_read.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_fmac_read.Init.MemInc = DMA_MINC_ENABLE; - hdma_fmac_read.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_fmac_read.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - hdma_fmac_read.Init.Mode = DMA_NORMAL; - hdma_fmac_read.Init.Priority = DMA_PRIORITY_HIGH; - instance.dma_handle = &hdma_fmac_read; - instance.stream = Stream::DMA2Stream2; - instance.global_handle= &hdmaOut; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - case SPI3_BASE: - hdma_spi3_rx.Instance = DMA1_Stream5; - hdma_spi3_rx.Init.Request = DMA_REQUEST_SPI3_RX; - hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE; - hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - hdma_spi3_rx.Init.Mode = DMA_NORMAL; - hdma_spi3_rx.Init.Priority = DMA_PRIORITY_LOW; - hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - hdma_spi3_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - instance.dma_handle = &hdma_spi3_rx; - instance.stream = Stream::DMA1Stream5; - instance.global_handle= &hdmarx; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - - hdma_spi3_tx.Instance = DMA1_Stream6; - hdma_spi3_tx.Init.Request = DMA_REQUEST_SPI3_TX; - hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_spi3_tx.Init.MemInc = DMA_MINC_ENABLE; - hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - hdma_spi3_tx.Init.Mode = DMA_NORMAL; - hdma_spi3_tx.Init.Priority = DMA_PRIORITY_LOW; - hdma_spi3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - hdma_spi3_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - instance.dma_handle = &hdma_spi3_tx; - instance.stream = Stream::DMA1Stream6; - instance.global_handle= &hdmatx; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; - break; - - default: - // Aqui poner que diga que el handle esta mal o algo - ErrorHandler(); - break; - } - - return; - } - - void DMA::start() { __HAL_RCC_DMA1_CLK_ENABLE(); @@ -465,9 +257,41 @@ void DMA::start() { Error_Handler(); } - __HAL_LINKDMA(instance.handle, instance.global_handle, instance.dma_handle); + __HAL_LINKDMA(instance->handle, instance.global_handle, instance->dma_handle); HAL_NVIC_SetPriority(instance.irqn, 0, 0); HAL_NVIC_EnableIRQ(instance.irqn); }, inst); } } + + +template +constexpr void DMA::inscribe_stream(T* handle, Streams*... streams){ + if constexpr (sizeof...(Streams) > MAX_STREAMS){ + ErrorHandler("The maximum number of streams is %d", MAX_STREAMS); + } + uint8_t num_streams = sizeof...(Streams); + + // Verify that the number of streams is correct for different peripherials + if constexpr (std::is_same && num_streams != 1){ + ErrorHandler("For ADC, there must be only one stream"); + } + else if constexpr (std::is_same && num_streams != 2){ + ErrorHandler("For SPI, there must be two streams (RX and TX)"); + } + else if constexpr (std::is_same && num_streams != 2){ + ErrorHandler("For I2C, there must be two streams (RX and TX)"); + } + else if constexpr (std::is_same && num_streams != 3){ + ErrorHandler("For FMAC, there must be three streams (preload, write and read)"); + } + + + Peripheral_type_instance instances[num_streams]; + + // All of the instances of the same peripherial will have the same handle + for constexpr (uint8_t num : num_streams){ + instances[num].handle = handle; + } + +} diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index d63e3b920..2717f2c7d 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -16,8 +16,8 @@ uint8_t ADC::id_counter = 0; unordered_map ADC::active_instances = {}; -ADC::InitData::InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, DMA::Stream dma_stream, string name) : - adc(adc), resolution(resolution), external_trigger(external_trigger), channels(channels), dma_stream(dma_stream), name(name) {} +ADC::InitData::InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, string name) : + adc(adc), resolution(resolution), external_trigger(external_trigger), channels(channels), name(name) {} ADC::Peripheral::Peripheral(ADC_HandleTypeDef* handle, LowPowerTimer& timer, InitData& init_data) : handle(handle), timer(timer), init_data(init_data) { diff --git a/Src/HALAL/Services/Communication/I2C/I2C.cpp b/Src/HALAL/Services/Communication/I2C/I2C.cpp index 61655d304..6ba12da50 100644 --- a/Src/HALAL/Services/Communication/I2C/I2C.cpp +++ b/Src/HALAL/Services/Communication/I2C/I2C.cpp @@ -23,8 +23,7 @@ uint8_t I2C::inscribe(I2C::Peripheral &i2c, uint8_t address) { Pin::inscribe(i2c_instance->SCL, ALTERNATIVE); Pin::inscribe(i2c_instance->SDA, ALTERNATIVE); - DMA::inscribe_stream(i2c_instance->RX_DMA); - DMA::inscribe_stream(i2c_instance->TX_DMA); + DMA::inscribe_stream_i2c(i2c_instance->hi2c, DMA1_Stream3, DMA1_Stream4); uint8_t id = I2C::id_counter++; diff --git a/Src/HALAL/Services/Communication/SPI/SPI.cpp b/Src/HALAL/Services/Communication/SPI/SPI.cpp index 9b498b12b..5d5eb9058 100644 --- a/Src/HALAL/Services/Communication/SPI/SPI.cpp +++ b/Src/HALAL/Services/Communication/SPI/SPI.cpp @@ -56,8 +56,7 @@ uint8_t SPI::inscribe(SPI::Peripheral& spi) { uint8_t id = SPI::id_counter++; if (spi_instance->use_DMA) { - DMA::inscribe_stream(spi_instance->hdma_rx); - DMA::inscribe_stream(spi_instance->hdma_tx); + DMA::inscribe_stream_spi(spi_instance->hspi, DMA1_Stream5, DMA1_Stream6); } SPI::registered_spi[id] = spi_instance; SPI::registered_spi_by_handler[spi_instance->hspi] = spi_instance; diff --git a/Src/HALAL/Services/FMAC/FMAC.cpp b/Src/HALAL/Services/FMAC/FMAC.cpp index 6b07bb19f..4b2107cab 100644 --- a/Src/HALAL/Services/FMAC/FMAC.cpp +++ b/Src/HALAL/Services/FMAC/FMAC.cpp @@ -32,9 +32,7 @@ void MultiplierAccelerator::IIR_software_in_software_out_inscribe(uint16_t input } void MultiplierAccelerator::inscribe(){ - DMA::inscribe_stream(Instance.dma_preload); - DMA::inscribe_stream(Instance.dma_read); - DMA::inscribe_stream(Instance.dma_write); + DMA::inscribe_stream_fmac(Instance.hfmac, DMA2_Stream0, DMA2_Stream1, DMA2_Stream2); } void MultiplierAccelerator::start(){ From d832eec66060684ffc19967c59d658c3c6fcf734 Mon Sep 17 00:00:00 2001 From: Jorge Date: Tue, 11 Nov 2025 12:09:27 +0100 Subject: [PATCH 035/109] feat: comprueba el numero de perifericos, cambios de nombre a algunas funcion y reorganizar un poco --- Inc/HALAL/Models/DMA/DMA.hpp | 319 +++++++++++++++++++++++++++++++---- Src/HALAL/Models/DMA/DMA.cpp | 297 -------------------------------- 2 files changed, 283 insertions(+), 333 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index ddf9f6245..640a888c4 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -1,60 +1,307 @@ /* * DMA.hpp * - * Created on: 10 dic. 2022 - * Author: aleja - */ - + * Created on: 10 dic. 2022 + * Author: aleja +*/ #pragma once - #include "C++Utilities/CppUtils.hpp" #include "stm32h7xx_hal.h" #include "main.h" #include "HALAL/Models/MPUManager/MPUManager.hpp" #include -#include +#include + #define MAX_STREAMS 16 -#define STREAMS_USED 10 + + + +template +struct Config { + uint32_t instance; + uint8_t num_streams {N}; + std::array handles; + std::array streams; + std::array irqn; +}; class DMA { -public: - template - struct Peripheral_type_instance { - T* handle; - DMA_HandleTypeDef* dma_handle; - DMA_HandleTypeDef* global_handle; - IRQn_Type irqn; - }; + public: + template + static constexpr auto inscribe_stream(); + + static void start(); + + template + constexpr bool is_spi(); + + template + constexpr bool is_i2c(); + + template + constexpr bool is_adc(); + + template + constexpr bool is_fmac(); + + template + static constexpr uint32_t get_Request(); + + template + static constexpr uint32_t get_Direction(); + + template + static constexpr uint32_t get_PeriphInc(); + + template + static constexpr uint32_t get_MemInc(); + + template + static constexpr uint32_t get_PeriphDataAlignment(); + + template + static constexpr uint32_t get_MemDataAlignment(); + + template + static constexpr uint32_t get_Mode(); + + template + static constexpr uint32_t get_Priority(); + + template + static constexpr uint32_t get_FIFOMode(); + + template + static constexpr uint32_t get_FIFOThreshold(); + + template + static constexpr uint32_t get_MemBurst(); + + template + static constexpr uint32_t get_PeriphBurst(); + + template + static constexpr IRQn_Type get_irqn(); +}; + + +template +constexpr auto DMA::inscribe_stream(){ + constexpr std::size_t N = sizeof...(Streams); + static_assert(N <= MAX_STREAMS, "Too many streams inscribed"); + + Config handleConfig; + handleConfig.instance = Instance; + constexpr uint32_t stream_vals[N] = {Streams...}; + handleConfig.streams = std::array{reinterpret_cast(Streams)...}; + + if constexpr (is_adc()) { + static_assert(N == 1, "ADC DMA must have exactly one stream"); + } + else if constexpr (is_fmac()) { + static_assert(N == 3, "FMAC DMA must have exactly three streams"); + } + else { + static_assert(N == 2, "Peripheral DMA must have exactly two streams (RX and TX)"); + } + + // TODO: verificar que los streams no esten siendo usados + + [&](std::index_sequence) { + (([&] { + handleConfig.handles[I].Request = get_Request(); + handleConfig.handles[I].Direction = get_Direction(); + handleConfig.handles[I].PeriphInc = get_PeriphInc(); + handleConfig.handles[I].MemInc = get_MemInc(); + handleConfig.handles[I].PeriphDataAlignment = get_PeriphDataAlignment(); + handleConfig.handles[I].MemDataAlignment = get_MemDataAlignment(); + handleConfig.handles[I].Mode = get_Mode(); + handleConfig.handles[I].Priority = get_Priority(); + handleConfig.handles[I].FIFOMode = get_FIFOMode(); + handleConfig.handles[I].FIFOThreshold = get_FIFOThreshold(); + handleConfig.handles[I].MemBurst = get_MemBurst(); + handleConfig.handles[I].PeriphBurst = get_PeriphBurst(); + + handleConfig[I] = get_irqn(); + + }()), ...); + }(std::make_index_sequence{}); + + return handleConfig; +} + +template +constexpr bool DMA::is_spi() { + return Instance == SPI1_BASE || Instance == SPI2_BASE || Instance == SPI3_BASE || + Instance == SPI4_BASE || Instance == SPI5_BASE; +} + +template +constexpr bool DMA::is_i2c() { + return Instance == I2C1_BASE || Instance == I2C2_BASE || Instance == I2C3_BASE || Instance == I2C5_BASE; +} + +template +constexpr bool DMA::is_adc() { + return Instance == ADC1_BASE || Instance == ADC2_BASE || Instance == ADC3_BASE; +} + +template +constexpr bool DMA::is_fmac() { + return Instance == FMAC_BASE; +} + +template +constexpr IRQn_Type DMA::get_irqn() { + if (stream == DMA1_Stream0_BASE) return DMA1_Stream0_IRQn; + if (stream == DMA1_Stream1_BASE) return DMA1_Stream1_IRQn; + if (stream == DMA1_Stream2_BASE) return DMA1_Stream2_IRQn; + if (stream == DMA1_Stream3_BASE) return DMA1_Stream3_IRQn; + if (stream == DMA1_Stream4_BASE) return DMA1_Stream4_IRQn; + if (stream == DMA1_Stream5_BASE) return DMA1_Stream5_IRQn; + if (stream == DMA1_Stream6_BASE) return DMA1_Stream6_IRQn; + if (stream == DMA1_Stream7_BASE) return DMA1_Stream7_IRQn; + + if (stream == DMA2_Stream0_BASE) return DMA2_Stream0_IRQn; + if (stream == DMA2_Stream1_BASE) return DMA2_Stream1_IRQn; + if (stream == DMA2_Stream2_BASE) return DMA2_Stream2_IRQn; + if (stream == DMA2_Stream3_BASE) return DMA2_Stream3_IRQn; + if (stream == DMA2_Stream4_BASE) return DMA2_Stream4_IRQn; + if (stream == DMA2_Stream5_BASE) return DMA2_Stream5_IRQn; + if (stream == DMA2_Stream6_BASE) return DMA2_Stream6_IRQn; + return DMA2_Stream7_IRQn; +} + + +template +constexpr uint32_t DMA::get_Request() { + if constexpr (Instance == ADC1_BASE) return DMA_REQUEST_ADC1; + if constexpr (Instance == ADC2_BASE) return DMA_REQUEST_ADC2; + if constexpr (Instance == ADC3_BASE) return DMA_REQUEST_ADC3; + + if constexpr (Instance == I2C1_BASE && i == 0) return DMA_REQUEST_I2C1_RX; + if constexpr (Instance == I2C1_BASE && i == 1) return DMA_REQUEST_I2C1_TX; + if constexpr (Instance == I2C2_BASE && i == 0) return DMA_REQUEST_I2C2_RX; + if constexpr (Instance == I2C2_BASE && i == 1) return DMA_REQUEST_I2C2_TX; + if constexpr (Instance == I2C3_BASE && i == 0) return DMA_REQUEST_I2C3_RX; + if constexpr (Instance == I2C3_BASE && i == 1) return DMA_REQUEST_I2C3_TX; + if constexpr (Instance == I2C5_BASE && i == 0) return DMA_REQUEST_I2C5_RX; + if constexpr (Instance == I2C5_BASE && i == 1) return DMA_REQUEST_I2C5_TX; + + if constexpr (Instance == SPI1_BASE && i == 0) return DMA_REQUEST_SPI1_RX; + if constexpr (Instance == SPI1_BASE && i == 1) return DMA_REQUEST_SPI1_TX; + if constexpr (Instance == SPI2_BASE && i == 0) return DMA_REQUEST_SPI2_RX; + if constexpr (Instance == SPI2_BASE && i == 1) return DMA_REQUEST_SPI2_TX; + if constexpr (Instance == SPI3_BASE && i == 0) return DMA_REQUEST_SPI3_RX; + if constexpr (Instance == SPI3_BASE && i == 1) return DMA_REQUEST_SPI3_TX; + if constexpr (Instance == SPI4_BASE && i == 0) return DMA_REQUEST_SPI4_RX; + if constexpr (Instance == SPI4_BASE && i == 1) return DMA_REQUEST_SPI4_TX; + if constexpr (Instance == SPI5_BASE && i == 0) return DMA_REQUEST_SPI5_RX; + if constexpr (Instance == SPI5_BASE && i == 1) return DMA_REQUEST_SPI5_TX; + + if constexpr (Instance == FMAC_BASE && i == 0) return DMA_REQUEST_MEM2MEM; + if constexpr (Instance == FMAC_BASE && i == 1) return DMA_REQUEST_FMAC_WRITE; + if constexpr (Instance == FMAC_BASE && i == 2) return DMA_REQUEST_FMAC_READ; + return 0; +} + +template +constexpr uint32_t DMA::get_Direction() { + if constexpr (is_fmac() && i == 0){ + return DMA_MEMORY_TO_MEMORY; + } + else if constexpr ((is_i2c() && i == 1) || + (is_spi() && i == 1) || + (is_fmac() && i == 1)){ + return DMA_MEMORY_TO_PERIPH; + } + + return DMA_PERIPH_TO_MEMORY; + +} - //To allow the array to be multiple types, idk first thing that came to mind - using InstanceList = std::variant< - Peripheral_type_instance, - Peripheral_type_instance, - Peripheral_type_instance, - Peripheral_type_instance - >; +template +constexpr uint32_t DMA::get_PeriphInc() { + if constexpr (is_fmac() && i == 0){ + return DMA_PINC_ENABLE; + } + return DMA_PINC_DISABLE; +} - static constexpr void inscribe_stream_adc(ADC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream); +template +constexpr uint32_t DMA::get_MemInc() { + if constexpr (is_fmac() && i == 0){ + return DMA_MINC_DISABLE; + } + return DMA_MINC_ENABLE; +} - static constexpr void inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); +template +constexpr uint32_t DMA::get_PeriphDataAlignment() { + if constexpr (is_spi()){ + return DMA_PDATAALIGN_WORD; + } + else if constexpr (is_spi()){ + return DMA_PDATAALIGN_BYTE; + } - static constexpr void inscribe_stream_spi(SPI_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx); + return DMA_PDATAALIGN_HALFWORD; +} - static constexpr void inscribe_stream_fmac(FMAC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_preload, DMA_Stream_TypeDef* stream_read, DMA_Stream_TypeDef* stream_write); +template +constexpr uint32_t DMA::get_MemDataAlignment() { + if constexpr (is_spi()){ + return DMA_MDATAALIGN_WORD; + } + else if constexpr (is_spi()){ + return DMA_MDATAALIGN_BYTE; + } + return DMA_MDATAALIGN_HALFWORD; +} - template - constexpr void inscribe_stream(T* handle, Streams*... streams); +template +constexpr uint32_t DMA::get_Mode() { + if constexpr (is_spi() || is_fmac()){ + return DMA_NORMAL; + } + + return DMA_CIRCULAR; + +} +template +constexpr uint32_t DMA::get_Priority() { + if constexpr (is_fmac()){ + return DMA_PRIORITY_HIGH; + } + + return DMA_PRIORITY_LOW; +} - static constexpr uint32_t get_dma_request(const void* instance, const bool mode); +template +constexpr uint32_t DMA::get_FIFOMode() { + if constexpr (is_fmac()){ + return DMA_FIFOMODE_ENABLE; + } + + return DMA_FIFOMODE_DISABLE; +} - static constexpr IRQn_Type get_irqn(const DMA_Stream_TypeDef* stream); +template +constexpr uint32_t DMA::get_FIFOThreshold() { + if constexpr (is_spi()){ + return DMA_FIFO_THRESHOLD_FULL; + } + return DMA_FIFO_THRESHOLD_HALFFULL; +} - static void start(); +template +constexpr uint32_t DMA::get_MemBurst() { + return DMA_MBURST_SINGLE; +} -private: - inline static constinit uint8_t inscribed_index = 0; - inline static constinit std::array inscribed_streams{}; - inline static DMA_HandleTypeDef dma_handles[MAX_STREAMS]; -}; \ No newline at end of file +template +constexpr uint32_t DMA::get_PeriphBurst() { + return DMA_PBURST_SINGLE; +} diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index 42f117940..e69de29bb 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -1,297 +0,0 @@ -/* - * DMA.cpp - * - * Created on: 10 dic. 2022 - * Author: aleja - */ - -#include "HALAL/Models/DMA/DMA.hpp" -#include "ErrorHandler/ErrorHandler.hpp" - - -constexpr uint32_t DMA::get_dma_request(const void* instance, const bool mode) { - if (instance == ADC1) return DMA_REQUEST_ADC1; - if (instance == ADC2) return DMA_REQUEST_ADC2; - if (instance == ADC3) return DMA_REQUEST_ADC3; - - if (instance == I2C1 && mode) return DMA_REQUEST_I2C1_RX; - if (instance == I2C1 && !mode) return DMA_REQUEST_I2C1_TX; - if (instance == I2C2 && mode) return DMA_REQUEST_I2C2_RX; - if (instance == I2C2 && !mode) return DMA_REQUEST_I2C2_TX; - if (instance == I2C3 && mode) return DMA_REQUEST_I2C3_RX; - if (instance == I2C3 && !mode) return DMA_REQUEST_I2C3_TX; - if (instance == I2C5 && mode) return DMA_REQUEST_I2C5_RX; // NO hay 4? - if (instance == I2C5 && !mode) return DMA_REQUEST_I2C5_TX; - - if (instance == SPI1 && mode) return DMA_REQUEST_SPI1_RX; - if (instance == SPI1 && !mode) return DMA_REQUEST_SPI1_TX; - if (instance == SPI2 && mode) return DMA_REQUEST_SPI2_RX; - if (instance == SPI2 && !mode) return DMA_REQUEST_SPI2_TX; - if (instance == SPI3 && mode) return DMA_REQUEST_SPI3_RX; - if (instance == SPI3 && !mode) return DMA_REQUEST_SPI3_TX; - if (instance == SPI4 && mode) return DMA_REQUEST_SPI4_RX; - if (instance == SPI4 && !mode) return DMA_REQUEST_SPI4_TX; - if (instance == SPI5 && mode) return DMA_REQUEST_SPI5_RX; - if (instance == SPI5 && !mode) return DMA_REQUEST_SPI5_TX; // NO hay 6? - - return 0; -} - - -constexpr IRQn_Type DMA::get_irqn(const DMA_Stream_TypeDef* stream) { - if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; - if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; - if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; - if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; - if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; - if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; - if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; - if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; - - if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; - if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; - if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; - if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; - if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; - if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; - if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; - if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; -} - - - -constexpr void DMA::inscribe_stream_adc(ADC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream) -{ - Peripheral_type_instance instance{}; - - instance.handle = handle; - dma_handle.Instance = stream; - dma_handle.Init.Request = get_dma_request(handle->Instance, true); // El modo no hace nada aquí - dma_handle.Init.Direction = DMA_PERIPH_TO_MEMORY; - dma_handle.Init.PeriphInc = DMA_PINC_DISABLE; - dma_handle.Init.MemInc = DMA_MINC_ENABLE; - dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - dma_handle.Init.Mode = DMA_CIRCULAR; - dma_handle.Init.Priority = DMA_PRIORITY_LOW; - dma_handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance.global_handle = handle->DMA_Handle; - instance.irqn = get_irqn(stream); - instance.dma_handle = &dma_handle; - - inscribed_streams[inscribed_index] = instance; - inscribed_index++; -} - - -constexpr void DMA::inscribe_stream_i2c(I2C_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx) -{ - // RX Stream - Peripheral_type_instance instance_rx{}; - - - instance_rx.handle = handle; - dma_handle_rx.Instance = stream_rx; - dma_handle_rx.Init.Request = get_dma_request(handle->Instance, true); - dma_handle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; - dma_handle_rx.Init.PeriphInc = DMA_PINC_DISABLE; - dma_handle_rx.Init.MemInc = DMA_MINC_ENABLE; - dma_handle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - dma_handle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - dma_handle_rx.Init.Mode = DMA_CIRCULAR; - dma_handle_rx.Init.Priority = DMA_PRIORITY_LOW; - dma_handle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance_rx.dma_handle = &dma_handle_rx; - instance_rx.global_handle = handle->hdmarx; - instance_rx.irqn = get_irqn(stream_rx); - - inscribed_streams[inscribed_index] = instance_rx; - inscribed_index++; - - // TX Stream - Peripheral_type_instance instance_tx{}; - - - instance_tx.handle = handle; - dma_handle_tx.Instance = stream_tx; - dma_handle_rx.Init.Request = get_dma_request(handle->Instance, false); - dma_handle_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; - dma_handle_tx.Init.PeriphInc = DMA_PINC_DISABLE; - dma_handle_tx.Init.MemInc = DMA_MINC_ENABLE; - dma_handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - dma_handle_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - dma_handle_tx.Init.Mode = DMA_CIRCULAR; - dma_handle_tx.Init.Priority = DMA_PRIORITY_LOW; - dma_handle_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - instance_tx.dma_handle = &dma_handle_tx; - instance_tx.global_handle = handle->hdmatx; - instance_tx.irqn = get_irqn(stream_tx); - - inscribed_streams[inscribed_index] = instance_tx; - inscribed_index++; -} - - -constexpr void DMA::inscribe_stream_spi(SPI_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_rx, DMA_Stream_TypeDef* stream_tx) -{ - // RX Stream - Peripheral_type_instance instance_rx{}; - static DMA_HandleTypeDef dma_handle_rx; - - instance_rx.handle = handle; - dma_handle_rx.Instance = stream_rx; - dma_handle_rx.Init.Request = get_dma_request(handle->Instance, true); - dma_handle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; - dma_handle_rx.Init.PeriphInc = DMA_PINC_DISABLE; - dma_handle_rx.Init.MemInc = DMA_MINC_ENABLE; - dma_handle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - dma_handle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - dma_handle_rx.Init.Mode = DMA_NORMAL; - dma_handle_rx.Init.Priority = DMA_PRIORITY_LOW; - dma_handle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - dma_handle_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - instance_rx.dma_handle = &dma_handle_rx; - instance_rx.global_handle = handle->hdmarx; - instance_rx.irqn = get_irqn(stream_rx); - - inscribed_streams[inscribed_index] = instance_rx; - inscribed_index++; - - // TX Stream - Peripheral_type_instance instance_tx{}; - static DMA_HandleTypeDef dma_handle_tx; - - instance_tx.handle = handle; - dma_handle_tx.Instance = stream_tx; - dma_handle_tx.Init.Request = get_dma_request(handle->Instance, false); - dma_handle_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; - dma_handle_tx.Init.PeriphInc = DMA_PINC_DISABLE; - dma_handle_tx.Init.MemInc = DMA_MINC_ENABLE; - dma_handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - dma_handle_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - dma_handle_tx.Init.Mode = DMA_NORMAL; - dma_handle_tx.Init.Priority = DMA_PRIORITY_LOW; - dma_handle_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - dma_handle_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - instance_tx.dma_handle = &dma_handle_tx; - instance_tx.global_handle = handle->hdmatx; - instance_tx.irqn = get_irqn(stream_tx); - - inscribed_streams[inscribed_index] = instance_tx; - inscribed_index++; -} - - -constexpr void DMA::inscribe_stream_fmac(FMAC_HandleTypeDef* handle, DMA_Stream_TypeDef* stream_preload, DMA_Stream_TypeDef* stream_read, DMA_Stream_TypeDef* stream_write) -{ - Peripheral_type_instance instance_preload{}; - static DMA_HandleTypeDef dma_handle_preload; - - instance_preload.handle = handle; - dma_handle_preload.Instance = stream_preload; - dma_handle_preload.Init.Request = DMA_REQUEST_MEM2MEM; - dma_handle_preload.Init.Direction = DMA_MEMORY_TO_MEMORY; - dma_handle_preload.Init.PeriphInc = DMA_PINC_ENABLE; - dma_handle_preload.Init.MemInc = DMA_MINC_DISABLE; - dma_handle_preload.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - dma_handle_preload.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - dma_handle_preload.Init.Mode = DMA_NORMAL; - dma_handle_preload.Init.Priority = DMA_PRIORITY_HIGH; - instance_preload.dma_handle = &dma_handle_preload; - instance_preload.global_handle = handle->hdmaPreload; - instance_preload.irqn = get_irqn(stream_preload); - - inscribed_streams[inscribed_index] = instance_preload; - inscribed_index++; - - Peripheral_type_instance instance_write{}; - static DMA_HandleTypeDef dma_handle_write; - - instance_write.handle = handle; - dma_handle_write.Instance = stream_write; - dma_handle_write.Init.Request = DMA_REQUEST_FMAC_WRITE; - dma_handle_write.Init.Direction = DMA_MEMORY_TO_PERIPH; - dma_handle_write.Init.PeriphInc = DMA_PINC_DISABLE; - dma_handle_write.Init.MemInc = DMA_MINC_ENABLE; - dma_handle_write.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - dma_handle_write.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - dma_handle_write.Init.Mode = DMA_NORMAL; - dma_handle_write.Init.Priority = DMA_PRIORITY_HIGH; - instance_write.dma_handle = &dma_handle_write; - instance_write.global_handle = handle->hdmaIn; - instance_write.irqn = get_irqn(stream_write); - - inscribed_streams[inscribed_index] = instance_write; - inscribed_index++; - - - Peripheral_type_instance instance_read{}; - static DMA_HandleTypeDef dma_handle_read; - - instance_read.handle = handle; - dma_handle_read.Instance = stream_read; - dma_handle_read.Init.Request = DMA_REQUEST_FMAC_READ; - dma_handle_read.Init.Direction = DMA_PERIPH_TO_MEMORY; - dma_handle_read.Init.PeriphInc = DMA_PINC_DISABLE; - dma_handle_read.Init.MemInc = DMA_MINC_ENABLE; - dma_handle_read.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - dma_handle_read.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - dma_handle_read.Init.Mode = DMA_NORMAL; - dma_handle_read.Init.Priority = DMA_PRIORITY_HIGH; - instance_read.dma_handle = &dma_handle_read; - instance_read.global_handle = handle->hdmaOut; - instance_read.irqn = get_irqn(stream_read); - - inscribed_streams[inscribed_index] = instance_read; - inscribed_index++; -} - - -void DMA::start() -{ - __HAL_RCC_DMA1_CLK_ENABLE(); - __HAL_RCC_DMA2_CLK_ENABLE(); - for (auto const &inst : inscribed_streams) { - std::visit([&](auto const &instance) { - if (HAL_DMA_Init(instance.dma_handle) != HAL_OK) - { - Error_Handler(); - } - __HAL_LINKDMA(instance->handle, instance.global_handle, instance->dma_handle); - HAL_NVIC_SetPriority(instance.irqn, 0, 0); - HAL_NVIC_EnableIRQ(instance.irqn); - }, inst); - } -} - - -template -constexpr void DMA::inscribe_stream(T* handle, Streams*... streams){ - if constexpr (sizeof...(Streams) > MAX_STREAMS){ - ErrorHandler("The maximum number of streams is %d", MAX_STREAMS); - } - uint8_t num_streams = sizeof...(Streams); - - // Verify that the number of streams is correct for different peripherials - if constexpr (std::is_same && num_streams != 1){ - ErrorHandler("For ADC, there must be only one stream"); - } - else if constexpr (std::is_same && num_streams != 2){ - ErrorHandler("For SPI, there must be two streams (RX and TX)"); - } - else if constexpr (std::is_same && num_streams != 2){ - ErrorHandler("For I2C, there must be two streams (RX and TX)"); - } - else if constexpr (std::is_same && num_streams != 3){ - ErrorHandler("For FMAC, there must be three streams (preload, write and read)"); - } - - - Peripheral_type_instance instances[num_streams]; - - // All of the instances of the same peripherial will have the same handle - for constexpr (uint8_t num : num_streams){ - instances[num].handle = handle; - } - -} From e39e204d1a9130540678246c9b5b742bef1c0f84 Mon Sep 17 00:00:00 2001 From: Jorge Date: Tue, 11 Nov 2025 13:42:50 +0100 Subject: [PATCH 036/109] feat: struct constructor, better is... logic, refactor inscribe (technically consteval), and a few more constexprs --- Inc/HALAL/Models/DMA/DMA.hpp | 141 ++++++++++++++++++----------------- Src/HALAL/Models/DMA/DMA.cpp | 28 +++++++ 2 files changed, 101 insertions(+), 68 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 640a888c4..fbd3ac399 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -14,24 +14,30 @@ #define MAX_STREAMS 16 - - template struct Config { uint32_t instance; - uint8_t num_streams {N}; - std::array handles; - std::array streams; - std::array irqn; + std::array handles{}; + std::array streams{}; + std::array irqn{}; + + constexpr Config(uint32_t inst, + std::array h, + std::array s, + std::array i) + : instance(inst), handles(h), streams(s), irqn(i) {} }; class DMA { public: template - static constexpr auto inscribe_stream(); + static consteval auto inscribe_stream(); static void start(); + template + constexpr bool is_one_of(); + template constexpr bool is_spi(); @@ -86,64 +92,62 @@ class DMA { template -constexpr auto DMA::inscribe_stream(){ +consteval auto DMA::inscribe_stream() { constexpr std::size_t N = sizeof...(Streams); static_assert(N <= MAX_STREAMS, "Too many streams inscribed"); - - Config handleConfig; - handleConfig.instance = Instance; - constexpr uint32_t stream_vals[N] = {Streams...}; - handleConfig.streams = std::array{reinterpret_cast(Streams)...}; - if constexpr (is_adc()) { - static_assert(N == 1, "ADC DMA must have exactly one stream"); - } - else if constexpr (is_fmac()) { - static_assert(N == 3, "FMAC DMA must have exactly three streams"); - } - else { - static_assert(N == 2, "Peripheral DMA must have exactly two streams (RX and TX)"); - } - - // TODO: verificar que los streams no esten siendo usados - - [&](std::index_sequence) { - (([&] { - handleConfig.handles[I].Request = get_Request(); - handleConfig.handles[I].Direction = get_Direction(); - handleConfig.handles[I].PeriphInc = get_PeriphInc(); - handleConfig.handles[I].MemInc = get_MemInc(); - handleConfig.handles[I].PeriphDataAlignment = get_PeriphDataAlignment(); - handleConfig.handles[I].MemDataAlignment = get_MemDataAlignment(); - handleConfig.handles[I].Mode = get_Mode(); - handleConfig.handles[I].Priority = get_Priority(); - handleConfig.handles[I].FIFOMode = get_FIFOMode(); - handleConfig.handles[I].FIFOThreshold = get_FIFOThreshold(); - handleConfig.handles[I].MemBurst = get_MemBurst(); - handleConfig.handles[I].PeriphBurst = get_PeriphBurst(); - - handleConfig[I] = get_irqn(); - - }()), ...); + constexpr std::array streams = { reinterpret_cast(Streams)... }; + + // Verificación de cantidad según periférico + if constexpr (is_adc()) static_assert(N == 1, "ADC DMA must have exactly one stream"); + else if constexpr (is_fmac()) static_assert(N == 3, "FMAC DMA must have exactly three streams"); + else static_assert(N == 2, "Peripheral DMA must have exactly two streams (RX and TX)"); + + constexpr auto make_handles = [](std::index_sequence) { + return std::array{ + DMA_InitTypeDef{ + .Request = get_Request(), + .Direction = get_Direction(), + .PeriphInc = get_PeriphInc(), + .MemInc = get_MemInc(), + .PeriphDataAlignment = get_PeriphDataAlignment(), + .MemDataAlignment = get_MemDataAlignment(), + .Mode = get_Mode(), + .Priority = get_Priority(), + .FIFOMode = get_FIFOMode(), + .FIFOThreshold = get_FIFOThreshold(), + .MemBurst = get_MemBurst(), + .PeriphBurst = get_PeriphBurst(), + }... + }; }(std::make_index_sequence{}); - - return handleConfig; + + constexpr auto make_irq = [](std::index_sequence) { + return std::array{ get_irqn()... }; + }(std::make_index_sequence{}); + + return Config{Instance, make_handles, streams, make_irq}; +} + + +template +constexpr bool DMA::is_one_of() { + return ((Instance == Bases) || ...); } template constexpr bool DMA::is_spi() { - return Instance == SPI1_BASE || Instance == SPI2_BASE || Instance == SPI3_BASE || - Instance == SPI4_BASE || Instance == SPI5_BASE; + return is_one_of(); } template constexpr bool DMA::is_i2c() { - return Instance == I2C1_BASE || Instance == I2C2_BASE || Instance == I2C3_BASE || Instance == I2C5_BASE; + return is_one_of(); } template constexpr bool DMA::is_adc() { - return Instance == ADC1_BASE || Instance == ADC2_BASE || Instance == ADC3_BASE; + return is_one_of(); } template @@ -153,23 +157,24 @@ constexpr bool DMA::is_fmac() { template constexpr IRQn_Type DMA::get_irqn() { - if (stream == DMA1_Stream0_BASE) return DMA1_Stream0_IRQn; - if (stream == DMA1_Stream1_BASE) return DMA1_Stream1_IRQn; - if (stream == DMA1_Stream2_BASE) return DMA1_Stream2_IRQn; - if (stream == DMA1_Stream3_BASE) return DMA1_Stream3_IRQn; - if (stream == DMA1_Stream4_BASE) return DMA1_Stream4_IRQn; - if (stream == DMA1_Stream5_BASE) return DMA1_Stream5_IRQn; - if (stream == DMA1_Stream6_BASE) return DMA1_Stream6_IRQn; - if (stream == DMA1_Stream7_BASE) return DMA1_Stream7_IRQn; - - if (stream == DMA2_Stream0_BASE) return DMA2_Stream0_IRQn; - if (stream == DMA2_Stream1_BASE) return DMA2_Stream1_IRQn; - if (stream == DMA2_Stream2_BASE) return DMA2_Stream2_IRQn; - if (stream == DMA2_Stream3_BASE) return DMA2_Stream3_IRQn; - if (stream == DMA2_Stream4_BASE) return DMA2_Stream4_IRQn; - if (stream == DMA2_Stream5_BASE) return DMA2_Stream5_IRQn; - if (stream == DMA2_Stream6_BASE) return DMA2_Stream6_IRQn; - return DMA2_Stream7_IRQn; + if constexpr (stream == DMA1_Stream0_BASE) return DMA1_Stream0_IRQn; + else if constexpr (stream == DMA1_Stream1_BASE) return DMA1_Stream1_IRQn; + else if constexpr (stream == DMA1_Stream2_BASE) return DMA1_Stream2_IRQn; + else if constexpr (stream == DMA1_Stream3_BASE) return DMA1_Stream3_IRQn; + else if constexpr (stream == DMA1_Stream4_BASE) return DMA1_Stream4_IRQn; + else if constexpr (stream == DMA1_Stream5_BASE) return DMA1_Stream5_IRQn; + else if constexpr (stream == DMA1_Stream6_BASE) return DMA1_Stream6_IRQn; + else if constexpr (stream == DMA1_Stream7_BASE) return DMA1_Stream7_IRQn; + + else if constexpr (stream == DMA2_Stream0_BASE) return DMA2_Stream0_IRQn; + else if constexpr (stream == DMA2_Stream1_BASE) return DMA2_Stream1_IRQn; + else if constexpr (stream == DMA2_Stream2_BASE) return DMA2_Stream2_IRQn; + else if constexpr (stream == DMA2_Stream3_BASE) return DMA2_Stream3_IRQn; + else if constexpr (stream == DMA2_Stream4_BASE) return DMA2_Stream4_IRQn; + else if constexpr (stream == DMA2_Stream5_BASE) return DMA2_Stream5_IRQn; + else if constexpr (stream == DMA2_Stream6_BASE) return DMA2_Stream6_IRQn; + else if constexpr (stream == DMA2_Stream7_BASE) return DMA2_Stream7_IRQn; + else static_assert([]{return false;}(), "Invalid DMA stream base address"); } @@ -238,7 +243,7 @@ constexpr uint32_t DMA::get_MemInc() { template constexpr uint32_t DMA::get_PeriphDataAlignment() { - if constexpr (is_spi()){ + if constexpr (is_i2c()){ return DMA_PDATAALIGN_WORD; } else if constexpr (is_spi()){ @@ -250,7 +255,7 @@ constexpr uint32_t DMA::get_PeriphDataAlignment() { template constexpr uint32_t DMA::get_MemDataAlignment() { - if constexpr (is_spi()){ + if constexpr (is_i2c()){ return DMA_MDATAALIGN_WORD; } else if constexpr (is_spi()){ diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index e69de29bb..57d310a9b 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -0,0 +1,28 @@ +#include "HALAL/Models/DMA/DMA.hpp" + + +void DMA::start() +{ + __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + + for (auto const &inst : inscribed_streams | std::views::take(inscribed_count)) { + std::visit([](auto const &cfg) { + for (size_t i = 0; i < cfg.num_streams; ++i) { + DMA_HandleTypeDef dma_handle{}; + dma_handle.Instance = cfg.streams[i]; + dma_handle.Init = cfg.handles[i]; + + if (HAL_DMA_Init(&dma_handle) != HAL_OK) { + Error_Handler(); + } + + // Enlazar DMA con periférico + __HAL_LINKDMA(cfg.instance, global_handle, dma_handle); + + HAL_NVIC_SetPriority(cfg.irqn[i], 0, 0); + HAL_NVIC_EnableIRQ(cfg.irqn[i]); + } + }, inst); + } +} From 1634bdb03da30e71f044010136990181d6498ae9 Mon Sep 17 00:00:00 2001 From: Jorge Date: Tue, 11 Nov 2025 17:17:17 +0100 Subject: [PATCH 037/109] algunas cosillas para que compile. falta conseguir pasarle las variables de los modulos al start --- Inc/HALAL/Models/DMA/DMA.hpp | 20 ++++----- Src/HALAL/Models/DMA/DMA.cpp | 45 ++++++++++---------- Src/HALAL/Services/ADC/ADC.cpp | 4 +- Src/HALAL/Services/Communication/I2C/I2C.cpp | 2 +- Src/HALAL/Services/Communication/SPI/SPI.cpp | 2 +- Src/HALAL/Services/FMAC/FMAC.cpp | 2 +- 6 files changed, 37 insertions(+), 38 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index fbd3ac399..edf07b7de 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -18,12 +18,12 @@ template struct Config { uint32_t instance; std::array handles{}; - std::array streams{}; + std::array streams{}; std::array irqn{}; constexpr Config(uint32_t inst, std::array h, - std::array s, + std::array s, std::array i) : instance(inst), handles(h), streams(s), irqn(i) {} }; @@ -32,23 +32,23 @@ class DMA { public: template static consteval auto inscribe_stream(); - + static void start(); template - constexpr bool is_one_of(); + static constexpr bool is_one_of(); template - constexpr bool is_spi(); + static constexpr bool is_spi(); template - constexpr bool is_i2c(); + static constexpr bool is_i2c(); template - constexpr bool is_adc(); + static constexpr bool is_adc(); template - constexpr bool is_fmac(); + static constexpr bool is_fmac(); template static constexpr uint32_t get_Request(); @@ -96,7 +96,7 @@ consteval auto DMA::inscribe_stream() { constexpr std::size_t N = sizeof...(Streams); static_assert(N <= MAX_STREAMS, "Too many streams inscribed"); - constexpr std::array streams = { reinterpret_cast(Streams)... }; + constexpr std::array streams = {(Streams)... }; // Verificación de cantidad según periférico if constexpr (is_adc()) static_assert(N == 1, "ADC DMA must have exactly one stream"); @@ -309,4 +309,4 @@ constexpr uint32_t DMA::get_MemBurst() { template constexpr uint32_t DMA::get_PeriphBurst() { return DMA_PBURST_SINGLE; -} +} \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index 57d310a9b..05a23e066 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -1,28 +1,27 @@ -#include "HALAL/Models/DMA/DMA.hpp" +// #include "HALAL/Models/DMA/DMA.hpp" +// void DMA::start() +// { +// __HAL_RCC_DMA1_CLK_ENABLE(); +// __HAL_RCC_DMA2_CLK_ENABLE(); -void DMA::start() -{ - __HAL_RCC_DMA1_CLK_ENABLE(); - __HAL_RCC_DMA2_CLK_ENABLE(); +// for (auto const &inst : instancias) { +// std::visit([](auto const &cfg) { +// for (size_t i = 0; i < cfg.handles.size(); ++i) { +// static DMA_HandleTypeDef dma_handle{}; +// dma_handle.Instance = cfg.streams[i]; +// dma_handle.Init = cfg.handles[i]; - for (auto const &inst : inscribed_streams | std::views::take(inscribed_count)) { - std::visit([](auto const &cfg) { - for (size_t i = 0; i < cfg.num_streams; ++i) { - DMA_HandleTypeDef dma_handle{}; - dma_handle.Instance = cfg.streams[i]; - dma_handle.Init = cfg.handles[i]; +// if (HAL_DMA_Init(&dma_handle) != HAL_OK) { +// Error_Handler(); +// } - if (HAL_DMA_Init(&dma_handle) != HAL_OK) { - Error_Handler(); - } +// // Enlazar DMA con periférico +// __HAL_LINKDMA(cfg.instance, global_handle, dma_handle); - // Enlazar DMA con periférico - __HAL_LINKDMA(cfg.instance, global_handle, dma_handle); - - HAL_NVIC_SetPriority(cfg.irqn[i], 0, 0); - HAL_NVIC_EnableIRQ(cfg.irqn[i]); - } - }, inst); - } -} +// HAL_NVIC_SetPriority(cfg.irqn[i], 0, 0); +// HAL_NVIC_EnableIRQ(cfg.irqn[i]); +// } +// }, inst); +// } +// } diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index 2717f2c7d..e73c195ce 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -42,7 +42,7 @@ uint8_t ADC::inscribe(Pin pin) { InitData& init_data = active_instances[id_counter].peripheral->init_data; - DMA::inscribe_stream(init_data.dma_stream); + constexpr auto dma_adc1_config {DMA::inscribe_stream()}; active_instances[id_counter].rank = init_data.channels.size(); init_data.channels.push_back(active_instances[id_counter].channel); return id_counter++; @@ -68,7 +68,7 @@ void ADC::turn_on(uint8_t id){ uint32_t buffer_length = peripheral->init_data.channels.size(); if (HAL_ADC_Start_DMA(peripheral->handle, (uint32_t*) peripheral->dma_data_buffer, buffer_length) != HAL_OK) { - ErrorHandler("DMA - %d - of ADC - %d - did not start correctly", peripheral->init_data.dma_stream, id); + //ErrorHandler("DMA - %d - of ADC - %d - did not start correctly", peripheral->init_data.dma_stream, id); return; } diff --git a/Src/HALAL/Services/Communication/I2C/I2C.cpp b/Src/HALAL/Services/Communication/I2C/I2C.cpp index 6ba12da50..a41133234 100644 --- a/Src/HALAL/Services/Communication/I2C/I2C.cpp +++ b/Src/HALAL/Services/Communication/I2C/I2C.cpp @@ -23,7 +23,7 @@ uint8_t I2C::inscribe(I2C::Peripheral &i2c, uint8_t address) { Pin::inscribe(i2c_instance->SCL, ALTERNATIVE); Pin::inscribe(i2c_instance->SDA, ALTERNATIVE); - DMA::inscribe_stream_i2c(i2c_instance->hi2c, DMA1_Stream3, DMA1_Stream4); + constexpr auto dma_i2c1_config {DMA::inscribe_stream()}; uint8_t id = I2C::id_counter++; diff --git a/Src/HALAL/Services/Communication/SPI/SPI.cpp b/Src/HALAL/Services/Communication/SPI/SPI.cpp index 5d5eb9058..6c590e3f3 100644 --- a/Src/HALAL/Services/Communication/SPI/SPI.cpp +++ b/Src/HALAL/Services/Communication/SPI/SPI.cpp @@ -56,7 +56,7 @@ uint8_t SPI::inscribe(SPI::Peripheral& spi) { uint8_t id = SPI::id_counter++; if (spi_instance->use_DMA) { - DMA::inscribe_stream_spi(spi_instance->hspi, DMA1_Stream5, DMA1_Stream6); + constexpr auto dma_spi1_config {DMA::inscribe_stream()}; } SPI::registered_spi[id] = spi_instance; SPI::registered_spi_by_handler[spi_instance->hspi] = spi_instance; diff --git a/Src/HALAL/Services/FMAC/FMAC.cpp b/Src/HALAL/Services/FMAC/FMAC.cpp index 4b2107cab..56bfbbda5 100644 --- a/Src/HALAL/Services/FMAC/FMAC.cpp +++ b/Src/HALAL/Services/FMAC/FMAC.cpp @@ -32,7 +32,7 @@ void MultiplierAccelerator::IIR_software_in_software_out_inscribe(uint16_t input } void MultiplierAccelerator::inscribe(){ - DMA::inscribe_stream_fmac(Instance.hfmac, DMA2_Stream0, DMA2_Stream1, DMA2_Stream2); + constexpr auto fmac_dma_config {DMA::inscribe_stream()}; } void MultiplierAccelerator::start(){ From 81fb4683b2b11a66e47265e62b373a1cbf8043bd Mon Sep 17 00:00:00 2001 From: Jorge Date: Wed, 12 Nov 2025 13:23:35 +0100 Subject: [PATCH 038/109] feat: agregar static a las variables constexpr --- Src/HALAL/Services/ADC/ADC.cpp | 2 +- Src/HALAL/Services/Communication/I2C/I2C.cpp | 2 +- Src/HALAL/Services/Communication/SPI/SPI.cpp | 2 +- Src/HALAL/Services/FMAC/FMAC.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index e73c195ce..2ee1b7fbc 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -42,7 +42,7 @@ uint8_t ADC::inscribe(Pin pin) { InitData& init_data = active_instances[id_counter].peripheral->init_data; - constexpr auto dma_adc1_config {DMA::inscribe_stream()}; + static constexpr auto dma_adc1_config {DMA::inscribe_stream()}; active_instances[id_counter].rank = init_data.channels.size(); init_data.channels.push_back(active_instances[id_counter].channel); return id_counter++; diff --git a/Src/HALAL/Services/Communication/I2C/I2C.cpp b/Src/HALAL/Services/Communication/I2C/I2C.cpp index a41133234..25ba233ac 100644 --- a/Src/HALAL/Services/Communication/I2C/I2C.cpp +++ b/Src/HALAL/Services/Communication/I2C/I2C.cpp @@ -23,7 +23,7 @@ uint8_t I2C::inscribe(I2C::Peripheral &i2c, uint8_t address) { Pin::inscribe(i2c_instance->SCL, ALTERNATIVE); Pin::inscribe(i2c_instance->SDA, ALTERNATIVE); - constexpr auto dma_i2c1_config {DMA::inscribe_stream()}; + static constexpr auto dma_i2c1_config {DMA::inscribe_stream()}; uint8_t id = I2C::id_counter++; diff --git a/Src/HALAL/Services/Communication/SPI/SPI.cpp b/Src/HALAL/Services/Communication/SPI/SPI.cpp index 6c590e3f3..f9f9628f6 100644 --- a/Src/HALAL/Services/Communication/SPI/SPI.cpp +++ b/Src/HALAL/Services/Communication/SPI/SPI.cpp @@ -56,7 +56,7 @@ uint8_t SPI::inscribe(SPI::Peripheral& spi) { uint8_t id = SPI::id_counter++; if (spi_instance->use_DMA) { - constexpr auto dma_spi1_config {DMA::inscribe_stream()}; + static constexpr auto dma_spi1_config {DMA::inscribe_stream()}; } SPI::registered_spi[id] = spi_instance; SPI::registered_spi_by_handler[spi_instance->hspi] = spi_instance; diff --git a/Src/HALAL/Services/FMAC/FMAC.cpp b/Src/HALAL/Services/FMAC/FMAC.cpp index 56bfbbda5..5e798f2ba 100644 --- a/Src/HALAL/Services/FMAC/FMAC.cpp +++ b/Src/HALAL/Services/FMAC/FMAC.cpp @@ -32,7 +32,7 @@ void MultiplierAccelerator::IIR_software_in_software_out_inscribe(uint16_t input } void MultiplierAccelerator::inscribe(){ - constexpr auto fmac_dma_config {DMA::inscribe_stream()}; + static constexpr auto fmac_dma_config {DMA::inscribe_stream()}; } void MultiplierAccelerator::start(){ From 5aa3106db0bfdb9bdc607ed118e71e3ec5dfc30a Mon Sep 17 00:00:00 2001 From: Jorge Date: Sat, 22 Nov 2025 19:45:39 +0100 Subject: [PATCH 039/109] me lo quiero pasar al PC solamente, luego hago bien el commit --- Inc/HALAL/Models/DMA/DMA.hpp | 329 +++++++++++++------------------ Src/HALAL/Services/FMAC/FMAC.cpp | 2 +- 2 files changed, 137 insertions(+), 194 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index edf07b7de..904869bd7 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -14,299 +14,242 @@ #define MAX_STREAMS 16 -template -struct Config { - uint32_t instance; - std::array handles{}; - std::array streams{}; - std::array irqn{}; - - constexpr Config(uint32_t inst, - std::array h, - std::array s, - std::array i) - : instance(inst), handles(h), streams(s), irqn(i) {} -}; - class DMA { public: template - static consteval auto inscribe_stream(); + static void inscribe_stream(); static void start(); - template - static constexpr bool is_one_of(); + static bool is_one_of(auto Instance, auto... Bases); - template - static constexpr bool is_spi(); + static bool is_spi(auto Instance); - template - static constexpr bool is_i2c(); + static bool is_i2c(auto Instance); - template - static constexpr bool is_adc(); + static bool is_adc(auto Instance); - template - static constexpr bool is_fmac(); + static bool is_fmac(auto Instance); - template - static constexpr uint32_t get_Request(); + + static uint32_t get_Request(auto Instance, uint8_t i); - template - static constexpr uint32_t get_Direction(); + static uint32_t get_Direction(auto Instance, uint8_t i); - template - static constexpr uint32_t get_PeriphInc(); + static uint32_t get_PeriphInc(auto Instance, uint8_t i); - template - static constexpr uint32_t get_MemInc(); + static uint32_t get_MemInc(auto Instance, uint8_t i); - template - static constexpr uint32_t get_PeriphDataAlignment(); + static uint32_t get_PeriphDataAlignment(auto Instance, uint8_t i); - template - static constexpr uint32_t get_MemDataAlignment(); + static uint32_t get_MemDataAlignment(auto Instance, uint8_t i); - template - static constexpr uint32_t get_Mode(); + static uint32_t get_Mode(auto Instance, uint8_t i); - template - static constexpr uint32_t get_Priority(); + static uint32_t get_Priority(auto Instance, uint8_t i); - template - static constexpr uint32_t get_FIFOMode(); + static uint32_t get_FIFOMode(auto Instance, uint8_t i); - template - static constexpr uint32_t get_FIFOThreshold(); + static uint32_t get_FIFOThreshold(auto Instance, uint8_t i); - template - static constexpr uint32_t get_MemBurst(); + static uint32_t get_MemBurst(auto Instance, uint8_t i); - template - static constexpr uint32_t get_PeriphBurst(); + static uint32_t get_PeriphBurst(auto Instance, uint8_t i); - template - static constexpr IRQn_Type get_irqn(); + static IRQn_Type get_irqn(auto stream); + + private: + static std::array inscribed_streams; + static uint8_t inscribed_index; + }; +inline uint8_t DMA::inscribed_index{0}; template -consteval auto DMA::inscribe_stream() { - constexpr std::size_t N = sizeof...(Streams); - static_assert(N <= MAX_STREAMS, "Too many streams inscribed"); - - constexpr std::array streams = {(Streams)... }; +void DMA::inscribe_stream() { + std::size_t N = sizeof...(Streams); + ErrorHandler(inscribed_index + N <= MAX_STREAMS, "Too many streams inscribed"); + std::array streams = {(DMA_Stream_TypeDef*)Streams... }; // Verificación de cantidad según periférico - if constexpr (is_adc()) static_assert(N == 1, "ADC DMA must have exactly one stream"); - else if constexpr (is_fmac()) static_assert(N == 3, "FMAC DMA must have exactly three streams"); - else static_assert(N == 2, "Peripheral DMA must have exactly two streams (RX and TX)"); - - constexpr auto make_handles = [](std::index_sequence) { - return std::array{ - DMA_InitTypeDef{ - .Request = get_Request(), - .Direction = get_Direction(), - .PeriphInc = get_PeriphInc(), - .MemInc = get_MemInc(), - .PeriphDataAlignment = get_PeriphDataAlignment(), - .MemDataAlignment = get_MemDataAlignment(), - .Mode = get_Mode(), - .Priority = get_Priority(), - .FIFOMode = get_FIFOMode(), - .FIFOThreshold = get_FIFOThreshold(), - .MemBurst = get_MemBurst(), - .PeriphBurst = get_PeriphBurst(), - }... - }; - }(std::make_index_sequence{}); - - constexpr auto make_irq = [](std::index_sequence) { - return std::array{ get_irqn()... }; - }(std::make_index_sequence{}); - - return Config{Instance, make_handles, streams, make_irq}; + if (is_adc(Instance)) ErrorHandler(N == 1, "ADC DMA must have exactly one stream"); + else if (is_fmac(Instance)) ErrorHandler(N == 3, "FMAC DMA must have exactly three streams"); + else ErrorHandler(N == 2, "Peripheral DMA must have exactly two streams (RX and TX)"); + + for (uint8_t i = 0; i < N; i++){ + DMA_HandleTypeDef dma_handle; + dma_handle.Init.Request = get_Request(Instance, i); + dma_handle.Init.Direction = get_Direction(Instance, i); + dma_handle.Init.PeriphInc = get_PeriphInc(Instance, i); + dma_handle.Init.MemInc = get_MemInc(Instance, i); + dma_handle.Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); + dma_handle.Init.MemDataAlignment = get_MemDataAlignment(Instance, i); + dma_handle.Init.Mode = get_Mode(Instance, i); + dma_handle.Init.Priority = get_Priority(Instance, i); + dma_handle.Init.FIFOMode = get_FIFOMode(Instance, i); + dma_handle.Init.FIFOThreshold = get_FIFOThreshold(Instance, i); + dma_handle.Init.MemBurst = get_MemBurst(Instance, i); + dma_handle.Init.PeriphBurst = get_PeriphBurst(Instance, i); + dma_handle.Instance = streams[i]; + inscribed_streams[inscribed_index++] = dma_handle; + } } -template -constexpr bool DMA::is_one_of() { +bool DMA::is_one_of(auto Instance, auto... Bases) { return ((Instance == Bases) || ...); } -template -constexpr bool DMA::is_spi() { - return is_one_of(); + bool DMA::is_spi(auto Instance) { + return is_one_of(Instance, SPI1, SPI2, SPI3, SPI4, SPI5); } -template -constexpr bool DMA::is_i2c() { - return is_one_of(); + bool DMA::is_i2c(auto Instance) { + return is_one_of(Instance, I2C1, I2C2, I2C3, I2C5); } -template -constexpr bool DMA::is_adc() { - return is_one_of(); + bool DMA::is_adc(auto Instance) { + return is_one_of(Instance, ADC1, ADC2, ADC3); } -template -constexpr bool DMA::is_fmac() { - return Instance == FMAC_BASE; + bool DMA::is_fmac(auto Instance) { + return Instance == FMAC; } -template -constexpr IRQn_Type DMA::get_irqn() { - if constexpr (stream == DMA1_Stream0_BASE) return DMA1_Stream0_IRQn; - else if constexpr (stream == DMA1_Stream1_BASE) return DMA1_Stream1_IRQn; - else if constexpr (stream == DMA1_Stream2_BASE) return DMA1_Stream2_IRQn; - else if constexpr (stream == DMA1_Stream3_BASE) return DMA1_Stream3_IRQn; - else if constexpr (stream == DMA1_Stream4_BASE) return DMA1_Stream4_IRQn; - else if constexpr (stream == DMA1_Stream5_BASE) return DMA1_Stream5_IRQn; - else if constexpr (stream == DMA1_Stream6_BASE) return DMA1_Stream6_IRQn; - else if constexpr (stream == DMA1_Stream7_BASE) return DMA1_Stream7_IRQn; - - else if constexpr (stream == DMA2_Stream0_BASE) return DMA2_Stream0_IRQn; - else if constexpr (stream == DMA2_Stream1_BASE) return DMA2_Stream1_IRQn; - else if constexpr (stream == DMA2_Stream2_BASE) return DMA2_Stream2_IRQn; - else if constexpr (stream == DMA2_Stream3_BASE) return DMA2_Stream3_IRQn; - else if constexpr (stream == DMA2_Stream4_BASE) return DMA2_Stream4_IRQn; - else if constexpr (stream == DMA2_Stream5_BASE) return DMA2_Stream5_IRQn; - else if constexpr (stream == DMA2_Stream6_BASE) return DMA2_Stream6_IRQn; - else if constexpr (stream == DMA2_Stream7_BASE) return DMA2_Stream7_IRQn; - else static_assert([]{return false;}(), "Invalid DMA stream base address"); -} - -template -constexpr uint32_t DMA::get_Request() { - if constexpr (Instance == ADC1_BASE) return DMA_REQUEST_ADC1; - if constexpr (Instance == ADC2_BASE) return DMA_REQUEST_ADC2; - if constexpr (Instance == ADC3_BASE) return DMA_REQUEST_ADC3; - - if constexpr (Instance == I2C1_BASE && i == 0) return DMA_REQUEST_I2C1_RX; - if constexpr (Instance == I2C1_BASE && i == 1) return DMA_REQUEST_I2C1_TX; - if constexpr (Instance == I2C2_BASE && i == 0) return DMA_REQUEST_I2C2_RX; - if constexpr (Instance == I2C2_BASE && i == 1) return DMA_REQUEST_I2C2_TX; - if constexpr (Instance == I2C3_BASE && i == 0) return DMA_REQUEST_I2C3_RX; - if constexpr (Instance == I2C3_BASE && i == 1) return DMA_REQUEST_I2C3_TX; - if constexpr (Instance == I2C5_BASE && i == 0) return DMA_REQUEST_I2C5_RX; - if constexpr (Instance == I2C5_BASE && i == 1) return DMA_REQUEST_I2C5_TX; - - if constexpr (Instance == SPI1_BASE && i == 0) return DMA_REQUEST_SPI1_RX; - if constexpr (Instance == SPI1_BASE && i == 1) return DMA_REQUEST_SPI1_TX; - if constexpr (Instance == SPI2_BASE && i == 0) return DMA_REQUEST_SPI2_RX; - if constexpr (Instance == SPI2_BASE && i == 1) return DMA_REQUEST_SPI2_TX; - if constexpr (Instance == SPI3_BASE && i == 0) return DMA_REQUEST_SPI3_RX; - if constexpr (Instance == SPI3_BASE && i == 1) return DMA_REQUEST_SPI3_TX; - if constexpr (Instance == SPI4_BASE && i == 0) return DMA_REQUEST_SPI4_RX; - if constexpr (Instance == SPI4_BASE && i == 1) return DMA_REQUEST_SPI4_TX; - if constexpr (Instance == SPI5_BASE && i == 0) return DMA_REQUEST_SPI5_RX; - if constexpr (Instance == SPI5_BASE && i == 1) return DMA_REQUEST_SPI5_TX; +IRQn_Type DMA::get_irqn(auto stream) { + if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; + else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; + else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; + else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; + else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; + else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; + else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; + else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; + + else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; + else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; + else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; + else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; + else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; + else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; + else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; + else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; + else ErrorHandler(); +} + +uint32_t DMA::get_Request(auto Instance, uint8_t i) { + if (Instance == ADC1) return DMA_REQUEST_ADC1; + if (Instance == ADC2) return DMA_REQUEST_ADC2; + if (Instance == ADC3) return DMA_REQUEST_ADC3; + + if (Instance == I2C1 && i == 0) return DMA_REQUEST_I2C1_RX; + if (Instance == I2C1 && i == 1) return DMA_REQUEST_I2C1_TX; + if (Instance == I2C2 && i == 0) return DMA_REQUEST_I2C2_RX; + if (Instance == I2C2 && i == 1) return DMA_REQUEST_I2C2_TX; + if (Instance == I2C3 && i == 0) return DMA_REQUEST_I2C3_RX; + if (Instance == I2C3 && i == 1) return DMA_REQUEST_I2C3_TX; + if (Instance == I2C5 && i == 0) return DMA_REQUEST_I2C5_RX; + if (Instance == I2C5 && i == 1) return DMA_REQUEST_I2C5_TX; + + if (Instance == SPI1 && i == 0) return DMA_REQUEST_SPI1_RX; + if (Instance == SPI1 && i == 1) return DMA_REQUEST_SPI1_TX; + if (Instance == SPI2 && i == 0) return DMA_REQUEST_SPI2_RX; + if (Instance == SPI2 && i == 1) return DMA_REQUEST_SPI2_TX; + if (Instance == SPI3 && i == 0) return DMA_REQUEST_SPI3_RX; + if (Instance == SPI3 && i == 1) return DMA_REQUEST_SPI3_TX; + if (Instance == SPI4 && i == 0) return DMA_REQUEST_SPI4_RX; + if (Instance == SPI4 && i == 1) return DMA_REQUEST_SPI4_TX; + if (Instance == SPI5 && i == 0) return DMA_REQUEST_SPI5_RX; + if (Instance == SPI5 && i == 1) return DMA_REQUEST_SPI5_TX; - if constexpr (Instance == FMAC_BASE && i == 0) return DMA_REQUEST_MEM2MEM; - if constexpr (Instance == FMAC_BASE && i == 1) return DMA_REQUEST_FMAC_WRITE; - if constexpr (Instance == FMAC_BASE && i == 2) return DMA_REQUEST_FMAC_READ; + if (Instance == FMAC && i == 0) return DMA_REQUEST_MEM2MEM; + if (Instance == FMAC && i == 1) return DMA_REQUEST_FMAC_WRITE; + if (Instance == FMAC && i == 2) return DMA_REQUEST_FMAC_READ; return 0; } -template -constexpr uint32_t DMA::get_Direction() { - if constexpr (is_fmac() && i == 0){ +uint32_t DMA::get_Direction(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ return DMA_MEMORY_TO_MEMORY; } - else if constexpr ((is_i2c() && i == 1) || - (is_spi() && i == 1) || - (is_fmac() && i == 1)){ + else if ((is_i2c(Instance) && i == 1) || + (is_spi(Instance) && i == 1) || + (is_fmac(Instance) && i == 1)){ return DMA_MEMORY_TO_PERIPH; } return DMA_PERIPH_TO_MEMORY; - } -template -constexpr uint32_t DMA::get_PeriphInc() { - if constexpr (is_fmac() && i == 0){ - return DMA_PINC_ENABLE; +uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_PINC_ENABLE;xº } return DMA_PINC_DISABLE; } - -template -constexpr uint32_t DMA::get_MemInc() { - if constexpr (is_fmac() && i == 0){ +uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ return DMA_MINC_DISABLE; } return DMA_MINC_ENABLE; } -template -constexpr uint32_t DMA::get_PeriphDataAlignment() { - if constexpr (is_i2c()){ +uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { + if (is_i2c()){ return DMA_PDATAALIGN_WORD; } - else if constexpr (is_spi()){ + else if (is_spi()){ return DMA_PDATAALIGN_BYTE; } return DMA_PDATAALIGN_HALFWORD; } -template -constexpr uint32_t DMA::get_MemDataAlignment() { - if constexpr (is_i2c()){ +uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { + if (is_i2c()){ return DMA_MDATAALIGN_WORD; } - else if constexpr (is_spi()){ + else if (is_spi()){ return DMA_MDATAALIGN_BYTE; } return DMA_MDATAALIGN_HALFWORD; } - -template -constexpr uint32_t DMA::get_Mode() { - if constexpr (is_spi() || is_fmac()){ +uint32_t DMA::get_Mode(auto Instance, uint8_t i) { + if (is_spi() || is_fmac(Instance)){ return DMA_NORMAL; } return DMA_CIRCULAR; - -} +} -template -constexpr uint32_t DMA::get_Priority() { - if constexpr (is_fmac()){ + uint32_t DMA::get_Priority(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ return DMA_PRIORITY_HIGH; } return DMA_PRIORITY_LOW; } - -template -constexpr uint32_t DMA::get_FIFOMode() { - if constexpr (is_fmac()){ - return DMA_FIFOMODE_ENABLE; +uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ + return DMA_FIFOMODE_ENABLE; } - return DMA_FIFOMODE_DISABLE; } -template -constexpr uint32_t DMA::get_FIFOThreshold() { - if constexpr (is_spi()){ +uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { + if (is_spi()){ return DMA_FIFO_THRESHOLD_FULL; } return DMA_FIFO_THRESHOLD_HALFFULL; } -template -constexpr uint32_t DMA::get_MemBurst() { +uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { return DMA_MBURST_SINGLE; } -template -constexpr uint32_t DMA::get_PeriphBurst() { +uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { return DMA_PBURST_SINGLE; } \ No newline at end of file diff --git a/Src/HALAL/Services/FMAC/FMAC.cpp b/Src/HALAL/Services/FMAC/FMAC.cpp index 5e798f2ba..546de926f 100644 --- a/Src/HALAL/Services/FMAC/FMAC.cpp +++ b/Src/HALAL/Services/FMAC/FMAC.cpp @@ -32,7 +32,7 @@ void MultiplierAccelerator::IIR_software_in_software_out_inscribe(uint16_t input } void MultiplierAccelerator::inscribe(){ - static constexpr auto fmac_dma_config {DMA::inscribe_stream()}; + DMA::inscribe_stream(); } void MultiplierAccelerator::start(){ From d70ab88916cf6627489920ad05f87e71dd298f13 Mon Sep 17 00:00:00 2001 From: Jorge Date: Sun, 23 Nov 2025 09:44:06 +0100 Subject: [PATCH 040/109] feat: agregar funciones que comprueban si el stream y la instancias ya estan siendo utilizadas --- Inc/HALAL/Models/DMA/DMA.hpp | 49 +++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 904869bd7..ae865e6e3 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -17,7 +17,7 @@ class DMA { public: template - static void inscribe_stream(); + static void inscribe_stream(auto handle); static void start(); @@ -62,21 +62,45 @@ class DMA { static std::array inscribed_streams; static uint8_t inscribed_index; + static std::set used_peripherials; + static std::set used_streams; + + static bool is_stream_available(uintptr_t stream); + static bool is_peripherial_available(uintptr_t peripherial); + }; inline uint8_t DMA::inscribed_index{0}; +inline std::set DMA::used_peripherals{}; +inline std::set DMA::used_streams{}; template -void DMA::inscribe_stream() { +void DMA::inscribe_stream(auto handle) { std::size_t N = sizeof...(Streams); ErrorHandler(inscribed_index + N <= MAX_STREAMS, "Too many streams inscribed"); + + uintptr_t periph_addr = reinterpret_cast(Instance); + ErrorHandler(is_peripheral_available(periph_addr), + "Peripheral already in use"); + std::array streams = {(DMA_Stream_TypeDef*)Streams... }; + for (uint8_t i = 0; i < N; i++){ + uintptr_t stream_addr = reinterpret_cast(streams[i]); + ErrorHandler(is_stream_available(stream_addr), + "DMA stream already in use"); + } + // Verificación de cantidad según periférico if (is_adc(Instance)) ErrorHandler(N == 1, "ADC DMA must have exactly one stream"); else if (is_fmac(Instance)) ErrorHandler(N == 3, "FMAC DMA must have exactly three streams"); else ErrorHandler(N == 2, "Peripheral DMA must have exactly two streams (RX and TX)"); + for (uint8_t i = 0; i < N; i++){ + used_streams.insert(reinterpret_cast(streams[i])); + } + used_peripherals.insert(periph_addr); + for (uint8_t i = 0; i < N; i++){ DMA_HandleTypeDef dma_handle; dma_handle.Init.Request = get_Request(Instance, i); @@ -96,6 +120,13 @@ void DMA::inscribe_stream() { } } +bool DMA::is_stream_available(uintptr_t stream) { + return used_streams.find(stream) == used_streams.end(); +} + +bool DMA::is_peripheral_available(uintptr_t peripheral) { + return used_peripherals.find(peripheral) == used_peripherals.end(); +} bool DMA::is_one_of(auto Instance, auto... Bases) { return ((Instance == Bases) || ...); @@ -185,7 +216,7 @@ uint32_t DMA::get_Direction(auto Instance, uint8_t i) { uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { if (is_fmac(Instance) && i == 0){ - return DMA_PINC_ENABLE;xº + return DMA_PINC_ENABLE; } return DMA_PINC_DISABLE; } @@ -197,10 +228,10 @@ uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { } uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { - if (is_i2c()){ + if (is_i2c(Instance)){ return DMA_PDATAALIGN_WORD; } - else if (is_spi()){ + else if (is_spi(Instance)){ return DMA_PDATAALIGN_BYTE; } @@ -208,17 +239,17 @@ uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { } uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { - if (is_i2c()){ + if (is_i2c(Instance)){ return DMA_MDATAALIGN_WORD; } - else if (is_spi()){ + else if (is_spi(Instance)){ return DMA_MDATAALIGN_BYTE; } return DMA_MDATAALIGN_HALFWORD; } uint32_t DMA::get_Mode(auto Instance, uint8_t i) { - if (is_spi() || is_fmac(Instance)){ + if (is_spi(Instance) || is_fmac(Instance)){ return DMA_NORMAL; } @@ -240,7 +271,7 @@ uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { } uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { - if (is_spi()){ + if (is_spi(Instance)){ return DMA_FIFO_THRESHOLD_FULL; } return DMA_FIFO_THRESHOLD_HALFFULL; From 6d8552fe286618544a0edacd0327cef1b8152376 Mon Sep 17 00:00:00 2001 From: Jorge Date: Mon, 24 Nov 2025 20:44:09 +0100 Subject: [PATCH 041/109] fuck constexpr, todo en runtime. feat: inscribe funciona, solo quedaria hacer el start --- Inc/HALAL/Models/DMA/DMA.hpp | 181 ++++++++++++++++++++++++----------- 1 file changed, 126 insertions(+), 55 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index ae865e6e3..ce21a18d1 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -13,24 +13,52 @@ #include #define MAX_STREAMS 16 - + class DMA { public: - template - static void inscribe_stream(auto handle); + static constexpr bool is_one_of(auto Instance, auto... Bases); - static void start(); + static constexpr bool is_spi(auto Instance); + + static constexpr bool is_i2c(auto Instance); - static bool is_one_of(auto Instance, auto... Bases); + static constexpr bool is_adc(auto Instance); - static bool is_spi(auto Instance); - - static bool is_i2c(auto Instance); + static constexpr bool is_fmac(auto Instance); - static bool is_adc(auto Instance); + template + requires ( + (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || + (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || + (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) + ) + static void inscribe_stream(auto handle); - static bool is_fmac(auto Instance); - + static void start(); + + private: + using PeriphVariant = std::variant< + SPI_HandleTypeDef*, + I2C_HandleTypeDef*, + ADC_HandleTypeDef*, + FMAC_HandleTypeDef* + >; + + template + using DmaLinkEntry = std::tuple< + PeriphHandle*, // (__HANDLE__) + DMA_HandleTypeDef*, // (__DMA_HANDLE__) + DMA_HandleTypeDef* PeriphHandle::*, // (__PPP_DMA_FIELD__) + IRQn_Type + >; + + template + static DmaLinkEntry make_dma_entry( + PeriphHandle* periph, + DMA_HandleTypeDef* dma, + DMA_HandleTypeDef* PeriphHandle::* member, + IRQn_Type irqn + ); static uint32_t get_Request(auto Instance, uint8_t i); @@ -57,94 +85,135 @@ class DMA { static uint32_t get_PeriphBurst(auto Instance, uint8_t i); static IRQn_Type get_irqn(auto stream); - - private: - static std::array inscribed_streams; - static uint8_t inscribed_index; - - static std::set used_peripherials; - static std::set used_streams; static bool is_stream_available(uintptr_t stream); + static bool is_peripherial_available(uintptr_t peripherial); + + static std::array, MAX_STREAMS> inscribed_streams; + static uint8_t inscribed_index; + static std::set used_peripherials; + static std::set used_streams; }; inline uint8_t DMA::inscribed_index{0}; -inline std::set DMA::used_peripherals{}; +inline std::set DMA::used_peripherials{}; inline std::set DMA::used_streams{}; +inline std::array, MAX_STREAMS> DMA::inscribed_streams{}; template +requires ( + (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || + (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || + (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) +) void DMA::inscribe_stream(auto handle) { - std::size_t N = sizeof...(Streams); - ErrorHandler(inscribed_index + N <= MAX_STREAMS, "Too many streams inscribed"); - + const std::size_t N = sizeof...(Streams); + if (inscribed_index + N > MAX_STREAMS){ + ErrorHandler("Too many streams inscribed"); + } + uintptr_t periph_addr = reinterpret_cast(Instance); - ErrorHandler(is_peripheral_available(periph_addr), - "Peripheral already in use"); - + if (!is_peripherial_available(periph_addr)){ + ErrorHandler("Peripheral already in use"); + } + std::array streams = {(DMA_Stream_TypeDef*)Streams... }; for (uint8_t i = 0; i < N; i++){ uintptr_t stream_addr = reinterpret_cast(streams[i]); - ErrorHandler(is_stream_available(stream_addr), - "DMA stream already in use"); + if (!is_stream_available(stream_addr)){ + ErrorHandler("DMA stream already in use"); + } } - // Verificación de cantidad según periférico - if (is_adc(Instance)) ErrorHandler(N == 1, "ADC DMA must have exactly one stream"); - else if (is_fmac(Instance)) ErrorHandler(N == 3, "FMAC DMA must have exactly three streams"); - else ErrorHandler(N == 2, "Peripheral DMA must have exactly two streams (RX and TX)"); - for (uint8_t i = 0; i < N; i++){ used_streams.insert(reinterpret_cast(streams[i])); } - used_peripherals.insert(periph_addr); + used_peripherials.insert(periph_addr); for (uint8_t i = 0; i < N; i++){ - DMA_HandleTypeDef dma_handle; - dma_handle.Init.Request = get_Request(Instance, i); - dma_handle.Init.Direction = get_Direction(Instance, i); - dma_handle.Init.PeriphInc = get_PeriphInc(Instance, i); - dma_handle.Init.MemInc = get_MemInc(Instance, i); - dma_handle.Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); - dma_handle.Init.MemDataAlignment = get_MemDataAlignment(Instance, i); - dma_handle.Init.Mode = get_Mode(Instance, i); - dma_handle.Init.Priority = get_Priority(Instance, i); - dma_handle.Init.FIFOMode = get_FIFOMode(Instance, i); - dma_handle.Init.FIFOThreshold = get_FIFOThreshold(Instance, i); - dma_handle.Init.MemBurst = get_MemBurst(Instance, i); - dma_handle.Init.PeriphBurst = get_PeriphBurst(Instance, i); - dma_handle.Instance = streams[i]; - inscribed_streams[inscribed_index++] = dma_handle; + DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; + dma->Instance = streams[i]; + dma->Init.Request = get_Request(Instance, i); + dma->Init.Direction = get_Direction(Instance, i); + dma->Init.PeriphInc = get_PeriphInc(Instance, i); + dma->Init.MemInc = get_MemInc(Instance, i); + dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); + dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); + dma->Init.Mode = get_Mode(Instance, i); + dma->Init.Priority = get_Priority(Instance, i); + dma->Init.FIFOMode = get_FIFOMode(Instance, i); + dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); + dma->Init.MemBurst = get_MemBurst(Instance, i); + dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); + IRQn_Type irq = get_irqn(streams[i]); + + if constexpr (is_spi(Instance)) { + auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + } + else if constexpr (is_i2c(Instance)) { + auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + } + else if constexpr (is_adc(Instance)) { + auto member = &ADC_HandleTypeDef::DMA_Handle; + inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + } + else if constexpr (is_fmac(Instance)) { + DMA_HandleTypeDef* FMAC_HandleTypeDef::* member; + if (i == 0) member = &FMAC_HandleTypeDef::hdmaPreload; + else if (i == 1) member = &FMAC_HandleTypeDef::hdmaIn; + else member = &FMAC_HandleTypeDef::hdmaOut; + inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + } + + inscribed_index++; } } +template +DMA::DmaLinkEntry DMA::make_dma_entry( + PeriphHandle* periph, + DMA_HandleTypeDef* dma, + DMA_HandleTypeDef* PeriphHandle::* member, + IRQn_Type irqn +){ + return std::tuple{ + periph, + dma, + member, + irqn + }; +} + bool DMA::is_stream_available(uintptr_t stream) { return used_streams.find(stream) == used_streams.end(); } -bool DMA::is_peripheral_available(uintptr_t peripheral) { - return used_peripherals.find(peripheral) == used_peripherals.end(); +bool DMA::is_peripherial_available(uintptr_t peripheral) { + return used_peripherials.find(peripheral) == used_peripherials.end(); } -bool DMA::is_one_of(auto Instance, auto... Bases) { +constexpr bool DMA::is_one_of(auto Instance, auto... Bases) { return ((Instance == Bases) || ...); } - bool DMA::is_spi(auto Instance) { +constexpr bool DMA::is_spi(auto Instance) { return is_one_of(Instance, SPI1, SPI2, SPI3, SPI4, SPI5); } - bool DMA::is_i2c(auto Instance) { +constexpr bool DMA::is_i2c(auto Instance) { return is_one_of(Instance, I2C1, I2C2, I2C3, I2C5); } - bool DMA::is_adc(auto Instance) { +constexpr bool DMA::is_adc(auto Instance) { return is_one_of(Instance, ADC1, ADC2, ADC3); } - bool DMA::is_fmac(auto Instance) { +constexpr bool DMA::is_fmac(auto Instance) { return Instance == FMAC; } @@ -201,6 +270,8 @@ uint32_t DMA::get_Request(auto Instance, uint8_t i) { return 0; } + + uint32_t DMA::get_Direction(auto Instance, uint8_t i) { if (is_fmac(Instance) && i == 0){ return DMA_MEMORY_TO_MEMORY; From dc971115745d36cacae3d1171d16fb1dec7792d7 Mon Sep 17 00:00:00 2001 From: Jorge Date: Tue, 25 Nov 2025 01:06:32 +0100 Subject: [PATCH 042/109] repartir entre archivos las funciones y hacer el start --- Inc/HALAL/Models/DMA/DMA.hpp | 277 ++++++++--------------------------- Src/HALAL/Models/DMA/DMA.cpp | 198 +++++++++++++++++++++---- 2 files changed, 236 insertions(+), 239 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index ce21a18d1..bc2b011f2 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -15,45 +15,21 @@ #define MAX_STREAMS 16 class DMA { - public: - static constexpr bool is_one_of(auto Instance, auto... Bases); - - static constexpr bool is_spi(auto Instance); - - static constexpr bool is_i2c(auto Instance); - - static constexpr bool is_adc(auto Instance); - - static constexpr bool is_fmac(auto Instance); - - template - requires ( - (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || - (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || - (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) - ) - static void inscribe_stream(auto handle); - - static void start(); - - private: - using PeriphVariant = std::variant< + using PeriphVariant = std::variant< SPI_HandleTypeDef*, I2C_HandleTypeDef*, ADC_HandleTypeDef*, FMAC_HandleTypeDef* >; + struct DmaLinkEntry{ + PeriphVariant periph; // (__HANDLE__) + DMA_HandleTypeDef* dma; // (__DMA_HANDLE__) + std::function linker; // (__PPP_DMA_FIELD__) + IRQn_Type irq; // (__IRQn_TYPE__) + }; template - using DmaLinkEntry = std::tuple< - PeriphHandle*, // (__HANDLE__) - DMA_HandleTypeDef*, // (__DMA_HANDLE__) - DMA_HandleTypeDef* PeriphHandle::*, // (__PPP_DMA_FIELD__) - IRQn_Type - >; - - template - static DmaLinkEntry make_dma_entry( + static DmaLinkEntry make_dma_entry( PeriphHandle* periph, DMA_HandleTypeDef* dma, DMA_HandleTypeDef* PeriphHandle::* member, @@ -90,25 +66,61 @@ class DMA { static bool is_peripherial_available(uintptr_t peripherial); - static std::array, MAX_STREAMS> inscribed_streams; + static std::array inscribed_streams; static uint8_t inscribed_index; static std::set used_peripherials; static std::set used_streams; + + public: + static constexpr bool is_one_of(auto Instance, auto... Bases); + + static constexpr bool is_spi(auto Instance); + + static constexpr bool is_i2c(auto Instance); + + static constexpr bool is_adc(auto Instance); + + static constexpr bool is_fmac(auto Instance); + + template + requires ( + (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || + (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || + (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) + ) + static void inscribe_stream(PeriphVariant handle); + + static void start(); }; -inline uint8_t DMA::inscribed_index{0}; -inline std::set DMA::used_peripherials{}; -inline std::set DMA::used_streams{}; -inline std::array, MAX_STREAMS> DMA::inscribed_streams{}; +constexpr bool DMA::is_one_of(auto Instance, auto... Bases) { + return ((Instance == Bases) || ...); +} + +constexpr bool DMA::is_spi(auto Instance) { + return is_one_of(Instance, SPI1, SPI2, SPI3, SPI4, SPI5); +} + +constexpr bool DMA::is_i2c(auto Instance) { + return is_one_of(Instance, I2C1, I2C2, I2C3, I2C5); +} + +constexpr bool DMA::is_adc(auto Instance) { + return is_one_of(Instance, ADC1, ADC2, ADC3); +} + +constexpr bool DMA::is_fmac(auto Instance) { + return Instance == FMAC; +} -template +template requires ( (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) ) -void DMA::inscribe_stream(auto handle) { +void DMA::inscribe_stream(PeriphVariant handle) { const std::size_t N = sizeof...(Streams); if (inscribed_index + N > MAX_STREAMS){ ErrorHandler("Too many streams inscribed"); @@ -151,23 +163,27 @@ void DMA::inscribe_stream(auto handle) { IRQn_Type irq = get_irqn(streams[i]); if constexpr (is_spi(Instance)) { + auto* spi_handle = std::get(handle); auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); } else if constexpr (is_i2c(Instance)) { + auto* i2c_handle = std::get(handle); auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); } else if constexpr (is_adc(Instance)) { + auto* adc_handle = std::get(handle); auto member = &ADC_HandleTypeDef::DMA_Handle; - inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); } else if constexpr (is_fmac(Instance)) { + auto* fmac_handle = std::get(handle); DMA_HandleTypeDef* FMAC_HandleTypeDef::* member; if (i == 0) member = &FMAC_HandleTypeDef::hdmaPreload; else if (i == 1) member = &FMAC_HandleTypeDef::hdmaIn; else member = &FMAC_HandleTypeDef::hdmaOut; - inscribed_streams[inscribed_index] = make_dma_entry(handle, dma, member, irq); + inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); } inscribed_index++; @@ -175,183 +191,20 @@ void DMA::inscribe_stream(auto handle) { } template -DMA::DmaLinkEntry DMA::make_dma_entry( +DMA::DmaLinkEntry DMA::make_dma_entry( PeriphHandle* periph, DMA_HandleTypeDef* dma, DMA_HandleTypeDef* PeriphHandle::* member, IRQn_Type irqn ){ - return std::tuple{ + return DmaLinkEntry{ periph, dma, - member, + [periph, member, dma](DMA_HandleTypeDef* d) { + periph->*member = d; + d->Parent = periph; + }, irqn }; } -bool DMA::is_stream_available(uintptr_t stream) { - return used_streams.find(stream) == used_streams.end(); -} - -bool DMA::is_peripherial_available(uintptr_t peripheral) { - return used_peripherials.find(peripheral) == used_peripherials.end(); -} - -constexpr bool DMA::is_one_of(auto Instance, auto... Bases) { - return ((Instance == Bases) || ...); -} - -constexpr bool DMA::is_spi(auto Instance) { - return is_one_of(Instance, SPI1, SPI2, SPI3, SPI4, SPI5); -} - -constexpr bool DMA::is_i2c(auto Instance) { - return is_one_of(Instance, I2C1, I2C2, I2C3, I2C5); -} - -constexpr bool DMA::is_adc(auto Instance) { - return is_one_of(Instance, ADC1, ADC2, ADC3); -} - -constexpr bool DMA::is_fmac(auto Instance) { - return Instance == FMAC; -} - - -IRQn_Type DMA::get_irqn(auto stream) { - if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; - else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; - else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; - else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; - else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; - else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; - else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; - else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; - - else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; - else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; - else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; - else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; - else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; - else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; - else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; - else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; - else ErrorHandler(); -} - -uint32_t DMA::get_Request(auto Instance, uint8_t i) { - if (Instance == ADC1) return DMA_REQUEST_ADC1; - if (Instance == ADC2) return DMA_REQUEST_ADC2; - if (Instance == ADC3) return DMA_REQUEST_ADC3; - - if (Instance == I2C1 && i == 0) return DMA_REQUEST_I2C1_RX; - if (Instance == I2C1 && i == 1) return DMA_REQUEST_I2C1_TX; - if (Instance == I2C2 && i == 0) return DMA_REQUEST_I2C2_RX; - if (Instance == I2C2 && i == 1) return DMA_REQUEST_I2C2_TX; - if (Instance == I2C3 && i == 0) return DMA_REQUEST_I2C3_RX; - if (Instance == I2C3 && i == 1) return DMA_REQUEST_I2C3_TX; - if (Instance == I2C5 && i == 0) return DMA_REQUEST_I2C5_RX; - if (Instance == I2C5 && i == 1) return DMA_REQUEST_I2C5_TX; - - if (Instance == SPI1 && i == 0) return DMA_REQUEST_SPI1_RX; - if (Instance == SPI1 && i == 1) return DMA_REQUEST_SPI1_TX; - if (Instance == SPI2 && i == 0) return DMA_REQUEST_SPI2_RX; - if (Instance == SPI2 && i == 1) return DMA_REQUEST_SPI2_TX; - if (Instance == SPI3 && i == 0) return DMA_REQUEST_SPI3_RX; - if (Instance == SPI3 && i == 1) return DMA_REQUEST_SPI3_TX; - if (Instance == SPI4 && i == 0) return DMA_REQUEST_SPI4_RX; - if (Instance == SPI4 && i == 1) return DMA_REQUEST_SPI4_TX; - if (Instance == SPI5 && i == 0) return DMA_REQUEST_SPI5_RX; - if (Instance == SPI5 && i == 1) return DMA_REQUEST_SPI5_TX; - - if (Instance == FMAC && i == 0) return DMA_REQUEST_MEM2MEM; - if (Instance == FMAC && i == 1) return DMA_REQUEST_FMAC_WRITE; - if (Instance == FMAC && i == 2) return DMA_REQUEST_FMAC_READ; - return 0; -} - - - -uint32_t DMA::get_Direction(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_MEMORY_TO_MEMORY; - } - else if ((is_i2c(Instance) && i == 1) || - (is_spi(Instance) && i == 1) || - (is_fmac(Instance) && i == 1)){ - return DMA_MEMORY_TO_PERIPH; - } - - return DMA_PERIPH_TO_MEMORY; -} - -uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_PINC_ENABLE; - } - return DMA_PINC_DISABLE; -} -uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_MINC_DISABLE; - } - return DMA_MINC_ENABLE; -} - -uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { - if (is_i2c(Instance)){ - return DMA_PDATAALIGN_WORD; - } - else if (is_spi(Instance)){ - return DMA_PDATAALIGN_BYTE; - } - - return DMA_PDATAALIGN_HALFWORD; -} - -uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { - if (is_i2c(Instance)){ - return DMA_MDATAALIGN_WORD; - } - else if (is_spi(Instance)){ - return DMA_MDATAALIGN_BYTE; - } - - return DMA_MDATAALIGN_HALFWORD; -} -uint32_t DMA::get_Mode(auto Instance, uint8_t i) { - if (is_spi(Instance) || is_fmac(Instance)){ - return DMA_NORMAL; - } - - return DMA_CIRCULAR; -} - - uint32_t DMA::get_Priority(auto Instance, uint8_t i) { - if (is_fmac(Instance)){ - return DMA_PRIORITY_HIGH; - } - - return DMA_PRIORITY_LOW; -} -uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { - if (is_fmac(Instance)){ - return DMA_FIFOMODE_ENABLE; - } - return DMA_FIFOMODE_DISABLE; -} - -uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { - if (is_spi(Instance)){ - return DMA_FIFO_THRESHOLD_FULL; - } - return DMA_FIFO_THRESHOLD_HALFFULL; -} - -uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { - return DMA_MBURST_SINGLE; -} - -uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { - return DMA_PBURST_SINGLE; -} \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index 05a23e066..b2266d0c4 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -1,27 +1,171 @@ -// #include "HALAL/Models/DMA/DMA.hpp" - -// void DMA::start() -// { -// __HAL_RCC_DMA1_CLK_ENABLE(); -// __HAL_RCC_DMA2_CLK_ENABLE(); - -// for (auto const &inst : instancias) { -// std::visit([](auto const &cfg) { -// for (size_t i = 0; i < cfg.handles.size(); ++i) { -// static DMA_HandleTypeDef dma_handle{}; -// dma_handle.Instance = cfg.streams[i]; -// dma_handle.Init = cfg.handles[i]; - -// if (HAL_DMA_Init(&dma_handle) != HAL_OK) { -// Error_Handler(); -// } - -// // Enlazar DMA con periférico -// __HAL_LINKDMA(cfg.instance, global_handle, dma_handle); - -// HAL_NVIC_SetPriority(cfg.irqn[i], 0, 0); -// HAL_NVIC_EnableIRQ(cfg.irqn[i]); -// } -// }, inst); -// } -// } +#include "HALAL/Models/DMA/DMA.hpp" + +inline uint8_t DMA::inscribed_index{0}; +inline std::set DMA::used_peripherials{}; +inline std::set DMA::used_streams{}; +inline std::array DMA::inscribed_streams{}; + +void DMA::start() { + for (uint8_t i = 0; i < inscribed_index; i++) { + auto& [periph, dma, linker, irq] = inscribed_streams[i]; + + // Inicializar DMA + if (HAL_DMA_Init(dma) != HAL_OK) { + ErrorHandler("DMA Init failed"); + } + + // Vincular DMA al periférico + linker(dma); + + // Configurar interrupción + HAL_NVIC_SetPriority(irq, 5, 0); + HAL_NVIC_EnableIRQ(irq); + } +} + +bool DMA::is_stream_available(uintptr_t stream) { + return used_streams.find(stream) == used_streams.end(); +} + +bool DMA::is_peripherial_available(uintptr_t peripheral) { + return used_peripherials.find(peripheral) == used_peripherials.end(); +} + + +IRQn_Type DMA::get_irqn(auto stream) { + if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; + else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; + else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; + else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; + else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; + else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; + else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; + else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; + + else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; + else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; + else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; + else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; + else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; + else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; + else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; + else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; + else ErrorHandler(); +} + +uint32_t DMA::get_Request(auto Instance, uint8_t i) { + if (Instance == ADC1) return DMA_REQUEST_ADC1; + if (Instance == ADC2) return DMA_REQUEST_ADC2; + if (Instance == ADC3) return DMA_REQUEST_ADC3; + + if (Instance == I2C1 && i == 0) return DMA_REQUEST_I2C1_RX; + if (Instance == I2C1 && i == 1) return DMA_REQUEST_I2C1_TX; + if (Instance == I2C2 && i == 0) return DMA_REQUEST_I2C2_RX; + if (Instance == I2C2 && i == 1) return DMA_REQUEST_I2C2_TX; + if (Instance == I2C3 && i == 0) return DMA_REQUEST_I2C3_RX; + if (Instance == I2C3 && i == 1) return DMA_REQUEST_I2C3_TX; + if (Instance == I2C5 && i == 0) return DMA_REQUEST_I2C5_RX; + if (Instance == I2C5 && i == 1) return DMA_REQUEST_I2C5_TX; + + if (Instance == SPI1 && i == 0) return DMA_REQUEST_SPI1_RX; + if (Instance == SPI1 && i == 1) return DMA_REQUEST_SPI1_TX; + if (Instance == SPI2 && i == 0) return DMA_REQUEST_SPI2_RX; + if (Instance == SPI2 && i == 1) return DMA_REQUEST_SPI2_TX; + if (Instance == SPI3 && i == 0) return DMA_REQUEST_SPI3_RX; + if (Instance == SPI3 && i == 1) return DMA_REQUEST_SPI3_TX; + if (Instance == SPI4 && i == 0) return DMA_REQUEST_SPI4_RX; + if (Instance == SPI4 && i == 1) return DMA_REQUEST_SPI4_TX; + if (Instance == SPI5 && i == 0) return DMA_REQUEST_SPI5_RX; + if (Instance == SPI5 && i == 1) return DMA_REQUEST_SPI5_TX; + + if (Instance == FMAC && i == 0) return DMA_REQUEST_MEM2MEM; + if (Instance == FMAC && i == 1) return DMA_REQUEST_FMAC_WRITE; + if (Instance == FMAC && i == 2) return DMA_REQUEST_FMAC_READ; + return 0; +} + + + +uint32_t DMA::get_Direction(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_MEMORY_TO_MEMORY; + } + else if ((is_i2c(Instance) && i == 1) || + (is_spi(Instance) && i == 1) || + (is_fmac(Instance) && i == 1)){ + return DMA_MEMORY_TO_PERIPH; + } + + return DMA_PERIPH_TO_MEMORY; +} + +uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_PINC_ENABLE; + } + return DMA_PINC_DISABLE; +} +uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_MINC_DISABLE; + } + return DMA_MINC_ENABLE; +} + +uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { + if (is_i2c(Instance)){ + return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes + } + else if (is_spi(Instance)){ + return DMA_PDATAALIGN_BYTE; + } + + return DMA_PDATAALIGN_HALFWORD; +} + +uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { + if (is_i2c(Instance)){ + return DMA_MDATAALIGN_WORD; + } + else if (is_spi(Instance)){ + return DMA_MDATAALIGN_BYTE; + } + + return DMA_MDATAALIGN_HALFWORD; +} +uint32_t DMA::get_Mode(auto Instance, uint8_t i) { + if (is_spi(Instance) || is_fmac(Instance)){ + return DMA_NORMAL; + } + + return DMA_CIRCULAR; +} + + uint32_t DMA::get_Priority(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ + return DMA_PRIORITY_HIGH; + } + + return DMA_PRIORITY_LOW; +} +uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ + return DMA_FIFOMODE_ENABLE; + } + return DMA_FIFOMODE_DISABLE; +} + +uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { + if (is_spi(Instance)){ + return DMA_FIFO_THRESHOLD_FULL; + } + return DMA_FIFO_THRESHOLD_HALFFULL; +} + +uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { + return DMA_MBURST_SINGLE; +} + +uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { + return DMA_PBURST_SINGLE; +} \ No newline at end of file From d70d07f34606e29fa291be1b3d075f9148d3558b Mon Sep 17 00:00:00 2001 From: Jorge Date: Tue, 25 Nov 2025 16:36:50 +0100 Subject: [PATCH 043/109] feat: start completado, mejor estructura, todos los perifericos configurados --- Inc/HALAL/Models/DMA/DMA.hpp | 241 +++++++++++------- Src/HALAL/Models/DMA/DMA.cpp | 250 +++++++------------ Src/HALAL/Services/ADC/ADC.cpp | 3 +- Src/HALAL/Services/Communication/I2C/I2C.cpp | 2 +- Src/HALAL/Services/Communication/SPI/SPI.cpp | 2 +- Src/HALAL/Services/FMAC/FMAC.cpp | 2 +- 6 files changed, 252 insertions(+), 248 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index bc2b011f2..c75f05c69 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -11,6 +11,9 @@ #include "HALAL/Models/MPUManager/MPUManager.hpp" #include #include +#include +#include +#include #define MAX_STREAMS 16 @@ -64,12 +67,12 @@ class DMA { static bool is_stream_available(uintptr_t stream); - static bool is_peripherial_available(uintptr_t peripherial); + static bool is_peripherial_available(unsigned long peripherial); static std::array inscribed_streams; static uint8_t inscribed_index; - static std::set used_peripherials; + static std::set used_peripherials; static std::set used_streams; public: @@ -94,117 +97,177 @@ class DMA { static void start(); }; +inline uint8_t DMA::inscribed_index{0}; +inline std::set DMA::used_peripherials{}; +inline std::set DMA::used_streams{}; +inline std::array DMA::inscribed_streams{}; + constexpr bool DMA::is_one_of(auto Instance, auto... Bases) { return ((Instance == Bases) || ...); } constexpr bool DMA::is_spi(auto Instance) { - return is_one_of(Instance, SPI1, SPI2, SPI3, SPI4, SPI5); + return is_one_of(Instance, SPI1_BASE, SPI2_BASE, SPI3_BASE, SPI4_BASE, SPI5_BASE); } constexpr bool DMA::is_i2c(auto Instance) { - return is_one_of(Instance, I2C1, I2C2, I2C3, I2C5); + return is_one_of(Instance, I2C1_BASE, I2C2_BASE, I2C3_BASE, I2C5_BASE); } constexpr bool DMA::is_adc(auto Instance) { - return is_one_of(Instance, ADC1, ADC2, ADC3); + return is_one_of(Instance, ADC1_BASE, ADC2_BASE, ADC3_BASE); } constexpr bool DMA::is_fmac(auto Instance) { - return Instance == FMAC; + return Instance == FMAC_BASE; } -template -requires ( - (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || - (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || - (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) -) -void DMA::inscribe_stream(PeriphVariant handle) { - const std::size_t N = sizeof...(Streams); - if (inscribed_index + N > MAX_STREAMS){ - ErrorHandler("Too many streams inscribed"); - } - - uintptr_t periph_addr = reinterpret_cast(Instance); - if (!is_peripherial_available(periph_addr)){ - ErrorHandler("Peripheral already in use"); - } +bool DMA::is_stream_available(uintptr_t stream) { + return used_streams.find(stream) == used_streams.end(); +} + +bool DMA::is_peripherial_available(unsigned long peripheral) { + return used_peripherials.find(peripheral) == used_peripherials.end(); +} + + +IRQn_Type DMA::get_irqn(auto stream) { + if (stream == DMA1_Stream0_BASE) return DMA1_Stream0_IRQn; + else if (stream == DMA1_Stream1_BASE) return DMA1_Stream1_IRQn; + else if (stream == DMA1_Stream2_BASE) return DMA1_Stream2_IRQn; + else if (stream == DMA1_Stream3_BASE) return DMA1_Stream3_IRQn; + else if (stream == DMA1_Stream4_BASE) return DMA1_Stream4_IRQn; + else if (stream == DMA1_Stream5_BASE) return DMA1_Stream5_IRQn; + else if (stream == DMA1_Stream6_BASE) return DMA1_Stream6_IRQn; + else if (stream == DMA1_Stream7_BASE) return DMA1_Stream7_IRQn; + + else if (stream == DMA2_Stream0_BASE) return DMA2_Stream0_IRQn; + else if (stream == DMA2_Stream1_BASE) return DMA2_Stream1_IRQn; + else if (stream == DMA2_Stream2_BASE) return DMA2_Stream2_IRQn; + else if (stream == DMA2_Stream3_BASE) return DMA2_Stream3_IRQn; + else if (stream == DMA2_Stream4_BASE) return DMA2_Stream4_IRQn; + else if (stream == DMA2_Stream5_BASE) return DMA2_Stream5_IRQn; + else if (stream == DMA2_Stream6_BASE) return DMA2_Stream6_IRQn; + else if (stream == DMA2_Stream7_BASE) return DMA2_Stream7_IRQn; + else ErrorHandler("Unknown DMA stream"); + return DMA1_Stream0_IRQn; // Nunca se alcanza +} + +uint32_t DMA::get_Request(auto Instance, uint8_t i) { + if (Instance == ADC1_BASE) return DMA_REQUEST_ADC1; + if (Instance == ADC2_BASE) return DMA_REQUEST_ADC2; + if (Instance == ADC3_BASE) return DMA_REQUEST_ADC3; + + if (Instance == I2C1_BASE && i == 0) return DMA_REQUEST_I2C1_RX; + if (Instance == I2C1_BASE && i == 1) return DMA_REQUEST_I2C1_TX; + if (Instance == I2C2_BASE && i == 0) return DMA_REQUEST_I2C2_RX; + if (Instance == I2C2_BASE && i == 1) return DMA_REQUEST_I2C2_TX; + if (Instance == I2C3_BASE && i == 0) return DMA_REQUEST_I2C3_RX; + if (Instance == I2C3_BASE && i == 1) return DMA_REQUEST_I2C3_TX; + if (Instance == I2C5_BASE && i == 0) return DMA_REQUEST_I2C5_RX; + if (Instance == I2C5_BASE && i == 1) return DMA_REQUEST_I2C5_TX; + + if (Instance == SPI1_BASE && i == 0) return DMA_REQUEST_SPI1_RX; + if (Instance == SPI1_BASE && i == 1) return DMA_REQUEST_SPI1_TX; + if (Instance == SPI2_BASE && i == 0) return DMA_REQUEST_SPI2_RX; + if (Instance == SPI2_BASE && i == 1) return DMA_REQUEST_SPI2_TX; + if (Instance == SPI3_BASE && i == 0) return DMA_REQUEST_SPI3_RX; + if (Instance == SPI3_BASE && i == 1) return DMA_REQUEST_SPI3_TX; + if (Instance == SPI4_BASE && i == 0) return DMA_REQUEST_SPI4_RX; + if (Instance == SPI4_BASE && i == 1) return DMA_REQUEST_SPI4_TX; + if (Instance == SPI5_BASE && i == 0) return DMA_REQUEST_SPI5_RX; + if (Instance == SPI5_BASE && i == 1) return DMA_REQUEST_SPI5_TX; - std::array streams = {(DMA_Stream_TypeDef*)Streams... }; + if (Instance == FMAC_BASE && i == 0) return DMA_REQUEST_MEM2MEM; + if (Instance == FMAC_BASE && i == 1) return DMA_REQUEST_FMAC_WRITE; + if (Instance == FMAC_BASE && i == 2) return DMA_REQUEST_FMAC_READ; + + ErrorHandler("Invalid DMA request configuration"); + return 0; +} + + - for (uint8_t i = 0; i < N; i++){ - uintptr_t stream_addr = reinterpret_cast(streams[i]); - if (!is_stream_available(stream_addr)){ - ErrorHandler("DMA stream already in use"); +uint32_t DMA::get_Direction(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_MEMORY_TO_MEMORY; } + else if ((is_i2c(Instance) && i == 1) || + (is_spi(Instance) && i == 1) || + (is_fmac(Instance) && i == 1)){ + return DMA_MEMORY_TO_PERIPH; + } + + return DMA_PERIPH_TO_MEMORY; +} + +uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_PINC_ENABLE; + } + return DMA_PINC_DISABLE; +} +uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_MINC_DISABLE; } + return DMA_MINC_ENABLE; +} - for (uint8_t i = 0; i < N; i++){ - used_streams.insert(reinterpret_cast(streams[i])); +uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { + if (is_i2c(Instance)){ + return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes } - used_peripherials.insert(periph_addr); - - for (uint8_t i = 0; i < N; i++){ - DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; - dma->Instance = streams[i]; - dma->Init.Request = get_Request(Instance, i); - dma->Init.Direction = get_Direction(Instance, i); - dma->Init.PeriphInc = get_PeriphInc(Instance, i); - dma->Init.MemInc = get_MemInc(Instance, i); - dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); - dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); - dma->Init.Mode = get_Mode(Instance, i); - dma->Init.Priority = get_Priority(Instance, i); - dma->Init.FIFOMode = get_FIFOMode(Instance, i); - dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); - dma->Init.MemBurst = get_MemBurst(Instance, i); - dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); - IRQn_Type irq = get_irqn(streams[i]); - - if constexpr (is_spi(Instance)) { - auto* spi_handle = std::get(handle); - auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); - } - else if constexpr (is_i2c(Instance)) { - auto* i2c_handle = std::get(handle); - auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); - } - else if constexpr (is_adc(Instance)) { - auto* adc_handle = std::get(handle); - auto member = &ADC_HandleTypeDef::DMA_Handle; - inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); - } - else if constexpr (is_fmac(Instance)) { - auto* fmac_handle = std::get(handle); - DMA_HandleTypeDef* FMAC_HandleTypeDef::* member; - if (i == 0) member = &FMAC_HandleTypeDef::hdmaPreload; - else if (i == 1) member = &FMAC_HandleTypeDef::hdmaIn; - else member = &FMAC_HandleTypeDef::hdmaOut; - inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); - } - - inscribed_index++; + else if (is_spi(Instance)){ + return DMA_PDATAALIGN_BYTE; + } + + return DMA_PDATAALIGN_HALFWORD; +} + +uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { + if (is_i2c(Instance)){ + return DMA_MDATAALIGN_WORD; + } + else if (is_spi(Instance)){ + return DMA_MDATAALIGN_BYTE; + } + + return DMA_MDATAALIGN_HALFWORD; +} +uint32_t DMA::get_Mode(auto Instance, uint8_t i) { + if (is_spi(Instance) || is_fmac(Instance)){ + return DMA_NORMAL; + } + + return DMA_CIRCULAR; +} + + uint32_t DMA::get_Priority(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ + return DMA_PRIORITY_HIGH; + } + + return DMA_PRIORITY_LOW; +} +uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ + return DMA_FIFOMODE_ENABLE; + } + return DMA_FIFOMODE_DISABLE; +} + +uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { + if (is_spi(Instance)){ + return DMA_FIFO_THRESHOLD_FULL; } + return DMA_FIFO_THRESHOLD_HALFFULL; } -template -DMA::DmaLinkEntry DMA::make_dma_entry( - PeriphHandle* periph, - DMA_HandleTypeDef* dma, - DMA_HandleTypeDef* PeriphHandle::* member, - IRQn_Type irqn -){ - return DmaLinkEntry{ - periph, - dma, - [periph, member, dma](DMA_HandleTypeDef* d) { - periph->*member = d; - d->Parent = periph; - }, - irqn - }; +uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { + return DMA_MBURST_SINGLE; } +uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { + return DMA_PBURST_SINGLE; +} \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index b2266d0c4..f91f455fe 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -1,171 +1,111 @@ #include "HALAL/Models/DMA/DMA.hpp" -inline uint8_t DMA::inscribed_index{0}; -inline std::set DMA::used_peripherials{}; -inline std::set DMA::used_streams{}; -inline std::array DMA::inscribed_streams{}; +template +DMA::DmaLinkEntry DMA::make_dma_entry( + PeriphHandle* periph, + DMA_HandleTypeDef* dma, + DMA_HandleTypeDef* PeriphHandle::* member, + IRQn_Type irqn +){ + return DmaLinkEntry{ + periph, + dma, + [periph, member](DMA_HandleTypeDef* d) { + periph->*member = d; + d->Parent = periph; + }, + irqn + }; +} + +template +requires ( + (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || + (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || + (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) +) +void DMA::inscribe_stream(PeriphVariant handle) { + const std::size_t N = sizeof...(Streams); + if (inscribed_index + N > MAX_STREAMS){ + ErrorHandler("Too many streams inscribed"); + } + + unsigned long periph_addr = reinterpret_cast(Instance); + if (!is_peripherial_available(periph_addr)){ + ErrorHandler("Peripheral already in use"); + } + + std::array streams = {(DMA_Stream_TypeDef*)Streams... }; + + for (uint8_t i = 0; i < N; i++){ + uintptr_t stream_addr = reinterpret_cast(streams[i]); + if (!is_stream_available(stream_addr)){ + ErrorHandler("DMA stream already in use"); + } + } + + for (uint8_t i = 0; i < N; i++){ + used_streams.insert(reinterpret_cast(streams[i])); + } + used_peripherials.insert(periph_addr); + + for (uint8_t i = 0; i < N; i++){ + DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; + dma->Instance = streams[i]; + dma->Init.Request = get_Request(Instance, i); + dma->Init.Direction = get_Direction(Instance, i); + dma->Init.PeriphInc = get_PeriphInc(Instance, i); + dma->Init.MemInc = get_MemInc(Instance, i); + dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); + dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); + dma->Init.Mode = get_Mode(Instance, i); + dma->Init.Priority = get_Priority(Instance, i); + dma->Init.FIFOMode = get_FIFOMode(Instance, i); + dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); + dma->Init.MemBurst = get_MemBurst(Instance, i); + dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); + IRQn_Type irq = get_irqn(streams[i]); + + if constexpr (is_spi(Instance)) { + auto* spi_handle = std::get(handle); + auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); + } + else if constexpr (is_i2c(Instance)) { + auto* i2c_handle = std::get(handle); + auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); + } + else if constexpr (is_adc(Instance)) { + auto* adc_handle = std::get(handle); + auto member = &ADC_HandleTypeDef::DMA_Handle; + inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); + } + else if constexpr (is_fmac(Instance)) { + auto* fmac_handle = std::get(handle); + auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : + (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : + &FMAC_HandleTypeDef::hdmaOut; + inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); + } + + inscribed_index++; + } +} void DMA::start() { + __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); for (uint8_t i = 0; i < inscribed_index; i++) { auto& [periph, dma, linker, irq] = inscribed_streams[i]; - // Inicializar DMA if (HAL_DMA_Init(dma) != HAL_OK) { ErrorHandler("DMA Init failed"); } - // Vincular DMA al periférico linker(dma); - // Configurar interrupción - HAL_NVIC_SetPriority(irq, 5, 0); + HAL_NVIC_SetPriority(irq, 0, 0); HAL_NVIC_EnableIRQ(irq); } } - -bool DMA::is_stream_available(uintptr_t stream) { - return used_streams.find(stream) == used_streams.end(); -} - -bool DMA::is_peripherial_available(uintptr_t peripheral) { - return used_peripherials.find(peripheral) == used_peripherials.end(); -} - - -IRQn_Type DMA::get_irqn(auto stream) { - if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; - else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; - else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; - else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; - else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; - else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; - else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; - else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; - - else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; - else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; - else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; - else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; - else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; - else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; - else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; - else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; - else ErrorHandler(); -} - -uint32_t DMA::get_Request(auto Instance, uint8_t i) { - if (Instance == ADC1) return DMA_REQUEST_ADC1; - if (Instance == ADC2) return DMA_REQUEST_ADC2; - if (Instance == ADC3) return DMA_REQUEST_ADC3; - - if (Instance == I2C1 && i == 0) return DMA_REQUEST_I2C1_RX; - if (Instance == I2C1 && i == 1) return DMA_REQUEST_I2C1_TX; - if (Instance == I2C2 && i == 0) return DMA_REQUEST_I2C2_RX; - if (Instance == I2C2 && i == 1) return DMA_REQUEST_I2C2_TX; - if (Instance == I2C3 && i == 0) return DMA_REQUEST_I2C3_RX; - if (Instance == I2C3 && i == 1) return DMA_REQUEST_I2C3_TX; - if (Instance == I2C5 && i == 0) return DMA_REQUEST_I2C5_RX; - if (Instance == I2C5 && i == 1) return DMA_REQUEST_I2C5_TX; - - if (Instance == SPI1 && i == 0) return DMA_REQUEST_SPI1_RX; - if (Instance == SPI1 && i == 1) return DMA_REQUEST_SPI1_TX; - if (Instance == SPI2 && i == 0) return DMA_REQUEST_SPI2_RX; - if (Instance == SPI2 && i == 1) return DMA_REQUEST_SPI2_TX; - if (Instance == SPI3 && i == 0) return DMA_REQUEST_SPI3_RX; - if (Instance == SPI3 && i == 1) return DMA_REQUEST_SPI3_TX; - if (Instance == SPI4 && i == 0) return DMA_REQUEST_SPI4_RX; - if (Instance == SPI4 && i == 1) return DMA_REQUEST_SPI4_TX; - if (Instance == SPI5 && i == 0) return DMA_REQUEST_SPI5_RX; - if (Instance == SPI5 && i == 1) return DMA_REQUEST_SPI5_TX; - - if (Instance == FMAC && i == 0) return DMA_REQUEST_MEM2MEM; - if (Instance == FMAC && i == 1) return DMA_REQUEST_FMAC_WRITE; - if (Instance == FMAC && i == 2) return DMA_REQUEST_FMAC_READ; - return 0; -} - - - -uint32_t DMA::get_Direction(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_MEMORY_TO_MEMORY; - } - else if ((is_i2c(Instance) && i == 1) || - (is_spi(Instance) && i == 1) || - (is_fmac(Instance) && i == 1)){ - return DMA_MEMORY_TO_PERIPH; - } - - return DMA_PERIPH_TO_MEMORY; -} - -uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_PINC_ENABLE; - } - return DMA_PINC_DISABLE; -} -uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_MINC_DISABLE; - } - return DMA_MINC_ENABLE; -} - -uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { - if (is_i2c(Instance)){ - return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes - } - else if (is_spi(Instance)){ - return DMA_PDATAALIGN_BYTE; - } - - return DMA_PDATAALIGN_HALFWORD; -} - -uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { - if (is_i2c(Instance)){ - return DMA_MDATAALIGN_WORD; - } - else if (is_spi(Instance)){ - return DMA_MDATAALIGN_BYTE; - } - - return DMA_MDATAALIGN_HALFWORD; -} -uint32_t DMA::get_Mode(auto Instance, uint8_t i) { - if (is_spi(Instance) || is_fmac(Instance)){ - return DMA_NORMAL; - } - - return DMA_CIRCULAR; -} - - uint32_t DMA::get_Priority(auto Instance, uint8_t i) { - if (is_fmac(Instance)){ - return DMA_PRIORITY_HIGH; - } - - return DMA_PRIORITY_LOW; -} -uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { - if (is_fmac(Instance)){ - return DMA_FIFOMODE_ENABLE; - } - return DMA_FIFOMODE_DISABLE; -} - -uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { - if (is_spi(Instance)){ - return DMA_FIFO_THRESHOLD_FULL; - } - return DMA_FIFO_THRESHOLD_HALFFULL; -} - -uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { - return DMA_MBURST_SINGLE; -} - -uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { - return DMA_PBURST_SINGLE; -} \ No newline at end of file diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index 2ee1b7fbc..c637354f5 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -42,7 +42,8 @@ uint8_t ADC::inscribe(Pin pin) { InitData& init_data = active_instances[id_counter].peripheral->init_data; - static constexpr auto dma_adc1_config {DMA::inscribe_stream()}; + + // DMA::inscribe_stream(); active_instances[id_counter].rank = init_data.channels.size(); init_data.channels.push_back(active_instances[id_counter].channel); return id_counter++; diff --git a/Src/HALAL/Services/Communication/I2C/I2C.cpp b/Src/HALAL/Services/Communication/I2C/I2C.cpp index 25ba233ac..758918905 100644 --- a/Src/HALAL/Services/Communication/I2C/I2C.cpp +++ b/Src/HALAL/Services/Communication/I2C/I2C.cpp @@ -23,7 +23,7 @@ uint8_t I2C::inscribe(I2C::Peripheral &i2c, uint8_t address) { Pin::inscribe(i2c_instance->SCL, ALTERNATIVE); Pin::inscribe(i2c_instance->SDA, ALTERNATIVE); - static constexpr auto dma_i2c1_config {DMA::inscribe_stream()}; + DMA::inscribe_stream(i2c_instance->hi2c); uint8_t id = I2C::id_counter++; diff --git a/Src/HALAL/Services/Communication/SPI/SPI.cpp b/Src/HALAL/Services/Communication/SPI/SPI.cpp index f9f9628f6..172cba4e7 100644 --- a/Src/HALAL/Services/Communication/SPI/SPI.cpp +++ b/Src/HALAL/Services/Communication/SPI/SPI.cpp @@ -56,7 +56,7 @@ uint8_t SPI::inscribe(SPI::Peripheral& spi) { uint8_t id = SPI::id_counter++; if (spi_instance->use_DMA) { - static constexpr auto dma_spi1_config {DMA::inscribe_stream()}; + DMA::inscribe_stream(spi_instance->hspi); } SPI::registered_spi[id] = spi_instance; SPI::registered_spi_by_handler[spi_instance->hspi] = spi_instance; diff --git a/Src/HALAL/Services/FMAC/FMAC.cpp b/Src/HALAL/Services/FMAC/FMAC.cpp index 546de926f..8ed6eafd1 100644 --- a/Src/HALAL/Services/FMAC/FMAC.cpp +++ b/Src/HALAL/Services/FMAC/FMAC.cpp @@ -32,7 +32,7 @@ void MultiplierAccelerator::IIR_software_in_software_out_inscribe(uint16_t input } void MultiplierAccelerator::inscribe(){ - DMA::inscribe_stream(); + DMA::inscribe_stream(Instance.hfmac); } void MultiplierAccelerator::start(){ From 8f496aeefd81d8391af2b616cc14ae7e23934acd Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Sun, 30 Nov 2025 00:43:07 +0100 Subject: [PATCH 044/109] hacer funciones inline para que pueda compilar --- Inc/HALAL/Models/DMA/DMA.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index c75f05c69..1138838e6 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -122,11 +122,11 @@ constexpr bool DMA::is_fmac(auto Instance) { return Instance == FMAC_BASE; } -bool DMA::is_stream_available(uintptr_t stream) { +inline bool DMA::is_stream_available(uintptr_t stream) { return used_streams.find(stream) == used_streams.end(); } -bool DMA::is_peripherial_available(unsigned long peripheral) { +inline bool DMA::is_peripherial_available(unsigned long peripheral) { return used_peripherials.find(peripheral) == used_peripherials.end(); } From 2651dc63fe89fc92ea71c32688f2dc32fc8d9f37 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Sun, 30 Nov 2025 10:36:57 +0100 Subject: [PATCH 045/109] adc inscribe_dma now working, moved dma implementations from cpp to hpp, fixed irqn function, and minor changes to inscribe_dma for legibility --- Inc/HALAL/Models/DMA/DMA.hpp | 129 ++++++++++++++++++++++++++++----- Src/HALAL/Models/DMA/DMA.cpp | 95 +----------------------- Src/HALAL/Services/ADC/ADC.cpp | 2 +- 3 files changed, 113 insertions(+), 113 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 1138838e6..3a37999d0 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -132,23 +132,23 @@ inline bool DMA::is_peripherial_available(unsigned long peripheral) { IRQn_Type DMA::get_irqn(auto stream) { - if (stream == DMA1_Stream0_BASE) return DMA1_Stream0_IRQn; - else if (stream == DMA1_Stream1_BASE) return DMA1_Stream1_IRQn; - else if (stream == DMA1_Stream2_BASE) return DMA1_Stream2_IRQn; - else if (stream == DMA1_Stream3_BASE) return DMA1_Stream3_IRQn; - else if (stream == DMA1_Stream4_BASE) return DMA1_Stream4_IRQn; - else if (stream == DMA1_Stream5_BASE) return DMA1_Stream5_IRQn; - else if (stream == DMA1_Stream6_BASE) return DMA1_Stream6_IRQn; - else if (stream == DMA1_Stream7_BASE) return DMA1_Stream7_IRQn; - - else if (stream == DMA2_Stream0_BASE) return DMA2_Stream0_IRQn; - else if (stream == DMA2_Stream1_BASE) return DMA2_Stream1_IRQn; - else if (stream == DMA2_Stream2_BASE) return DMA2_Stream2_IRQn; - else if (stream == DMA2_Stream3_BASE) return DMA2_Stream3_IRQn; - else if (stream == DMA2_Stream4_BASE) return DMA2_Stream4_IRQn; - else if (stream == DMA2_Stream5_BASE) return DMA2_Stream5_IRQn; - else if (stream == DMA2_Stream6_BASE) return DMA2_Stream6_IRQn; - else if (stream == DMA2_Stream7_BASE) return DMA2_Stream7_IRQn; + if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; + else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; + else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; + else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; + else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; + else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; + else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; + else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; + + else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; + else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; + else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; + else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; + else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; + else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; + else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; + else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; else ErrorHandler("Unknown DMA stream"); return DMA1_Stream0_IRQn; // Nunca se alcanza } @@ -270,4 +270,97 @@ uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { return DMA_PBURST_SINGLE; -} \ No newline at end of file +} + +template +DMA::DmaLinkEntry DMA::make_dma_entry( + PeriphHandle* periph, + DMA_HandleTypeDef* dma, + DMA_HandleTypeDef* PeriphHandle::* member, + IRQn_Type irqn +){ + return DmaLinkEntry{ + periph, + dma, + [periph, member](DMA_HandleTypeDef* d) { + periph->*member = d; + d->Parent = periph; + }, + irqn + }; +} + +template +requires ( + (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || + (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || + (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) +) +void DMA::inscribe_stream(PeriphVariant handle) { + const std::size_t N = sizeof...(Streams); + if (inscribed_index + N > MAX_STREAMS){ + ErrorHandler("Too many streams inscribed"); + } + + unsigned long periph_addr = reinterpret_cast(Instance); + if (!is_peripherial_available(periph_addr)){ + ErrorHandler("Peripheral already in use"); + } + used_peripherials.insert(periph_addr); + + std::array streams = {(DMA_Stream_TypeDef*)Streams... }; + + for (uint8_t i = 0; i < N; i++){ + uintptr_t stream_addr = reinterpret_cast(streams[i]); + if (!is_stream_available(stream_addr)){ + ErrorHandler("DMA stream already in use"); + used_streams.insert(stream_addr); + } + } + + + for (uint8_t i = 0; i < N; i++){ + DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; + dma->Instance = streams[i]; + dma->Init.Request = get_Request(Instance, i); + dma->Init.Direction = get_Direction(Instance, i); + dma->Init.PeriphInc = get_PeriphInc(Instance, i); + dma->Init.MemInc = get_MemInc(Instance, i); + dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); + dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); + dma->Init.Mode = get_Mode(Instance, i); + dma->Init.Priority = get_Priority(Instance, i); + dma->Init.FIFOMode = get_FIFOMode(Instance, i); + dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); + dma->Init.MemBurst = get_MemBurst(Instance, i); + dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); + IRQn_Type irq = get_irqn(streams[i]); + + if constexpr (is_spi(Instance)) { + auto* spi_handle = std::get(handle); + auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); + } + else if constexpr (is_i2c(Instance)) { + auto* i2c_handle = std::get(handle); + auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); + } + else if constexpr (is_adc(Instance)) { + auto* adc_handle = std::get(handle); + auto member = &ADC_HandleTypeDef::DMA_Handle; + inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); + } + else if constexpr (is_fmac(Instance)) { + auto* fmac_handle = std::get(handle); + auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : + (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : + &FMAC_HandleTypeDef::hdmaOut; + inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); + } + + inscribed_index++; + } +} + + diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index f91f455fe..db3768088 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -1,98 +1,5 @@ #include "HALAL/Models/DMA/DMA.hpp" -template -DMA::DmaLinkEntry DMA::make_dma_entry( - PeriphHandle* periph, - DMA_HandleTypeDef* dma, - DMA_HandleTypeDef* PeriphHandle::* member, - IRQn_Type irqn -){ - return DmaLinkEntry{ - periph, - dma, - [periph, member](DMA_HandleTypeDef* d) { - periph->*member = d; - d->Parent = periph; - }, - irqn - }; -} - -template -requires ( - (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || - (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || - (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) -) -void DMA::inscribe_stream(PeriphVariant handle) { - const std::size_t N = sizeof...(Streams); - if (inscribed_index + N > MAX_STREAMS){ - ErrorHandler("Too many streams inscribed"); - } - - unsigned long periph_addr = reinterpret_cast(Instance); - if (!is_peripherial_available(periph_addr)){ - ErrorHandler("Peripheral already in use"); - } - - std::array streams = {(DMA_Stream_TypeDef*)Streams... }; - - for (uint8_t i = 0; i < N; i++){ - uintptr_t stream_addr = reinterpret_cast(streams[i]); - if (!is_stream_available(stream_addr)){ - ErrorHandler("DMA stream already in use"); - } - } - - for (uint8_t i = 0; i < N; i++){ - used_streams.insert(reinterpret_cast(streams[i])); - } - used_peripherials.insert(periph_addr); - - for (uint8_t i = 0; i < N; i++){ - DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; - dma->Instance = streams[i]; - dma->Init.Request = get_Request(Instance, i); - dma->Init.Direction = get_Direction(Instance, i); - dma->Init.PeriphInc = get_PeriphInc(Instance, i); - dma->Init.MemInc = get_MemInc(Instance, i); - dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); - dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); - dma->Init.Mode = get_Mode(Instance, i); - dma->Init.Priority = get_Priority(Instance, i); - dma->Init.FIFOMode = get_FIFOMode(Instance, i); - dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); - dma->Init.MemBurst = get_MemBurst(Instance, i); - dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); - IRQn_Type irq = get_irqn(streams[i]); - - if constexpr (is_spi(Instance)) { - auto* spi_handle = std::get(handle); - auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); - } - else if constexpr (is_i2c(Instance)) { - auto* i2c_handle = std::get(handle); - auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); - } - else if constexpr (is_adc(Instance)) { - auto* adc_handle = std::get(handle); - auto member = &ADC_HandleTypeDef::DMA_Handle; - inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); - } - else if constexpr (is_fmac(Instance)) { - auto* fmac_handle = std::get(handle); - auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : - (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : - &FMAC_HandleTypeDef::hdmaOut; - inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); - } - - inscribed_index++; - } -} - void DMA::start() { __HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_DMA2_CLK_ENABLE(); @@ -108,4 +15,4 @@ void DMA::start() { HAL_NVIC_SetPriority(irq, 0, 0); HAL_NVIC_EnableIRQ(irq); } -} +} \ No newline at end of file diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index c637354f5..f44730324 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -43,7 +43,7 @@ uint8_t ADC::inscribe(Pin pin) { InitData& init_data = active_instances[id_counter].peripheral->init_data; - // DMA::inscribe_stream(); + DMA::inscribe_stream(active_instances[id_counter].peripheral->handle); active_instances[id_counter].rank = init_data.channels.size(); init_data.channels.push_back(active_instances[id_counter].channel); return id_counter++; From 3996ec09a010ec514bf21060dd4d4d079169a271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20S=C3=A1ez?= Date: Sun, 30 Nov 2025 13:57:40 +0100 Subject: [PATCH 046/109] Initial structure --- CMakeLists.txt | 6 +++--- Inc/stm32h7xx_hal_conf_template.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 037e4f115..b5b4eb106 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -250,7 +250,7 @@ target_compile_options(${STLIB_LIBRARY} PRIVATE $<$:-specs=nosys.specs> $<$:-ffunction-sections> $<$:-fdata-sections> - $<$:-fno-exceptions> + # $<$:-fno-exceptions> -Wno-psabi @@ -259,8 +259,8 @@ target_compile_options(${STLIB_LIBRARY} PRIVATE $<$:-Wall> $<$:-Wpedantic> $<$:-Werror> - $<$:-Wno-gnu-zero-variadic-macro-arguments> - $<$:-Wno-inconsistent-missing-override> + # $<$:-Wno-gnu-zero-variadic-macro-arguments> + # $<$:-Wno-inconsistent-missing-override> $<$:-fno-use-cxa-atexit> $<$:-fno-rtti> $<$:-Wno-address-of-packed-member> diff --git a/Inc/stm32h7xx_hal_conf_template.h b/Inc/stm32h7xx_hal_conf_template.h index 4f41c7d25..74fdc0c32 100644 --- a/Inc/stm32h7xx_hal_conf_template.h +++ b/Inc/stm32h7xx_hal_conf_template.h @@ -233,7 +233,7 @@ * @brief Uncomment the line below to expanse the "assert_param" macro in the * HAL drivers code */ -/* #define USE_FULL_ASSERT 1U */ +#define USE_FULL_ASSERT 1 /* Includes ------------------------------------------------------------------*/ From d7e562cf7f81bd176d8cc33061da425d6159c84a Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Tue, 2 Dec 2025 19:39:48 +0100 Subject: [PATCH 047/109] cambio de nombre al antiguo dma y empiezo con la nueva infraestructura compile-time --- Inc/HALAL/Models/DMA/DMA-old.hpp | 366 ++++++++++++++++++++++++ Inc/HALAL/Models/DMA/DMA.hpp | 469 +++++++++---------------------- 2 files changed, 497 insertions(+), 338 deletions(-) create mode 100644 Inc/HALAL/Models/DMA/DMA-old.hpp diff --git a/Inc/HALAL/Models/DMA/DMA-old.hpp b/Inc/HALAL/Models/DMA/DMA-old.hpp new file mode 100644 index 000000000..3a37999d0 --- /dev/null +++ b/Inc/HALAL/Models/DMA/DMA-old.hpp @@ -0,0 +1,366 @@ +/* + * DMA.hpp + * + * Created on: 10 dic. 2022 + * Author: aleja +*/ +#pragma once +#include "C++Utilities/CppUtils.hpp" +#include "stm32h7xx_hal.h" +#include "main.h" +#include "HALAL/Models/MPUManager/MPUManager.hpp" +#include +#include +#include +#include +#include + +#define MAX_STREAMS 16 + +class DMA { + using PeriphVariant = std::variant< + SPI_HandleTypeDef*, + I2C_HandleTypeDef*, + ADC_HandleTypeDef*, + FMAC_HandleTypeDef* + >; + struct DmaLinkEntry{ + PeriphVariant periph; // (__HANDLE__) + DMA_HandleTypeDef* dma; // (__DMA_HANDLE__) + std::function linker; // (__PPP_DMA_FIELD__) + IRQn_Type irq; // (__IRQn_TYPE__) + }; + + template + static DmaLinkEntry make_dma_entry( + PeriphHandle* periph, + DMA_HandleTypeDef* dma, + DMA_HandleTypeDef* PeriphHandle::* member, + IRQn_Type irqn + ); + + static uint32_t get_Request(auto Instance, uint8_t i); + + static uint32_t get_Direction(auto Instance, uint8_t i); + + static uint32_t get_PeriphInc(auto Instance, uint8_t i); + + static uint32_t get_MemInc(auto Instance, uint8_t i); + + static uint32_t get_PeriphDataAlignment(auto Instance, uint8_t i); + + static uint32_t get_MemDataAlignment(auto Instance, uint8_t i); + + static uint32_t get_Mode(auto Instance, uint8_t i); + + static uint32_t get_Priority(auto Instance, uint8_t i); + + static uint32_t get_FIFOMode(auto Instance, uint8_t i); + + static uint32_t get_FIFOThreshold(auto Instance, uint8_t i); + + static uint32_t get_MemBurst(auto Instance, uint8_t i); + + static uint32_t get_PeriphBurst(auto Instance, uint8_t i); + + static IRQn_Type get_irqn(auto stream); + + static bool is_stream_available(uintptr_t stream); + + static bool is_peripherial_available(unsigned long peripherial); + + static std::array inscribed_streams; + static uint8_t inscribed_index; + + static std::set used_peripherials; + static std::set used_streams; + + public: + static constexpr bool is_one_of(auto Instance, auto... Bases); + + static constexpr bool is_spi(auto Instance); + + static constexpr bool is_i2c(auto Instance); + + static constexpr bool is_adc(auto Instance); + + static constexpr bool is_fmac(auto Instance); + + template + requires ( + (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || + (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || + (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) + ) + static void inscribe_stream(PeriphVariant handle); + + static void start(); +}; + +inline uint8_t DMA::inscribed_index{0}; +inline std::set DMA::used_peripherials{}; +inline std::set DMA::used_streams{}; +inline std::array DMA::inscribed_streams{}; + +constexpr bool DMA::is_one_of(auto Instance, auto... Bases) { + return ((Instance == Bases) || ...); +} + +constexpr bool DMA::is_spi(auto Instance) { + return is_one_of(Instance, SPI1_BASE, SPI2_BASE, SPI3_BASE, SPI4_BASE, SPI5_BASE); +} + +constexpr bool DMA::is_i2c(auto Instance) { + return is_one_of(Instance, I2C1_BASE, I2C2_BASE, I2C3_BASE, I2C5_BASE); +} + +constexpr bool DMA::is_adc(auto Instance) { + return is_one_of(Instance, ADC1_BASE, ADC2_BASE, ADC3_BASE); +} + +constexpr bool DMA::is_fmac(auto Instance) { + return Instance == FMAC_BASE; +} + +inline bool DMA::is_stream_available(uintptr_t stream) { + return used_streams.find(stream) == used_streams.end(); +} + +inline bool DMA::is_peripherial_available(unsigned long peripheral) { + return used_peripherials.find(peripheral) == used_peripherials.end(); +} + + +IRQn_Type DMA::get_irqn(auto stream) { + if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; + else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; + else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; + else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; + else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; + else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; + else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; + else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; + + else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; + else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; + else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; + else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; + else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; + else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; + else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; + else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; + else ErrorHandler("Unknown DMA stream"); + return DMA1_Stream0_IRQn; // Nunca se alcanza +} + +uint32_t DMA::get_Request(auto Instance, uint8_t i) { + if (Instance == ADC1_BASE) return DMA_REQUEST_ADC1; + if (Instance == ADC2_BASE) return DMA_REQUEST_ADC2; + if (Instance == ADC3_BASE) return DMA_REQUEST_ADC3; + + if (Instance == I2C1_BASE && i == 0) return DMA_REQUEST_I2C1_RX; + if (Instance == I2C1_BASE && i == 1) return DMA_REQUEST_I2C1_TX; + if (Instance == I2C2_BASE && i == 0) return DMA_REQUEST_I2C2_RX; + if (Instance == I2C2_BASE && i == 1) return DMA_REQUEST_I2C2_TX; + if (Instance == I2C3_BASE && i == 0) return DMA_REQUEST_I2C3_RX; + if (Instance == I2C3_BASE && i == 1) return DMA_REQUEST_I2C3_TX; + if (Instance == I2C5_BASE && i == 0) return DMA_REQUEST_I2C5_RX; + if (Instance == I2C5_BASE && i == 1) return DMA_REQUEST_I2C5_TX; + + if (Instance == SPI1_BASE && i == 0) return DMA_REQUEST_SPI1_RX; + if (Instance == SPI1_BASE && i == 1) return DMA_REQUEST_SPI1_TX; + if (Instance == SPI2_BASE && i == 0) return DMA_REQUEST_SPI2_RX; + if (Instance == SPI2_BASE && i == 1) return DMA_REQUEST_SPI2_TX; + if (Instance == SPI3_BASE && i == 0) return DMA_REQUEST_SPI3_RX; + if (Instance == SPI3_BASE && i == 1) return DMA_REQUEST_SPI3_TX; + if (Instance == SPI4_BASE && i == 0) return DMA_REQUEST_SPI4_RX; + if (Instance == SPI4_BASE && i == 1) return DMA_REQUEST_SPI4_TX; + if (Instance == SPI5_BASE && i == 0) return DMA_REQUEST_SPI5_RX; + if (Instance == SPI5_BASE && i == 1) return DMA_REQUEST_SPI5_TX; + + if (Instance == FMAC_BASE && i == 0) return DMA_REQUEST_MEM2MEM; + if (Instance == FMAC_BASE && i == 1) return DMA_REQUEST_FMAC_WRITE; + if (Instance == FMAC_BASE && i == 2) return DMA_REQUEST_FMAC_READ; + + ErrorHandler("Invalid DMA request configuration"); + return 0; +} + + + +uint32_t DMA::get_Direction(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_MEMORY_TO_MEMORY; + } + else if ((is_i2c(Instance) && i == 1) || + (is_spi(Instance) && i == 1) || + (is_fmac(Instance) && i == 1)){ + return DMA_MEMORY_TO_PERIPH; + } + + return DMA_PERIPH_TO_MEMORY; +} + +uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_PINC_ENABLE; + } + return DMA_PINC_DISABLE; +} +uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { + if (is_fmac(Instance) && i == 0){ + return DMA_MINC_DISABLE; + } + return DMA_MINC_ENABLE; +} + +uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { + if (is_i2c(Instance)){ + return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes + } + else if (is_spi(Instance)){ + return DMA_PDATAALIGN_BYTE; + } + + return DMA_PDATAALIGN_HALFWORD; +} + +uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { + if (is_i2c(Instance)){ + return DMA_MDATAALIGN_WORD; + } + else if (is_spi(Instance)){ + return DMA_MDATAALIGN_BYTE; + } + + return DMA_MDATAALIGN_HALFWORD; +} +uint32_t DMA::get_Mode(auto Instance, uint8_t i) { + if (is_spi(Instance) || is_fmac(Instance)){ + return DMA_NORMAL; + } + + return DMA_CIRCULAR; +} + + uint32_t DMA::get_Priority(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ + return DMA_PRIORITY_HIGH; + } + + return DMA_PRIORITY_LOW; +} +uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { + if (is_fmac(Instance)){ + return DMA_FIFOMODE_ENABLE; + } + return DMA_FIFOMODE_DISABLE; +} + +uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { + if (is_spi(Instance)){ + return DMA_FIFO_THRESHOLD_FULL; + } + return DMA_FIFO_THRESHOLD_HALFFULL; +} + +uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { + return DMA_MBURST_SINGLE; +} + +uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { + return DMA_PBURST_SINGLE; +} + +template +DMA::DmaLinkEntry DMA::make_dma_entry( + PeriphHandle* periph, + DMA_HandleTypeDef* dma, + DMA_HandleTypeDef* PeriphHandle::* member, + IRQn_Type irqn +){ + return DmaLinkEntry{ + periph, + dma, + [periph, member](DMA_HandleTypeDef* d) { + periph->*member = d; + d->Parent = periph; + }, + irqn + }; +} + +template +requires ( + (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || + (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || + (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) +) +void DMA::inscribe_stream(PeriphVariant handle) { + const std::size_t N = sizeof...(Streams); + if (inscribed_index + N > MAX_STREAMS){ + ErrorHandler("Too many streams inscribed"); + } + + unsigned long periph_addr = reinterpret_cast(Instance); + if (!is_peripherial_available(periph_addr)){ + ErrorHandler("Peripheral already in use"); + } + used_peripherials.insert(periph_addr); + + std::array streams = {(DMA_Stream_TypeDef*)Streams... }; + + for (uint8_t i = 0; i < N; i++){ + uintptr_t stream_addr = reinterpret_cast(streams[i]); + if (!is_stream_available(stream_addr)){ + ErrorHandler("DMA stream already in use"); + used_streams.insert(stream_addr); + } + } + + + for (uint8_t i = 0; i < N; i++){ + DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; + dma->Instance = streams[i]; + dma->Init.Request = get_Request(Instance, i); + dma->Init.Direction = get_Direction(Instance, i); + dma->Init.PeriphInc = get_PeriphInc(Instance, i); + dma->Init.MemInc = get_MemInc(Instance, i); + dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); + dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); + dma->Init.Mode = get_Mode(Instance, i); + dma->Init.Priority = get_Priority(Instance, i); + dma->Init.FIFOMode = get_FIFOMode(Instance, i); + dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); + dma->Init.MemBurst = get_MemBurst(Instance, i); + dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); + IRQn_Type irq = get_irqn(streams[i]); + + if constexpr (is_spi(Instance)) { + auto* spi_handle = std::get(handle); + auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); + } + else if constexpr (is_i2c(Instance)) { + auto* i2c_handle = std::get(handle); + auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; + inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); + } + else if constexpr (is_adc(Instance)) { + auto* adc_handle = std::get(handle); + auto member = &ADC_HandleTypeDef::DMA_Handle; + inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); + } + else if constexpr (is_fmac(Instance)) { + auto* fmac_handle = std::get(handle); + auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : + (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : + &FMAC_HandleTypeDef::hdmaOut; + inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); + } + + inscribed_index++; + } +} + + diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 3a37999d0..c859c7672 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -1,9 +1,3 @@ -/* - * DMA.hpp - * - * Created on: 10 dic. 2022 - * Author: aleja -*/ #pragma once #include "C++Utilities/CppUtils.hpp" #include "stm32h7xx_hal.h" @@ -15,352 +9,151 @@ #include #include +using std::array; +using std::size_t; +using std::span; +using std::tuple; + #define MAX_STREAMS 16 -class DMA { - using PeriphVariant = std::variant< - SPI_HandleTypeDef*, - I2C_HandleTypeDef*, + +namespace ST_LIB { + struct DMA_Domain { + using xTypeDef = std::variant< + ADC_TypeDef*, + I2C_TypeDef*, + SPI_TypeDef*, + FMAC_TypeDef* + >; + using xHandleDef = std::variant< ADC_HandleTypeDef*, + I2C_HandleTypeDef*, + SPI_HandleTypeDef*, FMAC_HandleTypeDef* >; - struct DmaLinkEntry{ - PeriphVariant periph; // (__HANDLE__) - DMA_HandleTypeDef* dma; // (__DMA_HANDLE__) - std::function linker; // (__PPP_DMA_FIELD__) - IRQn_Type irq; // (__IRQn_TYPE__) - }; - - template - static DmaLinkEntry make_dma_entry( - PeriphHandle* periph, - DMA_HandleTypeDef* dma, - DMA_HandleTypeDef* PeriphHandle::* member, - IRQn_Type irqn - ); - - static uint32_t get_Request(auto Instance, uint8_t i); - - static uint32_t get_Direction(auto Instance, uint8_t i); - - static uint32_t get_PeriphInc(auto Instance, uint8_t i); - - static uint32_t get_MemInc(auto Instance, uint8_t i); - - static uint32_t get_PeriphDataAlignment(auto Instance, uint8_t i); - - static uint32_t get_MemDataAlignment(auto Instance, uint8_t i); - - static uint32_t get_Mode(auto Instance, uint8_t i); - - static uint32_t get_Priority(auto Instance, uint8_t i); - - static uint32_t get_FIFOMode(auto Instance, uint8_t i); - - static uint32_t get_FIFOThreshold(auto Instance, uint8_t i); - - static uint32_t get_MemBurst(auto Instance, uint8_t i); - - static uint32_t get_PeriphBurst(auto Instance, uint8_t i); - - static IRQn_Type get_irqn(auto stream); - - static bool is_stream_available(uintptr_t stream); - static bool is_peripherial_available(unsigned long peripherial); + enum class Instance : uint8_t {adc1, adc2, adc3, + i2c1, i2c2, i2c3, i2c5, + spi1, spi2, spi3, spi4, spi5, + fmac}; - static std::array inscribed_streams; - static uint8_t inscribed_index; - - static std::set used_peripherials; - static std::set used_streams; - - public: - static constexpr bool is_one_of(auto Instance, auto... Bases); + static inline xTypeDef instance_to_xTypeDef(Instance i) { + switch (i) { + case Instance::adc1: return ADC1; + case Instance::adc2: return ADC2; + case Instance::adc3: return ADC3; + + case Instance::i2c1: return I2C1; + case Instance::i2c2: return I2C2; + case Instance::i2c3: return I2C3; + case Instance::i2c5: return I2C5; + + case Instance::spi1: return SPI1; + case Instance::spi2: return SPI2; + case Instance::spi3: return SPI3; + case Instance::spi4: return SPI4; + case Instance::spi5: return SPI5; + + case Instance::fmac: return FMAC; + } + } - static constexpr bool is_spi(auto Instance); + enum class Stream : uint8_t {dma1_stream0, dma1_stream1, dma1_stream2, dma1_stream3, + dma1_stream4, dma1_stream5, dma1_stream6, dma1_stream7, + dma2_stream0, dma2_stream1, dma2_stream2, dma2_stream3, + dma2_stream4, dma2_stream5, dma2_stream6, dma2_stream7}; + + static inline DMA_Stream_TypeDef* stream_to_DMA_StreamTypeDef(Stream s) { + switch (s) { + case Stream::dma1_stream0: return DMA1_Stream0; + case Stream::dma1_stream1: return DMA1_Stream1; + case Stream::dma1_stream2: return DMA1_Stream2; + case Stream::dma1_stream3: return DMA1_Stream3; + case Stream::dma1_stream4: return DMA1_Stream4; + case Stream::dma1_stream5: return DMA1_Stream5; + case Stream::dma1_stream6: return DMA1_Stream6; + case Stream::dma1_stream7: return DMA1_Stream7; + + case Stream::dma2_stream0: return DMA2_Stream0; + case Stream::dma2_stream1: return DMA2_Stream1; + case Stream::dma2_stream2: return DMA2_Stream2; + case Stream::dma2_stream3: return DMA2_Stream3; + case Stream::dma2_stream4: return DMA2_Stream4; + case Stream::dma2_stream5: return DMA2_Stream5; + case Stream::dma2_stream6: return DMA2_Stream6; + case Stream::dma2_stream7: return DMA2_Stream7; + } + } - static constexpr bool is_i2c(auto Instance); - - static constexpr bool is_adc(auto Instance); - - static constexpr bool is_fmac(auto Instance); - - template - requires ( - (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || - (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || - (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) - ) - static void inscribe_stream(PeriphVariant handle); - - static void start(); -}; - -inline uint8_t DMA::inscribed_index{0}; -inline std::set DMA::used_peripherials{}; -inline std::set DMA::used_streams{}; -inline std::array DMA::inscribed_streams{}; - -constexpr bool DMA::is_one_of(auto Instance, auto... Bases) { - return ((Instance == Bases) || ...); -} - -constexpr bool DMA::is_spi(auto Instance) { - return is_one_of(Instance, SPI1_BASE, SPI2_BASE, SPI3_BASE, SPI4_BASE, SPI5_BASE); -} - -constexpr bool DMA::is_i2c(auto Instance) { - return is_one_of(Instance, I2C1_BASE, I2C2_BASE, I2C3_BASE, I2C5_BASE); -} - -constexpr bool DMA::is_adc(auto Instance) { - return is_one_of(Instance, ADC1_BASE, ADC2_BASE, ADC3_BASE); -} - -constexpr bool DMA::is_fmac(auto Instance) { - return Instance == FMAC_BASE; -} - -inline bool DMA::is_stream_available(uintptr_t stream) { - return used_streams.find(stream) == used_streams.end(); -} - -inline bool DMA::is_peripherial_available(unsigned long peripheral) { - return used_peripherials.find(peripheral) == used_peripherials.end(); -} - - -IRQn_Type DMA::get_irqn(auto stream) { - if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; - else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; - else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; - else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; - else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; - else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; - else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; - else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; - - else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; - else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; - else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; - else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; - else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; - else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; - else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; - else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; - else ErrorHandler("Unknown DMA stream"); - return DMA1_Stream0_IRQn; // Nunca se alcanza -} - -uint32_t DMA::get_Request(auto Instance, uint8_t i) { - if (Instance == ADC1_BASE) return DMA_REQUEST_ADC1; - if (Instance == ADC2_BASE) return DMA_REQUEST_ADC2; - if (Instance == ADC3_BASE) return DMA_REQUEST_ADC3; + struct Entry { + Instance instance; + std::array streams{}; + uint8_t count = 0; + IRQn_Type irqn; + }; - if (Instance == I2C1_BASE && i == 0) return DMA_REQUEST_I2C1_RX; - if (Instance == I2C1_BASE && i == 1) return DMA_REQUEST_I2C1_TX; - if (Instance == I2C2_BASE && i == 0) return DMA_REQUEST_I2C2_RX; - if (Instance == I2C2_BASE && i == 1) return DMA_REQUEST_I2C2_TX; - if (Instance == I2C3_BASE && i == 0) return DMA_REQUEST_I2C3_RX; - if (Instance == I2C3_BASE && i == 1) return DMA_REQUEST_I2C3_TX; - if (Instance == I2C5_BASE && i == 0) return DMA_REQUEST_I2C5_RX; - if (Instance == I2C5_BASE && i == 1) return DMA_REQUEST_I2C5_TX; + struct DMA{ + using domain = DMA_Domain; - if (Instance == SPI1_BASE && i == 0) return DMA_REQUEST_SPI1_RX; - if (Instance == SPI1_BASE && i == 1) return DMA_REQUEST_SPI1_TX; - if (Instance == SPI2_BASE && i == 0) return DMA_REQUEST_SPI2_RX; - if (Instance == SPI2_BASE && i == 1) return DMA_REQUEST_SPI2_TX; - if (Instance == SPI3_BASE && i == 0) return DMA_REQUEST_SPI3_RX; - if (Instance == SPI3_BASE && i == 1) return DMA_REQUEST_SPI3_TX; - if (Instance == SPI4_BASE && i == 0) return DMA_REQUEST_SPI4_RX; - if (Instance == SPI4_BASE && i == 1) return DMA_REQUEST_SPI4_TX; - if (Instance == SPI5_BASE && i == 0) return DMA_REQUEST_SPI5_RX; - if (Instance == SPI5_BASE && i == 1) return DMA_REQUEST_SPI5_TX; - - if (Instance == FMAC_BASE && i == 0) return DMA_REQUEST_MEM2MEM; - if (Instance == FMAC_BASE && i == 1) return DMA_REQUEST_FMAC_WRITE; - if (Instance == FMAC_BASE && i == 2) return DMA_REQUEST_FMAC_READ; + Entry e; - ErrorHandler("Invalid DMA request configuration"); - return 0; -} + template + consteval DMA(Instance instance) : e(instance) { + static_assert(sizeof...(Ss) <= 3, "Máximo 3 streams"); + size_t i = 0; + ((e.streams[i++] = Ss), ...); + e.count = i; + } + template consteval void inscribe(Ctx &ctx) const { + ctx.template add(e); + } + }; + static constexpr std::size_t max_instances {MAX_STREAMS}; + static_assert(max_instances > 0, "The number of instances must be greater than 0"); + + struct Config { + std::tuple> init_data{}; + }; -uint32_t DMA::get_Direction(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_MEMORY_TO_MEMORY; + template + static consteval std::array build(span instances){ + std::array cfgs{}; + + for (std::size_t i = 0; i < N; ++i){ + const auto &e = instances[i]; + + for (std::size_t j = 0; j < i; ++j){ + const auto &prev = instances[j]; + if (prev.instance == e.instance && prev.streams == e.streams){ + struct peripherial_already_inscribed {}; + throw peripherial_already_inscribed{}; + } + } + + std::array dma_handles; + for (std::size_t j = 0; j < e.count; j++){ + DMA_HandleTypeDef DMA_HandleStruct; + DMA_HandleStruct.Instance = e.streams[j]; + DMA_HandleStrcut.Init.Request = get_Request(e.instance, j); + DMA_HandleStrcut.Init.Direction = get_Direction(e.instance, j); + DMA_HandleStrcut.Init.PeriphInc = get_PeriphInc(e.instance, j); + DMA_HandleStrcut.Init.MemInc = get_MemInc(e.instance, j); + DMA_HandleStrcut.Init.PeriphDataAlignment = get_PeriphDataAlignment(e.instance, j); + DMA_HandleStrcut.Init.MemDataAlignment = get_MemDataAlignment(e.instance, j); + DMA_HandleStrcut.Init.Mode = get_Mode(e.instance, j); + DMA_HandleStrcut.Init.Priority = get_Priority(e.instance, j); + DMA_HandleStrcut.Init.FIFOMode = get_FIFOMode(e.instance, j); + DMA_HandleStrcut.Init.FIFOThreshold = get_FIFOThreshold(e.instance, j); + DMA_HandleStrcut.Init.MemBurst = get_MemBurst(e.instance, j); + DMA_HandleStrcut.Init.PeriphBurst = get_PeriphBurst(e.instance, j); + + dma_handles[i] = DMA_HandleStruct; + } + + cfgs[i].init_data = std::make_tuple(e.instance, dma_handles) + } } - else if ((is_i2c(Instance) && i == 1) || - (is_spi(Instance) && i == 1) || - (is_fmac(Instance) && i == 1)){ - return DMA_MEMORY_TO_PERIPH; - } - - return DMA_PERIPH_TO_MEMORY; -} - -uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_PINC_ENABLE; - } - return DMA_PINC_DISABLE; -} -uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_MINC_DISABLE; - } - return DMA_MINC_ENABLE; -} - -uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { - if (is_i2c(Instance)){ - return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes - } - else if (is_spi(Instance)){ - return DMA_PDATAALIGN_BYTE; - } - - return DMA_PDATAALIGN_HALFWORD; -} - -uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { - if (is_i2c(Instance)){ - return DMA_MDATAALIGN_WORD; - } - else if (is_spi(Instance)){ - return DMA_MDATAALIGN_BYTE; - } - - return DMA_MDATAALIGN_HALFWORD; -} -uint32_t DMA::get_Mode(auto Instance, uint8_t i) { - if (is_spi(Instance) || is_fmac(Instance)){ - return DMA_NORMAL; - } - - return DMA_CIRCULAR; -} - - uint32_t DMA::get_Priority(auto Instance, uint8_t i) { - if (is_fmac(Instance)){ - return DMA_PRIORITY_HIGH; - } - - return DMA_PRIORITY_LOW; -} -uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { - if (is_fmac(Instance)){ - return DMA_FIFOMODE_ENABLE; - } - return DMA_FIFOMODE_DISABLE; -} - -uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { - if (is_spi(Instance)){ - return DMA_FIFO_THRESHOLD_FULL; - } - return DMA_FIFO_THRESHOLD_HALFFULL; -} - -uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { - return DMA_MBURST_SINGLE; -} - -uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { - return DMA_PBURST_SINGLE; -} - -template -DMA::DmaLinkEntry DMA::make_dma_entry( - PeriphHandle* periph, - DMA_HandleTypeDef* dma, - DMA_HandleTypeDef* PeriphHandle::* member, - IRQn_Type irqn -){ - return DmaLinkEntry{ - periph, - dma, - [periph, member](DMA_HandleTypeDef* d) { - periph->*member = d; - d->Parent = periph; - }, - irqn }; -} - -template -requires ( - (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || - (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || - (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) -) -void DMA::inscribe_stream(PeriphVariant handle) { - const std::size_t N = sizeof...(Streams); - if (inscribed_index + N > MAX_STREAMS){ - ErrorHandler("Too many streams inscribed"); - } - - unsigned long periph_addr = reinterpret_cast(Instance); - if (!is_peripherial_available(periph_addr)){ - ErrorHandler("Peripheral already in use"); - } - used_peripherials.insert(periph_addr); - - std::array streams = {(DMA_Stream_TypeDef*)Streams... }; - - for (uint8_t i = 0; i < N; i++){ - uintptr_t stream_addr = reinterpret_cast(streams[i]); - if (!is_stream_available(stream_addr)){ - ErrorHandler("DMA stream already in use"); - used_streams.insert(stream_addr); - } - } - - - for (uint8_t i = 0; i < N; i++){ - DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; - dma->Instance = streams[i]; - dma->Init.Request = get_Request(Instance, i); - dma->Init.Direction = get_Direction(Instance, i); - dma->Init.PeriphInc = get_PeriphInc(Instance, i); - dma->Init.MemInc = get_MemInc(Instance, i); - dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); - dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); - dma->Init.Mode = get_Mode(Instance, i); - dma->Init.Priority = get_Priority(Instance, i); - dma->Init.FIFOMode = get_FIFOMode(Instance, i); - dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); - dma->Init.MemBurst = get_MemBurst(Instance, i); - dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); - IRQn_Type irq = get_irqn(streams[i]); - - if constexpr (is_spi(Instance)) { - auto* spi_handle = std::get(handle); - auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); - } - else if constexpr (is_i2c(Instance)) { - auto* i2c_handle = std::get(handle); - auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); - } - else if constexpr (is_adc(Instance)) { - auto* adc_handle = std::get(handle); - auto member = &ADC_HandleTypeDef::DMA_Handle; - inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); - } - else if constexpr (is_fmac(Instance)) { - auto* fmac_handle = std::get(handle); - auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : - (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : - &FMAC_HandleTypeDef::hdmaOut; - inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); - } - - inscribed_index++; - } -} - - +} \ No newline at end of file From c152e488db783bb6eb2a09a114cc18d0fb16e76c Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Wed, 3 Dec 2025 16:56:21 +0100 Subject: [PATCH 048/109] =?UTF-8?q?a=C3=B1adir=20funciones=20de=20configur?= =?UTF-8?q?acion=20del=20handle=20DMA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Inc/HALAL/Models/DMA/DMA.hpp | 205 +++++++++++++++++++++++++++++++---- 1 file changed, 184 insertions(+), 21 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index c859c7672..0bcf53946 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -37,6 +37,11 @@ namespace ST_LIB { spi1, spi2, spi3, spi4, spi5, fmac}; + enum class Stream : uint8_t {dma1_stream0, dma1_stream1, dma1_stream2, dma1_stream3, + dma1_stream4, dma1_stream5, dma1_stream6, dma1_stream7, + dma2_stream0, dma2_stream1, dma2_stream2, dma2_stream3, + dma2_stream4, dma2_stream5, dma2_stream6, dma2_stream7}; + static inline xTypeDef instance_to_xTypeDef(Instance i) { switch (i) { case Instance::adc1: return ADC1; @@ -57,11 +62,6 @@ namespace ST_LIB { case Instance::fmac: return FMAC; } } - - enum class Stream : uint8_t {dma1_stream0, dma1_stream1, dma1_stream2, dma1_stream3, - dma1_stream4, dma1_stream5, dma1_stream6, dma1_stream7, - dma2_stream0, dma2_stream1, dma2_stream2, dma2_stream3, - dma2_stream4, dma2_stream5, dma2_stream6, dma2_stream7}; static inline DMA_Stream_TypeDef* stream_to_DMA_StreamTypeDef(Stream s) { switch (s) { @@ -87,9 +87,8 @@ namespace ST_LIB { struct Entry { Instance instance; - std::array streams{}; + std::array, 3> streams{}; uint8_t count = 0; - IRQn_Type irqn; }; struct DMA{ @@ -101,7 +100,7 @@ namespace ST_LIB { consteval DMA(Instance instance) : e(instance) { static_assert(sizeof...(Ss) <= 3, "Máximo 3 streams"); size_t i = 0; - ((e.streams[i++] = Ss), ...); + ((e.streams[i++] = std::make_tuple(Ss, get_irqn(Ss))), ...); e.count = i; } @@ -117,6 +116,170 @@ namespace ST_LIB { std::tuple> init_data{}; }; + static inline IRQn_Type get_irqn(Stream stream) { + if (stream == Stream::dma1_stream0) return DMA1_Stream0_IRQn; + else if (stream == Stream::dma1_stream1) return DMA1_Stream1_IRQn; + else if (stream == Stream::dma1_stream2) return DMA1_Stream2_IRQn; + else if (stream == Stream::dma1_stream3) return DMA1_Stream3_IRQn; + else if (stream == Stream::dma1_stream4) return DMA1_Stream4_IRQn; + else if (stream == Stream::dma1_stream5) return DMA1_Stream5_IRQn; + else if (stream == Stream::dma1_stream6) return DMA1_Stream6_IRQn; + else if (stream == Stream::dma1_stream7) return DMA1_Stream7_IRQn; + + else if (stream == Stream::dma2_stream0) return DMA2_Stream0_IRQn; + else if (stream == Stream::dma2_stream1) return DMA2_Stream1_IRQn; + else if (stream == Stream::dma2_stream2) return DMA2_Stream2_IRQn; + else if (stream == Stream::dma2_stream3) return DMA2_Stream3_IRQn; + else if (stream == Stream::dma2_stream4) return DMA2_Stream4_IRQn; + else if (stream == Stream::dma2_stream5) return DMA2_Stream5_IRQn; + else if (stream == Stream::dma2_stream6) return DMA2_Stream6_IRQn; + else if (stream == Stream::dma2_stream7) return DMA2_Stream7_IRQn; + else ErrorHandler("Unknown DMA stream"); + return DMA1_Stream0_IRQn; // Nunca se alcanza + } + + // Si quitas el auto peta todo + static consteval inline bool is_one_of(Instance instance, auto... bases) { + return ((instance == bases) || ...); + } + + static consteval inline bool is_spi(Instance instance) { + return is_one_of(instance, Instance::spi1, Instance::spi2, + Instance::spi3, Instance::spi4, Instance::spi5); + } + + static consteval inline bool is_i2c(Instance instance) { + return is_one_of(instance, Instance::i2c1, Instance::i2c2, + Instance::i2c3, Instance::i2c5); + } + + static consteval inline bool is_adc(Instance instance) { + return is_one_of(instance, Instance::adc1, Instance::adc2, Instance::adc3); + } + + static consteval inline bool is_fmac(Instance instance) { + return instance == Instance::fmac; + } + + static consteval inline uint32_t get_Request(Instance instance, uint8_t i) { + if (instance == Instance::adc1) return DMA_REQUEST_ADC1; + if (instance == Instance::adc2) return DMA_REQUEST_ADC2; + if (instance == Instance::adc3) return DMA_REQUEST_ADC3; + + if (instance == Instance::i2c1 && i == 0) return DMA_REQUEST_I2C1_RX; + if (instance == Instance::i2c1 && i == 1) return DMA_REQUEST_I2C1_TX; + if (instance == Instance::i2c2 && i == 0) return DMA_REQUEST_I2C2_RX; + if (instance == Instance::i2c2 && i == 1) return DMA_REQUEST_I2C2_TX; + if (instance == Instance::i2c3 && i == 0) return DMA_REQUEST_I2C3_RX; + if (instance == Instance::i2c3 && i == 1) return DMA_REQUEST_I2C3_TX; + if (instance == Instance::i2c5 && i == 0) return DMA_REQUEST_I2C5_RX; + if (instance == Instance::i2c5 && i == 1) return DMA_REQUEST_I2C5_TX; + + if (instance == Instance::spi1 && i == 0) return DMA_REQUEST_SPI1_RX; + if (instance == Instance::spi1 && i == 1) return DMA_REQUEST_SPI1_TX; + if (instance == Instance::spi2 && i == 0) return DMA_REQUEST_SPI2_RX; + if (instance == Instance::spi2 && i == 1) return DMA_REQUEST_SPI2_TX; + if (instance == Instance::spi3 && i == 0) return DMA_REQUEST_SPI3_RX; + if (instance == Instance::spi3 && i == 1) return DMA_REQUEST_SPI3_TX; + if (instance == Instance::spi4 && i == 0) return DMA_REQUEST_SPI4_RX; + if (instance == Instance::spi4 && i == 1) return DMA_REQUEST_SPI4_TX; + if (instance == Instance::spi5 && i == 0) return DMA_REQUEST_SPI5_RX; + if (instance == Instance::spi5 && i == 1) return DMA_REQUEST_SPI5_TX; + + if (instance == Instance::fmac && i == 0) return DMA_REQUEST_MEM2MEM; + if (instance == Instance::fmac && i == 1) return DMA_REQUEST_FMAC_WRITE; + if (instance == Instance::fmac && i == 2) return DMA_REQUEST_FMAC_READ; + + ErrorHandler("Invalid DMA request configuration"); + return 0; + } + + + static consteval inline uint32_t get_Direction(Instance instance, uint8_t i) { + if (is_fmac(instance) && i == 0){ + return DMA_MEMORY_TO_MEMORY; + } + else if ((is_i2c(instance) && i == 1) || + (is_spi(instance) && i == 1) || + (is_fmac(instance) && i == 1)){ + return DMA_MEMORY_TO_PERIPH; + } + + return DMA_PERIPH_TO_MEMORY; + } + + static consteval inline uint32_t get_PeriphInc(Instance instance, uint8_t i) { + if (is_fmac(instance) && i == 0){ + return DMA_PINC_ENABLE; + } + return DMA_PINC_DISABLE; + } + static consteval inline uint32_t get_MemInc(Instance instance, uint8_t i) { + if (is_fmac(instance) && i == 0){ + return DMA_MINC_DISABLE; + } + return DMA_MINC_ENABLE; + } + + static consteval inline uint32_t get_PeriphDataAlignment(Instance instance, uint8_t i) { + if (is_i2c(instance)){ + return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes + } + else if (is_spi(instance)){ + return DMA_PDATAALIGN_BYTE; + } + + return DMA_PDATAALIGN_HALFWORD; + } + + static consteval inline uint32_t get_MemDataAlignment(Instance instance, uint8_t i) { + if (is_i2c(instance)){ + return DMA_MDATAALIGN_WORD; + } + else if (is_spi(instance)){ + return DMA_MDATAALIGN_BYTE; + } + + return DMA_MDATAALIGN_HALFWORD; + } + static consteval inline uint32_t get_Mode(Instance instance, uint8_t i) { + if (is_spi(instance) || is_fmac(instance)){ + return DMA_NORMAL; + } + + return DMA_CIRCULAR; + } + + static consteval inline uint32_t get_Priority(Instance instance, uint8_t i) { + if (is_fmac(instance)){ + return DMA_PRIORITY_HIGH; + } + + return DMA_PRIORITY_LOW; + } + static consteval inline uint32_t get_FIFOMode(Instance instance, uint8_t i) { + if (is_fmac(instance)){ + return DMA_FIFOMODE_ENABLE; + } + return DMA_FIFOMODE_DISABLE; + } + + static consteval inline uint32_t get_FIFOThreshold(Instance instance, uint8_t i) { + if (is_spi(instance)){ + return DMA_FIFO_THRESHOLD_FULL; + } + return DMA_FIFO_THRESHOLD_HALFFULL; + } + + static consteval inline uint32_t get_MemBurst(Instance instance, uint8_t i) { + return DMA_MBURST_SINGLE; + } + + static consteval inline uint32_t get_PeriphBurst(Instance instance, uint8_t i) { + return DMA_PBURST_SINGLE; + } + + template static consteval std::array build(span instances){ std::array cfgs{}; @@ -136,23 +299,23 @@ namespace ST_LIB { for (std::size_t j = 0; j < e.count; j++){ DMA_HandleTypeDef DMA_HandleStruct; DMA_HandleStruct.Instance = e.streams[j]; - DMA_HandleStrcut.Init.Request = get_Request(e.instance, j); - DMA_HandleStrcut.Init.Direction = get_Direction(e.instance, j); - DMA_HandleStrcut.Init.PeriphInc = get_PeriphInc(e.instance, j); - DMA_HandleStrcut.Init.MemInc = get_MemInc(e.instance, j); - DMA_HandleStrcut.Init.PeriphDataAlignment = get_PeriphDataAlignment(e.instance, j); - DMA_HandleStrcut.Init.MemDataAlignment = get_MemDataAlignment(e.instance, j); - DMA_HandleStrcut.Init.Mode = get_Mode(e.instance, j); - DMA_HandleStrcut.Init.Priority = get_Priority(e.instance, j); - DMA_HandleStrcut.Init.FIFOMode = get_FIFOMode(e.instance, j); - DMA_HandleStrcut.Init.FIFOThreshold = get_FIFOThreshold(e.instance, j); - DMA_HandleStrcut.Init.MemBurst = get_MemBurst(e.instance, j); - DMA_HandleStrcut.Init.PeriphBurst = get_PeriphBurst(e.instance, j); + DMA_HandleStruct.Init.Request = get_Request(e.instance, j); + DMA_HandleStruct.Init.Direction = get_Direction(e.instance, j); + DMA_HandleStruct.Init.PeriphInc = get_PeriphInc(e.instance, j); + DMA_HandleStruct.Init.MemInc = get_MemInc(e.instance, j); + DMA_HandleStruct.Init.PeriphDataAlignment = get_PeriphDataAlignment(e.instance, j); + DMA_HandleStruct.Init.MemDataAlignment = get_MemDataAlignment(e.instance, j); + DMA_HandleStruct.Init.Mode = get_Mode(e.instance, j); + DMA_HandleStruct.Init.Priority = get_Priority(e.instance, j); + DMA_HandleStruct.Init.FIFOMode = get_FIFOMode(e.instance, j); + DMA_HandleStruct.Init.FIFOThreshold = get_FIFOThreshold(e.instance, j); + DMA_HandleStruct.Init.MemBurst = get_MemBurst(e.instance, j); + DMA_HandleStruct.Init.PeriphBurst = get_PeriphBurst(e.instance, j); dma_handles[i] = DMA_HandleStruct; } - cfgs[i].init_data = std::make_tuple(e.instance, dma_handles) + cfgs[i].init_data = std::make_tuple(e.instance, dma_handles); } } }; From 61d093cdd1b2929e1a0352f0cf4e85253fd8fe48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20S=C3=A1ez?= Date: Wed, 3 Dec 2025 00:23:23 +0100 Subject: [PATCH 049/109] Added DigitalInput and DigitalOutput Services, and added support for Alternate functions --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b5b4eb106..1e510b57e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -250,7 +250,6 @@ target_compile_options(${STLIB_LIBRARY} PRIVATE $<$:-specs=nosys.specs> $<$:-ffunction-sections> $<$:-fdata-sections> - # $<$:-fno-exceptions> -Wno-psabi From db10f576ebb0f79967118be8d7ad1d4b66abd42d Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Wed, 3 Dec 2025 21:37:15 +0100 Subject: [PATCH 050/109] todo lo facil hecho, queda lo dificil (handle y global_handle) --- Inc/HALAL/HALAL.hpp | 1 + Inc/HALAL/Models/DMA/DMA.hpp | 352 +++-------------------------- Inc/HALAL/Models/DMA/DMA2.hpp | 374 +++++++++++++++++++++++++++++++ Src/HALAL/Models/DMA/DMA-old.cpp | 18 ++ Src/HALAL/Models/DMA/DMA.cpp | 51 +++-- Src/HALAL/Models/DMA/DMA2.cpp | 0 6 files changed, 466 insertions(+), 330 deletions(-) create mode 100644 Inc/HALAL/Models/DMA/DMA2.hpp create mode 100644 Src/HALAL/Models/DMA/DMA-old.cpp create mode 100644 Src/HALAL/Models/DMA/DMA2.cpp diff --git a/Inc/HALAL/HALAL.hpp b/Inc/HALAL/HALAL.hpp index 316c9605a..6b20c7bc8 100644 --- a/Inc/HALAL/HALAL.hpp +++ b/Inc/HALAL/HALAL.hpp @@ -5,6 +5,7 @@ #include "HALAL/Models/HALconfig/HALconfig.hpp" #include "HALAL/Models/DMA/DMA.hpp" +#include "HALAL/Models/DMA/DMA2.hpp" #include "HALAL/Services/DigitalOutputService/DigitalOutputService.hpp" #include "HALAL/Services/DigitalInputService/DigitalInputService.hpp" diff --git a/Inc/HALAL/Models/DMA/DMA.hpp b/Inc/HALAL/Models/DMA/DMA.hpp index 0bcf53946..a9799cbb9 100644 --- a/Inc/HALAL/Models/DMA/DMA.hpp +++ b/Inc/HALAL/Models/DMA/DMA.hpp @@ -1,322 +1,42 @@ +/* + * DMA.hpp + * + * Created on: 10 dic. 2022 + * Author: aleja + */ + #pragma once + #include "C++Utilities/CppUtils.hpp" #include "stm32h7xx_hal.h" -#include "main.h" #include "HALAL/Models/MPUManager/MPUManager.hpp" -#include -#include -#include -#include -#include - -using std::array; -using std::size_t; -using std::span; -using std::tuple; - -#define MAX_STREAMS 16 - - -namespace ST_LIB { - struct DMA_Domain { - using xTypeDef = std::variant< - ADC_TypeDef*, - I2C_TypeDef*, - SPI_TypeDef*, - FMAC_TypeDef* - >; - using xHandleDef = std::variant< - ADC_HandleTypeDef*, - I2C_HandleTypeDef*, - SPI_HandleTypeDef*, - FMAC_HandleTypeDef* - >; - - enum class Instance : uint8_t {adc1, adc2, adc3, - i2c1, i2c2, i2c3, i2c5, - spi1, spi2, spi3, spi4, spi5, - fmac}; - - enum class Stream : uint8_t {dma1_stream0, dma1_stream1, dma1_stream2, dma1_stream3, - dma1_stream4, dma1_stream5, dma1_stream6, dma1_stream7, - dma2_stream0, dma2_stream1, dma2_stream2, dma2_stream3, - dma2_stream4, dma2_stream5, dma2_stream6, dma2_stream7}; - - static inline xTypeDef instance_to_xTypeDef(Instance i) { - switch (i) { - case Instance::adc1: return ADC1; - case Instance::adc2: return ADC2; - case Instance::adc3: return ADC3; - - case Instance::i2c1: return I2C1; - case Instance::i2c2: return I2C2; - case Instance::i2c3: return I2C3; - case Instance::i2c5: return I2C5; - - case Instance::spi1: return SPI1; - case Instance::spi2: return SPI2; - case Instance::spi3: return SPI3; - case Instance::spi4: return SPI4; - case Instance::spi5: return SPI5; - - case Instance::fmac: return FMAC; - } - } - - static inline DMA_Stream_TypeDef* stream_to_DMA_StreamTypeDef(Stream s) { - switch (s) { - case Stream::dma1_stream0: return DMA1_Stream0; - case Stream::dma1_stream1: return DMA1_Stream1; - case Stream::dma1_stream2: return DMA1_Stream2; - case Stream::dma1_stream3: return DMA1_Stream3; - case Stream::dma1_stream4: return DMA1_Stream4; - case Stream::dma1_stream5: return DMA1_Stream5; - case Stream::dma1_stream6: return DMA1_Stream6; - case Stream::dma1_stream7: return DMA1_Stream7; - - case Stream::dma2_stream0: return DMA2_Stream0; - case Stream::dma2_stream1: return DMA2_Stream1; - case Stream::dma2_stream2: return DMA2_Stream2; - case Stream::dma2_stream3: return DMA2_Stream3; - case Stream::dma2_stream4: return DMA2_Stream4; - case Stream::dma2_stream5: return DMA2_Stream5; - case Stream::dma2_stream6: return DMA2_Stream6; - case Stream::dma2_stream7: return DMA2_Stream7; - } - } - - struct Entry { - Instance instance; - std::array, 3> streams{}; - uint8_t count = 0; - }; - - struct DMA{ - using domain = DMA_Domain; - - Entry e; - - template - consteval DMA(Instance instance) : e(instance) { - static_assert(sizeof...(Ss) <= 3, "Máximo 3 streams"); - size_t i = 0; - ((e.streams[i++] = std::make_tuple(Ss, get_irqn(Ss))), ...); - e.count = i; - } - - template consteval void inscribe(Ctx &ctx) const { - ctx.template add(e); - } - }; - - static constexpr std::size_t max_instances {MAX_STREAMS}; - static_assert(max_instances > 0, "The number of instances must be greater than 0"); - - struct Config { - std::tuple> init_data{}; - }; - - static inline IRQn_Type get_irqn(Stream stream) { - if (stream == Stream::dma1_stream0) return DMA1_Stream0_IRQn; - else if (stream == Stream::dma1_stream1) return DMA1_Stream1_IRQn; - else if (stream == Stream::dma1_stream2) return DMA1_Stream2_IRQn; - else if (stream == Stream::dma1_stream3) return DMA1_Stream3_IRQn; - else if (stream == Stream::dma1_stream4) return DMA1_Stream4_IRQn; - else if (stream == Stream::dma1_stream5) return DMA1_Stream5_IRQn; - else if (stream == Stream::dma1_stream6) return DMA1_Stream6_IRQn; - else if (stream == Stream::dma1_stream7) return DMA1_Stream7_IRQn; - - else if (stream == Stream::dma2_stream0) return DMA2_Stream0_IRQn; - else if (stream == Stream::dma2_stream1) return DMA2_Stream1_IRQn; - else if (stream == Stream::dma2_stream2) return DMA2_Stream2_IRQn; - else if (stream == Stream::dma2_stream3) return DMA2_Stream3_IRQn; - else if (stream == Stream::dma2_stream4) return DMA2_Stream4_IRQn; - else if (stream == Stream::dma2_stream5) return DMA2_Stream5_IRQn; - else if (stream == Stream::dma2_stream6) return DMA2_Stream6_IRQn; - else if (stream == Stream::dma2_stream7) return DMA2_Stream7_IRQn; - else ErrorHandler("Unknown DMA stream"); - return DMA1_Stream0_IRQn; // Nunca se alcanza - } - - // Si quitas el auto peta todo - static consteval inline bool is_one_of(Instance instance, auto... bases) { - return ((instance == bases) || ...); - } - - static consteval inline bool is_spi(Instance instance) { - return is_one_of(instance, Instance::spi1, Instance::spi2, - Instance::spi3, Instance::spi4, Instance::spi5); - } - - static consteval inline bool is_i2c(Instance instance) { - return is_one_of(instance, Instance::i2c1, Instance::i2c2, - Instance::i2c3, Instance::i2c5); - } - - static consteval inline bool is_adc(Instance instance) { - return is_one_of(instance, Instance::adc1, Instance::adc2, Instance::adc3); - } - - static consteval inline bool is_fmac(Instance instance) { - return instance == Instance::fmac; - } - - static consteval inline uint32_t get_Request(Instance instance, uint8_t i) { - if (instance == Instance::adc1) return DMA_REQUEST_ADC1; - if (instance == Instance::adc2) return DMA_REQUEST_ADC2; - if (instance == Instance::adc3) return DMA_REQUEST_ADC3; - - if (instance == Instance::i2c1 && i == 0) return DMA_REQUEST_I2C1_RX; - if (instance == Instance::i2c1 && i == 1) return DMA_REQUEST_I2C1_TX; - if (instance == Instance::i2c2 && i == 0) return DMA_REQUEST_I2C2_RX; - if (instance == Instance::i2c2 && i == 1) return DMA_REQUEST_I2C2_TX; - if (instance == Instance::i2c3 && i == 0) return DMA_REQUEST_I2C3_RX; - if (instance == Instance::i2c3 && i == 1) return DMA_REQUEST_I2C3_TX; - if (instance == Instance::i2c5 && i == 0) return DMA_REQUEST_I2C5_RX; - if (instance == Instance::i2c5 && i == 1) return DMA_REQUEST_I2C5_TX; - - if (instance == Instance::spi1 && i == 0) return DMA_REQUEST_SPI1_RX; - if (instance == Instance::spi1 && i == 1) return DMA_REQUEST_SPI1_TX; - if (instance == Instance::spi2 && i == 0) return DMA_REQUEST_SPI2_RX; - if (instance == Instance::spi2 && i == 1) return DMA_REQUEST_SPI2_TX; - if (instance == Instance::spi3 && i == 0) return DMA_REQUEST_SPI3_RX; - if (instance == Instance::spi3 && i == 1) return DMA_REQUEST_SPI3_TX; - if (instance == Instance::spi4 && i == 0) return DMA_REQUEST_SPI4_RX; - if (instance == Instance::spi4 && i == 1) return DMA_REQUEST_SPI4_TX; - if (instance == Instance::spi5 && i == 0) return DMA_REQUEST_SPI5_RX; - if (instance == Instance::spi5 && i == 1) return DMA_REQUEST_SPI5_TX; - - if (instance == Instance::fmac && i == 0) return DMA_REQUEST_MEM2MEM; - if (instance == Instance::fmac && i == 1) return DMA_REQUEST_FMAC_WRITE; - if (instance == Instance::fmac && i == 2) return DMA_REQUEST_FMAC_READ; - - ErrorHandler("Invalid DMA request configuration"); - return 0; - } - - - static consteval inline uint32_t get_Direction(Instance instance, uint8_t i) { - if (is_fmac(instance) && i == 0){ - return DMA_MEMORY_TO_MEMORY; - } - else if ((is_i2c(instance) && i == 1) || - (is_spi(instance) && i == 1) || - (is_fmac(instance) && i == 1)){ - return DMA_MEMORY_TO_PERIPH; - } - - return DMA_PERIPH_TO_MEMORY; - } - - static consteval inline uint32_t get_PeriphInc(Instance instance, uint8_t i) { - if (is_fmac(instance) && i == 0){ - return DMA_PINC_ENABLE; - } - return DMA_PINC_DISABLE; - } - static consteval inline uint32_t get_MemInc(Instance instance, uint8_t i) { - if (is_fmac(instance) && i == 0){ - return DMA_MINC_DISABLE; - } - return DMA_MINC_ENABLE; - } - - static consteval inline uint32_t get_PeriphDataAlignment(Instance instance, uint8_t i) { - if (is_i2c(instance)){ - return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes - } - else if (is_spi(instance)){ - return DMA_PDATAALIGN_BYTE; - } - - return DMA_PDATAALIGN_HALFWORD; - } - - static consteval inline uint32_t get_MemDataAlignment(Instance instance, uint8_t i) { - if (is_i2c(instance)){ - return DMA_MDATAALIGN_WORD; - } - else if (is_spi(instance)){ - return DMA_MDATAALIGN_BYTE; - } - - return DMA_MDATAALIGN_HALFWORD; - } - static consteval inline uint32_t get_Mode(Instance instance, uint8_t i) { - if (is_spi(instance) || is_fmac(instance)){ - return DMA_NORMAL; - } - - return DMA_CIRCULAR; - } - - static consteval inline uint32_t get_Priority(Instance instance, uint8_t i) { - if (is_fmac(instance)){ - return DMA_PRIORITY_HIGH; - } - - return DMA_PRIORITY_LOW; - } - static consteval inline uint32_t get_FIFOMode(Instance instance, uint8_t i) { - if (is_fmac(instance)){ - return DMA_FIFOMODE_ENABLE; - } - return DMA_FIFOMODE_DISABLE; - } - - static consteval inline uint32_t get_FIFOThreshold(Instance instance, uint8_t i) { - if (is_spi(instance)){ - return DMA_FIFO_THRESHOLD_FULL; - } - return DMA_FIFO_THRESHOLD_HALFFULL; - } - - static consteval inline uint32_t get_MemBurst(Instance instance, uint8_t i) { - return DMA_MBURST_SINGLE; - } - - static consteval inline uint32_t get_PeriphBurst(Instance instance, uint8_t i) { - return DMA_PBURST_SINGLE; - } - - - template - static consteval std::array build(span instances){ - std::array cfgs{}; - - for (std::size_t i = 0; i < N; ++i){ - const auto &e = instances[i]; - - for (std::size_t j = 0; j < i; ++j){ - const auto &prev = instances[j]; - if (prev.instance == e.instance && prev.streams == e.streams){ - struct peripherial_already_inscribed {}; - throw peripherial_already_inscribed{}; - } - } - - std::array dma_handles; - for (std::size_t j = 0; j < e.count; j++){ - DMA_HandleTypeDef DMA_HandleStruct; - DMA_HandleStruct.Instance = e.streams[j]; - DMA_HandleStruct.Init.Request = get_Request(e.instance, j); - DMA_HandleStruct.Init.Direction = get_Direction(e.instance, j); - DMA_HandleStruct.Init.PeriphInc = get_PeriphInc(e.instance, j); - DMA_HandleStruct.Init.MemInc = get_MemInc(e.instance, j); - DMA_HandleStruct.Init.PeriphDataAlignment = get_PeriphDataAlignment(e.instance, j); - DMA_HandleStruct.Init.MemDataAlignment = get_MemDataAlignment(e.instance, j); - DMA_HandleStruct.Init.Mode = get_Mode(e.instance, j); - DMA_HandleStruct.Init.Priority = get_Priority(e.instance, j); - DMA_HandleStruct.Init.FIFOMode = get_FIFOMode(e.instance, j); - DMA_HandleStruct.Init.FIFOThreshold = get_FIFOThreshold(e.instance, j); - DMA_HandleStruct.Init.MemBurst = get_MemBurst(e.instance, j); - DMA_HandleStruct.Init.PeriphBurst = get_PeriphBurst(e.instance, j); - dma_handles[i] = DMA_HandleStruct; - } - cfgs[i].init_data = std::make_tuple(e.instance, dma_handles); - } - } - }; -} \ No newline at end of file +class DMA { +public: + enum Stream : uint8_t { + DMA1Stream0 = 11, + DMA1Stream1 = 12, + DMA1Stream2 = 13, + DMA1Stream3 = 14, + DMA1Stream4 = 15, + DMA1Stream5 = 16, + DMA1Stream6 = 17, + DMA2Stream0 = 56, + DMA2Stream1 = 57, + DMA2Stream2 = 58, + DMA2Stream3 = 59, + DMA2Stream4 = 60, + DMA2Stream5 = 68, + DMA2Stream6 = 69, + DMA2Stream7 = 70, + }; + + static void inscribe_stream(); + static void inscribe_stream(Stream dma_stream); + static void start(); + +private: + static vector available_streams; + static vector inscribed_streams; +}; \ No newline at end of file diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp new file mode 100644 index 000000000..09be6526a --- /dev/null +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -0,0 +1,374 @@ +#pragma once +#include "C++Utilities/CppUtils.hpp" +#include "stm32h7xx_hal.h" +#include "main.h" +#include "HALAL/Models/MPUManager/MPUManager.hpp" +#include +#include +#include +#include +#include + +using std::array; +using std::size_t; +using std::span; +using std::tuple; + +#define MAX_STREAMS 16 + + +namespace ST_LIB { + struct DMA_Domain { + using xTypeDef = std::variant< + ADC_TypeDef*, + I2C_TypeDef*, + SPI_TypeDef*, + FMAC_TypeDef* + >; + using xHandleDef = std::variant< + ADC_HandleTypeDef*, + I2C_HandleTypeDef*, + SPI_HandleTypeDef*, + FMAC_HandleTypeDef* + >; + + enum class Instance : uint8_t {adc1, adc2, adc3, + i2c1, i2c2, i2c3, i2c5, + spi1, spi2, spi3, spi4, spi5, + fmac}; + + enum class Stream : uint8_t {dma1_stream0, dma1_stream1, dma1_stream2, dma1_stream3, + dma1_stream4, dma1_stream5, dma1_stream6, dma1_stream7, + dma2_stream0, dma2_stream1, dma2_stream2, dma2_stream3, + dma2_stream4, dma2_stream5, dma2_stream6, dma2_stream7}; + + static inline xTypeDef instance_to_xTypeDef(Instance i) { + switch (i) { + case Instance::adc1: return ADC1; + case Instance::adc2: return ADC2; + case Instance::adc3: return ADC3; + + case Instance::i2c1: return I2C1; + case Instance::i2c2: return I2C2; + case Instance::i2c3: return I2C3; + case Instance::i2c5: return I2C5; + + case Instance::spi1: return SPI1; + case Instance::spi2: return SPI2; + case Instance::spi3: return SPI3; + case Instance::spi4: return SPI4; + case Instance::spi5: return SPI5; + + case Instance::fmac: return FMAC; + } + } + + static inline DMA_Stream_TypeDef* stream_to_DMA_StreamTypeDef(Stream s) { + switch (s) { + case Stream::dma1_stream0: return DMA1_Stream0; + case Stream::dma1_stream1: return DMA1_Stream1; + case Stream::dma1_stream2: return DMA1_Stream2; + case Stream::dma1_stream3: return DMA1_Stream3; + case Stream::dma1_stream4: return DMA1_Stream4; + case Stream::dma1_stream5: return DMA1_Stream5; + case Stream::dma1_stream6: return DMA1_Stream6; + case Stream::dma1_stream7: return DMA1_Stream7; + + case Stream::dma2_stream0: return DMA2_Stream0; + case Stream::dma2_stream1: return DMA2_Stream1; + case Stream::dma2_stream2: return DMA2_Stream2; + case Stream::dma2_stream3: return DMA2_Stream3; + case Stream::dma2_stream4: return DMA2_Stream4; + case Stream::dma2_stream5: return DMA2_Stream5; + case Stream::dma2_stream6: return DMA2_Stream6; + case Stream::dma2_stream7: return DMA2_Stream7; + } + } + + struct Entry { + Instance instance; + std::array streams{}; + std::array irqn {}; + uint8_t count = 0; + }; + + struct DMA{ + using domain = DMA_Domain; + + Entry e; + + template + consteval DMA(Instance instance) : e(instance) { + static_assert(sizeof...(Ss) <= 3, "Máximo 3 streams"); + size_t i = 0; + ((e.streams[i++] = Ss), ...); + e.count = i; + for (size_t j = 0; j < i; j++){ + e.irqn[j] = get_irqn(e.streams[j]); + } + } + + template consteval void inscribe(Ctx &ctx) const { + ctx.template add(e); + } + }; + + // NO se para que quiero esto + static constexpr std::size_t max_instances {MAX_STREAMS}; + static_assert(max_instances > 0, "The number of instances must be greater than 0"); + + + + static inline IRQn_Type get_irqn(Stream stream) { + if (stream == Stream::dma1_stream0) return DMA1_Stream0_IRQn; + else if (stream == Stream::dma1_stream1) return DMA1_Stream1_IRQn; + else if (stream == Stream::dma1_stream2) return DMA1_Stream2_IRQn; + else if (stream == Stream::dma1_stream3) return DMA1_Stream3_IRQn; + else if (stream == Stream::dma1_stream4) return DMA1_Stream4_IRQn; + else if (stream == Stream::dma1_stream5) return DMA1_Stream5_IRQn; + else if (stream == Stream::dma1_stream6) return DMA1_Stream6_IRQn; + else if (stream == Stream::dma1_stream7) return DMA1_Stream7_IRQn; + + else if (stream == Stream::dma2_stream0) return DMA2_Stream0_IRQn; + else if (stream == Stream::dma2_stream1) return DMA2_Stream1_IRQn; + else if (stream == Stream::dma2_stream2) return DMA2_Stream2_IRQn; + else if (stream == Stream::dma2_stream3) return DMA2_Stream3_IRQn; + else if (stream == Stream::dma2_stream4) return DMA2_Stream4_IRQn; + else if (stream == Stream::dma2_stream5) return DMA2_Stream5_IRQn; + else if (stream == Stream::dma2_stream6) return DMA2_Stream6_IRQn; + else if (stream == Stream::dma2_stream7) return DMA2_Stream7_IRQn; + else ErrorHandler("Unknown DMA stream"); + return DMA1_Stream0_IRQn; // Nunca se alcanza + } + + // Si quitas el auto peta todo + static consteval inline bool is_one_of(Instance instance, auto... bases) { + return ((instance == bases) || ...); + } + + static consteval inline bool is_spi(Instance instance) { + return is_one_of(instance, Instance::spi1, Instance::spi2, + Instance::spi3, Instance::spi4, Instance::spi5); + } + + static consteval inline bool is_i2c(Instance instance) { + return is_one_of(instance, Instance::i2c1, Instance::i2c2, + Instance::i2c3, Instance::i2c5); + } + + static consteval inline bool is_adc(Instance instance) { + return is_one_of(instance, Instance::adc1, Instance::adc2, Instance::adc3); + } + + static consteval inline bool is_fmac(Instance instance) { + return instance == Instance::fmac; + } + + static consteval inline uint32_t get_Request(Instance instance, uint8_t i) { + if (instance == Instance::adc1) return DMA_REQUEST_ADC1; + if (instance == Instance::adc2) return DMA_REQUEST_ADC2; + if (instance == Instance::adc3) return DMA_REQUEST_ADC3; + + if (instance == Instance::i2c1 && i == 0) return DMA_REQUEST_I2C1_RX; + if (instance == Instance::i2c1 && i == 1) return DMA_REQUEST_I2C1_TX; + if (instance == Instance::i2c2 && i == 0) return DMA_REQUEST_I2C2_RX; + if (instance == Instance::i2c2 && i == 1) return DMA_REQUEST_I2C2_TX; + if (instance == Instance::i2c3 && i == 0) return DMA_REQUEST_I2C3_RX; + if (instance == Instance::i2c3 && i == 1) return DMA_REQUEST_I2C3_TX; + if (instance == Instance::i2c5 && i == 0) return DMA_REQUEST_I2C5_RX; + if (instance == Instance::i2c5 && i == 1) return DMA_REQUEST_I2C5_TX; + + if (instance == Instance::spi1 && i == 0) return DMA_REQUEST_SPI1_RX; + if (instance == Instance::spi1 && i == 1) return DMA_REQUEST_SPI1_TX; + if (instance == Instance::spi2 && i == 0) return DMA_REQUEST_SPI2_RX; + if (instance == Instance::spi2 && i == 1) return DMA_REQUEST_SPI2_TX; + if (instance == Instance::spi3 && i == 0) return DMA_REQUEST_SPI3_RX; + if (instance == Instance::spi3 && i == 1) return DMA_REQUEST_SPI3_TX; + if (instance == Instance::spi4 && i == 0) return DMA_REQUEST_SPI4_RX; + if (instance == Instance::spi4 && i == 1) return DMA_REQUEST_SPI4_TX; + if (instance == Instance::spi5 && i == 0) return DMA_REQUEST_SPI5_RX; + if (instance == Instance::spi5 && i == 1) return DMA_REQUEST_SPI5_TX; + + if (instance == Instance::fmac && i == 0) return DMA_REQUEST_MEM2MEM; + if (instance == Instance::fmac && i == 1) return DMA_REQUEST_FMAC_WRITE; + if (instance == Instance::fmac && i == 2) return DMA_REQUEST_FMAC_READ; + + ErrorHandler("Invalid DMA request configuration"); + return 0; + } + + + static consteval inline uint32_t get_Direction(Instance instance, uint8_t i) { + if (is_fmac(instance) && i == 0){ + return DMA_MEMORY_TO_MEMORY; + } + else if ((is_i2c(instance) && i == 1) || + (is_spi(instance) && i == 1) || + (is_fmac(instance) && i == 1)){ + return DMA_MEMORY_TO_PERIPH; + } + return DMA_PERIPH_TO_MEMORY; + } + + static consteval inline uint32_t get_PeriphInc(Instance instance, uint8_t i) { + if (is_fmac(instance) && i == 0){ + return DMA_PINC_ENABLE; + } + return DMA_PINC_DISABLE; + } + static consteval inline uint32_t get_MemInc(Instance instance, uint8_t i) { + if (is_fmac(instance) && i == 0){ + return DMA_MINC_DISABLE; + } + return DMA_MINC_ENABLE; + } + + static consteval inline uint32_t get_PeriphDataAlignment(Instance instance, uint8_t i) { + if (is_i2c(instance)){ + return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes + } + else if (is_spi(instance)){ + return DMA_PDATAALIGN_BYTE; + } + + return DMA_PDATAALIGN_HALFWORD; + } + + static consteval inline uint32_t get_MemDataAlignment(Instance instance, uint8_t i) { + if (is_i2c(instance)){ + return DMA_MDATAALIGN_WORD; + } + else if (is_spi(instance)){ + return DMA_MDATAALIGN_BYTE; + } + + return DMA_MDATAALIGN_HALFWORD; + } + static consteval inline uint32_t get_Mode(Instance instance, uint8_t i) { + if (is_spi(instance) || is_fmac(instance)){ + return DMA_NORMAL; + } + + return DMA_CIRCULAR; + } + + static consteval inline uint32_t get_Priority(Instance instance, uint8_t i) { + if (is_fmac(instance)){ + return DMA_PRIORITY_HIGH; + } + + return DMA_PRIORITY_LOW; + } + static consteval inline uint32_t get_FIFOMode(Instance instance, uint8_t i) { + if (is_fmac(instance)){ + return DMA_FIFOMODE_ENABLE; + } + return DMA_FIFOMODE_DISABLE; + } + + static consteval inline uint32_t get_FIFOThreshold(Instance instance, uint8_t i) { + if (is_spi(instance)){ + return DMA_FIFO_THRESHOLD_FULL; + } + return DMA_FIFO_THRESHOLD_HALFFULL; + } + + static consteval inline uint32_t get_MemBurst(Instance instance, uint8_t i) { + return DMA_MBURST_SINGLE; + } + + static consteval inline uint32_t get_PeriphBurst(Instance instance, uint8_t i) { + return DMA_PBURST_SINGLE; + } + + struct Config { + std::tuple, + std::array, + std::array> + init_data{}; + }; + + template + static consteval std::array build(span instances){ + std::array cfgs{}; + + for (std::size_t i = 0; i < N; ++i){ + const auto &e = instances[i]; + + for (std::size_t j = 0; j < i; ++j){ + const auto &prev = instances[j]; + if (prev.instance == e.instance && prev.streams == e.streams){ + struct peripherial_already_inscribed {}; + throw peripherial_already_inscribed{}; + } + } + + std::array dma_handles; + for (std::size_t j = 0; j < e.count; j++){ + DMA_InitTypeDef DMA_InitStruct; + //DMA_InitStruct.Instance = e.streams[j]; + DMA_InitStruct.Request = get_Request(e.instance, j); + DMA_InitStruct.Direction = get_Direction(e.instance, j); + DMA_InitStruct.PeriphInc = get_PeriphInc(e.instance, j); + DMA_InitStruct.MemInc = get_MemInc(e.instance, j); + DMA_InitStruct.PeriphDataAlignment = get_PeriphDataAlignment(e.instance, j); + DMA_InitStruct.MemDataAlignment = get_MemDataAlignment(e.instance, j); + DMA_InitStruct.Mode = get_Mode(e.instance, j); + DMA_InitStruct.Priority = get_Priority(e.instance, j); + DMA_InitStruct.FIFOMode = get_FIFOMode(e.instance, j); + DMA_InitStruct.FIFOThreshold = get_FIFOThreshold(e.instance, j); + DMA_InitStruct.MemBurst = get_MemBurst(e.instance, j); + DMA_InitStruct.PeriphBurst = get_PeriphBurst(e.instance, j); + + dma_handles[j] = DMA_InitStruct; + } + + cfgs[i].init_data = std::make_tuple(e.instance, dma_handles, e.streams, e.irqn); + } + return cfgs; + } + + template struct Init { + static inline std::array dma{}; + + static void init(std::span cfgs) { + static_assert(N > 0); + __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + for (std::size_t i = 0; i < N; ++i) { + const auto &e = cfgs[i]; + auto [instance, dma_handles, streams, irqn] = e.init_data; + + for (std::size_t j = 0; j < 3; j++){ + // Con la instancia necesito que me de el Handle del periferico + + dma[i].Instance = streams[j]; + dma[i].Init = dma_handles[j]; + if (HAL_DMA_Init(dma[i]) != HAL_OK) { + ErrorHandler("DMA Init failed"); + } + if (is_spi(instance)) { + auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; + } + else if (is_i2c(instance)) { + auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; + } + else if (is_adc(instance)) { + auto member = &ADC_HandleTypeDef::DMA_Handle; + } + else if (is_fmac(instance)) { + auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : + (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : + &FMAC_HandleTypeDef::hdmaOut; + } + //Linker + __HAL_LINKDMA(handle, member, dma[i]); + HAL_NVIC_SetPriority(irqn, 0, 0); + HAL_NVIC_EnableIRQ(irqn); + } + } + } + }; + }; +} \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA-old.cpp b/Src/HALAL/Models/DMA/DMA-old.cpp new file mode 100644 index 000000000..db3768088 --- /dev/null +++ b/Src/HALAL/Models/DMA/DMA-old.cpp @@ -0,0 +1,18 @@ +#include "HALAL/Models/DMA/DMA.hpp" + +void DMA::start() { + __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + for (uint8_t i = 0; i < inscribed_index; i++) { + auto& [periph, dma, linker, irq] = inscribed_streams[i]; + + if (HAL_DMA_Init(dma) != HAL_OK) { + ErrorHandler("DMA Init failed"); + } + + linker(dma); + + HAL_NVIC_SetPriority(irq, 0, 0); + HAL_NVIC_EnableIRQ(irq); + } +} \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp index db3768088..2fea33c37 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -1,18 +1,41 @@ +/* + * DMA.cpp + * + * Created on: 10 dic. 2022 + * Author: aleja + */ + #include "HALAL/Models/DMA/DMA.hpp" +#include "ErrorHandler/ErrorHandler.hpp" + +vector DMA::available_streams = { + DMA1Stream0, DMA1Stream1, DMA1Stream2, DMA1Stream3, DMA1Stream4, DMA1Stream5, DMA1Stream6, DMA2Stream0, DMA2Stream1, DMA2Stream2, DMA2Stream3, DMA2Stream4, DMA2Stream5, DMA2Stream6, DMA2Stream7, +}; + +vector DMA::inscribed_streams = {}; + +void DMA::inscribe_stream() { + if (available_streams.empty()) { + ErrorHandler("There are not any DMA Streams availables"); + return; + } + inscribed_streams.push_back(available_streams.back()); + available_streams.pop_back(); +} + +void DMA::inscribe_stream(Stream dma_stream) { + if (std::find(available_streams.begin(), available_streams.end(), dma_stream) == available_streams.end()) { + ErrorHandler("The DMA stream %d is not available", dma_stream); + return; + } + inscribed_streams.push_back(dma_stream); +} void DMA::start() { - __HAL_RCC_DMA1_CLK_ENABLE(); - __HAL_RCC_DMA2_CLK_ENABLE(); - for (uint8_t i = 0; i < inscribed_index; i++) { - auto& [periph, dma, linker, irq] = inscribed_streams[i]; - - if (HAL_DMA_Init(dma) != HAL_OK) { - ErrorHandler("DMA Init failed"); - } - - linker(dma); - - HAL_NVIC_SetPriority(irq, 0, 0); - HAL_NVIC_EnableIRQ(irq); - } + __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + for (Stream dma_stream : inscribed_streams) { + HAL_NVIC_SetPriority( (IRQn_Type)dma_stream, 0, 0); + HAL_NVIC_EnableIRQ( (IRQn_Type)dma_stream); + } } \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA2.cpp b/Src/HALAL/Models/DMA/DMA2.cpp new file mode 100644 index 000000000..e69de29bb From 9a029ecef1c070d2ab904b414cd1f147cddc90a6 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Wed, 10 Dec 2025 10:19:26 +0100 Subject: [PATCH 051/109] entry, build e instances_ ahora se rigen por stream y no instancia (la cual se puede repetir). cambios en sus constructores y nuevo metodo (setDMAHandle) para poder pasar el handle desde el periferico --- Inc/HALAL/Models/DMA/DMA2.hpp | 228 +++++++++++++++++++++++----------- 1 file changed, 155 insertions(+), 73 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index 09be6526a..c1af1c767 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -87,29 +87,38 @@ namespace ST_LIB { struct Entry { Instance instance; - std::array streams{}; - std::array irqn {}; - uint8_t count = 0; + Stream stream; + IRQn_Type irqn; + uint8_t id; }; - - struct DMA{ + + struct DMA { using domain = DMA_Domain; - Entry e; + std::array e{}; template - consteval DMA(Instance instance) : e(instance) { + consteval DMA(Instance instance) { static_assert(sizeof...(Ss) <= 3, "Máximo 3 streams"); - size_t i = 0; - ((e.streams[i++] = Ss), ...); - e.count = i; - for (size_t j = 0; j < i; j++){ - e.irqn[j] = get_irqn(e.streams[j]); + + Stream streams[] = { Ss... }; + constexpr uint8_t n = sizeof...(Ss); + + for (uint8_t j = 0; j < n; j++) { + e[j].instance = instance; + e[j].stream = streams[j]; + e[j].irqn = get_irqn(streams[j]); + e[j].id = j; } + } - template consteval void inscribe(Ctx &ctx) const { - ctx.template add(e); + template + consteval void inscribe(Ctx &ctx) const { + for (const auto& entry : e) { + if (entry.stream != Stream{}) + ctx.template add(entry); + } } }; @@ -142,25 +151,25 @@ namespace ST_LIB { } // Si quitas el auto peta todo - static consteval inline bool is_one_of(Instance instance, auto... bases) { + static constexpr inline bool is_one_of(Instance instance, auto... bases) { return ((instance == bases) || ...); } - static consteval inline bool is_spi(Instance instance) { + static constexpr inline bool is_spi(Instance instance) { return is_one_of(instance, Instance::spi1, Instance::spi2, Instance::spi3, Instance::spi4, Instance::spi5); } - static consteval inline bool is_i2c(Instance instance) { + static constexpr inline bool is_i2c(Instance instance) { return is_one_of(instance, Instance::i2c1, Instance::i2c2, Instance::i2c3, Instance::i2c5); } - static consteval inline bool is_adc(Instance instance) { + static constexpr inline bool is_adc(Instance instance) { return is_one_of(instance, Instance::adc1, Instance::adc2, Instance::adc3); } - static consteval inline bool is_fmac(Instance instance) { + static constexpr inline bool is_fmac(Instance instance) { return instance == Instance::fmac; } @@ -283,9 +292,10 @@ namespace ST_LIB { struct Config { std::tuple, - std::array, - std::array> + DMA_InitTypeDef, + Stream, + IRQn_Type, + uint8_t> init_data{}; }; @@ -296,41 +306,130 @@ namespace ST_LIB { for (std::size_t i = 0; i < N; ++i){ const auto &e = instances[i]; + // No entiendo como funciona esto, pero esta copiado tal cual + // Yo creo que a mi no me sirve porque mis instancias si que estan repetidas for (std::size_t j = 0; j < i; ++j){ const auto &prev = instances[j]; - if (prev.instance == e.instance && prev.streams == e.streams){ + if (prev.instance == e.instance && prev.stream == e.stream){ struct peripherial_already_inscribed {}; throw peripherial_already_inscribed{}; } } - - std::array dma_handles; - for (std::size_t j = 0; j < e.count; j++){ - DMA_InitTypeDef DMA_InitStruct; - //DMA_InitStruct.Instance = e.streams[j]; - DMA_InitStruct.Request = get_Request(e.instance, j); - DMA_InitStruct.Direction = get_Direction(e.instance, j); - DMA_InitStruct.PeriphInc = get_PeriphInc(e.instance, j); - DMA_InitStruct.MemInc = get_MemInc(e.instance, j); - DMA_InitStruct.PeriphDataAlignment = get_PeriphDataAlignment(e.instance, j); - DMA_InitStruct.MemDataAlignment = get_MemDataAlignment(e.instance, j); - DMA_InitStruct.Mode = get_Mode(e.instance, j); - DMA_InitStruct.Priority = get_Priority(e.instance, j); - DMA_InitStruct.FIFOMode = get_FIFOMode(e.instance, j); - DMA_InitStruct.FIFOThreshold = get_FIFOThreshold(e.instance, j); - DMA_InitStruct.MemBurst = get_MemBurst(e.instance, j); - DMA_InitStruct.PeriphBurst = get_PeriphBurst(e.instance, j); - - dma_handles[j] = DMA_InitStruct; - } - - cfgs[i].init_data = std::make_tuple(e.instance, dma_handles, e.streams, e.irqn); + + DMA_InitTypeDef DMA_InitStruct; + DMA_InitStruct.Request = get_Request(e.instance, e.id); + DMA_InitStruct.Direction = get_Direction(e.instance, e.id); + DMA_InitStruct.PeriphInc = get_PeriphInc(e.instance, e.id); + DMA_InitStruct.MemInc = get_MemInc(e.instance, e.id); + DMA_InitStruct.PeriphDataAlignment = get_PeriphDataAlignment(e.instance, e.id); + DMA_InitStruct.MemDataAlignment = get_MemDataAlignment(e.instance, e.id); + DMA_InitStruct.Mode = get_Mode(e.instance, e.id); + DMA_InitStruct.Priority = get_Priority(e.instance, e.id); + DMA_InitStruct.FIFOMode = get_FIFOMode(e.instance, e.id); + DMA_InitStruct.FIFOThreshold = get_FIFOThreshold(e.instance, e.id); + DMA_InitStruct.MemBurst = get_MemBurst(e.instance, e.id); + DMA_InitStruct.PeriphBurst = get_PeriphBurst(e.instance, e.id); + + + cfgs[i].init_data = std::make_tuple(e.instance, + DMA_InitStruct, + e.stream, + e.irqn, + e.id); } return cfgs; } + + struct Instances_ { + xTypeDef instance; + DMA_HandleTypeDef dma; + IRQn_Type irqn; + uint8_t id; + + void setDMAHandle(xHandleDef handle) { + std::visit([&](auto* real_instance){ + std::visit([&](auto* real_handle){ + using T = std::remove_pointer_t; + // --------------------------- + // ADC + // --------------------------- + if constexpr (std::is_same_v) + { + // ADC solo tiene un stream + __HAL_LINKDMA(real_handle, DMA_Handle, dma); + + HAL_NVIC_SetPriority(irqn, 0, 0); + HAL_NVIC_EnableIRQ(irqn); + return; + } + + // --------------------------- + // I2C + // id = 0 → RX + // id = 1 → TX + // --------------------------- + else if constexpr (std::is_same_v) + { + if (id == 0) + __HAL_LINKDMA(real_handle, hdmarx, dma); + else + __HAL_LINKDMA(real_handle, hdmatx, dma); + + HAL_NVIC_SetPriority(irqn, 0, 0); + HAL_NVIC_EnableIRQ(irqn); + return; + } + + // --------------------------- + // SPI + // id = 0 → RX + // id = 1 → TX + // --------------------------- + else if constexpr (std::is_same_v) + { + if (id == 0) + __HAL_LINKDMA(real_handle, hdmarx, dma); + else + __HAL_LINKDMA(real_handle, hdmatx, dma); + + HAL_NVIC_SetPriority(irqn, 0, 0); + HAL_NVIC_EnableIRQ(irqn); + return; + } + + // --------------------------- + // FMAC + // id = 0 → Preload + // id = 1 → In + // id = 2 → Out + // --------------------------- + else if constexpr (std::is_same_v) + { + if (id == 0) + __HAL_LINKDMA(real_handle, hdmaPreload, dma); + else if (id == 1) + __HAL_LINKDMA(real_handle, hdmaIn, dma); + else + __HAL_LINKDMA(real_handle, hdmaOut, dma); + + HAL_NVIC_SetPriority(irqn, 0, 0); + HAL_NVIC_EnableIRQ(irqn); + return; + } + + else { + ErrorHandler("Unsupported peripheral type in setDMAHandle"); + } + + }, handle); + + }, instance); + } + }; + template struct Init { - static inline std::array dma{}; + static inline std::array instances{}; static void init(std::span cfgs) { static_assert(N > 0); @@ -338,34 +437,17 @@ namespace ST_LIB { __HAL_RCC_DMA2_CLK_ENABLE(); for (std::size_t i = 0; i < N; ++i) { const auto &e = cfgs[i]; - auto [instance, dma_handles, streams, irqn] = e.init_data; + auto [instance, dma_init, stream, irqn, id] = e.init_data; - for (std::size_t j = 0; j < 3; j++){ - // Con la instancia necesito que me de el Handle del periferico - - dma[i].Instance = streams[j]; - dma[i].Init = dma_handles[j]; - if (HAL_DMA_Init(dma[i]) != HAL_OK) { - ErrorHandler("DMA Init failed"); - } - if (is_spi(instance)) { - auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; - } - else if (is_i2c(instance)) { - auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; - } - else if (is_adc(instance)) { - auto member = &ADC_HandleTypeDef::DMA_Handle; - } - else if (is_fmac(instance)) { - auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : - (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : - &FMAC_HandleTypeDef::hdmaOut; - } - //Linker - __HAL_LINKDMA(handle, member, dma[i]); - HAL_NVIC_SetPriority(irqn, 0, 0); - HAL_NVIC_EnableIRQ(irqn); + instances[i].instance = instance_to_xTypeDef(instance); + instances[i].dma.Instance = stream_to_DMA_StreamTypeDef(stream); + instances[i].dma.Init = dma_init; + instances[i].irqn = irqn; + instances[i].id = id; + + // No estoy seguro de que esto tenga que ir aqui + if (HAL_DMA_Init(instances[i].dma) != HAL_OK) { + ErrorHandler("DMA Init failed"); } } } From 2f65b2380350dcf2201d8232c3a1e29cf78059e5 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Wed, 10 Dec 2025 12:55:27 +0100 Subject: [PATCH 052/109] se me habia olvidado desreferenciar --- Inc/HALAL/Models/DMA/DMA2.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index c1af1c767..258230e70 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -125,8 +125,6 @@ namespace ST_LIB { // NO se para que quiero esto static constexpr std::size_t max_instances {MAX_STREAMS}; static_assert(max_instances > 0, "The number of instances must be greater than 0"); - - static inline IRQn_Type get_irqn(Stream stream) { if (stream == Stream::dma1_stream0) return DMA1_Stream0_IRQn; @@ -206,7 +204,6 @@ namespace ST_LIB { return 0; } - static consteval inline uint32_t get_Direction(Instance instance, uint8_t i) { if (is_fmac(instance) && i == 0){ return DMA_MEMORY_TO_MEMORY; @@ -225,6 +222,7 @@ namespace ST_LIB { } return DMA_PINC_DISABLE; } + static consteval inline uint32_t get_MemInc(Instance instance, uint8_t i) { if (is_fmac(instance) && i == 0){ return DMA_MINC_DISABLE; @@ -446,7 +444,7 @@ namespace ST_LIB { instances[i].id = id; // No estoy seguro de que esto tenga que ir aqui - if (HAL_DMA_Init(instances[i].dma) != HAL_OK) { + if (HAL_DMA_Init(&instances[i].dma) != HAL_OK) { ErrorHandler("DMA Init failed"); } } From 04fb46b63415e75561198c9ae8e76158f564f586 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Thu, 11 Dec 2025 18:29:59 +0100 Subject: [PATCH 053/109] modificar STLIB.hpp para meter el contexto de la DMA --- Inc/ST-LIB.hpp | 8 +++++++- Src/HALAL/Services/ADC/ADC.cpp | 3 +-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Inc/ST-LIB.hpp b/Inc/ST-LIB.hpp index 32fb54814..69b5a321c 100644 --- a/Inc/ST-LIB.hpp +++ b/Inc/ST-LIB.hpp @@ -71,7 +71,7 @@ template struct BuildCtx { }; using DomainsCtx = BuildCtx; + DigitalInputDomain, DMA_Domain /*, ADCDomain, PWMDomain, ...*/>; template struct Board { static consteval auto build_ctx() { @@ -90,12 +90,14 @@ template struct Board { constexpr std::size_t gpioN = domain_size(); constexpr std::size_t doutN = domain_size(); constexpr std::size_t dinN = domain_size(); + constexpr std::size_t dmaN = domain_size(); // ... struct ConfigBundle { std::array gpio_cfgs; std::array dout_cfgs; std::array din_cfgs; + std::array dma_cfgs; // ... }; @@ -106,6 +108,8 @@ template struct Board { ctx.template span()), .din_cfgs = DigitalInputDomain::template build( ctx.template span()), + .dma_cfgs = DMA_Domain::template build( + ctx.template span()), // ... }; } @@ -116,6 +120,7 @@ template struct Board { constexpr std::size_t gpioN = domain_size(); constexpr std::size_t doutN = domain_size(); constexpr std::size_t dinN = domain_size(); + constexpr std::size_t dmaN = domain_size(); // ... GPIODomain::Init::init(cfg.gpio_cfgs); @@ -123,6 +128,7 @@ template struct Board { GPIODomain::Init::instances); DigitalInputDomain::Init::init(cfg.din_cfgs, GPIODomain::Init::instances); + DMA_Domain::Init::init(cfg.dma_cfgs); // ... } diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index f44730324..4d23110b8 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -42,8 +42,7 @@ uint8_t ADC::inscribe(Pin pin) { InitData& init_data = active_instances[id_counter].peripheral->init_data; - - DMA::inscribe_stream(active_instances[id_counter].peripheral->handle); + active_instances[id_counter].rank = init_data.channels.size(); init_data.channels.push_back(active_instances[id_counter].channel); return id_counter++; From 1503056c7a08cd25efa9837fd2e59f96a01ae3cd Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Sun, 14 Dec 2025 19:24:14 +0100 Subject: [PATCH 054/109] eliminar que reciba el handle --- Inc/HALAL/Models/DMA/DMA2.hpp | 167 +++++++++++++++++----------------- 1 file changed, 85 insertions(+), 82 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index 258230e70..c5357fba9 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -339,90 +339,91 @@ namespace ST_LIB { } struct Instances_ { - xTypeDef instance; DMA_HandleTypeDef dma; - IRQn_Type irqn; uint8_t id; - void setDMAHandle(xHandleDef handle) { - std::visit([&](auto* real_instance){ - std::visit([&](auto* real_handle){ - using T = std::remove_pointer_t; - // --------------------------- - // ADC - // --------------------------- - if constexpr (std::is_same_v) - { - // ADC solo tiene un stream - __HAL_LINKDMA(real_handle, DMA_Handle, dma); - - HAL_NVIC_SetPriority(irqn, 0, 0); - HAL_NVIC_EnableIRQ(irqn); - return; - } - - // --------------------------- - // I2C - // id = 0 → RX - // id = 1 → TX - // --------------------------- - else if constexpr (std::is_same_v) - { - if (id == 0) - __HAL_LINKDMA(real_handle, hdmarx, dma); - else - __HAL_LINKDMA(real_handle, hdmatx, dma); - - HAL_NVIC_SetPriority(irqn, 0, 0); - HAL_NVIC_EnableIRQ(irqn); - return; - } - - // --------------------------- - // SPI - // id = 0 → RX - // id = 1 → TX - // --------------------------- - else if constexpr (std::is_same_v) - { - if (id == 0) - __HAL_LINKDMA(real_handle, hdmarx, dma); - else - __HAL_LINKDMA(real_handle, hdmatx, dma); - - HAL_NVIC_SetPriority(irqn, 0, 0); - HAL_NVIC_EnableIRQ(irqn); - return; - } - - // --------------------------- - // FMAC - // id = 0 → Preload - // id = 1 → In - // id = 2 → Out - // --------------------------- - else if constexpr (std::is_same_v) - { - if (id == 0) - __HAL_LINKDMA(real_handle, hdmaPreload, dma); - else if (id == 1) - __HAL_LINKDMA(real_handle, hdmaIn, dma); - else - __HAL_LINKDMA(real_handle, hdmaOut, dma); - - HAL_NVIC_SetPriority(irqn, 0, 0); - HAL_NVIC_EnableIRQ(irqn); - return; - } - - else { - ErrorHandler("Unsupported peripheral type in setDMAHandle"); - } - - }, handle); - - }, instance); + void start(uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength){ + HAL_DMA_Start_IT(&dma, SrcAddress, DstAddress, DataLength); } + // void setDMAHandle(xHandleDef handle) { + // std::visit([&](auto* real_instance){ + // std::visit([&](auto* real_handle){ + // using T = std::remove_pointer_t; + // // --------------------------- + // // ADC + // // --------------------------- + // if constexpr (std::is_same_v) + // { + // // ADC solo tiene un stream + // __HAL_LINKDMA(real_handle, DMA_Handle, dma); + + // HAL_NVIC_SetPriority(irqn, 0, 0); + // HAL_NVIC_EnableIRQ(irqn); + // return; + // } + + // // --------------------------- + // // I2C + // // id = 0 → RX + // // id = 1 → TX + // // --------------------------- + // else if constexpr (std::is_same_v) + // { + // if (id == 0) + // __HAL_LINKDMA(real_handle, hdmarx, dma); + // else + // __HAL_LINKDMA(real_handle, hdmatx, dma); + + // HAL_NVIC_SetPriority(irqn, 0, 0); + // HAL_NVIC_EnableIRQ(irqn); + // return; + // } + + // // --------------------------- + // // SPI + // // id = 0 → RX + // // id = 1 → TX + // // --------------------------- + // else if constexpr (std::is_same_v) + // { + // if (id == 0) + // __HAL_LINKDMA(real_handle, hdmarx, dma); + // else + // __HAL_LINKDMA(real_handle, hdmatx, dma); + + // HAL_NVIC_SetPriority(irqn, 0, 0); + // HAL_NVIC_EnableIRQ(irqn); + // return; + // } + + // // --------------------------- + // // FMAC + // // id = 0 → Preload + // // id = 1 → In + // // id = 2 → Out + // // --------------------------- + // else if constexpr (std::is_same_v) + // { + // if (id == 0) + // __HAL_LINKDMA(real_handle, hdmaPreload, dma); + // else if (id == 1) + // __HAL_LINKDMA(real_handle, hdmaIn, dma); + // else + // __HAL_LINKDMA(real_handle, hdmaOut, dma); + + // HAL_NVIC_SetPriority(irqn, 0, 0); + // HAL_NVIC_EnableIRQ(irqn); + // return; + // } + + // else { + // ErrorHandler("Unsupported peripheral type in setDMAHandle"); + // } + + // }, handle); + + // }, instance); + // } }; @@ -437,16 +438,18 @@ namespace ST_LIB { const auto &e = cfgs[i]; auto [instance, dma_init, stream, irqn, id] = e.init_data; - instances[i].instance = instance_to_xTypeDef(instance); instances[i].dma.Instance = stream_to_DMA_StreamTypeDef(stream); instances[i].dma.Init = dma_init; - instances[i].irqn = irqn; instances[i].id = id; // No estoy seguro de que esto tenga que ir aqui if (HAL_DMA_Init(&instances[i].dma) != HAL_OK) { ErrorHandler("DMA Init failed"); } + else{ + HAL_NVIC_SetPriority(irqn, 0, 0); + HAL_NVIC_EnableIRQ(irqn); + } } } }; From 7974f64d1fdc06b955f75a7c09c70cf2a827f6f9 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Sun, 14 Dec 2025 19:30:02 +0100 Subject: [PATCH 055/109] eliminar que reciba el handle --- Inc/HALAL/Models/DMA/DMA2.hpp | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index c5357fba9..1b1345bac 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -19,18 +19,6 @@ using std::tuple; namespace ST_LIB { struct DMA_Domain { - using xTypeDef = std::variant< - ADC_TypeDef*, - I2C_TypeDef*, - SPI_TypeDef*, - FMAC_TypeDef* - >; - using xHandleDef = std::variant< - ADC_HandleTypeDef*, - I2C_HandleTypeDef*, - SPI_HandleTypeDef*, - FMAC_HandleTypeDef* - >; enum class Instance : uint8_t {adc1, adc2, adc3, i2c1, i2c2, i2c3, i2c5, @@ -42,26 +30,6 @@ namespace ST_LIB { dma2_stream0, dma2_stream1, dma2_stream2, dma2_stream3, dma2_stream4, dma2_stream5, dma2_stream6, dma2_stream7}; - static inline xTypeDef instance_to_xTypeDef(Instance i) { - switch (i) { - case Instance::adc1: return ADC1; - case Instance::adc2: return ADC2; - case Instance::adc3: return ADC3; - - case Instance::i2c1: return I2C1; - case Instance::i2c2: return I2C2; - case Instance::i2c3: return I2C3; - case Instance::i2c5: return I2C5; - - case Instance::spi1: return SPI1; - case Instance::spi2: return SPI2; - case Instance::spi3: return SPI3; - case Instance::spi4: return SPI4; - case Instance::spi5: return SPI5; - - case Instance::fmac: return FMAC; - } - } static inline DMA_Stream_TypeDef* stream_to_DMA_StreamTypeDef(Stream s) { switch (s) { @@ -340,7 +308,6 @@ namespace ST_LIB { struct Instances_ { DMA_HandleTypeDef dma; - uint8_t id; void start(uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength){ HAL_DMA_Start_IT(&dma, SrcAddress, DstAddress, DataLength); @@ -440,9 +407,7 @@ namespace ST_LIB { instances[i].dma.Instance = stream_to_DMA_StreamTypeDef(stream); instances[i].dma.Init = dma_init; - instances[i].id = id; - // No estoy seguro de que esto tenga que ir aqui if (HAL_DMA_Init(&instances[i].dma) != HAL_OK) { ErrorHandler("DMA Init failed"); } From 38778afe49f34931648b483baaf0978aeae54696 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Sun, 14 Dec 2025 19:37:28 +0100 Subject: [PATCH 056/109] sacar streams fuera del struct --- Inc/HALAL/Models/DMA/DMA2.hpp | 82 +---------------------------------- 1 file changed, 2 insertions(+), 80 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index 1b1345bac..fa65bd22e 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -60,12 +60,13 @@ namespace ST_LIB { uint8_t id; }; + template struct DMA { using domain = DMA_Domain; std::array e{}; - template + consteval DMA(Instance instance) { static_assert(sizeof...(Ss) <= 3, "Máximo 3 streams"); @@ -312,85 +313,6 @@ namespace ST_LIB { void start(uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength){ HAL_DMA_Start_IT(&dma, SrcAddress, DstAddress, DataLength); } - // void setDMAHandle(xHandleDef handle) { - // std::visit([&](auto* real_instance){ - // std::visit([&](auto* real_handle){ - // using T = std::remove_pointer_t; - // // --------------------------- - // // ADC - // // --------------------------- - // if constexpr (std::is_same_v) - // { - // // ADC solo tiene un stream - // __HAL_LINKDMA(real_handle, DMA_Handle, dma); - - // HAL_NVIC_SetPriority(irqn, 0, 0); - // HAL_NVIC_EnableIRQ(irqn); - // return; - // } - - // // --------------------------- - // // I2C - // // id = 0 → RX - // // id = 1 → TX - // // --------------------------- - // else if constexpr (std::is_same_v) - // { - // if (id == 0) - // __HAL_LINKDMA(real_handle, hdmarx, dma); - // else - // __HAL_LINKDMA(real_handle, hdmatx, dma); - - // HAL_NVIC_SetPriority(irqn, 0, 0); - // HAL_NVIC_EnableIRQ(irqn); - // return; - // } - - // // --------------------------- - // // SPI - // // id = 0 → RX - // // id = 1 → TX - // // --------------------------- - // else if constexpr (std::is_same_v) - // { - // if (id == 0) - // __HAL_LINKDMA(real_handle, hdmarx, dma); - // else - // __HAL_LINKDMA(real_handle, hdmatx, dma); - - // HAL_NVIC_SetPriority(irqn, 0, 0); - // HAL_NVIC_EnableIRQ(irqn); - // return; - // } - - // // --------------------------- - // // FMAC - // // id = 0 → Preload - // // id = 1 → In - // // id = 2 → Out - // // --------------------------- - // else if constexpr (std::is_same_v) - // { - // if (id == 0) - // __HAL_LINKDMA(real_handle, hdmaPreload, dma); - // else if (id == 1) - // __HAL_LINKDMA(real_handle, hdmaIn, dma); - // else - // __HAL_LINKDMA(real_handle, hdmaOut, dma); - - // HAL_NVIC_SetPriority(irqn, 0, 0); - // HAL_NVIC_EnableIRQ(irqn); - // return; - // } - - // else { - // ErrorHandler("Unsupported peripheral type in setDMAHandle"); - // } - - // }, handle); - - // }, instance); - // } }; From 36e5d71fde7871e020c43e68711dad3e40f97496 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Wed, 17 Dec 2025 18:29:41 +0100 Subject: [PATCH 057/109] el commit que se me olvido hacer para que poder testear --- Inc/HALAL/Models/DMA/DMA2.hpp | 19 +++++++------ Inc/HALAL/Models/GPIO.hpp | 2 +- Src/HALAL/Models/DMA/DMA-old.cpp | 28 ++++++++++---------- Src/HALAL/Services/Communication/I2C/I2C.cpp | 2 +- Src/HALAL/Services/Communication/SPI/SPI.cpp | 2 +- Src/HALAL/Services/FMAC/FMAC.cpp | 2 +- 6 files changed, 29 insertions(+), 26 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index fa65bd22e..57a62afcf 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -18,9 +18,10 @@ using std::tuple; namespace ST_LIB { + extern void compile_error(const char *msg); struct DMA_Domain { - enum class Instance : uint8_t {adc1, adc2, adc3, + enum class Instance : uint8_t {none, adc1, adc2, adc3, i2c1, i2c2, i2c3, i2c5, spi1, spi2, spi3, spi4, spi5, fmac}; @@ -95,7 +96,7 @@ namespace ST_LIB { static constexpr std::size_t max_instances {MAX_STREAMS}; static_assert(max_instances > 0, "The number of instances must be greater than 0"); - static inline IRQn_Type get_irqn(Stream stream) { + static inline constexpr IRQn_Type get_irqn(Stream stream) { if (stream == Stream::dma1_stream0) return DMA1_Stream0_IRQn; else if (stream == Stream::dma1_stream1) return DMA1_Stream1_IRQn; else if (stream == Stream::dma1_stream2) return DMA1_Stream2_IRQn; @@ -141,6 +142,8 @@ namespace ST_LIB { } static consteval inline uint32_t get_Request(Instance instance, uint8_t i) { + if (instance == Instance::none) return DMA_REQUEST_MEM2MEM; + if (instance == Instance::adc1) return DMA_REQUEST_ADC1; if (instance == Instance::adc2) return DMA_REQUEST_ADC2; if (instance == Instance::adc3) return DMA_REQUEST_ADC3; @@ -174,7 +177,7 @@ namespace ST_LIB { } static consteval inline uint32_t get_Direction(Instance instance, uint8_t i) { - if (is_fmac(instance) && i == 0){ + if ((is_fmac(instance) && i == 0) || instance == Instance::none) { return DMA_MEMORY_TO_MEMORY; } else if ((is_i2c(instance) && i == 1) || @@ -221,7 +224,7 @@ namespace ST_LIB { return DMA_MDATAALIGN_HALFWORD; } static consteval inline uint32_t get_Mode(Instance instance, uint8_t i) { - if (is_spi(instance) || is_fmac(instance)){ + if (is_spi(instance) || is_fmac(instance) || instance == Instance::none){ return DMA_NORMAL; } @@ -235,6 +238,7 @@ namespace ST_LIB { return DMA_PRIORITY_LOW; } + static consteval inline uint32_t get_FIFOMode(Instance instance, uint8_t i) { if (is_fmac(instance)){ return DMA_FIFOMODE_ENABLE; @@ -277,9 +281,8 @@ namespace ST_LIB { // Yo creo que a mi no me sirve porque mis instancias si que estan repetidas for (std::size_t j = 0; j < i; ++j){ const auto &prev = instances[j]; - if (prev.instance == e.instance && prev.stream == e.stream){ - struct peripherial_already_inscribed {}; - throw peripherial_already_inscribed{}; + if (prev.stream == e.stream){ + compile_error("DMA stream already in use"); } } @@ -320,7 +323,7 @@ namespace ST_LIB { static inline std::array instances{}; static void init(std::span cfgs) { - static_assert(N > 0); + //static_assert(N > 0); __HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_DMA2_CLK_ENABLE(); for (std::size_t i = 0; i < N; ++i) { diff --git a/Inc/HALAL/Models/GPIO.hpp b/Inc/HALAL/Models/GPIO.hpp index c19131e37..2c29ca0e5 100644 --- a/Inc/HALAL/Models/GPIO.hpp +++ b/Inc/HALAL/Models/GPIO.hpp @@ -246,7 +246,7 @@ struct GPIODomain { static inline std::array instances{}; static void init(std::span cfgs) { - static_assert(N > 0); + //static_assert(N > 0); for (std::size_t i = 0; i < N; ++i) { const auto &e = cfgs[i]; auto [port, gpio_init] = e.init_data; diff --git a/Src/HALAL/Models/DMA/DMA-old.cpp b/Src/HALAL/Models/DMA/DMA-old.cpp index db3768088..5b3cb7830 100644 --- a/Src/HALAL/Models/DMA/DMA-old.cpp +++ b/Src/HALAL/Models/DMA/DMA-old.cpp @@ -1,18 +1,18 @@ -#include "HALAL/Models/DMA/DMA.hpp" +// #include "HALAL/Models/DMA/DMA.hpp" -void DMA::start() { - __HAL_RCC_DMA1_CLK_ENABLE(); - __HAL_RCC_DMA2_CLK_ENABLE(); - for (uint8_t i = 0; i < inscribed_index; i++) { - auto& [periph, dma, linker, irq] = inscribed_streams[i]; +// void DMA::start() { +// __HAL_RCC_DMA1_CLK_ENABLE(); +// __HAL_RCC_DMA2_CLK_ENABLE(); +// for (uint8_t i = 0; i < inscribed_index; i++) { +// auto& [periph, dma, linker, irq] = inscribed_streams[i]; - if (HAL_DMA_Init(dma) != HAL_OK) { - ErrorHandler("DMA Init failed"); - } +// if (HAL_DMA_Init(dma) != HAL_OK) { +// ErrorHandler("DMA Init failed"); +// } - linker(dma); +// linker(dma); - HAL_NVIC_SetPriority(irq, 0, 0); - HAL_NVIC_EnableIRQ(irq); - } -} \ No newline at end of file +// HAL_NVIC_SetPriority(irq, 0, 0); +// HAL_NVIC_EnableIRQ(irq); +// } +// } \ No newline at end of file diff --git a/Src/HALAL/Services/Communication/I2C/I2C.cpp b/Src/HALAL/Services/Communication/I2C/I2C.cpp index 758918905..967b9eb07 100644 --- a/Src/HALAL/Services/Communication/I2C/I2C.cpp +++ b/Src/HALAL/Services/Communication/I2C/I2C.cpp @@ -23,7 +23,7 @@ uint8_t I2C::inscribe(I2C::Peripheral &i2c, uint8_t address) { Pin::inscribe(i2c_instance->SCL, ALTERNATIVE); Pin::inscribe(i2c_instance->SDA, ALTERNATIVE); - DMA::inscribe_stream(i2c_instance->hi2c); + //DMA::inscribe_stream(i2c_instance->hi2c); uint8_t id = I2C::id_counter++; diff --git a/Src/HALAL/Services/Communication/SPI/SPI.cpp b/Src/HALAL/Services/Communication/SPI/SPI.cpp index 172cba4e7..8e48abce9 100644 --- a/Src/HALAL/Services/Communication/SPI/SPI.cpp +++ b/Src/HALAL/Services/Communication/SPI/SPI.cpp @@ -56,7 +56,7 @@ uint8_t SPI::inscribe(SPI::Peripheral& spi) { uint8_t id = SPI::id_counter++; if (spi_instance->use_DMA) { - DMA::inscribe_stream(spi_instance->hspi); + //DMA::inscribe_stream(spi_instance->hspi); } SPI::registered_spi[id] = spi_instance; SPI::registered_spi_by_handler[spi_instance->hspi] = spi_instance; diff --git a/Src/HALAL/Services/FMAC/FMAC.cpp b/Src/HALAL/Services/FMAC/FMAC.cpp index 8ed6eafd1..d7885689c 100644 --- a/Src/HALAL/Services/FMAC/FMAC.cpp +++ b/Src/HALAL/Services/FMAC/FMAC.cpp @@ -32,7 +32,7 @@ void MultiplierAccelerator::IIR_software_in_software_out_inscribe(uint16_t input } void MultiplierAccelerator::inscribe(){ - DMA::inscribe_stream(Instance.hfmac); + //DMA::inscribe_stream(Instance.hfmac); } void MultiplierAccelerator::start(){ From 10390cf961898dce33f99d84a38b326ab25b2500 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Thu, 18 Dec 2025 16:19:56 +0100 Subject: [PATCH 058/109] cambios para poder utilizar none y algunos errores corregidos, queda configurar interrupciones --- Inc/HALAL/Models/DMA/DMA2.hpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index 369fa0481..9960eb17d 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -52,6 +52,7 @@ namespace ST_LIB { case Stream::dma2_stream6: return DMA2_Stream6; case Stream::dma2_stream7: return DMA2_Stream7; } + return nullptr; } struct Entry { @@ -65,7 +66,7 @@ namespace ST_LIB { struct DMA { using domain = DMA_Domain; - std::array e{}; + std::array e{}; consteval DMA(Instance instance) { @@ -85,14 +86,12 @@ namespace ST_LIB { template consteval void inscribe(Ctx &ctx) const { - for (const auto& entry : e) { - if (entry.stream != Stream{}) - ctx.template add(entry); + for (const auto &entry : e) { + ctx.template add(entry); } } }; - // NO se para que quiero esto static constexpr std::size_t max_instances {MAX_STREAMS}; static_assert(max_instances > 0, "The number of instances must be greater than 0"); @@ -141,6 +140,10 @@ namespace ST_LIB { return instance == Instance::fmac; } + static constexpr inline bool is_none(Instance instance){ + return instance == Instance::none; + } + static consteval inline uint32_t get_Request(Instance instance, uint8_t i) { if (instance == Instance::none) return DMA_REQUEST_MEM2MEM; @@ -189,7 +192,7 @@ namespace ST_LIB { } static consteval inline uint32_t get_PeriphInc(Instance instance, uint8_t i) { - if (is_fmac(instance) && i == 0){ + if ((is_fmac(instance) && i == 0) || is_none(instance)){ return DMA_PINC_ENABLE; } return DMA_PINC_DISABLE; @@ -209,6 +212,11 @@ namespace ST_LIB { else if (is_spi(instance)){ return DMA_PDATAALIGN_BYTE; } + // Para la prueba + else if (is_none(instance)){ + return DMA_PDATAALIGN_WORD; + } + return DMA_PDATAALIGN_HALFWORD; } @@ -314,7 +322,7 @@ namespace ST_LIB { DMA_HandleTypeDef dma; void start(uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength){ - HAL_DMA_Start_IT(&dma, SrcAddress, DstAddress, DataLength); + HAL_DMA_Start(&dma, SrcAddress, DstAddress, DataLength); } }; @@ -323,13 +331,14 @@ namespace ST_LIB { static inline std::array instances{}; static void init(std::span cfgs) { - //static_assert(N > 0); + static_assert(N > 0); __HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_DMA2_CLK_ENABLE(); for (std::size_t i = 0; i < N; ++i) { const auto &e = cfgs[i]; auto [instance, dma_init, stream, irqn, id] = e.init_data; + instances[i].dma = {}; instances[i].dma.Instance = stream_to_DMA_StreamTypeDef(stream); instances[i].dma.Init = dma_init; From f908ab5d1c859824054efaf3924d8821e4236b3b Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Thu, 18 Dec 2025 23:18:41 +0100 Subject: [PATCH 059/109] =?UTF-8?q?ni=20me=20acuerdo,=20ma=C3=B1ana=20sigo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Inc/HALAL/Models/DMA/DMA2.hpp | 80 ++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index 9960eb17d..425282444 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -31,7 +31,7 @@ namespace ST_LIB { dma2_stream0, dma2_stream1, dma2_stream2, dma2_stream3, dma2_stream4, dma2_stream5, dma2_stream6, dma2_stream7}; - + static inline DMA_Stream_TypeDef* stream_to_DMA_StreamTypeDef(Stream s) { switch (s) { case Stream::dma1_stream0: return DMA1_Stream0; @@ -117,7 +117,6 @@ namespace ST_LIB { return DMA1_Stream0_IRQn; // Nunca se alcanza } - // Si quitas el auto peta todo static constexpr inline bool is_one_of(Instance instance, auto... bases) { return ((instance == bases) || ...); } @@ -279,7 +278,7 @@ namespace ST_LIB { }; template - static consteval std::array build(span instances){ + static consteval std::array build(span instances) { std::array cfgs{}; for (std::size_t i = 0; i < N; ++i){ @@ -318,15 +317,20 @@ namespace ST_LIB { return cfgs; } + + struct Instances_ { DMA_HandleTypeDef dma; void start(uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength){ - HAL_DMA_Start(&dma, SrcAddress, DstAddress, DataLength); + HAL_DMA_Start_IT(&dma, SrcAddress, DstAddress, DataLength); } }; + // Alomejor habria que meterlo en algun lado + static inline DMA_HandleTypeDef *dma_irq_table[16]; + template struct Init { static inline std::array instances{}; @@ -348,9 +352,75 @@ namespace ST_LIB { else{ HAL_NVIC_SetPriority(irqn, 0, 0); HAL_NVIC_EnableIRQ(irqn); + dma_irq_table[static_cast(stream)] = &instances[i].dma; + } } } }; + + void DMA1_Stream0_IRQHandler(void) { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[0]); + } + + void DMA1_Stream1_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[1]); + } + + void DMA1_Stream2_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[2]); + } + + void DMA1_Stream3_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[3]); + } + + void DMA1_Stream4_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[4]); + } + + void DMA1_Stream5_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[5]); + } + + void DMA1_Stream6_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[6]); + + } + + void DMA1_Stream7_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[7]); + } + + void DMA2_Stream0_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[8]); + } + + void DMA2_Stream1_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[9]); + } + void DMA2_Stream2_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[10]); + } + + void DMA2_Stream3_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[11]); + } + + void DMA2_Stream4_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[12]); + } + + void DMA2_Stream5_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[13]); + } + + void DMA2_Stream6_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[14]); + } + + void DMA2_Stream7_IRQHandler() { + HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[15]); + } }; -} +} \ No newline at end of file From 2631a375bb670587db44fbe2ee271dd6367ea85b Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Mon, 22 Dec 2025 17:53:13 +0100 Subject: [PATCH 060/109] debugging validacion --- DartConfiguration.tcl | 106 ++++++++++++++++++ Inc/HALAL/HALAL.hpp | 2 +- Inc/HALAL/Models/DMA/DMA2.hpp | 74 ++---------- .../DMA/{DMA-old.cpp => DMA-old.cpp.tmp} | 0 Src/HALAL/Models/DMA/{DMA.cpp => DMA.cpp.tmp} | 0 Src/HALAL/Models/DMA/DMA2.cpp | 66 +++++++++++ Tests/st-lib-test[1]_include.cmake | 5 + 7 files changed, 185 insertions(+), 68 deletions(-) create mode 100644 DartConfiguration.tcl rename Src/HALAL/Models/DMA/{DMA-old.cpp => DMA-old.cpp.tmp} (100%) rename Src/HALAL/Models/DMA/{DMA.cpp => DMA.cpp.tmp} (100%) create mode 100644 Tests/st-lib-test[1]_include.cmake diff --git a/DartConfiguration.tcl b/DartConfiguration.tcl new file mode 100644 index 000000000..4b6ce3c2b --- /dev/null +++ b/DartConfiguration.tcl @@ -0,0 +1,106 @@ +# This file is configured by CMake automatically as DartConfiguration.tcl +# If you choose not to use CMake, this file may be hand configured, by +# filling in the required variables. + + +# Configuration directories and files +SourceDirectory: /home/jorge/hyperloop/pruebaDMA3/deps/ST-LIB +BuildDirectory: /home/jorge/hyperloop/pruebaDMA3/deps/ST-LIB + +# Where to place the cost data store +CostDataFile: + +# Site is something like machine.domain, i.e. pragmatic.crd +Site: Pmint + +# Build name is osname-revision-compiler, i.e. Linux-2.4.2-2smp-c++ +BuildName: Linux-c++ + +# Subprojects +LabelsForSubprojects: + +# Submission information +SubmitURL: http:// +SubmitInactivityTimeout: + +# Dashboard start time +NightlyStartTime: 00:00:00 EDT + +# Commands for the build/test/submit cycle +ConfigureCommand: "/opt/st/stm32cubeclt_1.20.0/CMake/bin/cmake" "/home/jorge/hyperloop/pruebaDMA3/deps/ST-LIB" +MakeCommand: /opt/st/stm32cubeclt_1.20.0/CMake/bin/cmake --build . --config "${CTEST_CONFIGURATION_TYPE}" +DefaultCTestConfigurationType: Release + +# version control +UpdateVersionOnly: + +# CVS options +# Default is "-d -P -A" +CVSCommand: +CVSUpdateOptions: + +# Subversion options +SVNCommand: +SVNOptions: +SVNUpdateOptions: + +# Git options +GITCommand: /usr/bin/git +GITInitSubmodules: +GITUpdateOptions: +GITUpdateCustom: + +# Perforce options +P4Command: +P4Client: +P4Options: +P4UpdateOptions: +P4UpdateCustom: + +# Generic update command +UpdateCommand: /usr/bin/git +UpdateOptions: +UpdateType: git + +# Compiler info +Compiler: /usr/bin/c++ +CompilerVersion: 13.3.0 + +# Dynamic analysis (MemCheck) +PurifyCommand: +ValgrindCommand: +ValgrindCommandOptions: +DrMemoryCommand: +DrMemoryCommandOptions: +CudaSanitizerCommand: +CudaSanitizerCommandOptions: +MemoryCheckType: +MemoryCheckSanitizerOptions: +MemoryCheckCommand: MEMORYCHECK_COMMAND-NOTFOUND +MemoryCheckCommandOptions: +MemoryCheckSuppressionFile: + +# Coverage +CoverageCommand: /usr/bin/gcov +CoverageExtraFlags: -l + +# Testing options +# TimeOut is the amount of time in seconds to wait for processes +# to complete during testing. After TimeOut seconds, the +# process will be summarily terminated. +# Currently set to 25 minutes +TimeOut: 1500 + +# During parallel testing CTest will not start a new test if doing +# so would cause the system load to exceed this value. +TestLoad: + +UseLaunchers: +CurlOptions: +# warning, if you add new options here that have to do with submit, +# you have to update cmCTestSubmitCommand.cxx + +# For CTest submissions that timeout, these options +# specify behavior for retrying the submission +CTestSubmitRetryDelay: 5 +CTestSubmitRetryCount: 3 diff --git a/Inc/HALAL/HALAL.hpp b/Inc/HALAL/HALAL.hpp index 6b20c7bc8..e63ef56c2 100644 --- a/Inc/HALAL/HALAL.hpp +++ b/Inc/HALAL/HALAL.hpp @@ -4,7 +4,7 @@ #include "HALAL/Models/Pin.hpp" #include "HALAL/Models/HALconfig/HALconfig.hpp" -#include "HALAL/Models/DMA/DMA.hpp" +//#include "HALAL/Models/DMA/DMA.hpp" #include "HALAL/Models/DMA/DMA2.hpp" #include "HALAL/Services/DigitalOutputService/DigitalOutputService.hpp" diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index 425282444..6d7b5881f 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -15,7 +15,10 @@ using std::span; using std::tuple; #define MAX_STREAMS 16 - + + +// Alomejor habria que meterlo en algun lado + static inline DMA_HandleTypeDef *dma_irq_table[16]; namespace ST_LIB { extern void compile_error(const char *msg); @@ -328,8 +331,7 @@ namespace ST_LIB { }; - // Alomejor habria que meterlo en algun lado - static inline DMA_HandleTypeDef *dma_irq_table[16]; + template struct Init { static inline std::array instances{}; @@ -358,69 +360,7 @@ namespace ST_LIB { } } }; - - void DMA1_Stream0_IRQHandler(void) { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[0]); - } - - void DMA1_Stream1_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[1]); - } - - void DMA1_Stream2_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[2]); - } - - void DMA1_Stream3_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[3]); - } - - void DMA1_Stream4_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[4]); - } - - void DMA1_Stream5_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[5]); - } - - void DMA1_Stream6_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[6]); - - } - - void DMA1_Stream7_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[7]); - } - - void DMA2_Stream0_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[8]); - } - - void DMA2_Stream1_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[9]); - } - void DMA2_Stream2_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[10]); - } - - void DMA2_Stream3_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[11]); - } - - void DMA2_Stream4_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[12]); - } - - void DMA2_Stream5_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[13]); - } + }; +} - void DMA2_Stream6_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[14]); - } - void DMA2_Stream7_IRQHandler() { - HAL_DMA_IRQHandler(ST_LIB::DMA_Domain::dma_irq_table[15]); - } - }; -} \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA-old.cpp b/Src/HALAL/Models/DMA/DMA-old.cpp.tmp similarity index 100% rename from Src/HALAL/Models/DMA/DMA-old.cpp rename to Src/HALAL/Models/DMA/DMA-old.cpp.tmp diff --git a/Src/HALAL/Models/DMA/DMA.cpp b/Src/HALAL/Models/DMA/DMA.cpp.tmp similarity index 100% rename from Src/HALAL/Models/DMA/DMA.cpp rename to Src/HALAL/Models/DMA/DMA.cpp.tmp diff --git a/Src/HALAL/Models/DMA/DMA2.cpp b/Src/HALAL/Models/DMA/DMA2.cpp index e69de29bb..1ac02fcf2 100644 --- a/Src/HALAL/Models/DMA/DMA2.cpp +++ b/Src/HALAL/Models/DMA/DMA2.cpp @@ -0,0 +1,66 @@ +#include "HALAL/Models/DMA/DMA2.hpp" + + +extern "C" void DMA1_Stream0_IRQHandler(void) { + while(1); +} + +extern "C" void DMA1_Stream1_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[1]); +} + +extern "C" void DMA1_Stream2_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[2]); +} + +extern "C" void DMA1_Stream3_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[3]); +} + +extern "C" void DMA1_Stream4_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[4]); +} + +extern "C" void DMA1_Stream5_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[5]); +} + +extern "C" void DMA1_Stream6_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[6]); +} + +extern "C" void DMA1_Stream7_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[7]); +} + +extern "C" void DMA2_Stream0_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[8]); +} + +extern "C" void DMA2_Stream1_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[9]); +} + +extern "C" void DMA2_Stream2_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[10]); +} + +extern "C" void DMA2_Stream3_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[11]); +} + +extern "C" void DMA2_Stream4_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[12]); +} + +extern "C" void DMA2_Stream5_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[13]); +} + +extern "C" void DMA2_Stream6_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[14]); +} + +extern "C" void DMA2_Stream7_IRQHandler(void) { + HAL_DMA_IRQHandler(dma_irq_table[15]); +} diff --git a/Tests/st-lib-test[1]_include.cmake b/Tests/st-lib-test[1]_include.cmake new file mode 100644 index 000000000..7be2cd719 --- /dev/null +++ b/Tests/st-lib-test[1]_include.cmake @@ -0,0 +1,5 @@ +if(EXISTS "/home/jorge/hyperloop/pruebaDMA3/deps/ST-LIB/Tests/st-lib-test[1]_tests.cmake") + include("/home/jorge/hyperloop/pruebaDMA3/deps/ST-LIB/Tests/st-lib-test[1]_tests.cmake") +else() + add_test(st-lib-test_NOT_BUILT st-lib-test_NOT_BUILT) +endif() From b6b2c302944e67e3480c4b4ff79d9fe95f1bc7fd Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Mon, 22 Dec 2025 20:51:18 +0100 Subject: [PATCH 061/109] cmake cambiado para que se incluya la dma2.cpp --- CMakeLists.txt | 2 +- Inc/HALAL/Models/DMA/DMA2.hpp | 1 - Src/HALAL/Models/DMA/DMA2.cpp | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e510b57e..e8df90204 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,7 +197,7 @@ list(FILTER STLIB_HIGH_CPP_NO_ETH EXCLUDE REGEX "${STLIB_HIGH_ETH_REGEX}") # Librería STLIB_LIBRARY # ============================ -add_library(${STLIB_LIBRARY} STATIC +add_library(${STLIB_LIBRARY} OBJECT $<$:${HAL_SOURCES_COMMON}> $<$,$>:${HAL_SOURCES_ETH}> $<$,$>:${LWIP_SOURCES}> diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index 6d7b5881f..291aae91e 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -363,4 +363,3 @@ namespace ST_LIB { }; } - diff --git a/Src/HALAL/Models/DMA/DMA2.cpp b/Src/HALAL/Models/DMA/DMA2.cpp index 1ac02fcf2..27e1c9ac4 100644 --- a/Src/HALAL/Models/DMA/DMA2.cpp +++ b/Src/HALAL/Models/DMA/DMA2.cpp @@ -2,7 +2,7 @@ extern "C" void DMA1_Stream0_IRQHandler(void) { - while(1); + HAL_DMA_IRQHandler(dma_irq_table[0]); } extern "C" void DMA1_Stream1_IRQHandler(void) { From 9e4fb9e24d0a87ca45240aeda4a3c2852d141c8a Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Tue, 23 Dec 2025 12:22:26 +0100 Subject: [PATCH 062/109] cambios finales, prueba funciona --- Inc/HALAL/Models/DMA/DMA2.hpp | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index 291aae91e..cf69c810c 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -17,8 +17,10 @@ using std::tuple; #define MAX_STREAMS 16 -// Alomejor habria que meterlo en algun lado - static inline DMA_HandleTypeDef *dma_irq_table[16]; +extern "C" { + inline DMA_HandleTypeDef *dma_irq_table[16] = {nullptr}; +} + namespace ST_LIB { extern void compile_error(const char *msg); @@ -208,18 +210,12 @@ namespace ST_LIB { } static consteval inline uint32_t get_PeriphDataAlignment(Instance instance, uint8_t i) { - if (is_i2c(instance)){ - return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes - } - else if (is_spi(instance)){ + else if (is_spi(instance) || is_i2c(instance)){ return DMA_PDATAALIGN_BYTE; } - // Para la prueba else if (is_none(instance)){ return DMA_PDATAALIGN_WORD; } - - return DMA_PDATAALIGN_HALFWORD; } @@ -233,8 +229,9 @@ namespace ST_LIB { return DMA_MDATAALIGN_HALFWORD; } + static consteval inline uint32_t get_Mode(Instance instance, uint8_t i) { - if (is_spi(instance) || is_fmac(instance) || instance == Instance::none){ + if (is_spi(instance) || is_fmac(instance) || is_none(instance)){ return DMA_NORMAL; } @@ -287,8 +284,6 @@ namespace ST_LIB { for (std::size_t i = 0; i < N; ++i){ const auto &e = instances[i]; - // No entiendo como funciona esto, pero esta copiado tal cual - // Yo creo que a mi no me sirve porque mis instancias si que estan repetidas for (std::size_t j = 0; j < i; ++j){ const auto &prev = instances[j]; if (prev.stream == e.stream){ @@ -331,8 +326,6 @@ namespace ST_LIB { }; - - template struct Init { static inline std::array instances{}; @@ -354,8 +347,7 @@ namespace ST_LIB { else{ HAL_NVIC_SetPriority(irqn, 0, 0); HAL_NVIC_EnableIRQ(irqn); - dma_irq_table[static_cast(stream)] = &instances[i].dma; - + dma_irq_table[stream_to_index(stream)] = &instances[i].dma; } } } From 0cb7a1150a1f7597d4039c1cb77984531f0e9fae Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Tue, 23 Dec 2025 12:24:15 +0100 Subject: [PATCH 063/109] ahora de verdad funciona --- Inc/HALAL/Models/DMA/DMA2.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index cf69c810c..0ca605ffd 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -210,7 +210,7 @@ namespace ST_LIB { } static consteval inline uint32_t get_PeriphDataAlignment(Instance instance, uint8_t i) { - else if (is_spi(instance) || is_i2c(instance)){ + if (is_spi(instance) || is_i2c(instance)){ return DMA_PDATAALIGN_BYTE; } else if (is_none(instance)){ @@ -347,7 +347,7 @@ namespace ST_LIB { else{ HAL_NVIC_SetPriority(irqn, 0, 0); HAL_NVIC_EnableIRQ(irqn); - dma_irq_table[stream_to_index(stream)] = &instances[i].dma; + dma_irq_table[static_cast(stream)] = &instances[i].dma; } } } From 33b494269d9474bba29cd6314dfdb0728bb67bbf Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Tue, 30 Dec 2025 19:05:21 +0100 Subject: [PATCH 064/109] limpieza de rama p1 --- .gitignore | 3 + CMakeLists.txt | 5 +- DartConfiguration.tcl | 106 -------- Inc/HALAL/Models/DMA/DMA-old.hpp | 366 --------------------------- Src/HALAL/Models/DMA/DMA-old.cpp.tmp | 18 -- Src/HALAL/Models/DMA/DMA.cpp.tmp | 5 + 6 files changed, 11 insertions(+), 492 deletions(-) delete mode 100644 DartConfiguration.tcl delete mode 100644 Inc/HALAL/Models/DMA/DMA-old.hpp delete mode 100644 Src/HALAL/Models/DMA/DMA-old.cpp.tmp diff --git a/.gitignore b/.gitignore index a16ea42ff..a92b9999b 100644 --- a/.gitignore +++ b/.gitignore @@ -91,3 +91,6 @@ CMakeUserPresets.json *.pdb _codeql_build_dir/ _codeql_detected_source_root + +# Cosas mias +DartConfiguration.tcl diff --git a/CMakeLists.txt b/CMakeLists.txt index e8df90204..7a9a4828b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -250,6 +250,7 @@ target_compile_options(${STLIB_LIBRARY} PRIVATE $<$:-specs=nosys.specs> $<$:-ffunction-sections> $<$:-fdata-sections> + $<$:-fno-exceptions> -Wno-psabi @@ -258,8 +259,8 @@ target_compile_options(${STLIB_LIBRARY} PRIVATE $<$:-Wall> $<$:-Wpedantic> $<$:-Werror> - # $<$:-Wno-gnu-zero-variadic-macro-arguments> - # $<$:-Wno-inconsistent-missing-override> + $<$:-Wno-gnu-zero-variadic-macro-arguments> + $<$:-Wno-inconsistent-missing-override> $<$:-fno-use-cxa-atexit> $<$:-fno-rtti> $<$:-Wno-address-of-packed-member> diff --git a/DartConfiguration.tcl b/DartConfiguration.tcl deleted file mode 100644 index 4b6ce3c2b..000000000 --- a/DartConfiguration.tcl +++ /dev/null @@ -1,106 +0,0 @@ -# This file is configured by CMake automatically as DartConfiguration.tcl -# If you choose not to use CMake, this file may be hand configured, by -# filling in the required variables. - - -# Configuration directories and files -SourceDirectory: /home/jorge/hyperloop/pruebaDMA3/deps/ST-LIB -BuildDirectory: /home/jorge/hyperloop/pruebaDMA3/deps/ST-LIB - -# Where to place the cost data store -CostDataFile: - -# Site is something like machine.domain, i.e. pragmatic.crd -Site: Pmint - -# Build name is osname-revision-compiler, i.e. Linux-2.4.2-2smp-c++ -BuildName: Linux-c++ - -# Subprojects -LabelsForSubprojects: - -# Submission information -SubmitURL: http:// -SubmitInactivityTimeout: - -# Dashboard start time -NightlyStartTime: 00:00:00 EDT - -# Commands for the build/test/submit cycle -ConfigureCommand: "/opt/st/stm32cubeclt_1.20.0/CMake/bin/cmake" "/home/jorge/hyperloop/pruebaDMA3/deps/ST-LIB" -MakeCommand: /opt/st/stm32cubeclt_1.20.0/CMake/bin/cmake --build . --config "${CTEST_CONFIGURATION_TYPE}" -DefaultCTestConfigurationType: Release - -# version control -UpdateVersionOnly: - -# CVS options -# Default is "-d -P -A" -CVSCommand: -CVSUpdateOptions: - -# Subversion options -SVNCommand: -SVNOptions: -SVNUpdateOptions: - -# Git options -GITCommand: /usr/bin/git -GITInitSubmodules: -GITUpdateOptions: -GITUpdateCustom: - -# Perforce options -P4Command: -P4Client: -P4Options: -P4UpdateOptions: -P4UpdateCustom: - -# Generic update command -UpdateCommand: /usr/bin/git -UpdateOptions: -UpdateType: git - -# Compiler info -Compiler: /usr/bin/c++ -CompilerVersion: 13.3.0 - -# Dynamic analysis (MemCheck) -PurifyCommand: -ValgrindCommand: -ValgrindCommandOptions: -DrMemoryCommand: -DrMemoryCommandOptions: -CudaSanitizerCommand: -CudaSanitizerCommandOptions: -MemoryCheckType: -MemoryCheckSanitizerOptions: -MemoryCheckCommand: MEMORYCHECK_COMMAND-NOTFOUND -MemoryCheckCommandOptions: -MemoryCheckSuppressionFile: - -# Coverage -CoverageCommand: /usr/bin/gcov -CoverageExtraFlags: -l - -# Testing options -# TimeOut is the amount of time in seconds to wait for processes -# to complete during testing. After TimeOut seconds, the -# process will be summarily terminated. -# Currently set to 25 minutes -TimeOut: 1500 - -# During parallel testing CTest will not start a new test if doing -# so would cause the system load to exceed this value. -TestLoad: - -UseLaunchers: -CurlOptions: -# warning, if you add new options here that have to do with submit, -# you have to update cmCTestSubmitCommand.cxx - -# For CTest submissions that timeout, these options -# specify behavior for retrying the submission -CTestSubmitRetryDelay: 5 -CTestSubmitRetryCount: 3 diff --git a/Inc/HALAL/Models/DMA/DMA-old.hpp b/Inc/HALAL/Models/DMA/DMA-old.hpp deleted file mode 100644 index 3a37999d0..000000000 --- a/Inc/HALAL/Models/DMA/DMA-old.hpp +++ /dev/null @@ -1,366 +0,0 @@ -/* - * DMA.hpp - * - * Created on: 10 dic. 2022 - * Author: aleja -*/ -#pragma once -#include "C++Utilities/CppUtils.hpp" -#include "stm32h7xx_hal.h" -#include "main.h" -#include "HALAL/Models/MPUManager/MPUManager.hpp" -#include -#include -#include -#include -#include - -#define MAX_STREAMS 16 - -class DMA { - using PeriphVariant = std::variant< - SPI_HandleTypeDef*, - I2C_HandleTypeDef*, - ADC_HandleTypeDef*, - FMAC_HandleTypeDef* - >; - struct DmaLinkEntry{ - PeriphVariant periph; // (__HANDLE__) - DMA_HandleTypeDef* dma; // (__DMA_HANDLE__) - std::function linker; // (__PPP_DMA_FIELD__) - IRQn_Type irq; // (__IRQn_TYPE__) - }; - - template - static DmaLinkEntry make_dma_entry( - PeriphHandle* periph, - DMA_HandleTypeDef* dma, - DMA_HandleTypeDef* PeriphHandle::* member, - IRQn_Type irqn - ); - - static uint32_t get_Request(auto Instance, uint8_t i); - - static uint32_t get_Direction(auto Instance, uint8_t i); - - static uint32_t get_PeriphInc(auto Instance, uint8_t i); - - static uint32_t get_MemInc(auto Instance, uint8_t i); - - static uint32_t get_PeriphDataAlignment(auto Instance, uint8_t i); - - static uint32_t get_MemDataAlignment(auto Instance, uint8_t i); - - static uint32_t get_Mode(auto Instance, uint8_t i); - - static uint32_t get_Priority(auto Instance, uint8_t i); - - static uint32_t get_FIFOMode(auto Instance, uint8_t i); - - static uint32_t get_FIFOThreshold(auto Instance, uint8_t i); - - static uint32_t get_MemBurst(auto Instance, uint8_t i); - - static uint32_t get_PeriphBurst(auto Instance, uint8_t i); - - static IRQn_Type get_irqn(auto stream); - - static bool is_stream_available(uintptr_t stream); - - static bool is_peripherial_available(unsigned long peripherial); - - static std::array inscribed_streams; - static uint8_t inscribed_index; - - static std::set used_peripherials; - static std::set used_streams; - - public: - static constexpr bool is_one_of(auto Instance, auto... Bases); - - static constexpr bool is_spi(auto Instance); - - static constexpr bool is_i2c(auto Instance); - - static constexpr bool is_adc(auto Instance); - - static constexpr bool is_fmac(auto Instance); - - template - requires ( - (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || - (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || - (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) - ) - static void inscribe_stream(PeriphVariant handle); - - static void start(); -}; - -inline uint8_t DMA::inscribed_index{0}; -inline std::set DMA::used_peripherials{}; -inline std::set DMA::used_streams{}; -inline std::array DMA::inscribed_streams{}; - -constexpr bool DMA::is_one_of(auto Instance, auto... Bases) { - return ((Instance == Bases) || ...); -} - -constexpr bool DMA::is_spi(auto Instance) { - return is_one_of(Instance, SPI1_BASE, SPI2_BASE, SPI3_BASE, SPI4_BASE, SPI5_BASE); -} - -constexpr bool DMA::is_i2c(auto Instance) { - return is_one_of(Instance, I2C1_BASE, I2C2_BASE, I2C3_BASE, I2C5_BASE); -} - -constexpr bool DMA::is_adc(auto Instance) { - return is_one_of(Instance, ADC1_BASE, ADC2_BASE, ADC3_BASE); -} - -constexpr bool DMA::is_fmac(auto Instance) { - return Instance == FMAC_BASE; -} - -inline bool DMA::is_stream_available(uintptr_t stream) { - return used_streams.find(stream) == used_streams.end(); -} - -inline bool DMA::is_peripherial_available(unsigned long peripheral) { - return used_peripherials.find(peripheral) == used_peripherials.end(); -} - - -IRQn_Type DMA::get_irqn(auto stream) { - if (stream == DMA1_Stream0) return DMA1_Stream0_IRQn; - else if (stream == DMA1_Stream1) return DMA1_Stream1_IRQn; - else if (stream == DMA1_Stream2) return DMA1_Stream2_IRQn; - else if (stream == DMA1_Stream3) return DMA1_Stream3_IRQn; - else if (stream == DMA1_Stream4) return DMA1_Stream4_IRQn; - else if (stream == DMA1_Stream5) return DMA1_Stream5_IRQn; - else if (stream == DMA1_Stream6) return DMA1_Stream6_IRQn; - else if (stream == DMA1_Stream7) return DMA1_Stream7_IRQn; - - else if (stream == DMA2_Stream0) return DMA2_Stream0_IRQn; - else if (stream == DMA2_Stream1) return DMA2_Stream1_IRQn; - else if (stream == DMA2_Stream2) return DMA2_Stream2_IRQn; - else if (stream == DMA2_Stream3) return DMA2_Stream3_IRQn; - else if (stream == DMA2_Stream4) return DMA2_Stream4_IRQn; - else if (stream == DMA2_Stream5) return DMA2_Stream5_IRQn; - else if (stream == DMA2_Stream6) return DMA2_Stream6_IRQn; - else if (stream == DMA2_Stream7) return DMA2_Stream7_IRQn; - else ErrorHandler("Unknown DMA stream"); - return DMA1_Stream0_IRQn; // Nunca se alcanza -} - -uint32_t DMA::get_Request(auto Instance, uint8_t i) { - if (Instance == ADC1_BASE) return DMA_REQUEST_ADC1; - if (Instance == ADC2_BASE) return DMA_REQUEST_ADC2; - if (Instance == ADC3_BASE) return DMA_REQUEST_ADC3; - - if (Instance == I2C1_BASE && i == 0) return DMA_REQUEST_I2C1_RX; - if (Instance == I2C1_BASE && i == 1) return DMA_REQUEST_I2C1_TX; - if (Instance == I2C2_BASE && i == 0) return DMA_REQUEST_I2C2_RX; - if (Instance == I2C2_BASE && i == 1) return DMA_REQUEST_I2C2_TX; - if (Instance == I2C3_BASE && i == 0) return DMA_REQUEST_I2C3_RX; - if (Instance == I2C3_BASE && i == 1) return DMA_REQUEST_I2C3_TX; - if (Instance == I2C5_BASE && i == 0) return DMA_REQUEST_I2C5_RX; - if (Instance == I2C5_BASE && i == 1) return DMA_REQUEST_I2C5_TX; - - if (Instance == SPI1_BASE && i == 0) return DMA_REQUEST_SPI1_RX; - if (Instance == SPI1_BASE && i == 1) return DMA_REQUEST_SPI1_TX; - if (Instance == SPI2_BASE && i == 0) return DMA_REQUEST_SPI2_RX; - if (Instance == SPI2_BASE && i == 1) return DMA_REQUEST_SPI2_TX; - if (Instance == SPI3_BASE && i == 0) return DMA_REQUEST_SPI3_RX; - if (Instance == SPI3_BASE && i == 1) return DMA_REQUEST_SPI3_TX; - if (Instance == SPI4_BASE && i == 0) return DMA_REQUEST_SPI4_RX; - if (Instance == SPI4_BASE && i == 1) return DMA_REQUEST_SPI4_TX; - if (Instance == SPI5_BASE && i == 0) return DMA_REQUEST_SPI5_RX; - if (Instance == SPI5_BASE && i == 1) return DMA_REQUEST_SPI5_TX; - - if (Instance == FMAC_BASE && i == 0) return DMA_REQUEST_MEM2MEM; - if (Instance == FMAC_BASE && i == 1) return DMA_REQUEST_FMAC_WRITE; - if (Instance == FMAC_BASE && i == 2) return DMA_REQUEST_FMAC_READ; - - ErrorHandler("Invalid DMA request configuration"); - return 0; -} - - - -uint32_t DMA::get_Direction(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_MEMORY_TO_MEMORY; - } - else if ((is_i2c(Instance) && i == 1) || - (is_spi(Instance) && i == 1) || - (is_fmac(Instance) && i == 1)){ - return DMA_MEMORY_TO_PERIPH; - } - - return DMA_PERIPH_TO_MEMORY; -} - -uint32_t DMA::get_PeriphInc(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_PINC_ENABLE; - } - return DMA_PINC_DISABLE; -} -uint32_t DMA::get_MemInc(auto Instance, uint8_t i) { - if (is_fmac(Instance) && i == 0){ - return DMA_MINC_DISABLE; - } - return DMA_MINC_ENABLE; -} - -uint32_t DMA::get_PeriphDataAlignment(auto Instance, uint8_t i) { - if (is_i2c(Instance)){ - return DMA_PDATAALIGN_WORD; // Revisar esto, I2C suele trabajar con bytes - } - else if (is_spi(Instance)){ - return DMA_PDATAALIGN_BYTE; - } - - return DMA_PDATAALIGN_HALFWORD; -} - -uint32_t DMA::get_MemDataAlignment(auto Instance, uint8_t i) { - if (is_i2c(Instance)){ - return DMA_MDATAALIGN_WORD; - } - else if (is_spi(Instance)){ - return DMA_MDATAALIGN_BYTE; - } - - return DMA_MDATAALIGN_HALFWORD; -} -uint32_t DMA::get_Mode(auto Instance, uint8_t i) { - if (is_spi(Instance) || is_fmac(Instance)){ - return DMA_NORMAL; - } - - return DMA_CIRCULAR; -} - - uint32_t DMA::get_Priority(auto Instance, uint8_t i) { - if (is_fmac(Instance)){ - return DMA_PRIORITY_HIGH; - } - - return DMA_PRIORITY_LOW; -} -uint32_t DMA::get_FIFOMode(auto Instance, uint8_t i) { - if (is_fmac(Instance)){ - return DMA_FIFOMODE_ENABLE; - } - return DMA_FIFOMODE_DISABLE; -} - -uint32_t DMA::get_FIFOThreshold(auto Instance, uint8_t i) { - if (is_spi(Instance)){ - return DMA_FIFO_THRESHOLD_FULL; - } - return DMA_FIFO_THRESHOLD_HALFFULL; -} - -uint32_t DMA::get_MemBurst(auto Instance, uint8_t i) { - return DMA_MBURST_SINGLE; -} - -uint32_t DMA::get_PeriphBurst(auto Instance, uint8_t i) { - return DMA_PBURST_SINGLE; -} - -template -DMA::DmaLinkEntry DMA::make_dma_entry( - PeriphHandle* periph, - DMA_HandleTypeDef* dma, - DMA_HandleTypeDef* PeriphHandle::* member, - IRQn_Type irqn -){ - return DmaLinkEntry{ - periph, - dma, - [periph, member](DMA_HandleTypeDef* d) { - periph->*member = d; - d->Parent = periph; - }, - irqn - }; -} - -template -requires ( - (DMA::is_adc(Instance) && sizeof...(Streams) == 1) || - (DMA::is_fmac(Instance) && sizeof...(Streams) == 3) || - (!DMA::is_adc(Instance) && !DMA::is_fmac(Instance) && sizeof...(Streams) == 2) -) -void DMA::inscribe_stream(PeriphVariant handle) { - const std::size_t N = sizeof...(Streams); - if (inscribed_index + N > MAX_STREAMS){ - ErrorHandler("Too many streams inscribed"); - } - - unsigned long periph_addr = reinterpret_cast(Instance); - if (!is_peripherial_available(periph_addr)){ - ErrorHandler("Peripheral already in use"); - } - used_peripherials.insert(periph_addr); - - std::array streams = {(DMA_Stream_TypeDef*)Streams... }; - - for (uint8_t i = 0; i < N; i++){ - uintptr_t stream_addr = reinterpret_cast(streams[i]); - if (!is_stream_available(stream_addr)){ - ErrorHandler("DMA stream already in use"); - used_streams.insert(stream_addr); - } - } - - - for (uint8_t i = 0; i < N; i++){ - DMA_HandleTypeDef* dma = new DMA_HandleTypeDef{}; - dma->Instance = streams[i]; - dma->Init.Request = get_Request(Instance, i); - dma->Init.Direction = get_Direction(Instance, i); - dma->Init.PeriphInc = get_PeriphInc(Instance, i); - dma->Init.MemInc = get_MemInc(Instance, i); - dma->Init.PeriphDataAlignment = get_PeriphDataAlignment(Instance, i); - dma->Init.MemDataAlignment = get_MemDataAlignment(Instance, i); - dma->Init.Mode = get_Mode(Instance, i); - dma->Init.Priority = get_Priority(Instance, i); - dma->Init.FIFOMode = get_FIFOMode(Instance, i); - dma->Init.FIFOThreshold = get_FIFOThreshold(Instance, i); - dma->Init.MemBurst = get_MemBurst(Instance, i); - dma->Init.PeriphBurst = get_PeriphBurst(Instance, i); - IRQn_Type irq = get_irqn(streams[i]); - - if constexpr (is_spi(Instance)) { - auto* spi_handle = std::get(handle); - auto member = (i == 0) ? &SPI_HandleTypeDef::hdmarx : &SPI_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(spi_handle, dma, member, irq); - } - else if constexpr (is_i2c(Instance)) { - auto* i2c_handle = std::get(handle); - auto member = (i == 0) ? &I2C_HandleTypeDef::hdmarx : &I2C_HandleTypeDef::hdmatx; - inscribed_streams[inscribed_index] = make_dma_entry(i2c_handle, dma, member, irq); - } - else if constexpr (is_adc(Instance)) { - auto* adc_handle = std::get(handle); - auto member = &ADC_HandleTypeDef::DMA_Handle; - inscribed_streams[inscribed_index] = make_dma_entry(adc_handle, dma, member, irq); - } - else if constexpr (is_fmac(Instance)) { - auto* fmac_handle = std::get(handle); - auto member = (i == 0) ? &FMAC_HandleTypeDef::hdmaPreload : - (i == 1) ? &FMAC_HandleTypeDef::hdmaIn : - &FMAC_HandleTypeDef::hdmaOut; - inscribed_streams[inscribed_index] = make_dma_entry(fmac_handle, dma, member, irq); - } - - inscribed_index++; - } -} - - diff --git a/Src/HALAL/Models/DMA/DMA-old.cpp.tmp b/Src/HALAL/Models/DMA/DMA-old.cpp.tmp deleted file mode 100644 index 5b3cb7830..000000000 --- a/Src/HALAL/Models/DMA/DMA-old.cpp.tmp +++ /dev/null @@ -1,18 +0,0 @@ -// #include "HALAL/Models/DMA/DMA.hpp" - -// void DMA::start() { -// __HAL_RCC_DMA1_CLK_ENABLE(); -// __HAL_RCC_DMA2_CLK_ENABLE(); -// for (uint8_t i = 0; i < inscribed_index; i++) { -// auto& [periph, dma, linker, irq] = inscribed_streams[i]; - -// if (HAL_DMA_Init(dma) != HAL_OK) { -// ErrorHandler("DMA Init failed"); -// } - -// linker(dma); - -// HAL_NVIC_SetPriority(irq, 0, 0); -// HAL_NVIC_EnableIRQ(irq); -// } -// } \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp.tmp b/Src/HALAL/Models/DMA/DMA.cpp.tmp index 2fea33c37..bfc875a9c 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp.tmp +++ b/Src/HALAL/Models/DMA/DMA.cpp.tmp @@ -5,6 +5,11 @@ * Author: aleja */ + +# Para que este codigo conviva con la nueva dma hay que forzarlo un pelin. Yo (Jorge no pm), creo que la DMA nueva puede funcionar para todos los perifericos. En caso +# de que no sea asi, cambiare esto para que funcione (sera solo un momentito) + + #include "HALAL/Models/DMA/DMA.hpp" #include "ErrorHandler/ErrorHandler.hpp" From 3f5b436dd564c2794501706b69c3f805cadd099d Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Tue, 30 Dec 2025 19:10:36 +0100 Subject: [PATCH 065/109] limpieza de rama p2 --- .gitignore | 1 + Inc/HALAL/Models/GPIO.hpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a92b9999b..3560a45b4 100644 --- a/.gitignore +++ b/.gitignore @@ -94,3 +94,4 @@ _codeql_detected_source_root # Cosas mias DartConfiguration.tcl +Tests/st-lib-test[1]_include.cmake diff --git a/Inc/HALAL/Models/GPIO.hpp b/Inc/HALAL/Models/GPIO.hpp index 2c29ca0e5..c19131e37 100644 --- a/Inc/HALAL/Models/GPIO.hpp +++ b/Inc/HALAL/Models/GPIO.hpp @@ -246,7 +246,7 @@ struct GPIODomain { static inline std::array instances{}; static void init(std::span cfgs) { - //static_assert(N > 0); + static_assert(N > 0); for (std::size_t i = 0; i < N; ++i) { const auto &e = cfgs[i]; auto [port, gpio_init] = e.init_data; From 550fde1db6e78fab779057bdab15593bc2243c31 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Tue, 30 Dec 2025 19:29:47 +0100 Subject: [PATCH 066/109] cambiar gpio para que el static assert me deje compilar --- Inc/HALAL/Models/GPIO.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Inc/HALAL/Models/GPIO.hpp b/Inc/HALAL/Models/GPIO.hpp index c19131e37..3d6103457 100644 --- a/Inc/HALAL/Models/GPIO.hpp +++ b/Inc/HALAL/Models/GPIO.hpp @@ -246,7 +246,8 @@ struct GPIODomain { static inline std::array instances{}; static void init(std::span cfgs) { - static_assert(N > 0); + // Esto solo lo comento para que vaya bien la prueba de la DMA + //static_assert(N > 0); for (std::size_t i = 0; i < N; ++i) { const auto &e = cfgs[i]; auto [port, gpio_init] = e.init_data; From d3432a15dfbb298ea98cb005395716a4dae94411 Mon Sep 17 00:00:00 2001 From: Foniks Date: Sun, 28 Dec 2025 01:56:51 +0100 Subject: [PATCH 067/109] feat(SPI): First implementation with most of the infrastructure and hadware settings --- Inc/HALAL/Models/SPI2.hpp | 522 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 522 insertions(+) create mode 100644 Inc/HALAL/Models/SPI2.hpp diff --git a/Inc/HALAL/Models/SPI2.hpp b/Inc/HALAL/Models/SPI2.hpp new file mode 100644 index 000000000..2f15e21e5 --- /dev/null +++ b/Inc/HALAL/Models/SPI2.hpp @@ -0,0 +1,522 @@ +/* + * SPI2.hpp + * + * Created on: 27 dec. 2025 + * Author: Boris + */ + +#ifndef SPI2_HPP +#define SPI2_HPP + +#include "C++Utilities/CppImports.hpp" +#include "HALAL/Models/GPIO.hpp" +#include "ErrorHandler/ErrorHandler.hpp" + +using ST_LIB::GPIODomain; + +namespace ST_LIB { + +struct SPIDomain { + +/** + * ========================================= + * Internal working things + * ========================================= + */ + + enum class SPIPeripheral : uintptr_t { + spi1 = SPI1_BASE, + spi2 = SPI2_BASE, + spi3 = SPI3_BASE, + spi4 = SPI4_BASE, + spi5 = SPI5_BASE, + spi6 = SPI6_BASE, + }; + + enum class SPIMode : bool { + MASTER = true, + SLAVE = false, + } + + consteval GPIODomain::AlternateFunction get_af(GPIODomain::Pin &pin, SPIPeripheral peripheral) { + if (peripheral == SPIPeripheral::spi2) { + if (pin == PB4) return GPIODomain::AlternateFunction::AF7; + } + if (peripheral == SPIPeripheral::spi3) { + if (pin == PA4) return GPIODomain::AlternateFunction::AF6; + if (pin == PA15) return GPIODomain::AlternateFunction::AF6; + if (pin == PB2) return GPIODomain::AlternateFunction::AF7; + if (pin == PB3) return GPIODomain::AlternateFunction::AF6; + if (pin == PB4) return GPIODomain::AlternateFunction::AF6; + if (pin == PB5) return GPIODomain::AlternateFunction::AF7; + if (pin == PC10) return GPIODomain::AlternateFunction::AF6; + if (pin == PC11) return GPIODomain::AlternateFunction::AF6; + if (pin == PC12) return GPIODomain::AlternateFunction::AF6; + } + if (peripheral == SPIPeripheral::spi6) { + if (pin == PA4) return GPIODomain::AlternateFunction::AF8; + if (pin == PA5) return GPIODomain::AlternateFunction::AF8; + if (pin == PA6) return GPIODomain::AlternateFunction::AF8; + if (pin == PA7) return GPIODomain::AlternateFunction::AF8; + if (pin == PA15) return GPIODomain::AlternateFunction::AF7; + if (pin == PB3) return GPIODomain::AlternateFunction::AF8; + if (pin == PB4) return GPIODomain::AlternateFunction::AF8; + if (pin == PB5) return GPIODomain::AlternateFunction::AF8; + } + + return GPIODomain::AlternateFunction::AF5; // Default AF for everything else + } + + static constexpr std::size_t max_instances{6}; + + struct Entry { + SPIPeripheral peripheral; + SPIMode mode; + + std::size_t sck_gpio_idx; + std::size_t miso_gpio_idx; + std::size_t mosi_gpio_idx; + std::size_t nss_gpio_idx; + + uint32_t max_baudrate; // Will set the baudrate as fast as possible under this value + + // DMA here, maybe? Depends on new DMA implementation + }; + + struct Config { + SPIPeripheral peripheral; + SPIMode mode; + + std::size_t sck_gpio_idx; + std::size_t miso_gpio_idx; + std::size_t mosi_gpio_idx; + std::size_t nss_gpio_idx; + + uint32_t max_baudrate; // Will set the baudrate as fast as possible under this value + + // DMA here, maybe? Depends on new DMA implementation + }; + + +/** + * ========================================= + * Instance (state holder) + * ========================================= + */ + struct Instance { + template friend struct Init; + + + + + private: + SPI_HandleTypeDef hspi; + SPI_TypeDef* instance; + GPIODomain::Instance& sck_gpio_instance; + GPIODomain::Instance& miso_gpio_instance; + GPIODomain::Instance& mosi_gpio_instance; + GPIODomain::Instance& nss_gpio_instance; + }; + + +/** + * ========================================= + * Request Object + * ========================================= + */ + struct Device { + using domain = SPIDomain; + + SPIPeripheral peripheral; + SPIMode mode; + + GPIODomain::GPIO sck_gpio; + GPIODomain::GPIO miso_gpio; + GPIODomain::GPIO mosi_gpio; + GPIODomain::GPIO nss_gpio; + + uint32_t max_baudrate; // Will set the baudrate as fast as possible under this value + + consteval Device(SPIMode mode, SPIPeripheral peripheral, uint32_t max_baudrate, + GPIODomain::Pin sck_pin, GPIODomain::Pin miso_pin, + GPIODomain::Pin mosi_pin, GPIODomain::Pin nss_pin) + : peripheral{peripheral}, mode{mode}, max_baudrate{max_baudrate} { + + switch (peripheral) { + case SPIPeripheral::spi1: + if (sck_pin != PB3 && + sck_pin != PG11 && + sck_pin != PA5) { + compile_error("Invalid SCK pin for SPI1"); + } + if (miso_pin != PB4 && + miso_pin != PG9 && + miso_pin != PA6) { + compile_error("Invalid MISO pin for SPI1"); + } + if (mosi_pin != PB5 && + mosi_pin != PD7 && + mosi_pin != PA7) { + compile_error("Invalid MOSI pin for SPI1"); + } + if (nss_pin != PG10 && + nss_pin != PA15 && + nss_pin != PA4) { + compile_error("Invalid NSS pin for SPI1"); + } + break; + + case SPIPeripheral::spi2: + if (sck_pin != PD3 && + sck_pin != PA12 && + sck_pin != PA9 && + sck_pin != PB13 && + sck_pin != PB10) { + compile_error("Invalid SCK pin for SPI2"); + } + if (miso_pin != PC2 && + miso_pin != PB14) { + compile_error("Invalid MISO pin for SPI2"); + } + if (mosi_pin != PC3 && + mosi_pin != PC1 && + mosi_pin != PB15) { + compile_error("Invalid MOSI pin for SPI2"); + } + if (nss_pin != PB9 && + nss_pin != PB4 && + nss_pin != PA11 && + nss_pin != PB12) { + compile_error("Invalid NSS pin for SPI2"); + } + break; + + case SPIPeripheral::spi3: + if (sck_pin != PB3 && + sck_pin != PC10) { + compile_error("Invalid SCK pin for SPI3"); + } + if (miso_pin != PB4 && + miso_pin != PC11) { + compile_error("Invalid MISO pin for SPI3"); + } + if (mosi_pin != PB5 && + mosi_pin != PD6 && + mosi_pin != PC12 && + mosi_pin != PB2) { + compile_error("Invalid MOSI pin for SPI3"); + } + if (nss_pin != PA15 && + nss_pin != PA4) { + compile_error("Invalid NSS pin for SPI3"); + } + break; + + case SPIPeripheral::spi4: + if (sck_pin != PE2 && + sck_pin != PE12) { + compile_error("Invalid SCK pin for SPI4"); + } + if (miso_pin != PE5 && + miso_pin != PE13) { + compile_error("Invalid MISO pin for SPI4"); + } + if (mosi_pin != PE6 && + mosi_pin != PE14) { + compile_error("Invalid MOSI pin for SPI4"); + } + if (nss_pin != PE4 && + nss_pin != PE11) { + compile_error("Invalid NSS pin for SPI4"); + } + break; + + case SPIPeripheral::spi5: + if (sck_pin != PF7) { + compile_error("Invalid SCK pin for SPI5"); + } + if (miso_pin != PF8) { + compile_error("Invalid MISO pin for SPI5"); + } + if (mosi_pin != PF9 && + mosi_pin != PF11) { + compile_error("Invalid MOSI pin for SPI5"); + } + if (nss_pin != PF6) { + compile_error("Invalid NSS pin for SPI5"); + } + break; + + case SPIPeripheral::spi6: + if (sck_pin != PB3 && + sck_pin != PG13 && + sck_pin != PC10 && + sck_pin != PA7) { + compile_error("Invalid SCK pin for SPI6"); + } + if (miso_pin != PB4 && + miso_pin != PG12 && + miso_pin != PA6) { + compile_error("Invalid MISO pin for SPI6"); + } + if (mosi_pin != PB5 && + mosi_pin != PG14 && + mosi_pin != PA7) { + compile_error("Invalid MOSI pin for SPI6"); + } + if (nss_pin != PA0 && + nss_pin != PA15 && + nss_pin != PG8 && + nss_pin != PA4) { + compile_error("Invalid NSS pin for SPI6"); + } + break; + + default: + compile_error("Invalid SPI peripheral specified in SPIDomain::Device"); + } + + sck_gpio = GPIODomain::GPIO{sck_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(sck_pin, peripheral)}; + miso_gpio = GPIODomain::GPIO{miso_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(miso_pin, peripheral)}; + mosi_gpio = GPIODomain::GPIO{mosi_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(mosi_pin, peripheral)}; + nss_gpio = GPIODomain::GPIO{nss_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(nss_pin, peripheral)}; + } + + template + consteval void inscribe(Ctx &ctx) const { + Entry e{ + .peripheral = peripheral, + .mode = mode, + .sck_gpio_idx = ctx.template add(sck_gpio.e), + .miso_gpio_idx = ctx.template add(miso_gpio.e), + .mosi_gpio_idx = ctx.template add(mosi_gpio.e), + .nss_gpio_idx = ctx.template add(nss_gpio.e), + }; + + ctx.template add(e); + } + }; + +/** + * ========================================= + * Internal working things + * ========================================= + */ + template + static consteval array build(span entries) { + array cfgs{}; + + if (N == 0) { + return cfgs; + } + + bool used_peripherals[6] = {false}; + + for (std::size_t i = 0; i < N; ++i) { + cfgs[i].peripheral = entries[i].peripheral; + cfgs[i].mode = entries[i].mode; + cfgs[i].sck_gpio_idx = entries[i].sck_gpio_idx; + cfgs[i].miso_gpio_idx = entries[i].miso_gpio_idx; + cfgs[i].mosi_gpio_idx = entries[i].mosi_gpio_idx; + cfgs[i].nss_gpio_idx = entries[i].nss_gpio_idx; + + if (peripheral == SPIPeripheral::spi1) { + if (used_peripherals[0]) { + compile_error("SPI1 peripheral already used"); + } + used_peripherals[0] = true; + } else if (peripheral == SPIPeripheral::spi2) { + if (used_peripherals[1]) { + compile_error("SPI2 peripheral already used"); + } + used_peripherals[1] = true; + } else if (peripheral == SPIPeripheral::spi3) { + if (used_peripherals[2]) { + compile_error("SPI3 peripheral already used"); + } + used_peripherals[2] = true; + } else if (peripheral == SPIPeripheral::spi4) { + if (used_peripherals[3]) { + compile_error("SPI4 peripheral already used"); + } + used_peripherals[3] = true; + } else if (peripheral == SPIPeripheral::spi5) { + if (used_peripherals[4]) { + compile_error("SPI5 peripheral already used"); + } + used_peripherals[4] = true; + } else if (peripheral == SPIPeripheral::spi6) { + if (used_peripherals[5]) { + compile_error("SPI6 peripheral already used"); + } + used_peripherals[5] = true; + } + } + + return cfgs; + } + + template + struct Init { + static inline std::array instances{}; + + static void init(std::span cfgs, + std::span gpio_instances) { + for (std::size_t i = 0; i < N; ++i) { + const auto &e = cfgs[i]; + + instances[i].sck_gpio_instance = gpio_instances[e.sck_gpio_idx]; + instances[i].miso_gpio_instance = gpio_instances[e.miso_gpio_idx]; + instances[i].mosi_gpio_instance = gpio_instances[e.mosi_gpio_idx]; + instances[i].nss_gpio_instance = gpio_instances[e.nss_gpio_idx]; + instances[i].instance = reinterpret_cast(e.peripheral); + + // Configure clock + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + if (peripheral == SPIPeripheral::spi1) { + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI1; + PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + ErrorHanlder("Unable to configure SPI%i clock", i+1); + } + __HAL_RCC_SPI1_CLK_ENABLE(); + } else if (peripheral == SPIPeripheral::spi2) { + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI2; + PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + ErrorHanlder("Unable to configure SPI%i clock", i+1); + } + __HAL_RCC_SPI2_CLK_ENABLE(); + } else if (peripheral == SPIPeripheral::spi3) { + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI3; + PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + ErrorHanlder("Unable to configure SPI%i clock", i+1); + } + __HAL_RCC_SPI3_CLK_ENABLE(); + } else if (peripheral == SPIPeripheral::spi4) { + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI4; + PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL2; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + ErrorHanlder("Unable to configure SPI%i clock", i+1); + } + __HAL_RCC_SPI4_CLK_ENABLE(); + } else if (peripheral == SPIPeripheral::spi5) { + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI5; + PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL2; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + ErrorHanlder("Unable to configure SPI%i clock", i+1); + } + __HAL_RCC_SPI5_CLK_ENABLE(); + } else if (peripheral == SPIPeripheral::spi6) { + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI6; + PeriphClkInitStruct.Spi6ClockSelection = RCC_SPI6CLKSOURCE_PLL2; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + ErrorHanlder("Unable to configure SPI%i clock", i+1); + } + __HAL_RCC_SPI6_CLK_ENABLE(); + } + + + auto hspi = instances[i].hspi; + hspi.Instance = instances[i].instance; + + auto init = hspi.Init; + if (e.mode == SPIMode::MASTER) { + init.Mode = SPI_MODE_MASTER; + init.NSS = SPI_NSS_HARD_OUTPUT; // Hardware control for now, should add software later for more flexibility + // Baudrate prescaler calculation + uint32_t pclk_freq; + if (peripheral == SPIPeripheral::spi1 || + peripheral == SPIPeripheral::spi2 || + peripheral == SPIPeripheral::spi3) { + pclk_freq = HAL_RCC_GetPLL1Freq(); // This function does not exist, I'll add the frequency actual getter later + } else { + pclk_freq = HAL_RCC_GetPLL2Freq(); // This function does not exist, I'll add the frequency actual getter later + } + } else { + init.Mode = SPI_MODE_SLAVE; + init.NSS = SPI_NSS_HARD_INPUT; + } + init.Direction = SPI_DIRECTION_2LINES; + init.DataSize = SPI_DATASIZE_8BIT; // Works with any data size (at least for bytes) + init.CLKPolarity = SPI_POLARITY_LOW; + init.CLKPhase = SPI_PHASE_1EDGE; + // Calculate BaudRatePrescaler + init.BaudRatePrescaler = // TODO + init.FirstBit = SPI_FIRSTBIT_MSB; // Must check if LSB first is needed for anything later + init.TIMode = SPI_TIMODE_DISABLE; // Texas Instruments mode, like, why would we use that? + init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; // Doesn't seem that useful here, better to handle CRC manually with the CRC peripheral if needed + init.CRCPolynomial = 0; // Nope + init.CRCLength = SPI_CRC_LENGTH_8BIT; // Doesn't matter since CRC calculation is disabled + init.NSSPMode = SPI_NSS_PULSE_DISABLE; // Hardcoded for now, may add a setting later + init.NSSPolarity = SPI_NSS_POLARITY_LOW; // Standard polarity + init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA; // 1 byte, since we're using 8 bit data size for safety, may add a setting later + init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN; + init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN; + init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE; + init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE; + init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE; // If you are having overrun issues, then you have a problem somewhere else + init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; // Keeps MOSI, MISO, SCK state when not communicating, ensure no floating lines and no random noise + init.IOSwap = SPI_IO_SWAP_DISABLE; // Should not be needed + + + if (HAL_SPI_Init(spi->hspi) != HAL_OK) { + ErrorHandler("Unable to init SPI%i", i+1); + return; + } + + // Enable NVIC + if (peripheral == SPIPeripheral::spi1) { + HAL_NVIC_SetPriority(SPI1_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(SPI1_IRQn); + } else if (peripheral == SPIPeripheral::spi2) { + HAL_NVIC_SetPriority(SPI2_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(SPI2_IRQn); + } else if (peripheral == SPIPeripheral::spi3) { + HAL_NVIC_SetPriority(SPI3_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(SPI3_IRQn); + } else if (peripheral == SPIPeripheral::spi4) { + HAL_NVIC_SetPriority(SPI4_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(SPI4_IRQn); + } else if (peripheral == SPIPeripheral::spi5) { + HAL_NVIC_SetPriority(SPI5_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(SPI5_IRQn); + } else if (peripheral == SPIPeripheral::spi6) { + HAL_NVIC_SetPriority(SPI6_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(SPI6_IRQn); + } + } + } + + }; +}; + +} // namespace ST_LIB + +// IRQ Handlers, won't use HAL callbacks, will use LL for all the main work, HAL just for init + +extern "C" { + +void SPI1_IRQHandler(void) { + // Implementation to be done +} +void SPI2_IRQHandler(void) { + // Implementation to be done +} +void SPI3_IRQHandler(void) { + // Implementation to be done +} +void SPI4_IRQHandler(void) { + // Implementation to be done +} +void SPI5_IRQHandler(void) { + // Implementation to be done +} +void SPI6_IRQHandler(void) { + // Implementation to be done +} + +} + +#endif // SPI2_HPP \ No newline at end of file From f5cb0297023e7726baadb2e64ee2d759f1e01cda Mon Sep 17 00:00:00 2001 From: Foniks Date: Sun, 28 Dec 2025 22:00:41 +0100 Subject: [PATCH 068/109] feat(SPI): Baudrate prescaler calculation --- Inc/HALAL/Models/SPI2.hpp | 50 +++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/Inc/HALAL/Models/SPI2.hpp b/Inc/HALAL/Models/SPI2.hpp index 2f15e21e5..a34366124 100644 --- a/Inc/HALAL/Models/SPI2.hpp +++ b/Inc/HALAL/Models/SPI2.hpp @@ -67,6 +67,40 @@ struct SPIDomain { return GPIODomain::AlternateFunction::AF5; // Default AF for everything else } + static constexpr uint32_t get_prescaler_flag(uint32_t prescaler) { + switch (prescaler) { + case 2: return SPI_BAUDRATEPRESCALER_2; + case 4: return SPI_BAUDRATEPRESCALER_4; + case 8: return SPI_BAUDRATEPRESCALER_8; + case 16: return SPI_BAUDRATEPRESCALER_16; + case 32: return SPI_BAUDRATEPRESCALER_32; + case 64: return SPI_BAUDRATEPRESCALER_64; + case 128: return SPI_BAUDRATEPRESCALER_128; + case 256: return SPI_BAUDRATEPRESCALER_256; + default: + if consteval { + compile_error("Invalid prescaler value"); + } else { + ErrorHandler("Invalid prescaler value"); + return SPI_BAUDRATEPRESCALER_256; + } + } + } + + static uint32_t calculate_prescaler(uint32_t src_freq, uint32_t max_baud) { + uint32_t prescaler = 2; // Smallest prescaler available + + while ((src_freq / prescaler) > max_baud) { + prescaler *= 2; // Prescaler doubles each step (it must be a power of 2) + + if (prescaler > 256) { + ErrorHandler("Cannot achieve desired baudrate, speed is too low"); + } + } + + return get_prescaler_flag(prescaler); + } + static constexpr std::size_t max_instances{6}; struct Entry { @@ -365,10 +399,7 @@ struct SPIDomain { for (std::size_t i = 0; i < N; ++i) { const auto &e = cfgs[i]; - instances[i].sck_gpio_instance = gpio_instances[e.sck_gpio_idx]; - instances[i].miso_gpio_instance = gpio_instances[e.miso_gpio_idx]; - instances[i].mosi_gpio_instance = gpio_instances[e.mosi_gpio_idx]; - instances[i].nss_gpio_instance = gpio_instances[e.nss_gpio_idx]; + SPIPeripheral peripheral = e.peripheral; instances[i].instance = reinterpret_cast(e.peripheral); // Configure clock @@ -430,10 +461,15 @@ struct SPIDomain { if (peripheral == SPIPeripheral::spi1 || peripheral == SPIPeripheral::spi2 || peripheral == SPIPeripheral::spi3) { - pclk_freq = HAL_RCC_GetPLL1Freq(); // This function does not exist, I'll add the frequency actual getter later + pclk_freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123); + } else if (peripheral == SPIPeripheral::spi4 || + peripheral == SPIPeripheral::spi5) { + pclk_freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45); } else { - pclk_freq = HAL_RCC_GetPLL2Freq(); // This function does not exist, I'll add the frequency actual getter later + pclk_freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6); } + init.BaudRatePrescaler = calculate_prescaler(pclk_freq, e.max_baudrate); + } else { init.Mode = SPI_MODE_SLAVE; init.NSS = SPI_NSS_HARD_INPUT; @@ -454,7 +490,7 @@ struct SPIDomain { init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA; // 1 byte, since we're using 8 bit data size for safety, may add a setting later init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN; init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN; - init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE; + init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE; // Should check if this works or the peripheral needs some delay init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE; init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE; // If you are having overrun issues, then you have a problem somewhere else init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; // Keeps MOSI, MISO, SCK state when not communicating, ensure no floating lines and no random noise From efbf9c07d4e02a87f1375188ebffafa15796abce Mon Sep 17 00:00:00 2001 From: Foniks Date: Sun, 28 Dec 2025 22:06:10 +0100 Subject: [PATCH 069/109] feat(SPI): Add IRQ handlers and HAL callbacks --- Inc/HALAL/Models/SPI2.hpp | 41 +++++-------- Src/HALAL/Models/SPI2.cpp | 118 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 26 deletions(-) create mode 100644 Src/HALAL/Models/SPI2.cpp diff --git a/Inc/HALAL/Models/SPI2.hpp b/Inc/HALAL/Models/SPI2.hpp index a34366124..18215c12c 100644 --- a/Inc/HALAL/Models/SPI2.hpp +++ b/Inc/HALAL/Models/SPI2.hpp @@ -14,6 +14,8 @@ using ST_LIB::GPIODomain; +extern ST_LIB::SPIDomain::Instance* spi_instances[ST_LIB::SPIDomain::max_instances]; + namespace ST_LIB { struct SPIDomain { @@ -402,7 +404,7 @@ struct SPIDomain { SPIPeripheral peripheral = e.peripheral; instances[i].instance = reinterpret_cast(e.peripheral); - // Configure clock + // Configure clock and store handle RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; if (peripheral == SPIPeripheral::spi1) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI1; @@ -411,6 +413,8 @@ struct SPIDomain { ErrorHanlder("Unable to configure SPI%i clock", i+1); } __HAL_RCC_SPI1_CLK_ENABLE(); + + spi_instances[0] = &instances[i]; } else if (peripheral == SPIPeripheral::spi2) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI2; PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; @@ -418,6 +422,8 @@ struct SPIDomain { ErrorHanlder("Unable to configure SPI%i clock", i+1); } __HAL_RCC_SPI2_CLK_ENABLE(); + + spi_instances[1] = &instances[i]; } else if (peripheral == SPIPeripheral::spi3) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI3; PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; @@ -425,6 +431,8 @@ struct SPIDomain { ErrorHanlder("Unable to configure SPI%i clock", i+1); } __HAL_RCC_SPI3_CLK_ENABLE(); + + spi_instances[2] = &instances[i]; } else if (peripheral == SPIPeripheral::spi4) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI4; PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL2; @@ -432,6 +440,8 @@ struct SPIDomain { ErrorHanlder("Unable to configure SPI%i clock", i+1); } __HAL_RCC_SPI4_CLK_ENABLE(); + + spi_instances[3] = &instances[i]; } else if (peripheral == SPIPeripheral::spi5) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI5; PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL2; @@ -439,6 +449,8 @@ struct SPIDomain { ErrorHanlder("Unable to configure SPI%i clock", i+1); } __HAL_RCC_SPI5_CLK_ENABLE(); + + spi_instances[4] = &instances[i]; } else if (peripheral == SPIPeripheral::spi6) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI6; PeriphClkInitStruct.Spi6ClockSelection = RCC_SPI6CLKSOURCE_PLL2; @@ -446,6 +458,8 @@ struct SPIDomain { ErrorHanlder("Unable to configure SPI%i clock", i+1); } __HAL_RCC_SPI6_CLK_ENABLE(); + + spi_instances[5] = &instances[i]; } @@ -524,35 +538,10 @@ struct SPIDomain { } } } - }; }; } // namespace ST_LIB -// IRQ Handlers, won't use HAL callbacks, will use LL for all the main work, HAL just for init - -extern "C" { - -void SPI1_IRQHandler(void) { - // Implementation to be done -} -void SPI2_IRQHandler(void) { - // Implementation to be done -} -void SPI3_IRQHandler(void) { - // Implementation to be done -} -void SPI4_IRQHandler(void) { - // Implementation to be done -} -void SPI5_IRQHandler(void) { - // Implementation to be done -} -void SPI6_IRQHandler(void) { - // Implementation to be done -} - -} #endif // SPI2_HPP \ No newline at end of file diff --git a/Src/HALAL/Models/SPI2.cpp b/Src/HALAL/Models/SPI2.cpp new file mode 100644 index 000000000..aef3458a1 --- /dev/null +++ b/Src/HALAL/Models/SPI2.cpp @@ -0,0 +1,118 @@ +#include "HALAL/Models/SPI2.hpp" + +ST_LIB::SPIDomain::Instance* spi_instances[ST_LIB::SPIDomain::max_instances]; + +extern "C" { + +/** + * ========================================= + * IRQ Handlers + * ========================================= + */ + +void SPI1_IRQHandler(void) { + auto inst = ST_LIB::spi_instances[0]; + if (inst == nullptr) { + ErrorHandler("SPI1 IRQ Handler called but instance is null"); + return; + } + HAL_SPI_IRQHandler(&inst->hspi); +} +void SPI2_IRQHandler(void) { + auto inst = ST_LIB::spi_instances[1]; + if (inst == nullptr) { + ErrorHandler("SPI2 IRQ Handler called but instance is null"); + return; + } + HAL_SPI_IRQHandler(&inst->hspi); +} +void SPI3_IRQHandler(void) { + auto inst = ST_LIB::spi_instances[2]; + if (inst == nullptr) { + ErrorHandler("SPI3 IRQ Handler called but instance is null"); + return; + } + HAL_SPI_IRQHandler(&inst->hspi); +} +void SPI4_IRQHandler(void) { + auto inst = ST_LIB::spi_instances[3]; + if (inst == nullptr) { + ErrorHandler("SPI4 IRQ Handler called but instance is null"); + return; + } + HAL_SPI_IRQHandler(&inst->hspi); +} +void SPI5_IRQHandler(void) { + auto inst = ST_LIB::spi_instances[4]; + if (inst == nullptr) { + ErrorHandler("SPI5 IRQ Handler called but instance is null"); + return; + } + HAL_SPI_IRQHandler(&inst->hspi); +} +void SPI6_IRQHandler(void) { + auto inst = ST_LIB::spi_instances[5]; + if (inst == nullptr) { + ErrorHandler("SPI6 IRQ Handler called but instance is null"); + return; + } + HAL_SPI_IRQHandler(&inst->hspi); +} + + +/** + * ========================================= + * HAL Callbacks + * ========================================= + */ + +void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) { + ST_LIB::SPIDomain::Instance* inst = nullptr; + if (hspi == spi_instances[0]->hspi) { + inst = spi_instances[0]; + } else if (hspi == spi_instances[1]->hspi) { + inst = spi_instances[1]; + } else if (hspi == spi_instances[2]->hspi) { + inst = spi_instances[2]; + } else if (hspi == spi_instances[3]->hspi) { + inst = spi_instances[3]; + } else if (hspi == spi_instances[4]->hspi) { + inst = spi_instances[4]; + } else if (hspi == spi_instances[5]->hspi) { + inst = spi_instances[5]; + } + + if (inst->operation_flag != nullptr) { + *(inst->operation_flag) = true; + } +} + +void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) { + HAL_SPI_TxCpltCallback(hspi); // Same logic +} + +void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { + HAL_SPI_TxCpltCallback(hspi); // Same logic +} + +void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { + uint32_t error_code = hspi->ErrorCode; + uint32_t inst_idx = 0; + if (hspi == spi_instances[0]->hspi) { + inst_idx = 0; + } else if (hspi == spi_instances[1]->hspi) { + inst_idx = 1; + } else if (hspi == spi_instances[2]->hspi) { + inst_idx = 2; + } else if (hspi == spi_instances[3]->hspi) { + inst_idx = 3; + } else if (hspi == spi_instances[4]->hspi) { + inst_idx = 4; + } else if (hspi == spi_instances[5]->hspi) { + inst_idx = 5; + } + + ErrorHandler("SPI%i failed with error number %u", inst_idx + 1, error_code); +} + +} \ No newline at end of file From 2c95ba0fb683bddc2f1b738568473b857046a369 Mon Sep 17 00:00:00 2001 From: Foniks Date: Sun, 28 Dec 2025 22:38:32 +0100 Subject: [PATCH 070/109] fix(SPI): Fix error spi number --- Inc/HALAL/Models/SPI2.hpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Inc/HALAL/Models/SPI2.hpp b/Inc/HALAL/Models/SPI2.hpp index 18215c12c..23920c27b 100644 --- a/Inc/HALAL/Models/SPI2.hpp +++ b/Inc/HALAL/Models/SPI2.hpp @@ -406,6 +406,7 @@ struct SPIDomain { // Configure clock and store handle RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + uint8_t spi_number = 0; if (peripheral == SPIPeripheral::spi1) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI1; PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; @@ -414,7 +415,7 @@ struct SPIDomain { } __HAL_RCC_SPI1_CLK_ENABLE(); - spi_instances[0] = &instances[i]; + spi_number = 1; } else if (peripheral == SPIPeripheral::spi2) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI2; PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; @@ -423,7 +424,7 @@ struct SPIDomain { } __HAL_RCC_SPI2_CLK_ENABLE(); - spi_instances[1] = &instances[i]; + spi_number = 2; } else if (peripheral == SPIPeripheral::spi3) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI3; PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; @@ -432,7 +433,7 @@ struct SPIDomain { } __HAL_RCC_SPI3_CLK_ENABLE(); - spi_instances[2] = &instances[i]; + spi_number = 3; } else if (peripheral == SPIPeripheral::spi4) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI4; PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL2; @@ -441,7 +442,7 @@ struct SPIDomain { } __HAL_RCC_SPI4_CLK_ENABLE(); - spi_instances[3] = &instances[i]; + spi_number = 4; } else if (peripheral == SPIPeripheral::spi5) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI5; PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL2; @@ -450,7 +451,7 @@ struct SPIDomain { } __HAL_RCC_SPI5_CLK_ENABLE(); - spi_instances[4] = &instances[i]; + spi_number = 5; } else if (peripheral == SPIPeripheral::spi6) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI6; PeriphClkInitStruct.Spi6ClockSelection = RCC_SPI6CLKSOURCE_PLL2; @@ -459,9 +460,10 @@ struct SPIDomain { } __HAL_RCC_SPI6_CLK_ENABLE(); - spi_instances[5] = &instances[i]; + spi_number = 6; } + spi_instances[spi_number - 1] = &instances[i]; auto hspi = instances[i].hspi; hspi.Instance = instances[i].instance; @@ -511,8 +513,8 @@ struct SPIDomain { init.IOSwap = SPI_IO_SWAP_DISABLE; // Should not be needed - if (HAL_SPI_Init(spi->hspi) != HAL_OK) { - ErrorHandler("Unable to init SPI%i", i+1); + if (HAL_SPI_Init(&hspi) != HAL_OK) { + ErrorHandler("Unable to init SPI%u", spi_number); return; } From a2f06398807921c404c2afbac0e248eb5f26d2d1 Mon Sep 17 00:00:00 2001 From: Foniks Date: Sun, 28 Dec 2025 22:40:28 +0100 Subject: [PATCH 071/109] fix(SPI): Callback handling --- Src/HALAL/Models/SPI2.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/Src/HALAL/Models/SPI2.cpp b/Src/HALAL/Models/SPI2.cpp index aef3458a1..f9850d505 100644 --- a/Src/HALAL/Models/SPI2.cpp +++ b/Src/HALAL/Models/SPI2.cpp @@ -68,18 +68,21 @@ void SPI6_IRQHandler(void) { void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) { ST_LIB::SPIDomain::Instance* inst = nullptr; - if (hspi == spi_instances[0]->hspi) { + if (spi_instances[0] != nullptr && hspi == &spi_instances[0]->hspi) { inst = spi_instances[0]; - } else if (hspi == spi_instances[1]->hspi) { + } else if (spi_instances[1] != nullptr && hspi == &spi_instances[1]->hspi) { inst = spi_instances[1]; - } else if (hspi == spi_instances[2]->hspi) { + } else if (spi_instances[2] != nullptr && hspi == &spi_instances[2]->hspi) { inst = spi_instances[2]; - } else if (hspi == spi_instances[3]->hspi) { + } else if (spi_instances[3] != nullptr && hspi == &spi_instances[3]->hspi) { inst = spi_instances[3]; - } else if (hspi == spi_instances[4]->hspi) { + } else if (spi_instances[4] != nullptr && hspi == &spi_instances[4]->hspi) { inst = spi_instances[4]; - } else if (hspi == spi_instances[5]->hspi) { + } else if (spi_instances[5] != nullptr && hspi == &spi_instances[5]->hspi) { inst = spi_instances[5]; + } else { + ErrorHandler("SPI IRQ Callback called but instance is null"); + return; } if (inst->operation_flag != nullptr) { @@ -98,18 +101,21 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { uint32_t error_code = hspi->ErrorCode; uint32_t inst_idx = 0; - if (hspi == spi_instances[0]->hspi) { + if (spi_instances[0] != nullptr && hspi == &spi_instances[0]->hspi) { inst_idx = 0; - } else if (hspi == spi_instances[1]->hspi) { + } else if (spi_instances[1] != nullptr && hspi == &spi_instances[1]->hspi) { inst_idx = 1; - } else if (hspi == spi_instances[2]->hspi) { + } else if (spi_instances[2] != nullptr && hspi == &spi_instances[2]->hspi) { inst_idx = 2; - } else if (hspi == spi_instances[3]->hspi) { + } else if (spi_instances[3] != nullptr && hspi == &spi_instances[3]->hspi) { inst_idx = 3; - } else if (hspi == spi_instances[4]->hspi) { + } else if (spi_instances[4] != nullptr && hspi == &spi_instances[4]->hspi) { inst_idx = 4; - } else if (hspi == spi_instances[5]->hspi) { + } else if (spi_instances[5] != nullptr && hspi == &spi_instances[5]->hspi) { inst_idx = 5; + } else { + ErrorHandler("SPI IRQ Callback called but instance is null"); + return; } ErrorHandler("SPI%i failed with error number %u", inst_idx + 1, error_code); From 8ca8bdebedbb43f474e2272e43c3ef2592b43b81 Mon Sep 17 00:00:00 2001 From: Foniks Date: Sun, 28 Dec 2025 22:40:47 +0100 Subject: [PATCH 072/109] feat(SPI): Implement API for both Master and Slave --- Inc/HALAL/Models/SPI2.hpp | 135 ++++++++++++++++++++++++++++++++------ 1 file changed, 114 insertions(+), 21 deletions(-) diff --git a/Inc/HALAL/Models/SPI2.hpp b/Inc/HALAL/Models/SPI2.hpp index 23920c27b..a1be6996c 100644 --- a/Inc/HALAL/Models/SPI2.hpp +++ b/Inc/HALAL/Models/SPI2.hpp @@ -134,27 +134,6 @@ struct SPIDomain { }; -/** - * ========================================= - * Instance (state holder) - * ========================================= - */ - struct Instance { - template friend struct Init; - - - - - private: - SPI_HandleTypeDef hspi; - SPI_TypeDef* instance; - GPIODomain::Instance& sck_gpio_instance; - GPIODomain::Instance& miso_gpio_instance; - GPIODomain::Instance& mosi_gpio_instance; - GPIODomain::Instance& nss_gpio_instance; - }; - - /** * ========================================= * Request Object @@ -333,6 +312,120 @@ struct SPIDomain { } }; + +/** + * ========================================= + * Instance (state holder) + * ========================================= + */ + struct Instance { + template friend struct Init; + template friend struct SPIWrapper; + friend void ::SPI1_IRQHandler(void); + friend void ::SPI2_IRQHandler(void); + friend void ::SPI3_IRQHandler(void); + friend void ::SPI4_IRQHandler(void); + friend void ::SPI5_IRQHandler(void); + friend void ::SPI6_IRQHandler(void); + + private: + SPI_HandleTypeDef hspi; + SPI_TypeDef* instance; + + volatile bool* operation_flag; + }; + + +/** + * ========================================= + * Wrapper, public API + * ========================================= + */ + + template requires(device_request.mode == SPIMode::MASTER) + struct SPIWrapper { + SPIWrapper(Instance &instance) : spi_instance{instance} {} + + bool send(span data) { + auto error_code = HAL_SPI_Transmit(&spi_instance.hspi, data.data(), data.size(), 10); + return check_error_code(error_code); + } + bool receive(span data) { + auto error_code = HAL_SPI_Receive(&spi_instance.hspi, data.data(), data.size(), 10); + return check_error_code(error_code); + } + bool transceive(span tx_data, span rx_data) { + auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, tx_data.data(), rx_data.data(), tx_data.size(), 10); + return check_error_code(error_code); + } + + bool send_DMA(span data, volatile bool* operation_flag = nullptr) { + spi_instance.operation_flag = operation_flag; + auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, data.data(), data.size()); + return check_error_code(error_code); + } + bool receive_DMA(span data, volatile bool* operation_flag = nullptr) { + spi_instance.operation_flag = operation_flag; + auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, data.data(), data.size()); + return check_error_code(error_code); + } + bool transceive_DMA(span tx_data, span rx_data, volatile bool* operation_flag = nullptr) { + spi_instance.operation_flag = operation_flag; + auto size = std::min(tx_data.size(), rx_data.size()); + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, tx_data.data(), rx_data.data(), size); + return check_error_code(error_code); + } + + private: + Instance& spi_instance; + bool check_error_code(HAL_StatusTypeDef error_code) { + if (error_code == HAL_OK) { + return true; + } else if (error_code == HAL_BUSY) { + return false; + } else { + ErrorHandler("SPI transmit error: %u", static_cast(error_code)); + return false; + } + } + }; + + template requires(device_request.mode == SPIMode::SLAVE) + struct SPIWrapper { + SPIWrapper(Instance &instance) : spi_instance{instance} {} + + bool listen(span data, volatile bool* operation_flag = nullptr) { + spi_instance.operation_flag = operation_flag; + auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, data.data(), data.size()); + return check_error_code(error_code); + } + bool arm(span tx_data, volatile bool* operation_flag = nullptr) { + spi_instance.operation_flag = operation_flag; + auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, tx_data.data(), tx_data.size()); + return check_error_code(error_code); + } + bool transceive(span tx_data, span rx_data, volatile bool* operation_flag = nullptr) { + spi_instance.operation_flag = operation_flag; + auto size = std::min(tx_data.size(), rx_data.size()); + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, tx_data.data(), rx_data.data(), size); + return check_error_code(error_code); + } + + private: + Instance& spi_instance; + bool check_error_code(HAL_StatusTypeDef error_code) { + if (error_code == HAL_OK) { + return true; + } else if (error_code == HAL_BUSY) { + return false; + } else { + ErrorHandler("SPI transmit error: %u", static_cast(error_code)); + return false; + } + } + }; + + /** * ========================================= * Internal working things From baaf149c8380f1e36fc5c3df721e5b0b54d5b664 Mon Sep 17 00:00:00 2001 From: Foniks Date: Sun, 28 Dec 2025 22:45:11 +0100 Subject: [PATCH 073/109] doc(SPI): Add tooltip comments --- Inc/HALAL/Models/SPI2.hpp | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Inc/HALAL/Models/SPI2.hpp b/Inc/HALAL/Models/SPI2.hpp index a1be6996c..a2c9d96c1 100644 --- a/Inc/HALAL/Models/SPI2.hpp +++ b/Inc/HALAL/Models/SPI2.hpp @@ -342,33 +342,59 @@ struct SPIDomain { * ========================================= */ + /** + * @brief SPI Wrapper for Master mode operations. + */ template requires(device_request.mode == SPIMode::MASTER) struct SPIWrapper { SPIWrapper(Instance &instance) : spi_instance{instance} {} + /** + * @brief Sends data over SPI in blocking mode. + */ bool send(span data) { auto error_code = HAL_SPI_Transmit(&spi_instance.hspi, data.data(), data.size(), 10); return check_error_code(error_code); } + + /** + * @brief Receives data over SPI in blocking mode. + */ bool receive(span data) { auto error_code = HAL_SPI_Receive(&spi_instance.hspi, data.data(), data.size(), 10); return check_error_code(error_code); } + + /** + * @brief Sends and receives data over SPI in blocking mode. + */ bool transceive(span tx_data, span rx_data) { auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, tx_data.data(), rx_data.data(), tx_data.size(), 10); return check_error_code(error_code); } + + /** + * @brief Sends data over SPI using DMA, uses an optional operation flag to signal completion. + */ bool send_DMA(span data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, data.data(), data.size()); return check_error_code(error_code); } + + /** + * @brief Receives data over SPI using DMA, uses an optional operation flag to signal completion. + */ bool receive_DMA(span data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, data.data(), data.size()); return check_error_code(error_code); } + + /** + * @brief Sends and receives data over SPI using DMA, uses an optional operation flag to signal completion. + */ bool transceive_DMA(span tx_data, span rx_data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; auto size = std::min(tx_data.size(), rx_data.size()); @@ -390,20 +416,34 @@ struct SPIDomain { } }; + /** + * @brief SPI Wrapper for Slave mode operations. Doesn't allow for blocking operations. + */ template requires(device_request.mode == SPIMode::SLAVE) struct SPIWrapper { SPIWrapper(Instance &instance) : spi_instance{instance} {} + /** + * @brief Listens for data over SPI using DMA, uses an optional operation flag to signal completion. + */ bool listen(span data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, data.data(), data.size()); return check_error_code(error_code); } + + /** + * @brief Arms the SPI to send data over DMA when requested, uses an optional operation flag to signal completion. + */ bool arm(span tx_data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, tx_data.data(), tx_data.size()); return check_error_code(error_code); } + + /** + * @brief Sends and receives data over SPI using DMA, uses an optional operation flag to signal completion. + */ bool transceive(span tx_data, span rx_data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; auto size = std::min(tx_data.size(), rx_data.size()); From b0e15161ac5efde5f0001a202e4bc60a8207e211 Mon Sep 17 00:00:00 2001 From: Foniks Date: Sun, 28 Dec 2025 22:59:59 +0100 Subject: [PATCH 074/109] fix(SPI): Typo in ErrorHandler function name --- Inc/HALAL/Models/SPI2.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Inc/HALAL/Models/SPI2.hpp b/Inc/HALAL/Models/SPI2.hpp index a2c9d96c1..d251c170e 100644 --- a/Inc/HALAL/Models/SPI2.hpp +++ b/Inc/HALAL/Models/SPI2.hpp @@ -544,7 +544,7 @@ struct SPIDomain { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI1; PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - ErrorHanlder("Unable to configure SPI%i clock", i+1); + ErrorHandler("Unable to configure SPI%i clock", i+1); } __HAL_RCC_SPI1_CLK_ENABLE(); @@ -553,7 +553,7 @@ struct SPIDomain { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI2; PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - ErrorHanlder("Unable to configure SPI%i clock", i+1); + ErrorHandler("Unable to configure SPI%i clock", i+1); } __HAL_RCC_SPI2_CLK_ENABLE(); @@ -562,7 +562,7 @@ struct SPIDomain { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI3; PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - ErrorHanlder("Unable to configure SPI%i clock", i+1); + ErrorHandler("Unable to configure SPI%i clock", i+1); } __HAL_RCC_SPI3_CLK_ENABLE(); @@ -571,7 +571,7 @@ struct SPIDomain { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI4; PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL2; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - ErrorHanlder("Unable to configure SPI%i clock", i+1); + ErrorHandler("Unable to configure SPI%i clock", i+1); } __HAL_RCC_SPI4_CLK_ENABLE(); @@ -580,7 +580,7 @@ struct SPIDomain { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI5; PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL2; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - ErrorHanlder("Unable to configure SPI%i clock", i+1); + ErrorHandler("Unable to configure SPI%i clock", i+1); } __HAL_RCC_SPI5_CLK_ENABLE(); @@ -589,7 +589,7 @@ struct SPIDomain { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI6; PeriphClkInitStruct.Spi6ClockSelection = RCC_SPI6CLKSOURCE_PLL2; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - ErrorHanlder("Unable to configure SPI%i clock", i+1); + ErrorHandler("Unable to configure SPI%i clock", i+1); } __HAL_RCC_SPI6_CLK_ENABLE(); From d6595a397a1fbb5721e312f32bee509d30b517cc Mon Sep 17 00:00:00 2001 From: Foniks Date: Sun, 28 Dec 2025 23:07:09 +0100 Subject: [PATCH 075/109] fix(SPI): Move spi_instances declaration --- Inc/HALAL/Models/SPI2.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Inc/HALAL/Models/SPI2.hpp b/Inc/HALAL/Models/SPI2.hpp index d251c170e..ed1757a47 100644 --- a/Inc/HALAL/Models/SPI2.hpp +++ b/Inc/HALAL/Models/SPI2.hpp @@ -14,7 +14,6 @@ using ST_LIB::GPIODomain; -extern ST_LIB::SPIDomain::Instance* spi_instances[ST_LIB::SPIDomain::max_instances]; namespace ST_LIB { @@ -336,6 +335,7 @@ struct SPIDomain { }; + static inline Instance* spi_instances[max_instances]; /** * ========================================= * Wrapper, public API From 7f0e3d8d4f7256cdfebb43918d65a8121e9b4ac6 Mon Sep 17 00:00:00 2001 From: Foniks Date: Sun, 28 Dec 2025 23:32:51 +0100 Subject: [PATCH 076/109] fix(SPI): General syntax errror fixes --- Inc/HALAL/Models/SPI2.hpp | 204 ++++++++++++++++++++------------------ 1 file changed, 105 insertions(+), 99 deletions(-) diff --git a/Inc/HALAL/Models/SPI2.hpp b/Inc/HALAL/Models/SPI2.hpp index ed1757a47..3f26b5575 100644 --- a/Inc/HALAL/Models/SPI2.hpp +++ b/Inc/HALAL/Models/SPI2.hpp @@ -37,32 +37,37 @@ struct SPIDomain { enum class SPIMode : bool { MASTER = true, SLAVE = false, + }; + + static bool compare_pin(const GPIODomain::Pin &p1, const GPIODomain::Pin &p2) { + return (p1.port == p2.port) && (p1.pin == p2.pin); } - consteval GPIODomain::AlternateFunction get_af(GPIODomain::Pin &pin, SPIPeripheral peripheral) { + static consteval GPIODomain::AlternateFunction get_af(const GPIODomain::Pin &pin, SPIPeripheral peripheral) { + if (peripheral == SPIPeripheral::spi2) { - if (pin == PB4) return GPIODomain::AlternateFunction::AF7; + if (compare_pin(pin, PB4)) return GPIODomain::AlternateFunction::AF7; } if (peripheral == SPIPeripheral::spi3) { - if (pin == PA4) return GPIODomain::AlternateFunction::AF6; - if (pin == PA15) return GPIODomain::AlternateFunction::AF6; - if (pin == PB2) return GPIODomain::AlternateFunction::AF7; - if (pin == PB3) return GPIODomain::AlternateFunction::AF6; - if (pin == PB4) return GPIODomain::AlternateFunction::AF6; - if (pin == PB5) return GPIODomain::AlternateFunction::AF7; - if (pin == PC10) return GPIODomain::AlternateFunction::AF6; - if (pin == PC11) return GPIODomain::AlternateFunction::AF6; - if (pin == PC12) return GPIODomain::AlternateFunction::AF6; + if (compare_pin(pin, PA4)) return GPIODomain::AlternateFunction::AF6; + if (compare_pin(pin, PA15)) return GPIODomain::AlternateFunction::AF6; + if (compare_pin(pin, PB2)) return GPIODomain::AlternateFunction::AF7; + if (compare_pin(pin, PB3)) return GPIODomain::AlternateFunction::AF6; + if (compare_pin(pin, PB4)) return GPIODomain::AlternateFunction::AF6; + if (compare_pin(pin, PB5)) return GPIODomain::AlternateFunction::AF7; + if (compare_pin(pin, PC10)) return GPIODomain::AlternateFunction::AF6; + if (compare_pin(pin, PC11)) return GPIODomain::AlternateFunction::AF6; + if (compare_pin(pin, PC12)) return GPIODomain::AlternateFunction::AF6; } if (peripheral == SPIPeripheral::spi6) { - if (pin == PA4) return GPIODomain::AlternateFunction::AF8; - if (pin == PA5) return GPIODomain::AlternateFunction::AF8; - if (pin == PA6) return GPIODomain::AlternateFunction::AF8; - if (pin == PA7) return GPIODomain::AlternateFunction::AF8; - if (pin == PA15) return GPIODomain::AlternateFunction::AF7; - if (pin == PB3) return GPIODomain::AlternateFunction::AF8; - if (pin == PB4) return GPIODomain::AlternateFunction::AF8; - if (pin == PB5) return GPIODomain::AlternateFunction::AF8; + if (compare_pin(pin, PA4)) return GPIODomain::AlternateFunction::AF8; + if (compare_pin(pin, PA5)) return GPIODomain::AlternateFunction::AF8; + if (compare_pin(pin, PA6)) return GPIODomain::AlternateFunction::AF8; + if (compare_pin(pin, PA7)) return GPIODomain::AlternateFunction::AF8; + if (compare_pin(pin, PA15)) return GPIODomain::AlternateFunction::AF7; + if (compare_pin(pin, PB3)) return GPIODomain::AlternateFunction::AF8; + if (compare_pin(pin, PB4)) return GPIODomain::AlternateFunction::AF8; + if (compare_pin(pin, PB5)) return GPIODomain::AlternateFunction::AF8; } return GPIODomain::AlternateFunction::AF5; // Default AF for everything else @@ -143,145 +148,151 @@ struct SPIDomain { SPIPeripheral peripheral; SPIMode mode; + uint32_t max_baudrate; // Will set the baudrate as fast as possible under this value GPIODomain::GPIO sck_gpio; GPIODomain::GPIO miso_gpio; GPIODomain::GPIO mosi_gpio; GPIODomain::GPIO nss_gpio; - uint32_t max_baudrate; // Will set the baudrate as fast as possible under this value + consteval Device(SPIMode mode, SPIPeripheral peripheral, uint32_t max_baudrate, GPIODomain::Pin sck_pin, GPIODomain::Pin miso_pin, GPIODomain::Pin mosi_pin, GPIODomain::Pin nss_pin) - : peripheral{peripheral}, mode{mode}, max_baudrate{max_baudrate} { + : peripheral{peripheral}, mode{mode}, max_baudrate{max_baudrate}, + sck_gpio(sck_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(sck_pin, peripheral)), + miso_gpio(miso_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(miso_pin, peripheral)), + mosi_gpio(mosi_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(mosi_pin, peripheral)), + nss_gpio(nss_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(nss_pin, peripheral)) + { switch (peripheral) { case SPIPeripheral::spi1: - if (sck_pin != PB3 && - sck_pin != PG11 && - sck_pin != PA5) { + if (!compare_pin(sck_pin, PB3) && + !compare_pin(sck_pin, PG11) && + !compare_pin(sck_pin, PA5)) { compile_error("Invalid SCK pin for SPI1"); } - if (miso_pin != PB4 && - miso_pin != PG9 && - miso_pin != PA6) { + if (!compare_pin(miso_pin, PB4) && + !compare_pin(miso_pin, PG9) && + !compare_pin(miso_pin, PA6)) { compile_error("Invalid MISO pin for SPI1"); } - if (mosi_pin != PB5 && - mosi_pin != PD7 && - mosi_pin != PA7) { + if (!compare_pin(mosi_pin, PB5) && + !compare_pin(mosi_pin, PD7) && + !compare_pin(mosi_pin, PA7)) { compile_error("Invalid MOSI pin for SPI1"); } - if (nss_pin != PG10 && - nss_pin != PA15 && - nss_pin != PA4) { + if (!compare_pin(nss_pin, PG10) && + !compare_pin(nss_pin, PA15) && + !compare_pin(nss_pin, PA4)) { compile_error("Invalid NSS pin for SPI1"); } break; case SPIPeripheral::spi2: - if (sck_pin != PD3 && - sck_pin != PA12 && - sck_pin != PA9 && - sck_pin != PB13 && - sck_pin != PB10) { + if (!compare_pin(sck_pin, PD3) && + !compare_pin(sck_pin, PA12) && + !compare_pin(sck_pin, PA9) && + !compare_pin(sck_pin, PB13) && + !compare_pin(sck_pin, PB10)) { compile_error("Invalid SCK pin for SPI2"); } - if (miso_pin != PC2 && - miso_pin != PB14) { + if (!compare_pin(miso_pin, PC2) && + !compare_pin(miso_pin, PB14)) { compile_error("Invalid MISO pin for SPI2"); } - if (mosi_pin != PC3 && - mosi_pin != PC1 && - mosi_pin != PB15) { + if (!compare_pin(mosi_pin, PC3) && + !compare_pin(mosi_pin, PC1) && + !compare_pin(mosi_pin, PB15)) { compile_error("Invalid MOSI pin for SPI2"); } - if (nss_pin != PB9 && - nss_pin != PB4 && - nss_pin != PA11 && - nss_pin != PB12) { + if (!compare_pin(nss_pin, PB9) && + !compare_pin(nss_pin, PB4) && + !compare_pin(nss_pin, PA11) && + !compare_pin(nss_pin, PB12)) { compile_error("Invalid NSS pin for SPI2"); } break; case SPIPeripheral::spi3: - if (sck_pin != PB3 && - sck_pin != PC10) { + if (!compare_pin(sck_pin, PB3) && + !compare_pin(sck_pin, PC10)) { compile_error("Invalid SCK pin for SPI3"); } - if (miso_pin != PB4 && - miso_pin != PC11) { + if (!compare_pin(miso_pin, PB4) && + !compare_pin(miso_pin, PC11)) { compile_error("Invalid MISO pin for SPI3"); } - if (mosi_pin != PB5 && - mosi_pin != PD6 && - mosi_pin != PC12 && - mosi_pin != PB2) { + if (!compare_pin(mosi_pin, PB5) && + !compare_pin(mosi_pin, PD6) && + !compare_pin(mosi_pin, PC12) && + !compare_pin(mosi_pin, PB2)) { compile_error("Invalid MOSI pin for SPI3"); } - if (nss_pin != PA15 && - nss_pin != PA4) { + if (!compare_pin(nss_pin, PA15) && + !compare_pin(nss_pin, PA4)) { compile_error("Invalid NSS pin for SPI3"); } break; case SPIPeripheral::spi4: - if (sck_pin != PE2 && - sck_pin != PE12) { + if (!compare_pin(sck_pin, PE2) && + !compare_pin(sck_pin, PE12)) { compile_error("Invalid SCK pin for SPI4"); } - if (miso_pin != PE5 && - miso_pin != PE13) { + if (!compare_pin(miso_pin, PE5) && + !compare_pin(miso_pin, PE13)) { compile_error("Invalid MISO pin for SPI4"); } - if (mosi_pin != PE6 && - mosi_pin != PE14) { + if (!compare_pin(mosi_pin, PE6) && + !compare_pin(mosi_pin, PE14)) { compile_error("Invalid MOSI pin for SPI4"); } - if (nss_pin != PE4 && - nss_pin != PE11) { + if (!compare_pin(nss_pin, PE4) && + !compare_pin(nss_pin, PE11)) { compile_error("Invalid NSS pin for SPI4"); } break; case SPIPeripheral::spi5: - if (sck_pin != PF7) { + if (!compare_pin(sck_pin, PF7)) { compile_error("Invalid SCK pin for SPI5"); } - if (miso_pin != PF8) { + if (!compare_pin(miso_pin, PF8)) { compile_error("Invalid MISO pin for SPI5"); } - if (mosi_pin != PF9 && - mosi_pin != PF11) { + if (!compare_pin(mosi_pin, PF9) && + !compare_pin(mosi_pin, PF11)) { compile_error("Invalid MOSI pin for SPI5"); } - if (nss_pin != PF6) { + if (!compare_pin(nss_pin, PF6)) { compile_error("Invalid NSS pin for SPI5"); } break; case SPIPeripheral::spi6: - if (sck_pin != PB3 && - sck_pin != PG13 && - sck_pin != PC10 && - sck_pin != PA7) { + if (!compare_pin(sck_pin, PB3) && + !compare_pin(sck_pin, PG13) && + !compare_pin(sck_pin, PC10) && + !compare_pin(sck_pin, PA7)) { compile_error("Invalid SCK pin for SPI6"); } - if (miso_pin != PB4 && - miso_pin != PG12 && - miso_pin != PA6) { + if (!compare_pin(miso_pin, PB4) && + !compare_pin(miso_pin, PG12) && + !compare_pin(miso_pin, PA6)) { compile_error("Invalid MISO pin for SPI6"); } - if (mosi_pin != PB5 && - mosi_pin != PG14 && - mosi_pin != PA7) { + if (!compare_pin(mosi_pin, PB5) && + !compare_pin(mosi_pin, PG14) && + !compare_pin(mosi_pin, PA7)) { compile_error("Invalid MOSI pin for SPI6"); } - if (nss_pin != PA0 && - nss_pin != PA15 && - nss_pin != PG8 && - nss_pin != PA4) { + if (!compare_pin(nss_pin, PA0) && + !compare_pin(nss_pin, PA15) && + !compare_pin(nss_pin, PG8) && + !compare_pin(nss_pin, PA4)) { compile_error("Invalid NSS pin for SPI6"); } break; @@ -289,11 +300,6 @@ struct SPIDomain { default: compile_error("Invalid SPI peripheral specified in SPIDomain::Device"); } - - sck_gpio = GPIODomain::GPIO{sck_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(sck_pin, peripheral)}; - miso_gpio = GPIODomain::GPIO{miso_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(miso_pin, peripheral)}; - mosi_gpio = GPIODomain::GPIO{mosi_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(mosi_pin, peripheral)}; - nss_gpio = GPIODomain::GPIO{nss_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(nss_pin, peripheral)}; } template @@ -320,12 +326,6 @@ struct SPIDomain { struct Instance { template friend struct Init; template friend struct SPIWrapper; - friend void ::SPI1_IRQHandler(void); - friend void ::SPI2_IRQHandler(void); - friend void ::SPI3_IRQHandler(void); - friend void ::SPI4_IRQHandler(void); - friend void ::SPI5_IRQHandler(void); - friend void ::SPI6_IRQHandler(void); private: SPI_HandleTypeDef hspi; @@ -342,11 +342,15 @@ struct SPIDomain { * ========================================= */ + // SPI Wrapper primary template + template + struct SPIWrapper; + /** * @brief SPI Wrapper for Master mode operations. */ - template requires(device_request.mode == SPIMode::MASTER) - struct SPIWrapper { + template + struct SPIWrapper { SPIWrapper(Instance &instance) : spi_instance{instance} {} /** @@ -419,8 +423,8 @@ struct SPIDomain { /** * @brief SPI Wrapper for Slave mode operations. Doesn't allow for blocking operations. */ - template requires(device_request.mode == SPIMode::SLAVE) - struct SPIWrapper { + template + struct SPIWrapper { SPIWrapper(Instance &instance) : spi_instance{instance} {} /** @@ -489,6 +493,8 @@ struct SPIDomain { cfgs[i].mosi_gpio_idx = entries[i].mosi_gpio_idx; cfgs[i].nss_gpio_idx = entries[i].nss_gpio_idx; + auto peripheral = entries[i].peripheral; + if (peripheral == SPIPeripheral::spi1) { if (used_peripherals[0]) { compile_error("SPI1 peripheral already used"); From c090b4b890d7b227fc21a2dbd57ea8e0764792dd Mon Sep 17 00:00:00 2001 From: Foniks Date: Sun, 28 Dec 2025 23:33:12 +0100 Subject: [PATCH 077/109] feat(SPI): Add SPI domain to ST-LIB --- Inc/HALAL/HALAL.hpp | 1 + Inc/ST-LIB.hpp | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/Inc/HALAL/HALAL.hpp b/Inc/HALAL/HALAL.hpp index 316c9605a..a76251feb 100644 --- a/Inc/HALAL/HALAL.hpp +++ b/Inc/HALAL/HALAL.hpp @@ -27,6 +27,7 @@ #include "HALAL/Services/Encoder/Encoder.hpp" #include "HALAL/Services/EXTI/EXTI.hpp" +#include "HALAL/Models/SPI2.hpp" #include "HALAL/Services/Communication/SPI/SPI.hpp" #include "HALAL/Services/Communication/UART/UART.hpp" #include "HALAL/Services/Communication/I2C/I2C.hpp" diff --git a/Inc/ST-LIB.hpp b/Inc/ST-LIB.hpp index 221035b08..92fe1e868 100644 --- a/Inc/ST-LIB.hpp +++ b/Inc/ST-LIB.hpp @@ -103,12 +103,14 @@ template struct Board { constexpr std::size_t gpioN = domain_size(); constexpr std::size_t doutN = domain_size(); constexpr std::size_t dinN = domain_size(); + constexpr std::size_t spiN = domain_size(); // ... struct ConfigBundle { std::array gpio_cfgs; std::array dout_cfgs; std::array din_cfgs; + std::array spi_cfgs; // ... }; @@ -119,6 +121,8 @@ template struct Board { ctx.template span()), .din_cfgs = DigitalInputDomain::template build( ctx.template span()), + .spi_cfgs = SPIDomain::template build( + ctx.template span()), // ... }; } @@ -129,6 +133,7 @@ template struct Board { constexpr std::size_t gpioN = domain_size(); constexpr std::size_t doutN = domain_size(); constexpr std::size_t dinN = domain_size(); + constexpr std::size_t spiN = domain_size(); // ... GPIODomain::Init::init(cfg.gpio_cfgs); @@ -136,6 +141,8 @@ template struct Board { GPIODomain::Init::instances); DigitalInputDomain::Init::init(cfg.din_cfgs, GPIODomain::Init::instances); + SPIDomain::Init::init(cfg.spi_cfgs, + GPIODomain::Init::instances); // ... } From 288e5c0b71ba57bebe77f6ce16a4a89ddf420a66 Mon Sep 17 00:00:00 2001 From: Foniks Date: Sun, 28 Dec 2025 23:58:05 +0100 Subject: [PATCH 078/109] fix(SPI): Remove forgotten line --- Inc/HALAL/Models/SPI2.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Inc/HALAL/Models/SPI2.hpp b/Inc/HALAL/Models/SPI2.hpp index 3f26b5575..3b214e32e 100644 --- a/Inc/HALAL/Models/SPI2.hpp +++ b/Inc/HALAL/Models/SPI2.hpp @@ -633,8 +633,6 @@ struct SPIDomain { init.DataSize = SPI_DATASIZE_8BIT; // Works with any data size (at least for bytes) init.CLKPolarity = SPI_POLARITY_LOW; init.CLKPhase = SPI_PHASE_1EDGE; - // Calculate BaudRatePrescaler - init.BaudRatePrescaler = // TODO init.FirstBit = SPI_FIRSTBIT_MSB; // Must check if LSB first is needed for anything later init.TIMode = SPI_TIMODE_DISABLE; // Texas Instruments mode, like, why would we use that? init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; // Doesn't seem that useful here, better to handle CRC manually with the CRC peripheral if needed From 4d6f8b4bf7896c4621a2defb043e04fc2b56043d Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Mon, 29 Dec 2025 12:06:22 +0100 Subject: [PATCH 079/109] fix(SPI): General fixes to make it compile --- Inc/HALAL/Models/SPI2.hpp | 35 +++++++++++++++++++++++++++++++---- Inc/ST-LIB.hpp | 2 +- Src/HALAL/Models/SPI2.cpp | 12 ++++++------ 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/Inc/HALAL/Models/SPI2.hpp b/Inc/HALAL/Models/SPI2.hpp index 3b214e32e..55115fcdb 100644 --- a/Inc/HALAL/Models/SPI2.hpp +++ b/Inc/HALAL/Models/SPI2.hpp @@ -10,10 +10,25 @@ #include "C++Utilities/CppImports.hpp" #include "HALAL/Models/GPIO.hpp" +#include "HALAL/Models/Pin.hpp" #include "ErrorHandler/ErrorHandler.hpp" using ST_LIB::GPIODomain; +// Forward declaration of IRQ handlers and HAL callbacks +extern "C" { + void SPI1_IRQHandler(void); + void SPI2_IRQHandler(void); + void SPI3_IRQHandler(void); + void SPI4_IRQHandler(void); + void SPI5_IRQHandler(void); + void SPI6_IRQHandler(void); + + void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi); + void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi); + void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi); + void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi); +} namespace ST_LIB { @@ -39,7 +54,7 @@ struct SPIDomain { SLAVE = false, }; - static bool compare_pin(const GPIODomain::Pin &p1, const GPIODomain::Pin &p2) { + static consteval bool compare_pin(const GPIODomain::Pin &p1, const GPIODomain::Pin &p2) { return (p1.port == p2.port) && (p1.pin == p2.pin); } @@ -323,9 +338,21 @@ struct SPIDomain { * Instance (state holder) * ========================================= */ + template struct Init; // Forward declaration + template struct SPIWrapper; // Forward declaration struct Instance { - template friend struct Init; - template friend struct SPIWrapper; + template friend struct Init; + template friend struct SPIWrapper; + friend void ::SPI1_IRQHandler(void); + friend void ::SPI2_IRQHandler(void); + friend void ::SPI3_IRQHandler(void); + friend void ::SPI4_IRQHandler(void); + friend void ::SPI5_IRQHandler(void); + friend void ::SPI6_IRQHandler(void); + friend void ::HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi); + friend void ::HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi); + friend void ::HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi); + friend void ::HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi); private: SPI_HandleTypeDef hspi; @@ -607,7 +634,7 @@ struct SPIDomain { auto hspi = instances[i].hspi; hspi.Instance = instances[i].instance; - auto init = hspi.Init; + auto& init = hspi.Init; if (e.mode == SPIMode::MASTER) { init.Mode = SPI_MODE_MASTER; init.NSS = SPI_NSS_HARD_OUTPUT; // Hardware control for now, should add software later for more flexibility diff --git a/Inc/ST-LIB.hpp b/Inc/ST-LIB.hpp index 92fe1e868..57c3c0679 100644 --- a/Inc/ST-LIB.hpp +++ b/Inc/ST-LIB.hpp @@ -84,7 +84,7 @@ template struct BuildCtx { }; using DomainsCtx = BuildCtx; + DigitalInputDomain, SPIDomain /*, ADCDomain, PWMDomain, ...*/>; template struct Board { static consteval auto build_ctx() { diff --git a/Src/HALAL/Models/SPI2.cpp b/Src/HALAL/Models/SPI2.cpp index f9850d505..efaa4ba05 100644 --- a/Src/HALAL/Models/SPI2.cpp +++ b/Src/HALAL/Models/SPI2.cpp @@ -11,7 +11,7 @@ extern "C" { */ void SPI1_IRQHandler(void) { - auto inst = ST_LIB::spi_instances[0]; + auto inst = ST_LIB::SPIDomain::spi_instances[0]; if (inst == nullptr) { ErrorHandler("SPI1 IRQ Handler called but instance is null"); return; @@ -19,7 +19,7 @@ void SPI1_IRQHandler(void) { HAL_SPI_IRQHandler(&inst->hspi); } void SPI2_IRQHandler(void) { - auto inst = ST_LIB::spi_instances[1]; + auto inst = ST_LIB::SPIDomain::spi_instances[1]; if (inst == nullptr) { ErrorHandler("SPI2 IRQ Handler called but instance is null"); return; @@ -27,7 +27,7 @@ void SPI2_IRQHandler(void) { HAL_SPI_IRQHandler(&inst->hspi); } void SPI3_IRQHandler(void) { - auto inst = ST_LIB::spi_instances[2]; + auto inst = ST_LIB::SPIDomain::spi_instances[2]; if (inst == nullptr) { ErrorHandler("SPI3 IRQ Handler called but instance is null"); return; @@ -35,7 +35,7 @@ void SPI3_IRQHandler(void) { HAL_SPI_IRQHandler(&inst->hspi); } void SPI4_IRQHandler(void) { - auto inst = ST_LIB::spi_instances[3]; + auto inst = ST_LIB::SPIDomain::spi_instances[3]; if (inst == nullptr) { ErrorHandler("SPI4 IRQ Handler called but instance is null"); return; @@ -43,7 +43,7 @@ void SPI4_IRQHandler(void) { HAL_SPI_IRQHandler(&inst->hspi); } void SPI5_IRQHandler(void) { - auto inst = ST_LIB::spi_instances[4]; + auto inst = ST_LIB::SPIDomain::spi_instances[4]; if (inst == nullptr) { ErrorHandler("SPI5 IRQ Handler called but instance is null"); return; @@ -51,7 +51,7 @@ void SPI5_IRQHandler(void) { HAL_SPI_IRQHandler(&inst->hspi); } void SPI6_IRQHandler(void) { - auto inst = ST_LIB::spi_instances[5]; + auto inst = ST_LIB::SPIDomain::spi_instances[5]; if (inst == nullptr) { ErrorHandler("SPI6 IRQ Handler called but instance is null"); return; From 3af661337c8f6aae50bc018e3291ffea44471f3f Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Mon, 29 Dec 2025 12:33:01 +0100 Subject: [PATCH 080/109] fix(SPI): Forgot to set up max baudrate --- Inc/HALAL/Models/SPI2.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Inc/HALAL/Models/SPI2.hpp b/Inc/HALAL/Models/SPI2.hpp index 55115fcdb..21abde98f 100644 --- a/Inc/HALAL/Models/SPI2.hpp +++ b/Inc/HALAL/Models/SPI2.hpp @@ -326,6 +326,7 @@ struct SPIDomain { .miso_gpio_idx = ctx.template add(miso_gpio.e), .mosi_gpio_idx = ctx.template add(mosi_gpio.e), .nss_gpio_idx = ctx.template add(nss_gpio.e), + .max_baudrate = max_baudrate }; ctx.template add(e); @@ -519,6 +520,7 @@ struct SPIDomain { cfgs[i].miso_gpio_idx = entries[i].miso_gpio_idx; cfgs[i].mosi_gpio_idx = entries[i].mosi_gpio_idx; cfgs[i].nss_gpio_idx = entries[i].nss_gpio_idx; + cfgs[i].max_baudrate = entries[i].max_baudrate; auto peripheral = entries[i].peripheral; From 1bd4fc2a3fd29c787f35408118a3c1891d401ca0 Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Wed, 14 Jan 2026 20:07:29 +0100 Subject: [PATCH 081/109] feat(DMA): udpate inscribe method to return indices --- Inc/HALAL/Models/DMA/DMA2.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index 0ca605ffd..3f9081468 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -90,10 +90,12 @@ namespace ST_LIB { } template - consteval void inscribe(Ctx &ctx) const { - for (const auto &entry : e) { - ctx.template add(entry); + consteval array inscribe(Ctx &ctx) const { + array indices{}; + for (size_t i = 0; i < sizeof...(Ss); i++) { + indices[i] = ctx.template add(e[i], this); } + return indices; } }; From eb72bf62c45b8f7c1b5bb0e761329aaf6d0dfc74 Mon Sep 17 00:00:00 2001 From: Foniks Date: Mon, 19 Jan 2026 22:00:54 +0100 Subject: [PATCH 082/109] feat(SPI): Add DMA linking --- Inc/HALAL/Models/SPI2.hpp | 62 +++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/Inc/HALAL/Models/SPI2.hpp b/Inc/HALAL/Models/SPI2.hpp index 21abde98f..99639d386 100644 --- a/Inc/HALAL/Models/SPI2.hpp +++ b/Inc/HALAL/Models/SPI2.hpp @@ -12,8 +12,10 @@ #include "HALAL/Models/GPIO.hpp" #include "HALAL/Models/Pin.hpp" #include "ErrorHandler/ErrorHandler.hpp" +#include "HALAL/Models/DMA/DMA2.hpp" using ST_LIB::GPIODomain; +using ST_LIB::DMA_Domain; // Forward declaration of IRQ handlers and HAL callbacks extern "C" { @@ -133,9 +135,10 @@ struct SPIDomain { std::size_t mosi_gpio_idx; std::size_t nss_gpio_idx; - uint32_t max_baudrate; // Will set the baudrate as fast as possible under this value + std::size_t dma_rx_idx; + std::size_t dma_tx_idx; - // DMA here, maybe? Depends on new DMA implementation + uint32_t max_baudrate; // Will set the baudrate as fast as possible under this value }; struct Config { @@ -147,9 +150,10 @@ struct SPIDomain { std::size_t mosi_gpio_idx; std::size_t nss_gpio_idx; - uint32_t max_baudrate; // Will set the baudrate as fast as possible under this value + std::size_t dma_rx_idx; + std::size_t dma_tx_idx; - // DMA here, maybe? Depends on new DMA implementation + uint32_t max_baudrate; // Will set the baudrate as fast as possible under this value }; @@ -170,16 +174,19 @@ struct SPIDomain { GPIODomain::GPIO mosi_gpio; GPIODomain::GPIO nss_gpio; + DMA_Domain::Stream dma_rx_stream; + DMA_Domain::Stream dma_tx_stream; - consteval Device(SPIMode mode, SPIPeripheral peripheral, uint32_t max_baudrate, GPIODomain::Pin sck_pin, GPIODomain::Pin miso_pin, - GPIODomain::Pin mosi_pin, GPIODomain::Pin nss_pin) + GPIODomain::Pin mosi_pin, GPIODomain::Pin nss_pin, + DMA_Domain::Stream rx_stream, DMA_Domain::Stream tx_stream) : peripheral{peripheral}, mode{mode}, max_baudrate{max_baudrate}, sck_gpio(sck_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(sck_pin, peripheral)), miso_gpio(miso_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(miso_pin, peripheral)), mosi_gpio(mosi_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(mosi_pin, peripheral)), - nss_gpio(nss_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(nss_pin, peripheral)) + nss_gpio(nss_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(nss_pin, peripheral)), + dma_rx_stream(rx_stream), dma_tx_stream(tx_stream) { switch (peripheral) { @@ -319,6 +326,29 @@ struct SPIDomain { template consteval void inscribe(Ctx &ctx) const { + // Convert spix to DMA_Domain::Instance + DMA_Domain::Instance dma_instance; + switch (peripheral) { + case SPIPeripheral::spi1: + dma_instance = DMA_Domain::Instance::spi1; + break; + case SPIPeripheral::spi2: + dma_instance = DMA_Domain::Instance::spi2; + break; + case SPIPeripheral::spi3: + dma_instance = DMA_Domain::Instance::spi3; + break; + case SPIPeripheral::spi4: + dma_instance = DMA_Domain::Instance::spi4; + break; + case SPIPeripheral::spi5: + dma_instance = DMA_Domain::Instance::spi5; + break; + default: + compile_error("Invalid SPI peripheral for DMA mapping"); + } + DMA_Domain::DMA dma_rx_tx(dma_instance); + std::size_t[2] dma_indices = dma_rx_tx.inscribe(ctx); Entry e{ .peripheral = peripheral, .mode = mode, @@ -326,6 +356,8 @@ struct SPIDomain { .miso_gpio_idx = ctx.template add(miso_gpio.e), .mosi_gpio_idx = ctx.template add(mosi_gpio.e), .nss_gpio_idx = ctx.template add(nss_gpio.e), + .dma_rx_idx = dma_indices[0], + .dma_tx_idx = dma_indices[1], .max_baudrate = max_baudrate }; @@ -565,7 +597,8 @@ struct SPIDomain { static inline std::array instances{}; static void init(std::span cfgs, - std::span gpio_instances) { + std::span gpio_instances, + std::span dma_instances) { for (std::size_t i = 0; i < N; ++i) { const auto &e = cfgs[i]; @@ -633,9 +666,20 @@ struct SPIDomain { spi_instances[spi_number - 1] = &instances[i]; - auto hspi = instances[i].hspi; + auto& hspi = instances[i].hspi; hspi.Instance = instances[i].instance; + auto& dma_rx = dma_instances[e.dma_rx_idx]; + auto& dma_tx = dma_instances[e.dma_tx_idx]; + + // DMA handles are already configured and initialized by DMA_Domain + hspi.hdmarx = &dma_rx.hdma; + hspi.hdmatx = &dma_tx.hdma; + + // Link back from DMA to SPI (required by HAL) + dma_rx.hdma.Parent = &hspi; + dma_tx.hdma.Parent = &hspi; + auto& init = hspi.Init; if (e.mode == SPIMode::MASTER) { init.Mode = SPI_MODE_MASTER; From 980fa9c81b833477ab38531af09241f2cf5a949b Mon Sep 17 00:00:00 2001 From: Foniks Date: Mon, 19 Jan 2026 23:42:09 +0100 Subject: [PATCH 083/109] feat(SPI): Implement configuration API + some cleanup --- Inc/HALAL/HALAL.hpp | 2 +- Inc/HALAL/Models/{ => SPI}/SPI2.hpp | 236 ++++++++++++++-------- Inc/HALAL/Models/SPI/SPIConfig.hpp | 295 ++++++++++++++++++++++++++++ Src/HALAL/Models/{ => SPI}/SPI2.cpp | 15 +- 4 files changed, 464 insertions(+), 84 deletions(-) rename Inc/HALAL/Models/{ => SPI}/SPI2.hpp (79%) create mode 100644 Inc/HALAL/Models/SPI/SPIConfig.hpp rename Src/HALAL/Models/{ => SPI}/SPI2.cpp (88%) diff --git a/Inc/HALAL/HALAL.hpp b/Inc/HALAL/HALAL.hpp index 3fa7c9a7f..519716d26 100644 --- a/Inc/HALAL/HALAL.hpp +++ b/Inc/HALAL/HALAL.hpp @@ -28,7 +28,7 @@ #include "HALAL/Services/Encoder/Encoder.hpp" #include "HALAL/Services/EXTI/EXTI.hpp" -#include "HALAL/Models/SPI2.hpp" +#include "HALAL/Models/SPI/SPI2.hpp" #include "HALAL/Services/Communication/SPI/SPI.hpp" #include "HALAL/Services/Communication/UART/UART.hpp" #include "HALAL/Services/Communication/I2C/I2C.hpp" diff --git a/Inc/HALAL/Models/SPI2.hpp b/Inc/HALAL/Models/SPI/SPI2.hpp similarity index 79% rename from Inc/HALAL/Models/SPI2.hpp rename to Inc/HALAL/Models/SPI/SPI2.hpp index 99639d386..f7d491c88 100644 --- a/Inc/HALAL/Models/SPI2.hpp +++ b/Inc/HALAL/Models/SPI/SPI2.hpp @@ -13,9 +13,11 @@ #include "HALAL/Models/Pin.hpp" #include "ErrorHandler/ErrorHandler.hpp" #include "HALAL/Models/DMA/DMA2.hpp" +#include "HALAL/Models/SPI/SPIConfig.hpp" using ST_LIB::GPIODomain; using ST_LIB::DMA_Domain; +using ST_LIB::SPIConfigTypes; // Forward declaration of IRQ handlers and HAL callbacks extern "C" { @@ -42,6 +44,18 @@ struct SPIDomain { * ========================================= */ + // Configuration types + using ClockPolarity = SPIConfigTypes::ClockPolarity; + using ClockPhase = SPIConfigTypes::ClockPhase; + using BitOrder = SPIConfigTypes::BitOrder; + using NSSMode = SPIConfigTypes::NSSMode; + using DataSize = SPIConfigTypes::DataSize; + using Direction = SPIConfigTypes::Direction; + using FIFOThreshold = SPIConfigTypes::FIFOThreshold; + using NSSPolarity = SPIConfigTypes::NSSPolarity; + using CRCLength = SPIConfigTypes::CRCLength; + using SPIConfig = SPIConfigTypes::SPIConfig; + enum class SPIPeripheral : uintptr_t { spi1 = SPI1_BASE, spi2 = SPI2_BASE, @@ -110,19 +124,8 @@ struct SPIDomain { } } - static uint32_t calculate_prescaler(uint32_t src_freq, uint32_t max_baud) { - uint32_t prescaler = 2; // Smallest prescaler available - - while ((src_freq / prescaler) > max_baud) { - prescaler *= 2; // Prescaler doubles each step (it must be a power of 2) - - if (prescaler > 256) { - ErrorHandler("Cannot achieve desired baudrate, speed is too low"); - } - } - - return get_prescaler_flag(prescaler); - } + // Forward declaration + static uint32_t calculate_prescaler(uint32_t src_freq, uint32_t max_baud); static constexpr std::size_t max_instances{6}; @@ -133,12 +136,13 @@ struct SPIDomain { std::size_t sck_gpio_idx; std::size_t miso_gpio_idx; std::size_t mosi_gpio_idx; - std::size_t nss_gpio_idx; + std::optional nss_gpio_idx; std::size_t dma_rx_idx; std::size_t dma_tx_idx; uint32_t max_baudrate; // Will set the baudrate as fast as possible under this value + SPIConfig config; // User-defined SPI configuration }; struct Config { @@ -148,12 +152,13 @@ struct SPIDomain { std::size_t sck_gpio_idx; std::size_t miso_gpio_idx; std::size_t mosi_gpio_idx; - std::size_t nss_gpio_idx; + std::optional nss_gpio_idx; std::size_t dma_rx_idx; std::size_t dma_tx_idx; uint32_t max_baudrate; // Will set the baudrate as fast as possible under this value + SPIConfig config; // User-defined SPI configuration }; @@ -162,33 +167,69 @@ struct SPIDomain { * Request Object * ========================================= */ + template struct Device { using domain = SPIDomain; SPIPeripheral peripheral; SPIMode mode; uint32_t max_baudrate; // Will set the baudrate as fast as possible under this value + SPIConfig config; // User-defined SPI configuration GPIODomain::GPIO sck_gpio; GPIODomain::GPIO miso_gpio; GPIODomain::GPIO mosi_gpio; - GPIODomain::GPIO nss_gpio; - - DMA_Domain::Stream dma_rx_stream; - DMA_Domain::Stream dma_tx_stream; + std::optional nss_gpio; consteval Device(SPIMode mode, SPIPeripheral peripheral, uint32_t max_baudrate, GPIODomain::Pin sck_pin, GPIODomain::Pin miso_pin, GPIODomain::Pin mosi_pin, GPIODomain::Pin nss_pin, - DMA_Domain::Stream rx_stream, DMA_Domain::Stream tx_stream) + SPIConfig config = SPIConfig{}) : peripheral{peripheral}, mode{mode}, max_baudrate{max_baudrate}, + config{config}, sck_gpio(sck_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(sck_pin, peripheral)), miso_gpio(miso_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(miso_pin, peripheral)), mosi_gpio(mosi_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(mosi_pin, peripheral)), - nss_gpio(nss_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(nss_pin, peripheral)), - dma_rx_stream(rx_stream), dma_tx_stream(tx_stream) + nss_gpio(GPIODomain::GPIO(nss_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(nss_pin, peripheral))) { + config.validate(); + + if (config.nss_mode == NSSMode::SOFTWARE) { + compile_error("Use NSSMode::SOFTWARE, and omit NSS pin for software NSS management, it is handled externally"); + } + + validate_nss_pin(peripheral, nss_pin); + + validate_spi_pins(peripheral, sck_pin, miso_pin, mosi_pin); + } + + // Constructor without NSS pin (for software NSS mode) + consteval Device(SPIMode mode, SPIPeripheral peripheral, uint32_t max_baudrate, + GPIODomain::Pin sck_pin, GPIODomain::Pin miso_pin, + GPIODomain::Pin mosi_pin, + SPIConfig config) + : peripheral{peripheral}, mode{mode}, max_baudrate{max_baudrate}, + config{config}, + sck_gpio(sck_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(sck_pin, peripheral)), + miso_gpio(miso_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(miso_pin, peripheral)), + mosi_gpio(mosi_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(mosi_pin, peripheral)), + nss_gpio(std::nullopt) // No NSS GPIO + { + config.validate(); + + if (config.nss_mode == NSSMode::HARDWARE) { + compile_error("NSS pin must be provided for hardware NSS mode, or use NSSMode::SOFTWARE"); + } + + validate_spi_pins(peripheral, sck_pin, miso_pin, mosi_pin); + } + private: + // Helper function to validate SPI pins (SCK, MISO, MOSI only) + static consteval void validate_spi_pins(SPIPeripheral peripheral, + GPIODomain::Pin sck_pin, + GPIODomain::Pin miso_pin, + GPIODomain::Pin mosi_pin) { switch (peripheral) { case SPIPeripheral::spi1: if (!compare_pin(sck_pin, PB3) && @@ -206,11 +247,6 @@ struct SPIDomain { !compare_pin(mosi_pin, PA7)) { compile_error("Invalid MOSI pin for SPI1"); } - if (!compare_pin(nss_pin, PG10) && - !compare_pin(nss_pin, PA15) && - !compare_pin(nss_pin, PA4)) { - compile_error("Invalid NSS pin for SPI1"); - } break; case SPIPeripheral::spi2: @@ -230,12 +266,6 @@ struct SPIDomain { !compare_pin(mosi_pin, PB15)) { compile_error("Invalid MOSI pin for SPI2"); } - if (!compare_pin(nss_pin, PB9) && - !compare_pin(nss_pin, PB4) && - !compare_pin(nss_pin, PA11) && - !compare_pin(nss_pin, PB12)) { - compile_error("Invalid NSS pin for SPI2"); - } break; case SPIPeripheral::spi3: @@ -253,10 +283,6 @@ struct SPIDomain { !compare_pin(mosi_pin, PB2)) { compile_error("Invalid MOSI pin for SPI3"); } - if (!compare_pin(nss_pin, PA15) && - !compare_pin(nss_pin, PA4)) { - compile_error("Invalid NSS pin for SPI3"); - } break; case SPIPeripheral::spi4: @@ -272,10 +298,6 @@ struct SPIDomain { !compare_pin(mosi_pin, PE14)) { compile_error("Invalid MOSI pin for SPI4"); } - if (!compare_pin(nss_pin, PE4) && - !compare_pin(nss_pin, PE11)) { - compile_error("Invalid NSS pin for SPI4"); - } break; case SPIPeripheral::spi5: @@ -289,9 +311,6 @@ struct SPIDomain { !compare_pin(mosi_pin, PF11)) { compile_error("Invalid MOSI pin for SPI5"); } - if (!compare_pin(nss_pin, PF6)) { - compile_error("Invalid NSS pin for SPI5"); - } break; case SPIPeripheral::spi6: @@ -311,6 +330,54 @@ struct SPIDomain { !compare_pin(mosi_pin, PA7)) { compile_error("Invalid MOSI pin for SPI6"); } + break; + + default: + compile_error("Invalid SPI peripheral specified in SPIDomain::Device"); + } + } + + // Helper function to validate NSS pin (only called for hardware NSS mode) + static consteval void validate_nss_pin(SPIPeripheral peripheral, GPIODomain::Pin nss_pin) { + switch (peripheral) { + case SPIPeripheral::spi1: + if (!compare_pin(nss_pin, PA4) && + !compare_pin(nss_pin, PA15) && + !compare_pin(nss_pin, PG10)) { + compile_error("Invalid NSS pin for SPI1"); + } + break; + + case SPIPeripheral::spi2: + if (!compare_pin(nss_pin, PA11) && + !compare_pin(nss_pin, PB9) && + !compare_pin(nss_pin, PB4) && + !compare_pin(nss_pin, PB12)) { + compile_error("Invalid NSS pin for SPI2"); + } + break; + + case SPIPeripheral::spi3: + if (!compare_pin(nss_pin, PA15) && + !compare_pin(nss_pin, PA4)) { + compile_error("Invalid NSS pin for SPI3"); + } + break; + + case SPIPeripheral::spi4: + if (!compare_pin(nss_pin, PE4) && + !compare_pin(nss_pin, PE11)) { + compile_error("Invalid NSS pin for SPI4"); + } + break; + + case SPIPeripheral::spi5: + if (!compare_pin(nss_pin, PF6)) { + compile_error("Invalid NSS pin for SPI5"); + } + break; + + case SPIPeripheral::spi6: if (!compare_pin(nss_pin, PA0) && !compare_pin(nss_pin, PA15) && !compare_pin(nss_pin, PG8) && @@ -347,18 +414,26 @@ struct SPIDomain { default: compile_error("Invalid SPI peripheral for DMA mapping"); } - DMA_Domain::DMA dma_rx_tx(dma_instance); - std::size_t[2] dma_indices = dma_rx_tx.inscribe(ctx); + DMA_Domain::DMA dma_rx_tx(dma_instance); + auto dma_indices = dma_rx_tx.inscribe(ctx); + + // Conditionally add NSS GPIO if provided + std::optional nss_idx = std::nullopt; + if (nss_gpio.has_value()) { + nss_idx = ctx.template add(nss_gpio.value().e); + } + Entry e{ .peripheral = peripheral, .mode = mode, .sck_gpio_idx = ctx.template add(sck_gpio.e), .miso_gpio_idx = ctx.template add(miso_gpio.e), .mosi_gpio_idx = ctx.template add(mosi_gpio.e), - .nss_gpio_idx = ctx.template add(nss_gpio.e), + .nss_gpio_idx = nss_idx, .dma_rx_idx = dma_indices[0], .dma_tx_idx = dma_indices[1], - .max_baudrate = max_baudrate + .max_baudrate = max_baudrate, + .config = config }; ctx.template add(e); @@ -552,7 +627,10 @@ struct SPIDomain { cfgs[i].miso_gpio_idx = entries[i].miso_gpio_idx; cfgs[i].mosi_gpio_idx = entries[i].mosi_gpio_idx; cfgs[i].nss_gpio_idx = entries[i].nss_gpio_idx; + cfgs[i].dma_rx_idx = entries[i].dma_rx_idx; + cfgs[i].dma_tx_idx = entries[i].dma_tx_idx; cfgs[i].max_baudrate = entries[i].max_baudrate; + cfgs[i].config = entries[i].config; auto peripheral = entries[i].peripheral; @@ -612,55 +690,49 @@ struct SPIDomain { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI1; PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - ErrorHandler("Unable to configure SPI%i clock", i+1); + ErrorHandler("Unable to configure SPI1 clock"); } __HAL_RCC_SPI1_CLK_ENABLE(); - spi_number = 1; } else if (peripheral == SPIPeripheral::spi2) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI2; PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - ErrorHandler("Unable to configure SPI%i clock", i+1); + ErrorHandler("Unable to configure SPI2 clock"); } __HAL_RCC_SPI2_CLK_ENABLE(); - spi_number = 2; } else if (peripheral == SPIPeripheral::spi3) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI3; PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - ErrorHandler("Unable to configure SPI%i clock", i+1); + ErrorHandler("Unable to configure SPI3 clock"); } __HAL_RCC_SPI3_CLK_ENABLE(); - spi_number = 3; } else if (peripheral == SPIPeripheral::spi4) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI4; PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL2; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - ErrorHandler("Unable to configure SPI%i clock", i+1); + ErrorHandler("Unable to configure SPI4 clock"); } __HAL_RCC_SPI4_CLK_ENABLE(); - spi_number = 4; } else if (peripheral == SPIPeripheral::spi5) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI5; PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL2; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - ErrorHandler("Unable to configure SPI%i clock", i+1); + ErrorHandler("Unable to configure SPI5 clock"); } __HAL_RCC_SPI5_CLK_ENABLE(); - spi_number = 5; } else if (peripheral == SPIPeripheral::spi6) { PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI6; PeriphClkInitStruct.Spi6ClockSelection = RCC_SPI6CLKSOURCE_PLL2; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { - ErrorHandler("Unable to configure SPI%i clock", i+1); + ErrorHandler("Unable to configure SPI6 clock"); } __HAL_RCC_SPI6_CLK_ENABLE(); - spi_number = 6; } @@ -683,7 +755,6 @@ struct SPIDomain { auto& init = hspi.Init; if (e.mode == SPIMode::MASTER) { init.Mode = SPI_MODE_MASTER; - init.NSS = SPI_NSS_HARD_OUTPUT; // Hardware control for now, should add software later for more flexibility // Baudrate prescaler calculation uint32_t pclk_freq; if (peripheral == SPIPeripheral::spi1 || @@ -697,31 +768,32 @@ struct SPIDomain { pclk_freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6); } init.BaudRatePrescaler = calculate_prescaler(pclk_freq, e.max_baudrate); - } else { init.Mode = SPI_MODE_SLAVE; - init.NSS = SPI_NSS_HARD_INPUT; - } - init.Direction = SPI_DIRECTION_2LINES; - init.DataSize = SPI_DATASIZE_8BIT; // Works with any data size (at least for bytes) - init.CLKPolarity = SPI_POLARITY_LOW; - init.CLKPhase = SPI_PHASE_1EDGE; - init.FirstBit = SPI_FIRSTBIT_MSB; // Must check if LSB first is needed for anything later - init.TIMode = SPI_TIMODE_DISABLE; // Texas Instruments mode, like, why would we use that? - init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; // Doesn't seem that useful here, better to handle CRC manually with the CRC peripheral if needed - init.CRCPolynomial = 0; // Nope - init.CRCLength = SPI_CRC_LENGTH_8BIT; // Doesn't matter since CRC calculation is disabled - init.NSSPMode = SPI_NSS_PULSE_DISABLE; // Hardcoded for now, may add a setting later - init.NSSPolarity = SPI_NSS_POLARITY_LOW; // Standard polarity - init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA; // 1 byte, since we're using 8 bit data size for safety, may add a setting later + } + + init.NSS = SPIConfigTypes::translate_nss_mode(e.config.nss_mode, e.mode == SPIMode::MASTER); + init.Direction = SPIConfigTypes::translate_direction(e.config.direction); + init.DataSize = SPIConfigTypes::translate_data_size(e.config.data_size); + init.CLKPolarity = SPIConfigTypes::translate_clock_polarity(e.config.polarity); + init.CLKPhase = SPIConfigTypes::translate_clock_phase(e.config.phase); + init.FirstBit = SPIConfigTypes::translate_bit_order(e.config.bit_order); + init.TIMode = SPIConfigTypes::translate_ti_mode(e.config.ti_mode); + init.CRCCalculation = SPIConfigTypes::translate_crc_calculation(e.config.crc_calculation); + if (e.config.crc_calculation) { + init.CRCPolynomial = e.config.crc_polynomial; + init.CRCLength = SPIConfigTypes::translate_crc_length(e.config.crc_length); + } + init.NSSPMode = SPIConfigTypes::translate_nss_pulse(e.config.nss_pulse); + init.NSSPolarity = SPIConfigTypes::translate_nss_polarity(e.config.nss_polarity); + init.FifoThreshold = SPIConfigTypes::translate_fifo_threshold(e.config.fifo_threshold); init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN; init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN; - init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE; // Should check if this works or the peripheral needs some delay - init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE; - init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE; // If you are having overrun issues, then you have a problem somewhere else - init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; // Keeps MOSI, MISO, SCK state when not communicating, ensure no floating lines and no random noise - init.IOSwap = SPI_IO_SWAP_DISABLE; // Should not be needed - + init.MasterSSIdleness = SPIConfigTypes::translate_ss_idleness(e.config.master_ss_idleness); + init.MasterInterDataIdleness = SPIConfigTypes::translate_interdata_idleness(e.config.master_interdata_idleness); + init.MasterReceiverAutoSusp = SPIConfigTypes::translate_rx_autosusp(e.config.master_rx_autosusp); + init.MasterKeepIOState = SPIConfigTypes::translate_keep_io_state(e.config.keep_io_state); + init.IOSwap = SPIConfigTypes::translate_io_swap(e.config.io_swap); if (HAL_SPI_Init(&hspi) != HAL_OK) { ErrorHandler("Unable to init SPI%u", spi_number); diff --git a/Inc/HALAL/Models/SPI/SPIConfig.hpp b/Inc/HALAL/Models/SPI/SPIConfig.hpp new file mode 100644 index 000000000..0215de56d --- /dev/null +++ b/Inc/HALAL/Models/SPI/SPIConfig.hpp @@ -0,0 +1,295 @@ +/* + * SPIConfig.hpp + * + * Created on: 19 jan. 2026 + * Author: Boris + */ + +#ifndef SPICONFIG_HPP +#define SPICONFIG_HPP + +#include "C++Utilities/CppImports.hpp" +#include "ErrorHandler/ErrorHandler.hpp" + +namespace ST_LIB { + +struct SPIConfigTypes { + + enum class ClockPolarity : bool { + LOW = false, // Clock idle state is low (CPOL=0) + HIGH = true // Clock idle state is high (CPOL=1) + }; + + enum class ClockPhase : bool { + FIRST_EDGE = false, // Data sampled on first clock edge (CPHA=0) + SECOND_EDGE = true // Data sampled on second clock edge (CPHA=1) + }; + + enum class BitOrder : bool { + MSB_FIRST = false, + LSB_FIRST = true + }; + + enum class NSSMode { + SOFTWARE, // Software NSS management (manual control) + HARDWARE // Hardware NSS management (automatic) + }; + + enum class DataSize : uint8_t { + SIZE_4BIT = 4, + SIZE_5BIT = 5, + SIZE_6BIT = 6, + SIZE_7BIT = 7, + SIZE_8BIT = 8, + SIZE_9BIT = 9, + SIZE_10BIT = 10, + SIZE_11BIT = 11, + SIZE_12BIT = 12, + SIZE_13BIT = 13, + SIZE_14BIT = 14, + SIZE_15BIT = 15, + SIZE_16BIT = 16, + SIZE_17BIT = 17, + SIZE_18BIT = 18, + SIZE_19BIT = 19, + SIZE_20BIT = 20, + SIZE_21BIT = 21, + SIZE_22BIT = 22, + SIZE_23BIT = 23, + SIZE_24BIT = 24, + SIZE_25BIT = 25, + SIZE_26BIT = 26, + SIZE_27BIT = 27, + SIZE_28BIT = 28, + SIZE_29BIT = 29, + SIZE_30BIT = 30, + SIZE_31BIT = 31, + SIZE_32BIT = 32 + }; + + enum class Direction { + FULL_DUPLEX, // 2-line bidirectional (most common) + HALF_DUPLEX, // 1-line bidirectional + SIMPLEX_TX_ONLY, // Transmit only + SIMPLEX_RX_ONLY // Receive only + }; + + enum class FIFOThreshold : uint8_t { + THRESHOLD_01DATA = 1, + THRESHOLD_02DATA = 2, + THRESHOLD_03DATA = 3, + THRESHOLD_04DATA = 4, + THRESHOLD_05DATA = 5, + THRESHOLD_06DATA = 6, + THRESHOLD_07DATA = 7, + THRESHOLD_08DATA = 8, + THRESHOLD_09DATA = 9, + THRESHOLD_10DATA = 10, + THRESHOLD_11DATA = 11, + THRESHOLD_12DATA = 12, + THRESHOLD_13DATA = 13, + THRESHOLD_14DATA = 14, + THRESHOLD_15DATA = 15, + THRESHOLD_16DATA = 16 + }; + + enum class NSSPolarity { + ACTIVE_LOW = false, + ACTIVE_HIGH = true + }; + + enum class CRCLength : uint8_t { + DATASIZE = 0, // CRC length matches data size + CRC_4BIT = 4, + CRC_5BIT = 5, + CRC_6BIT = 6, + CRC_7BIT = 7, + CRC_8BIT = 8, + CRC_9BIT = 9, + CRC_10BIT = 10, + CRC_11BIT = 11, + CRC_12BIT = 12, + CRC_13BIT = 13, + CRC_14BIT = 14, + CRC_15BIT = 15, + CRC_16BIT = 16, + CRC_17BIT = 17, + CRC_18BIT = 18, + CRC_19BIT = 19, + CRC_20BIT = 20, + CRC_21BIT = 21, + CRC_22BIT = 22, + CRC_23BIT = 23, + CRC_24BIT = 24, + CRC_25BIT = 25, + CRC_26BIT = 26, + CRC_27BIT = 27, + CRC_28BIT = 28, + CRC_29BIT = 29, + CRC_30BIT = 30, + CRC_31BIT = 31, + CRC_32BIT = 32 + }; + + /** + * @brief User-facing SPI configuration options + */ + struct SPIConfig { + // Core settings + ClockPolarity polarity = ClockPolarity::LOW; + ClockPhase phase = ClockPhase::FIRST_EDGE; + BitOrder bit_order = BitOrder::MSB_FIRST; + NSSMode nss_mode = NSSMode::HARDWARE; + + // Data format + DataSize data_size = DataSize::SIZE_8BIT; + Direction direction = Direction::FULL_DUPLEX; + FIFOThreshold fifo_threshold = FIFOThreshold::THRESHOLD_01DATA; + + // NSS settings + bool nss_pulse = false; // NSS pulse between data frames (master only) + NSSPolarity nss_polarity = NSSPolarity::ACTIVE_LOW; + + // Master timing settings + uint8_t master_ss_idleness = 0; // Cycles (0-15) between NSS and first data + uint8_t master_interdata_idleness = 0; // Cycles (0-15) between data frames + + // Advanced options + bool keep_io_state = true; // Keep pin states when idle (prevents floating) + bool master_rx_autosusp = false; // Auto-suspend in master RX mode to prevent overrun + bool io_swap = false; // Swap MISO/MOSI pins + + // Protocol options + bool ti_mode = false; // Enable TI synchronous serial frame format (Microwire compatible) + + // CRC options (hardware CRC calculation) + bool crc_calculation = false; // Enable hardware CRC calculation + uint32_t crc_polynomial = 0x07; // CRC polynomial (must be odd, default for CRC-8) + CRCLength crc_length = CRCLength::DATASIZE; // CRC length (default: matches data size) + + constexpr SPIConfig() = default; + + constexpr SPIConfig(ClockPolarity pol, ClockPhase ph, + BitOrder order = BitOrder::MSB_FIRST, + NSSMode nss = NSSMode::HARDWARE) + : polarity(pol), phase(ph), bit_order(order), nss_mode(nss) {} + + // Compile-time validation + constexpr void validate() const { + // Validate CRC polynomial if CRC is enabled + if (crc_calculation) { + if (crc_polynomial == 0 || crc_polynomial > 0xFFFF) { + compile_error("CRC polynomial must be between 1 and 65535"); + } + if ((crc_polynomial & 1) == 0) { + compile_error("CRC polynomial must be odd"); + } + } + + // Validate timing parameters + if (master_ss_idleness > 15) { + compile_error("master_ss_idleness must be 0-15"); + } + if (master_interdata_idleness > 15) { + compile_error("master_interdata_idleness must be 0-15"); + } + } + }; + + static constexpr uint32_t translate_nss_mode(NSSMode mode, bool is_master) { + if (mode == NSSMode::SOFTWARE) { + return SPI_NSS_SOFT; + } + // Hardware mode - depends on master/slave + return (is_master) ? SPI_NSS_HARD_OUTPUT : SPI_NSS_HARD_INPUT; + } + + // Translation functions from custom config to HAL constants + static constexpr uint32_t translate_clock_polarity(ClockPolarity pol) { + return (pol == ClockPolarity::LOW) ? SPI_POLARITY_LOW : SPI_POLARITY_HIGH; + } + + static constexpr uint32_t translate_clock_phase(ClockPhase phase) { + return (phase == ClockPhase::FIRST_EDGE) ? SPI_PHASE_1EDGE : SPI_PHASE_2EDGE; + } + + static constexpr uint32_t translate_bit_order(BitOrder order) { + return (order == BitOrder::MSB_FIRST) ? SPI_FIRSTBIT_MSB : SPI_FIRSTBIT_LSB; + } + + static constexpr uint32_t translate_data_size(DataSize size) { + // HAL uses SIZE-1 (e.g., 8 bits = 0x07) + return static_cast(size) - 1; + } + + static constexpr uint32_t translate_direction(Direction dir) { + switch (dir) { + case Direction::FULL_DUPLEX: + return SPI_DIRECTION_2LINES; + case Direction::HALF_DUPLEX: + return SPI_DIRECTION_1LINE; + case Direction::SIMPLEX_TX_ONLY: + return SPI_DIRECTION_2LINES_TXONLY; + case Direction::SIMPLEX_RX_ONLY: + return SPI_DIRECTION_2LINES_RXONLY; + } + return SPI_DIRECTION_2LINES; + } + + static constexpr uint32_t translate_fifo_threshold(FIFOThreshold threshold) { + // HAL uses (value-1) << 5 for FIFO threshold + return (static_cast(threshold) - 1) << 5; + } + + static constexpr uint32_t translate_nss_polarity(NSSPolarity pol) { + return (pol == NSSPolarity::ACTIVE_LOW) ? SPI_NSS_POLARITY_LOW : SPI_NSS_POLARITY_HIGH; + } + + static constexpr uint32_t translate_nss_pulse(bool enable) { + return enable ? SPI_NSS_PULSE_ENABLE : SPI_NSS_PULSE_DISABLE; + } + + static constexpr uint32_t translate_ss_idleness(uint8_t cycles) { + // Clamp to valid range 0-15 + if (cycles > 15) cycles = 15; + return cycles; + } + + static constexpr uint32_t translate_interdata_idleness(uint8_t cycles) { + // Clamp to valid range 0-15, shift to proper position + if (cycles > 15) cycles = 15; + return (cycles << 4); // These are in bits 7:4 of CFG2 + } + + static constexpr uint32_t translate_keep_io_state(bool enable) { + return enable ? SPI_MASTER_KEEP_IO_STATE_ENABLE : SPI_MASTER_KEEP_IO_STATE_DISABLE; + } + + static constexpr uint32_t translate_rx_autosusp(bool enable) { + return enable ? SPI_MASTER_RX_AUTOSUSP_ENABLE : SPI_MASTER_RX_AUTOSUSP_DISABLE; + } + + static constexpr uint32_t translate_io_swap(bool enable) { + return enable ? SPI_IO_SWAP_ENABLE : SPI_IO_SWAP_DISABLE; + } + + static constexpr uint32_t translate_ti_mode(bool enable) { + return enable ? SPI_TIMODE_ENABLE : SPI_TIMODE_DISABLE; + } + + static constexpr uint32_t translate_crc_calculation(bool enable) { + return enable ? SPI_CRCCALCULATION_ENABLE : SPI_CRCCALCULATION_DISABLE; + } + + static constexpr uint32_t translate_crc_length(CRCLength length) { + if (length == CRCLength::DATASIZE) { + return SPI_CRC_LENGTH_DATASIZE; + } + // HAL uses (value-1) << 16 for CRC length + return (static_cast(length) - 1) << 16; + } +}; + +} // namespace ST_LIB + +#endif // SPICONFIG_HPP diff --git a/Src/HALAL/Models/SPI2.cpp b/Src/HALAL/Models/SPI/SPI2.cpp similarity index 88% rename from Src/HALAL/Models/SPI2.cpp rename to Src/HALAL/Models/SPI/SPI2.cpp index efaa4ba05..95b593826 100644 --- a/Src/HALAL/Models/SPI2.cpp +++ b/Src/HALAL/Models/SPI/SPI2.cpp @@ -1,4 +1,17 @@ -#include "HALAL/Models/SPI2.hpp" +#include "HALAL/Models/SPI/SPI2.hpp" +uint32_t ST_LIB::SPIDomain::calculate_prescaler(uint32_t src_freq, uint32_t max_baud) { + uint32_t prescaler = 2; // Smallest prescaler available + + while ((src_freq / prescaler) > max_baud) { + prescaler *= 2; // Prescaler doubles each step (it must be a power of 2) + + if (prescaler > 256) { + ErrorHandler("Cannot achieve desired baudrate, speed is too low"); + } + } + + return get_prescaler_flag(prescaler); +} ST_LIB::SPIDomain::Instance* spi_instances[ST_LIB::SPIDomain::max_instances]; From ba15465d0dbdcad899ef3ce9b03d2b98b054f685 Mon Sep 17 00:00:00 2001 From: Foniks Date: Mon, 19 Jan 2026 23:44:26 +0100 Subject: [PATCH 084/109] fix(SPI): Update SPI in ST-LIB.hpp --- Inc/ST-LIB.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Inc/ST-LIB.hpp b/Inc/ST-LIB.hpp index 0dd784fba..10cfdc357 100644 --- a/Inc/ST-LIB.hpp +++ b/Inc/ST-LIB.hpp @@ -148,7 +148,8 @@ template struct Board { GPIODomain::Init::instances); DMA_Domain::Init::init(cfg.dma_cfgs); SPIDomain::Init::init(cfg.spi_cfgs, - GPIODomain::Init::instances); + GPIODomain::Init::instances, + DMA_Domain::Init::instances); // ... } From a6402afeb0f9d276bdb000bfd79c68f56fa9b079 Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Tue, 20 Jan 2026 20:10:52 +0100 Subject: [PATCH 085/109] feat(SPI): Make inscribe return size_t --- Inc/HALAL/Models/SPI/SPI2.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Inc/HALAL/Models/SPI/SPI2.hpp b/Inc/HALAL/Models/SPI/SPI2.hpp index f7d491c88..85058d229 100644 --- a/Inc/HALAL/Models/SPI/SPI2.hpp +++ b/Inc/HALAL/Models/SPI/SPI2.hpp @@ -392,7 +392,7 @@ struct SPIDomain { } template - consteval void inscribe(Ctx &ctx) const { + consteval std::size_t inscribe(Ctx &ctx) const { // Convert spix to DMA_Domain::Instance DMA_Domain::Instance dma_instance; switch (peripheral) { @@ -436,7 +436,7 @@ struct SPIDomain { .config = config }; - ctx.template add(e); + return ctx.template add(e); } }; From 40dc326cdcaf2638bdd5b9b7dfe64e88e591e5da Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Wed, 21 Jan 2026 21:51:25 +0100 Subject: [PATCH 086/109] automatic stream assignment (no tengo claro que vaya, lo probare con el adc) --- Inc/HALAL/Models/DMA/DMA2.hpp | 58 ++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index 3f9081468..a7f4cce94 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -31,7 +31,7 @@ namespace ST_LIB { spi1, spi2, spi3, spi4, spi5, fmac}; - enum class Stream : uint8_t {dma1_stream0, dma1_stream1, dma1_stream2, dma1_stream3, + enum class Stream : uint8_t {none, dma1_stream0, dma1_stream1, dma1_stream2, dma1_stream3, dma1_stream4, dma1_stream5, dma1_stream6, dma1_stream7, dma2_stream0, dma2_stream1, dma2_stream2, dma2_stream3, dma2_stream4, dma2_stream5, dma2_stream6, dma2_stream7}; @@ -56,6 +56,7 @@ namespace ST_LIB { case Stream::dma2_stream5: return DMA2_Stream5; case Stream::dma2_stream6: return DMA2_Stream6; case Stream::dma2_stream7: return DMA2_Stream7; + case Stream::none: return nullptr; } return nullptr; } @@ -83,7 +84,11 @@ namespace ST_LIB { for (uint8_t j = 0; j < n; j++) { e[j].instance = instance; e[j].stream = streams[j]; - e[j].irqn = get_irqn(streams[j]); + if (streams[j] != Stream::none) { + e[j].irqn = get_irqn(streams[j]); + } else { + e[j].irqn = (IRQn_Type)0; // Dummy value + } e[j].id = j; } @@ -120,8 +125,8 @@ namespace ST_LIB { else if (stream == Stream::dma2_stream5) return DMA2_Stream5_IRQn; else if (stream == Stream::dma2_stream6) return DMA2_Stream6_IRQn; else if (stream == Stream::dma2_stream7) return DMA2_Stream7_IRQn; - else ErrorHandler("Unknown DMA stream"); - return DMA1_Stream0_IRQn; // Nunca se alcanza + else if (stream == Stream::none) return (IRQn_Type)0; + else compile_error("No tiene que llegar aqui nunca, creo"); } static constexpr inline bool is_one_of(Instance instance, auto... bases) { @@ -181,7 +186,7 @@ namespace ST_LIB { if (instance == Instance::fmac && i == 1) return DMA_REQUEST_FMAC_WRITE; if (instance == Instance::fmac && i == 2) return DMA_REQUEST_FMAC_READ; - ErrorHandler("Invalid DMA request configuration"); + compile_error("Invalid DMA request configuration"); return 0; } @@ -282,12 +287,49 @@ namespace ST_LIB { template static consteval std::array build(span instances) { std::array cfgs{}; + std::array ents; + for(size_t i=0; i used_streams{}; // Defaults to false + + // First pass: process user-specified streams + for (std::size_t i = 0; i < N; ++i) { + const auto &e = ents[i]; + if (e.stream != Stream::none) { + uint8_t stream_idx = static_cast(e.stream) - 1; + if (used_streams[stream_idx]) { + compile_error("DMA stream already in use"); + } + used_streams[stream_idx] = true; + } + } + + // Second pass: assign streams for entries with Stream::none + for (std::size_t i = 0; i < N; ++i) { + auto &e = ents[i]; + if (e.stream == Stream::none) { + bool assigned = false; + for (uint8_t j = 0; j < MAX_STREAMS; ++j) { + if (!used_streams[j]) { + e.stream = static_cast(j + 1); + e.irqn = get_irqn(e.stream); + used_streams[j] = true; + assigned = true; + break; + } + } + if (!assigned) { + compile_error("Not enough DMA streams available"); + } + } + } + for (std::size_t i = 0; i < N; ++i){ - const auto &e = instances[i]; + const auto &e = ents[i]; for (std::size_t j = 0; j < i; ++j){ - const auto &prev = instances[j]; + const auto &prev = ents[j]; if (prev.stream == e.stream){ compile_error("DMA stream already in use"); } @@ -349,7 +391,7 @@ namespace ST_LIB { else{ HAL_NVIC_SetPriority(irqn, 0, 0); HAL_NVIC_EnableIRQ(irqn); - dma_irq_table[static_cast(stream)] = &instances[i].dma; + dma_irq_table[static_cast(stream) - 1] = &instances[i].dma; } } } From 5cce7e480b43689e6260272ba7018efd18715c7c Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Thu, 22 Jan 2026 02:16:56 +0100 Subject: [PATCH 087/109] fix(SPI): Fix compile_error --- Inc/HALAL/Models/SPI/SPI2.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Inc/HALAL/Models/SPI/SPI2.hpp b/Inc/HALAL/Models/SPI/SPI2.hpp index 85058d229..1799226ec 100644 --- a/Inc/HALAL/Models/SPI/SPI2.hpp +++ b/Inc/HALAL/Models/SPI/SPI2.hpp @@ -35,6 +35,7 @@ extern "C" { } namespace ST_LIB { +extern void compile_error(const char *msg); struct SPIDomain { From 72f165b2e615c2f7890ec9577f482711c84376c8 Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Thu, 22 Jan 2026 02:35:43 +0100 Subject: [PATCH 088/109] fix(SPI): Fix inscribe --- Inc/HALAL/Models/SPI/SPI2.hpp | 96 +++++++++++++++++------------------ 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/Inc/HALAL/Models/SPI/SPI2.hpp b/Inc/HALAL/Models/SPI/SPI2.hpp index 1799226ec..4a5978c8a 100644 --- a/Inc/HALAL/Models/SPI/SPI2.hpp +++ b/Inc/HALAL/Models/SPI/SPI2.hpp @@ -225,6 +225,54 @@ struct SPIDomain { validate_spi_pins(peripheral, sck_pin, miso_pin, mosi_pin); } + template + consteval std::size_t inscribe(Ctx &ctx) const { + // Convert spix to DMA_Domain::Instance + DMA_Domain::Instance dma_instance; + switch (peripheral) { + case SPIPeripheral::spi1: + dma_instance = DMA_Domain::Instance::spi1; + break; + case SPIPeripheral::spi2: + dma_instance = DMA_Domain::Instance::spi2; + break; + case SPIPeripheral::spi3: + dma_instance = DMA_Domain::Instance::spi3; + break; + case SPIPeripheral::spi4: + dma_instance = DMA_Domain::Instance::spi4; + break; + case SPIPeripheral::spi5: + dma_instance = DMA_Domain::Instance::spi5; + break; + default: + compile_error("Invalid SPI peripheral for DMA mapping"); + } + DMA_Domain::DMA dma_rx_tx(dma_instance); + auto dma_indices = dma_rx_tx.inscribe(ctx); + + // Conditionally add NSS GPIO if provided + std::optional nss_idx = std::nullopt; + if (nss_gpio.has_value()) { + nss_idx = nss_gpio.value().inscribe(ctx); + } + + Entry e{ + .peripheral = peripheral, + .mode = mode, + .sck_gpio_idx = sck_gpio.inscribe(ctx), + .miso_gpio_idx = miso_gpio.inscribe(ctx), + .mosi_gpio_idx = mosi_gpio.inscribe(ctx), + .nss_gpio_idx = nss_idx, + .dma_rx_idx = dma_indices[0], + .dma_tx_idx = dma_indices[1], + .max_baudrate = max_baudrate, + .config = config + }; + + return ctx.template add(e, this); + } + private: // Helper function to validate SPI pins (SCK, MISO, MOSI only) static consteval void validate_spi_pins(SPIPeripheral peripheral, @@ -391,54 +439,6 @@ struct SPIDomain { compile_error("Invalid SPI peripheral specified in SPIDomain::Device"); } } - - template - consteval std::size_t inscribe(Ctx &ctx) const { - // Convert spix to DMA_Domain::Instance - DMA_Domain::Instance dma_instance; - switch (peripheral) { - case SPIPeripheral::spi1: - dma_instance = DMA_Domain::Instance::spi1; - break; - case SPIPeripheral::spi2: - dma_instance = DMA_Domain::Instance::spi2; - break; - case SPIPeripheral::spi3: - dma_instance = DMA_Domain::Instance::spi3; - break; - case SPIPeripheral::spi4: - dma_instance = DMA_Domain::Instance::spi4; - break; - case SPIPeripheral::spi5: - dma_instance = DMA_Domain::Instance::spi5; - break; - default: - compile_error("Invalid SPI peripheral for DMA mapping"); - } - DMA_Domain::DMA dma_rx_tx(dma_instance); - auto dma_indices = dma_rx_tx.inscribe(ctx); - - // Conditionally add NSS GPIO if provided - std::optional nss_idx = std::nullopt; - if (nss_gpio.has_value()) { - nss_idx = ctx.template add(nss_gpio.value().e); - } - - Entry e{ - .peripheral = peripheral, - .mode = mode, - .sck_gpio_idx = ctx.template add(sck_gpio.e), - .miso_gpio_idx = ctx.template add(miso_gpio.e), - .mosi_gpio_idx = ctx.template add(mosi_gpio.e), - .nss_gpio_idx = nss_idx, - .dma_rx_idx = dma_indices[0], - .dma_tx_idx = dma_indices[1], - .max_baudrate = max_baudrate, - .config = config - }; - - return ctx.template add(e); - } }; From 9d25db795df76588a4733edb539d51815f75f32c Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Thu, 22 Jan 2026 11:40:30 +0100 Subject: [PATCH 089/109] minor sintaxis change --- Inc/HALAL/Models/DMA/DMA2.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index a7f4cce94..bd578ea52 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -361,7 +361,7 @@ namespace ST_LIB { - struct Instances_ { + struct Instance { DMA_HandleTypeDef dma; void start(uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength){ @@ -371,7 +371,7 @@ namespace ST_LIB { template struct Init { - static inline std::array instances{}; + static inline std::array instances{}; static void init(std::span cfgs) { static_assert(N > 0); From 8404700ce34b6b5c0d07c841d7c0361c5031a5ee Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Thu, 22 Jan 2026 21:59:07 +0100 Subject: [PATCH 090/109] fix(SPI): Fix things --- Inc/HALAL/Models/DMA/DMA2.hpp | 2 +- Inc/HALAL/Models/SPI/SPI2.hpp | 60 ++--- Src/HALAL/HALAL.cpp | 2 +- Src/HALAL/Services/Communication/SPI/SPI.cpp | 248 +++++++++---------- 4 files changed, 156 insertions(+), 156 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index 3f9081468..2f7757120 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -332,7 +332,7 @@ namespace ST_LIB { static inline std::array instances{}; static void init(std::span cfgs) { - static_assert(N > 0); + if (N == 0) return; __HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_DMA2_CLK_ENABLE(); for (std::size_t i = 0; i < N; ++i) { diff --git a/Inc/HALAL/Models/SPI/SPI2.hpp b/Inc/HALAL/Models/SPI/SPI2.hpp index 4a5978c8a..bbba063d4 100644 --- a/Inc/HALAL/Models/SPI/SPI2.hpp +++ b/Inc/HALAL/Models/SPI/SPI2.hpp @@ -181,6 +181,8 @@ struct SPIDomain { GPIODomain::GPIO miso_gpio; GPIODomain::GPIO mosi_gpio; std::optional nss_gpio; + + DMA_Domain::DMA dma_rx_tx; consteval Device(SPIMode mode, SPIPeripheral peripheral, uint32_t max_baudrate, GPIODomain::Pin sck_pin, GPIODomain::Pin miso_pin, @@ -191,7 +193,8 @@ struct SPIDomain { sck_gpio(sck_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(sck_pin, peripheral)), miso_gpio(miso_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(miso_pin, peripheral)), mosi_gpio(mosi_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(mosi_pin, peripheral)), - nss_gpio(GPIODomain::GPIO(nss_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(nss_pin, peripheral))) + nss_gpio(GPIODomain::GPIO(nss_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(nss_pin, peripheral))), + dma_rx_tx(dma_instance(peripheral)) { config.validate(); @@ -214,7 +217,8 @@ struct SPIDomain { sck_gpio(sck_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(sck_pin, peripheral)), miso_gpio(miso_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(miso_pin, peripheral)), mosi_gpio(mosi_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(mosi_pin, peripheral)), - nss_gpio(std::nullopt) // No NSS GPIO + nss_gpio(std::nullopt), // No NSS GPIO + dma_rx_tx(dma_instance(peripheral)) { config.validate(); @@ -227,28 +231,6 @@ struct SPIDomain { template consteval std::size_t inscribe(Ctx &ctx) const { - // Convert spix to DMA_Domain::Instance - DMA_Domain::Instance dma_instance; - switch (peripheral) { - case SPIPeripheral::spi1: - dma_instance = DMA_Domain::Instance::spi1; - break; - case SPIPeripheral::spi2: - dma_instance = DMA_Domain::Instance::spi2; - break; - case SPIPeripheral::spi3: - dma_instance = DMA_Domain::Instance::spi3; - break; - case SPIPeripheral::spi4: - dma_instance = DMA_Domain::Instance::spi4; - break; - case SPIPeripheral::spi5: - dma_instance = DMA_Domain::Instance::spi5; - break; - default: - compile_error("Invalid SPI peripheral for DMA mapping"); - } - DMA_Domain::DMA dma_rx_tx(dma_instance); auto dma_indices = dma_rx_tx.inscribe(ctx); // Conditionally add NSS GPIO if provided @@ -439,6 +421,25 @@ struct SPIDomain { compile_error("Invalid SPI peripheral specified in SPIDomain::Device"); } } + + static consteval DMA_Domain::Instance dma_instance(SPIPeripheral peripheral) { + switch (peripheral) { + case SPIPeripheral::spi1: + return DMA_Domain::Instance::spi1; + case SPIPeripheral::spi2: + return DMA_Domain::Instance::spi2; + case SPIPeripheral::spi3: + return DMA_Domain::Instance::spi3; + case SPIPeripheral::spi4: + return DMA_Domain::Instance::spi4; + case SPIPeripheral::spi5: + return DMA_Domain::Instance::spi5; + // case SPIPeripheral::spi6: + // return DMA_Domain::Instance::spi6; + default: + compile_error("Invalid SPI peripheral specified in SPIDomain::Device"); + } + } }; @@ -677,7 +678,7 @@ struct SPIDomain { static void init(std::span cfgs, std::span gpio_instances, - std::span dma_instances) { + std::span dma_instances) { for (std::size_t i = 0; i < N; ++i) { const auto &e = cfgs[i]; @@ -746,13 +747,12 @@ struct SPIDomain { auto& dma_tx = dma_instances[e.dma_tx_idx]; // DMA handles are already configured and initialized by DMA_Domain - hspi.hdmarx = &dma_rx.hdma; - hspi.hdmatx = &dma_tx.hdma; + hspi.hdmarx = &dma_rx.dma; + hspi.hdmatx = &dma_tx.dma; // Link back from DMA to SPI (required by HAL) - dma_rx.hdma.Parent = &hspi; - dma_tx.hdma.Parent = &hspi; - + dma_rx.dma.Parent = &hspi; + dma_tx.dma.Parent = &hspi; auto& init = hspi.Init; if (e.mode == SPIMode::MASTER) { init.Mode = SPI_MODE_MASTER; diff --git a/Src/HALAL/HALAL.cpp b/Src/HALAL/HALAL.cpp index 3a309fb2d..fc1e1d405 100644 --- a/Src/HALAL/HALAL.cpp +++ b/Src/HALAL/HALAL.cpp @@ -34,7 +34,7 @@ static void common_start(UART::Peripheral &printf_peripheral) { #endif #ifdef HAL_DMA_MODULE_ENABLED - DMA::start(); + // DMA::start(); #endif #ifdef HAL_FMAC_MODULE_ENABLED diff --git a/Src/HALAL/Services/Communication/SPI/SPI.cpp b/Src/HALAL/Services/Communication/SPI/SPI.cpp index 8e48abce9..007f1f0e2 100644 --- a/Src/HALAL/Services/Communication/SPI/SPI.cpp +++ b/Src/HALAL/Services/Communication/SPI/SPI.cpp @@ -432,130 +432,130 @@ void SPI::init(SPI::Instance* spi) { spi->initialized = true; } -void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef* hspi) { - if (!SPI::registered_spi_by_handler.contains(hspi)) { - ErrorHandler("Used SPI protocol without the HALAL SPI interface"); - return; - } - - SPI::Instance* spi = SPI::registered_spi_by_handler[hspi]; - switch (spi->state) { - case SPI::IDLE: - // Does nothing as there is no Order handling on a direct send - break; - case SPI::STARTING_ORDER: { - SPIBaseOrder* Order = - SPIBaseOrder::SPIOrdersByID[*(spi->SPIOrderID)]; - if (spi->mode == - SPI_MODE_MASTER) { // checks if the Order is ready on slave - if (*(spi->available_end) == *(spi->SPIOrderID)) { - spi->state = SPI::PROCESSING_ORDER; - Order->master_prepare_buffer(spi->tx_buffer); - SPI::turn_off_chip_select(spi); - - SPI::spi_communicate_order_data( - spi, spi->tx_buffer, spi->rx_buffer, - Order->payload_size - PAYLOAD_OVERHEAD); - } else { - spi->try_count++; - switch (*(spi->available_end)) { - case NO_ORDER_ID: { - spi->last_end_check = Time::get_global_tick(); - SPI::turn_on_chip_select(spi); - } break; - default: - case ERROR_ORDER_ID: { - spi->last_end_check = Time::get_global_tick(); - spi->error_count++; - SPI::turn_on_chip_select(spi); - } break; - } - } - } else { - ErrorHandler("Used master transmit Order on a slave spi"); - } - break; - } - case SPI::WAITING_ORDER: { - SPIBaseOrder* Order = - SPIBaseOrder::SPIOrdersByID[*(spi->SPIOrderID)]; - if (Order == 0x0) { - SPI::spi_recover(spi, hspi); - return; - } else if (spi->mode == - SPI_MODE_SLAVE) { // prepares the Order on the slave - Order->slave_prepare_buffer(spi->tx_buffer); - SPI::spi_communicate_order_data( - spi, spi->tx_buffer, spi->rx_buffer, Order->payload_size); - SPI::mark_slave_ready(spi); - spi->state = SPI::PROCESSING_ORDER; - } else { - ErrorHandler("Used slave process Orders on a master spi"); - } - break; - } - case SPI::PROCESSING_ORDER: { - SPIBaseOrder* Order = - SPIBaseOrder::SPIOrdersByID[*(spi->SPIOrderID)]; - - if (spi->mode == SPI_MODE_MASTER) { // ends communication - if (*(uint16_t*)&spi - ->rx_buffer[Order->CRC_index - PAYLOAD_OVERHEAD] != - *spi->SPIOrderID) { - spi->state = SPI::STARTING_ORDER; - SPI::master_check_available_end(spi); - return; - } - spi->Order_count++; - SPI::turn_on_chip_select(spi); - Order->master_process_callback(spi->rx_buffer); - spi->state = SPI::IDLE; - } else { // prepares the next received Order - if (*(uint16_t*)&spi->rx_buffer[Order->CRC_index] != - *spi->SPIOrderID) { - SPI::spi_recover(spi, hspi); - return; - } - spi->Order_count++; - SPI::mark_slave_waiting(spi); - *(spi->SPIOrderID) = NO_ORDER_ID; - *(spi->available_end) = NO_ORDER_ID; - Order->slave_process_callback(spi->rx_buffer); - SPI::slave_check_packet_ID(spi); - spi->state = SPI::WAITING_ORDER; - } - break; - } - case SPI::ERROR_RECOVERY: { - if (spi->mode == SPI_MODE_MASTER) { - // TODO - } else { - SPI::mark_slave_waiting(spi); - spi->state = - SPI::WAITING_ORDER; // prepares the next received Order - *(spi->SPIOrderID) = NO_ORDER_ID; - *(spi->available_end) = NO_ORDER_ID; - SPI::slave_check_packet_ID(spi); - } - break; - } - default: - ErrorHandler("Unknown spi state: %d", spi->state); - break; - } -} - -void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef* hspi) {} - -void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef* hspi) {} - -void HAL_SPI_ErrorCallback(SPI_HandleTypeDef* hspi) { - if ((hspi->ErrorCode & HAL_SPI_ERROR_UDR) != 0) { - SPI::spi_recover(SPI::registered_spi_by_handler[hspi], hspi); - } else { - ErrorHandler("SPI error number %u", hspi->ErrorCode); - } -} +// void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef* hspi) { +// if (!SPI::registered_spi_by_handler.contains(hspi)) { +// ErrorHandler("Used SPI protocol without the HALAL SPI interface"); +// return; +// } + +// SPI::Instance* spi = SPI::registered_spi_by_handler[hspi]; +// switch (spi->state) { +// case SPI::IDLE: +// // Does nothing as there is no Order handling on a direct send +// break; +// case SPI::STARTING_ORDER: { +// SPIBaseOrder* Order = +// SPIBaseOrder::SPIOrdersByID[*(spi->SPIOrderID)]; +// if (spi->mode == +// SPI_MODE_MASTER) { // checks if the Order is ready on slave +// if (*(spi->available_end) == *(spi->SPIOrderID)) { +// spi->state = SPI::PROCESSING_ORDER; +// Order->master_prepare_buffer(spi->tx_buffer); +// SPI::turn_off_chip_select(spi); + +// SPI::spi_communicate_order_data( +// spi, spi->tx_buffer, spi->rx_buffer, +// Order->payload_size - PAYLOAD_OVERHEAD); +// } else { +// spi->try_count++; +// switch (*(spi->available_end)) { +// case NO_ORDER_ID: { +// spi->last_end_check = Time::get_global_tick(); +// SPI::turn_on_chip_select(spi); +// } break; +// default: +// case ERROR_ORDER_ID: { +// spi->last_end_check = Time::get_global_tick(); +// spi->error_count++; +// SPI::turn_on_chip_select(spi); +// } break; +// } +// } +// } else { +// ErrorHandler("Used master transmit Order on a slave spi"); +// } +// break; +// } +// case SPI::WAITING_ORDER: { +// SPIBaseOrder* Order = +// SPIBaseOrder::SPIOrdersByID[*(spi->SPIOrderID)]; +// if (Order == 0x0) { +// SPI::spi_recover(spi, hspi); +// return; +// } else if (spi->mode == +// SPI_MODE_SLAVE) { // prepares the Order on the slave +// Order->slave_prepare_buffer(spi->tx_buffer); +// SPI::spi_communicate_order_data( +// spi, spi->tx_buffer, spi->rx_buffer, Order->payload_size); +// SPI::mark_slave_ready(spi); +// spi->state = SPI::PROCESSING_ORDER; +// } else { +// ErrorHandler("Used slave process Orders on a master spi"); +// } +// break; +// } +// case SPI::PROCESSING_ORDER: { +// SPIBaseOrder* Order = +// SPIBaseOrder::SPIOrdersByID[*(spi->SPIOrderID)]; + +// if (spi->mode == SPI_MODE_MASTER) { // ends communication +// if (*(uint16_t*)&spi +// ->rx_buffer[Order->CRC_index - PAYLOAD_OVERHEAD] != +// *spi->SPIOrderID) { +// spi->state = SPI::STARTING_ORDER; +// SPI::master_check_available_end(spi); +// return; +// } +// spi->Order_count++; +// SPI::turn_on_chip_select(spi); +// Order->master_process_callback(spi->rx_buffer); +// spi->state = SPI::IDLE; +// } else { // prepares the next received Order +// if (*(uint16_t*)&spi->rx_buffer[Order->CRC_index] != +// *spi->SPIOrderID) { +// SPI::spi_recover(spi, hspi); +// return; +// } +// spi->Order_count++; +// SPI::mark_slave_waiting(spi); +// *(spi->SPIOrderID) = NO_ORDER_ID; +// *(spi->available_end) = NO_ORDER_ID; +// Order->slave_process_callback(spi->rx_buffer); +// SPI::slave_check_packet_ID(spi); +// spi->state = SPI::WAITING_ORDER; +// } +// break; +// } +// case SPI::ERROR_RECOVERY: { +// if (spi->mode == SPI_MODE_MASTER) { +// // TODO +// } else { +// SPI::mark_slave_waiting(spi); +// spi->state = +// SPI::WAITING_ORDER; // prepares the next received Order +// *(spi->SPIOrderID) = NO_ORDER_ID; +// *(spi->available_end) = NO_ORDER_ID; +// SPI::slave_check_packet_ID(spi); +// } +// break; +// } +// default: +// ErrorHandler("Unknown spi state: %d", spi->state); +// break; +// } +// } + +// // void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef* hspi) {} + +// // void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef* hspi) {} + +// // void HAL_SPI_ErrorCallback(SPI_HandleTypeDef* hspi) { +// // if ((hspi->ErrorCode & HAL_SPI_ERROR_UDR) != 0) { +// // SPI::spi_recover(SPI::registered_spi_by_handler[hspi], hspi); +// // } else { +// // ErrorHandler("SPI error number %u", hspi->ErrorCode); +// // } +// // } void SPI::spi_communicate_order_data(SPI::Instance* spi, uint8_t* value_to_send, uint8_t* value_to_receive, From 6538affc4d97989d06296a839f4ff109536997af Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Thu, 22 Jan 2026 22:52:27 +0100 Subject: [PATCH 091/109] fix(SPI): Pin A15 AF were incorrect --- Inc/HALAL/Models/Pin.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Inc/HALAL/Models/Pin.hpp b/Inc/HALAL/Models/Pin.hpp index 97096e90c..d8dade25b 100644 --- a/Inc/HALAL/Models/Pin.hpp +++ b/Inc/HALAL/Models/Pin.hpp @@ -22,7 +22,7 @@ constexpr GPIODomain::Pin PA11{A, GPIO_PIN_11, 0b0101111110010011}; constexpr GPIODomain::Pin PA12{A, GPIO_PIN_12, 0b0011111110010111}; constexpr GPIODomain::Pin PA13{A, GPIO_PIN_13, 0b1000000000000001}; constexpr GPIODomain::Pin PA14{A, GPIO_PIN_14, 0b1000000000000001}; -constexpr GPIODomain::Pin PA15{A, GPIO_PIN_15, 0b0111010111111011}; +constexpr GPIODomain::Pin PA15{A, GPIO_PIN_15, 0b1100111111010011}; // Port B constexpr GPIODomain::Pin PB0{B, GPIO_PIN_0, 0b0111110011111011}; From a6cc1e31466069069b52eecf695c7a079483205e Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Fri, 23 Jan 2026 01:26:44 +0100 Subject: [PATCH 092/109] fix(SPI): Fix instances array --- Inc/HALAL/Models/SPI/SPI2.hpp | 21 +++++++++++++++++++-- Src/HALAL/Models/SPI/SPI2.cpp | 6 ++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Inc/HALAL/Models/SPI/SPI2.hpp b/Inc/HALAL/Models/SPI/SPI2.hpp index bbba063d4..9cd6212fb 100644 --- a/Inc/HALAL/Models/SPI/SPI2.hpp +++ b/Inc/HALAL/Models/SPI/SPI2.hpp @@ -738,8 +738,6 @@ struct SPIDomain { spi_number = 6; } - spi_instances[spi_number - 1] = &instances[i]; - auto& hspi = instances[i].hspi; hspi.Instance = instances[i].instance; @@ -753,6 +751,10 @@ struct SPIDomain { // Link back from DMA to SPI (required by HAL) dma_rx.dma.Parent = &hspi; dma_tx.dma.Parent = &hspi; + + HAL_DMA_Init(hspi.hdmarx); + HAL_DMA_Init(hspi.hdmatx); + auto& init = hspi.Init; if (e.mode == SPIMode::MASTER) { init.Mode = SPI_MODE_MASTER; @@ -821,6 +823,21 @@ struct SPIDomain { HAL_NVIC_SetPriority(SPI6_IRQn, 1, 0); HAL_NVIC_EnableIRQ(SPI6_IRQn); } + + // Map instance pointer + if (peripheral == SPIPeripheral::spi1) { + spi_instances[0] = &instances[i]; + } else if (peripheral == SPIPeripheral::spi2) { + spi_instances[1] = &instances[i]; + } else if (peripheral == SPIPeripheral::spi3) { + spi_instances[2] = &instances[i]; + } else if (peripheral == SPIPeripheral::spi4) { + spi_instances[3] = &instances[i]; + } else if (peripheral == SPIPeripheral::spi5) { + spi_instances[4] = &instances[i]; + } else if (peripheral == SPIPeripheral::spi6) { + spi_instances[5] = &instances[i]; + } } } }; diff --git a/Src/HALAL/Models/SPI/SPI2.cpp b/Src/HALAL/Models/SPI/SPI2.cpp index 95b593826..f83ea553c 100644 --- a/Src/HALAL/Models/SPI/SPI2.cpp +++ b/Src/HALAL/Models/SPI/SPI2.cpp @@ -13,8 +13,6 @@ uint32_t ST_LIB::SPIDomain::calculate_prescaler(uint32_t src_freq, uint32_t max_ return get_prescaler_flag(prescaler); } -ST_LIB::SPIDomain::Instance* spi_instances[ST_LIB::SPIDomain::max_instances]; - extern "C" { /** @@ -80,6 +78,8 @@ void SPI6_IRQHandler(void) { */ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) { + auto& spi_instances = ST_LIB::SPIDomain::spi_instances; + ST_LIB::SPIDomain::Instance* inst = nullptr; if (spi_instances[0] != nullptr && hspi == &spi_instances[0]->hspi) { inst = spi_instances[0]; @@ -112,6 +112,8 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { } void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { + auto& spi_instances = ST_LIB::SPIDomain::spi_instances; + uint32_t error_code = hspi->ErrorCode; uint32_t inst_idx = 0; if (spi_instances[0] != nullptr && hspi == &spi_instances[0]->hspi) { From 6d49eb37e687e98a1efffc8a19f5dc55378f7aa1 Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Mon, 26 Jan 2026 01:10:00 +0100 Subject: [PATCH 093/109] feat(SPI): Add templated functions to acccept anything --- Inc/HALAL/Models/SPI/SPI2.hpp | 194 ++++++++++++++++++++++++++++++---- 1 file changed, 176 insertions(+), 18 deletions(-) diff --git a/Inc/HALAL/Models/SPI/SPI2.hpp b/Inc/HALAL/Models/SPI/SPI2.hpp index 9cd6212fb..020af5314 100644 --- a/Inc/HALAL/Models/SPI/SPI2.hpp +++ b/Inc/HALAL/Models/SPI/SPI2.hpp @@ -493,53 +493,155 @@ struct SPIDomain { /** * @brief Sends data over SPI in blocking mode. */ - bool send(span data) { - auto error_code = HAL_SPI_Transmit(&spi_instance.hspi, data.data(), data.size(), 10); + template + bool send(span data) { + auto error_code = HAL_SPI_Transmit(&spi_instance.hspi, (uint8_t*)data.data(), data.size(), 10); + return check_error_code(error_code); + } + + /** + * @brief Sends a trivially copyable data type over SPI in blocking mode. + */ + template + bool send(const T& data) requires std::is_trivially_copyable_v { + auto error_code = HAL_SPI_Transmit(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T), 10); return check_error_code(error_code); } /** * @brief Receives data over SPI in blocking mode. */ - bool receive(span data) { - auto error_code = HAL_SPI_Receive(&spi_instance.hspi, data.data(), data.size(), 10); + template + bool receive(span data) { + auto error_code = HAL_SPI_Receive(&spi_instance.hspi, (uint8_t*)data.data(), data.size(), 10); + return check_error_code(error_code); + } + + /** + * @brief Receives a trivially copyable data type over SPI in blocking mode. + */ + template + bool receive(T& data) requires std::is_trivially_copyable_v { + auto error_code = HAL_SPI_Receive(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T), 10); return check_error_code(error_code); } /** * @brief Sends and receives data over SPI in blocking mode. */ - bool transceive(span tx_data, span rx_data) { - auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, tx_data.data(), rx_data.data(), tx_data.size(), 10); + template + bool transceive(span tx_data, span rx_data) { + auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, (uint8_t*)tx_data.data(), (uint8_t*)rx_data.data(), std::min(tx_data.size(), rx_data.size()), 10); return check_error_code(error_code); } + /** + * @brief Sends and receives a trivially copyable data type over SPI in blocking mode. + */ + template + bool transceive(span tx_data, T& rx_data) requires std::is_trivially_copyable_v { + auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, (uint8_t*)tx_data.data(), reinterpret_cast(&rx_data), std::min(tx_data.size(), sizeof(T)), 10); + return check_error_code(error_code); + } + + /** + * @brief Sends and receives a trivially copyable data type over SPI in blocking mode. + */ + template + bool transceive(const T& tx_data, span rx_data) requires std::is_trivially_copyable_v { + auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, reinterpret_cast(&tx_data), (uint8_t*)rx_data.data(), std::min(sizeof(T), rx_data.size()), 10); + return check_error_code(error_code); + } + + /** + * @brief Sends and receives a trivially copyable data type over SPI in blocking mode. + */ + template + bool transceive(const T1& tx_data, T2& rx_data) requires (std::is_trivially_copyable_v && std::is_trivially_copyable_v) { + auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, reinterpret_cast(&tx_data), reinterpret_cast(&rx_data), std::min(sizeof(T1), sizeof(T2)), 10); + return check_error_code(error_code); + } /** * @brief Sends data over SPI using DMA, uses an optional operation flag to signal completion. */ - bool send_DMA(span data, volatile bool* operation_flag = nullptr) { + template + bool send_DMA(span data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; - auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, data.data(), data.size()); + auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, (uint8_t*)data.data(), data.size()); + return check_error_code(error_code); + } + + /** + * @brief Sends a trivially copyable data type over SPI using DMA, uses an optional operation flag to signal completion. + */ + template + bool send_DMA(const T& data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { + spi_instance.operation_flag = operation_flag; + auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T)); return check_error_code(error_code); } /** * @brief Receives data over SPI using DMA, uses an optional operation flag to signal completion. */ - bool receive_DMA(span data, volatile bool* operation_flag = nullptr) { + template + bool receive_DMA(span data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; - auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, data.data(), data.size()); + auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, (uint8_t*)data.data(), data.size()); + return check_error_code(error_code); + } + + /** + * @brief Receives a trivially copyable data type over SPI using DMA, uses an optional operation flag to signal completion. + */ + template + bool receive_DMA(T& data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { + spi_instance.operation_flag = operation_flag; + auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T)); return check_error_code(error_code); } /** * @brief Sends and receives data over SPI using DMA, uses an optional operation flag to signal completion. */ - bool transceive_DMA(span tx_data, span rx_data, volatile bool* operation_flag = nullptr) { + template + bool transceive_DMA(span tx_data, span rx_data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; auto size = std::min(tx_data.size(), rx_data.size()); - auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, tx_data.data(), rx_data.data(), size); + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), (uint8_t*)rx_data.data(), size); + return check_error_code(error_code); + } + + /** + * @brief Sends a span and receives a trivially copyable type over SPI using DMA, uses an optional operation flag to signal completion. + */ + template + bool transceive_DMA(span tx_data, T& rx_data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { + spi_instance.operation_flag = operation_flag; + auto size = std::min(tx_data.size(), sizeof(T)); + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), reinterpret_cast(&rx_data), size); + return check_error_code(error_code); + } + + /** + * @brief Sends a trivially copyable type and receives a span over SPI using DMA, uses an optional operation flag to signal completion. + */ + template + bool transceive_DMA(const T& tx_data, span rx_data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { + spi_instance.operation_flag = operation_flag; + auto size = std::min(sizeof(T), rx_data.size()); + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, reinterpret_cast(&tx_data), (uint8_t*)rx_data.data(), size); + return check_error_code(error_code); + } + + /** + * @brief Sends and receives a trivially copyable data type over SPI using DMA, uses an optional operation flag to signal completion. + */ + template + bool transceive_DMA(const T1& tx_data, T2& rx_data, volatile bool* operation_flag = nullptr) requires (std::is_trivially_copyable_v && std::is_trivially_copyable_v) { + spi_instance.operation_flag = operation_flag; + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, reinterpret_cast(&tx_data), reinterpret_cast(&rx_data), std::min(sizeof(T1), sizeof(T2))); return check_error_code(error_code); } @@ -567,28 +669,84 @@ struct SPIDomain { /** * @brief Listens for data over SPI using DMA, uses an optional operation flag to signal completion. */ - bool listen(span data, volatile bool* operation_flag = nullptr) { + template + bool listen(span data, volatile bool* operation_flag = nullptr) { + spi_instance.operation_flag = operation_flag; + auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, (uint8_t*)data.data(), data.size()); + return check_error_code(error_code); + } + + /** + * @brief Listens for trivially copyable data type over SPI using DMA, uses an optional operation flag to signal completion. + */ + template + bool listen(T& data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { spi_instance.operation_flag = operation_flag; - auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, data.data(), data.size()); + auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T)); return check_error_code(error_code); } /** * @brief Arms the SPI to send data over DMA when requested, uses an optional operation flag to signal completion. */ - bool arm(span tx_data, volatile bool* operation_flag = nullptr) { + template + bool arm(span tx_data, volatile bool* operation_flag = nullptr) { + spi_instance.operation_flag = operation_flag; + auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), tx_data.size()); + return check_error_code(error_code); + } + + /** + * @brief Arms the SPI to send a trivially copyable data type over DMA when requested, uses an optional operation flag to signal completion. + */ + template + bool arm(const T& data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { spi_instance.operation_flag = operation_flag; - auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, tx_data.data(), tx_data.size()); + auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T)); return check_error_code(error_code); } /** * @brief Sends and receives data over SPI using DMA, uses an optional operation flag to signal completion. */ - bool transceive(span tx_data, span rx_data, volatile bool* operation_flag = nullptr) { + template + bool transceive(span tx_data, span rx_data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; auto size = std::min(tx_data.size(), rx_data.size()); - auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, tx_data.data(), rx_data.data(), size); + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), (uint8_t*)rx_data.data(), size); + return check_error_code(error_code); + } + + /** + * @brief Sends a span and receives a trivially copyable type over SPI using DMA, uses an optional operation flag to signal completion. + */ + template + bool transceive(span tx_data, T& rx_data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { + spi_instance.operation_flag = operation_flag; + auto size = std::min(tx_data.size(), sizeof(T)); + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), reinterpret_cast(&rx_data), size); + return check_error_code(error_code); + } + + /** + * @brief Sends a trivially copyable type and receives a span over SPI using DMA, uses an optional operation flag to signal completion. + */ + template + bool transceive(const T& tx_data, span rx_data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { + spi_instance.operation_flag = operation_flag; + auto size = std::min(sizeof(T), rx_data.size()); + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, reinterpret_cast(&tx_data), (uint8_t*)rx_data.data(), size); + return check_error_code(error_code); + } + + /** + * @brief Sends and receives a trivially copyable data type over SPI using DMA, uses an optional operation flag to signal completion. + */ + template + bool transceive(const T1& tx_data, T2& rx_data, volatile bool* operation_flag = nullptr) requires (std::is_trivially_copyable_v && std::is_trivially_copyable_v) { + spi_instance.operation_flag = operation_flag; + auto size = std::min(sizeof(T1), sizeof(T2)); + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, reinterpret_cast(&tx_data), reinterpret_cast(&rx_data), size); return check_error_code(error_code); } From 770f323c49d2e53e1247d4d5f8a6cae413fcc583 Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Tue, 27 Jan 2026 23:53:58 +0100 Subject: [PATCH 094/109] fix(SPI): Alignments and correct frame calculations --- Inc/HALAL/Models/SPI/SPI2.hpp | 179 ++++++++++++++++++++++++++++------ 1 file changed, 149 insertions(+), 30 deletions(-) diff --git a/Inc/HALAL/Models/SPI/SPI2.hpp b/Inc/HALAL/Models/SPI/SPI2.hpp index 020af5314..837af9a82 100644 --- a/Inc/HALAL/Models/SPI/SPI2.hpp +++ b/Inc/HALAL/Models/SPI/SPI2.hpp @@ -488,6 +488,9 @@ struct SPIDomain { */ template struct SPIWrapper { + static constexpr uint32_t data_bits = static_cast(device_request.config.data_size); + static constexpr uint32_t frame_size = (data_bits <= 8) ? 1 : ((data_bits <= 16) ? 2 : 4); + SPIWrapper(Instance &instance) : spi_instance{instance} {} /** @@ -495,7 +498,11 @@ struct SPIDomain { */ template bool send(span data) { - auto error_code = HAL_SPI_Transmit(&spi_instance.hspi, (uint8_t*)data.data(), data.size(), 10); + if (data.size_bytes() % frame_size != 0) { + ErrorHandler("SPI data size (%d) not aligned to frame size (%d)", data.size_bytes(), frame_size); + return false; + } + auto error_code = HAL_SPI_Transmit(&spi_instance.hspi, (uint8_t*)data.data(), data.size_bytes() / frame_size, 10); return check_error_code(error_code); } @@ -504,7 +511,11 @@ struct SPIDomain { */ template bool send(const T& data) requires std::is_trivially_copyable_v { - auto error_code = HAL_SPI_Transmit(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T), 10); + if (sizeof(T) % frame_size != 0) { + ErrorHandler("SPI data type size (%d) not aligned to frame size (%d)", sizeof(T), frame_size); + return false; + } + auto error_code = HAL_SPI_Transmit(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T) / frame_size, 10); return check_error_code(error_code); } @@ -513,7 +524,11 @@ struct SPIDomain { */ template bool receive(span data) { - auto error_code = HAL_SPI_Receive(&spi_instance.hspi, (uint8_t*)data.data(), data.size(), 10); + if (data.size_bytes() % frame_size != 0) { + ErrorHandler("SPI data size (%d) not aligned to frame size (%d)", data.size_bytes(), frame_size); + return false; + } + auto error_code = HAL_SPI_Receive(&spi_instance.hspi, (uint8_t*)data.data(), data.size_bytes() / frame_size, 10); return check_error_code(error_code); } @@ -522,7 +537,11 @@ struct SPIDomain { */ template bool receive(T& data) requires std::is_trivially_copyable_v { - auto error_code = HAL_SPI_Receive(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T), 10); + if (sizeof(T) % frame_size != 0) { + ErrorHandler("SPI data type size (%d) not aligned to frame size (%d)", sizeof(T), frame_size); + return false; + } + auto error_code = HAL_SPI_Receive(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T) / frame_size, 10); return check_error_code(error_code); } @@ -531,7 +550,12 @@ struct SPIDomain { */ template bool transceive(span tx_data, span rx_data) { - auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, (uint8_t*)tx_data.data(), (uint8_t*)rx_data.data(), std::min(tx_data.size(), rx_data.size()), 10); + size_t size = std::min(tx_data.size_bytes(), rx_data.size_bytes()); + if (size % frame_size != 0) { + ErrorHandler("SPI transaction size (%d) not aligned to frame size (%d)", size, frame_size); + return false; + } + auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, (uint8_t*)tx_data.data(), (uint8_t*)rx_data.data(), size / frame_size, 10); return check_error_code(error_code); } @@ -540,7 +564,12 @@ struct SPIDomain { */ template bool transceive(span tx_data, T& rx_data) requires std::is_trivially_copyable_v { - auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, (uint8_t*)tx_data.data(), reinterpret_cast(&rx_data), std::min(tx_data.size(), sizeof(T)), 10); + size_t size = std::min(tx_data.size_bytes(), sizeof(T)); + if (size % frame_size != 0) { + ErrorHandler("SPI transaction size (%d) not aligned to frame size (%d)", size, frame_size); + return false; + } + auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, (uint8_t*)tx_data.data(), reinterpret_cast(&rx_data), size / frame_size, 10); return check_error_code(error_code); } @@ -549,7 +578,12 @@ struct SPIDomain { */ template bool transceive(const T& tx_data, span rx_data) requires std::is_trivially_copyable_v { - auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, reinterpret_cast(&tx_data), (uint8_t*)rx_data.data(), std::min(sizeof(T), rx_data.size()), 10); + size_t size = std::min(sizeof(T), rx_data.size_bytes()); + if (size % frame_size != 0) { + ErrorHandler("SPI transaction size (%d) not aligned to frame size (%d)", size, frame_size); + return false; + } + auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, reinterpret_cast(&tx_data), (uint8_t*)rx_data.data(), size / frame_size, 10); return check_error_code(error_code); } @@ -558,7 +592,12 @@ struct SPIDomain { */ template bool transceive(const T1& tx_data, T2& rx_data) requires (std::is_trivially_copyable_v && std::is_trivially_copyable_v) { - auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, reinterpret_cast(&tx_data), reinterpret_cast(&rx_data), std::min(sizeof(T1), sizeof(T2)), 10); + size_t size = std::min(sizeof(T1), sizeof(T2)); + if (size % frame_size != 0) { + ErrorHandler("SPI transaction size (%d) not aligned to frame size (%d)", size, frame_size); + return false; + } + auto error_code = HAL_SPI_TransmitReceive(&spi_instance.hspi, reinterpret_cast(&tx_data), reinterpret_cast(&rx_data), size / frame_size, 10); return check_error_code(error_code); } @@ -568,7 +607,11 @@ struct SPIDomain { template bool send_DMA(span data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; - auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, (uint8_t*)data.data(), data.size()); + if (data.size_bytes() % frame_size != 0) { + ErrorHandler("SPI data size (%d) not aligned to frame size (%d)", data.size_bytes(), frame_size); + return false; + } + auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, (uint8_t*)data.data(), data.size_bytes() / frame_size); return check_error_code(error_code); } @@ -578,7 +621,11 @@ struct SPIDomain { template bool send_DMA(const T& data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { spi_instance.operation_flag = operation_flag; - auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T)); + if (sizeof(T) % frame_size != 0) { + ErrorHandler("SPI data size (%d) not aligned to frame size (%d)", sizeof(T), frame_size); + return false; + } + auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T) / frame_size); return check_error_code(error_code); } @@ -588,7 +635,11 @@ struct SPIDomain { template bool receive_DMA(span data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; - auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, (uint8_t*)data.data(), data.size()); + if (data.size_bytes() % frame_size != 0) { + ErrorHandler("SPI data size (%d) not aligned to frame size (%d)", data.size_bytes(), frame_size); + return false; + } + auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, (uint8_t*)data.data(), data.size_bytes() / frame_size); return check_error_code(error_code); } @@ -598,7 +649,11 @@ struct SPIDomain { template bool receive_DMA(T& data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { spi_instance.operation_flag = operation_flag; - auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T)); + if (sizeof(T) % frame_size != 0) { + ErrorHandler("SPI data size (%d) not aligned to frame size (%d)", sizeof(T), frame_size); + return false; + } + auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T) / frame_size); return check_error_code(error_code); } @@ -608,8 +663,12 @@ struct SPIDomain { template bool transceive_DMA(span tx_data, span rx_data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; - auto size = std::min(tx_data.size(), rx_data.size()); - auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), (uint8_t*)rx_data.data(), size); + auto size = std::min(tx_data.size_bytes(), rx_data.size_bytes()); + if (size % frame_size != 0) { + ErrorHandler("SPI transaction size (%d) not aligned to frame size (%d)", size, frame_size); + return false; + } + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), (uint8_t*)rx_data.data(), size / frame_size); return check_error_code(error_code); } @@ -619,8 +678,12 @@ struct SPIDomain { template bool transceive_DMA(span tx_data, T& rx_data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { spi_instance.operation_flag = operation_flag; - auto size = std::min(tx_data.size(), sizeof(T)); - auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), reinterpret_cast(&rx_data), size); + auto size = std::min(tx_data.size_bytes(), sizeof(T)); + if (size % frame_size != 0) { + ErrorHandler("SPI transaction size (%d) not aligned to frame size (%d)", size, frame_size); + return false; + } + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), reinterpret_cast(&rx_data), size / frame_size); return check_error_code(error_code); } @@ -630,8 +693,12 @@ struct SPIDomain { template bool transceive_DMA(const T& tx_data, span rx_data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { spi_instance.operation_flag = operation_flag; - auto size = std::min(sizeof(T), rx_data.size()); - auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, reinterpret_cast(&tx_data), (uint8_t*)rx_data.data(), size); + auto size = std::min(sizeof(T), rx_data.size_bytes()); + if (size % frame_size != 0) { + ErrorHandler("SPI transaction size (%d) not aligned to frame size (%d)", size, frame_size); + return false; + } + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, reinterpret_cast(&tx_data), (uint8_t*)rx_data.data(), size / frame_size); return check_error_code(error_code); } @@ -641,7 +708,12 @@ struct SPIDomain { template bool transceive_DMA(const T1& tx_data, T2& rx_data, volatile bool* operation_flag = nullptr) requires (std::is_trivially_copyable_v && std::is_trivially_copyable_v) { spi_instance.operation_flag = operation_flag; - auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, reinterpret_cast(&tx_data), reinterpret_cast(&rx_data), std::min(sizeof(T1), sizeof(T2))); + auto size = std::min(sizeof(T1), sizeof(T2)); + if (size % frame_size != 0) { + ErrorHandler("SPI transaction size (%d) not aligned to frame size (%d)", size, frame_size); + return false; + } + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, reinterpret_cast(&tx_data), reinterpret_cast(&rx_data), size / frame_size); return check_error_code(error_code); } @@ -664,6 +736,9 @@ struct SPIDomain { */ template struct SPIWrapper { + static constexpr uint32_t data_bits = static_cast(device_request.config.data_size); + static constexpr uint32_t frame_size = (data_bits <= 8) ? 1 : ((data_bits <= 16) ? 2 : 4); + SPIWrapper(Instance &instance) : spi_instance{instance} {} /** @@ -672,7 +747,11 @@ struct SPIDomain { template bool listen(span data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; - auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, (uint8_t*)data.data(), data.size()); + if (data.size_bytes() % frame_size != 0) { + ErrorHandler("SPI data size (%d) not aligned to frame size (%d)", data.size_bytes(), frame_size); + return false; + } + auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, (uint8_t*)data.data(), data.size_bytes() / frame_size); return check_error_code(error_code); } @@ -682,7 +761,11 @@ struct SPIDomain { template bool listen(T& data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { spi_instance.operation_flag = operation_flag; - auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T)); + if (sizeof(T) % frame_size != 0) { + ErrorHandler("SPI data size (%d) not aligned to frame size (%d)", sizeof(T), frame_size); + return false; + } + auto error_code = HAL_SPI_Receive_DMA(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T) / frame_size); return check_error_code(error_code); } @@ -692,7 +775,11 @@ struct SPIDomain { template bool arm(span tx_data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; - auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), tx_data.size()); + if (tx_data.size_bytes() % frame_size != 0) { + ErrorHandler("SPI data size (%d) not aligned to frame size (%d)", tx_data.size_bytes(), frame_size); + return false; + } + auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), tx_data.size_bytes() / frame_size); return check_error_code(error_code); } @@ -702,7 +789,11 @@ struct SPIDomain { template bool arm(const T& data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { spi_instance.operation_flag = operation_flag; - auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T)); + if (sizeof(T) % frame_size != 0) { + ErrorHandler("SPI data size (%d) not aligned to frame size (%d)", sizeof(T), frame_size); + return false; + } + auto error_code = HAL_SPI_Transmit_DMA(&spi_instance.hspi, reinterpret_cast(&data), sizeof(T) / frame_size); return check_error_code(error_code); } @@ -712,8 +803,12 @@ struct SPIDomain { template bool transceive(span tx_data, span rx_data, volatile bool* operation_flag = nullptr) { spi_instance.operation_flag = operation_flag; - auto size = std::min(tx_data.size(), rx_data.size()); - auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), (uint8_t*)rx_data.data(), size); + auto size = std::min(tx_data.size_bytes(), rx_data.size_bytes()); + if (size % frame_size != 0) { + ErrorHandler("SPI transaction size (%d) not aligned to frame size (%d)", size, frame_size); + return false; + } + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), (uint8_t*)rx_data.data(), size / frame_size); return check_error_code(error_code); } @@ -723,8 +818,12 @@ struct SPIDomain { template bool transceive(span tx_data, T& rx_data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { spi_instance.operation_flag = operation_flag; - auto size = std::min(tx_data.size(), sizeof(T)); - auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), reinterpret_cast(&rx_data), size); + auto size = std::min(tx_data.size_bytes(), sizeof(T)); + if (size % frame_size != 0) { + ErrorHandler("SPI transaction size (%d) not aligned to frame size (%d)", size, frame_size); + return false; + } + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, (uint8_t*)tx_data.data(), reinterpret_cast(&rx_data), size / frame_size); return check_error_code(error_code); } @@ -734,8 +833,12 @@ struct SPIDomain { template bool transceive(const T& tx_data, span rx_data, volatile bool* operation_flag = nullptr) requires std::is_trivially_copyable_v { spi_instance.operation_flag = operation_flag; - auto size = std::min(sizeof(T), rx_data.size()); - auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, reinterpret_cast(&tx_data), (uint8_t*)rx_data.data(), size); + auto size = std::min(sizeof(T), rx_data.size_bytes()); + if (size % frame_size != 0) { + ErrorHandler("SPI transaction size (%d) not aligned to frame size (%d)", size, frame_size); + return false; + } + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, reinterpret_cast(&tx_data), (uint8_t*)rx_data.data(), size / frame_size); return check_error_code(error_code); } @@ -746,7 +849,11 @@ struct SPIDomain { bool transceive(const T1& tx_data, T2& rx_data, volatile bool* operation_flag = nullptr) requires (std::is_trivially_copyable_v && std::is_trivially_copyable_v) { spi_instance.operation_flag = operation_flag; auto size = std::min(sizeof(T1), sizeof(T2)); - auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, reinterpret_cast(&tx_data), reinterpret_cast(&rx_data), size); + if (size % frame_size != 0) { + ErrorHandler("SPI transaction size (%d) not aligned to frame size (%d)", size, frame_size); + return false; + } + auto error_code = HAL_SPI_TransmitReceive_DMA(&spi_instance.hspi, reinterpret_cast(&tx_data), reinterpret_cast(&rx_data), size / frame_size); return check_error_code(error_code); } @@ -910,6 +1017,18 @@ struct SPIDomain { dma_rx.dma.Parent = &hspi; dma_tx.dma.Parent = &hspi; + if (e.config.data_size > DataSize::SIZE_16BIT) { + dma_rx.dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + dma_rx.dma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + dma_tx.dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + dma_tx.dma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + } else if (e.config.data_size > DataSize::SIZE_8BIT) { + dma_rx.dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + dma_rx.dma.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + dma_tx.dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + dma_tx.dma.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + } + HAL_DMA_Init(hspi.hdmarx); HAL_DMA_Init(hspi.hdmatx); From 1731518bc6adc1b759791714869a6121178d30df Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Wed, 28 Jan 2026 00:27:17 +0100 Subject: [PATCH 095/109] feat(SPI): Add slave software nss interface --- Inc/HALAL/Models/SPI/SPI2.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Inc/HALAL/Models/SPI/SPI2.hpp b/Inc/HALAL/Models/SPI/SPI2.hpp index 837af9a82..97c137422 100644 --- a/Inc/HALAL/Models/SPI/SPI2.hpp +++ b/Inc/HALAL/Models/SPI/SPI2.hpp @@ -741,6 +741,14 @@ struct SPIDomain { SPIWrapper(Instance &instance) : spi_instance{instance} {} + void set_software_nss(bool selected) requires (device_request.config.nss_mode == SPIConfigTypes::NSSMode::SOFTWARE) { + if (selected) { + CLEAR_BIT(spi_instance.instance->CR1, SPI_CR1_SSI); + } else { + SET_BIT(spi_instance.instance->CR1, SPI_CR1_SSI); + } + } + /** * @brief Listens for data over SPI using DMA, uses an optional operation flag to signal completion. */ From a559017de58ab1b80fe0f72a6446f6154260314e Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Fri, 30 Jan 2026 19:46:15 +0100 Subject: [PATCH 096/109] fix(GH_Actions): Don't upload build artifacts --- .github/workflows/build.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 974e7ff1b..8320b0d6b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,12 +55,12 @@ jobs: cmake --build --preset ${{ inputs.preset }} shell: bash - - name: Upload Build - id: upload-build-artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ inputs.preset }} - path: out/build/${{ inputs.preset }}/libst-lib.a - retention-days: 7 - compression-level: 0 - if-no-files-found: error \ No newline at end of file + # - name: Upload Build + # id: upload-build-artifact + # uses: actions/upload-artifact@v4 + # with: + # name: ${{ inputs.preset }} + # path: out/build/${{ inputs.preset }}/libst-lib.a + # retention-days: 7 + # compression-level: 0 + # if-no-files-found: error \ No newline at end of file From 41cc5771bc68f7c9fe428cff29105b854e9b1a09 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Sat, 31 Jan 2026 20:11:03 +0100 Subject: [PATCH 097/109] multiple names fixed --- Inc/HALAL/Models/DMA/DMA2.hpp | 116 +++++++++++++++++----------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index bd578ea52..e81d16505 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -26,7 +26,7 @@ namespace ST_LIB { extern void compile_error(const char *msg); struct DMA_Domain { - enum class Instance : uint8_t {none, adc1, adc2, adc3, + enum class Peripheral : uint8_t {none, adc1, adc2, adc3, i2c1, i2c2, i2c3, i2c5, spi1, spi2, spi3, spi4, spi5, fmac}; @@ -62,7 +62,7 @@ namespace ST_LIB { } struct Entry { - Instance instance; + Peripheral instance; Stream stream; IRQn_Type irqn; uint8_t id; @@ -75,7 +75,7 @@ namespace ST_LIB { std::array e{}; - consteval DMA(Instance instance) { + consteval DMA(Peripheral instance) { static_assert(sizeof...(Ss) <= 3, "Máximo 3 streams"); Stream streams[] = { Ss... }; @@ -129,69 +129,69 @@ namespace ST_LIB { else compile_error("No tiene que llegar aqui nunca, creo"); } - static constexpr inline bool is_one_of(Instance instance, auto... bases) { + static constexpr inline bool is_one_of(Peripheral instance, auto... bases) { return ((instance == bases) || ...); } - static constexpr inline bool is_spi(Instance instance) { - return is_one_of(instance, Instance::spi1, Instance::spi2, - Instance::spi3, Instance::spi4, Instance::spi5); + static constexpr inline bool is_spi(Peripheral instance) { + return is_one_of(instance, Peripheral::spi1, Peripheral::spi2, + Peripheral::spi3, Peripheral::spi4, Peripheral::spi5); } - static constexpr inline bool is_i2c(Instance instance) { - return is_one_of(instance, Instance::i2c1, Instance::i2c2, - Instance::i2c3, Instance::i2c5); + static constexpr inline bool is_i2c(Peripheral instance) { + return is_one_of(instance, Peripheral::i2c1, Peripheral::i2c2, + Peripheral::i2c3, Peripheral::i2c5); } - static constexpr inline bool is_adc(Instance instance) { - return is_one_of(instance, Instance::adc1, Instance::adc2, Instance::adc3); + static constexpr inline bool is_adc(Peripheral instance) { + return is_one_of(instance, Peripheral::adc1, Peripheral::adc2, Peripheral::adc3); } - static constexpr inline bool is_fmac(Instance instance) { - return instance == Instance::fmac; + static constexpr inline bool is_fmac(Peripheral instance) { + return instance == Peripheral::fmac; } - static constexpr inline bool is_none(Instance instance){ - return instance == Instance::none; + static constexpr inline bool is_none(Peripheral instance){ + return instance == Peripheral::none; } - static consteval inline uint32_t get_Request(Instance instance, uint8_t i) { - if (instance == Instance::none) return DMA_REQUEST_MEM2MEM; - - if (instance == Instance::adc1) return DMA_REQUEST_ADC1; - if (instance == Instance::adc2) return DMA_REQUEST_ADC2; - if (instance == Instance::adc3) return DMA_REQUEST_ADC3; - - if (instance == Instance::i2c1 && i == 0) return DMA_REQUEST_I2C1_RX; - if (instance == Instance::i2c1 && i == 1) return DMA_REQUEST_I2C1_TX; - if (instance == Instance::i2c2 && i == 0) return DMA_REQUEST_I2C2_RX; - if (instance == Instance::i2c2 && i == 1) return DMA_REQUEST_I2C2_TX; - if (instance == Instance::i2c3 && i == 0) return DMA_REQUEST_I2C3_RX; - if (instance == Instance::i2c3 && i == 1) return DMA_REQUEST_I2C3_TX; - if (instance == Instance::i2c5 && i == 0) return DMA_REQUEST_I2C5_RX; - if (instance == Instance::i2c5 && i == 1) return DMA_REQUEST_I2C5_TX; - - if (instance == Instance::spi1 && i == 0) return DMA_REQUEST_SPI1_RX; - if (instance == Instance::spi1 && i == 1) return DMA_REQUEST_SPI1_TX; - if (instance == Instance::spi2 && i == 0) return DMA_REQUEST_SPI2_RX; - if (instance == Instance::spi2 && i == 1) return DMA_REQUEST_SPI2_TX; - if (instance == Instance::spi3 && i == 0) return DMA_REQUEST_SPI3_RX; - if (instance == Instance::spi3 && i == 1) return DMA_REQUEST_SPI3_TX; - if (instance == Instance::spi4 && i == 0) return DMA_REQUEST_SPI4_RX; - if (instance == Instance::spi4 && i == 1) return DMA_REQUEST_SPI4_TX; - if (instance == Instance::spi5 && i == 0) return DMA_REQUEST_SPI5_RX; - if (instance == Instance::spi5 && i == 1) return DMA_REQUEST_SPI5_TX; + static consteval inline uint32_t get_Request(Peripheral instance, uint8_t i) { + if (instance == Peripheral::none) return DMA_REQUEST_MEM2MEM; + + if (instance == Peripheral::adc1) return DMA_REQUEST_ADC1; + if (instance == Peripheral::adc2) return DMA_REQUEST_ADC2; + if (instance == Peripheral::adc3) return DMA_REQUEST_ADC3; + + if (instance == Peripheral::i2c1 && i == 0) return DMA_REQUEST_I2C1_RX; + if (instance == Peripheral::i2c1 && i == 1) return DMA_REQUEST_I2C1_TX; + if (instance == Peripheral::i2c2 && i == 0) return DMA_REQUEST_I2C2_RX; + if (instance == Peripheral::i2c2 && i == 1) return DMA_REQUEST_I2C2_TX; + if (instance == Peripheral::i2c3 && i == 0) return DMA_REQUEST_I2C3_RX; + if (instance == Peripheral::i2c3 && i == 1) return DMA_REQUEST_I2C3_TX; + if (instance == Peripheral::i2c5 && i == 0) return DMA_REQUEST_I2C5_RX; + if (instance == Peripheral::i2c5 && i == 1) return DMA_REQUEST_I2C5_TX; + + if (instance == Peripheral::spi1 && i == 0) return DMA_REQUEST_SPI1_RX; + if (instance == Peripheral::spi1 && i == 1) return DMA_REQUEST_SPI1_TX; + if (instance == Peripheral::spi2 && i == 0) return DMA_REQUEST_SPI2_RX; + if (instance == Peripheral::spi2 && i == 1) return DMA_REQUEST_SPI2_TX; + if (instance == Peripheral::spi3 && i == 0) return DMA_REQUEST_SPI3_RX; + if (instance == Peripheral::spi3 && i == 1) return DMA_REQUEST_SPI3_TX; + if (instance == Peripheral::spi4 && i == 0) return DMA_REQUEST_SPI4_RX; + if (instance == Peripheral::spi4 && i == 1) return DMA_REQUEST_SPI4_TX; + if (instance == Peripheral::spi5 && i == 0) return DMA_REQUEST_SPI5_RX; + if (instance == Peripheral::spi5 && i == 1) return DMA_REQUEST_SPI5_TX; - if (instance == Instance::fmac && i == 0) return DMA_REQUEST_MEM2MEM; - if (instance == Instance::fmac && i == 1) return DMA_REQUEST_FMAC_WRITE; - if (instance == Instance::fmac && i == 2) return DMA_REQUEST_FMAC_READ; + if (instance == Peripheral::fmac && i == 0) return DMA_REQUEST_MEM2MEM; + if (instance == Peripheral::fmac && i == 1) return DMA_REQUEST_FMAC_WRITE; + if (instance == Peripheral::fmac && i == 2) return DMA_REQUEST_FMAC_READ; compile_error("Invalid DMA request configuration"); return 0; } - static consteval inline uint32_t get_Direction(Instance instance, uint8_t i) { - if ((is_fmac(instance) && i == 0) || instance == Instance::none) { + static consteval inline uint32_t get_Direction(Peripheral instance, uint8_t i) { + if ((is_fmac(instance) && i == 0) || instance == Peripheral::none) { return DMA_MEMORY_TO_MEMORY; } else if ((is_i2c(instance) && i == 1) || @@ -202,21 +202,21 @@ namespace ST_LIB { return DMA_PERIPH_TO_MEMORY; } - static consteval inline uint32_t get_PeriphInc(Instance instance, uint8_t i) { + static consteval inline uint32_t get_PeriphInc(Peripheral instance, uint8_t i) { if ((is_fmac(instance) && i == 0) || is_none(instance)){ return DMA_PINC_ENABLE; } return DMA_PINC_DISABLE; } - static consteval inline uint32_t get_MemInc(Instance instance, uint8_t i) { + static consteval inline uint32_t get_MemInc(Peripheral instance, uint8_t i) { if (is_fmac(instance) && i == 0){ return DMA_MINC_DISABLE; } return DMA_MINC_ENABLE; } - static consteval inline uint32_t get_PeriphDataAlignment(Instance instance, uint8_t i) { + static consteval inline uint32_t get_PeriphDataAlignment(Peripheral instance, uint8_t i) { if (is_spi(instance) || is_i2c(instance)){ return DMA_PDATAALIGN_BYTE; } @@ -226,7 +226,7 @@ namespace ST_LIB { return DMA_PDATAALIGN_HALFWORD; } - static consteval inline uint32_t get_MemDataAlignment(Instance instance, uint8_t i) { + static consteval inline uint32_t get_MemDataAlignment(Peripheral instance, uint8_t i) { if (is_i2c(instance)){ return DMA_MDATAALIGN_WORD; } @@ -237,7 +237,7 @@ namespace ST_LIB { return DMA_MDATAALIGN_HALFWORD; } - static consteval inline uint32_t get_Mode(Instance instance, uint8_t i) { + static consteval inline uint32_t get_Mode(Peripheral instance, uint8_t i) { if (is_spi(instance) || is_fmac(instance) || is_none(instance)){ return DMA_NORMAL; } @@ -245,7 +245,7 @@ namespace ST_LIB { return DMA_CIRCULAR; } - static consteval inline uint32_t get_Priority(Instance instance, uint8_t i) { + static consteval inline uint32_t get_Priority(Peripheral instance, uint8_t i) { if (is_fmac(instance)){ return DMA_PRIORITY_HIGH; } @@ -253,30 +253,30 @@ namespace ST_LIB { return DMA_PRIORITY_LOW; } - static consteval inline uint32_t get_FIFOMode(Instance instance, uint8_t i) { + static consteval inline uint32_t get_FIFOMode(Peripheral instance, uint8_t i) { if (is_fmac(instance)){ return DMA_FIFOMODE_ENABLE; } return DMA_FIFOMODE_DISABLE; } - static consteval inline uint32_t get_FIFOThreshold(Instance instance, uint8_t i) { + static consteval inline uint32_t get_FIFOThreshold(Peripheral instance, uint8_t i) { if (is_spi(instance)){ return DMA_FIFO_THRESHOLD_FULL; } return DMA_FIFO_THRESHOLD_HALFFULL; } - static consteval inline uint32_t get_MemBurst(Instance instance, uint8_t i) { + static consteval inline uint32_t get_MemBurst(Peripheral instance, uint8_t i) { return DMA_MBURST_SINGLE; } - static consteval inline uint32_t get_PeriphBurst(Instance instance, uint8_t i) { + static consteval inline uint32_t get_PeriphBurst(Peripheral instance, uint8_t i) { return DMA_PBURST_SINGLE; } struct Config { - std::tuple Date: Sat, 31 Jan 2026 20:46:51 +0100 Subject: [PATCH 098/109] build.yml --- .github/workflows/build.yml | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 974e7ff1b..1e8fc4869 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -53,14 +53,4 @@ jobs: run: | cmake --preset ${{ inputs.preset }} cmake --build --preset ${{ inputs.preset }} - shell: bash - - - name: Upload Build - id: upload-build-artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ inputs.preset }} - path: out/build/${{ inputs.preset }}/libst-lib.a - retention-days: 7 - compression-level: 0 - if-no-files-found: error \ No newline at end of file + shell: bash \ No newline at end of file From f2615f0203e76288304c5eb6ef47f731c62450d2 Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Mon, 2 Feb 2026 12:37:51 +0100 Subject: [PATCH 099/109] fix(ST-LIB): Missing comma (#556) --- Inc/ST-LIB.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Inc/ST-LIB.hpp b/Inc/ST-LIB.hpp index 6ec9ef0f3..0bf1d7499 100644 --- a/Inc/ST-LIB.hpp +++ b/Inc/ST-LIB.hpp @@ -140,7 +140,7 @@ template struct Board { .dma_cfgs = DMA_Domain::template build( ctx.template span()), .mdma_packet_cfgs = MdmaPacketDomain::template build( - ctx.template span()) + ctx.template span()), .sd_cfgs = SdDomain::template build( ctx.template span()), // ... From 9356b3aedfe9944956b757546a61d53b05dfd7c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20L=C3=B3pez?= <120128034+victor-Lopez25@users.noreply.github.com> Date: Mon, 2 Feb 2026 12:56:24 +0100 Subject: [PATCH 100/109] Feat/new dual pwm (#555) * PWM rework, now in HALAL/Services/PWM (not in pwm/pwm) * Add DualPWM implementation, deadtime might be wrong? * both timerpins must be pwm pins * fix timer_wrapper_test (hopefully) * fix stuff found wrong in pwm.hpp when making dualpwm.hpp * fix deadtime calculation * fix: Max pins per timer is 7 --- Inc/HALAL/HALAL.hpp | 3 + Inc/HALAL/Models/TimerDomain/TimerDomain.hpp | 235 +++++++++------- Inc/HALAL/Services/PWM/DualPWM.hpp | 273 +++++++++++++++++++ Inc/HALAL/Services/PWM/PWM.hpp | 164 +++++++++++ Inc/HALAL/Services/PWM/PWM/NewPWM.hpp | 221 --------------- Inc/HALAL/Services/Time/TimerWrapper.hpp | 239 ++++++++++------ Tests/Time/timer_wrapper_test.cpp | 14 +- 7 files changed, 730 insertions(+), 419 deletions(-) create mode 100644 Inc/HALAL/Services/PWM/DualPWM.hpp create mode 100644 Inc/HALAL/Services/PWM/PWM.hpp delete mode 100644 Inc/HALAL/Services/PWM/PWM/NewPWM.hpp diff --git a/Inc/HALAL/HALAL.hpp b/Inc/HALAL/HALAL.hpp index 35cc4b043..efff5dece 100644 --- a/Inc/HALAL/HALAL.hpp +++ b/Inc/HALAL/HALAL.hpp @@ -21,6 +21,9 @@ #include "HALAL/Services/PWM/PhasedPWM/PhasedPWM.hpp" #include "HALAL/Services/PWM/DualPhasedPWM/DualPhasedPWM.hpp" +#include "HALAL/Services/PWM/PWM.hpp" +#include "HALAL/Services/PWM/DualPWM.hpp" + #include "HALAL/Services/Time/TimerWrapper.hpp" #include "HALAL/Services/Time/Scheduler.hpp" #include "HALAL/Services/Time/RTC.hpp" diff --git a/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp b/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp index cf39d686e..551d019a1 100644 --- a/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp +++ b/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp @@ -146,6 +146,12 @@ enum class TimerChannel : uint8_t { CHANNEL_4 = 4, CHANNEL_5 = 5, CHANNEL_6 = 6, + + CHANNEL_NEGATED_FLAG = 8, + + CHANNEL_1_NEGATED = 1 | CHANNEL_NEGATED_FLAG, + CHANNEL_2_NEGATED = 2 | CHANNEL_NEGATED_FLAG, + CHANNEL_3_NEGATED = 3 | CHANNEL_NEGATED_FLAG, }; struct TimerPin { @@ -187,25 +193,11 @@ struct TimerDomain { // There are 16 timers static constexpr std::size_t max_instances = 16; - enum CountingMode : uint8_t { - UP = 0, - DOWN = 1, - /* center-aligned = counter counts up and down alternatively */ - /* Output compare interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are - set only when the counter is counting down */ - CENTER_ALIGNED_INTERRUPT_DOWN = 2, - /* Output compare interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are - set only when the counter is counting up */ - CENTER_ALIGNED_INTERRUPT_UP = 3, - /* both up and down */ - CENTER_ALIGNED_INTERRUPT_BOTH = 4, - }; - struct Entry { std::array name; /* max length = 7 */ TimerRequest request; uint8_t pin_count; - std::array pins; /* this won't be read in Timer constructor */ + std::array pins; /* this won't be read in Timer constructor */ }; struct Config { @@ -279,6 +271,9 @@ struct TimerDomain { GPIODomain::GPIO gpio1; GPIODomain::GPIO gpio2; GPIODomain::GPIO gpio3; + GPIODomain::GPIO gpio4; + GPIODomain::GPIO gpio5; + GPIODomain::GPIO gpio6; static consteval GPIODomain::AlternateFunction get_gpio_af(ST_LIB::TimerRequest req, ST_LIB::TimerPin pin); @@ -342,32 +337,46 @@ struct TimerDomain { template consteval Timer(TimerRequest request = TimerRequest::AnyGeneralPurpose, std::array name = EMPTY_TIMER_NAME, T... pinargs) : - e(name, request, sizeof...(pinargs), std::array({GetPinFromIdx(pinargs, 0), GetPinFromIdx(pinargs, 1), GetPinFromIdx(pinargs, 2), GetPinFromIdx(pinargs, 3)})), + e(name, request, sizeof...(pinargs), + std::array( + {GetPinFromIdx(pinargs, 0), GetPinFromIdx(pinargs, 1), GetPinFromIdx(pinargs, 2), + GetPinFromIdx(pinargs, 3), GetPinFromIdx(pinargs, 4), GetPinFromIdx(pinargs, 5), + GetPinFromIdx(pinargs, 6)})), gpio0(GetGPIOFromIdx(pinargs, request, 0)), gpio1(GetGPIOFromIdx(pinargs, request, 1)), gpio2(GetGPIOFromIdx(pinargs, request, 2)), - gpio3(GetGPIOFromIdx(pinargs, request, 3)) + gpio3(GetGPIOFromIdx(pinargs, request, 3)), + gpio4(GetGPIOFromIdx(pinargs, request, 4)), + gpio5(GetGPIOFromIdx(pinargs, request, 5)), + gpio6(GetGPIOFromIdx(pinargs, request, 6)) { static_assert((std::is_same_v && ...), "All template arguments must be of type TimerPin"); - if(sizeof...(pinargs) > 4) { - ST_LIB::compile_error("Max 4 pins per timer"); + if(sizeof...(pinargs) > 7) { + ST_LIB::compile_error("Max 7 pins per timer"); } } // anything uninitialized will be 0 template consteval Timer(Entry ent, T... pinargs) : - e(ent.name, ent.request, sizeof...(pinargs), std::array({GetPinFromIdx(pinargs, 0), GetPinFromIdx(pinargs, 1), GetPinFromIdx(pinargs, 2), GetPinFromIdx(pinargs, 3)})), + e(ent.name, ent.request, sizeof...(pinargs), + std::array( + {GetPinFromIdx(pinargs, 0), GetPinFromIdx(pinargs, 1), GetPinFromIdx(pinargs, 2), + GetPinFromIdx(pinargs, 3), GetPinFromIdx(pinargs, 4), GetPinFromIdx(pinargs, 5), + GetPinFromIdx(pinargs, 6)})), gpio0(GetGPIOFromIdx(pinargs, ent.request, 0)), gpio1(GetGPIOFromIdx(pinargs, ent.request, 1)), gpio2(GetGPIOFromIdx(pinargs, ent.request, 2)), - gpio3(GetGPIOFromIdx(pinargs, ent.request, 3)) + gpio3(GetGPIOFromIdx(pinargs, ent.request, 3)), + gpio4(GetGPIOFromIdx(pinargs, ent.request, 4)), + gpio5(GetGPIOFromIdx(pinargs, ent.request, 5)), + gpio6(GetGPIOFromIdx(pinargs, ent.request, 6)) { static_assert((std::is_same_v && ...), "All template arguments must be of type TimerPin"); - if(sizeof...(pinargs) > 4) { - ST_LIB::compile_error("Max 4 pins per timer"); + if(sizeof...(pinargs) > 7) { + ST_LIB::compile_error("Max 7 pins per timer"); } } @@ -377,6 +386,9 @@ struct TimerDomain { if(e.pin_count > 1) { gpio1.inscribe(ctx); } if(e.pin_count > 2) { gpio2.inscribe(ctx); } if(e.pin_count > 3) { gpio3.inscribe(ctx); } + if(e.pin_count > 4) { gpio4.inscribe(ctx); } + if(e.pin_count > 5) { gpio5.inscribe(ctx); } + if(e.pin_count > 6) { gpio6.inscribe(ctx); } TimerDomain::Entry local_entry = { .name = e.name, @@ -580,6 +592,14 @@ TimerDomain::Timer::get_gpio_af(ST_LIB::TimerRequest req, ST_LIB::TimerPin pin) Channel_2 = 2, Channel_3 = 3, Channel_4 = 4, + + NegatedChannelFlag = 8, + + Channel_1_Negated = 1 | NegatedChannelFlag, + Channel_2_Negated = 2 | NegatedChannelFlag, + Channel_3_Negated = 3 | NegatedChannelFlag, + Channel_4_Negated = 4 | NegatedChannelFlag, + ExternalTriggerFilter, /* ETR */ BreakInput_1, BreakInput_2, @@ -596,45 +616,45 @@ TimerDomain::Timer::get_gpio_af(ST_LIB::TimerRequest req, ST_LIB::TimerPin pin) // 4 capture-compare channels // complementary output #define Tim1PinsMacro \ - {ST_LIB::PE6, ST_LIB::GPIODomain::AlternateFunction::AF1, BreakInput_2}, \ - {ST_LIB::PE6, ST_LIB::GPIODomain::AlternateFunction::AF12, BreakInputCompare_2}, \ + {ST_LIB::PE6, ST_LIB::GPIODomain::AlternateFunction::AF1, BreakInput_2}, \ + {ST_LIB::PE6, ST_LIB::GPIODomain::AlternateFunction::AF12, BreakInputCompare_2}, \ \ - {ST_LIB::PA6, ST_LIB::GPIODomain::AlternateFunction::AF1, BreakInput_1}, \ - {ST_LIB::PA6, ST_LIB::GPIODomain::AlternateFunction::AF11, BreakInputCompare_1}, \ + {ST_LIB::PA6, ST_LIB::GPIODomain::AlternateFunction::AF1, BreakInput_1}, \ + {ST_LIB::PA6, ST_LIB::GPIODomain::AlternateFunction::AF11, BreakInputCompare_1}, \ \ - {ST_LIB::PA7, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, /* negated */ \ - {ST_LIB::PB0, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_2}, /* negated */ \ - {ST_LIB::PB1, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_3}, /* negated */ \ - {ST_LIB::PE7, ST_LIB::GPIODomain::AlternateFunction::AF1, ExternalTriggerFilter}, \ - {ST_LIB::PE8, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, /* negated */ \ - {ST_LIB::PE9, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, \ - {ST_LIB::PE10, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_2}, /* negated */\ - {ST_LIB::PE11, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_2}, \ - {ST_LIB::PE12, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_3}, /* negated */\ - {ST_LIB::PE13, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_3}, \ - {ST_LIB::PE14, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_4}, \ + {ST_LIB::PA7, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1_Negated}, \ + {ST_LIB::PB0, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_2_Negated}, \ + {ST_LIB::PB1, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_3_Negated}, \ + {ST_LIB::PE7, ST_LIB::GPIODomain::AlternateFunction::AF1, ExternalTriggerFilter}, \ + {ST_LIB::PE8, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1_Negated}, \ + {ST_LIB::PE9, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, \ + {ST_LIB::PE10, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_2_Negated}, \ + {ST_LIB::PE11, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_2}, \ + {ST_LIB::PE12, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_3_Negated}, \ + {ST_LIB::PE13, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_3}, \ + {ST_LIB::PE14, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_4}, \ \ - {ST_LIB::PE15, ST_LIB::GPIODomain::AlternateFunction::AF1, BreakInput_1}, \ - {ST_LIB::PE15, ST_LIB::GPIODomain::AlternateFunction::AF13, BreakInputCompare_1}, \ + {ST_LIB::PE15, ST_LIB::GPIODomain::AlternateFunction::AF1, BreakInput_1}, \ + {ST_LIB::PE15, ST_LIB::GPIODomain::AlternateFunction::AF13, BreakInputCompare_1}, \ \ - {ST_LIB::PB12, ST_LIB::GPIODomain::AlternateFunction::AF1, BreakInput_1}, \ - {ST_LIB::PB12, ST_LIB::GPIODomain::AlternateFunction::AF13, BreakInputCompare_1}, \ + {ST_LIB::PB12, ST_LIB::GPIODomain::AlternateFunction::AF1, BreakInput_1}, \ + {ST_LIB::PB12, ST_LIB::GPIODomain::AlternateFunction::AF13, BreakInputCompare_1}, \ \ - {ST_LIB::PB13, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, /* negated */\ - {ST_LIB::PB14, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_2}, /* negated */\ - {ST_LIB::PB15, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_3}, /* negated */\ + {ST_LIB::PB13, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1_Negated}, \ + {ST_LIB::PB14, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_2_Negated}, \ + {ST_LIB::PB15, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_3_Negated}, \ \ - {ST_LIB::PG4, ST_LIB::GPIODomain::AlternateFunction::AF1, BreakInput_2}, \ - {ST_LIB::PG4, ST_LIB::GPIODomain::AlternateFunction::AF11, BreakInputCompare_2}, \ + {ST_LIB::PG4, ST_LIB::GPIODomain::AlternateFunction::AF1, BreakInput_2}, \ + {ST_LIB::PG4, ST_LIB::GPIODomain::AlternateFunction::AF11, BreakInputCompare_2}, \ \ - {ST_LIB::PG5, ST_LIB::GPIODomain::AlternateFunction::AF1, ExternalTriggerFilter}, \ + {ST_LIB::PG5, ST_LIB::GPIODomain::AlternateFunction::AF1, ExternalTriggerFilter}, \ \ - {ST_LIB::PA8, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, \ - {ST_LIB::PA9, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_2}, \ - {ST_LIB::PA10, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_3}, \ - {ST_LIB::PA11, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_4}, \ + {ST_LIB::PA8, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, \ + {ST_LIB::PA9, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_2}, \ + {ST_LIB::PA10, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_3}, \ + {ST_LIB::PA11, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_4}, \ \ - {ST_LIB::PA12, ST_LIB::GPIODomain::AlternateFunction::AF1, ExternalTriggerFilter}, \ + {ST_LIB::PA12, ST_LIB::GPIODomain::AlternateFunction::AF1, ExternalTriggerFilter},\ {ST_LIB::PA12, ST_LIB::GPIODomain::AlternateFunction::AF12, BreakInput_2}, // 4 capture-compare channels @@ -644,10 +664,10 @@ TimerDomain::Timer::get_gpio_af(ST_LIB::TimerRequest req, ST_LIB::TimerPin pin) {ST_LIB::PA1, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_2}, \ {ST_LIB::PA2, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_3}, \ {ST_LIB::PA3, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_4}, \ - \ + \ {ST_LIB::PA5, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, \ {ST_LIB::PA5, ST_LIB::GPIODomain::AlternateFunction::AF1, ExternalTriggerFilter}, \ - \ + \ {ST_LIB::PA15, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, \ {ST_LIB::PA15, ST_LIB::GPIODomain::AlternateFunction::AF1, ExternalTriggerFilter}, \ {ST_LIB::PB3, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_2}, \ @@ -660,15 +680,15 @@ TimerDomain::Timer::get_gpio_af(ST_LIB::TimerRequest req, ST_LIB::TimerPin pin) {ST_LIB::PA7, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_2}, \ {ST_LIB::PB0, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_3}, \ {ST_LIB::PB1, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_4}, \ - \ + \ {ST_LIB::PB4, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_1}, \ {ST_LIB::PB5, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_2}, \ - \ + \ {ST_LIB::PC6, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_1}, \ {ST_LIB::PC7, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_2}, \ {ST_LIB::PC8, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_3}, \ {ST_LIB::PC9, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_4}, \ - \ + \ {ST_LIB::PD2, ST_LIB::GPIODomain::AlternateFunction::AF2, ExternalTriggerFilter}, // 4 capture-compare channels @@ -677,12 +697,12 @@ TimerDomain::Timer::get_gpio_af(ST_LIB::TimerRequest req, ST_LIB::TimerPin pin) {ST_LIB::PB7, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_2}, \ {ST_LIB::PB8, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_3}, \ {ST_LIB::PB9, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_4}, \ - \ + \ {ST_LIB::PD12, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_1}, \ {ST_LIB::PD13, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_2}, \ {ST_LIB::PD14, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_3}, \ {ST_LIB::PD15, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_4}, \ - \ + \ {ST_LIB::PE0, ST_LIB::GPIODomain::AlternateFunction::AF2, ExternalTriggerFilter}, // 4 capture-compare channels @@ -701,32 +721,32 @@ TimerDomain::Timer::get_gpio_af(ST_LIB::TimerRequest req, ST_LIB::TimerPin pin) // 4 capture-compare channels // complementary output #define Tim8PinsMacro \ - {ST_LIB::PA0, ST_LIB::GPIODomain::AlternateFunction::AF3, ExternalTriggerFilter}, \ - {ST_LIB::PA5, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_1}, /* negated */ \ + {ST_LIB::PA0, ST_LIB::GPIODomain::AlternateFunction::AF3, ExternalTriggerFilter}, \ + {ST_LIB::PA5, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_1_Negated}, \ \ - {ST_LIB::PA6, ST_LIB::GPIODomain::AlternateFunction::AF3, BreakInput_1}, \ - {ST_LIB::PA6, ST_LIB::GPIODomain::AlternateFunction::AF10, BreakInputCompare_1}, \ + {ST_LIB::PA6, ST_LIB::GPIODomain::AlternateFunction::AF3, BreakInput_1}, \ + {ST_LIB::PA6, ST_LIB::GPIODomain::AlternateFunction::AF10, BreakInputCompare_1}, \ \ - {ST_LIB::PA7, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_1}, /* negated */ \ + {ST_LIB::PA7, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_1_Negated}, \ \ - {ST_LIB::PA8, ST_LIB::GPIODomain::AlternateFunction::AF3, BreakInput_2}, \ - {ST_LIB::PA8, ST_LIB::GPIODomain::AlternateFunction::AF12, BreakInputCompare_2}, \ + {ST_LIB::PA8, ST_LIB::GPIODomain::AlternateFunction::AF3, BreakInput_2}, \ + {ST_LIB::PA8, ST_LIB::GPIODomain::AlternateFunction::AF12, BreakInputCompare_2}, \ \ - {ST_LIB::PB0, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_2}, /* negated */ \ - {ST_LIB::PB1, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_3}, /* negated */ \ - {ST_LIB::PB14, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_2}, /* negated */\ - {ST_LIB::PB15, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_3}, /* negated */\ + {ST_LIB::PB0, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_2_Negated}, \ + {ST_LIB::PB1, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_3_Negated}, \ + {ST_LIB::PB14, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_2_Negated}, \ + {ST_LIB::PB15, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_3_Negated}, \ \ - {ST_LIB::PC6, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_1}, \ - {ST_LIB::PC7, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_2}, \ - {ST_LIB::PC8, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_3}, \ - {ST_LIB::PC9, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_4}, \ + {ST_LIB::PC6, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_1}, \ + {ST_LIB::PC7, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_2}, \ + {ST_LIB::PC8, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_3}, \ + {ST_LIB::PC9, ST_LIB::GPIODomain::AlternateFunction::AF3, Channel_4}, \ \ - {ST_LIB::PG2, ST_LIB::GPIODomain::AlternateFunction::AF3, BreakInput_1}, \ - {ST_LIB::PG2, ST_LIB::GPIODomain::AlternateFunction::AF11, BreakInputCompare_1}, \ + {ST_LIB::PG2, ST_LIB::GPIODomain::AlternateFunction::AF3, BreakInput_1}, \ + {ST_LIB::PG2, ST_LIB::GPIODomain::AlternateFunction::AF11, BreakInputCompare_1}, \ \ - {ST_LIB::PG3, ST_LIB::GPIODomain::AlternateFunction::AF3, BreakInput_2}, \ - {ST_LIB::PG3, ST_LIB::GPIODomain::AlternateFunction::AF11, BreakInputCompare_2}, \ + {ST_LIB::PG3, ST_LIB::GPIODomain::AlternateFunction::AF3, BreakInput_2}, \ + {ST_LIB::PG3, ST_LIB::GPIODomain::AlternateFunction::AF11, BreakInputCompare_2}, \ \ {ST_LIB::PG8, ST_LIB::GPIODomain::AlternateFunction::AF3, ExternalTriggerFilter}, @@ -747,34 +767,34 @@ TimerDomain::Timer::get_gpio_af(ST_LIB::TimerRequest req, ST_LIB::TimerPin pin) // 2 capture-compare channels #define Tim15PinsMacro \ - {ST_LIB::PA0, ST_LIB::GPIODomain::AlternateFunction::AF4, BreakInput_1}, \ - \ - {ST_LIB::PA1, ST_LIB::GPIODomain::AlternateFunction::AF4, Channel_1}, /* negated */ \ - {ST_LIB::PA2, ST_LIB::GPIODomain::AlternateFunction::AF4, Channel_1}, \ - {ST_LIB::PA3, ST_LIB::GPIODomain::AlternateFunction::AF4, Channel_2}, \ - \ - {ST_LIB::PC12, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_1}, \ - {ST_LIB::PD2, ST_LIB::GPIODomain::AlternateFunction::AF4, Channel_2}, \ - \ - {ST_LIB::PE3, ST_LIB::GPIODomain::AlternateFunction::AF4, BreakInput_1}, \ - {ST_LIB::PE4, ST_LIB::GPIODomain::AlternateFunction::AF4, BreakInput_1}, \ - \ - {ST_LIB::PE4, ST_LIB::GPIODomain::AlternateFunction::AF4, Channel_1}, \ + {ST_LIB::PA0, ST_LIB::GPIODomain::AlternateFunction::AF4, BreakInput_1}, \ + \ + {ST_LIB::PA1, ST_LIB::GPIODomain::AlternateFunction::AF4, Channel_1_Negated}, \ + {ST_LIB::PA2, ST_LIB::GPIODomain::AlternateFunction::AF4, Channel_1}, \ + {ST_LIB::PA3, ST_LIB::GPIODomain::AlternateFunction::AF4, Channel_2}, \ + \ + {ST_LIB::PC12, ST_LIB::GPIODomain::AlternateFunction::AF2, Channel_1}, \ + {ST_LIB::PD2, ST_LIB::GPIODomain::AlternateFunction::AF4, Channel_2}, \ + \ + {ST_LIB::PE3, ST_LIB::GPIODomain::AlternateFunction::AF4, BreakInput_1}, \ + {ST_LIB::PE4, ST_LIB::GPIODomain::AlternateFunction::AF4, BreakInput_1}, \ + \ + {ST_LIB::PE4, ST_LIB::GPIODomain::AlternateFunction::AF4, Channel_1}, \ {ST_LIB::PE4, ST_LIB::GPIODomain::AlternateFunction::AF4, Channel_2}, // 1 capture-compare channel #define Tim16PinsMacro \ - {ST_LIB::PF6, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, \ - {ST_LIB::PF8, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, /* negated */ \ + {ST_LIB::PF6, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, \ + {ST_LIB::PF8, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1_Negated}, \ {ST_LIB::PF10, ST_LIB::GPIODomain::AlternateFunction::AF1, BreakInput_1}, // 1 capture-compare channel #define Tim17PinsMacro \ - {ST_LIB::PB5, ST_LIB::GPIODomain::AlternateFunction::AF1, BreakInput_1}, \ - {ST_LIB::PB7, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, /* negated */ \ - {ST_LIB::PB9, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, \ - {ST_LIB::PF7, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, \ - {ST_LIB::PF9, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, /* negated */ \ + {ST_LIB::PB5, ST_LIB::GPIODomain::AlternateFunction::AF1, BreakInput_1}, \ + {ST_LIB::PB7, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1_Negated}, \ + {ST_LIB::PB9, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, \ + {ST_LIB::PF7, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1}, \ + {ST_LIB::PF9, ST_LIB::GPIODomain::AlternateFunction::AF1, Channel_1_Negated}, \ {ST_LIB::PG6, ST_LIB::GPIODomain::AlternateFunction::AF1, BreakInput_1}, // 4 capture-compare channels @@ -784,12 +804,12 @@ TimerDomain::Timer::get_gpio_af(ST_LIB::TimerRequest req, ST_LIB::TimerPin pin) {ST_LIB::PF1, ST_LIB::GPIODomain::AlternateFunction::AF13, Channel_2}, \ {ST_LIB::PF2, ST_LIB::GPIODomain::AlternateFunction::AF13, Channel_3}, \ {ST_LIB::PF3, ST_LIB::GPIODomain::AlternateFunction::AF13, Channel_4}, \ - \ + \ {ST_LIB::PF6, ST_LIB::GPIODomain::AlternateFunction::AF13, Channel_1}, \ {ST_LIB::PF7, ST_LIB::GPIODomain::AlternateFunction::AF13, Channel_2}, \ {ST_LIB::PF8, ST_LIB::GPIODomain::AlternateFunction::AF13, Channel_3}, \ {ST_LIB::PF9, ST_LIB::GPIODomain::AlternateFunction::AF13, Channel_4}, \ - \ + \ {ST_LIB::PG3, ST_LIB::GPIODomain::AlternateFunction::AF13, ExternalTriggerFilter}, \ {ST_LIB::PG12, ST_LIB::GPIODomain::AlternateFunction::AF13, Channel_1}, \ {ST_LIB::PG13, ST_LIB::GPIODomain::AlternateFunction::AF13, Channel_2}, \ @@ -850,15 +870,20 @@ TimerDomain::Timer::get_gpio_af(ST_LIB::TimerRequest req, ST_LIB::TimerPin pin) {{Tim24PinsMacro}, tim24pin_count}, /* TIM24 */ }; - if(req == TimerRequest::AnyGeneralPurpose || - req == TimerRequest::Any32bit) + if(req == TimerRequest::AnyGeneralPurpose || req == TimerRequest::Any32bit) { ST_LIB::compile_error("Any* timers can't use pins"); + return GPIODomain::AlternateFunction::NO_AF; } - if(req == TimerRequest::Basic_6 || - req == TimerRequest::Basic_7) + if(req == TimerRequest::Basic_6 || req == TimerRequest::Basic_7) { ST_LIB::compile_error("Basic timers can't use pins"); + return GPIODomain::AlternateFunction::NO_AF; + } + + if(pin.channel == TimerChannel::CHANNEL_NEGATED_FLAG) { + ST_LIB::compile_error("You're not supporsed to use TimerChannel::CHANNEL_NEGATED_FLAG as a channel nº"); + return GPIODomain::AlternateFunction::NO_AF; } bool found = false; diff --git a/Inc/HALAL/Services/PWM/DualPWM.hpp b/Inc/HALAL/Services/PWM/DualPWM.hpp new file mode 100644 index 000000000..6ced7d3f2 --- /dev/null +++ b/Inc/HALAL/Services/PWM/DualPWM.hpp @@ -0,0 +1,273 @@ +/* + * NewPWM.hpp + * + * Created on: Jan 31, 2026 + * Author: victor + */ +#pragma once + +#include "HALAL/Models/TimerDomain/TimerDomain.hpp" +#ifdef HAL_TIM_MODULE_ENABLED +#include "HALAL/Models/GPIO.hpp" + +namespace ST_LIB { + +template +struct TimerWrapper; + +template +class DualPWM { + static consteval uint8_t get_channel_state_idx(const ST_LIB::TimerChannel ch) { + switch(ch) { + case TimerChannel::CHANNEL_1: case TimerChannel::CHANNEL_1_NEGATED: + case TimerChannel::CHANNEL_2: case TimerChannel::CHANNEL_2_NEGATED: + case TimerChannel::CHANNEL_3: case TimerChannel::CHANNEL_3_NEGATED: + case TimerChannel::CHANNEL_4: + case TimerChannel::CHANNEL_5: + case TimerChannel::CHANNEL_6: + return (static_cast(ch) & + ~static_cast(TimerChannel::CHANNEL_NEGATED_FLAG)) - 1; + + default: ST_LIB::compile_error("unreachable"); + return 0; + } + } + + static consteval uint8_t get_channel_mul4(const ST_LIB::TimerChannel ch) { + switch(ch) { + case TimerChannel::CHANNEL_1: case TimerChannel::CHANNEL_1_NEGATED: return 0x00; + case TimerChannel::CHANNEL_2: case TimerChannel::CHANNEL_2_NEGATED: return 0x04; + case TimerChannel::CHANNEL_3: case TimerChannel::CHANNEL_3_NEGATED: return 0x08; + case TimerChannel::CHANNEL_4: return 0x0C; + case TimerChannel::CHANNEL_5: return 0x10; + case TimerChannel::CHANNEL_6: return 0x14; + + default: ST_LIB::compile_error("unreachable"); + return 0; + } + } + + TimerWrapper *timer; + uint32_t frequency; + float duty_cycle = 0; + bool is_on_positive = false; + bool is_on_negative = false; + bool is_center_aligned; + +public: + DualPWM(TimerWrapper *tim, uint32_t polarity, uint32_t negated_polarity) : timer(tim) { + this->is_center_aligned = ((timer->instance->tim->CR1 & TIM_CR1_CMS) != 0); + + TIM_OC_InitTypeDef sConfigOC = { + .OCMode = TIM_OCMODE_PWM1, + .Pulse = 0, + + .OCPolarity = polarity, + .OCNPolarity = negated_polarity, + + .OCFastMode = TIM_OCFAST_DISABLE, + .OCIdleState = TIM_OCIDLESTATE_RESET, + .OCNIdleState = TIM_OCNIDLESTATE_RESET, + }; + + timer->template config_output_compare_channel(&sConfigOC); + timer->template set_output_compare_preload_enable(); + } + + void turn_on() { + turn_on_positive(); + turn_on_negative(); + } + + void turn_off() { + turn_off_positive(); + turn_off_negative(); + } + + void turn_on_positive() { + if(this->is_on_positive) return; + + //if(HAL_TIM_PWM_Start(timer->instance->hal_tim, channel) != HAL_OK) { ErrorHandler("", 0); } + volatile HAL_TIM_ChannelStateTypeDef *state = &timer->instance->hal_tim->ChannelState[get_channel_state_idx(pin.channel)]; + if(*state != HAL_TIM_CHANNEL_STATE_READY) { + ErrorHandler("Channel not ready"); + } + + *state = HAL_TIM_CHANNEL_STATE_BUSY; + // enable CCx + uint32_t enableCCx = TIM_CCER_CC1E << (get_channel_mul4(pin.channel) & 0x1FU); /* 0x1FU = 31 bits max shift */ + SET_BIT(timer->instance->tim->CCER, enableCCx); + + if constexpr(timer->is_break_instance) { + // Main Output Enable + SET_BIT(timer->instance->tim->BDTR, TIM_BDTR_MOE); + } + + if constexpr(timer->is_slave_instance) { + uint32_t tmpsmcr = timer->instance->tim->SMCR & TIM_SMCR_SMS; + if(!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr)) { + timer->counter_enable(); + } + } else { + timer->counter_enable(); + } + + this->is_on_positive = true; + } + + void turn_on_negative() { + if(this->is_on_negative) return; + + //if(HAL_TIM_PWM_Start(timer->instance->hal_tim, channel) != HAL_OK) { ErrorHandler("", 0); } + volatile HAL_TIM_ChannelStateTypeDef *state = &timer->instance->hal_tim->ChannelNState[get_channel_state_idx(negated_pin.channel)]; + if(*state != HAL_TIM_CHANNEL_STATE_READY) { + ErrorHandler("Channel not ready"); + } + + *state = HAL_TIM_CHANNEL_STATE_BUSY; + // enable CCNx + uint32_t enableCCNx = TIM_CCER_CC1NE << (get_channel_mul4(negated_pin.channel) & 0x1FU); /* 0x1FU = 31 bits max shift */ + SET_BIT(timer->instance->tim->CCER, enableCCNx); + + if constexpr(timer->is_break_instance) { + // Main Output Enable + SET_BIT(timer->instance->tim->BDTR, TIM_BDTR_MOE); + } + + if constexpr(timer->is_slave_instance) { + uint32_t tmpsmcr = timer->instance->tim->SMCR & TIM_SMCR_SMS; + if(!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr)) { + timer->counter_enable(); + } + } else { + timer->counter_enable(); + } + + this->is_on_negative = true; + } + + void turn_off_positive() { + if(!this->is_on_positive) return; + + CLEAR_BIT(timer->tim->CCER, (uint32_t)(TIM_CCER_CC1E << (get_channel_mul4(pin.channel) & 0x1FU))); + + HAL_TIM_ChannelStateTypeDef *state = &timer->instance->hal_tim.ChannelState[get_channel_state_idx(pin.channel)]; + *state = HAL_TIM_CHANNEL_STATE_READY; + + if(timer->are_all_channels_free()) { + if constexpr(timer->is_break_instance) { + // Disable Main Output Enable (MOE) + CLEAR_BIT(timer->tim->BDTR, TIM_BDTR_MOE); + } + timer->counter_disable(); + } + + this->is_on_positive = false; + } + + void turn_off_negative() { + if(!this->is_on_negative) return; + + CLEAR_BIT(timer->tim->CCER, (uint32_t)(TIM_CCER_CC1NE << (get_channel_mul4(negated_pin.channel) & 0x1FU))); + + HAL_TIM_ChannelStateTypeDef *state = &timer->instance->hal_tim.ChannelState[get_channel_state_idx(negated_pin.channel)]; + *state = HAL_TIM_CHANNEL_STATE_READY; + + if(timer->are_all_channels_free()) { + if constexpr(timer->is_break_instance) { + // Disable Main Output Enable (MOE) + CLEAR_BIT(timer->tim->BDTR, TIM_BDTR_MOE); + } + timer->counter_disable(); + } + + this->is_on_negative = false; + } + + void set_duty_cycle(float duty_cycle) { + uint16_t raw_duty = (uint16_t)((float)(timer->instance->tim->ARR + 1) / 100.0f * duty_cycle); + timer->template set_capture_compare(raw_duty); + this->duty_cycle = duty_cycle; + } + + void set_timer_frequency_quick(uint32_t frequency) { + if(is_center_aligned) { + frequency = 2*frequency; + } + this->frequency = frequency; + timer->instance->tim->ARR = (timer->get_clock_frequency() / (timer->instance->tim->PSC + 1)) / frequency; + + set_duty_cycle(duty_cycle); + } + + void set_timer_frequency(uint32_t frequency) { + if(is_center_aligned) { + frequency = 2*frequency; + } + this->frequency = frequency; + + /* a = timer clock frequency + * b = (psc + 1) * frequency + * arr = (a - b/2) / b + */ + float psc_plus_1_mul_freq = (float)(timer->instance->tim->PSC + 1) * (float)frequency; + timer->instance->tim->ARR = (uint32_t)((float)timer->get_clock_frequency() / psc_plus_1_mul_freq - 0.5f); + + set_duty_cycle(duty_cycle); + } + + void configure(uint32_t frequency, float duty_cycle, int64_t dead_time_ns) { + this->duty_cycle = duty_cycle; + this->set_timer_frequency(frequency); + this->set_dead_time(dead_time_ns); + } + + uint32_t get_frequency() const { + return this->frequency; + } + float get_duty_cycle() const { + return this->duty_cycle; + } + + void set_dead_time(int64_t dead_time_ns) { + TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; + + int64_t time = dead_time_ns; + + float clock_period_ns = 1000'000'000.0f / (float)timer->get_clock_frequency(); + if(time <= 127 * clock_period_ns) { + /* range 1: DTG[7] = 0; DTG[6:0] = [0..127]) */ + sBreakDeadTimeConfig.DeadTime = time / clock_period_ns; + } else if(time <= (2 * clock_period_ns * 127)) { + /* range 2: DTG[7:6] = 0b10; DTG[5:0] = 2*(64 + [0..63]) */ + sBreakDeadTimeConfig.DeadTime = + 0b1000'0000 | (uint32_t)((float)time / (2 * clock_period_ns) - 64); + } else if(time <= (8 * clock_period_ns * 63)) { + /* range 3: DTG[7:5] = 0b110; DTG[4:0] = 8*(32 + [0..31]) */ + int64_t min = (8 * clock_period_ns * 32); + if(time < min) { time = min; } + sBreakDeadTimeConfig.DeadTime = + 0b1100'0000 | (uint32_t)((float)time / (8 * clock_period_ns) - 32); + } else if(time <= (16 * clock_period_ns * 63)) { + /* range 4: DTG[7:5] = 0b111; DTG[4:0] = 16*(32 + [0..31]) */ + int64_t min = (16 * clock_period_ns * 32); + if(time < min) { time = min; } + sBreakDeadTimeConfig.DeadTime = + 0b1110'0000 | (uint32_t)((float)time / (16 * clock_period_ns) - 32); + } else { + ErrorHandler("Invalid dead time configuration"); + } + + //sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; + //sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE; + HAL_TIMEx_ConfigBreakDeadTime(timer->instance->hal_tim, &sBreakDeadTimeConfig); + + if constexpr(timer->is_break_instance) { + // Main Output Enable + SET_BIT(timer->instance->tim->BDTR, TIM_BDTR_MOE); + } + } +}; +} // namespace ST_LIB + +#endif // HAL_TIM_MODULE_ENABLED diff --git a/Inc/HALAL/Services/PWM/PWM.hpp b/Inc/HALAL/Services/PWM/PWM.hpp new file mode 100644 index 000000000..7c7da3e32 --- /dev/null +++ b/Inc/HALAL/Services/PWM/PWM.hpp @@ -0,0 +1,164 @@ +/* + * NewPWM.hpp + * + * Created on: Dec 30, 2025 + * Author: victor + */ +#pragma once + +#include "HALAL/Models/TimerDomain/TimerDomain.hpp" +#ifdef HAL_TIM_MODULE_ENABLED +#include "HALAL/Models/GPIO.hpp" + +namespace ST_LIB { + +template +struct TimerWrapper; + +template +class PWM { + static consteval uint8_t get_channel_state_idx(const ST_LIB::TimerChannel ch) { + switch(ch) { + case TimerChannel::CHANNEL_1: case TimerChannel::CHANNEL_1_NEGATED: + case TimerChannel::CHANNEL_2: case TimerChannel::CHANNEL_2_NEGATED: + case TimerChannel::CHANNEL_3: case TimerChannel::CHANNEL_3_NEGATED: + case TimerChannel::CHANNEL_4: + case TimerChannel::CHANNEL_5: + case TimerChannel::CHANNEL_6: + return (static_cast(ch) & + static_cast(TimerChannel::CHANNEL_NEGATED_FLAG)) - 1; + + default: ST_LIB::compile_error("unreachable"); + return 0; + } + } + + static consteval uint8_t get_channel_mul4(const ST_LIB::TimerChannel ch) { + switch(ch) { + case TimerChannel::CHANNEL_1: case TimerChannel::CHANNEL_1_NEGATED: return 0x00; + case TimerChannel::CHANNEL_2: case TimerChannel::CHANNEL_2_NEGATED: return 0x04; + case TimerChannel::CHANNEL_3: case TimerChannel::CHANNEL_3_NEGATED: return 0x08; + case TimerChannel::CHANNEL_4: return 0x0C; + case TimerChannel::CHANNEL_5: return 0x10; + case TimerChannel::CHANNEL_6: return 0x14; + + default: ST_LIB::compile_error("unreachable"); + return 0; + } + } + + TimerWrapper *timer; + uint32_t frequency; + float duty_cycle = 0; + bool is_on = false; + bool is_center_aligned; + +public: + PWM(TimerWrapper *tim, uint32_t polarity, uint32_t negated_polarity) : timer(tim) { + this->is_center_aligned = ((timer->instance->tim->CR1 & TIM_CR1_CMS) != 0); + + TIM_OC_InitTypeDef sConfigOC = { + .OCMode = TIM_OCMODE_PWM1, + .Pulse = 0, + + .OCPolarity = polarity, + .OCNPolarity = negated_polarity, + + .OCFastMode = TIM_OCFAST_DISABLE, + .OCIdleState = TIM_OCIDLESTATE_RESET, + .OCNIdleState = TIM_OCNIDLESTATE_RESET, + }; + timer->template config_output_compare_channel(&sConfigOC); + timer->template set_output_compare_preload_enable(); + } + + void turn_on() { + if(this->is_on) return; + + //if(HAL_TIM_PWM_Start(timer->instance->hal_tim, channel) != HAL_OK) { ErrorHandler("", 0); } + volatile HAL_TIM_ChannelStateTypeDef *state = &timer->instance->hal_tim->ChannelState[get_channel_state_idx(pin.channel)]; + if(*state != HAL_TIM_CHANNEL_STATE_READY) { + ErrorHandler("Channel not ready"); + } + + *state = HAL_TIM_CHANNEL_STATE_BUSY; + // enable CCx + uint32_t enableCCx = TIM_CCER_CC1E << (get_channel_mul4(pin.channel) & 0x1FU); /* 0x1FU = 31 bits max shift */ + SET_BIT(timer->instance->tim->CCER, enableCCx); + + if constexpr(timer->is_break_instance) { + // Main Output Enable + SET_BIT(timer->instance->tim->BDTR, TIM_BDTR_MOE); + } + + if constexpr(timer->is_slave_instance) { + uint32_t tmpsmcr = timer->instance->tim->SMCR & TIM_SMCR_SMS; + if(!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr)) { + timer->counter_enable(); + } + } else { + timer->counter_enable(); + } + + this->is_on = true; + } + + void turn_off() { + if(!this->is_on) return; + + CLEAR_BIT(timer->tim->CCER, (uint32_t)(TIM_CCER_CC1E << (get_channel_mul4(pin.channel) & 0x1FU))); + + HAL_TIM_ChannelStateTypeDef *state = &timer->instance->hal_tim.ChannelState[get_channel_state_idx(pin.channel)]; + *state = HAL_TIM_CHANNEL_STATE_READY; + + if(timer->are_all_channels_free()) { + if constexpr(timer->is_break_instance) { + // Disable Main Output Enable (MOE) + CLEAR_BIT(timer->tim->BDTR, TIM_BDTR_MOE); + } + timer->counter_disable(); + } + + this->is_on = false; + } + + void set_duty_cycle(float duty_cycle) { + uint16_t raw_duty = (uint16_t)((float)(timer->instance->tim->ARR + 1) / 100.0f * duty_cycle); + timer->template set_capture_compare(raw_duty); + this->duty_cycle = duty_cycle; + } + + void set_timer_frequency_quick(uint32_t frequency) { + if(is_center_aligned) { + frequency = 2*frequency; + } + this->frequency = frequency; + timer->instance->tim->ARR = (timer->get_clock_frequency() / (timer->instance->tim->PSC + 1)) / frequency; + + set_duty_cycle(duty_cycle); + } + + void set_timer_frequency(uint32_t frequency) { + if(is_center_aligned) { + frequency = 2*frequency; + } + this->frequency = frequency; + + /* a = timer clock frequency + * b = (psc + 1) * frequency + * arr = (a - b/2) / b + */ + float psc_plus_1_mul_freq = (float)(timer->instance->tim->PSC + 1) * (float)frequency; + timer->instance->tim->ARR = (uint32_t)((float)timer->get_clock_frequency() / psc_plus_1_mul_freq - 0.5f); + + set_duty_cycle(duty_cycle); + } + + void configure(uint32_t frequency, float duty_cycle) { + this->duty_cycle = duty_cycle; + this->set_timer_frequency(frequency); + } +}; +} // namespace ST_LIB + +#endif // HAL_TIM_MODULE_ENABLED diff --git a/Inc/HALAL/Services/PWM/PWM/NewPWM.hpp b/Inc/HALAL/Services/PWM/PWM/NewPWM.hpp deleted file mode 100644 index 7a358b960..000000000 --- a/Inc/HALAL/Services/PWM/PWM/NewPWM.hpp +++ /dev/null @@ -1,221 +0,0 @@ -/* - * NewPWM.hpp - * - * Created on: Dec 30, 2025 - * Author: victor - */ -#pragma once - -#ifdef HAL_TIM_MODULE_ENABLED -#include "HALAL/Models/TimerDomain/TimerDomain.hpp" -#include "HALAL/Models/GPIO.hpp" - -namespace ST_LIB { - -template -struct TimerWrapper; - -template -class PWM { - static consteval uint8_t get_channel_state_idx(const ST_LIB::TimerChannel ch) { - switch(ch) { - case TimerChannel::CHANNEL_1: - case TimerChannel::CHANNEL_2: - case TimerChannel::CHANNEL_3: - case TimerChannel::CHANNEL_4: - case TimerChannel::CHANNEL_5: - case TimerChannel::CHANNEL_6: - return static_cast(ch) - 1; - - default: ST_LIB::compile_error("unreachable"); - return 0; - } - } - - static consteval uint8_t get_channel_mul4(const ST_LIB::TimerChannel ch) { - switch(ch) { - case TimerChannel::CHANNEL_1: return 0x00; - case TimerChannel::CHANNEL_2: return 0x04; - case TimerChannel::CHANNEL_3: return 0x08; - case TimerChannel::CHANNEL_4: return 0x0C; - case TimerChannel::CHANNEL_5: return 0x10; - case TimerChannel::CHANNEL_6: return 0x14; - - default: ST_LIB::compile_error("unreachable"); - return 0; - } - } - - TimerWrapper *timer; - uint32_t frequency; - float duty_cycle; - bool is_on = false; - bool is_center_aligned; - -public: - PWM(TimerWrapper *tim, uint32_t polarity, uint32_t negated_polarity) : timer(tim) { - this->is_center_aligned = ((timer->instance.tim->CR1 & TIM_CR1_CMS) != 0); - - TIM_OC_InitTypeDef sConfigOC = { - .OCMode = TIM_OCMODE_PWM1, - .Pulse = 0, - - .OCPolarity = polarity, - .OCNPolarity = negated_polarity, - - .OCFastMode = TIM_OCFAST_DISABLE, - .OCIdleState = TIM_OCIDLESTATE_RESET, - .OCNIdleState = TIM_OCNIDLESTATE_RESET, - }; - timer->template config_output_compare_channel(&sConfigOC); - timer->template set_output_compare_preload_enable(); - } - - void turn_on() { - if(this->is_on) return; - - //if(HAL_TIM_PWM_Start(timer->instance.hal_tim, channel) != HAL_OK) { ErrorHandler("", 0); } - volatile HAL_TIM_ChannelStateTypeDef *state = &timer->instance.hal_tim->ChannelState[get_channel_state_idx(pin.channel)]; - if(*state != HAL_TIM_CHANNEL_STATE_READY) { - ErrorHandler("Channel not ready"); - } - - *state = HAL_TIM_CHANNEL_STATE_BUSY; - // enable CCx - uint32_t enableCCx = TIM_CCER_CC1E << (get_channel_mul4(pin.channel) & 0x1FU); /* 0x1FU = 31 bits max shift */ - SET_BIT(timer->instance.tim->CCER, enableCCx); - - if constexpr(timer->is_break_instance) { - // Main Output Enable - SET_BIT(timer->instance.tim->BDTR, TIM_BDTR_MOE); - } - - if constexpr(timer->is_slave_instance) { - uint32_t tmpsmcr = timer->instance.tim->SMCR & TIM_SMCR_SMS; - if(!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr)) { - timer->counter_enable(); - } - } else { - timer->counter_enable(); - } - - if constexpr(pin.channel == ST_LIB::TimerChannel::CHANNEL_1) { - SET_BIT(timer->instance.tim->CCER, TIM_CCER_CC1E); - } else if constexpr(pin.channel == ST_LIB::TimerChannel::CHANNEL_2) { - SET_BIT(timer->instance.tim->CCER, TIM_CCER_CC2E); - } else if constexpr(pin.channel == ST_LIB::TimerChannel::CHANNEL_3) { - SET_BIT(timer->instance.tim->CCER, TIM_CCER_CC3E); - } else if constexpr(pin.channel == ST_LIB::TimerChannel::CHANNEL_4) { - SET_BIT(timer->instance.tim->CCER, TIM_CCER_CC4E); - } else if constexpr(pin.channel == ST_LIB::TimerChannel::CHANNEL_5) { - SET_BIT(timer->instance.tim->CCER, TIM_CCER_CC5E); - } else if constexpr(pin.channel == ST_LIB::TimerChannel::CHANNEL_6) { - SET_BIT(timer->instance.tim->CCER, TIM_CCER_CC6E); - } - - this->is_on = true; - } - - void turn_off() { - if(!this->is_on) return; - // if(HAL_TIM_PWM_Stop(timer->instance.hal_tim, channel) != HAL_OK) { ErrorHandler("", 0); } - - SET_BIT(timer->tim->CCER, (uint32_t)(TIM_CCx_DISABLE << (get_channel_mul4(pin.channel) & 0x1FU))); - - if constexpr(timer->is_break_instance) { - // Disable Main Output Enable (MOE) - CLEAR_BIT(timer->tim->BDTR, TIM_BDTR_MOE); - } - - HAL_TIM_ChannelStateTypeDef *state = &timer->instance.hal_tim.ChannelState[get_channel_state_idx(pin.channel)]; - *state = HAL_TIM_CHANNEL_STATE_READY; - - if(timer->instance.hal_tim->ChannelState[0] == HAL_TIM_CHANNEL_STATE_READY && - timer->instance.hal_tim->ChannelState[1] == HAL_TIM_CHANNEL_STATE_READY && - timer->instance.hal_tim->ChannelState[2] == HAL_TIM_CHANNEL_STATE_READY && - timer->instance.hal_tim->ChannelState[3] == HAL_TIM_CHANNEL_STATE_READY && - timer->instance.hal_tim->ChannelState[4] == HAL_TIM_CHANNEL_STATE_READY && - timer->instance.hal_tim->ChannelState[5] == HAL_TIM_CHANNEL_STATE_READY) - { - timer->counter_disable(); - } - - this->is_on = false; - } - - void set_duty_cycle(float duty_cycle) { - uint16_t raw_duty = (uint16_t)((float)(timer->instance.tim->ARR + 1) / 100.0f * duty_cycle); - timer->template set_capture_compare(raw_duty); - this->duty_cycle = duty_cycle; - } - - void set_frequency_quick(uint32_t frequency) { - if(is_center_aligned) { - frequency = 2*frequency; - } - this->frequency = frequency; - timer->instance.tim->ARR = (timer->get_clock_frequency() / (timer->instance.tim->PSC + 1)) / frequency; - - set_duty_cycle(duty_cycle); - } - - void set_frequency(uint32_t frequency) { - if(is_center_aligned) { - frequency = 2*frequency; - } - this->frequency = frequency; - - /* a = timer clock frequency - * b = (psc + 1) * frequency - * arr = (a - b/2) / b - */ - float psc_plus_1_mul_freq = (float)(timer->instance.tim->PSC + 1) * (float)frequency; - timer->instance.tim->ARR = (uint32_t)((float)timer->get_clock_frequency() / psc_plus_1_mul_freq - 0.5f); - - set_duty_cycle(duty_cycle); - } - - void configure(uint32_t frequency, float duty_cycle) { - this->duty_cycle = duty_cycle; - set_frequency(frequency); - } - - void set_dead_time(int64_t dead_time_ns) { - TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; - - int64_t time = dead_time_ns; - - float clock_period_ns = 1000.0f / (float)timer->get_clock_frequency(); - if(time <= 127 * clock_period_ns) { - sBreakDeadTimeConfig.DeadTime = time / clock_period_ns; - } else if(time <= (2 * clock_period_ns * 127)) { - sBreakDeadTimeConfig.DeadTime = time / (2 * clock_period_ns) - 64 + 128; - } else if(time <= (8 * clock_period_ns * 127)) { - sBreakDeadTimeConfig.DeadTime = time / (8 * clock_period_ns) -32 + 192; - } else if(time <= (16 * clock_period_ns * 127)) { - sBreakDeadTimeConfig.DeadTime = time / (16 * clock_period_ns) -32 + 224; - } else { - ErrorHandler("Invalid dead time configuration"); - } - - sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; - sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; - sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; - sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE; - sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; - sBreakDeadTimeConfig.BreakFilter = 0; - sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE; - sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH; - sBreakDeadTimeConfig.Break2Filter = 0; - sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; - HAL_TIMEx_ConfigBreakDeadTime(timer->instance.hal_tim, &sBreakDeadTimeConfig); - - if constexpr(timer->is_break_instance) { - // Main Output Enable - SET_BIT(timer->tim->BDTR, TIM_BDTR_MOE); - } - } -}; -} // namespace ST_LIB - -#endif // HAL_TIM_MODULE_ENABLED diff --git a/Inc/HALAL/Services/Time/TimerWrapper.hpp b/Inc/HALAL/Services/Time/TimerWrapper.hpp index 05e1b2f97..0a8721b62 100644 --- a/Inc/HALAL/Services/Time/TimerWrapper.hpp +++ b/Inc/HALAL/Services/Time/TimerWrapper.hpp @@ -16,20 +16,36 @@ #ifdef HAL_TIM_MODULE_ENABLED #include "HALAL/Models/TimerDomain/TimerDomain.hpp" -#include "HALAL/Services/PWM/PWM/NewPWM.hpp" +#include "HALAL/Services/PWM/DualPWM.hpp" +#include "HALAL/Services/PWM/PWM.hpp" #include "HALAL/Models/GPIO.hpp" #include "ErrorHandler/ErrorHandler.hpp" #define get_timer_instance(board, timer_type) \ - ST_LIB::TimerWrapper(board::instance_of()) + ST_LIB::TimerWrapper(&board::instance_of()) namespace ST_LIB { template struct TimerWrapper { - TimerDomain::Instance& instance; - TimerWrapper(TimerDomain::Instance& inst) : instance(inst) {} + TimerDomain::Instance *instance = nullptr; + TimerWrapper() = default; + TimerWrapper(TimerDomain::Instance *inst) : instance(inst) {} + + enum CountingMode : uint8_t { + UP = 0, + DOWN = 1, + /* center-aligned = counter counts up and down alternatively */ + /* Output compare interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are + set only when the counter is counting down */ + CENTER_ALIGNED_INTERRUPT_DOWN = 2, + /* Output compare interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are + set only when the counter is counting up */ + CENTER_ALIGNED_INTERRUPT_UP = 3, + /* both up and down */ + CENTER_ALIGNED_INTERRUPT_BOTH = 4, + }; static constexpr bool is_32bit_instance = ( dev.e.request == TimerRequest::GeneralPurpose32bit_2 || @@ -85,14 +101,14 @@ struct TimerWrapper { switch(dev.e.request) { case TimerRequest::Advanced_1: case TimerRequest::Advanced_8: - return (ch == TimerChannel::CHANNEL_1) || - (ch == TimerChannel::CHANNEL_2) || - (ch == TimerChannel::CHANNEL_3); + return (ch == TimerChannel::CHANNEL_1) || (ch == TimerChannel::CHANNEL_1_NEGATED) || + (ch == TimerChannel::CHANNEL_2) || (ch == TimerChannel::CHANNEL_2_NEGATED) || + (ch == TimerChannel::CHANNEL_3) || (ch == TimerChannel::CHANNEL_3_NEGATED); case TimerRequest::GeneralPurpose_15: case TimerRequest::GeneralPurpose_16: case TimerRequest::GeneralPurpose_17: - return ch == TimerChannel::CHANNEL_1; + return (ch == TimerChannel::CHANNEL_1) || (ch == TimerChannel::CHANNEL_1_NEGATED); default: return false; @@ -139,43 +155,82 @@ struct TimerWrapper { ST_LIB::compile_error("Pin must be configured in TimerDomain as a PWM"); } return PWM(this, polarity, negated_polarity); - } else if constexpr(dev.e.pin_count == 4 && + } else if constexpr(dev.e.pin_count > 3 && dev.e.pins[3].pin == pin.pin && dev.e.pins[3].channel == pin.channel) { if constexpr(dev.e.pins[3].af != TimerAF::PWM) { ST_LIB::compile_error("Pin must be configured in TimerDomain as a PWM"); } return PWM(this, polarity, negated_polarity); + } else if constexpr(dev.e.pin_count > 4 && + dev.e.pins[4].pin == pin.pin && dev.e.pins[4].channel == pin.channel) + { + if constexpr(dev.e.pins[4].af != TimerAF::PWM) { + ST_LIB::compile_error("Pin must be configured in TimerDomain as a PWM"); + } + return PWM(this, polarity, negated_polarity); + } else if constexpr(dev.e.pin_count > 5 && + dev.e.pins[5].pin == pin.pin && dev.e.pins[5].channel == pin.channel) + { + if constexpr(dev.e.pins[5].af != TimerAF::PWM) { + ST_LIB::compile_error("Pin must be configured in TimerDomain as a PWM"); + } + return PWM(this, polarity, negated_polarity); + } else if constexpr(dev.e.pin_count > 6 && + dev.e.pins[6].pin == pin.pin && dev.e.pins[6].channel == pin.channel) + { + if constexpr(dev.e.pins[6].af != TimerAF::PWM) { + ST_LIB::compile_error("Pin must be configured in TimerDomain as a PWM"); + } + return PWM(this, polarity, negated_polarity); + } else if constexpr(dev.e.pin_count == 7 && + dev.e.pins[7].pin == pin.pin && dev.e.pins[7].channel == pin.channel) + { + if constexpr(dev.e.pins[7].af != TimerAF::PWM) { + ST_LIB::compile_error("Pin must be configured in TimerDomain as a PWM"); + } + return PWM(this, polarity, negated_polarity); } else { ST_LIB::compile_error("No pins passed to TimerWrapper are the same as the pins passed to get_pwm() [this method]"); } } + template + inline DualPWM get_dual_pwm(uint32_t polarity = TIM_OCPOLARITY_HIGH, uint32_t negated_polarity = TIM_OCNPOLARITY_HIGH) + { + static_assert(dev.e.pin_count > 1, "Need at least two pins on one timer to get a dual pwm"); + + // NOTE: No voy a comprobar todo esto, no hará falta comprobarlo con la siguiente versión del pwm, dualpwm + static_assert((static_cast(pin.channel) | static_cast(TimerChannel::CHANNEL_NEGATED_FLAG)) == static_cast(negated_pin.channel)); + static_assert(pin.af == TimerAF::PWM && negated_pin.af == TimerAF::PWM); + return DualPWM(this, polarity, negated_polarity); + } + inline void counter_enable() { - SET_BIT(instance.tim->CR1, TIM_CR1_CEN); + SET_BIT(instance->tim->CR1, TIM_CR1_CEN); } inline void counter_disable() { - CLEAR_BIT(instance.tim->CR1, TIM_CR1_CEN); + CLEAR_BIT(instance->tim->CR1, TIM_CR1_CEN); } inline void clear_update_interrupt_flag() { - CLEAR_BIT(instance.tim->SR, TIM_SR_UIF); + CLEAR_BIT(instance->tim->SR, TIM_SR_UIF); } /* Disabled by default */ inline void enable_update_interrupt() { - SET_BIT(instance.tim->DIER, TIM_DIER_UIE); + SET_BIT(instance->tim->DIER, TIM_DIER_UIE); } inline void disable_update_interrupt() { - CLEAR_BIT(instance.tim->DIER, TIM_DIER_UIE); + CLEAR_BIT(instance->tim->DIER, TIM_DIER_UIE); } /* Disabled by default */ inline void enable_nvic() { - NVIC_EnableIRQ(TimerDomain::timer_irqn[instance.timer_idx]); + NVIC_EnableIRQ(TimerDomain::timer_irqn[instance->timer_idx]); } inline void disable_nvic() { - NVIC_DisableIRQ(TimerDomain::timer_irqn[instance.timer_idx]); + NVIC_DisableIRQ(TimerDomain::timer_irqn[instance->timer_idx]); } /* Enable UEV. The Update (UEV) event is generated by one of the following events: @@ -185,84 +240,84 @@ struct TimerWrapper { * Enabled by default */ inline void enable_update_event() { - CLEAR_BIT(instance.tim->CR1, TIM_CR1_UDIS); + CLEAR_BIT(instance->tim->CR1, TIM_CR1_UDIS); } /* Disable UEV. The Update event is not generated, shadow registers keep their value * (ARR, PSC, CCRx). However the counter and the prescaler are reinitialized if the UG bit * is set or if a hardware reset is received from the slave mode controller. */ inline void disable_update_event() { - SET_BIT(instance.tim->CR1, TIM_CR1_UDIS); + SET_BIT(instance->tim->CR1, TIM_CR1_UDIS); } /* default: disabled */ inline void break_interrupt_enable() { static_assert(dev.e.request == TimerRequest::Advanced_1 || dev.e.request == TimerRequest::Advanced_8, "Error: Break interrupt enable only allowed in advanced timers {TIM1, TIM8}"); - SET_BIT(instance.tim->DIER, TIM_DIER_BIE); + SET_BIT(instance->tim->DIER, TIM_DIER_BIE); } inline void break_interrupt_disable() { static_assert(dev.e.request == TimerRequest::Advanced_1 || dev.e.request == TimerRequest::Advanced_8, "Error: Break interrupt enable only allowed in advanced timers {TIM1, TIM8}"); - CLEAR_BIT(instance.tim->DIER, TIM_DIER_BIE); + CLEAR_BIT(instance->tim->DIER, TIM_DIER_BIE); } /* interrupt gets called only once, counter needs to be reenabled */ inline void set_one_pulse_mode() { - SET_BIT(instance.tim->CR1, TIM_CR1_OPM); + SET_BIT(instance->tim->CR1, TIM_CR1_OPM); } inline void set_multi_interrupt_mode() { - CLEAR_BIT(instance.tim->CR1, TIM_CR1_OPM); + CLEAR_BIT(instance->tim->CR1, TIM_CR1_OPM); } inline TIM_HandleTypeDef *get_hal_handle() { - return instance.hal_tim; + return instance->hal_tim; } inline TIM_TypeDef *get_cmsis_handle() { - return instance.tim; + return instance->tim; } inline void set_prescaler(uint16_t psc) { - instance.tim->PSC = psc; + instance->tim->PSC = psc; } inline void configure32bit(void (*callback)(void*), void *callback_data, uint32_t period) { static_assert(this->is_32bit_instance, "Only timers {TIM2, TIM5, TIM23, TIM24} have a 32-bit resolution"); - instance.tim->ARR = period; - TimerDomain::callbacks[instance.timer_idx] = callback; - TimerDomain::callback_data[instance.timer_idx] = callback_data; + instance->tim->ARR = period; + TimerDomain::callbacks[instance->timer_idx] = callback; + TimerDomain::callback_data[instance->timer_idx] = callback_data; this->counter_enable(); } inline void configure16bit(void (*callback)(void*), void *callback_data, uint16_t period) { - instance.tim->ARR = period; - TimerDomain::callbacks[instance.timer_idx] = callback; - TimerDomain::callback_data[instance.timer_idx] = callback_data; + instance->tim->ARR = period; + TimerDomain::callbacks[instance->timer_idx] = callback; + TimerDomain::callback_data[instance->timer_idx] = callback_data; this->counter_enable(); } /* WARNING: The counter _must_ be disabled to switch from edge-aligned to center-aligned mode */ - template + template inline void set_counting_mode(void) { constexpr uint8_t reqint = static_cast(dev.e.request); static_assert(!this->only_supports_upcounting, "Error: In request reqidx: Timers other than {Advanced{TIM1, TIM8}, TIM2, TIM3, TIM4, TIM5, TIM23, TIM24} only support upcounting"); - if constexpr (mode == TimerDomain::CountingMode::UP) { - MODIFY_REG(instance.tim->CR1, TIM_CR1_CMS, 0); - CLEAR_BIT(instance.tim->CR1, TIM_CR1_DIR); // upcounter - } else if constexpr (mode == TimerDomain::CountingMode::DOWN) { - MODIFY_REG(instance.tim->CR1, TIM_CR1_CMS, 0); - SET_BIT(instance.tim->CR1, TIM_CR1_DIR); // downcounter - } else if constexpr (mode == TimerDomain::CountingMode::CENTER_ALIGNED_INTERRUPT_DOWN) { - MODIFY_REG(instance.tim->CR1, TIM_CR1_CMS, TIM_CR1_CMS_0); - } else if constexpr (mode == TimerDomain::CountingMode::CENTER_ALIGNED_INTERRUPT_UP) { - MODIFY_REG(instance.tim->CR1, TIM_CR1_CMS, TIM_CR1_CMS_1); - } else if constexpr (mode == TimerDomain::CountingMode::CENTER_ALIGNED_INTERRUPT_BOTH) { - MODIFY_REG(instance.tim->CR1, TIM_CR1_CMS, (TIM_CR1_CMS_0 | TIM_CR1_CMS_1)); + if constexpr (mode == CountingMode::UP) { + MODIFY_REG(instance->tim->CR1, TIM_CR1_CMS, 0); + CLEAR_BIT(instance->tim->CR1, TIM_CR1_DIR); // upcounter + } else if constexpr (mode == CountingMode::DOWN) { + MODIFY_REG(instance->tim->CR1, TIM_CR1_CMS, 0); + SET_BIT(instance->tim->CR1, TIM_CR1_DIR); // downcounter + } else if constexpr (mode == CountingMode::CENTER_ALIGNED_INTERRUPT_DOWN) { + MODIFY_REG(instance->tim->CR1, TIM_CR1_CMS, TIM_CR1_CMS_0); + } else if constexpr (mode == CountingMode::CENTER_ALIGNED_INTERRUPT_UP) { + MODIFY_REG(instance->tim->CR1, TIM_CR1_CMS, TIM_CR1_CMS_1); + } else if constexpr (mode == CountingMode::CENTER_ALIGNED_INTERRUPT_BOTH) { + MODIFY_REG(instance->tim->CR1, TIM_CR1_CMS, (TIM_CR1_CMS_0 | TIM_CR1_CMS_1)); } } @@ -271,24 +326,31 @@ struct TimerWrapper { template inline void config_output_compare_channel(const TIM_OC_InitTypeDef *OC_Config) { + if constexpr(!((ch == TimerChannel::CHANNEL_1) || (ch == TimerChannel::CHANNEL_2) || + (ch == TimerChannel::CHANNEL_3) || (ch == TimerChannel::CHANNEL_4) || + (ch == TimerChannel::CHANNEL_5) || (ch == TimerChannel::CHANNEL_6))) + { + ST_LIB::compile_error("config_output_compare_channel should only be called with channels [1..6] (not negated)"); + } + uint32_t tmpccmrx; uint32_t tmpccer; uint32_t tmpcr2; - tmpccer = instance.tim->CCER; + tmpccer = instance->tim->CCER; - tmpcr2 = instance.tim->CR2; + tmpcr2 = instance->tim->CR2; if constexpr(ch == TimerChannel::CHANNEL_1 || ch == TimerChannel::CHANNEL_2) { - tmpccmrx = instance.tim->CCMR1; + tmpccmrx = instance->tim->CCMR1; } else if constexpr(ch == TimerChannel::CHANNEL_3 || ch == TimerChannel::CHANNEL_4) { - tmpccmrx = instance.tim->CCMR2; + tmpccmrx = instance->tim->CCMR2; } else if constexpr(ch == TimerChannel::CHANNEL_5 || ch == TimerChannel::CHANNEL_6) { - tmpccmrx = instance.tim->CCMR3; + tmpccmrx = instance->tim->CCMR3; } if constexpr(ch == TimerChannel::CHANNEL_1) { - CLEAR_BIT(instance.tim->CCER, TIM_CCER_CC1E); + CLEAR_BIT(instance->tim->CCER, TIM_CCER_CC1E); CLEAR_BIT(tmpccmrx, TIM_CCMR1_OC1M); CLEAR_BIT(tmpccmrx, TIM_CCMR1_CC1S); @@ -297,7 +359,7 @@ struct TimerWrapper { CLEAR_BIT(tmpccer, TIM_CCER_CC1P); SET_BIT(tmpccer, OC_Config->OCPolarity); } else if constexpr(ch == TimerChannel::CHANNEL_2) { - CLEAR_BIT(instance.tim->CCER, TIM_CCER_CC2E); + CLEAR_BIT(instance->tim->CCER, TIM_CCER_CC2E); CLEAR_BIT(tmpccmrx, TIM_CCMR1_OC2M); CLEAR_BIT(tmpccmrx, TIM_CCMR1_CC2S); @@ -306,7 +368,7 @@ struct TimerWrapper { CLEAR_BIT(tmpccer, TIM_CCER_CC2P); SET_BIT(tmpccer, OC_Config->OCPolarity << 4U); } else if constexpr(ch == TimerChannel::CHANNEL_3) { - CLEAR_BIT(instance.tim->CCER, TIM_CCER_CC3E); + CLEAR_BIT(instance->tim->CCER, TIM_CCER_CC3E); CLEAR_BIT(tmpccmrx, TIM_CCMR2_OC3M); CLEAR_BIT(tmpccmrx, TIM_CCMR2_CC3S); @@ -315,7 +377,7 @@ struct TimerWrapper { CLEAR_BIT(tmpccer, TIM_CCER_CC3P); SET_BIT(tmpccer, OC_Config->OCPolarity << 8U); } else if constexpr(ch == TimerChannel::CHANNEL_4) { - CLEAR_BIT(instance.tim->CCER, TIM_CCER_CC4E); + CLEAR_BIT(instance->tim->CCER, TIM_CCER_CC4E); CLEAR_BIT(tmpccmrx, TIM_CCMR2_OC4M); CLEAR_BIT(tmpccmrx, TIM_CCMR2_CC4S); @@ -324,7 +386,7 @@ struct TimerWrapper { CLEAR_BIT(tmpccer, TIM_CCER_CC4P); SET_BIT(tmpccer, OC_Config->OCPolarity << 12U); } else if constexpr(ch == TimerChannel::CHANNEL_5) { - CLEAR_BIT(instance.tim->CCER, TIM_CCER_CC5E); + CLEAR_BIT(instance->tim->CCER, TIM_CCER_CC5E); CLEAR_BIT(tmpccmrx, TIM_CCMR3_OC5M); @@ -332,7 +394,7 @@ struct TimerWrapper { CLEAR_BIT(tmpccer, TIM_CCER_CC5P); SET_BIT(tmpccer, OC_Config->OCPolarity << 16U); } else if constexpr(ch == TimerChannel::CHANNEL_6) { - CLEAR_BIT(instance.tim->CCER, TIM_CCER_CC6E); + CLEAR_BIT(instance->tim->CCER, TIM_CCER_CC6E); CLEAR_BIT(tmpccmrx, TIM_CCMR3_OC6M); @@ -390,66 +452,71 @@ struct TimerWrapper { } } - instance.tim->CR2 = tmpcr2; + instance->tim->CR2 = tmpcr2; if constexpr(ch == TimerChannel::CHANNEL_1 || ch == TimerChannel::CHANNEL_2) { - instance.tim->CCMR1 = tmpccmrx; + instance->tim->CCMR1 = tmpccmrx; } else if constexpr(ch == TimerChannel::CHANNEL_3 || ch == TimerChannel::CHANNEL_4) { - instance.tim->CCMR2 = tmpccmrx; + instance->tim->CCMR2 = tmpccmrx; } else if constexpr(ch == TimerChannel::CHANNEL_5 || ch == TimerChannel::CHANNEL_6) { - instance.tim->CCMR3 = tmpccmrx; + instance->tim->CCMR3 = tmpccmrx; } - if constexpr(ch == TimerChannel::CHANNEL_1) instance.tim->CCR1 = OC_Config->Pulse; - else if constexpr(ch == TimerChannel::CHANNEL_2) instance.tim->CCR2 = OC_Config->Pulse; - else if constexpr(ch == TimerChannel::CHANNEL_3) instance.tim->CCR3 = OC_Config->Pulse; - else if constexpr(ch == TimerChannel::CHANNEL_4) instance.tim->CCR4 = OC_Config->Pulse; - else if constexpr(ch == TimerChannel::CHANNEL_5) instance.tim->CCR5 = OC_Config->Pulse; - else if constexpr(ch == TimerChannel::CHANNEL_6) instance.tim->CCR6 = OC_Config->Pulse; + if constexpr(ch == TimerChannel::CHANNEL_1) instance->tim->CCR1 = OC_Config->Pulse; + else if constexpr(ch == TimerChannel::CHANNEL_2) instance->tim->CCR2 = OC_Config->Pulse; + else if constexpr(ch == TimerChannel::CHANNEL_3) instance->tim->CCR3 = OC_Config->Pulse; + else if constexpr(ch == TimerChannel::CHANNEL_4) instance->tim->CCR4 = OC_Config->Pulse; + else if constexpr(ch == TimerChannel::CHANNEL_5) instance->tim->CCR5 = OC_Config->Pulse; + else if constexpr(ch == TimerChannel::CHANNEL_6) instance->tim->CCR6 = OC_Config->Pulse; - instance.tim->CCER = tmpccer; + instance->tim->CCER = tmpccer; } template inline void set_output_compare_preload_enable() { - if constexpr (ch == TimerChannel::CHANNEL_1) { - SET_BIT(instance.tim->CCMR1, TIM_CCMR1_OC1PE); - } else if constexpr(ch == TimerChannel::CHANNEL_2) { - SET_BIT(instance.tim->CCMR1, TIM_CCMR1_OC2PE); - } else if constexpr(ch == TimerChannel::CHANNEL_3) { - SET_BIT(instance.tim->CCMR2, TIM_CCMR2_OC3PE); + if constexpr((ch == TimerChannel::CHANNEL_1) || (ch == TimerChannel::CHANNEL_1_NEGATED)) { + SET_BIT(instance->tim->CCMR1, TIM_CCMR1_OC1PE); + } else if constexpr((ch == TimerChannel::CHANNEL_2) || (ch == TimerChannel::CHANNEL_2_NEGATED)) { + SET_BIT(instance->tim->CCMR1, TIM_CCMR1_OC2PE); + } else if constexpr((ch == TimerChannel::CHANNEL_3) || (ch == TimerChannel::CHANNEL_3_NEGATED)) { + SET_BIT(instance->tim->CCMR2, TIM_CCMR2_OC3PE); } else if constexpr(ch == TimerChannel::CHANNEL_4) { - SET_BIT(instance.tim->CCMR2, TIM_CCMR2_OC4PE); + SET_BIT(instance->tim->CCMR2, TIM_CCMR2_OC4PE); } else if constexpr(ch == TimerChannel::CHANNEL_5) { - SET_BIT(instance.tim->CCMR3, TIM_CCMR3_OC5PE); + SET_BIT(instance->tim->CCMR3, TIM_CCMR3_OC5PE); } else if constexpr(ch == TimerChannel::CHANNEL_6) { - SET_BIT(instance.tim->CCMR3, TIM_CCMR3_OC6PE); + SET_BIT(instance->tim->CCMR3, TIM_CCMR3_OC6PE); } else ST_LIB::compile_error("Unknown timer channel, there are only 6 channels [1..6]"); } template inline void set_capture_compare(uint16_t val) { - if constexpr (ch == TimerChannel::CHANNEL_1) { - instance.tim->CCR1 = val; - } else if constexpr(ch == TimerChannel::CHANNEL_2) { - instance.tim->CCR2 = val; - } else if constexpr(ch == TimerChannel::CHANNEL_3) { - instance.tim->CCR3 = val; + if constexpr((ch == TimerChannel::CHANNEL_1) || (ch == TimerChannel::CHANNEL_1_NEGATED)) { + instance->tim->CCR1 = val; + } else if constexpr((ch == TimerChannel::CHANNEL_2) || (ch == TimerChannel::CHANNEL_2_NEGATED)) { + instance->tim->CCR2 = val; + } else if constexpr((ch == TimerChannel::CHANNEL_3) || (ch == TimerChannel::CHANNEL_3_NEGATED)) { + instance->tim->CCR3 = val; } else if constexpr(ch == TimerChannel::CHANNEL_4) { - instance.tim->CCR4 = val; + instance->tim->CCR4 = val; } else if constexpr(ch == TimerChannel::CHANNEL_5) { - instance.tim->CCR5 = val; + instance->tim->CCR5 = val; } else if constexpr(ch == TimerChannel::CHANNEL_6) { - instance.tim->CCR6 = val; + instance->tim->CCR6 = val; } else ST_LIB::compile_error("Unknown timer channel, there are only 6 channels [1..6]"); } + inline bool are_all_channels_free() { + return ((instance->tim->CCER & TIM_CCER_CCxE_MASK) == 0) && + ((instance->tim->CCER & TIM_CCER_CCxNE_MASK) == 0); + } + // leftover from old TimerPeripheral, maybe this was useful? inline uint16_t get_prescaler() { - return instance.tim->PSC; + return instance->tim->PSC; } inline uint32_t get_period() { - return instance.tim->ARR; + return instance->tim->ARR; } }; } // namespace ST_LIB diff --git a/Tests/Time/timer_wrapper_test.cpp b/Tests/Time/timer_wrapper_test.cpp index 88c8b1168..47a657dca 100644 --- a/Tests/Time/timer_wrapper_test.cpp +++ b/Tests/Time/timer_wrapper_test.cpp @@ -47,7 +47,7 @@ ST_LIB::TimerDomain::Instance tim1_inst { }; TEST_F(TimerWrapperTests, Counter_EnabledDisabled) { - ST_LIB::TimerWrapper tim1(tim1_inst); + ST_LIB::TimerWrapper tim1(&tim1_inst); tim1.counter_enable(); EXPECT_EQ(TIM1_BASE->CR1 & TIM_CR1_CEN, TIM_CR1_CEN); @@ -56,7 +56,7 @@ TEST_F(TimerWrapperTests, Counter_EnabledDisabled) { } TEST_F(TimerWrapperTests, UpdateInterrupt_EnabledDisabled) { - ST_LIB::TimerWrapper tim1(tim1_inst); + ST_LIB::TimerWrapper tim1(&tim1_inst); tim1.enable_update_interrupt(); EXPECT_EQ(TIM1_BASE->DIER & TIM_DIER_UIE, TIM_DIER_UIE); @@ -65,7 +65,7 @@ TEST_F(TimerWrapperTests, UpdateInterrupt_EnabledDisabled) { } TEST_F(TimerWrapperTests, NVIC_EnabledDisabled) { - ST_LIB::TimerWrapper tim1(tim1_inst); + ST_LIB::TimerWrapper tim1(&tim1_inst); tim1.enable_nvic(); EXPECT_EQ(NVIC_GetEnableIRQ(TIM1_UP_IRQn), 1); @@ -74,7 +74,7 @@ TEST_F(TimerWrapperTests, NVIC_EnabledDisabled) { } TEST_F(TimerWrapperTests, UpdateEvent_EnabledDisabled) { - ST_LIB::TimerWrapper tim1(tim1_inst); + ST_LIB::TimerWrapper tim1(&tim1_inst); tim1.enable_update_event(); EXPECT_EQ(TIM1_BASE->CR1 & TIM_CR1_UDIS, 0); @@ -83,7 +83,7 @@ TEST_F(TimerWrapperTests, UpdateEvent_EnabledDisabled) { } TEST_F(TimerWrapperTests, BreakInterrupt_EnabledDisabled) { - ST_LIB::TimerWrapper tim1(tim1_inst); + ST_LIB::TimerWrapper tim1(&tim1_inst); tim1.break_interrupt_enable(); EXPECT_EQ(TIM1_BASE->DIER & TIM_DIER_BIE, TIM_DIER_BIE); @@ -92,7 +92,7 @@ TEST_F(TimerWrapperTests, BreakInterrupt_EnabledDisabled) { } TEST_F(TimerWrapperTests, OnePulseMode_EnabledDisabled) { - ST_LIB::TimerWrapper tim1(tim1_inst); + ST_LIB::TimerWrapper tim1(&tim1_inst); tim1.set_one_pulse_mode(); EXPECT_EQ(TIM1_BASE->CR1 & TIM_CR1_OPM, TIM_CR1_OPM); @@ -103,7 +103,7 @@ TEST_F(TimerWrapperTests, OnePulseMode_EnabledDisabled) { void callback(void *raw) {} TEST_F(TimerWrapperTests, ConfigureTimer) { - ST_LIB::TimerWrapper tim1(tim1_inst); + ST_LIB::TimerWrapper tim1(&tim1_inst); #define PRESCALER_VAL 200 #define PERIOD 1000 From 9a75f54db43f0729bfabbead60f65e2b4bf3ee23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20L=C3=B3pez?= <120128034+victor-Lopez25@users.noreply.github.com> Date: Wed, 4 Feb 2026 19:13:38 +0100 Subject: [PATCH 101/109] Hotfix! fixed a bug with a strange case when getting an overflow (#560) * Hotfix! fixed a bug with a strange case when getting an overflow of global_timer_us_ (overflow of 32 bits) * fix scheduler tests --- Src/HALAL/Services/Time/Scheduler.cpp | 14 +-- Tests/Time/scheduler_test.cpp | 135 +++++++++++++++++--------- 2 files changed, 91 insertions(+), 58 deletions(-) diff --git a/Src/HALAL/Services/Time/Scheduler.cpp b/Src/HALAL/Services/Time/Scheduler.cpp index 81aa1f781..354b3d2db 100644 --- a/Src/HALAL/Services/Time/Scheduler.cpp +++ b/Src/HALAL/Services/Time/Scheduler.cpp @@ -224,7 +224,7 @@ void Scheduler::remove_sorted(uint8_t id) { uint64_t pattern = pattern_32; ((uint32_t*)&pattern)[1] = pattern_32; - // diff becomes 0xid..id_0_id..id where 0 is the nibble where id is in sorted_task_ids + // diff becomes 0x..._0_... where 0 is the nibble where id is in sorted_task_ids uint64_t diff = Scheduler::sorted_task_ids_ ^ pattern; //https://stackoverflow.com/questions/79058066/finding-position-of-zero-nibble-in-64-bits @@ -261,22 +261,14 @@ void Scheduler::schedule_next_interval() { current_interval_us_ = 1; Scheduler_global_timer->ARR = 1; Scheduler_global_timer->CNT = 1; - Scheduler::global_timer_enable(); } else { if (diff < -1) [[unlikely]]{ current_interval_us_ = static_cast(0 - diff); } else { current_interval_us_ = static_cast(diff); } - configure_timer_for_interval(current_interval_us_); + Scheduler_global_timer->ARR = static_cast(current_interval_us_ - 1u); } -} - -inline void Scheduler::configure_timer_for_interval(uint32_t microseconds) { - // NOTE(vic): disabling the timer _might_ be necessary to prevent the timer from firing in the middle of configuring it, highly unlikely since it has a period of at least 1 microsecond - // TODO(vic): Validation: check arr is set correctly here: https://github.com/HyperloopUPV-H8/ST-LIB/pull/534#pullrequestreview-3529132356 - Scheduler_global_timer->ARR = static_cast(microseconds - 1u); - Scheduler_global_timer->CNT = 0; Scheduler::global_timer_enable(); } @@ -314,7 +306,7 @@ uint16_t Scheduler::register_task(uint32_t period_us, callback_t func) { task.callback = func; task.period_us = period_us; task.repeating = true; - task.next_fire_us = static_cast(global_tick_us_ + period_us); + task.next_fire_us = static_cast(global_tick_us_ + Scheduler_global_timer->CNT + period_us); task.id = static_cast(slot); insert_sorted(slot); schedule_next_interval(); diff --git a/Tests/Time/scheduler_test.cpp b/Tests/Time/scheduler_test.cpp index e1cc34435..4ca80f940 100644 --- a/Tests/Time/scheduler_test.cpp +++ b/Tests/Time/scheduler_test.cpp @@ -99,6 +99,52 @@ TEST_F(SchedulerTests, GlobalTickOverflow) { EXPECT_EQ(count, 5); } +#define multiple_tasks \ + X(1) \ + X(2) \ + X(3) \ + X(4) \ + X(5) \ + X(6) \ + X(7) \ + X(8) \ + X(9) \ + X(10) \ + X(11) \ + X(12) \ + X(13) \ + X(14) \ + X(15) \ + X(16) + +#define X(n) \ + int multiple_task##n##count = 0; \ + void multiple_task_##n(void) { \ + multiple_task##n##count++; \ + } +multiple_tasks +#undef X + +TEST_F(SchedulerTests, GlobalTickOverflowManyTasks) { + Scheduler::global_tick_us_ = 0xFFFFFFF0ULL; // Near 32-bit max + Scheduler::register_task(10, &multiple_task_1); + Scheduler::register_task(20, &multiple_task_2); + Scheduler::register_task(30, &multiple_task_3); + Scheduler::start(); + TIM2_BASE->PSC = 2; // quicker test + + constexpr int NUM_TICKS = 100; + for(int i = 0; i < NUM_TICKS; i++){ + for(int j = 0; j <= TIM2_BASE->PSC; j++) TIM2_BASE->inc_cnt_and_check(1); + + Scheduler::update(); + } + // 100 ticks /20 ticks/task = 5 executions. + EXPECT_EQ(multiple_task1count, NUM_TICKS / 10); + EXPECT_EQ(multiple_task2count, NUM_TICKS / 20); + EXPECT_EQ(multiple_task3count, NUM_TICKS / 30); +} + TEST_F(SchedulerTests, TimeoutClearAddTask) { uint8_t timeout_id = Scheduler::set_timeout(10, &fake_workload); Scheduler::start(); @@ -119,6 +165,7 @@ TEST_F(SchedulerTests, TimeoutClearAddTask) { EXPECT_EQ(Scheduler::active_task_count_, 1); } +int tickidx = 0; static volatile int connecting_execs{0}; static volatile int operational_execs{0}; static volatile int fault_execs{0}; @@ -142,19 +189,19 @@ TEST_F(SchedulerTests, TaskDe_ReRegistration) { TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 100; - for(int i = 0; i < NUM_TICKS; i++) { + for(; tickidx < NUM_TICKS; tickidx++) { for(int j = 0; j <= TIM2_BASE->PSC; j++) TIM2_BASE->inc_cnt_and_check(1); - if(i == 21){ - Scheduler::unregister_task(connecting_task); + if(tickidx == 21){ operational_task = Scheduler::register_task(10,operational_cyclic); + Scheduler::unregister_task(connecting_task); } - if(i == 45){ - Scheduler::unregister_task(operational_task); + if(tickidx == 45){ fault_task = Scheduler::register_task(10,fault_cyclic); + Scheduler::unregister_task(operational_task); } - if( i == 70){ + if(tickidx == 70){ Scheduler::unregister_task(fault_task); - i = 100; // finish test + tickidx = 100; // finish test } Scheduler::update(); } @@ -163,65 +210,59 @@ TEST_F(SchedulerTests, TaskDe_ReRegistration) { EXPECT_EQ(fault_execs, 2); } -#define multiple_tasks \ - X(1) \ - X(2) \ - X(3) \ - X(4) \ - X(5) \ - X(6) \ - X(7) \ - X(8) \ - X(9) \ - X(10) \ - X(11) \ - X(12) \ - X(13) \ - X(14) \ - X(15) \ - X(16) - -#define X(n) \ - int multiple_task##n##count = 0; \ - void multiple_task_##n(void) { \ - multiple_task##n##count++; \ - } -multiple_tasks -#undef X TEST_F(SchedulerTests, MultipleTasks) { -#define X(n) uint8_t taskid##n = Scheduler::register_task(n, &multiple_task_##n); \ - (void)taskid##n; - multiple_tasks -#undef X + multiple_task1count = 0; + multiple_task2count = 0; + multiple_task3count = 0; + multiple_task4count = 0; + multiple_task5count = 0; + multiple_task6count = 0; + + Scheduler::register_task(1, &multiple_task_1); + Scheduler::register_task(2, &multiple_task_2); + Scheduler::register_task(3, &multiple_task_3); + Scheduler::register_task(4, &multiple_task_4); + Scheduler::register_task(5, &multiple_task_5); + Scheduler::register_task(6, &multiple_task_6); Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 300; for(int i = 0; i < NUM_TICKS; i++) { - for(int j = 0; j <= TIM2_BASE->PSC; j++) TIM2_BASE->inc_cnt_and_check(1); Scheduler::update(); + for(int j = 0; j <= TIM2_BASE->PSC; j++) TIM2_BASE->inc_cnt_and_check(1); } -#define X(n) EXPECT_EQ(multiple_task##n##count, NUM_TICKS / n); - multiple_tasks -#undef X + EXPECT_EQ(multiple_task1count, NUM_TICKS / 1 - 1); + EXPECT_EQ(multiple_task2count, NUM_TICKS / 2 - 1); + EXPECT_EQ(multiple_task3count, NUM_TICKS / 3 - 1); + EXPECT_EQ(multiple_task4count, NUM_TICKS / 4 - 1); + EXPECT_EQ(multiple_task5count, NUM_TICKS / 5 - 1); + EXPECT_EQ(multiple_task6count, NUM_TICKS / 6 - 1); } TEST_F(SchedulerTests, SameTaskMultipleTimes) { -#define X(n) uint8_t taskid_##n = Scheduler::register_task(n, &multiple_task_1); \ - (void)taskid_##n; - multiple_tasks -#undef X + multiple_task1count = 0; + Scheduler::register_task(1, &multiple_task_1); + Scheduler::register_task(2, &multiple_task_1); + Scheduler::register_task(3, &multiple_task_1); + Scheduler::register_task(4, &multiple_task_1); + Scheduler::register_task(5, &multiple_task_1); + Scheduler::register_task(6, &multiple_task_1); multiple_task1count = 0; Scheduler::start(); TIM2_BASE->PSC = 2; // quicker test constexpr int NUM_TICKS = 300; for(int i = 0; i < NUM_TICKS; i++) { - for(int j = 0; j <= TIM2_BASE->PSC; j++) TIM2_BASE->inc_cnt_and_check(1); Scheduler::update(); + for(int j = 0; j <= TIM2_BASE->PSC; j++) TIM2_BASE->inc_cnt_and_check(1); } -#define X(n) NUM_TICKS / n + - EXPECT_EQ(multiple_task1count, multiple_tasks 0); + EXPECT_EQ(multiple_task1count, NUM_TICKS / 1 - 1 + + NUM_TICKS / 2 - 1 + + NUM_TICKS / 3 - 1 + + NUM_TICKS / 4 - 1 + + NUM_TICKS / 5 - 1 + + NUM_TICKS / 6 - 1); } From 5535002709ae3352f7f406f30013ab29f5a84cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20L=C3=B3pez?= <120128034+victor-Lopez25@users.noreply.github.com> Date: Thu, 5 Feb 2026 11:11:00 +0100 Subject: [PATCH 102/109] fixed set_timer_frequency (#562) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fixed set_timer_frequency... Now doesn't need to set_duty_cycle for any other pwms from the same timer (does it automatically) * Add pwm_frequency as a pointer too, add get_frequency and get_duty_cycle to PWM * Make set_pwm_frequency, set_timer_frequency templated * Add extra parens * remove unused param in PWM configure * Add check for <= 0.0f duty_cycle and > 100.0f * Durisimo este error * Add inline and unlikely to clamping in set_duty_cycle * PWM fix and pin::start * Update GPIO initialization logic for NOT_USED mode Refactor GPIO initialization for NOT_USED mode. --------- Co-authored-by: Cantonplas Co-authored-by: Daniel Cantó Catalán <144663567+Cantonplas@users.noreply.github.com> --- Inc/HALAL/Models/TimerDomain/TimerDomain.hpp | 9 +++ Inc/HALAL/Services/PWM/DualPWM.hpp | 68 +++++++----------- Inc/HALAL/Services/PWM/PWM.hpp | 59 +++++++-------- Inc/HALAL/Services/Time/TimerWrapper.hpp | 75 +++++++++++++++++--- Src/HALAL/HALAL.cpp | 2 +- Src/HALAL/Models/PinModel/Pin.cpp | 5 +- 6 files changed, 129 insertions(+), 89 deletions(-) diff --git a/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp b/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp index 551d019a1..89c5f089b 100644 --- a/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp +++ b/Inc/HALAL/Models/TimerDomain/TimerDomain.hpp @@ -160,6 +160,15 @@ struct TimerPin { ST_LIB::TimerChannel channel; }; +#ifndef DEFAULT_PWM_FREQUENCY_MODE +#define DEFAULT_PWM_FREQUENCY_MODE ST_LIB::PWM_Frequency_Mode::PRECISION +#endif + +enum class PWM_Frequency_Mode { + PRECISION, + SPEED, +}; + constexpr std::array create_timer_idxmap() { std::array result{}; diff --git a/Inc/HALAL/Services/PWM/DualPWM.hpp b/Inc/HALAL/Services/PWM/DualPWM.hpp index 6ced7d3f2..41b20ad94 100644 --- a/Inc/HALAL/Services/PWM/DualPWM.hpp +++ b/Inc/HALAL/Services/PWM/DualPWM.hpp @@ -48,15 +48,15 @@ class DualPWM { } TimerWrapper *timer; - uint32_t frequency; - float duty_cycle = 0; + uint32_t *frequency; + float *duty_cycle = nullptr; bool is_on_positive = false; bool is_on_negative = false; - bool is_center_aligned; public: - DualPWM(TimerWrapper *tim, uint32_t polarity, uint32_t negated_polarity) : timer(tim) { - this->is_center_aligned = ((timer->instance->tim->CR1 & TIM_CR1_CMS) != 0); + DualPWM(TimerWrapper *tim, uint32_t polarity, uint32_t negated_polarity, float *duty_ptr, uint32_t *frequency_ptr) : timer(tim) { + duty_cycle = duty_ptr; + frequency = frequency_ptr; TIM_OC_InitTypeDef sConfigOC = { .OCMode = TIM_OCMODE_PWM1, @@ -74,12 +74,12 @@ class DualPWM { timer->template set_output_compare_preload_enable(); } - void turn_on() { + inline void turn_on() { turn_on_positive(); turn_on_negative(); } - void turn_off() { + inline void turn_off() { turn_off_positive(); turn_off_negative(); } @@ -184,49 +184,35 @@ class DualPWM { this->is_on_negative = false; } - void set_duty_cycle(float duty_cycle) { - uint16_t raw_duty = (uint16_t)((float)(timer->instance->tim->ARR + 1) / 100.0f * duty_cycle); - timer->template set_capture_compare(raw_duty); - this->duty_cycle = duty_cycle; - } - - void set_timer_frequency_quick(uint32_t frequency) { - if(is_center_aligned) { - frequency = 2*frequency; + inline void set_duty_cycle(float duty_cycle) { + if(duty_cycle <= 0.0f) [[unlikely]] { + timer->template set_capture_compare(0); + *(this->duty_cycle) = 0.0f; + return; } - this->frequency = frequency; - timer->instance->tim->ARR = (timer->get_clock_frequency() / (timer->instance->tim->PSC + 1)) / frequency; - - set_duty_cycle(duty_cycle); + + if(duty_cycle > 100.0f) [[unlikely]] { duty_cycle = 100.0f; } + uint16_t raw_duty = (uint16_t)((float)(timer->instance->tim->ARR + 1) * (duty_cycle / 100.0f)); + timer->template set_capture_compare(raw_duty); + *(this->duty_cycle) = duty_cycle; } - void set_timer_frequency(uint32_t frequency) { - if(is_center_aligned) { - frequency = 2*frequency; - } - this->frequency = frequency; - - /* a = timer clock frequency - * b = (psc + 1) * frequency - * arr = (a - b/2) / b - */ - float psc_plus_1_mul_freq = (float)(timer->instance->tim->PSC + 1) * (float)frequency; - timer->instance->tim->ARR = (uint32_t)((float)timer->get_clock_frequency() / psc_plus_1_mul_freq - 0.5f); - - set_duty_cycle(duty_cycle); + template + inline void set_timer_frequency(uint32_t frequency) { + timer->template set_pwm_frequency(frequency); } - void configure(uint32_t frequency, float duty_cycle, int64_t dead_time_ns) { - this->duty_cycle = duty_cycle; - this->set_timer_frequency(frequency); + inline void configure(uint32_t frequency, float duty_cycle, int64_t dead_time_ns) { + *(this->duty_cycle) = duty_cycle; + this->template set_timer_frequency(frequency); this->set_dead_time(dead_time_ns); } - uint32_t get_frequency() const { - return this->frequency; + inline uint32_t get_frequency() const { + return *(this->frequency); } - float get_duty_cycle() const { - return this->duty_cycle; + inline float get_duty_cycle() const { + return *(this->duty_cycle); } void set_dead_time(int64_t dead_time_ns) { diff --git a/Inc/HALAL/Services/PWM/PWM.hpp b/Inc/HALAL/Services/PWM/PWM.hpp index 7c7da3e32..e743c63ac 100644 --- a/Inc/HALAL/Services/PWM/PWM.hpp +++ b/Inc/HALAL/Services/PWM/PWM.hpp @@ -48,14 +48,14 @@ class PWM { } TimerWrapper *timer; - uint32_t frequency; - float duty_cycle = 0; + uint32_t *frequency; + float *duty_cycle = nullptr; bool is_on = false; - bool is_center_aligned; public: - PWM(TimerWrapper *tim, uint32_t polarity, uint32_t negated_polarity) : timer(tim) { - this->is_center_aligned = ((timer->instance->tim->CR1 & TIM_CR1_CMS) != 0); + PWM(TimerWrapper *tim, uint32_t polarity, uint32_t negated_polarity, float *duty_ptr, uint32_t *frequency_ptr) : timer(tim) { + duty_cycle = duty_ptr; + frequency = frequency_ptr; TIM_OC_InitTypeDef sConfigOC = { .OCMode = TIM_OCMODE_PWM1, @@ -122,41 +122,34 @@ class PWM { this->is_on = false; } - void set_duty_cycle(float duty_cycle) { - uint16_t raw_duty = (uint16_t)((float)(timer->instance->tim->ARR + 1) / 100.0f * duty_cycle); + inline void set_duty_cycle(float duty_cycle) { + if(duty_cycle <= 0.0f) [[unlikely]] { + timer->template set_capture_compare(0); + *(this->duty_cycle) = 0.0f; + return; + } + + if(duty_cycle > 100.0f) [[unlikely]] { duty_cycle = 100.0f; } + uint16_t raw_duty = (uint16_t)((float)(timer->instance->tim->ARR + 1) / (100.0f * duty_cycle)); timer->template set_capture_compare(raw_duty); - this->duty_cycle = duty_cycle; + *(this->duty_cycle) = duty_cycle; } - void set_timer_frequency_quick(uint32_t frequency) { - if(is_center_aligned) { - frequency = 2*frequency; - } - this->frequency = frequency; - timer->instance->tim->ARR = (timer->get_clock_frequency() / (timer->instance->tim->PSC + 1)) / frequency; - - set_duty_cycle(duty_cycle); + template + inline void set_timer_frequency(uint32_t frequency) { + timer->template set_pwm_frequency(frequency); } - void set_timer_frequency(uint32_t frequency) { - if(is_center_aligned) { - frequency = 2*frequency; - } - this->frequency = frequency; - - /* a = timer clock frequency - * b = (psc + 1) * frequency - * arr = (a - b/2) / b - */ - float psc_plus_1_mul_freq = (float)(timer->instance->tim->PSC + 1) * (float)frequency; - timer->instance->tim->ARR = (uint32_t)((float)timer->get_clock_frequency() / psc_plus_1_mul_freq - 0.5f); - - set_duty_cycle(duty_cycle); + inline void configure(uint32_t frequency, float duty_cycle) { + *(this->duty_cycle) = duty_cycle; + this->template set_timer_frequency(frequency); } - void configure(uint32_t frequency, float duty_cycle) { - this->duty_cycle = duty_cycle; - this->set_timer_frequency(frequency); + inline uint32_t get_frequency() const { + return *(this->frequency); + } + inline float get_duty_cycle() const { + return *(this->duty_cycle); } }; } // namespace ST_LIB diff --git a/Inc/HALAL/Services/Time/TimerWrapper.hpp b/Inc/HALAL/Services/Time/TimerWrapper.hpp index 0a8721b62..016f6bba5 100644 --- a/Inc/HALAL/Services/Time/TimerWrapper.hpp +++ b/Inc/HALAL/Services/Time/TimerWrapper.hpp @@ -33,6 +33,10 @@ struct TimerWrapper { TimerWrapper() = default; TimerWrapper(TimerDomain::Instance *inst) : instance(inst) {} + static constexpr int MAX_pwm_channel_duties = 4; + float pwm_channel_duties[MAX_pwm_channel_duties] = {0.0f, 0.0f, 0.0f, 0.0f}; + uint32_t pwm_frequency = 0; + enum CountingMode : uint8_t { UP = 0, DOWN = 1, @@ -140,56 +144,72 @@ struct TimerWrapper { if constexpr(dev.e.pins[0].af != TimerAF::PWM) { ST_LIB::compile_error("Pin must be configured in TimerDomain as a PWM"); } - return PWM(this, polarity, negated_polarity); + return PWM(this, polarity, negated_polarity, + &pwm_channel_duties[static_cast(pin.channel) & + ~static_cast(TimerChannel::CHANNEL_NEGATED_FLAG)], &pwm_frequency); } else if constexpr(dev.e.pin_count > 1 && dev.e.pins[1].pin == pin.pin && dev.e.pins[1].channel == pin.channel) { if constexpr(dev.e.pins[1].af != TimerAF::PWM) { ST_LIB::compile_error("Pin must be configured in TimerDomain as a PWM"); } - return PWM(this, polarity, negated_polarity); + return PWM(this, polarity, negated_polarity, + &pwm_channel_duties[static_cast(pin.channel) & + ~static_cast(TimerChannel::CHANNEL_NEGATED_FLAG)], &pwm_frequency); } else if constexpr(dev.e.pin_count > 2 && dev.e.pins[2].pin == pin.pin && dev.e.pins[2].channel == pin.channel) { if constexpr(dev.e.pins[2].af != TimerAF::PWM) { ST_LIB::compile_error("Pin must be configured in TimerDomain as a PWM"); } - return PWM(this, polarity, negated_polarity); + return PWM(this, polarity, negated_polarity, + &pwm_channel_duties[static_cast(pin.channel) & + ~static_cast(TimerChannel::CHANNEL_NEGATED_FLAG)], &pwm_frequency); } else if constexpr(dev.e.pin_count > 3 && dev.e.pins[3].pin == pin.pin && dev.e.pins[3].channel == pin.channel) { if constexpr(dev.e.pins[3].af != TimerAF::PWM) { ST_LIB::compile_error("Pin must be configured in TimerDomain as a PWM"); } - return PWM(this, polarity, negated_polarity); + return PWM(this, polarity, negated_polarity, + &pwm_channel_duties[static_cast(pin.channel) & + ~static_cast(TimerChannel::CHANNEL_NEGATED_FLAG)], &pwm_frequency); } else if constexpr(dev.e.pin_count > 4 && dev.e.pins[4].pin == pin.pin && dev.e.pins[4].channel == pin.channel) { if constexpr(dev.e.pins[4].af != TimerAF::PWM) { ST_LIB::compile_error("Pin must be configured in TimerDomain as a PWM"); } - return PWM(this, polarity, negated_polarity); + return PWM(this, polarity, negated_polarity, + &pwm_channel_duties[static_cast(pin.channel) & + ~static_cast(TimerChannel::CHANNEL_NEGATED_FLAG)], &pwm_frequency); } else if constexpr(dev.e.pin_count > 5 && dev.e.pins[5].pin == pin.pin && dev.e.pins[5].channel == pin.channel) { if constexpr(dev.e.pins[5].af != TimerAF::PWM) { ST_LIB::compile_error("Pin must be configured in TimerDomain as a PWM"); } - return PWM(this, polarity, negated_polarity); + return PWM(this, polarity, negated_polarity, + &pwm_channel_duties[static_cast(pin.channel) & + ~static_cast(TimerChannel::CHANNEL_NEGATED_FLAG)], &pwm_frequency); } else if constexpr(dev.e.pin_count > 6 && dev.e.pins[6].pin == pin.pin && dev.e.pins[6].channel == pin.channel) { if constexpr(dev.e.pins[6].af != TimerAF::PWM) { ST_LIB::compile_error("Pin must be configured in TimerDomain as a PWM"); } - return PWM(this, polarity, negated_polarity); + return PWM(this, polarity, negated_polarity, + &pwm_channel_duties[static_cast(pin.channel) & + ~static_cast(TimerChannel::CHANNEL_NEGATED_FLAG)], &pwm_frequency); } else if constexpr(dev.e.pin_count == 7 && dev.e.pins[7].pin == pin.pin && dev.e.pins[7].channel == pin.channel) { if constexpr(dev.e.pins[7].af != TimerAF::PWM) { ST_LIB::compile_error("Pin must be configured in TimerDomain as a PWM"); } - return PWM(this, polarity, negated_polarity); + return PWM(this, polarity, negated_polarity, + &pwm_channel_duties[static_cast(pin.channel) & + ~static_cast(TimerChannel::CHANNEL_NEGATED_FLAG)], &pwm_frequency); } else { ST_LIB::compile_error("No pins passed to TimerWrapper are the same as the pins passed to get_pwm() [this method]"); } @@ -203,7 +223,8 @@ struct TimerWrapper { // NOTE: No voy a comprobar todo esto, no hará falta comprobarlo con la siguiente versión del pwm, dualpwm static_assert((static_cast(pin.channel) | static_cast(TimerChannel::CHANNEL_NEGATED_FLAG)) == static_cast(negated_pin.channel)); static_assert(pin.af == TimerAF::PWM && negated_pin.af == TimerAF::PWM); - return DualPWM(this, polarity, negated_polarity); + return DualPWM(this, polarity, negated_polarity, + &pwm_channel_duties[static_cast(pin.channel) - 1], &pwm_frequency); } inline void counter_enable() { @@ -321,7 +342,41 @@ struct TimerWrapper { } } - /////////////////////////////////////// + /////////////////////////////////////////// + // Below are methods used by other objects + + template + void set_pwm_frequency(uint32_t frequency) { + /* If it's center aligned duplicate the frequency */ + if((instance->tim->CR1 & TIM_CR1_CMS) != 0) { + frequency = 2*frequency; + } + pwm_frequency = frequency; + + if constexpr(mode == ST_LIB::PWM_Frequency_Mode::SPEED) { + instance->tim->ARR = (this->get_clock_frequency() / (instance->tim->PSC + 1)) / frequency; + } else if constexpr(mode == ST_LIB::PWM_Frequency_Mode::PRECISION) { + float psc_plus_1_mul_freq = (float)(instance->tim->PSC + 1) * (float)frequency; + instance->tim->ARR = (uint32_t)((float)get_clock_frequency() / psc_plus_1_mul_freq - 0.5f); + } + + if(pwm_channel_duties[0] != 0.0f) { + uint16_t raw_duty = (uint16_t)((float)(instance->tim->ARR + 1) / 100.0f * pwm_channel_duties[0]); + instance->tim->CCR1 = raw_duty; + } + if(pwm_channel_duties[1] != 0.0f) { + uint16_t raw_duty = (uint16_t)((float)(instance->tim->ARR + 1) / 100.0f * pwm_channel_duties[1]); + instance->tim->CCR2 = raw_duty; + } + if(pwm_channel_duties[2] != 0.0f) { + uint16_t raw_duty = (uint16_t)((float)(instance->tim->ARR + 1) / 100.0f * pwm_channel_duties[2]); + instance->tim->CCR3 = raw_duty; + } + if(pwm_channel_duties[3] != 0.0f) { + uint16_t raw_duty = (uint16_t)((float)(instance->tim->ARR + 1) / 100.0f * pwm_channel_duties[3]); + instance->tim->CCR4 = raw_duty; + } + } template inline void config_output_compare_channel(const TIM_OC_InitTypeDef *OC_Config) diff --git a/Src/HALAL/HALAL.cpp b/Src/HALAL/HALAL.cpp index f35056527..86e8fe40b 100644 --- a/Src/HALAL/HALAL.cpp +++ b/Src/HALAL/HALAL.cpp @@ -73,7 +73,7 @@ static void common_start(UART::Peripheral &printf_peripheral) { #endif #ifdef HAL_TIM_MODULE_ENABLED - Encoder::start(); + // Encoder::start(); Global_RTC::start_rtc(); //TimerPeripheral::start(); //Time::start(); diff --git a/Src/HALAL/Models/PinModel/Pin.cpp b/Src/HALAL/Models/PinModel/Pin.cpp index 19d5adfcc..da409644b 100644 --- a/Src/HALAL/Models/PinModel/Pin.cpp +++ b/Src/HALAL/Models/PinModel/Pin.cpp @@ -72,10 +72,7 @@ void Pin::start() { GPIO_InitStruct.Pin = pin.gpio_pin; switch (pin.mode) { case OperationMode::NOT_USED: - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_PULLDOWN; - HAL_GPIO_Init(pin.port, &GPIO_InitStruct); - break; + break; case OperationMode::OUTPUT: GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; From 0dd2472c40ab2a7a12f42a51e2dcd0f7cd32d2b9 Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Fri, 6 Feb 2026 15:46:07 +0100 Subject: [PATCH 103/109] funcionando con la antigua dma --- Inc/HALAL/Services/ADC/ADC.hpp | 5 +++-- Inc/HALAL/Services/Communication/I2C/I2C.hpp | 4 +++- Inc/HALAL/Services/Communication/SPI/SPI.hpp | 5 +++-- Inc/HALAL/Services/FMAC/FMAC.hpp | 6 +++++- Src/HALAL/Models/DMA/{DMA.cpp.tmp => DMA.cpp} | 6 +----- Src/HALAL/Services/ADC/ADC.cpp | 10 +++++----- Src/HALAL/Services/Communication/I2C/I2C.cpp | 5 +++-- Src/HALAL/Services/Communication/SPI/SPI.cpp | 5 +++-- Src/HALAL/Services/FMAC/FMAC.cpp | 5 +++-- 9 files changed, 29 insertions(+), 22 deletions(-) rename Src/HALAL/Models/DMA/{DMA.cpp.tmp => DMA.cpp} (81%) diff --git a/Inc/HALAL/Services/ADC/ADC.hpp b/Inc/HALAL/Services/ADC/ADC.hpp index 2c17d0a16..72da2d727 100644 --- a/Inc/HALAL/Services/ADC/ADC.hpp +++ b/Inc/HALAL/Services/ADC/ADC.hpp @@ -42,10 +42,11 @@ class ADC { uint32_t resolution; uint32_t external_trigger; vector channels; + DMA::Stream dma_stream; string name; InitData() = default; - InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, string name); + InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, DMA::Stream dma_stream, string name); }; class Peripheral { @@ -154,4 +155,4 @@ class ADC { static void init(Peripheral& peripheral); }; -#endif +#endif \ No newline at end of file diff --git a/Inc/HALAL/Services/Communication/I2C/I2C.hpp b/Inc/HALAL/Services/Communication/I2C/I2C.hpp index 16f2adb23..68a05da68 100644 --- a/Inc/HALAL/Services/Communication/I2C/I2C.hpp +++ b/Inc/HALAL/Services/Communication/I2C/I2C.hpp @@ -33,6 +33,8 @@ class I2C { Pin &SDA; I2C_HandleTypeDef *hi2c; I2C_TypeDef *instance; + DMA::Stream RX_DMA; + DMA::Stream TX_DMA; uint8_t address = 0; uint32_t speed_frequency_kHz = 100; uint32_t data_length_in_bits = 8; @@ -149,4 +151,4 @@ class I2C { static void init(I2C::Instance *i2c); }; -#endif +#endif \ No newline at end of file diff --git a/Inc/HALAL/Services/Communication/SPI/SPI.hpp b/Inc/HALAL/Services/Communication/SPI/SPI.hpp index ad3af9a79..4770e63de 100644 --- a/Inc/HALAL/Services/Communication/SPI/SPI.hpp +++ b/Inc/HALAL/Services/Communication/SPI/SPI.hpp @@ -55,7 +55,8 @@ class SPI{ SPI_HandleTypeDef* hspi; /**< HAL spi struct pin. */ SPI_TypeDef* instance; /**< HAL spi instance. */ - + DMA::Stream hdma_tx; /**< HAL DMA handler for writting */ + DMA::Stream hdma_rx; /**< HAL DMA handler for reading */ uint32_t baud_rate_prescaler; /**< SPI baud prescaler.*/ uint32_t mode = SPI_MODE_MASTER; /**< SPI mode. */ @@ -347,4 +348,4 @@ class SPI{ static void init(SPI::Instance* spi); }; -#endif +#endif \ No newline at end of file diff --git a/Inc/HALAL/Services/FMAC/FMAC.hpp b/Inc/HALAL/Services/FMAC/FMAC.hpp index 65ad277f2..484898a16 100644 --- a/Inc/HALAL/Services/FMAC/FMAC.hpp +++ b/Inc/HALAL/Services/FMAC/FMAC.hpp @@ -58,6 +58,10 @@ class MultiplierAccelerator{ struct FMACInstance{ FMACmodes mode; FMAC_HandleTypeDef *hfmac; + DMA::Stream dma_preload; + DMA::Stream dma_read; + DMA::Stream dma_write; + }; static FMACInstance Instance; @@ -128,4 +132,4 @@ class MultiplierAccelerator{ int16_t *FeedbackInValues, uint8_t FeedbackInSize, int16_t *FInValues, uint8_t FInSize, int16_t *OutValues, uint8_t OutSize, FMACmodes mode); }; -#endif +#endif \ No newline at end of file diff --git a/Src/HALAL/Models/DMA/DMA.cpp.tmp b/Src/HALAL/Models/DMA/DMA.cpp similarity index 81% rename from Src/HALAL/Models/DMA/DMA.cpp.tmp rename to Src/HALAL/Models/DMA/DMA.cpp index bfc875a9c..d0f9a95f5 100644 --- a/Src/HALAL/Models/DMA/DMA.cpp.tmp +++ b/Src/HALAL/Models/DMA/DMA.cpp @@ -2,13 +2,9 @@ * DMA.cpp * * Created on: 10 dic. 2022 - * Author: aleja - */ + * Author: aleja */ -# Para que este codigo conviva con la nueva dma hay que forzarlo un pelin. Yo (Jorge no pm), creo que la DMA nueva puede funcionar para todos los perifericos. En caso -# de que no sea asi, cambiare esto para que funcione (sera solo un momentito) - #include "HALAL/Models/DMA/DMA.hpp" #include "ErrorHandler/ErrorHandler.hpp" diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index 4ec12705a..815bd850f 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -16,8 +16,8 @@ uint8_t ADC::id_counter = 0; unordered_map ADC::active_instances = {}; -ADC::InitData::InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, string name) : - adc(adc), resolution(resolution), external_trigger(external_trigger), channels(channels), name(name) {} +ADC::InitData::InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, DMA::Stream dma_stream, string name) : + adc(adc), resolution(resolution), external_trigger(external_trigger), channels(channels), dma_stream(dma_stream), name(name) {} ADC::Peripheral::Peripheral(ADC_HandleTypeDef* handle, LowPowerTimer& timer, InitData& init_data) : handle(handle), timer(timer), init_data(init_data) { @@ -42,7 +42,7 @@ uint8_t ADC::inscribe(Pin pin) { InitData& init_data = active_instances[id_counter].peripheral->init_data; - + DMA::inscribe_stream(init_data.dma_stream); active_instances[id_counter].rank = init_data.channels.size(); init_data.channels.push_back(active_instances[id_counter].channel); return id_counter++; @@ -68,7 +68,7 @@ void ADC::turn_on(uint8_t id){ uint32_t buffer_length = peripheral->init_data.channels.size(); if (HAL_ADC_Start_DMA(peripheral->handle, (uint32_t*) peripheral->dma_data_buffer, buffer_length) != HAL_OK) { - ErrorHandler("DMA - %d - of ADC - %d - did not start correctly", id); + ErrorHandler("DMA - %d - of ADC - %d - did not start correctly", peripheral->init_data.dma_stream, id); return; } @@ -169,4 +169,4 @@ void ADC::init(Peripheral& peripheral) { void HAL_ADC_ConvCpltCallback (ADC_HandleTypeDef *hadc){ } -#endif +#endif \ No newline at end of file diff --git a/Src/HALAL/Services/Communication/I2C/I2C.cpp b/Src/HALAL/Services/Communication/I2C/I2C.cpp index 967b9eb07..1af2a9784 100644 --- a/Src/HALAL/Services/Communication/I2C/I2C.cpp +++ b/Src/HALAL/Services/Communication/I2C/I2C.cpp @@ -23,7 +23,8 @@ uint8_t I2C::inscribe(I2C::Peripheral &i2c, uint8_t address) { Pin::inscribe(i2c_instance->SCL, ALTERNATIVE); Pin::inscribe(i2c_instance->SDA, ALTERNATIVE); - //DMA::inscribe_stream(i2c_instance->hi2c); + DMA::inscribe_stream(i2c_instance->RX_DMA); + DMA::inscribe_stream(i2c_instance->TX_DMA); uint8_t id = I2C::id_counter++; @@ -271,4 +272,4 @@ void I2C::init(I2C::Instance *i2c) { } i2c->is_initialized = true; } -#endif +#endif \ No newline at end of file diff --git a/Src/HALAL/Services/Communication/SPI/SPI.cpp b/Src/HALAL/Services/Communication/SPI/SPI.cpp index 8e48abce9..46a072988 100644 --- a/Src/HALAL/Services/Communication/SPI/SPI.cpp +++ b/Src/HALAL/Services/Communication/SPI/SPI.cpp @@ -56,7 +56,8 @@ uint8_t SPI::inscribe(SPI::Peripheral& spi) { uint8_t id = SPI::id_counter++; if (spi_instance->use_DMA) { - //DMA::inscribe_stream(spi_instance->hspi); + DMA::inscribe_stream(spi_instance->hdma_rx); + DMA::inscribe_stream(spi_instance->hdma_tx); } SPI::registered_spi[id] = spi_instance; SPI::registered_spi_by_handler[spi_instance->hspi] = spi_instance; @@ -611,4 +612,4 @@ void SPI::spi_check_bus_collision(SPI::Instance* spi) { } } -#endif +#endif \ No newline at end of file diff --git a/Src/HALAL/Services/FMAC/FMAC.cpp b/Src/HALAL/Services/FMAC/FMAC.cpp index d7885689c..1076a69b0 100644 --- a/Src/HALAL/Services/FMAC/FMAC.cpp +++ b/Src/HALAL/Services/FMAC/FMAC.cpp @@ -32,7 +32,9 @@ void MultiplierAccelerator::IIR_software_in_software_out_inscribe(uint16_t input } void MultiplierAccelerator::inscribe(){ - //DMA::inscribe_stream(Instance.hfmac); + DMA::inscribe_stream(Instance.dma_preload); + DMA::inscribe_stream(Instance.dma_read); + DMA::inscribe_stream(Instance.dma_write); } void MultiplierAccelerator::start(){ @@ -166,4 +168,3 @@ void HAL_FMAC_ErrorCallback(FMAC_HandleTypeDef *hfmac){ ErrorHandler("Error while running FMAC"); } - From 2d110708c501ccc76295ce7a3cda714089a81e2e Mon Sep 17 00:00:00 2001 From: Jorge Canut Date: Fri, 6 Feb 2026 23:00:36 +0100 Subject: [PATCH 104/109] adc en teoria funcional, aun no he probado --- Inc/HALAL/Services/ADC/ADC.hpp | 6 +++--- Src/HALAL/Services/ADC/ADC.cpp | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Inc/HALAL/Services/ADC/ADC.hpp b/Inc/HALAL/Services/ADC/ADC.hpp index 72da2d727..100dba5a6 100644 --- a/Inc/HALAL/Services/ADC/ADC.hpp +++ b/Inc/HALAL/Services/ADC/ADC.hpp @@ -10,7 +10,7 @@ #include "HALAL/Models/PinModel/Pin.hpp" #include "HALAL/Models/LowPowerTimer/LowPowerTimer.hpp" -#include "HALAL/Models/DMA/DMA.hpp" +#include "HALAL/Models/DMA/DMA2.hpp" #if defined(HAL_ADC_MODULE_ENABLED) && defined(HAL_LPTIM_MODULE_ENABLED) @@ -42,11 +42,11 @@ class ADC { uint32_t resolution; uint32_t external_trigger; vector channels; - DMA::Stream dma_stream; + ST_LIB::DMA_Domain::Instance *dma_instance; string name; InitData() = default; - InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, DMA::Stream dma_stream, string name); + InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, ST_LIB::DMA_Domain::Instance *dma_instance, string name); }; class Peripheral { diff --git a/Src/HALAL/Services/ADC/ADC.cpp b/Src/HALAL/Services/ADC/ADC.cpp index 815bd850f..4abc262f1 100644 --- a/Src/HALAL/Services/ADC/ADC.cpp +++ b/Src/HALAL/Services/ADC/ADC.cpp @@ -16,8 +16,8 @@ uint8_t ADC::id_counter = 0; unordered_map ADC::active_instances = {}; -ADC::InitData::InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, DMA::Stream dma_stream, string name) : - adc(adc), resolution(resolution), external_trigger(external_trigger), channels(channels), dma_stream(dma_stream), name(name) {} +ADC::InitData::InitData(ADC_TypeDef* adc, uint32_t resolution, uint32_t external_trigger, vector& channels, ST_LIB::DMA_Domain::Instance *dma_instance, string name) : + adc(adc), resolution(resolution), external_trigger(external_trigger), channels(channels), dma_instance(dma_instance), name(name) {} ADC::Peripheral::Peripheral(ADC_HandleTypeDef* handle, LowPowerTimer& timer, InitData& init_data) : handle(handle), timer(timer), init_data(init_data) { @@ -42,7 +42,7 @@ uint8_t ADC::inscribe(Pin pin) { InitData& init_data = active_instances[id_counter].peripheral->init_data; - DMA::inscribe_stream(init_data.dma_stream); + //DMA::inscribe_stream(init_data.dma_stream); active_instances[id_counter].rank = init_data.channels.size(); init_data.channels.push_back(active_instances[id_counter].channel); return id_counter++; @@ -68,7 +68,7 @@ void ADC::turn_on(uint8_t id){ uint32_t buffer_length = peripheral->init_data.channels.size(); if (HAL_ADC_Start_DMA(peripheral->handle, (uint32_t*) peripheral->dma_data_buffer, buffer_length) != HAL_OK) { - ErrorHandler("DMA - %d - of ADC - %d - did not start correctly", peripheral->init_data.dma_stream, id); + ErrorHandler("DMA - %d - of ADC - %d - did not start correctly", peripheral->init_data.dma_instance, id); return; } @@ -146,6 +146,8 @@ void ADC::init(Peripheral& peripheral) { } } + __HAL_LINKDMA(&adc_handle, DMA_Handle, init_data.dma_instance->dma); + uint8_t counter = 0; for(uint32_t channel : peripheral.init_data.channels) { sConfig.Channel = channel; From 81327625a4fa45629956169ca3bdd5a5b560bcb4 Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Sun, 8 Feb 2026 15:57:16 +0100 Subject: [PATCH 105/109] fix(SPI): Fix merge things --- Inc/HALAL/Models/DMA/DMA2.hpp | 2 +- Inc/HALAL/Models/SPI/SPI2.hpp | 26 +++++++++++++------------- Inc/ST-LIB.hpp | 6 ------ 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index 0738a352e..ae9e54cc3 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -28,7 +28,7 @@ namespace ST_LIB { enum class Peripheral : uint8_t {none, adc1, adc2, adc3, i2c1, i2c2, i2c3, i2c5, - spi1, spi2, spi3, spi4, spi5, + spi1, spi2, spi3, spi4, spi5, spi6, fmac}; enum class Stream : uint8_t {none, dma1_stream0, dma1_stream1, dma1_stream2, dma1_stream3, diff --git a/Inc/HALAL/Models/SPI/SPI2.hpp b/Inc/HALAL/Models/SPI/SPI2.hpp index 97c137422..2d22f61cd 100644 --- a/Inc/HALAL/Models/SPI/SPI2.hpp +++ b/Inc/HALAL/Models/SPI/SPI2.hpp @@ -194,7 +194,7 @@ struct SPIDomain { miso_gpio(miso_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(miso_pin, peripheral)), mosi_gpio(mosi_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(mosi_pin, peripheral)), nss_gpio(GPIODomain::GPIO(nss_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(nss_pin, peripheral))), - dma_rx_tx(dma_instance(peripheral)) + dma_rx_tx(dma_peripheral(peripheral)) { config.validate(); @@ -218,7 +218,7 @@ struct SPIDomain { miso_gpio(miso_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(miso_pin, peripheral)), mosi_gpio(mosi_pin, GPIODomain::OperationMode::ALT_PP, GPIODomain::Pull::None, GPIODomain::Speed::VeryHigh, get_af(mosi_pin, peripheral)), nss_gpio(std::nullopt), // No NSS GPIO - dma_rx_tx(dma_instance(peripheral)) + dma_rx_tx(dma_peripheral(peripheral)) { config.validate(); @@ -422,20 +422,20 @@ struct SPIDomain { } } - static consteval DMA_Domain::Instance dma_instance(SPIPeripheral peripheral) { + static consteval DMA_Domain::Peripheral dma_peripheral(SPIPeripheral peripheral) { switch (peripheral) { case SPIPeripheral::spi1: - return DMA_Domain::Instance::spi1; + return DMA_Domain::Peripheral::spi1; case SPIPeripheral::spi2: - return DMA_Domain::Instance::spi2; + return DMA_Domain::Peripheral::spi2; case SPIPeripheral::spi3: - return DMA_Domain::Instance::spi3; + return DMA_Domain::Peripheral::spi3; case SPIPeripheral::spi4: - return DMA_Domain::Instance::spi4; + return DMA_Domain::Peripheral::spi4; case SPIPeripheral::spi5: - return DMA_Domain::Instance::spi5; - // case SPIPeripheral::spi6: - // return DMA_Domain::Instance::spi6; + return DMA_Domain::Peripheral::spi5; + case SPIPeripheral::spi6: + return DMA_Domain::Peripheral::spi6; default: compile_error("Invalid SPI peripheral specified in SPIDomain::Device"); } @@ -951,7 +951,7 @@ struct SPIDomain { static void init(std::span cfgs, std::span gpio_instances, - std::span dma_instances) { + std::span dma_peripherals) { for (std::size_t i = 0; i < N; ++i) { const auto &e = cfgs[i]; @@ -1014,8 +1014,8 @@ struct SPIDomain { auto& hspi = instances[i].hspi; hspi.Instance = instances[i].instance; - auto& dma_rx = dma_instances[e.dma_rx_idx]; - auto& dma_tx = dma_instances[e.dma_tx_idx]; + auto& dma_rx = dma_peripherals[e.dma_rx_idx]; + auto& dma_tx = dma_peripherals[e.dma_tx_idx]; // DMA handles are already configured and initialized by DMA_Domain hspi.hdmarx = &dma_rx.dma; diff --git a/Inc/ST-LIB.hpp b/Inc/ST-LIB.hpp index a553c35e6..55acbb589 100644 --- a/Inc/ST-LIB.hpp +++ b/Inc/ST-LIB.hpp @@ -111,7 +111,6 @@ template struct Board { constexpr std::size_t dmaN = domain_size(); constexpr std::size_t doutN = domain_size(); constexpr std::size_t dinN = domain_size(); - constexpr std::size_t dmaN = domain_size(); constexpr std::size_t mdmaPacketN = domain_size(); constexpr std::size_t sdN = domain_size(); constexpr std::size_t spiN = domain_size(); @@ -124,7 +123,6 @@ template struct Board { std::array dma_cfgs; std::array dout_cfgs; std::array din_cfgs; - std::array dma_cfgs; std::array mdma_packet_cfgs; std::array sd_cfgs; std::array spi_cfgs; @@ -144,8 +142,6 @@ template struct Board { ctx.template span()), .din_cfgs = DigitalInputDomain::template build( ctx.template span()), - .dma_cfgs = DMA_Domain::template build( - ctx.template span()), .mdma_packet_cfgs = MdmaPacketDomain::template build( ctx.template span()), .sd_cfgs = SdDomain::template build( @@ -165,7 +161,6 @@ template struct Board { constexpr std::size_t dmaN = domain_size(); constexpr std::size_t doutN = domain_size(); constexpr std::size_t dinN = domain_size(); - constexpr std::size_t dmaN = domain_size(); constexpr std::size_t mdmaPacketN = domain_size(); constexpr std::size_t sdN = domain_size(); constexpr std::size_t spiN = domain_size(); @@ -179,7 +174,6 @@ template struct Board { GPIODomain::Init::instances); DigitalInputDomain::Init::init(cfg.din_cfgs, GPIODomain::Init::instances); - DMA_Domain::Init::init(cfg.dma_cfgs); MdmaPacketDomain::Init::init(cfg.mdma_packet_cfgs, MPUDomain::Init::instances); SdDomain::Init::init(cfg.sd_cfgs, From bc7c1e5651e7082ae0adb7ce61d2e2c0861759d5 Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Sun, 8 Feb 2026 15:57:40 +0100 Subject: [PATCH 106/109] fix(HardFault): Include string.h so that it can compile --- Inc/HALAL/HardFault/HardfaultTrace.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Inc/HALAL/HardFault/HardfaultTrace.h b/Inc/HALAL/HardFault/HardfaultTrace.h index 6fe45e4b0..669a51c3f 100644 --- a/Inc/HALAL/HardFault/HardfaultTrace.h +++ b/Inc/HALAL/HardFault/HardfaultTrace.h @@ -4,6 +4,7 @@ #include "stm32h7xx_ll_gpio.h" #include "stm32h7xx_ll_bus.h" #include "stm32h7xx_ll_tim.h" +#include #define METADATA_FLASH_ADDR (0x080DFD00) //Metadata pool flash address #define HF_FLASH_ADDR (0x080C0000U) //Hard_fault_flash address #define HF_FLAG_VALUE (0xFF00FF00U) //Flag to know if already is written information in the flash From b8453be8bc6ab63dea3ab16970de9a0d0f3d975c Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Sun, 8 Feb 2026 16:10:19 +0100 Subject: [PATCH 107/109] fix(SPI): Fix merge, now works --- CMakeLists.txt | 2 ++ Inc/ST-LIB.hpp | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75d3fd0e0..1af94da3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -243,6 +243,8 @@ set(HALAL_CPP_NO_ETH ${CMAKE_CURRENT_LIST_DIR}/Src/HALAL/Models/MDMA/MDMA.cpp ${CMAKE_CURRENT_LIST_DIR}/Src/HALAL/Models/MPUManager/MPUManager.cpp ${CMAKE_CURRENT_LIST_DIR}/Src/HALAL/Models/Packets/SPIOrder.cpp + ${CMAKE_CURRENT_LIST_DIR}/Src/HALAL/Models/SPI/SPI2.cpp + ${CMAKE_CURRENT_LIST_DIR}/Src/HALAL/Models/DMA/DMA2.cpp ${CMAKE_CURRENT_LIST_DIR}/Src/HALAL/Models/PinModel/Pin.cpp ${CMAKE_CURRENT_LIST_DIR}/Src/HALAL/Models/TimerDomain/TimerDomain.cpp ${CMAKE_CURRENT_LIST_DIR}/Src/HALAL/Models/TimerPeripheral/TimerPeripheral.cpp diff --git a/Inc/ST-LIB.hpp b/Inc/ST-LIB.hpp index c391cf4a8..fc7c2d200 100644 --- a/Inc/ST-LIB.hpp +++ b/Inc/ST-LIB.hpp @@ -145,8 +145,6 @@ template struct Board { ctx.template span()), .mdma_packet_cfgs = MdmaPacketDomain::template build( ctx.template span()), - .sd_cfgs = SdDomain::template build( - ctx.template span()), .sd_cfgs = SdDomain::template build(ctx.template span()), .eth_cfgs = EthernetDomain::template build( ctx.template span()), From 4aee5a3bfbed50026e00fe9f61460a4d60b71dee Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Sun, 8 Feb 2026 16:17:31 +0100 Subject: [PATCH 108/109] fix(DMA): Missing spi6 --- Inc/HALAL/Models/DMA/DMA2.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Inc/HALAL/Models/DMA/DMA2.hpp b/Inc/HALAL/Models/DMA/DMA2.hpp index ae9e54cc3..3b33c2c30 100644 --- a/Inc/HALAL/Models/DMA/DMA2.hpp +++ b/Inc/HALAL/Models/DMA/DMA2.hpp @@ -135,7 +135,7 @@ namespace ST_LIB { static constexpr inline bool is_spi(Peripheral instance) { return is_one_of(instance, Peripheral::spi1, Peripheral::spi2, - Peripheral::spi3, Peripheral::spi4, Peripheral::spi5); + Peripheral::spi3, Peripheral::spi4, Peripheral::spi5, Peripheral::spi6); } static constexpr inline bool is_i2c(Peripheral instance) { From 7d416c719a62e7e986f3db6b33b33a076abcbb24 Mon Sep 17 00:00:00 2001 From: Boris Mladenov Beslimov Date: Sun, 8 Feb 2026 16:23:07 +0100 Subject: [PATCH 109/109] fix: General small things --- Inc/HALAL/Models/SPI/SPI2.hpp | 2 +- Inc/stm32h7xx_hal_conf_template.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Inc/HALAL/Models/SPI/SPI2.hpp b/Inc/HALAL/Models/SPI/SPI2.hpp index 2d22f61cd..dbcd23507 100644 --- a/Inc/HALAL/Models/SPI/SPI2.hpp +++ b/Inc/HALAL/Models/SPI/SPI2.hpp @@ -468,7 +468,7 @@ struct SPIDomain { SPI_HandleTypeDef hspi; SPI_TypeDef* instance; - volatile bool* operation_flag; + volatile bool* operation_flag = nullptr; }; diff --git a/Inc/stm32h7xx_hal_conf_template.h b/Inc/stm32h7xx_hal_conf_template.h index 74fdc0c32..4f41c7d25 100644 --- a/Inc/stm32h7xx_hal_conf_template.h +++ b/Inc/stm32h7xx_hal_conf_template.h @@ -233,7 +233,7 @@ * @brief Uncomment the line below to expanse the "assert_param" macro in the * HAL drivers code */ -#define USE_FULL_ASSERT 1 +/* #define USE_FULL_ASSERT 1U */ /* Includes ------------------------------------------------------------------*/