diff --git a/.gitignore b/.gitignore index a8c25b94..8df0c86a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.cache .vs/ .vscode/.cortex-debug* build/ diff --git a/.vscode/launch.json b/.vscode/launch.json index be41011a..912b94b0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -47,6 +47,26 @@ "type": "cortex-debug", "servertype": "jlink", "device": "STM32G070RB" + }, + { + "name": "stm32wb55rg", + "cwd": "${workspaceFolder}", + "executable": "${command:cmake.launchTargetPath}", + "request": "launch", + "type": "cortex-debug", + "device": "STM32WB55RG", + "servertype": "external", + "runToEntryPoint": "main", + "showDevDebugOutput": "both", + "gdbTarget": "host.docker.internal:61234", + "overrideLaunchCommands": [ + "monitor reset", + "-target-download", + "monitor reset" + ], + "overrideRestartCommands": [ + "monitor reset" + ] } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..b1487505 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "cmake.copyCompileCommands": "${workspaceFolder}/build/compile_commands.json", + "sonarlint.pathToCompileCommands": "${workspaceFolder}/build/compile_commands.json", + "clangd.arguments": ["--query-driver=/**/arm-none-eabi-*"], + "C_Cpp.autoAddFileAssociations": false +} diff --git a/CMakeLists.txt b/CMakeLists.txt index f3f90a3b..9684f151 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ if (HALST_STANDALONE) FetchContent_Declare( emil GIT_REPOSITORY https://github.com/philips-software/amp-embedded-infra-lib.git - GIT_TAG 419f636bd76f2c0ee2f7524ca548e724bf479e27 # unreleased + GIT_TAG 16dde0b5e8a10acae790e00e1cbb75e891f5925f # unreleased ) FetchContent_MakeAvailable(emil) diff --git a/CMakePresets.json b/CMakePresets.json index fd763188..5260979c 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -7,7 +7,8 @@ "binaryDir": "${sourceDir}/build/${presetName}", "installDir": "${sourceDir}/install", "cacheVariables": { - "HALST_BUILD_EXAMPLES": true + "HALST_BUILD_EXAMPLES": true, + "CMAKE_EXPORT_COMPILE_COMMANDS": "On" } }, { @@ -134,6 +135,18 @@ "HALST_BUILD_EXAMPLES_FREERTOS": true, "FREERTOS_CONFIG_FILE_DIRECTORY": "${sourceDir}/examples/freertos/config" } + }, + { + "name": "stm32g474", + "displayName": "stm32g474", + "description": "Build for stm32g474", + "inherits": "stm32", + "toolchainFile": "${sourceDir}/build/${presetName}/_deps/emil-src/cmake/toolchain-arm-gcc-m4-fpv4-sp-d16.cmake", + "cacheVariables": { + "TARGET_CORTEX": "m4", + "TARGET_MCU_FAMILY": "stm32g4xx", + "TARGET_MCU": "stm32g474" + } } ], "buildPresets": [ diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index fccbc2be..6fd2ce54 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(blink) add_subdirectory(freertos) +add_subdirectory(helloworld) diff --git a/examples/blink/CMakeLists.txt b/examples/blink/CMakeLists.txt index b8ede84e..21a48545 100644 --- a/examples/blink/CMakeLists.txt +++ b/examples/blink/CMakeLists.txt @@ -1,5 +1,10 @@ add_executable(hal_st.blink_nucleo144 Main.cpp) -emil_build_for(hal_st.blink_nucleo144 TARGET_MCU_VENDOR st PREREQUISITE_BOOL HALST_BUILD_EXAMPLES) +emil_build_for(hal_st.blink_nucleo144 + TARGET_MCU stm32f429 + TARGET_MCU stm32f746 + TARGET_MCU stm32f767 + PREREQUISITE_BOOL HALST_BUILD_EXAMPLES +) target_compile_definitions(hal_st.blink_nucleo144 PUBLIC NUCLEO=Nucleo144Ui @@ -18,10 +23,16 @@ emil_generate_artifacts(TARGET hal_st.blink_nucleo144 LST MAP BIN HEX) ###################################################################### add_executable(hal_st.blink_nucleo64 Main.cpp) -emil_build_for(hal_st.blink_nucleo64 TARGET_MCU_VENDOR st PREREQUISITE_BOOL HALST_BUILD_EXAMPLES) +emil_build_for(hal_st.blink_nucleo64 + TARGET_MCU stm32g431 + TARGET_MCU stm32g474 + TARGET_MCU stm32wb55 + PREREQUISITE_BOOL HALST_BUILD_EXAMPLES +) target_compile_definitions(hal_st.blink_nucleo64 PUBLIC - NUCLEO=Nucleo64Ui + $<$>:NUCLEO=Nucleo64Ui> + $<$:NUCLEO=Nucleo64WBUi> ) target_link_libraries(hal_st.blink_nucleo64 PRIVATE diff --git a/examples/helloworld/CMakeLists.txt b/examples/helloworld/CMakeLists.txt new file mode 100644 index 00000000..5a197f35 --- /dev/null +++ b/examples/helloworld/CMakeLists.txt @@ -0,0 +1,21 @@ +add_executable(hal_st.helloworld_nucleo64 Main.cpp) +emil_build_for(hal_st.helloworld_nucleo64 + TARGET_MCU stm32g474 + TARGET_MCU stm32wb55 + PREREQUISITE_BOOL HALST_BUILD_EXAMPLES +) + +target_compile_definitions(hal_st.helloworld_nucleo64 PUBLIC + $<$>:NUCLEO=Nucleo64Ui> + $<$:NUCLEO=Nucleo64WBUi> +) + +target_link_libraries(hal_st.helloworld_nucleo64 PRIVATE + services.util + hal_st.instantiations +) + +halst_target_default_linker_scripts(hal_st.helloworld_nucleo64) +halst_target_default_init(hal_st.helloworld_nucleo64) + +emil_generate_artifacts(TARGET hal_st.helloworld_nucleo64 LST MAP BIN HEX) diff --git a/examples/helloworld/Main.cpp b/examples/helloworld/Main.cpp new file mode 100644 index 00000000..4742f74a --- /dev/null +++ b/examples/helloworld/Main.cpp @@ -0,0 +1,51 @@ +#include "hal/interfaces/Gpio.hpp" +#include "hal_st/instantiations/NucleoUi.hpp" +#include "hal_st/instantiations/StmEventInfrastructure.hpp" +#include "infra/timer/Timer.hpp" +#include "services/tracer/GlobalTracer.hpp" +#include "services/tracer/StreamWriterOnSerialCommunication.hpp" +#include "services/tracer/Tracer.hpp" +#include "services/tracer/TracerWithDateTime.hpp" +#include "services/util/DebugLed.hpp" +#include +#include + +unsigned int hse_value = 24'000'000; + +int main() +{ + HAL_Init(); + + static main_::StmEventInfrastructure eventInfrastructure; + static main_::NUCLEO ui; + static services::DebugLed debugLed(ui.ledGreen); + static hal::DmaStm dmaStm; + +#if defined(STM32G0) || defined(STM32G4) + static hal::GpioPinStm stLinkUartTxPin{ hal::Port::A, 2 }; + static hal::GpioPinStm stLinkUartRxPin{ hal::Port::A, 3 }; + static hal::DmaStm::TransmitStream transmitStream{ dmaStm, hal::DmaChannelId{ 1, 1, DMA_REQUEST_USART2_TX } }; + static hal::UartStmDma stLinkUartDma{ transmitStream, 2, stLinkUartTxPin, stLinkUartRxPin }; +#endif + +#if defined(STM32WB) + static hal::GpioPinStm stLinkUartTxPin{ hal::Port::B, 6 }; + static hal::GpioPinStm stLinkUartRxPin{ hal::Port::B, 7 }; + static hal::DmaStm::TransmitStream transmitStream{ dmaStm, hal::DmaChannelId{ 1, 1, DMA_REQUEST_USART1_TX } }; + static hal::UartStmDma stLinkUartDma{ transmitStream, 1, stLinkUartTxPin, stLinkUartRxPin }; +#endif + + static services::StreamWriterOnSerialCommunication::WithStorage<64> streamWriterOnSerialCommunication{ stLinkUartDma }; + static infra::TextOutputStream::WithErrorPolicy textOutputStream{ streamWriterOnSerialCommunication }; + static services::TracerWithDateTime tracerWithDateTime{ textOutputStream }; + + services::SetGlobalTracerInstance(tracerWithDateTime); + + static infra::TimerRepeating timerRepeating{ std::chrono::seconds{ 1 }, [] + { + services::GlobalTracer().Trace() << "Hello World !"; + } }; + + eventInfrastructure.Run(); + __builtin_unreachable(); +} diff --git a/hal_st/instantiations/NucleoUi.hpp b/hal_st/instantiations/NucleoUi.hpp index 169c4498..8a1111e4 100644 --- a/hal_st/instantiations/NucleoUi.hpp +++ b/hal_st/instantiations/NucleoUi.hpp @@ -1,7 +1,9 @@ #ifndef HAL_ST_NUCLEO_UI_HPP #define HAL_ST_NUCLEO_UI_HPP +#include "hal_st/stm32fxxx/DmaStm.hpp" #include "hal_st/stm32fxxx/GpioStm.hpp" +#include "hal_st/stm32fxxx/UartStmDma.hpp" namespace main_ { diff --git a/hal_st/stm32fxxx/AnalogToDigitalPinStm.cpp b/hal_st/stm32fxxx/AnalogToDigitalPinStm.cpp index cf5e128a..130ddc01 100644 --- a/hal_st/stm32fxxx/AnalogToDigitalPinStm.cpp +++ b/hal_st/stm32fxxx/AnalogToDigitalPinStm.cpp @@ -39,23 +39,20 @@ namespace hal { ADC_ChannelConfTypeDef channelConfig; channelConfig.Channel = adcChannel[analogPin.AdcChannel(adc.index + 1)]; -#if !defined(STM32WB) - channelConfig.Rank = 1; -#else +#if defined(STM32WB) || defined(STM32G0) || defined(STM32G4) channelConfig.Rank = ADC_REGULAR_RANK_1; +#else + channelConfig.Rank = 1; #endif #if defined(STM32F0) || defined(STM32F3) channelConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5; -#elif defined(STM32WB) +#elif defined(STM32WB) || defined(STM32G4) channelConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5; channelConfig.Offset = 0; channelConfig.OffsetNumber = ADC_OFFSET_NONE; channelConfig.SingleDiff = ADC_SINGLE_ENDED; #elif defined(STM32G0) channelConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES_5; -#elif defined(STM32G4) - channelConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES_5; - channelConfig.Offset = 0; #else channelConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; channelConfig.Offset = 0; @@ -100,7 +97,7 @@ namespace hal #if !defined(STM32F3) handle.Init.DMAContinuousRequests = DISABLE; #endif -#if defined(STM32WB) +#if defined(STM32WB) || defined(STM32G0) || defined(STM32G4) handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; #elif !defined(STM32F3) handle.Init.EOCSelection = DISABLE; diff --git a/hal_st/stm32fxxx/CMakeLists.txt b/hal_st/stm32fxxx/CMakeLists.txt index 6ae04a1e..9e00cdf4 100644 --- a/hal_st/stm32fxxx/CMakeLists.txt +++ b/hal_st/stm32fxxx/CMakeLists.txt @@ -33,6 +33,8 @@ target_sources(hal_st.stm32fxxx PRIVATE $<$:DefaultClockNucleoG070RB.hpp> $<$:DefaultClockNucleoG431RB.cpp> $<$:DefaultClockNucleoG431RB.hpp> + $<$:DefaultClockNucleoG474RE.cpp> + $<$:DefaultClockNucleoG474RE.hpp> $<$:DefaultClockNucleoWB55RG.cpp> $<$:DefaultClockNucleoWB55RG.hpp> DigitalToAnalogPinStm.cpp @@ -111,6 +113,9 @@ if (TARGET_MCU_VENDOR STREQUAL st) elseif (TARGET_MCU STREQUAL stm32g431) set(gpio_xml "${CMAKE_CURRENT_SOURCE_DIR}/ip/GPIO-STM32G43x_gpio_v1_0_Modes.xml") set(mcu_xml "${CMAKE_CURRENT_SOURCE_DIR}/mcu/STM32G431R(6-8-B)Tx.xml") + elseif (TARGET_MCU STREQUAL stm32g474) + set(gpio_xml "${CMAKE_CURRENT_SOURCE_DIR}/ip/GPIO-STM32G47x_gpio_v1_0_Modes.xml") + set(mcu_xml "${CMAKE_CURRENT_SOURCE_DIR}/mcu/STM32G474R(B-C-E)Tx.xml") elseif (TARGET_MCU_VARIANT STREQUAL stm32wb55rg) set(gpio_xml "${CMAKE_CURRENT_SOURCE_DIR}/ip/GPIO-STM32WB55x_gpio_v1_0_Modes.xml") set(mcu_xml "${CMAKE_CURRENT_SOURCE_DIR}/mcu/STM32WB55RGVx.xml") diff --git a/hal_st/stm32fxxx/DefaultClockNucleoG474RE.cpp b/hal_st/stm32fxxx/DefaultClockNucleoG474RE.cpp new file mode 100644 index 00000000..fdc6c680 --- /dev/null +++ b/hal_st/stm32fxxx/DefaultClockNucleoG474RE.cpp @@ -0,0 +1,47 @@ +#include DEVICE_HEADER +#include "hal_st/stm32fxxx/DefaultClockNucleoG474RE.hpp" + +/* The system Clock is configured as follows: + * System Clock source = PLL (HSE) + * SYSCLK(Hz) = 170,000,000 + * HCLK(Hz) = 170,000,000 + * AHB Prescaler = 1 + * APB1 Prescaler = 1 + * APB2 Prescaler = 1 + * HSI Frequency(Hz) = 24MHz + * VDD(V) = 3.3 + * Main regulator output voltage = Scale1 mode + */ +void ConfigureDefaultClockNucleo474RE() +{ + RCC_OscInitTypeDef RCC_OscInitStruct = { 0 }; + RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 }; + + /** Configure the main internal regulator output voltage + */ + HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST); + + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV6; + RCC_OscInitStruct.PLL.PLLN = 85; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4); +} diff --git a/hal_st/stm32fxxx/DefaultClockNucleoG474RE.hpp b/hal_st/stm32fxxx/DefaultClockNucleoG474RE.hpp new file mode 100644 index 00000000..e791d2c0 --- /dev/null +++ b/hal_st/stm32fxxx/DefaultClockNucleoG474RE.hpp @@ -0,0 +1,6 @@ +#ifndef HAL_ST_DEFAULT_CLOCK_HPP +#define HAL_ST_DEFAULT_CLOCK_HPP + +void ConfigureDefaultClockNucleo474RE(); + +#endif diff --git a/hal_st/stm32fxxx/DmaStm.cpp b/hal_st/stm32fxxx/DmaStm.cpp index fc328587..4175a7a0 100644 --- a/hal_st/stm32fxxx/DmaStm.cpp +++ b/hal_st/stm32fxxx/DmaStm.cpp @@ -1,4 +1,5 @@ #include "hal_st/stm32fxxx/DmaStm.hpp" +#include "infra/util/ByteRange.hpp" #if !defined(STM32F0) && !defined(STM32F1) && !defined(STM32F3) @@ -6,84 +7,254 @@ namespace hal { namespace { - -#if defined(STM32F7) || defined(STM32F4) - - volatile uint32_t* const dmaISR[2][8] = { - { &DMA1->LISR, &DMA1->LISR, &DMA1->LISR, &DMA1->LISR, &DMA1->HISR, &DMA1->HISR, &DMA1->HISR, &DMA1->HISR }, - { &DMA2->LISR, &DMA2->LISR, &DMA2->LISR, &DMA2->LISR, &DMA2->HISR, &DMA2->HISR, &DMA2->HISR, &DMA2->HISR } +#if defined(DMA_STREAM_BASED) + const std::array dmaISR{ + std::array{ &DMA1->LISR, &DMA1->LISR, &DMA1->LISR, &DMA1->LISR, &DMA1->HISR, &DMA1->HISR, &DMA1->HISR, &DMA1->HISR }, + std::array{ &DMA2->LISR, &DMA2->LISR, &DMA2->LISR, &DMA2->LISR, &DMA2->HISR, &DMA2->HISR, &DMA2->HISR, &DMA2->HISR }, }; - volatile uint32_t* const dmaIFCR[2][8] = { - { &DMA1->LIFCR, &DMA1->LIFCR, &DMA1->LIFCR, &DMA1->LIFCR, &DMA1->HIFCR, &DMA1->HIFCR, &DMA1->HIFCR, &DMA1->HIFCR }, - { &DMA2->LIFCR, &DMA2->LIFCR, &DMA2->LIFCR, &DMA2->LIFCR, &DMA2->HIFCR, &DMA2->HIFCR, &DMA2->HIFCR, &DMA2->HIFCR } + const std::array dmaIFCR{ + std::array{ &DMA1->LIFCR, &DMA1->LIFCR, &DMA1->LIFCR, &DMA1->LIFCR, &DMA1->HIFCR, &DMA1->HIFCR, &DMA1->HIFCR, &DMA1->HIFCR }, + std::array{ &DMA2->LIFCR, &DMA2->LIFCR, &DMA2->LIFCR, &DMA2->LIFCR, &DMA2->HIFCR, &DMA2->HIFCR, &DMA2->HIFCR, &DMA2->HIFCR }, }; - DMA_Stream_TypeDef* const dmaStream[2][8] = { - { 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 } + const std::array DmaChannel{ + std::array{ DMA1_Stream0, DMA1_Stream1, DMA1_Stream2, DMA1_Stream3, DMA1_Stream4, DMA1_Stream5, DMA1_Stream6, DMA1_Stream7 }, + std::array{ DMA2_Stream0, DMA2_Stream1, DMA2_Stream2, DMA2_Stream3, DMA2_Stream4, DMA2_Stream5, DMA2_Stream6, DMA2_Stream7 }, }; - const IRQn_Type dmaIrq[2][8] = { - { DMA1_Stream0_IRQn, DMA1_Stream1_IRQn, DMA1_Stream2_IRQn, DMA1_Stream3_IRQn, DMA1_Stream4_IRQn, DMA1_Stream5_IRQn, DMA1_Stream6_IRQn, DMA1_Stream7_IRQn }, - { DMA2_Stream0_IRQn, DMA2_Stream1_IRQn, DMA2_Stream2_IRQn, DMA2_Stream3_IRQn, DMA2_Stream4_IRQn, DMA2_Stream5_IRQn, DMA2_Stream6_IRQn, DMA2_Stream7_IRQn } + const std::array dmaIrq{ + std::array{ DMA1_Stream0_IRQn, DMA1_Stream1_IRQn, DMA1_Stream2_IRQn, DMA1_Stream3_IRQn, DMA1_Stream4_IRQn, DMA1_Stream5_IRQn, DMA1_Stream6_IRQn, DMA1_Stream7_IRQn }, + std::array{ DMA2_Stream0_IRQn, DMA2_Stream1_IRQn, DMA2_Stream2_IRQn, DMA2_Stream3_IRQn, DMA2_Stream4_IRQn, DMA2_Stream5_IRQn, DMA2_Stream6_IRQn, DMA2_Stream7_IRQn }, }; + const std::array dmaChannel + { + DMA_CHANNEL_0, + DMA_CHANNEL_1, + DMA_CHANNEL_2, + DMA_CHANNEL_3, + DMA_CHANNEL_4, + DMA_CHANNEL_5, + DMA_CHANNEL_6, + DMA_CHANNEL_7, #if defined(STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx) - const uint32_t dmaChannel[16] = { - DMA_CHANNEL_0, DMA_CHANNEL_1, DMA_CHANNEL_2, DMA_CHANNEL_3, DMA_CHANNEL_4, DMA_CHANNEL_5, DMA_CHANNEL_6, DMA_CHANNEL_7, - DMA_CHANNEL_8, DMA_CHANNEL_9, DMA_CHANNEL_10, DMA_CHANNEL_11, DMA_CHANNEL_12, DMA_CHANNEL_13, DMA_CHANNEL_14, DMA_CHANNEL_15 - }; -#else - const uint32_t dmaChannel[8] = { - DMA_CHANNEL_0, DMA_CHANNEL_1, DMA_CHANNEL_2, DMA_CHANNEL_3, DMA_CHANNEL_4, DMA_CHANNEL_5, DMA_CHANNEL_6, DMA_CHANNEL_7 + DMA_CHANNEL_8, + DMA_CHANNEL_9, + DMA_CHANNEL_10, + DMA_CHANNEL_11, + DMA_CHANNEL_12, + DMA_CHANNEL_13, + DMA_CHANNEL_14, + DMA_CHANNEL_15, +#endif }; + + const std::array streamToTCIF{ DMA_FLAG_TCIF0_4, DMA_FLAG_TCIF1_5, DMA_FLAG_TCIF2_6, DMA_FLAG_TCIF3_7, DMA_FLAG_TCIF0_4, DMA_FLAG_TCIF1_5, DMA_FLAG_TCIF2_6, DMA_FLAG_TCIF3_7 }; + const std::array streamToHTIF{ DMA_FLAG_HTIF0_4, DMA_FLAG_HTIF1_5, DMA_FLAG_HTIF2_6, DMA_FLAG_HTIF3_7, DMA_FLAG_HTIF0_4, DMA_FLAG_HTIF1_5, DMA_FLAG_HTIF2_6, DMA_FLAG_HTIF3_7 }; + const std::array streamToTEIF{ DMA_FLAG_TEIF0_4, DMA_FLAG_TEIF1_5, DMA_FLAG_TEIF2_6, DMA_FLAG_TEIF3_7, DMA_FLAG_TEIF0_4, DMA_FLAG_TEIF1_5, DMA_FLAG_TEIF2_6, DMA_FLAG_TEIF3_7 }; #endif - const uint32_t streamToTCIF[8] = { DMA_FLAG_TCIF0_4, DMA_FLAG_TCIF1_5, DMA_FLAG_TCIF2_6, DMA_FLAG_TCIF3_7, DMA_FLAG_TCIF0_4, DMA_FLAG_TCIF1_5, DMA_FLAG_TCIF2_6, DMA_FLAG_TCIF3_7 }; - const uint32_t streamToHTIF[8] = { DMA_FLAG_HTIF0_4, DMA_FLAG_HTIF1_5, DMA_FLAG_HTIF2_6, DMA_FLAG_HTIF3_7, DMA_FLAG_HTIF0_4, DMA_FLAG_HTIF1_5, DMA_FLAG_HTIF2_6, DMA_FLAG_HTIF3_7 }; - const uint32_t streamToTEIF[8] = { DMA_FLAG_TEIF0_4, DMA_FLAG_TEIF1_5, DMA_FLAG_TEIF2_6, DMA_FLAG_TEIF3_7, DMA_FLAG_TEIF0_4, DMA_FLAG_TEIF1_5, DMA_FLAG_TEIF2_6, DMA_FLAG_TEIF3_7 }; +#if defined(DMA_CHANNEL_BASED) + // clang-format off + const std::array dmaISR + { + std::array + { + &DMA1->ISR, + &DMA1->ISR, + &DMA1->ISR, + &DMA1->ISR, + &DMA1->ISR, + &DMA1->ISR, +#if defined(DMA1_Channel7) + &DMA1->ISR, +#endif +#if defined(DMA1_Channel8) + &DMA1->ISR, +#endif + }, +#if defined(DMA2_Channel1) + std::array + { + &DMA2->ISR, + &DMA2->ISR, + &DMA2->ISR, + &DMA2->ISR, + &DMA2->ISR, + &DMA2->ISR, +#if defined(DMA2_Channel7) + &DMA2->ISR, +#endif +#if defined(DMA2_Channel8) + &DMA2->ISR, +#endif + }, +#endif + }; -#elif defined(STM32WB) || defined(STM32G4) - volatile uint32_t* const dmaISR[2][7] = { - { &DMA1->ISR, &DMA1->ISR, &DMA1->ISR, &DMA1->ISR, &DMA1->ISR, &DMA1->ISR, &DMA1->ISR }, - { &DMA2->ISR, &DMA2->ISR, &DMA2->ISR, &DMA2->ISR, &DMA2->ISR, &DMA2->ISR, &DMA2->ISR } + const std::array dmaIFCR + { + std::array + { + &DMA1->IFCR, + &DMA1->IFCR, + &DMA1->IFCR, + &DMA1->IFCR, + &DMA1->IFCR, + &DMA1->IFCR, +#if defined(DMA1_Channel7) + &DMA1->IFCR, +#endif +#if defined(DMA1_Channel8) + &DMA1->IFCR, +#endif + }, +#if defined(DMA2_Channel1) + std::array + { + &DMA2->IFCR, + &DMA2->IFCR, + &DMA2->IFCR, + &DMA2->IFCR, + &DMA2->IFCR, + &DMA2->IFCR, +#if defined(DMA2_Channel7) + &DMA2->IFCR, +#endif +#if defined(DMA2_Channel8) + &DMA2->IFCR, +#endif + }, +#endif }; - volatile uint32_t* const dmaIFCR[2][7] = { - { &DMA1->IFCR, &DMA1->IFCR, &DMA1->IFCR, &DMA1->IFCR, &DMA1->IFCR, &DMA1->IFCR, &DMA1->IFCR }, - { &DMA2->IFCR, &DMA2->IFCR, &DMA2->IFCR, &DMA2->IFCR, &DMA2->IFCR, &DMA2->IFCR, &DMA2->IFCR } + const std::array DmaChannel + { + std::array + { + DMA1_Channel1, + DMA1_Channel2, + DMA1_Channel3, + DMA1_Channel4, + DMA1_Channel5, + DMA1_Channel6, +#if defined(DMA1_Channel7) + DMA1_Channel7, +#endif +#if defined(DMA1_Channel8) + DMA1_Channel8, +#endif + }, +#if defined(DMA2_Channel1) + std::array + { + DMA2_Channel1, + DMA2_Channel2, + DMA2_Channel3, + DMA2_Channel4, + DMA2_Channel5, + DMA2_Channel6, +#if defined(DMA2_Channel7) + DMA2_Channel7, +#endif +#if defined(DMA2_Channel8) + DMA2_Channel8, +#endif + }, +#endif }; + const std::array dmaIrq + { + std::array + { + DMA1_Channel1_IRQn, + DMA1_Channel2_IRQn, + DMA1_Channel3_IRQn, + DMA1_Channel4_IRQn, + DMA1_Channel5_IRQn, + DMA1_Channel6_IRQn, +#if defined(DMA1_Channel7) + DMA1_Channel7_IRQn, +#endif +#if defined(DMA1_Channel8) + DMA1_Channel8_IRQn, +#endif + }, +#if defined(DMA2_Channel1) + std::array + { + DMA2_Channel1_IRQn, + DMA2_Channel2_IRQn, + DMA2_Channel3_IRQn, + DMA2_Channel4_IRQn, + DMA2_Channel5_IRQn, + DMA2_Channel6_IRQn, +#if defined(DMA2_Channel7) + DMA2_Channel7_IRQn, +#endif +#if defined(DMA2_Channel8) + DMA2_Channel8_IRQn, +#endif + }, #endif + }; -#if defined(STM32WB) - DMA_Channel_TypeDef* const dmaStream[2][7] = { - { DMA1_Channel1, DMA1_Channel2, DMA1_Channel3, DMA1_Channel4, DMA1_Channel5, DMA1_Channel6, DMA1_Channel7 }, - { DMA2_Channel1, DMA2_Channel2, DMA2_Channel3, DMA2_Channel4, DMA2_Channel5, DMA2_Channel6, DMA2_Channel7 } + const std::array streamToTCIF + { + DMA_FLAG_TC1, + DMA_FLAG_TC2, + DMA_FLAG_TC3, + DMA_FLAG_TC4, + DMA_FLAG_TC5, + DMA_FLAG_TC6, +#if defined(DMA_FLAG_TC7) + DMA_FLAG_TC7, +#endif +#if defined(DMA_FLAG_TC8) + DMA_FLAG_TC8, +#endif }; - const IRQn_Type dmaIrq[2][7] = { - { DMA1_Channel1_IRQn, DMA1_Channel2_IRQn, DMA1_Channel3_IRQn, DMA1_Channel4_IRQn, DMA1_Channel5_IRQn, DMA1_Channel6_IRQn, DMA1_Channel7_IRQn }, - { DMA2_Channel1_IRQn, DMA2_Channel2_IRQn, DMA2_Channel3_IRQn, DMA2_Channel4_IRQn, DMA2_Channel5_IRQn, DMA2_Channel6_IRQn, DMA2_Channel7_IRQn } + const std::array streamToHTIF + { + DMA_FLAG_HT1, + DMA_FLAG_HT2, + DMA_FLAG_HT3, + DMA_FLAG_HT4, + DMA_FLAG_HT5, + DMA_FLAG_HT6, +#if defined(DMA_FLAG_HT7) + DMA_FLAG_HT7, +#endif +#if defined(DMA_FLAG_HT8) + DMA_FLAG_HT8, +#endif }; - - const uint32_t streamToTCIF[7] = { DMA_FLAG_TC1, DMA_FLAG_TC2, DMA_FLAG_TC3, DMA_FLAG_TC4, DMA_FLAG_TC5, DMA_FLAG_TC6, DMA_FLAG_TC7 }; - const uint32_t streamToHTIF[7] = { DMA_FLAG_HT1, DMA_FLAG_HT2, DMA_FLAG_HT3, DMA_FLAG_HT4, DMA_FLAG_HT5, DMA_FLAG_HT6, DMA_FLAG_HT7 }; - const uint32_t streamToTEIF[7] = { DMA_FLAG_TE1, DMA_FLAG_TE2, DMA_FLAG_TE3, DMA_FLAG_TE4, DMA_FLAG_TE5, DMA_FLAG_TE6, DMA_FLAG_TE7 }; -#elif defined(STM32G4) - DMA_Channel_TypeDef* const dmaStream[2][6] = { - { DMA1_Channel1, DMA1_Channel2, DMA1_Channel3, DMA1_Channel4, DMA1_Channel5, DMA1_Channel6 }, - { DMA2_Channel1, DMA2_Channel2, DMA2_Channel3, DMA2_Channel4, DMA2_Channel5, DMA2_Channel6 } + const std::array streamToTEIF + { + DMA_FLAG_TE1, + DMA_FLAG_TE2, + DMA_FLAG_TE3, + DMA_FLAG_TE4, + DMA_FLAG_TE5, + DMA_FLAG_TE6, +#if defined(DMA_FLAG_TE7) + DMA_FLAG_TE7, +#endif +#if defined(DMA_FLAG_TE8) + DMA_FLAG_TE8, +#endif }; +#endif - const IRQn_Type dmaIrq[2][7] = { - { DMA1_Channel1_IRQn, DMA1_Channel2_IRQn, DMA1_Channel3_IRQn, DMA1_Channel4_IRQn, DMA1_Channel5_IRQn, DMA1_Channel6_IRQn }, - { DMA2_Channel1_IRQn, DMA2_Channel2_IRQn, DMA2_Channel3_IRQn, DMA2_Channel4_IRQn, DMA2_Channel5_IRQn, DMA2_Channel6_IRQn } - }; + // clang-format on - const uint32_t streamToTCIF[7] = { DMA_FLAG_TC1, DMA_FLAG_TC2, DMA_FLAG_TC3, DMA_FLAG_TC4, DMA_FLAG_TC5, DMA_FLAG_TC6 }; - const uint32_t streamToHTIF[7] = { DMA_FLAG_HT1, DMA_FLAG_HT2, DMA_FLAG_HT3, DMA_FLAG_HT4, DMA_FLAG_HT5, DMA_FLAG_HT6 }; - const uint32_t streamToTEIF[7] = { DMA_FLAG_TE1, DMA_FLAG_TE2, DMA_FLAG_TE3, DMA_FLAG_TE4, DMA_FLAG_TE5, DMA_FLAG_TE6 }; -#endif + static_assert(dmaISR[0].size() == dmaIFCR[0].size()); + static_assert(dmaISR[0].size() == DmaChannel[0].size()); + static_assert(dmaISR[0].size() == dmaIrq[0].size()); + static_assert(dmaISR[0].size() == streamToTCIF.size()); + static_assert(dmaISR[0].size() == streamToHTIF.size()); + static_assert(dmaISR[0].size() == streamToTEIF.size()); uint32_t dummy; } @@ -117,21 +288,48 @@ namespace hal streamAllocation[dmaIndex] &= ~(1 << streamIndex); } - DmaStm::StreamBase::StreamBase(DmaStm& dma, DmaChannelId channelId, volatile void* peripheralAddress) + DmaStm::Stream::Stream(DmaStm& dma, DmaChannelId channelId) : dma(dma) , dmaIndex(channelId.dma) + +#if defined(DMA_STREAM_BASED) , streamIndex(channelId.stream) +#else + , streamIndex(channelId.channel) +#endif { dma.ReserveStream(dmaIndex, streamIndex); + + DMA_HandleTypeDef DmaChannelHandle = {}; + + DmaChannelHandle.Instance = DmaChannel[dmaIndex][streamIndex]; + + DmaChannelHandle.Init.Direction = DMA_MEMORY_TO_PERIPH; + DmaChannelHandle.Init.PeriphInc = DMA_PINC_DISABLE; + DmaChannelHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + DmaChannelHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + DmaChannelHandle.Init.Mode = DMA_NORMAL; + DmaChannelHandle.Init.Priority = DMA_PRIORITY_MEDIUM; +#if defined(DMA_STREAM_BASED) + DmaChannelHandle.Init.Channel = dmaChannel[channelId.channel]; + DmaChannelHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + DmaChannelHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + DmaChannelHandle.Init.MemBurst = DMA_MBURST_SINGLE; + DmaChannelHandle.Init.PeriphBurst = DMA_PBURST_SINGLE; +#else + DmaChannelHandle.Init.Request = channelId.mux; +#endif + + HAL_DMA_Init(&DmaChannelHandle); } - DmaStm::StreamBase::~StreamBase() + DmaStm::Stream::~Stream() { if (streamIndex != 0xff) dma.ReleaseStream(dmaIndex, streamIndex); } - DmaStm::StreamBase::StreamBase(StreamBase&& other) + DmaStm::Stream::Stream(Stream&& other) noexcept : dma(other.dma) , dmaIndex(other.dmaIndex) , streamIndex(other.streamIndex) @@ -139,7 +337,7 @@ namespace hal other.streamIndex = 0xff; } - DmaStm::StreamBase& DmaStm::StreamBase::operator=(StreamBase&& other) + DmaStm::Stream& DmaStm::Stream::operator=(Stream&& other) { dmaIndex = other.dmaIndex; streamIndex = other.streamIndex; @@ -149,19 +347,25 @@ namespace hal return *this; } - uint8_t DmaStm::StreamBase::DataSize() const + uint8_t DmaStm::Stream::DataSize() const { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) - return 1 << ((streamRegister->CR & DMA_SxCR_PSIZE) >> POSITION_VAL(DMA_SxCR_PSIZE)); + return 1 << ((streamRegister->CR & DMA_SxCR_MSIZE) >> POSITION_VAL(DMA_SxCR_MSIZE)); #else - return 1 << ((streamRegister->CCR & DMA_CCR_PSIZE) >> POSITION_VAL(DMA_CCR_PSIZE)); + return 1 << ((streamRegister->CCR & DMA_CCR_MSIZE) >> POSITION_VAL(DMA_CCR_MSIZE)); #endif } - void DmaStm::StreamBase::SetDataSize(uint8_t dataSizeInBytes) + void DmaStm::Stream::SetDataSize(uint8_t dataSizeInBytes) { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + SetPeripheralDataSize(dataSizeInBytes); + SetMemoryDataSize(dataSizeInBytes); + } + + void DmaStm::Stream::SetPeripheralDataSize(uint8_t dataSizeInBytes) + { + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) streamRegister->CR = (streamRegister->CR & ~DMA_SxCR_PSIZE) | ((dataSizeInBytes & 1) == 0 ? DMA_SxCR_PSIZE_0 : 0) | (dataSizeInBytes > 2 ? DMA_SxCR_PSIZE_1 : 0); #else @@ -169,9 +373,19 @@ namespace hal #endif } - bool DmaStm::StreamBase::StopTransfer() + void DmaStm::Stream::SetMemoryDataSize(uint8_t dataSizeInBytes) + { + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; +#if defined(STM32F7) || defined(STM32F4) + streamRegister->CR = (streamRegister->CR & ~DMA_SxCR_MSIZE) | ((dataSizeInBytes & 1) == 0 ? DMA_SxCR_MSIZE_0 : 0) | (dataSizeInBytes > 2 ? DMA_SxCR_MSIZE_1 : 0); +#else + streamRegister->CCR = (streamRegister->CCR & ~DMA_CCR_MSIZE) | ((dataSizeInBytes & 1) == 0 ? DMA_CCR_MSIZE_0 : 0) | (dataSizeInBytes > 2 ? DMA_CCR_MSIZE_1 : 0); +#endif + } + + bool DmaStm::Stream::StopTransfer() { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; bool finished = Finished(); DisableHalfTransferCompleteInterrupt(); DisableTransferCompleteInterrupt(); @@ -180,9 +394,9 @@ namespace hal return !finished; } - void DmaStm::StreamBase::Disable() + void DmaStm::Stream::Disable() { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) streamRegister->CR &= ~DMA_SxCR_EN; #else @@ -190,9 +404,9 @@ namespace hal #endif } - void DmaStm::StreamBase::DisableHalfTransferCompleteInterrupt() + void DmaStm::Stream::DisableHalfTransferCompleteInterrupt() { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) streamRegister->CR &= ~DMA_IT_HT; #else @@ -200,9 +414,9 @@ namespace hal #endif } - void DmaStm::StreamBase::DisableMemoryIncrement() + void DmaStm::Stream::DisableMemoryIncrement() { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) streamRegister->CR &= ~DMA_MINC_ENABLE; #else @@ -210,9 +424,9 @@ namespace hal #endif } - void DmaStm::StreamBase::DisableTransferCompleteInterrupt() + void DmaStm::Stream::DisableTransferCompleteInterrupt() { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) streamRegister->CR &= ~DMA_IT_TC; #else @@ -220,9 +434,19 @@ namespace hal #endif } - void DmaStm::StreamBase::Enable() + void DmaStm::Stream::DisableCircularMode() { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; +#if defined(STM32F7) || defined(STM32F4) + streamRegister->CR &= ~DMA_SxCR_CIRC; +#else + streamRegister->CCR &= ~DMA_CCR_CIRC; +#endif + } + + void DmaStm::Stream::Enable() + { + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) streamRegister->CR |= DMA_SxCR_EN; #else @@ -230,9 +454,9 @@ namespace hal #endif } - void DmaStm::StreamBase::EnableHalfTransferCompleteInterrupt() + void DmaStm::Stream::EnableHalfTransferCompleteInterrupt() { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) streamRegister->CR |= DMA_IT_HT; #else @@ -240,9 +464,9 @@ namespace hal #endif } - void DmaStm::StreamBase::EnableMemoryIncrement() + void DmaStm::Stream::EnableMemoryIncrement() { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) streamRegister->CR |= DMA_MINC_ENABLE; #else @@ -250,9 +474,9 @@ namespace hal #endif } - void DmaStm::StreamBase::EnableTransferCompleteInterrupt() + void DmaStm::Stream::EnableTransferCompleteInterrupt() { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) streamRegister->CR |= DMA_IT_TC; #else @@ -260,9 +484,19 @@ namespace hal #endif } - bool DmaStm::StreamBase::Finished() const + void DmaStm::Stream::EnableCircularMode() + { + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; +#if defined(STM32F7) || defined(STM32F4) + streamRegister->CR |= DMA_SxCR_CIRC; +#else + streamRegister->CCR |= DMA_CCR_CIRC; +#endif + } + + bool DmaStm::Stream::Finished() const { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) return (streamRegister->CR & DMA_SxCR_EN) == 0; #else @@ -271,9 +505,9 @@ namespace hal #endif } - void DmaStm::StreamBase::SetMemoryAddress(const void* memoryAddress) + void DmaStm::Stream::SetMemoryAddress(const void* memoryAddress) { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) streamRegister->M0AR = reinterpret_cast(memoryAddress); #else @@ -281,9 +515,9 @@ namespace hal #endif } - void DmaStm::StreamBase::SetMemoryToPeripheralMode() + void DmaStm::Stream::SetMemoryToPeripheralMode() { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) streamRegister->CR |= DMA_MEMORY_TO_PERIPH; #else @@ -291,9 +525,9 @@ namespace hal #endif } - void DmaStm::StreamBase::SetPeripheralAddress(volatile void* peripheralAddress) + void DmaStm::Stream::SetPeripheralAddress(volatile void* peripheralAddress) { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) streamRegister->PAR = reinterpret_cast(peripheralAddress); #else @@ -301,9 +535,9 @@ namespace hal #endif } - void DmaStm::StreamBase::SetPeripheralToMemoryMode() + void DmaStm::Stream::SetPeripheralToMemoryMode() { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) streamRegister->CR &= ~DMA_MEMORY_TO_PERIPH; #else @@ -311,9 +545,9 @@ namespace hal #endif } - void DmaStm::StreamBase::SetTransferSize(uint16_t size) + void DmaStm::Stream::SetTransferSize(uint16_t size) { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; #if defined(STM32F7) || defined(STM32F4) streamRegister->NDTR = size / DataSize(); #else @@ -321,200 +555,242 @@ namespace hal #endif } - DmaStm::Stream::Stream(DmaStm& dma, DmaChannelId channelId, volatile void* peripheralAddress, infra::Function actionOnTransferComplete) - : StreamBase(dma, channelId, peripheralAddress) - , actionOnTransferComplete(actionOnTransferComplete) - , interruptHandler(hal::dmaIrq[dmaIndex][streamIndex], [this]() - { - OnInterrupt(); - }) + bool DmaStm::Stream::IsHalfComplete() const { - DMA_HandleTypeDef dmaStreamHandle = {}; - - dmaStreamHandle.Instance = dmaStream[dmaIndex][streamIndex]; - - dmaStreamHandle.Init.Direction = DMA_MEMORY_TO_PERIPH; - dmaStreamHandle.Init.PeriphInc = DMA_PINC_DISABLE; - dmaStreamHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - dmaStreamHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - dmaStreamHandle.Init.Mode = DMA_NORMAL; - dmaStreamHandle.Init.Priority = DMA_PRIORITY_MEDIUM; -#if defined(STM32F7) || defined(STM32F4) - dmaStreamHandle.Init.Channel = dmaChannel[channelId.channel]; - dmaStreamHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - dmaStreamHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - dmaStreamHandle.Init.MemBurst = DMA_MBURST_SINGLE; - dmaStreamHandle.Init.PeriphBurst = DMA_PBURST_SINGLE; -#else - dmaStreamHandle.Init.Request = channelId.channel; -#endif - - HAL_DMA_Init(&dmaStreamHandle); - SetPeripheralAddress(peripheralAddress); + return *dmaISR[dmaIndex][streamIndex] & streamToHTIF[streamIndex]; } - DmaStm::Stream::Stream(Stream&& other) - : StreamBase(std::move(other)) - , interruptHandler(std::move(other.interruptHandler), [this]() - { - OnInterrupt(); - }) - , actionOnTransferComplete(other.actionOnTransferComplete) + bool DmaStm::Stream::IsFullComplete() const { - other.actionOnTransferComplete = nullptr; + return *dmaISR[dmaIndex][streamIndex] & streamToTCIF[streamIndex]; } - DmaStm::Stream& DmaStm::Stream::operator=(Stream&& other) + void DmaStm::Stream::ClearHalfComplete() const { - StreamBase::operator=(std::move(other)); - - actionOnTransferComplete = other.actionOnTransferComplete; - interruptHandler.Assign(std::move(other.interruptHandler), [this]() - { - OnInterrupt(); - }); - - other.actionOnTransferComplete = nullptr; + *dmaIFCR[dmaIndex][streamIndex] |= streamToHTIF[streamIndex]; + } - return *this; + void DmaStm::Stream::ClearFullComplete() const + { + *dmaIFCR[dmaIndex][streamIndex] |= streamToTCIF[streamIndex]; } - void DmaStm::Stream::StartTransmit(infra::ConstByteRange data) + size_t DmaStm::Stream::BytesToTransfer() const { - assert(data.size() <= 65535); - assert(!data.empty()); - __DMB(); + auto streamRegister = DmaChannel[dmaIndex][streamIndex]; +#if defined(STM32F7) || defined(STM32F4) + return streamRegister->NDTR * DataSize(); +#else + return streamRegister->CNDTR * DataSize(); +#endif + } + void DmaStm::TransceiveStream::StartTransmit(infra::ConstByteRange data) + { SetMemoryToPeripheralMode(); EnableMemoryIncrement(); SetTransferSize(data.size()); SetMemoryAddress(data.begin()); - EnableTransferCompleteInterrupt(); Enable(); } - void DmaStm::Stream::StartTransmitDummy(uint16_t size) + void DmaStm::TransceiveStream::StartTransmitDummy(uint16_t size) { - DisableMemoryIncrement(); SetMemoryToPeripheralMode(); + DisableMemoryIncrement(); SetTransferSize(size); SetMemoryAddress(&dummy); - EnableTransferCompleteInterrupt(); Enable(); } - void DmaStm::Stream::StartReceive(infra::ByteRange data) + void DmaStm::TransceiveStream::StartReceive(infra::ByteRange data) { - assert(data.size() <= 65535); + this->data = data; + SetPeripheralToMemoryMode(); EnableMemoryIncrement(); SetTransferSize(data.size()); SetMemoryAddress(data.begin()); - EnableTransferCompleteInterrupt(); Enable(); } - void DmaStm::Stream::StartReceiveDummy(uint16_t size) + void DmaStm::TransceiveStream::StartReceiveDummy(uint16_t size) { SetPeripheralToMemoryMode(); DisableMemoryIncrement(); SetTransferSize(size); SetMemoryAddress(&dummy); - EnableTransferCompleteInterrupt(); Enable(); } - void DmaStm::Stream::OnInterrupt() + size_t DmaStm::TransceiveStream::ReceivedSize() const + { + return (data.size() - BytesToTransfer()) / DataSize(); + } + + DmaStm::StreamInterruptHandler::StreamInterruptHandler(Stream& stream, const infra::Function& transferFullComplete) + : stream{ stream } + , dispatchedInterruptHandler{ dmaIrq[stream.dmaIndex][stream.streamIndex], [this] + { + OnInterrupt(); + } } + , transferFullComplete{ transferFullComplete } + { + stream.DisableCircularMode(); + stream.EnableTransferCompleteInterrupt(); + } + + void DmaStm::StreamInterruptHandler::OnInterrupt() { - if (*dmaISR[dmaIndex][streamIndex] & streamToTCIF[streamIndex]) + if (stream.IsFullComplete()) { - *dmaIFCR[dmaIndex][streamIndex] |= streamToTCIF[streamIndex]; - Disable(); + stream.ClearFullComplete(); + + stream.Disable(); __DMB(); - interruptHandler.ClearPending(); - actionOnTransferComplete(); + dispatchedInterruptHandler.ClearPending(); + transferFullComplete(); } } - DmaStm::CircularStream::CircularStream(DmaStm& dma, DmaChannelId channelId, volatile void* peripheralAddress, infra::Function actionOnFirstHalfDone, infra::Function actionOnSecondHalfDone) - : StreamBase(dma, channelId, peripheralAddress) - , actionOnFirstHalfDone(actionOnFirstHalfDone) - , actionOnSecondHalfDone(actionOnSecondHalfDone) - , interruptHandler(hal::dmaIrq[dmaIndex][streamIndex], [this]() - { - OnInterrupt(); - }) + DmaStm::CircularStreamInterruptHandler::CircularStreamInterruptHandler(Stream& stream, const infra::Function& transferHalfComplete, const infra::Function& transferFullComplete) + : stream{ stream } + , immediateInterruptHandler{ dmaIrq[stream.dmaIndex][stream.streamIndex], [this] + { + OnInterrupt(); + } } + , transferHalfComplete{ transferHalfComplete } + , transferFullComplete{ transferFullComplete } { - DMA_HandleTypeDef dmaStreamHandle = {}; + stream.EnableCircularMode(); + stream.EnableHalfTransferCompleteInterrupt(); + stream.EnableTransferCompleteInterrupt(); + } - dmaStreamHandle.Instance = dmaStream[dmaIndex][streamIndex]; + bool DmaStm::CircularStreamInterruptHandler::IsInterruptPending() const + { + return stream.IsHalfComplete() || stream.IsFullComplete(); + } - dmaStreamHandle.Init.Direction = DMA_MEMORY_TO_PERIPH; - dmaStreamHandle.Init.PeriphInc = DMA_PINC_DISABLE; - dmaStreamHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - dmaStreamHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - dmaStreamHandle.Init.Mode = DMA_CIRCULAR; - dmaStreamHandle.Init.Priority = DMA_PRIORITY_MEDIUM; -#if defined(STM32F7) || defined(STM32F4) - dmaStreamHandle.Init.Channel = dmaChannel[channelId.channel]; - dmaStreamHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; - dmaStreamHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - dmaStreamHandle.Init.MemBurst = DMA_MBURST_SINGLE; - dmaStreamHandle.Init.PeriphBurst = DMA_PBURST_SINGLE; -#else - dmaStreamHandle.Init.Request = channelId.channel; -#endif + void DmaStm::CircularStreamInterruptHandler::OnInterrupt() + { + if (stream.IsHalfComplete()) + { + stream.ClearHalfComplete(); + + immediateInterruptHandler.ClearPending(); + + transferHalfComplete(); + } - HAL_DMA_Init(&dmaStreamHandle); - SetPeripheralAddress(peripheralAddress); + if (stream.IsFullComplete()) + { + stream.ClearFullComplete(); + + immediateInterruptHandler.ClearPending(); + + transferFullComplete(); + } } - size_t DmaStm::CircularStream::ReceivedSize() const + DmaStm::PeripheralTransceiveStream::PeripheralTransceiveStream(TransceiveStream& stream, volatile void* peripheralAddress, uint8_t peripheralTransferSize) + : stream{ stream } { - auto streamRegister = dmaStream[dmaIndex][streamIndex]; -#if defined(STM32F7) || defined(STM32F4) - size_t bytesToTransfer = streamRegister->NDTR * DataSize(); -#else - size_t bytesToTransfer = streamRegister->CNDTR * DataSize(); -#endif + stream.SetPeripheralAddress(peripheralAddress); + stream.SetPeripheralDataSize(peripheralTransferSize); + } - return data.size() - bytesToTransfer; + void DmaStm::PeripheralTransceiveStream::SetPeripheralTransferSize(uint8_t peripheralTransferSize) + { + stream.SetPeripheralDataSize(peripheralTransferSize); } - void DmaStm::CircularStream::StartReceive(infra::ByteRange data) + bool DmaStm::PeripheralTransceiveStream::StopTransfer() { - assert(data.size() <= 65535); + return stream.StopTransfer(); + } - this->data = data; + void DmaStm::PeripheralTransceiveStream::StartTransmitDummy(uint16_t size, uint8_t dataSize) + { + stream.SetMemoryDataSize(dataSize); + stream.StartTransmitDummy(size); + } - SetPeripheralToMemoryMode(); - EnableMemoryIncrement(); - SetTransferSize(data.size()); - SetMemoryAddress(data.begin()); - EnableTransferCompleteInterrupt(); - EnableHalfTransferCompleteInterrupt(); - Enable(); + void DmaStm::PeripheralTransceiveStream::StartReceiveDummy(uint16_t size, uint8_t dataSize) + { + stream.SetMemoryDataSize(dataSize); + stream.StartReceiveDummy(size); } - void DmaStm::CircularStream::OnInterrupt() + size_t DmaStm::PeripheralTransceiveStream::ReceivedSize() const { - if (*dmaISR[dmaIndex][streamIndex] & streamToTCIF[streamIndex]) - { - *dmaIFCR[dmaIndex][streamIndex] |= streamToTCIF[streamIndex]; + return stream.ReceivedSize(); + } - interruptHandler.ClearPending(); - actionOnSecondHalfDone(); - } - else if (*dmaISR[dmaIndex][streamIndex] & streamToHTIF[streamIndex]) - { - *dmaIFCR[dmaIndex][streamIndex] |= streamToHTIF[streamIndex]; + /////////////////////////////// - interruptHandler.ClearPending(); - actionOnFirstHalfDone(); - } + TransceiverDmaChannelBase::TransceiverDmaChannelBase(DmaStm::TransceiveStream& stream, volatile void* peripheralAddress, uint8_t peripheralTransferSize) + : peripheralStream{ stream, peripheralAddress, peripheralTransferSize } + { + } + + bool TransceiverDmaChannelBase::StopTransfer() + { + return peripheralStream.StopTransfer(); + } + + void TransceiverDmaChannelBase::SetPeripheralTransferSize(uint8_t peripheralTransferSize) + { + peripheralStream.SetPeripheralTransferSize(peripheralTransferSize); + } + + void TransceiverDmaChannelBase::StartTransmitDummy(uint16_t size, uint8_t dataSize) + { + peripheralStream.StartTransmitDummy(size, dataSize); + } + + size_t TransceiverDmaChannelBase::ReceivedSize() const + { + return peripheralStream.ReceivedSize(); + } + + void TransceiverDmaChannelBase::StartReceiveDummy(uint16_t size, uint8_t dataSize) + { + peripheralStream.StartReceiveDummy(size, dataSize); } + + TransceiverDmaChannel::TransceiverDmaChannel(DmaStm::TransceiveStream& stream, volatile void* peripheralAddress, uint8_t peripheralTransferSize, const infra::Function& transferFullComplete) + : TransceiverDmaChannelBase{ stream, peripheralAddress, peripheralTransferSize } + , streamInterruptHandler{ stream, transferFullComplete } + {} + + TransmitDmaChannel::TransmitDmaChannel(DmaStm::TransmitStream& stream, volatile void* peripheralAddress, uint8_t peripheralTransferSize, const infra::Function& transferFullComplete) + : TransceiverDmaChannel{ stream, peripheralAddress, peripheralTransferSize, transferFullComplete } + {} + + ReceiveDmaChannel::ReceiveDmaChannel(DmaStm::ReceiveStream& stream, volatile void* peripheralAddress, uint8_t peripheralTransferSize, const infra::Function& transferFullComplete) + : TransceiverDmaChannel{ stream, peripheralAddress, peripheralTransferSize, transferFullComplete } + {} + + CircularTransceiverDmaChannel::CircularTransceiverDmaChannel(DmaStm::TransceiveStream& stream, volatile void* peripheralAddress, uint8_t peripheralTransferSize, const infra::Function& transferHalfComplete, const infra::Function& transferFullComplete) + : TransceiverDmaChannelBase{ stream, peripheralAddress, peripheralTransferSize } + , circularStreamInterruptHandler{ stream, transferHalfComplete, transferFullComplete } + {} + + bool CircularTransceiverDmaChannel::IsInterruptPending() const + { + return circularStreamInterruptHandler.IsInterruptPending(); + } + + CircularTransmitDmaChannel::CircularTransmitDmaChannel(DmaStm::TransmitStream& stream, volatile void* peripheralAddress, uint8_t peripheralTransferSize, const infra::Function& transferHalfComplete, const infra::Function& transferFullComplete) + : CircularTransceiverDmaChannel{ stream, peripheralAddress, peripheralTransferSize, transferHalfComplete, transferFullComplete } + {} + + CircularReceiveDmaChannel::CircularReceiveDmaChannel(DmaStm::ReceiveStream& stream, volatile void* peripheralAddress, uint8_t peripheralTransferSize, const infra::Function& transferHalfComplete, const infra::Function& transferFullComplete) + : CircularTransceiverDmaChannel{ stream, peripheralAddress, peripheralTransferSize, transferHalfComplete, transferFullComplete } + {} } #endif diff --git a/hal_st/stm32fxxx/DmaStm.hpp b/hal_st/stm32fxxx/DmaStm.hpp index 8adb8446..ec745608 100644 --- a/hal_st/stm32fxxx/DmaStm.hpp +++ b/hal_st/stm32fxxx/DmaStm.hpp @@ -5,9 +5,18 @@ #include "hal_st/cortex/InterruptCortex.hpp" #include "infra/util/ByteRange.hpp" #include "infra/util/Function.hpp" +#include "infra/util/MemoryRange.hpp" +#include namespace hal { +#if defined(STM32G0) || defined(STM32G4) || defined(STM32WB) +#define DMA_CHANNEL_BASED +#else +#define DMA_STREAM_BASED +#endif + +#if defined(DMA_STREAM_BASED) struct DmaChannelId { constexpr DmaChannelId(uint8_t oneBasedDma, uint8_t stream, uint8_t channel) @@ -20,39 +29,65 @@ namespace hal uint8_t stream; uint8_t channel; }; +#else + struct DmaChannelId + { + constexpr DmaChannelId(uint8_t oneBasedDma, uint8_t oneBasedChannel, uint8_t mux) + : dma{ static_cast(oneBasedDma - 1) } + , channel{ static_cast(oneBasedChannel - 1) } + , mux{ mux } + {} + + uint8_t dma; + uint8_t channel; + uint8_t mux; + }; +#endif + + class TransceiverDmaChannel; + class CircularTransceiverDmaChannel; + + class TransmitDmaChannel; + class ReceiveDmaChannel; + + class CircularTransmitDmaChannel; + class CircularReceiveDmaChannel; class DmaStm { public: - class StreamBase + class Stream { + public: + Stream(DmaStm& dma, DmaChannelId channelId); + protected: - StreamBase(DmaStm& dma, DmaChannelId channelId, volatile void* peripheralAddress); - StreamBase(const StreamBase&) = delete; - StreamBase(StreamBase&& other); - virtual ~StreamBase(); + Stream(const Stream&) = delete; + Stream(Stream&& other) noexcept; + virtual ~Stream(); public: uint8_t DataSize() const; void SetDataSize(uint8_t dataSizeInBytes); + void SetPeripheralDataSize(uint8_t dataSizeInBytes); + void SetMemoryDataSize(uint8_t dataSizeInBytes); bool StopTransfer(); protected: - StreamBase& operator=(const StreamBase&) = delete; - StreamBase& operator=(StreamBase&& other); - virtual void OnInterrupt() = 0; - - private: - friend class DmaStm; + Stream& operator=(const Stream&) = delete; + Stream& operator=(Stream&& other); + protected: void Disable(); void DisableHalfTransferCompleteInterrupt(); void DisableMemoryIncrement(); void DisableTransferCompleteInterrupt(); + void DisableCircularMode(); void Enable(); void EnableHalfTransferCompleteInterrupt(); void EnableMemoryIncrement(); void EnableTransferCompleteInterrupt(); + void EnableCircularMode(); bool Finished() const; void SetMemoryAddress(const void* memoryAddress); void SetMemoryToPeripheralMode(); @@ -60,54 +95,146 @@ namespace hal void SetPeripheralToMemoryMode(); void SetTransferSize(uint16_t size); + bool IsHalfComplete() const; + bool IsFullComplete() const; + + void ClearHalfComplete() const; + void ClearFullComplete() const; + + size_t BytesToTransfer() const; + private: + friend DmaStm; + DmaStm& dma; uint8_t dmaIndex; uint8_t streamIndex = 0xff; }; - class Stream - : public StreamBase + class TransceiveStream + : private Stream { public: - Stream(DmaStm& dma, DmaChannelId channelId, volatile void* peripheralAddress, infra::Function actionOnTransferComplete); - Stream(const Stream&) = delete; - Stream(Stream&& other); - - Stream& operator=(const Stream&) = delete; - Stream& operator=(Stream&& other); + using Stream::Stream; void StartTransmit(infra::ConstByteRange data); void StartTransmitDummy(uint16_t size); void StartReceive(infra::ByteRange data); void StartReceiveDummy(uint16_t size); + size_t ReceivedSize() const; - protected: - void OnInterrupt() override; + friend DmaStm; + friend TransceiverDmaChannel; + friend CircularTransceiverDmaChannel; private: - DispatchedInterruptHandler interruptHandler; - infra::Function actionOnTransferComplete; + infra::ByteRange data; }; - class CircularStream - : public StreamBase + class TransmitStream : private TransceiveStream { public: - CircularStream(DmaStm& dma, DmaChannelId channelId, volatile void* peripheralAddress, infra::Function actionOnFirstHalfDone, infra::Function actionOnSecondHalfDone); + using TransceiveStream::TransceiveStream; - std::size_t ReceivedSize() const; - void StartReceive(infra::ByteRange data); + using TransceiveStream::StartTransmit; + using TransceiveStream::StartTransmitDummy; - protected: - void OnInterrupt() override; + friend TransmitDmaChannel; + friend CircularTransmitDmaChannel; + }; + + class ReceiveStream : private TransceiveStream + { + public: + using TransceiveStream::TransceiveStream; + + using TransceiveStream::ReceivedSize; + using TransceiveStream::StartReceive; + using TransceiveStream::StartReceiveDummy; + + friend ReceiveDmaChannel; + friend CircularReceiveDmaChannel; + }; + + class StreamInterruptHandler + { + public: + StreamInterruptHandler(Stream& stream, const infra::Function& transferFullComplete); private: - ImmediateInterruptHandler interruptHandler; - infra::Function actionOnFirstHalfDone; - infra::Function actionOnSecondHalfDone; + void OnInterrupt(); - infra::ByteRange data; + Stream& stream; + + DispatchedInterruptHandler dispatchedInterruptHandler; + + infra::Function transferFullComplete; + }; + + class CircularStreamInterruptHandler + { + public: + CircularStreamInterruptHandler(Stream& stream, const infra::Function& transferHalfComplete, const infra::Function& transferFullComplete); + + bool IsInterruptPending() const; + + private: + void OnInterrupt(); + + Stream& stream; + + ImmediateInterruptHandler immediateInterruptHandler; + + infra::Function transferHalfComplete; + infra::Function transferFullComplete; + }; + + class PeripheralTransceiveStream + { + public: + PeripheralTransceiveStream(TransceiveStream& stream, volatile void* peripheralAddress, uint8_t peripheralTransferSize); + + void SetPeripheralTransferSize(uint8_t peripheralTransferSize); + bool StopTransfer(); + + template + void StartTransmit(infra::MemoryRange data); + void StartTransmitDummy(uint16_t size, uint8_t dataSize = 1); + + template + void StartReceive(infra::MemoryRange data); + void StartReceiveDummy(uint16_t size, uint8_t dataSize = 1); + + size_t ReceivedSize() const; + + private: + TransceiveStream& stream; + }; + + class PeripheralTransmitStream : private PeripheralTransceiveStream + { + public: + using PeripheralTransceiveStream::PeripheralTransceiveStream; + + using PeripheralTransceiveStream::SetPeripheralTransferSize; + using PeripheralTransceiveStream::StopTransfer; + + using PeripheralTransceiveStream::StartTransmit; + using PeripheralTransceiveStream::StartTransmitDummy; + }; + + class PeripheralReceiveStream : private PeripheralTransceiveStream + { + public: + using PeripheralTransceiveStream::PeripheralTransceiveStream; + + using PeripheralTransceiveStream::SetPeripheralTransferSize; + using PeripheralTransceiveStream::StopTransfer; + + using PeripheralTransceiveStream::StartReceive; + using PeripheralTransceiveStream::StartReceiveDummy; + + using PeripheralTransceiveStream::ReceivedSize; }; public: @@ -121,6 +248,147 @@ namespace hal private: std::array streamAllocation = { { 0, 0 } }; }; + + class TransceiverDmaChannelBase + { + public: + TransceiverDmaChannelBase(DmaStm::TransceiveStream& stream, volatile void* peripheralAddress, uint8_t peripheralTransferSize); + + bool StopTransfer(); + void SetPeripheralTransferSize(uint8_t peripheralTransferSize); + + template + void StartTransmit(infra::MemoryRange data); + void StartTransmitDummy(uint16_t size, uint8_t dataSize = 1); + + template + void StartReceive(infra::MemoryRange data); + void StartReceiveDummy(uint16_t size, uint8_t dataSize = 1); + + size_t ReceivedSize() const; + + private: + DmaStm::PeripheralTransceiveStream peripheralStream; + }; + + class TransceiverDmaChannel : public TransceiverDmaChannelBase + { + public: + TransceiverDmaChannel(DmaStm::TransceiveStream& receiveStream, volatile void* peripheralAddress, uint8_t peripheralTransferSize, const infra::Function& transferFullComplete); + + private: + DmaStm::StreamInterruptHandler streamInterruptHandler; + }; + + class TransmitDmaChannel : private TransceiverDmaChannel + { + public: + TransmitDmaChannel(DmaStm::TransmitStream& transmitStream, volatile void* peripheralAddress, uint8_t peripheralTransferSize, const infra::Function& transferFullComplete); + + using TransceiverDmaChannel::SetPeripheralTransferSize; + using TransceiverDmaChannel::StopTransfer; + + using TransceiverDmaChannel::StartTransmit; + using TransceiverDmaChannel::StartTransmitDummy; + + using TransceiverDmaChannel::StartReceive; + using TransceiverDmaChannel::StartReceiveDummy; + + using TransceiverDmaChannel::ReceivedSize; + }; + + class ReceiveDmaChannel : private TransceiverDmaChannel + { + public: + ReceiveDmaChannel(DmaStm::ReceiveStream& receiveStream, volatile void* peripheralAddress, uint8_t peripheralTransferSize, const infra::Function& transferFullComplete); + + using TransceiverDmaChannel::SetPeripheralTransferSize; + using TransceiverDmaChannel::StopTransfer; + + using TransceiverDmaChannel::StartTransmit; + using TransceiverDmaChannel::StartTransmitDummy; + + using TransceiverDmaChannel::StartReceive; + using TransceiverDmaChannel::StartReceiveDummy; + + using TransceiverDmaChannel::ReceivedSize; + }; + + class CircularTransceiverDmaChannel : public TransceiverDmaChannelBase + { + public: + CircularTransceiverDmaChannel(DmaStm::TransceiveStream& stream, volatile void* peripheralAddress, uint8_t peripheralTransferSize, const infra::Function& transferHalfComplete, const infra::Function& transferFullComplete); + + bool IsInterruptPending() const; + + private: + DmaStm::CircularStreamInterruptHandler circularStreamInterruptHandler; + }; + + class CircularTransmitDmaChannel : private CircularTransceiverDmaChannel + { + public: + CircularTransmitDmaChannel(DmaStm::TransmitStream& stream, volatile void* peripheralAddress, uint8_t peripheralTransferSize, const infra::Function& transferHalfComplete, const infra::Function& transferFullComplete); + + using CircularTransceiverDmaChannel::SetPeripheralTransferSize; + using CircularTransceiverDmaChannel::StopTransfer; + + using CircularTransceiverDmaChannel::StartTransmit; + using CircularTransceiverDmaChannel::StartTransmitDummy; + + using CircularTransceiverDmaChannel::StartReceive; + using CircularTransceiverDmaChannel::StartReceiveDummy; + + using CircularTransceiverDmaChannel::ReceivedSize; + }; + + class CircularReceiveDmaChannel : private CircularTransceiverDmaChannel + { + public: + CircularReceiveDmaChannel(DmaStm::ReceiveStream& stream, volatile void* peripheralAddress, uint8_t peripheralTransferSize, const infra::Function& transferHalfComplete, const infra::Function& transferFullComplete); + + using CircularTransceiverDmaChannel::SetPeripheralTransferSize; + using CircularTransceiverDmaChannel::StopTransfer; + + using CircularTransceiverDmaChannel::StartTransmit; + using CircularTransceiverDmaChannel::StartTransmitDummy; + + using CircularTransceiverDmaChannel::StartReceive; + using CircularTransceiverDmaChannel::StartReceiveDummy; + + using CircularTransceiverDmaChannel::ReceivedSize; + + using CircularTransceiverDmaChannel::IsInterruptPending; + }; + + //// Implementation //// + + template + void DmaStm::PeripheralTransceiveStream::StartTransmit(infra::MemoryRange data) + { + stream.SetMemoryDataSize(sizeof(U)); + stream.StartTransmit(infra::ReinterpretCastByteRange(data)); + } + + template + void DmaStm::PeripheralTransceiveStream::StartReceive(infra::MemoryRange data) + { + stream.SetMemoryDataSize(sizeof(U)); + stream.StartReceive(infra::ReinterpretCastByteRange(data)); + } + + template + void TransceiverDmaChannelBase::StartTransmit(infra::MemoryRange data) + { + peripheralStream.StartTransmit(data); + } + + template + void TransceiverDmaChannelBase::StartReceive(infra::MemoryRange data) + { + peripheralStream.StartReceive(data); + } + } #endif diff --git a/hal_st/stm32fxxx/QuadSpiStmDma.cpp b/hal_st/stm32fxxx/QuadSpiStmDma.cpp index d52fbc5c..c5c53266 100644 --- a/hal_st/stm32fxxx/QuadSpiStmDma.cpp +++ b/hal_st/stm32fxxx/QuadSpiStmDma.cpp @@ -4,23 +4,14 @@ namespace hal { - namespace - { -#if defined(STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) || defined(STM32F777xx) || defined(STM32F779xx) - const DmaChannelId quadSpiDmaChannel{ 2, 2, 11 }; -#else - const DmaChannelId quadSpiDmaChannel{ 2, 7, 3 }; -#endif - } - - QuadSpiStmDma::QuadSpiStmDma(hal::DmaStm& dma, GpioPinStm& clock, GpioPinStm& slaveSelect, GpioPinStm& data0, GpioPinStm& data1, GpioPinStm& data2, GpioPinStm& data3, const Config& config) + QuadSpiStmDma::QuadSpiStmDma(hal::DmaStm::TransceiveStream& transceiveStream, GpioPinStm& clock, GpioPinStm& slaveSelect, GpioPinStm& data0, GpioPinStm& data1, GpioPinStm& data2, GpioPinStm& data3, const Config& config) : clock(clock, PinConfigTypeStm::quadSpiClock, 0) , slaveSelect(slaveSelect, PinConfigTypeStm::quadSpiSlaveSelect, 0) , data0(data0, PinConfigTypeStm::quadSpiData0, 0) , data1(data1, PinConfigTypeStm::quadSpiData1, 0) , data2(data2, PinConfigTypeStm::quadSpiData2, 0) , data3(data3, PinConfigTypeStm::quadSpiData3, 0) - , dmaStream(dma, quadSpiDmaChannel, &QUADSPI->DR, [this]() + , dmaStream(transceiveStream, &QUADSPI->DR, 1, [this]() { OnDmaTransferDone(); }) diff --git a/hal_st/stm32fxxx/QuadSpiStmDma.hpp b/hal_st/stm32fxxx/QuadSpiStmDma.hpp index 9fbe7638..632ae00b 100644 --- a/hal_st/stm32fxxx/QuadSpiStmDma.hpp +++ b/hal_st/stm32fxxx/QuadSpiStmDma.hpp @@ -24,7 +24,7 @@ namespace hal public: using Config = QuadSpiStmDmaConfig; - QuadSpiStmDma(hal::DmaStm& dma, GpioPinStm& clock, GpioPinStm& slaveSelect, GpioPinStm& data0, GpioPinStm& data1, GpioPinStm& data2, GpioPinStm& data3, const Config& config = Config()); + QuadSpiStmDma(hal::DmaStm::TransceiveStream& transceiveStream, GpioPinStm& clock, GpioPinStm& slaveSelect, GpioPinStm& data0, GpioPinStm& data1, GpioPinStm& data2, GpioPinStm& data3, const Config& config = Config()); ~QuadSpiStmDma(); void SendData(const Header& header, infra::ConstByteRange data, Lines lines, const infra::Function& actionOnCompletion) override; @@ -52,7 +52,7 @@ namespace hal PeripheralPinStm data3; infra::AutoResetFunction onDone; - hal::DmaStm::Stream dmaStream; + hal::TransceiverDmaChannel dmaStream; DispatchedInterruptHandler interruptHandler; }; } diff --git a/hal_st/stm32fxxx/SpiDataSizeConfiguratorStm.cpp b/hal_st/stm32fxxx/SpiDataSizeConfiguratorStm.cpp index 9a811c7f..9350ae3a 100644 --- a/hal_st/stm32fxxx/SpiDataSizeConfiguratorStm.cpp +++ b/hal_st/stm32fxxx/SpiDataSizeConfiguratorStm.cpp @@ -11,7 +11,7 @@ namespace hal void SpiDataSizeConfiguratorStm::ActivateConfiguration() { oldDataSize = spi.DataSize(); - spi.SetDataSize(16); + spi.SetDataSize(dataSize); } void SpiDataSizeConfiguratorStm::DeactivateConfiguration() diff --git a/hal_st/stm32fxxx/SpiMasterStmDma.cpp b/hal_st/stm32fxxx/SpiMasterStmDma.cpp index 0159e4c0..e05b01bb 100644 --- a/hal_st/stm32fxxx/SpiMasterStmDma.cpp +++ b/hal_st/stm32fxxx/SpiMasterStmDma.cpp @@ -3,29 +3,19 @@ namespace hal { - namespace - { - const std::array, 6> defaultDmaChannelId = { { std::make_pair(DmaChannelId{ 2, 3, 3 }, DmaChannelId{ 2, 0, 3 }), - std::make_pair(DmaChannelId{ 1, 4, 0 }, DmaChannelId{ 1, 3, 0 }), - std::make_pair(DmaChannelId{ 1, 5, 0 }, DmaChannelId{ 1, 0, 0 }), - std::make_pair(DmaChannelId{ 2, 1, 4 }, DmaChannelId{ 2, 0, 4 }), - std::make_pair(DmaChannelId{ 2, 4, 2 }, DmaChannelId{ 2, 3, 2 }), - std::make_pair(DmaChannelId{ 2, 5, 1 }, DmaChannelId{ 2, 6, 1 }) } }; - } - - SpiMasterStmDma::SpiMasterStmDma(hal::DmaStm& dmaStm, uint8_t oneBasedSpiIndex, GpioPinStm& clock, GpioPinStm& miso, GpioPinStm& mosi, const Config& config, GpioPinStm& slaveSelect) + SpiMasterStmDma::SpiMasterStmDma(hal::DmaStm::TransmitStream& transmitStream, hal::DmaStm::ReceiveStream& receiveStream, uint8_t oneBasedSpiIndex, GpioPinStm& clock, GpioPinStm& miso, GpioPinStm& mosi, const Config& config, GpioPinStm& slaveSelect) : spiInstance(oneBasedSpiIndex - 1) , clock(clock, PinConfigTypeStm::spiClock, oneBasedSpiIndex) , miso(miso, PinConfigTypeStm::spiMiso, oneBasedSpiIndex) , mosi(mosi, PinConfigTypeStm::spiMosi, oneBasedSpiIndex) , slaveSelect(slaveSelect, PinConfigTypeStm::spiSlaveSelect, oneBasedSpiIndex) - , rx(dmaStm, config.dmaChannelRx.ValueOr(defaultDmaChannelId[spiInstance].second), &peripheralSpi[spiInstance]->DR, [this]() + , tx(transmitStream, &peripheralSpi[spiInstance]->DR, 1, [this]() { - ReceiveDone(); + SendDone(); }) - , tx(dmaStm, config.dmaChannelTx.ValueOr(defaultDmaChannelId[spiInstance].first), &peripheralSpi[spiInstance]->DR, [this]() + , rx(receiveStream, &peripheralSpi[spiInstance]->DR, 1, [this]() { - SendDone(); + ReceiveDone(); }) { EnableClockSpi(spiInstance); @@ -65,7 +55,9 @@ namespace hal void SpiMasterStmDma::SendAndReceive(infra::ConstByteRange sendData, infra::ByteRange receiveData) { - uint32_t maxDmaSize = 65535 - (DataSize() > 8 ? 1 : 0); + const auto dataSize = DataSize(); + const auto maxDmaSize = 65535 - (dataSize > 8 ? 1 : 0); + sendBuffer = infra::DiscardHead(sendData, maxDmaSize); sendData = infra::Head(sendData, maxDmaSize); receiveBuffer = infra::DiscardHead(receiveData, maxDmaSize); @@ -77,18 +69,35 @@ namespace hal if (!sendData.empty() && !receiveData.empty()) { assert(sendData.size() == receiveData.size()); - rx.StartReceive(receiveData); - tx.StartTransmit(sendData); + + if (dataSize <= 8) + { + rx.StartReceive(receiveData); + tx.StartTransmit(sendData); + } + else + { + rx.StartReceive(infra::ReinterpretCastMemoryRange(receiveData)); + tx.StartTransmit(infra::ReinterpretCastMemoryRange(sendData)); + } } else if (!sendData.empty()) { - rx.StartReceiveDummy(sendData.size()); - tx.StartTransmit(sendData); + rx.StartReceiveDummy(sendData.size(), dataSize <= 8 ? 1 : 2); + + if (dataSize <= 8) + tx.StartTransmit(sendData); + else + tx.StartTransmit(infra::ReinterpretCastMemoryRange(sendData)); } else if (!receiveData.empty()) { - rx.StartReceive(receiveData); - tx.StartTransmitDummy(receiveData.size()); + if (dataSize <= 8) + rx.StartReceive(receiveData); + else + rx.StartReceive(infra::ReinterpretCastMemoryRange(receiveData)); + + tx.StartTransmitDummy(receiveData.size(), dataSize <= 8 ? 1 : 2); } else std::abort(); @@ -119,6 +128,9 @@ namespace hal DisableDma(); peripheralSpi[spiInstance]->CR1 &= ~SPI_CR1_SPE; + tx.SetPeripheralTransferSize(dataSizeInBits <= 8 ? 1 : 2); + rx.SetPeripheralTransferSize(dataSizeInBits <= 8 ? 1 : 2); + #if defined(STM32F0) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4) assert(dataSizeInBits >= 4 && dataSizeInBits <= 16); peripheralSpi[spiInstance]->CR2 = (peripheralSpi[spiInstance]->CR2 & ~SPI_CR2_DS) | ((dataSizeInBits - 1) << POSITION_VAL(SPI_CR2_DS)) | (dataSizeInBits <= 8 ? SPI_CR2_FRXTH : 0); @@ -126,10 +138,9 @@ namespace hal assert(dataSizeInBits == 8 || dataSizeInBits == 16); peripheralSpi[spiInstance]->CR1 = peripheralSpi[spiInstance]->CR1 & ~SPI_CR1_DFF | (dataSizeInBits == 16 ? SPI_CR1_DFF : 0); #endif - tx.SetDataSize(dataSizeInBits <= 8 ? 1 : 2); - rx.SetDataSize(dataSizeInBits <= 8 ? 1 : 2); peripheralSpi[spiInstance]->CR1 |= SPI_CR1_SPE; + EnableDma(); } diff --git a/hal_st/stm32fxxx/SpiMasterStmDma.hpp b/hal_st/stm32fxxx/SpiMasterStmDma.hpp index f3c9d678..ec9de72e 100644 --- a/hal_st/stm32fxxx/SpiMasterStmDma.hpp +++ b/hal_st/stm32fxxx/SpiMasterStmDma.hpp @@ -8,22 +8,22 @@ namespace hal { + namespace detail + { + struct SpiMasterStmDmaConfig + { + bool msbFirst{ true }; + uint32_t baudRatePrescaler{ SPI_BAUDRATEPRESCALER_16 }; + }; + } + class SpiMasterStmDma : public SpiMaster { public: - struct Config - { - constexpr Config() - {} - - bool msbFirst = true; - uint32_t baudRatePrescaler = SPI_BAUDRATEPRESCALER_16; - infra::Optional dmaChannelTx; - infra::Optional dmaChannelRx; - }; + using Config = detail::SpiMasterStmDmaConfig; - SpiMasterStmDma(hal::DmaStm& dmaStm, uint8_t oneBasedSpiIndex, GpioPinStm& clock, GpioPinStm& miso, GpioPinStm& mosi, const Config& config = Config(), GpioPinStm& slaveSelect = dummyPinStm); + SpiMasterStmDma(hal::DmaStm::TransmitStream& transmitStream, hal::DmaStm::ReceiveStream& receiveStream, uint8_t oneBasedSpiIndex, GpioPinStm& clock, GpioPinStm& miso, GpioPinStm& mosi, const Config& config = Config(), GpioPinStm& slaveSelect = dummyPinStm); void SendAndReceive(infra::ConstByteRange sendData, infra::ByteRange receiveData, SpiAction nextAction, const infra::Function& onDone) override; void SetChipSelectConfigurator(ChipSelectConfigurator& configurator) override; @@ -59,8 +59,8 @@ namespace hal bool receiveDone = false; bool sendDone = false; - hal::DmaStm::Stream tx; - hal::DmaStm::Stream rx; + hal::TransmitDmaChannel tx; + hal::ReceiveDmaChannel rx; }; } diff --git a/hal_st/stm32fxxx/SpiSlaveStmDma.cpp b/hal_st/stm32fxxx/SpiSlaveStmDma.cpp index 1f696231..72f1583b 100644 --- a/hal_st/stm32fxxx/SpiSlaveStmDma.cpp +++ b/hal_st/stm32fxxx/SpiSlaveStmDma.cpp @@ -4,29 +4,19 @@ namespace hal { - namespace - { - const std::array, 6> defaultDmaChannelId = { { std::make_pair(DmaChannelId{ 2, 3, 3 }, DmaChannelId{ 2, 0, 3 }), - std::make_pair(DmaChannelId{ 1, 4, 0 }, DmaChannelId{ 1, 3, 0 }), - std::make_pair(DmaChannelId{ 1, 5, 0 }, DmaChannelId{ 1, 0, 0 }), - std::make_pair(DmaChannelId{ 2, 1, 4 }, DmaChannelId{ 2, 0, 4 }), - std::make_pair(DmaChannelId{ 2, 4, 2 }, DmaChannelId{ 2, 3, 2 }), - std::make_pair(DmaChannelId{ 2, 5, 1 }, DmaChannelId{ 2, 6, 1 }) } }; - } - - SpiSlaveStmDma::SpiSlaveStmDma(hal::DmaStm& dmaStm, uint8_t oneBasedSpiIndex, GpioPinStm& clock, GpioPinStm& miso, GpioPinStm& mosi, GpioPinStm& slaveSelect, const Config& config) + SpiSlaveStmDma::SpiSlaveStmDma(hal::DmaStm::TransmitStream& transmitStream, hal::DmaStm::ReceiveStream& receiveStream, uint8_t oneBasedSpiIndex, GpioPinStm& clock, GpioPinStm& miso, GpioPinStm& mosi, GpioPinStm& slaveSelect) : spiInstance(oneBasedSpiIndex - 1) , clock(clock, PinConfigTypeStm::spiClock, oneBasedSpiIndex) , miso(miso, PinConfigTypeStm::spiMiso, oneBasedSpiIndex) , mosi(mosi, PinConfigTypeStm::spiMosi, oneBasedSpiIndex) , slaveSelect(slaveSelect, PinConfigTypeStm::spiSlaveSelect, oneBasedSpiIndex) - , rx(dmaStm, config.dmaChannelRx.ValueOr(defaultDmaChannelId[spiInstance].second), &peripheralSpi[spiInstance]->DR, [this]() + , tx(transmitStream, &peripheralSpi[spiInstance]->DR, 1, [this]() { - ReceiveDone(); + SendDone(); }) - , tx(dmaStm, config.dmaChannelTx.ValueOr(defaultDmaChannelId[spiInstance].first), &peripheralSpi[spiInstance]->DR, [this]() + , rx(receiveStream, &peripheralSpi[spiInstance]->DR, 1, [this]() { - SendDone(); + ReceiveDone(); }) { ResetPeripheralSpi(spiInstance); diff --git a/hal_st/stm32fxxx/SpiSlaveStmDma.hpp b/hal_st/stm32fxxx/SpiSlaveStmDma.hpp index c1f91878..2a78e51c 100644 --- a/hal_st/stm32fxxx/SpiSlaveStmDma.hpp +++ b/hal_st/stm32fxxx/SpiSlaveStmDma.hpp @@ -12,16 +12,7 @@ namespace hal : public SpiSlave { public: - struct Config - { - constexpr Config() - {} - - infra::Optional dmaChannelTx; - infra::Optional dmaChannelRx; - }; - - SpiSlaveStmDma(hal::DmaStm& dmaStm, uint8_t oneBasedSpiIndex, GpioPinStm& clock, GpioPinStm& miso, GpioPinStm& mosi, GpioPinStm& slaveSelect, const Config& config = Config()); + SpiSlaveStmDma(hal::DmaStm::TransmitStream& transmitStream, hal::DmaStm::ReceiveStream& receiveStream, uint8_t oneBasedSpiIndex, GpioPinStm& clock, GpioPinStm& miso, GpioPinStm& mosi, GpioPinStm& slaveSelect); void SendAndReceive(infra::ConstByteRange sendData, infra::ByteRange receiveData, const infra::Function& onDone) override; bool CancelTransmission() override; @@ -47,8 +38,8 @@ namespace hal bool receiveDone = false; bool sendDone = false; - hal::DmaStm::Stream tx; - hal::DmaStm::Stream rx; + hal::TransmitDmaChannel tx; + hal::ReceiveDmaChannel rx; }; } diff --git a/hal_st/stm32fxxx/UartStm.cpp b/hal_st/stm32fxxx/UartStm.cpp index 6c3bda19..d20edbb6 100644 --- a/hal_st/stm32fxxx/UartStm.cpp +++ b/hal_st/stm32fxxx/UartStm.cpp @@ -1,53 +1,60 @@ #include "hal_st/stm32fxxx/UartStm.hpp" #include "generated/stm32fxxx/PeripheralTable.hpp" +#include "hal_st/stm32fxxx/GpioStm.hpp" #include "infra/event/EventDispatcher.hpp" #include "infra/util/BoundedVector.hpp" namespace hal { - UartStm::UartStm(uint8_t aUartIndex, GpioPinStm& uartTxPin, GpioPinStm& uartRxPin, const Config& config) - : uartIndex(aUartIndex - 1) - , uartTx(uartTxPin, PinConfigTypeStm::uartTx, aUartIndex) - , uartRx(uartRxPin, PinConfigTypeStm::uartRx, aUartIndex) + UartStm::UartStm(uint8_t oneBasedIndex, GpioPinStm& uartTxPin, GpioPinStm& uartRxPin, const Config& config) + : UartStm(oneBasedIndex, uartTxPin, uartRxPin, dummyPinStm, dummyPinStm, config, false) + {} + + UartStm::UartStm(uint8_t oneBasedIndex, GpioPinStm& uartTxPin, GpioPinStm& uartRxPin, GpioPinStm& uartRtsPin, GpioPinStm& uartCtsPin, const Config& config) + : UartStm(oneBasedIndex, uartTxPin, uartRxPin, uartRtsPin, uartCtsPin, config, true) + {} + + UartStm::UartStm(uint8_t oneBasedIndex, GpioPinStm& uartTxPin, GpioPinStm& uartRxPin, GpioPinStm& uartRtsPin, GpioPinStm& uartCtsPin, const Config& config, bool hasFlowControl) + : uartIndex(oneBasedIndex - 1) + , uartTx(uartTxPin, PinConfigTypeStm::uartTx, oneBasedIndex) + , uartRx(uartRxPin, PinConfigTypeStm::uartRx, oneBasedIndex) + , uartRts(uartRtsPin, PinConfigTypeStm::uartRts, oneBasedIndex) + , uartCts(uartCtsPin, PinConfigTypeStm::uartCts, oneBasedIndex) , uartHandle() { uartArray = peripheralUart; uartIrqArray = peripheralUartIrq; RegisterInterrupt(config); EnableClockUart(uartIndex); - UartStmHalInit(config); - } - - UartStm::UartStm(uint8_t aUartIndex, GpioPinStm& uartTxPin, GpioPinStm& uartRxPin, GpioPinStm& uartRtsPin, GpioPinStm& uartCtsPin, const Config& config) - : UartStm(aUartIndex, uartTxPin, uartRxPin, config) - { - uartRts.Emplace(uartRtsPin, PinConfigTypeStm::uartRts, aUartIndex); - uartCts.Emplace(uartCtsPin, PinConfigTypeStm::uartCts, aUartIndex); + UartStmHalInit(config, hasFlowControl); } #if defined(STM32WB) - UartStm::UartStm(uint8_t aUartIndex, GpioPinStm& uartTxPin, GpioPinStm& uartRxPin, LpUart lpUart, const Config& config) - : uartIndex(aUartIndex - 1) - , uartTx(uartTxPin, PinConfigTypeStm::lpuartTx, aUartIndex) - , uartRx(uartRxPin, PinConfigTypeStm::lpuartRx, aUartIndex) + UartStm::UartStm(uint8_t oneBasedIndex, GpioPinStm& uartTxPin, GpioPinStm& uartRxPin, LpUart lpUart, const Config& config) + : UartStm(oneBasedIndex, uartTxPin, uartRxPin, dummyPinStm, dummyPinStm, lpUart, config, false) + {} + + UartStm::UartStm(uint8_t oneBasedIndex, GpioPinStm& uartTxPin, GpioPinStm& uartRxPin, GpioPinStm& uartRtsPin, GpioPinStm& uartCtsPin, LpUart lpUart, const Config& config) + : UartStm(oneBasedIndex, uartTxPin, uartRxPin, uartRtsPin, uartCtsPin, lpUart, config, true) + {} + + UartStm::UartStm(uint8_t oneBasedIndex, GpioPinStm& uartTxPin, GpioPinStm& uartRxPin, GpioPinStm& uartRtsPin, GpioPinStm& uartCtsPin, LpUart lpUart, const Config& config, bool hasFlowControl) + : uartIndex(oneBasedIndex - 1) + , uartTx(uartTxPin, PinConfigTypeStm::lpuartTx, oneBasedIndex) + , uartRx(uartRxPin, PinConfigTypeStm::lpuartRx, oneBasedIndex) + , uartRts(uartRtsPin, PinConfigTypeStm::lpuartRts, oneBasedIndex) + , uartCts(uartCtsPin, PinConfigTypeStm::lpuartCts, oneBasedIndex) , uartHandle() { uartArray = peripheralLpuart; uartIrqArray = peripheralLpuartIrq; RegisterInterrupt(config); EnableClockLpuart(uartIndex); - UartStmHalInit(config); - } - - UartStm::UartStm(uint8_t aUartIndex, GpioPinStm& uartTxPin, GpioPinStm& uartRxPin, GpioPinStm& uartRtsPin, GpioPinStm& uartCtsPin, LpUart lpUart, const Config& config) - : UartStm(aUartIndex, uartTxPin, uartRxPin, lpUart, config) - { - uartRts.Emplace(uartRtsPin, PinConfigTypeStm::lpuartRts, aUartIndex); - uartCts.Emplace(uartCtsPin, PinConfigTypeStm::lpuartCts, aUartIndex); + UartStmHalInit(config, hasFlowControl); } #endif - void UartStm::UartStmHalInit(const Config& config) + void UartStm::UartStmHalInit(const Config& config, bool hasFlowControl) { uartHandle.Instance = uartArray[uartIndex]; uartHandle.Init.BaudRate = config.baudrate; @@ -55,7 +62,7 @@ namespace hal uartHandle.Init.StopBits = USART_STOPBITS_1; uartHandle.Init.Parity = config.parity; uartHandle.Init.Mode = USART_MODE_TX_RX; - uartHandle.Init.HwFlowCtl = config.hwFlowControl; + uartHandle.Init.HwFlowCtl = hasFlowControl ? UART_HWCONTROL_RTS_CTS : UART_HWCONTROL_NONE; #if defined(STM32F0) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) uartHandle.Init.OverSampling = UART_OVERSAMPLING_8; uartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_ENABLE; @@ -101,10 +108,7 @@ namespace hal void UartStm::RegisterInterrupt(const Config& config) { - if (config.priority) - Register(uartIrqArray[uartIndex], *config.priority); - else - Register(uartIrqArray[uartIndex]); + Register(uartIrqArray[uartIndex], config.priority); } void UartStm::TransferComplete() diff --git a/hal_st/stm32fxxx/UartStm.hpp b/hal_st/stm32fxxx/UartStm.hpp index ee535c77..1cf4e498 100644 --- a/hal_st/stm32fxxx/UartStm.hpp +++ b/hal_st/stm32fxxx/UartStm.hpp @@ -14,35 +14,44 @@ namespace hal extern const LpUart lpUart; #endif + + namespace detail + { + struct UartStmConfig + { + uint32_t baudrate{ 115200 }; + uint32_t parity{ USART_PARITY_NONE }; + InterruptPriority priority{ InterruptPriority::Normal }; + }; + } + class UartStm : public SerialCommunication , private InterruptHandler { public: - struct Config - { - constexpr Config() - {} + using Config = detail::UartStmConfig; - uint32_t baudrate = 115200; - uint32_t hwFlowControl = UART_HWCONTROL_NONE; - uint32_t parity = USART_PARITY_NONE; - infra::Optional priority; - }; - - UartStm(uint8_t aUartIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, const Config& config = Config()); - UartStm(uint8_t aUartIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config = Config()); + UartStm(uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, const Config& config = Config()); + UartStm(uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config = Config()); +#if defined(STM32WB) + UartStm(uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, LpUart lpUart, const Config& config = Config()); + UartStm(uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, LpUart lpUart, const Config& config = Config()); +#endif + private: + UartStm(uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config, bool hasFlowControl); #if defined(STM32WB) - UartStm(uint8_t aUartIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, LpUart lpUart, const Config& config = Config()); - UartStm(uint8_t aUartIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, LpUart lpUart, const Config& config = Config()); + UartStm(uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, LpUart lpUart, const Config& config, bool hasFlowControl); #endif + + public: ~UartStm(); void SendData(infra::MemoryRange data, infra::Function actionOnCompletion = infra::emptyFunction) override; void ReceiveData(infra::Function dataReceived) override; private: - void UartStmHalInit(const Config& config); + void UartStmHalInit(const Config& config, bool hasFlowControl); void RegisterInterrupt(const Config& config); void TransferComplete(); void Invoke() override; @@ -51,8 +60,8 @@ namespace hal uint8_t uartIndex; hal::PeripheralPinStm uartTx; hal::PeripheralPinStm uartRx; - infra::Optional uartRts; - infra::Optional uartCts; + hal::PeripheralPinStm uartRts; + hal::PeripheralPinStm uartCts; UART_HandleTypeDef uartHandle = {}; diff --git a/hal_st/stm32fxxx/UartStmDma.cpp b/hal_st/stm32fxxx/UartStmDma.cpp index 56a15262..99e85f46 100644 --- a/hal_st/stm32fxxx/UartStmDma.cpp +++ b/hal_st/stm32fxxx/UartStmDma.cpp @@ -7,86 +7,51 @@ namespace hal { namespace { - const std::array defaultDmaChannelId = { { DmaChannelId{ 2, 7, 4 }, - DmaChannelId{ 1, 6, 4 }, - DmaChannelId{ 1, 3, 4 }, - DmaChannelId{ 1, 4, 4 }, - DmaChannelId{ 1, 7, 4 }, - DmaChannelId{ 2, 6, 5 }, - DmaChannelId{ 1, 1, 5 }, - DmaChannelId{ 1, 0, 5 } } }; - } - - UartStmDma::UartStmDma(hal::DmaStm& dma, uint8_t aUartIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, const Config& config) - : uartIndex(aUartIndex - 1) - , uartTx(uartTx, PinConfigTypeStm::uartTx, aUartIndex) - , uartRx(uartRx, PinConfigTypeStm::uartRx, aUartIndex) - , uartHandle() - , dma(dma) -#if defined(STM32F0) || defined(STM32F1) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4) - , transmitDmaChannel(dma, config.dmaChannelTx.ValueOr(defaultDmaChannelId[uartIndex]), &peripheralUart[uartIndex]->TDR, [this]() - { - TransferComplete(); - }) -#else - , transmitDmaChannel(dma, config.dmaChannelTx.ValueOr(defaultDmaChannelId[uartIndex]), &peripheralUart[uartIndex]->DR, [this]() - { - TransferComplete(); - }) -#endif - { - RegisterInterrupt(config); - EnableClockUart(uartIndex); - - uartHandle.Instance = peripheralUart[uartIndex]; - uartHandle.Init.BaudRate = config.baudrate; - uartHandle.Init.WordLength = config.parity == USART_PARITY_NONE ? USART_WORDLENGTH_8B : USART_WORDLENGTH_9B; - uartHandle.Init.StopBits = USART_STOPBITS_1; - uartHandle.Init.Parity = config.parity; - uartHandle.Init.Mode = USART_MODE_TX_RX; - uartHandle.Init.HwFlowCtl = config.hwFlowControl; -#if defined(STM32F0) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4) - uartHandle.Init.OverSampling = UART_OVERSAMPLING_8; - uartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_ENABLE; + volatile void* PeripheralAddress(uint8_t uartIndex) + { +#if defined(STM32F0) || defined(STM32F1) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G0) || defined(STM32G4) + return &peripheralUart[uartIndex]->TDR; #else - uartHandle.Init.OverSampling = UART_OVERSAMPLING_8; + return &peripheralUart[uartIndex]->DR; #endif - HAL_UART_Init(&uartHandle); - - peripheralUart[uartIndex]->CR2 &= ~USART_CLOCK_ENABLED; - peripheralUart[uartIndex]->CR3 |= USART_CR3_DMAT; + } } - UartStmDma::UartStmDma(hal::DmaStm& dma, uint8_t aUartIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config) - : uartIndex(aUartIndex - 1) - , uartTx(uartTx, PinConfigTypeStm::uartTx, aUartIndex) - , uartRx(uartRx, PinConfigTypeStm::uartRx, aUartIndex) - , uartRts(infra::inPlace, uartRts, PinConfigTypeStm::uartRts, aUartIndex) - , uartCts(infra::inPlace, uartCts, PinConfigTypeStm::uartCts, aUartIndex) - , uartHandle() - , dma(dma) -#if defined(STM32F0) || defined(STM32F1) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4) - , transmitDmaChannel(dma, config.dmaChannelTx.ValueOr(defaultDmaChannelId[uartIndex]), &peripheralUart[uartIndex]->TDR, [this]() - { - TransferComplete(); - }) -#else - , transmitDmaChannel(dma, config.dmaChannelTx.ValueOr(defaultDmaChannelId[uartIndex]), &peripheralUart[uartIndex]->DR, [this]() - { - TransferComplete(); - }) -#endif + UartStmDma::UartStmDma(DmaStm::TransmitStream& transmitStream, uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, const Config& config) + : UartStmDma{ transmitStream, oneBasedIndex, uartTx, uartRx, hal::dummyPinStm, hal::dummyPinStm, config, false } + {} + + UartStmDma::UartStmDma(DmaStm::TransmitStream& transmitStream, uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config) + : UartStmDma{ transmitStream, oneBasedIndex, uartTx, uartRx, uartRts, uartCts, config, true } + {} + + UartStmDma::UartStmDma(DmaStm::TransmitStream& transmitStream, uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config, bool hasFlowControl) + : uartIndex(oneBasedIndex - 1) + , uartTx(uartTx, PinConfigTypeStm::uartTx, oneBasedIndex) + , uartRx(uartRx, PinConfigTypeStm::uartRx, oneBasedIndex) + , uartRts(uartRts, PinConfigTypeStm::uartRts, oneBasedIndex) + , uartCts(uartCts, PinConfigTypeStm::uartCts, oneBasedIndex) + , transmitDmaChannel{ transmitStream, PeripheralAddress(uartIndex), 1, [this]() + { + TransferComplete(); + } } { RegisterInterrupt(config); EnableClockUart(uartIndex); + UART_HandleTypeDef uartHandle = {}; uartHandle.Instance = peripheralUart[uartIndex]; uartHandle.Init.BaudRate = config.baudrate; uartHandle.Init.WordLength = config.parity == USART_PARITY_NONE ? USART_WORDLENGTH_8B : USART_WORDLENGTH_9B; uartHandle.Init.StopBits = USART_STOPBITS_1; uartHandle.Init.Parity = config.parity; uartHandle.Init.Mode = USART_MODE_TX_RX; - uartHandle.Init.HwFlowCtl = config.hwFlowControl; + + if (hasFlowControl) + uartHandle.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS; + else + uartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; + #if defined(STM32F0) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4) uartHandle.Init.OverSampling = UART_OVERSAMPLING_8; uartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_ENABLE; @@ -129,10 +94,7 @@ namespace hal void UartStmDma::RegisterInterrupt(const Config& config) { - if (config.priority) - Register(peripheralUartIrq[uartIndex], *config.priority); - else - Register(peripheralUartIrq[uartIndex]); + Register(peripheralUartIrq[uartIndex], config.priority); } void UartStmDma::TransferComplete() @@ -149,14 +111,16 @@ namespace hal { infra::BoundedVector::WithMaxSize<8> buffer; -#if defined(STM32F0) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4) +#if defined(STM32F0) || defined(STM32F3) || defined(STM32F7) || defined(STM32G4) || defined(STM32WB) while (peripheralUart[uartIndex]->ISR & USART_ISR_RXNE) +#elif defined(STM32G0) + while (peripheralUart[uartIndex]->ISR & USART_ISR_RXNE_RXFNE) #else while (peripheralUart[uartIndex]->SR & USART_SR_RXNE) #endif { uint8_t receivedByte = -#if defined(STM32F0) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4) +#if defined(STM32F0) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G0) || defined(STM32G4) peripheralUart[uartIndex]->RDR; #else peripheralUart[uartIndex]->DR; @@ -165,7 +129,7 @@ namespace hal } // If buffer is empty then interrupt was raised by Overrun Error (ORE) and we miss data. -#if defined(STM32F0) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4) +#if defined(STM32F0) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G0) || defined(STM32G4) really_assert(!(buffer.empty() && peripheralUart[uartIndex]->ISR & USART_ISR_ORE)); #else really_assert(!(buffer.empty() && peripheralUart[uartIndex]->SR & USART_SR_ORE)); diff --git a/hal_st/stm32fxxx/UartStmDma.hpp b/hal_st/stm32fxxx/UartStmDma.hpp index bb1ec5bf..f32e735a 100644 --- a/hal_st/stm32fxxx/UartStmDma.hpp +++ b/hal_st/stm32fxxx/UartStmDma.hpp @@ -5,30 +5,38 @@ #include "hal_st/cortex/InterruptCortex.hpp" #include "hal_st/stm32fxxx/DmaStm.hpp" #include "hal_st/stm32fxxx/GpioStm.hpp" +#include +#include DEVICE_HEADER namespace hal { + namespace detail + { + + struct UartStmDmaConfig + { + uint32_t baudrate{ 115200 }; + uint32_t parity{ USART_PARITY_NONE }; + + hal::InterruptPriority priority{ hal::InterruptPriority::Normal }; + }; + } + class UartStmDma : public SerialCommunication , private InterruptHandler { public: - struct Config - { - constexpr Config() - {} - - uint32_t baudrate = 115200; - uint32_t hwFlowControl = UART_HWCONTROL_NONE; - uint32_t parity = USART_PARITY_NONE; - infra::Optional dmaChannelTx; - infra::Optional priority; - }; + using Config = detail::UartStmDmaConfig; - UartStmDma(hal::DmaStm& dmaStm, uint8_t uartIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, const Config& config = Config()); - UartStmDma(hal::DmaStm& dmaStm, uint8_t uartIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config = Config()); + UartStmDma(DmaStm::TransmitStream& transmitStream, uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, const Config& config = Config()); + UartStmDma(DmaStm::TransmitStream& transmitStream, uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config = Config()); ~UartStmDma(); + private: + UartStmDma(DmaStm::TransmitStream& transmitStream, uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config, bool hasFlowControl); + + public: void SendData(infra::MemoryRange data, infra::Function actionOnCompletion = infra::emptyFunction) override; void ReceiveData(infra::Function dataReceived) override; @@ -41,13 +49,10 @@ namespace hal uint8_t uartIndex; PeripheralPinStm uartTx; PeripheralPinStm uartRx; - infra::Optional uartRts; - infra::Optional uartCts; - - UART_HandleTypeDef uartHandle = {}; + PeripheralPinStm uartRts; + PeripheralPinStm uartCts; - hal::DmaStm& dma; - DmaStm::Stream transmitDmaChannel; + TransmitDmaChannel transmitDmaChannel; infra::Function transferDataComplete; infra::Function dataReceived; diff --git a/hal_st/stm32fxxx/UartStmDuplexDma.cpp b/hal_st/stm32fxxx/UartStmDuplexDma.cpp index ba5bd1e0..159bb713 100644 --- a/hal_st/stm32fxxx/UartStmDuplexDma.cpp +++ b/hal_st/stm32fxxx/UartStmDuplexDma.cpp @@ -1,120 +1,89 @@ #include "hal_st/stm32fxxx/UartStmDuplexDma.hpp" #include "generated/stm32fxxx/PeripheralTable.hpp" #include "infra/event/EventDispatcher.hpp" -#include "infra/util/BoundedVector.hpp" namespace hal { namespace { - uint16_t defaultRxTimeout = 16; + uint32_t defaultRxTimeout = 16; -#if defined(STM32WB) - const std::array defaultTxDmaChannelId = { { DmaChannelId{ 1, 0, DMA_REQUEST_USART1_TX } } }; - - const std::array defaultRxDmaChannelId = { { DmaChannelId{ 1, 0, DMA_REQUEST_USART1_RX } } }; + volatile void* TransmitRegister(uint8_t uartIndex) + { +#if defined(STM32F0) || defined(STM32F1) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4) + return &peripheralUart[uartIndex]->TDR; #else - const std::array defaultTxDmaChannelId = { { DmaChannelId{ 2, 7, 4 }, - DmaChannelId{ 1, 6, 4 }, - DmaChannelId{ 1, 3, 4 }, - DmaChannelId{ 1, 4, 4 }, - DmaChannelId{ 1, 7, 4 }, - DmaChannelId{ 2, 6, 5 }, - DmaChannelId{ 1, 1, 5 }, - DmaChannelId{ 1, 0, 5 } } }; - - const std::array defaultRxDmaChannelId = { { DmaChannelId{ 2, 2, 4 }, - DmaChannelId{ 1, 5, 4 }, - DmaChannelId{ 1, 1, 4 }, - DmaChannelId{ 1, 2, 4 }, - DmaChannelId{ 1, 0, 4 }, - DmaChannelId{ 2, 7, 5 }, - DmaChannelId{ 1, 3, 5 }, - DmaChannelId{ 1, 6, 5 } } }; + return &peripheralUart[uartIndex]->DR; #endif + } - } - - UartStmDuplexDma::UartStmDuplexDma(infra::MemoryRange rxBuffer, hal::DmaStm& dma, uint8_t aUartIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, const Config& config) - : rxBuffer(rxBuffer) - , uartIndex(aUartIndex - 1) - , uartTx(uartTx, PinConfigTypeStm::uartTx, aUartIndex) - , uartRx(uartRx, PinConfigTypeStm::uartRx, aUartIndex) - , uartHandle() - , dma(dma) + volatile void* ReceiveRegister(uint8_t uartIndex) + { #if defined(STM32F0) || defined(STM32F1) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4) - , transmitDmaChannel(dma, config.dmaChannelTx.ValueOr(defaultTxDmaChannelId[uartIndex]), &peripheralUart[uartIndex]->TDR, [this]() - { - TransferComplete(); - }) - , receiveDmaChannel( - dma, config.dmaChannelRx.ValueOr(defaultRxDmaChannelId[uartIndex]), &peripheralUart[uartIndex]->RDR, [this]() - { - ReceiveComplete(this->rxBuffer.size() / 2); - }, - [this]() - { - ReceiveComplete(this->rxBuffer.size()); - }) + return &peripheralUart[uartIndex]->RDR; #else - , transmitDmaChannel(dma, config.dmaChannelTx.ValueOr(defaultTxDmaChannelId[uartIndex]), &peripheralUart[uartIndex]->DR, [this]() - { - TransferComplete(); - }) - , receiveDmaChannel( - dma, config.dmaChannelRx.ValueOr(defaultRxDmaChannelId[uartIndex]), &peripheralUart[uartIndex]->DR, [this]() - { - ReceiveComplete(this->rxBuffer.size() / 2); - }, - [this]() - { - ReceiveComplete(this->rxBuffer.size()); - }) + return &peripheralUart[uartIndex]->DR; #endif - { - Configure(config); + } } - UartStmDuplexDma::UartStmDuplexDma(infra::MemoryRange rxBuffer, hal::DmaStm& dma, uint8_t aUartIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config) - : rxBuffer(rxBuffer) - , uartIndex(aUartIndex - 1) - , uartTx(uartTx, PinConfigTypeStm::uartTx, aUartIndex) - , uartRx(uartRx, PinConfigTypeStm::uartRx, aUartIndex) - , uartRts(infra::inPlace, uartRts, PinConfigTypeStm::uartRts, aUartIndex) - , uartCts(infra::inPlace, uartCts, PinConfigTypeStm::uartCts, aUartIndex) - , uartHandle() - , dma(dma) -#if defined(STM32F0) || defined(STM32F1) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4) - , transmitDmaChannel(dma, config.dmaChannelTx.ValueOr(defaultTxDmaChannelId[uartIndex]), &peripheralUart[uartIndex]->TDR, [this]() - { - TransferComplete(); - }) - , receiveDmaChannel( - dma, config.dmaChannelRx.ValueOr(defaultRxDmaChannelId[uartIndex]), &peripheralUart[uartIndex]->RDR, [this]() - { - ReceiveComplete(this->rxBuffer.size() / 2); - }, - [this]() - { - ReceiveComplete(this->rxBuffer.size()); - }) -#else - , transmitDmaChannel(dma, config.dmaChannelTx.ValueOr(defaultTxDmaChannelId[uartIndex]), &peripheralUart[uartIndex]->DR, [this]() - { - TransferComplete(); - }) - , receiveDmaChannel( - dma, config.dmaChannelRx.ValueOr(defaultRxDmaChannelId[uartIndex]), &peripheralUart[uartIndex]->DR, [this]() - { - ReceiveComplete(this->rxBuffer.size() / 2); - }, - [this]() - { - ReceiveComplete(this->rxBuffer.size()); - }) -#endif + UartStmDuplexDma::UartStmDuplexDma(infra::MemoryRange rxBuffer, hal::DmaStm::TransmitStream& transmitStream, hal::DmaStm::ReceiveStream& receiveStream, uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, const Config& config) + : UartStmDuplexDma{ rxBuffer, transmitStream, receiveStream, oneBasedIndex, uartTx, uartRx, hal::dummyPinStm, hal::dummyPinStm, config, false } + {} + + UartStmDuplexDma::UartStmDuplexDma(infra::MemoryRange rxBuffer, hal::DmaStm::TransmitStream& transmitStream, hal::DmaStm::ReceiveStream& receiveStream, uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config) + : UartStmDuplexDma{ rxBuffer, transmitStream, receiveStream, oneBasedIndex, uartTx, uartRx, uartRts, uartCts, config, true } + {} + + UartStmDuplexDma::UartStmDuplexDma(infra::MemoryRange rxBuffer, hal::DmaStm::TransmitStream& transmitStream, hal::DmaStm::ReceiveStream& receiveStream, uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config, bool hasFlowControl) + : rxBuffer{ rxBuffer } + , uartIndex{ static_cast(oneBasedIndex - 1) } + , uartTx{ uartTx, PinConfigTypeStm::uartTx, oneBasedIndex } + , uartRx{ uartRx, PinConfigTypeStm::uartRx, oneBasedIndex } + , uartRts{ uartRts, PinConfigTypeStm::uartRts, oneBasedIndex } + , uartCts{ uartCts, PinConfigTypeStm::uartCts, oneBasedIndex } + , transmitDmaChannel{ transmitStream, TransmitRegister(uartIndex), 1, [this] + { + TransferComplete(); + } } + , receiveDmaChannel{ receiveStream, ReceiveRegister(uartIndex), 1, [this] + { + HalfReceiveComplete(); + }, + [this] + { + FullReceiveComplete(); + } } { - Configure(config); + RegisterInterrupt(config); + EnableClockUart(uartIndex); + + UART_HandleTypeDef uartHandle = {}; + uartHandle.Instance = peripheralUart[uartIndex]; + uartHandle.Init.BaudRate = config.baudrate; + uartHandle.Init.WordLength = USART_WORDLENGTH_8B; + uartHandle.Init.StopBits = USART_STOPBITS_1; + uartHandle.Init.Parity = USART_PARITY_NONE; + uartHandle.Init.Mode = USART_MODE_TX_RX; + + if (hasFlowControl) + uartHandle.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS; + else + uartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; + + uartHandle.Init.OverSampling = UART_OVERSAMPLING_16; + uartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_ENABLE; + + HAL_UART_Init(&uartHandle); + +#if defined(STM32WB) + peripheralUart[uartIndex]->CR1 &= ~USART_CR1_UE; + peripheralUart[uartIndex]->CR1 |= USART_CR1_FIFOEN | USART_CR1_UE; +#endif + + peripheralUart[uartIndex]->CR1 &= ~USART_CR1_RE; + peripheralUart[uartIndex]->CR2 &= ~USART_CLOCK_ENABLED; + peripheralUart[uartIndex]->CR3 |= USART_CR3_DMAT | USART_CR3_DMAR; } UartStmDuplexDma::~UartStmDuplexDma() @@ -146,52 +115,32 @@ namespace hal peripheralUart[uartIndex]->RTOR = defaultRxTimeout; } - void UartStmDuplexDma::Configure(const Config& config) + void UartStmDuplexDma::HalfReceiveComplete() { - RegisterInterrupt(config); - EnableClockUart(uartIndex); - - uartHandle.Instance = peripheralUart[uartIndex]; - uartHandle.Init.BaudRate = config.baudrate; - uartHandle.Init.WordLength = USART_WORDLENGTH_8B; - uartHandle.Init.StopBits = USART_STOPBITS_1; - uartHandle.Init.Parity = USART_PARITY_NONE; - uartHandle.Init.Mode = USART_MODE_TX_RX; - uartHandle.Init.HwFlowCtl = config.hwFlowControl; - uartHandle.Init.OverSampling = UART_OVERSAMPLING_16; - uartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_ENABLE; - - HAL_UART_Init(&uartHandle); - -#if defined(STM32WB) - peripheralUart[uartIndex]->CR1 &= ~USART_CR1_UE; - peripheralUart[uartIndex]->CR1 |= USART_CR1_FIFOEN | USART_CR1_UE; -#endif + ReceiveComplete(this->rxBuffer.size() / 2); + } - peripheralUart[uartIndex]->CR1 &= ~USART_CR1_RE; - peripheralUart[uartIndex]->CR2 &= ~USART_CLOCK_ENABLED; - peripheralUart[uartIndex]->CR3 |= USART_CR3_DMAT | USART_CR3_DMAR; + void UartStmDuplexDma::FullReceiveComplete() + { + ReceiveComplete(this->rxBuffer.size()); } void UartStmDuplexDma::ReceiveComplete(size_t currentPosition) { - if (currentPosition == lastReceivedPosition) + if (currentPosition == lastReceivedPosition || !dataReceived) return; - if (dataReceived) - { - infra::ConstByteRange receivedData(rxBuffer.begin() + lastReceivedPosition, rxBuffer.begin() + currentPosition); - lastReceivedPosition = currentPosition == rxBuffer.size() ? 0 : currentPosition; - dataReceived(receivedData); - } + really_assert(lastReceivedPosition <= currentPosition); + + infra::ConstByteRange receivedData(rxBuffer.begin() + lastReceivedPosition, rxBuffer.begin() + currentPosition); + lastReceivedPosition = currentPosition == rxBuffer.size() ? 0 : currentPosition; + + dataReceived(receivedData); } void UartStmDuplexDma::RegisterInterrupt(const Config& config) { - if (config.priority) - Register(peripheralUartIrq[uartIndex], *config.priority); - else - Register(peripheralUartIrq[uartIndex]); + Register(peripheralUartIrq[uartIndex], config.priority); } void UartStmDuplexDma::TransferComplete() @@ -208,7 +157,13 @@ namespace hal if (peripheralUart[uartIndex]->ISR & USART_ISR_RTOF) { peripheralUart[uartIndex]->ICR = USART_ICR_RTOCF; - ReceiveComplete(receiveDmaChannel.ReceivedSize()); + + const auto receivedSize = receiveDmaChannel.ReceivedSize(); + + if (receiveDmaChannel.IsInterruptPending()) + return; + + ReceiveComplete(receivedSize); } } } diff --git a/hal_st/stm32fxxx/UartStmDuplexDma.hpp b/hal_st/stm32fxxx/UartStmDuplexDma.hpp index ad6fa6b6..2b7e6661 100644 --- a/hal_st/stm32fxxx/UartStmDuplexDma.hpp +++ b/hal_st/stm32fxxx/UartStmDuplexDma.hpp @@ -6,41 +6,50 @@ #include "hal_st/stm32fxxx/DmaStm.hpp" #include "hal_st/stm32fxxx/GpioStm.hpp" #include +#include namespace hal { + namespace detail + { + struct UartStmDuplexDmaConfig + { + uint32_t baudrate{ 115200 }; + hal::InterruptPriority priority{ hal::InterruptPriority::Normal }; + }; + } + class UartStmDuplexDma : public SerialCommunication , private InterruptHandler { public: - struct Config - { - constexpr Config() - {} - - uint32_t baudrate = 115200; - uint32_t hwFlowControl = UART_HWCONTROL_NONE; - infra::Optional dmaChannelTx; - infra::Optional dmaChannelRx; - infra::Optional priority; - }; + using Config = detail::UartStmDuplexDmaConfig; template using WithRxBuffer = infra::WithStorage>; - UartStmDuplexDma(infra::MemoryRange rxBuffer, hal::DmaStm& dmaStm, uint8_t uartIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, const Config& config = Config()); - UartStmDuplexDma(infra::MemoryRange rxBuffer, hal::DmaStm& dmaStm, uint8_t uartIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config = Config()); + UartStmDuplexDma(infra::MemoryRange rxBuffer, hal::DmaStm::TransmitStream& transmitStream, hal::DmaStm::ReceiveStream& receiveStream, uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, const Config& config = Config()); + UartStmDuplexDma(infra::MemoryRange rxBuffer, hal::DmaStm::TransmitStream& transmitStream, hal::DmaStm::ReceiveStream& receiveStream, uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config = Config()); + + private: + UartStmDuplexDma(infra::MemoryRange rxBuffer, hal::DmaStm::TransmitStream& transmitStream, hal::DmaStm::ReceiveStream& receiveStream, uint8_t oneBasedIndex, GpioPinStm& uartTx, GpioPinStm& uartRx, GpioPinStm& uartRts, GpioPinStm& uartCts, const Config& config, bool hasFlowControl); + + public: ~UartStmDuplexDma(); + // Implementation of SerialCommunication void SendData(infra::MemoryRange data, infra::Function actionOnCompletion = infra::emptyFunction) override; void ReceiveData(infra::Function dataReceived) override; private: - void Configure(const Config& config); + void HalfReceiveComplete(); + void FullReceiveComplete(); void ReceiveComplete(size_t currentPosition); void RegisterInterrupt(const Config& config); void TransferComplete(); + + // Implementation of InterruptHandler void Invoke() override; private: @@ -48,14 +57,11 @@ namespace hal uint8_t uartIndex; PeripheralPinStm uartTx; PeripheralPinStm uartRx; - infra::Optional uartRts; - infra::Optional uartCts; - - UART_HandleTypeDef uartHandle = {}; + PeripheralPinStm uartRts; + PeripheralPinStm uartCts; - hal::DmaStm& dma; - DmaStm::Stream transmitDmaChannel; - DmaStm::CircularStream receiveDmaChannel; + hal::TransmitDmaChannel transmitDmaChannel; + hal::CircularReceiveDmaChannel receiveDmaChannel; infra::Function transferDataComplete; infra::Function dataReceived; diff --git a/hal_st/stm32fxxx/ip/GPIO-STM32G47x_gpio_v1_0_Modes.xml b/hal_st/stm32fxxx/ip/GPIO-STM32G47x_gpio_v1_0_Modes.xml new file mode 100644 index 00000000..ca306c6f --- /dev/null +++ b/hal_st/stm32fxxx/ip/GPIO-STM32G47x_gpio_v1_0_Modes.xml @@ -0,0 +1,5661 @@ + + + GPIO: General Purpose Input Output + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AlternateFunction + + + + + + + + + + GPIODefaultOutputPP + + + + + GPIO_MODE_OUTPUT_PP + GPIO_MODE_OUTPUT_OD + + + + + + + + GPIODefaultOutputPP + + + + + GPIO_MODE_OUTPUT_PP + GPIO_MODE_OUTPUT_OD + + + + + + + + GPIODefaultOutputPP + + + + + GPIO_MODE_OUTPUT_PP + GPIO_MODE_OUTPUT_OD + + + + + + + + GPIODefaultOutputPP + + + + + GPIO_MODE_OUTPUT_PP + GPIO_MODE_OUTPUT_OD + + + + + + + + GPIODefaultOutputPP + + + + + GPIO_MODE_OUTPUT_PP + GPIO_MODE_OUTPUT_OD + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + + + + + + AlternateFunctionHighSpeedDefault + + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunctionHighSpeedDefault + + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunctionHighSpeedDefault + + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunctionHighSpeedDefault + + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunctionHighSpeedDefault + + + + + + GPIO_MODE_AF_PP + + + + + + AlternateFunction + + + + GPIO_PULLUP + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + + GPIO_PULLUP + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + + GPIO_PULLUP + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + + GPIO_PULLUP + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + + GPIO_PULLUP + + + + GPIO_MODE_AF_PP + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_OD + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_OD + + + + + + AlternateFunctionDefaultPP + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionDefaultPP + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionDefaultPP + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionDefaultPP + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionDefaultPP + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + AlternateFunction + + + GPIO_SPEED_FREQ_VERY_HIGH + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + GPIO_SPEED_FREQ_VERY_HIGH + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + GPIO_SPEED_FREQ_VERY_HIGH + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + GPIO_SPEED_FREQ_VERY_HIGH + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunction + + + GPIO_SPEED_FREQ_VERY_HIGH + + + + + GPIO_MODE_AF_PP + + + + + GPIO + + GPIO_NOPULL + + + + GPIO_MODE_ANALOG + + + + + GPIO + + GPIO_NOPULL + + + + GPIO_MODE_ANALOG_ADC_CONTROL + + + + + GPIO + + + + GPIO_MODE_INPUT + + + + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + + + + + AlternateFunctionHighSpeedDefault + + + + + + GPIO_MODE_AF_PP + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + + + + + AlternateFunction + + + + GPIO_PULLUP + + + + GPIO_MODE_AF_PP + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_OD + + + + + AlternateFunctionDefaultPP + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + AlternateFunction + + + GPIO_SPEED_FREQ_VERY_HIGH + + + + + GPIO_MODE_AF_PP + + + + + EXTI + + + + + + + EXTIRisingFalling + + + + + + + + AlternateFunctionDefaultOD + + + GPIO_SPEED_FREQ_LOW + + + GPIO_NOPULL + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionDefaultOD + + + GPIO_SPEED_FREQ_LOW + + + GPIO_NOPULL + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionDefaultOD + + + GPIO_SPEED_FREQ_LOW + + + GPIO_NOPULL + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionDefaultOD + + + GPIO_SPEED_FREQ_LOW + + + GPIO_NOPULL + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionDefaultOD + + + GPIO_SPEED_FREQ_LOW + + + GPIO_NOPULL + + + + GPIO_MODE_AF_OD + + + + + + AlternateFunctionDefaultPP + + + GPIO_SPEED_FREQ_LOW + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunctionDefaultPP + + + GPIO_SPEED_FREQ_LOW + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunctionDefaultPP + + + GPIO_SPEED_FREQ_LOW + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunctionDefaultPP + + + GPIO_SPEED_FREQ_LOW + + + + + GPIO_MODE_AF_PP + + + + + + + AlternateFunctionDefaultPP + + + GPIO_SPEED_FREQ_LOW + + + + + GPIO_MODE_AF_PP + + + + + AlternateFunction + + + GPIO_SPEED_FREQ_LOW + + + + + GPIO_MODE_AF_PP + + + + + AlternateFunction + + + + + + GPIO_MODE_AF_PP + + + + + + AlternateFunctionDefaultOD + + + + + + GPIO_MODE_AF_OD + GPIO_MODE_AF_PP + + + + + + + AlternateFunctionDefaultOD + + + + + + GPIO_MODE_AF_OD + GPIO_MODE_AF_PP + + + + + + + AlternateFunctionDefaultOD + + + + + + GPIO_MODE_AF_OD + GPIO_MODE_AF_PP + + + + + + + AlternateFunctionDefaultOD + + + + + + GPIO_MODE_AF_OD + GPIO_MODE_AF_PP + + + + + + + AlternateFunctionDefaultOD + + + + + + GPIO_MODE_AF_OD + GPIO_MODE_AF_PP + + + + + + AlternateFunctionNoPullOrPullUp + + + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionNoPullOrPullUp + + + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionNoPullOrPullUp + + + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionNoPullOrPullUp + + + + + + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionNoPullOrPullUp + + + + + + GPIO_MODE_AF_OD + + + + + + AlternateFunctionDefaultPPHFirst + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionDefaultPPHFirst + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionDefaultPPHFirst + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionDefaultPPHFirst + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + + AlternateFunctionDefaultPPHFirst + + + + + + GPIO_MODE_AF_PP + GPIO_MODE_AF_OD + + + + + + + GPIO_PIN_0 + + + + GPIO_AF8_COMP1 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF1_TIM2 + + + + + GPIO_AF14_TIM2 + + + + + GPIO_AF2_TIM5 + + + + + GPIO_AF9_TIM8_COMP1 + + + + + GPIO_AF10_TIM8 + + + + + GPIO_AF7_USART2 + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_1 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF0_RTC_50Hz + + + + + GPIO_AF9_TIM15 + + + + + GPIO_AF1_TIM2 + + + + + GPIO_AF2_TIM5 + + + + + GPIO_AF7_USART2 + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_10 + + + + GPIO_AF8_COMP6 + + + + + GPIO_AF3_UCPD1 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF4_I2C2 + + + + + GPIO_AF12_SAI1 + + + + + GPIO_AF14_SAI1 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF1_TIM17 + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF10_TIM2 + + + + + GPIO_AF11_TIM8_COMP1 + + + + + GPIO_AF7_USART1 + + + + + + GPIO_PIN_11 + + + + GPIO_AF8_COMP1 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF9_FDCAN1 + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF12_TIM1_COMP1 + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF11_TIM1 + + + + + GPIO_AF10_TIM4 + + + + + GPIO_AF7_USART1 + + + + + GPIO_AF7_USART1 + + + + + + GPIO_PIN_12 + + + + GPIO_AF8_COMP2 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF9_FDCAN1 + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF1_TIM16 + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF11_TIM1 + + + + + GPIO_AF10_TIM4 + + + + + GPIO_AF7_USART1 + + + + + GPIO_AF7_USART1 + + + + + + GPIO_PIN_13 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF4_I2C1 + + + + + GPIO_AF3_I2C4 + + + + + GPIO_AF5_IR + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF0_TRACE + + + + + GPIO_AF1_TIM16 + + + + + GPIO_AF10_TIM4 + + + + + GPIO_AF7_USART3 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_14 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF4_I2C1 + + + + + GPIO_AF3_I2C4 + + + + + GPIO_AF1_LPTIM1 + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF0_TRACE + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF5_TIM8 + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_15 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF11_FDCAN3 + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF4_I2C1 + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF5_SPI1 + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF0_TRACE + + + + + GPIO_AF9_TIM1 + + + + + GPIO_AF1_TIM2 + + + + + GPIO_AF14_TIM2 + + + + + GPIO_AF2_TIM8 + + + + + GPIO_AF8_UART4 + + + + + GPIO_AF8_UART4 + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_2 + + + + GPIO_AF8_COMP2 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_LPUART1 + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF9_TIM15 + + + + + GPIO_AF1_TIM2 + + + + + GPIO_AF2_TIM5 + + + + + GPIO_AF14_UCPD1 + + + + + GPIO_AF14_UCPD1 + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_3 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_LPUART1 + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF3_SAI1 + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF9_TIM15 + + + + + GPIO_AF1_TIM2 + + + + + GPIO_AF2_TIM5 + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_4 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF5_SPI1 + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF2_TIM3 + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_5 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF5_SPI1 + + + + + GPIO_AF1_TIM2 + + + + + GPIO_AF2_TIM2 + + + + + GPIO_AF14_UCPD1 + + + + + GPIO_AF14_UCPD1 + + + + + + GPIO_PIN_6 + + + + GPIO_AF8_COMP1 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_LPUART1 + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF5_SPI1 + + + + + GPIO_AF1_TIM16 + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF2_TIM3 + + + + + GPIO_AF4_TIM8 + + + + + + GPIO_PIN_7 + + + + GPIO_AF8_COMP2 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF5_SPI1 + + + + + GPIO_AF1_TIM17 + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF2_TIM3 + + + + + GPIO_AF4_TIM8 + + + + + GPIO_AF14_UCPD1 + + + + + GPIO_AF14_UCPD1 + + + + + + GPIO_PIN_8 + + + + GPIO_AF8_COMP7 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF11_FDCAN3 + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF4_I2C2 + + + + + GPIO_AF2_I2C3 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF0_MCO + + + + + GPIO_AF12_SAI1 + + + + + GPIO_AF14_SAI1 + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF10_TIM4 + + + + + GPIO_AF7_USART1 + + + + + + GPIO_PIN_9 + + + + GPIO_AF8_COMP5 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF4_I2C2 + + + + + GPIO_AF2_I2C3 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF14_SAI1 + + + + + GPIO_AF9_TIM15 + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF10_TIM2 + + + + + GPIO_AF7_USART1 + + + + + + GPIO_PIN_0 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF2_TIM3 + + + + + GPIO_AF4_TIM8 + + + + + GPIO_AF14_UCPD1 + + + + + GPIO_AF14_UCPD1 + + + + + + GPIO_PIN_1 + + + + GPIO_AF8_COMP4 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF12_LPUART1 + + + + + GPIO_AF12_LPUART1 + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF2_TIM3 + + + + + GPIO_AF4_TIM8 + + + + + + GPIO_PIN_10 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF8_LPUART1 + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF14_SAI1 + + + + + GPIO_AF12_TIM1_COMP1 + + + + + GPIO_AF1_TIM2 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_11 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF8_LPUART1 + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF1_TIM2 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_12 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF9_FDCAN2 + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF4_I2C2 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF8_LPUART1 + + + + + GPIO_AF8_LPUART1 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF2_TIM5 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_13 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF9_FDCAN2 + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF8_LPUART1 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF7_USART3 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_14 + + + + GPIO_AF8_COMP4 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF1_TIM15 + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF7_USART3 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_15 + + + + GPIO_AF3_COMP3 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF0_RTC_50Hz + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF2_TIM15 + + + + + GPIO_AF1_TIM15 + + + + + GPIO_AF4_TIM1 + + + + + + GPIO_PIN_2 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF4_I2C3 + + + + + GPIO_AF1_LPTIM1 + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF0_RTC_50Hz + + + + + GPIO_AF3_TIM20 + + + + + GPIO_AF2_TIM5 + + + + + + GPIO_PIN_3 + + + + GPIO_AF3_UCPD1 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF11_FDCAN3 + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF12_HRTIM1 + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF14_SAI1 + + + + + GPIO_AF5_SPI1 + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF0_TRACE + + + + + GPIO_AF1_TIM2 + + + + + GPIO_AF10_TIM3 + + + + + GPIO_AF2_TIM4 + + + + + GPIO_AF4_TIM8 + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_4 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF11_FDCAN3 + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF14_SAI1 + + + + + GPIO_AF5_SPI1 + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF0_TRACE + + + + + GPIO_AF1_TIM16 + + + + + GPIO_AF10_TIM17 + + + + + GPIO_AF2_TIM3 + + + + + GPIO_AF4_TIM8 + + + + + GPIO_AF8_UART5 + + + + + GPIO_AF8_UART5 + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_5 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF9_FDCAN2 + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF4_I2C1 + + + + + GPIO_AF8_I2C3 + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF11_LPTIM1 + + + + + GPIO_AF12_SAI1 + + + + + GPIO_AF5_SPI1 + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF1_TIM16 + + + + + GPIO_AF10_TIM17 + + + + + GPIO_AF2_TIM3 + + + + + GPIO_AF3_TIM8 + + + + + GPIO_AF14_UART5 + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_6 + + + + GPIO_AF8_COMP4 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF9_FDCAN2 + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF12_HRTIM1 + + + + + GPIO_AF11_LPTIM1 + + + + + GPIO_AF14_SAI1 + + + + + GPIO_AF1_TIM16 + + + + + GPIO_AF2_TIM4 + + + + + GPIO_AF10_TIM8 + + + + + GPIO_AF5_TIM8 + + + + + GPIO_AF6_TIM8 + + + + + GPIO_AF7_USART1 + + + + + + GPIO_PIN_7 + + + + GPIO_AF8_COMP3 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF4_I2C1 + + + + + GPIO_AF3_I2C4 + + + + + GPIO_AF11_LPTIM1 + + + + + GPIO_AF1_TIM17 + + + + + GPIO_AF10_TIM3 + + + + + GPIO_AF2_TIM4 + + + + + GPIO_AF5_TIM8 + + + + + GPIO_AF14_UART4 + + + + + GPIO_AF7_USART1 + + + + + + GPIO_PIN_8 + + + + GPIO_AF8_COMP1 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF9_FDCAN1 + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF4_I2C1 + + + + + GPIO_AF3_SAI1 + + + + + GPIO_AF14_SAI1 + + + + + GPIO_AF1_TIM16 + + + + + GPIO_AF12_TIM1_COMP1 + + + + + GPIO_AF2_TIM4 + + + + + GPIO_AF10_TIM8 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_9 + + + + GPIO_AF8_COMP2 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF9_FDCAN1 + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF4_I2C1 + + + + + GPIO_AF6_IR + + + + + GPIO_AF3_SAI1 + + + + + GPIO_AF14_SAI1 + + + + + GPIO_AF1_TIM17 + + + + + GPIO_AF12_TIM1_COMP1 + + + + + GPIO_AF2_TIM4 + + + + + GPIO_AF10_TIM8 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_0 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF1_LPTIM1 + + + + + GPIO_AF8_LPUART1 + + + + + GPIO_AF2_TIM1 + + + + + + GPIO_PIN_1 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF1_LPTIM1 + + + + + GPIO_AF8_LPUART1 + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF2_TIM1 + + + + + + GPIO_PIN_10 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF4_TIM8 + + + + + GPIO_AF5_UART4 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_11 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF3_HRTIM1 + + + + + GPIO_AF8_I2C3 + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF4_TIM8 + + + + + GPIO_AF5_UART4 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_12 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF3_HRTIM1 + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF1_TIM5 + + + + + GPIO_AF4_TIM8 + + + + + GPIO_AF5_UART5 + + + + + GPIO_AF14_UCPD1 + + + + + GPIO_AF14_UCPD1 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_13 + + + GPIO_SPEED_FREQ_LOW + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF2_TIM1 + + + + + GPIO_AF4_TIM1 + + + + + GPIO_AF6_TIM8 + + + + + + GPIO_PIN_14 + + + GPIO_SPEED_FREQ_LOW + + + + GPIO_AF15_EVENTOUT + + + + + + GPIO_PIN_15 + + + GPIO_SPEED_FREQ_LOW + + + + GPIO_AF15_EVENTOUT + + + + + + GPIO_PIN_2 + + + + GPIO_AF3_COMP3 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF1_LPTIM1 + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF2_TIM1 + + + + + GPIO_AF6_TIM20 + + + + + + GPIO_PIN_3 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF1_LPTIM1 + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF3_SAI1 + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF0_TRACE + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF2_TIM1 + + + + + + GPIO_PIN_4 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF4_I2C2 + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF2_TIM1 + + + + + GPIO_AF7_USART1 + + + + + + GPIO_PIN_5 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF3_SAI1 + + + + + GPIO_AF2_TIM15 + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF7_USART1 + + + + + + GPIO_PIN_6 + + + + GPIO_AF7_COMP6 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF3_HRTIM1 + + + + + GPIO_AF8_I2C4 + + + + + GPIO_AF6_SPI2 + + + + + GPIO_AF2_TIM3 + + + + + GPIO_AF4_TIM8 + + + + + + GPIO_PIN_7 + + + + GPIO_AF7_COMP5 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF13_HRTIM1 + + + + + GPIO_AF3_HRTIM1 + + + + + GPIO_AF8_I2C4 + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF2_TIM3 + + + + + GPIO_AF4_TIM8 + + + + + + GPIO_PIN_8 + + + + GPIO_AF7_COMP7 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF3_HRTIM1 + + + + + GPIO_AF8_I2C3 + + + + + GPIO_AF6_TIM20 + + + + + GPIO_AF2_TIM3 + + + + + GPIO_AF4_TIM8 + + + + + + GPIO_PIN_9 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF3_HRTIM1 + + + + + GPIO_AF8_I2C3 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF2_TIM3 + + + + + GPIO_AF6_TIM8 + + + + + GPIO_AF4_TIM8 + + + + + + GPIO_PIN_0 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF9_FDCAN1 + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF6_TIM8 + + + + + + GPIO_PIN_1 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF9_FDCAN1 + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF6_TIM8 + + + + + GPIO_AF4_TIM8 + + + + + + GPIO_PIN_10 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_11 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF4_I2C4 + + + + + GPIO_AF1_TIM5 + + + + + GPIO_AF7_USART3 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_12 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF2_TIM4 + + + + + GPIO_AF7_USART3 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_13 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF2_TIM4 + + + + + + GPIO_PIN_14 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF2_TIM4 + + + + + + GPIO_PIN_15 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF6_SPI2 + + + + + GPIO_AF2_TIM4 + + + + + + GPIO_PIN_2 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF2_TIM3 + + + + + GPIO_AF4_TIM8 + + + + + GPIO_AF5_UART5 + + + + + + GPIO_PIN_3 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF2_TIM2 + + + + + GPIO_AF2_TIM2 + + + + + GPIO_AF7_USART2 + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_4 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF2_TIM2 + + + + + GPIO_AF7_USART2 + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_5 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_6 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF3_SAI1 + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF2_TIM2 + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_7 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF2_TIM2 + + + + + GPIO_AF7_USART2 + + + + + + GPIO_PIN_8 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_9 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_0 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF4_TIM16 + + + + + GPIO_AF3_TIM20 + + + + + GPIO_AF6_TIM20 + + + + + GPIO_AF2_TIM4 + + + + + GPIO_AF7_USART1 + + + + + + GPIO_PIN_1 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF4_TIM17 + + + + + GPIO_AF6_TIM20 + + + + + GPIO_AF7_USART1 + + + + + + GPIO_PIN_10 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF2_TIM1 + + + + + + GPIO_PIN_11 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF5_SPI4 + + + + + GPIO_AF2_TIM1 + + + + + + GPIO_PIN_12 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF5_SPI4 + + + + + GPIO_AF2_TIM1 + + + + + + GPIO_PIN_13 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF5_SPI4 + + + + + GPIO_AF2_TIM1 + + + + + + GPIO_PIN_14 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF5_SPI4 + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF2_TIM1 + + + + + + GPIO_PIN_15 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF2_TIM1 + + + + + GPIO_AF6_TIM1 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_2 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF3_SAI1 + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF5_SPI4 + + + + + GPIO_AF0_TRACE + + + + + GPIO_AF6_TIM20 + + + + + GPIO_AF2_TIM3 + + + + + + GPIO_PIN_3 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF5_SPI4 + + + + + GPIO_AF0_TRACE + + + + + GPIO_AF6_TIM20 + + + + + GPIO_AF2_TIM3 + + + + + + GPIO_PIN_4 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF3_SAI1 + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF5_SPI4 + + + + + GPIO_AF0_TRACE + + + + + GPIO_AF6_TIM20 + + + + + GPIO_AF2_TIM3 + + + + + + GPIO_PIN_5 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF3_SAI1 + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF5_SPI4 + + + + + GPIO_AF0_TRACE + + + + + GPIO_AF6_TIM20 + + + + + GPIO_AF2_TIM3 + + + + + + GPIO_PIN_6 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF3_SAI1 + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF5_SPI4 + + + + + GPIO_AF0_TRACE + + + + + GPIO_AF6_TIM20 + + + + + + GPIO_PIN_7 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF2_TIM1 + + + + + + GPIO_PIN_8 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF2_TIM1 + + + + + GPIO_AF1_TIM5 + + + + + + GPIO_PIN_9 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF2_TIM1 + + + + + GPIO_AF1_TIM5 + + + + + + GPIO_PIN_0 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF4_I2C2 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF6_TIM1 + + + + + + GPIO_PIN_1 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF5_SPI2 + + + + + + GPIO_PIN_10 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF3_TIM15 + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_11 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_12 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_13 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF4_I2C4 + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_14 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF4_I2C4 + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_15 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF4_I2C4 + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_2 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF4_I2C2 + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_3 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF4_I2C3 + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_4 + + + + GPIO_AF2_COMP1 + + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF4_I2C3 + + + + + GPIO_AF3_TIM20 + + + + + + GPIO_PIN_5 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_6 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF4_I2C2 + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF3_SAI1 + + + + + GPIO_AF2_TIM4 + + + + + GPIO_AF6_TIM5 + + + + + GPIO_AF1_TIM5 + + + + + GPIO_AF7_USART3 + + + + + GPIO_AF7_USART3 + + + + + + GPIO_PIN_7 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF2_TIM20 + + + + + GPIO_AF6_TIM5 + + + + + + GPIO_PIN_8 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF2_TIM20 + + + + + GPIO_AF6_TIM5 + + + + + + GPIO_PIN_9 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF10_QUADSPI + + + + + GPIO_AF13_SAI1 + + + + + GPIO_AF5_SPI2 + + + + + GPIO_AF3_TIM15 + + + + + GPIO_AF2_TIM20 + + + + + GPIO_AF6_TIM5 + + + + + + GPIO_PIN_0 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_1 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_10 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF0_MCO + + + + + + GPIO_PIN_2 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF5_SPI1 + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_3 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF4_I2C4 + + + + + GPIO_AF5_SPI1 + + + + + GPIO_AF2_TIM20 + + + + + GPIO_AF6_TIM20 + + + + + + GPIO_PIN_4 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF4_I2C4 + + + + + GPIO_AF5_SPI1 + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_5 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF8_LPUART1 + + + + + GPIO_AF5_SPI1 + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_6 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF4_I2C3 + + + + + GPIO_AF8_LPUART1 + + + + + GPIO_AF8_LPUART1 + + + + + GPIO_AF2_TIM20 + + + + + + GPIO_PIN_7 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF4_I2C3 + + + + + GPIO_AF8_LPUART1 + + + + + GPIO_AF3_SAI1 + + + + + GPIO_AF13_SAI1 + + + + + + GPIO_PIN_8 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF4_I2C3 + + + + + GPIO_AF8_LPUART1 + + + + + + GPIO_PIN_9 + + + + GPIO_AF15_EVENTOUT + + + + + GPIO_AF12_FMC + + + + + GPIO_AF12_FMC + + + + + GPIO_AF6_SPI3 + + + + + GPIO_AF14_TIM15 + + + + + GPIO_AF7_USART1 + + + + + + GPIO_SPEED_FREQ_LOW + + + + + GPIOA + + + + + GPIOB + + + + + GPIOC + + + + + GPIOD + + + + + GPIOE + + + + + GPIOF + + + + + GPIOG + + + diff --git a/hal_st/stm32fxxx/mcu/STM32G474R(B-C-E)Tx.xml b/hal_st/stm32fxxx/mcu/STM32G474R(B-C-E)Tx.xml new file mode 100644 index 00000000..3e2166a8 --- /dev/null +++ b/hal_st/stm32fxxx/mcu/STM32G474R(B-C-E)Tx.xml @@ -0,0 +1,859 @@ + + + ARM Cortex-M4 + 170 + 128 + 52 + DIE469 + 128 + 256 + 512 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/integration_test/tester/EchoFromCloud.hpp b/integration_test/tester/EchoFromCloud.hpp index 24f786ea..a31cb01c 100644 --- a/integration_test/tester/EchoFromCloud.hpp +++ b/integration_test/tester/EchoFromCloud.hpp @@ -12,7 +12,8 @@ namespace main_ hal::GpioPinStm hostUartTxPin{ hal::Port::C, 10 }; hal::GpioPinStm hostUartRxPin{ hal::Port::C, 11 }; hal::DmaStm dma; - hal::UartStmDma hostUart{ dma, 4, hostUartTxPin, hostUartRxPin }; + hal::DmaStm::TransmitStream transmitStream{ dma, hal::DmaChannelId{ 1, 4, 4 } }; + hal::UartStmDma hostUart{ transmitStream, 4, hostUartTxPin, hostUartRxPin }; services::MethodSerializerFactory ::ForServices::AndProxies serializerFactory; main_::EchoOnSerialCommunication<256> echo{ hostUart, serializerFactory }; }; diff --git a/st/CMakeLists.txt b/st/CMakeLists.txt index 161b3fb0..c8e75991 100644 --- a/st/CMakeLists.txt +++ b/st/CMakeLists.txt @@ -38,6 +38,7 @@ target_compile_definitions(st.hal_driver_stm32g4xx PUBLIC STM32G4=1 DEVICE_HEADER="stm32g4xx.h" $<$:STM32G431xx=1> + $<$:STM32G474xx=1> ) add_hal_driver(st.hal_driver_stm32wbxx STM32WBxx_HAL_Driver CMSIS_STM32WBxx) diff --git a/st/ldscripts/mem_stm32g474.ld b/st/ldscripts/mem_stm32g474.ld new file mode 100644 index 00000000..bf4cd7b9 --- /dev/null +++ b/st/ldscripts/mem_stm32g474.ld @@ -0,0 +1,6 @@ +MEMORY +{ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K + RAM_SHARED (xrw) : ORIGIN = 0, LENGTH = 0 + FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 512K +}