From 4c546820fdb28bf46fae6606716ae34e2f4ba950 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 31 May 2021 20:40:16 +0200 Subject: [PATCH 01/35] added gyrol3gd20h stm32 test file --- stm32h7/CMakeLists.txt | 1 + stm32h7/devicetest/CMakeLists.txt | 3 +++ stm32h7/devicetest/GyroL3GD20H.cpp | 35 ++++++++++++++++++++++++++++++ stm32h7/devicetest/GyroL3GD20H.h | 21 ++++++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 stm32h7/devicetest/CMakeLists.txt create mode 100644 stm32h7/devicetest/GyroL3GD20H.cpp create mode 100644 stm32h7/devicetest/GyroL3GD20H.h diff --git a/stm32h7/CMakeLists.txt b/stm32h7/CMakeLists.txt index e69de29..9197332 100644 --- a/stm32h7/CMakeLists.txt +++ b/stm32h7/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(devicetest) diff --git a/stm32h7/devicetest/CMakeLists.txt b/stm32h7/devicetest/CMakeLists.txt new file mode 100644 index 0000000..dab7eaf --- /dev/null +++ b/stm32h7/devicetest/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(${TARGET_NAME} PRIVATE + GyroL3GD20H.cpp +) \ No newline at end of file diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp new file mode 100644 index 0000000..567b8e8 --- /dev/null +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -0,0 +1,35 @@ +#include "GyroL3GD20H.h" + +#include "fsfw/serviceinterface/ServiceInterface.h" +#include "stm32h7xx_nucleo.h" +#include "stm32h7xx_hal_spi.h" + +uint8_t ALIGN_32BYTES(GyroL3GD20H::recvBuffer[recvBufferSize]); + +GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle): spiHandle(spiHandle) { +} + +ReturnValue_t GyroL3GD20H::performOperation() { + /*##-1- Configure the SPI peripheral #######################################*/ + /* Set the SPI parameters */ + spiHandle->Instance = SPI1; + spiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; + spiHandle->Init.Direction = SPI_DIRECTION_2LINES; + spiHandle->Init.CLKPhase = SPI_PHASE_1EDGE; + spiHandle->Init.CLKPolarity = SPI_POLARITY_LOW; + spiHandle->Init.DataSize = SPI_DATASIZE_8BIT; + spiHandle->Init.FirstBit = SPI_FIRSTBIT_MSB; + spiHandle->Init.TIMode = SPI_TIMODE_DISABLE; + spiHandle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + spiHandle->Init.CRCPolynomial = 7; + spiHandle->Init.CRCLength = SPI_CRC_LENGTH_8BIT; + spiHandle->Init.NSS = SPI_NSS_SOFT; + spiHandle->Init.NSSPMode = SPI_NSS_PULSE_DISABLE; + /* Recommended setting to avoid glitches */ + spiHandle->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; + spiHandle->Init.Mode = SPI_MODE_MASTER; + if(HAL_SPI_Init(spiHandle) != HAL_OK) { + sif::printWarning("Error initializing SPI\n"); + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/stm32h7/devicetest/GyroL3GD20H.h b/stm32h7/devicetest/GyroL3GD20H.h new file mode 100644 index 0000000..29edacb --- /dev/null +++ b/stm32h7/devicetest/GyroL3GD20H.h @@ -0,0 +1,21 @@ +#ifndef FSFW_HAL_STM32H7_DEVICETEST_GYRO_L3GD20H_H_ +#define FSFW_HAL_STM32H7_DEVICETEST_GYRO_L3GD20H_H_ + +#include "stm32h7xx_hal.h" +#include "stm32h7xx_hal_spi.h" +#include + +#include "fsfw/returnvalues/HasReturnvaluesIF.h" + +class GyroL3GD20H { +public: + GyroL3GD20H(SPI_HandleTypeDef* spiHandle); + + ReturnValue_t performOperation(); +private: + SPI_HandleTypeDef* spiHandle; + static constexpr size_t recvBufferSize = 32 * 10; + static uint8_t recvBuffer[recvBufferSize]; +}; + +#endif /* FSFW_HAL_STM32H7_DEVICETEST_GYRO_L3GD20H_H_ */ From 22384aec6a352c29e9c7e5a6252f15e73a6162b0 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 3 Jun 2021 14:00:50 +0200 Subject: [PATCH 02/35] continued stm32 spi code --- common/spi/spiCommon.h | 17 +++++++ linux/spi/spiDefinitions.h | 8 +-- stm32h7/CMakeLists.txt | 1 + stm32h7/devicetest/GyroL3GD20H.cpp | 81 +++++++++++++++++++++++++++--- stm32h7/devicetest/GyroL3GD20H.h | 17 ++++++- stm32h7/spi/CMakeLists.txt | 3 ++ stm32h7/spi/spiDefinitions.cpp | 26 ++++++++++ stm32h7/spi/spiDefinitions.h | 16 ++++++ 8 files changed, 152 insertions(+), 17 deletions(-) create mode 100644 common/spi/spiCommon.h create mode 100644 stm32h7/spi/CMakeLists.txt create mode 100644 stm32h7/spi/spiDefinitions.cpp create mode 100644 stm32h7/spi/spiDefinitions.h diff --git a/common/spi/spiCommon.h b/common/spi/spiCommon.h new file mode 100644 index 0000000..9b3aef6 --- /dev/null +++ b/common/spi/spiCommon.h @@ -0,0 +1,17 @@ +#ifndef FSFW_HAL_COMMON_SPI_SPICOMMON_H_ +#define FSFW_HAL_COMMON_SPI_SPICOMMON_H_ + +#include + +namespace spi { + +enum SpiModes: uint8_t { + MODE_0, + MODE_1, + MODE_2, + MODE_3 +}; + +} + +#endif /* FSFW_HAL_COMMON_SPI_SPICOMMON_H_ */ diff --git a/linux/spi/spiDefinitions.h b/linux/spi/spiDefinitions.h index ee56f6d..14af4fd 100644 --- a/linux/spi/spiDefinitions.h +++ b/linux/spi/spiDefinitions.h @@ -2,6 +2,7 @@ #define LINUX_SPI_SPIDEFINITONS_H_ #include "../../common/gpio/gpioDefinitions.h" +#include "../../common/spi/spiCommon.h" #include "fsfw/returnvalues/HasReturnvaluesIF.h" #include @@ -13,13 +14,6 @@ class SpiComIF; namespace spi { -enum SpiModes: uint8_t { - MODE_0, - MODE_1, - MODE_2, - MODE_3 -}; - enum SpiComIfModes { REGULAR, CALLBACK diff --git a/stm32h7/CMakeLists.txt b/stm32h7/CMakeLists.txt index 9197332..730f7f1 100644 --- a/stm32h7/CMakeLists.txt +++ b/stm32h7/CMakeLists.txt @@ -1 +1,2 @@ +add_subdirectory(spi) add_subdirectory(devicetest) diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index 567b8e8..6f72ca7 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -1,22 +1,29 @@ #include "GyroL3GD20H.h" +#include "stm32h7xx_spi_dma_msp.h" +#include "spiConf.h" +#include "../spi/spiDefinitions.h" +#include "fsfw/tasks/TaskFactory.h" #include "fsfw/serviceinterface/ServiceInterface.h" + #include "stm32h7xx_nucleo.h" #include "stm32h7xx_hal_spi.h" -uint8_t ALIGN_32BYTES(GyroL3GD20H::recvBuffer[recvBufferSize]); +std::array GyroL3GD20H::rxBuffer; +TransferStates transferState = TransferStates::IDLE; +DMA_HandleTypeDef txDmaHandle; +DMA_HandleTypeDef rxDmaHandle; GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle): spiHandle(spiHandle) { + setDmaHandles(&txDmaHandle, &rxDmaHandle); } -ReturnValue_t GyroL3GD20H::performOperation() { - /*##-1- Configure the SPI peripheral #######################################*/ - /* Set the SPI parameters */ +ReturnValue_t GyroL3GD20H::initialize() { + // Configure the SPI peripheral spiHandle->Instance = SPI1; - spiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; + spiHandle->Init.BaudRatePrescaler = SPI_GetPrescaler(HAL_RCC_GetHCLKFreq(), 3900000); spiHandle->Init.Direction = SPI_DIRECTION_2LINES; - spiHandle->Init.CLKPhase = SPI_PHASE_1EDGE; - spiHandle->Init.CLKPolarity = SPI_POLARITY_LOW; + spi::assignSpiMode(spi::SpiModes::MODE_3, spiHandle); spiHandle->Init.DataSize = SPI_DATASIZE_8BIT; spiHandle->Init.FirstBit = SPI_FIRSTBIT_MSB; spiHandle->Init.TIMode = SPI_TIMODE_DISABLE; @@ -25,11 +32,69 @@ ReturnValue_t GyroL3GD20H::performOperation() { spiHandle->Init.CRCLength = SPI_CRC_LENGTH_8BIT; spiHandle->Init.NSS = SPI_NSS_SOFT; spiHandle->Init.NSSPMode = SPI_NSS_PULSE_DISABLE; - /* Recommended setting to avoid glitches */ + // Recommended setting to avoid glitches spiHandle->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; spiHandle->Init.Mode = SPI_MODE_MASTER; if(HAL_SPI_Init(spiHandle) != HAL_OK) { sif::printWarning("Error initializing SPI\n"); + return HasReturnvaluesIF::RETURN_FAILED; } return HasReturnvaluesIF::RETURN_OK; } + +ReturnValue_t GyroL3GD20H::performOperation() { + + transferState = TransferStates::WAIT; + // Start SPI transfer via DMA + if(HAL_SPI_TransmitReceive_DMA(spiHandle, txBuffer.data(), rxBuffer.data(), 2) != HAL_OK) { + // Transfer error in transmission process + sif::printWarning("Error transmitting SPI with DMA\n"); + } + + // Wait for the transfer to complete + while (transferState == TransferStates::WAIT) { + TaskFactory::delayTask(1); + } + + // Invalidate cache prior to access by CPU + SCB_InvalidateDCache_by_Addr ((uint32_t *)rxBuffer.data(), recvBufferSize); + + switch(transferState) { + case(TransferStates::SUCCESS): { + sif::printInfo("Transfer success\n"); + transferState = TransferStates::IDLE; + break; + } + case(TransferStates::FAILURE): { + sif::printWarning("Transfer failure\n"); + transferState = TransferStates::FAILURE; + break; + } + default: { + break; + } + } + return HasReturnvaluesIF::RETURN_OK; +} + +/** + * @brief TxRx Transfer completed callback. + * @param hspi: SPI handle + * @note This example shows a simple way to report end of DMA TxRx transfer, and + * you can add your own implementation. + * @retval None + */ +void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { + transferState = TransferStates::SUCCESS; +} + +/** + * @brief SPI error callbacks. + * @param hspi: SPI handle + * @note This example shows a simple way to report transfer error, and you can + * add your own implementation. + * @retval None + */ +void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { + transferState = TransferStates::FAILURE; +} diff --git a/stm32h7/devicetest/GyroL3GD20H.h b/stm32h7/devicetest/GyroL3GD20H.h index 29edacb..2a5b991 100644 --- a/stm32h7/devicetest/GyroL3GD20H.h +++ b/stm32h7/devicetest/GyroL3GD20H.h @@ -3,19 +3,32 @@ #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_spi.h" -#include #include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include +#include + +enum class TransferStates { + IDLE, + WAIT, + SUCCESS, + FAILURE +}; + class GyroL3GD20H { public: GyroL3GD20H(SPI_HandleTypeDef* spiHandle); + ReturnValue_t initialize(); ReturnValue_t performOperation(); + private: + SPI_HandleTypeDef* spiHandle; static constexpr size_t recvBufferSize = 32 * 10; - static uint8_t recvBuffer[recvBufferSize]; + static std::array rxBuffer; + std::array txBuffer; }; #endif /* FSFW_HAL_STM32H7_DEVICETEST_GYRO_L3GD20H_H_ */ diff --git a/stm32h7/spi/CMakeLists.txt b/stm32h7/spi/CMakeLists.txt new file mode 100644 index 0000000..3b5fd0d --- /dev/null +++ b/stm32h7/spi/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(${TARGET_NAME} PRIVATE + spiDefinitions.cpp +) diff --git a/stm32h7/spi/spiDefinitions.cpp b/stm32h7/spi/spiDefinitions.cpp new file mode 100644 index 0000000..9c141e7 --- /dev/null +++ b/stm32h7/spi/spiDefinitions.cpp @@ -0,0 +1,26 @@ +#include "spiDefinitions.h" + +void spi::assignSpiMode(SpiModes spiMode, SPI_HandleTypeDef *spiHandle) { + switch(spiMode) { + case(SpiModes::MODE_0): { + spiHandle->Init.CLKPolarity = SPI_POLARITY_LOW; + spiHandle->Init.CLKPhase = SPI_PHASE_1EDGE; + break; + } + case(SpiModes::MODE_1): { + spiHandle->Init.CLKPolarity = SPI_POLARITY_LOW; + spiHandle->Init.CLKPhase = SPI_PHASE_2EDGE; + break; + } + case(SpiModes::MODE_2): { + spiHandle->Init.CLKPolarity = SPI_POLARITY_HIGH; + spiHandle->Init.CLKPhase = SPI_PHASE_1EDGE; + break; + } + case(SpiModes::MODE_3): { + spiHandle->Init.CLKPolarity = SPI_POLARITY_HIGH; + spiHandle->Init.CLKPhase = SPI_PHASE_2EDGE; + break; + } + } +} diff --git a/stm32h7/spi/spiDefinitions.h b/stm32h7/spi/spiDefinitions.h new file mode 100644 index 0000000..3e002f2 --- /dev/null +++ b/stm32h7/spi/spiDefinitions.h @@ -0,0 +1,16 @@ +#ifndef FSFW_HAL_STM32H7_SPI_SPIDEFINITIONS_H_ +#define FSFW_HAL_STM32H7_SPI_SPIDEFINITIONS_H_ + +#include "../../common/spi/spiCommon.h" + +#include "stm32h7xx_hal.h" +#include "stm32h7xx_hal_spi.h" + +namespace spi { + +void assignSpiMode(SpiModes spiMode, SPI_HandleTypeDef* spiHandle); + +} + + +#endif /* FSFW_HAL_STM32H7_SPI_SPIDEFINITIONS_H_ */ From dc6327b909005c968a4794c3d8b2f9ac94ad59e1 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 3 Jun 2021 14:03:38 +0200 Subject: [PATCH 03/35] added spi hal functions --- stm32h7/devicetest/GyroL3GD20H.cpp | 2 +- stm32h7/spi/spiDefinitions.cpp | 26 ++++++++++++++++++++++++++ stm32h7/spi/spiDefinitions.h | 8 ++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index 6f72ca7..a56ea4c 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -21,7 +21,7 @@ GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle): spiHandle(spiHandle) { ReturnValue_t GyroL3GD20H::initialize() { // Configure the SPI peripheral spiHandle->Instance = SPI1; - spiHandle->Init.BaudRatePrescaler = SPI_GetPrescaler(HAL_RCC_GetHCLKFreq(), 3900000); + spiHandle->Init.BaudRatePrescaler = spi::getPrescaler(HAL_RCC_GetHCLKFreq(), 3900000); spiHandle->Init.Direction = SPI_DIRECTION_2LINES; spi::assignSpiMode(spi::SpiModes::MODE_3, spiHandle); spiHandle->Init.DataSize = SPI_DATASIZE_8BIT; diff --git a/stm32h7/spi/spiDefinitions.cpp b/stm32h7/spi/spiDefinitions.cpp index 9c141e7..4846293 100644 --- a/stm32h7/spi/spiDefinitions.cpp +++ b/stm32h7/spi/spiDefinitions.cpp @@ -24,3 +24,29 @@ void spi::assignSpiMode(SpiModes spiMode, SPI_HandleTypeDef *spiHandle) { } } } + +uint32_t spi::getPrescaler(uint32_t clock_src_freq, uint32_t baudrate_mbps) { + uint32_t divisor = 0; + uint32_t spi_clk = clock_src_freq; + uint32_t presc = 0; + static const uint32_t baudrate[] = { + SPI_BAUDRATEPRESCALER_2, + SPI_BAUDRATEPRESCALER_4, + SPI_BAUDRATEPRESCALER_8, + SPI_BAUDRATEPRESCALER_16, + SPI_BAUDRATEPRESCALER_32, + SPI_BAUDRATEPRESCALER_64, + SPI_BAUDRATEPRESCALER_128, + SPI_BAUDRATEPRESCALER_256, + }; + + while( spi_clk > baudrate_mbps) { + presc = baudrate[divisor]; + if (++divisor > 7) + break; + + spi_clk = ( spi_clk >> 1); + } + + return presc; +} diff --git a/stm32h7/spi/spiDefinitions.h b/stm32h7/spi/spiDefinitions.h index 3e002f2..ae07c7c 100644 --- a/stm32h7/spi/spiDefinitions.h +++ b/stm32h7/spi/spiDefinitions.h @@ -10,6 +10,14 @@ namespace spi { void assignSpiMode(SpiModes spiMode, SPI_HandleTypeDef* spiHandle); +/** + * @brief Set SPI frequency to calculate correspondent baud-rate prescaler. + * @param clock_src_freq Frequency of clock source + * @param baudrate_mbps Baudrate to set to set + * @retval Baudrate prescaler + */ +uint32_t getPrescaler(uint32_t clock_src_freq, uint32_t baudrate_mbps); + } From 21414c3594e1e36f0c177fc6f69678c83a894206 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 3 Jun 2021 14:38:34 +0200 Subject: [PATCH 04/35] extended spi core --- stm32h7/devicetest/GyroL3GD20H.cpp | 2 ++ stm32h7/spi/CMakeLists.txt | 1 + stm32h7/spi/spiCore.c | 56 ++++++++++++++++++++++++++++++ stm32h7/spi/spiCore.h | 36 +++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 stm32h7/spi/spiCore.c create mode 100644 stm32h7/spi/spiCore.h diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index a56ea4c..fad9923 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -2,6 +2,7 @@ #include "stm32h7xx_spi_dma_msp.h" #include "spiConf.h" #include "../spi/spiDefinitions.h" +#include "../spi/spiCore.h" #include "fsfw/tasks/TaskFactory.h" #include "fsfw/serviceinterface/ServiceInterface.h" @@ -21,6 +22,7 @@ GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle): spiHandle(spiHandle) { ReturnValue_t GyroL3GD20H::initialize() { // Configure the SPI peripheral spiHandle->Instance = SPI1; + uint32_t test = HAL_RCC_GetHCLKFreq(); spiHandle->Init.BaudRatePrescaler = spi::getPrescaler(HAL_RCC_GetHCLKFreq(), 3900000); spiHandle->Init.Direction = SPI_DIRECTION_2LINES; spi::assignSpiMode(spi::SpiModes::MODE_3, spiHandle); diff --git a/stm32h7/spi/CMakeLists.txt b/stm32h7/spi/CMakeLists.txt index 3b5fd0d..99d39dd 100644 --- a/stm32h7/spi/CMakeLists.txt +++ b/stm32h7/spi/CMakeLists.txt @@ -1,3 +1,4 @@ target_sources(${TARGET_NAME} PRIVATE + spiCore.c spiDefinitions.cpp ) diff --git a/stm32h7/spi/spiCore.c b/stm32h7/spi/spiCore.c new file mode 100644 index 0000000..ebb956d --- /dev/null +++ b/stm32h7/spi/spiCore.c @@ -0,0 +1,56 @@ +#include "spiCore.h" + +SPI_HandleTypeDef* spiHandle = NULL; +DMA_HandleTypeDef* hdma_tx = NULL; +DMA_HandleTypeDef* hdma_rx = NULL; + +void setDmaHandles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle) { + hdma_tx = txHandle; + hdma_rx = rxHandle; +} + +void getDmaHandles(DMA_HandleTypeDef** txHandle, DMA_HandleTypeDef** rxHandle) { + *txHandle = hdma_tx; + *rxHandle = hdma_rx; +} + +void assignSpiHandle(SPI_HandleTypeDef *spiHandle_) { + if(spiHandle_ == NULL) { + return; + } + spiHandle = spiHandle_; +} + +SPI_HandleTypeDef* getSpiHandle() { + return spiHandle; +} + +/** + * @brief This function handles DMA Rx interrupt request. + * @param None + * @retval None + */ +void SPIx_DMA_RX_IRQHandler(void) +{ + HAL_DMA_IRQHandler(spiHandle->hdmarx); +} + +/** + * @brief This function handles DMA Tx interrupt request. + * @param None + * @retval None + */ +void SPIx_DMA_TX_IRQHandler(void) +{ + HAL_DMA_IRQHandler(spiHandle->hdmatx); +} + +/** + * @brief This function handles SPIx interrupt request. + * @param None + * @retval None + */ +void SPIx_IRQHandler(void) +{ + HAL_SPI_IRQHandler(spiHandle); +} diff --git a/stm32h7/spi/spiCore.h b/stm32h7/spi/spiCore.h new file mode 100644 index 0000000..9af0de0 --- /dev/null +++ b/stm32h7/spi/spiCore.h @@ -0,0 +1,36 @@ +#ifndef FSFW_HAL_STM32H7_SPI_SPICORE_H_ +#define FSFW_HAL_STM32H7_SPI_SPICORE_H_ + +#include "stm32h7xx_hal.h" +#include "stm32h7xx_hal_dma.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Assign DMA handles. Required to use DMA for SPI transfers. + * @param txHandle + * @param rxHandle + */ +void setDmaHandles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle); + +void getDmaHandles(DMA_HandleTypeDef** txHandle, DMA_HandleTypeDef** rxHandle); + +/** + * Assign SPI handle. Needs to be done before using the SPI + * @param spiHandle + */ +void assignSpiHandle(SPI_HandleTypeDef *spiHandle); + +/** + * Get the assigned SPI handle. + * @return + */ +SPI_HandleTypeDef* getSpiHandle(); + +#ifdef __cplusplus +} +#endif + +#endif /* FSFW_HAL_STM32H7_SPI_SPICORE_H_ */ From 78a66e1b677ae0daa532db222ecdd0097c01399a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 3 Jun 2021 15:12:34 +0200 Subject: [PATCH 05/35] added IRS abstraction --- stm32h7/CMakeLists.txt | 4 +++ stm32h7/interrupts.c | 35 +++++++++++++++++++ stm32h7/interrupts.h | 23 +++++++++++++ stm32h7/spi/CMakeLists.txt | 1 + stm32h7/spi/interrupts.c | 12 +++++++ stm32h7/spi/interrupts.h | 8 +++++ stm32h7/spi/spiCore.c | 70 ++++++++++++++++++++++---------------- 7 files changed, 124 insertions(+), 29 deletions(-) create mode 100644 stm32h7/interrupts.c create mode 100644 stm32h7/interrupts.h create mode 100644 stm32h7/spi/interrupts.c create mode 100644 stm32h7/spi/interrupts.h diff --git a/stm32h7/CMakeLists.txt b/stm32h7/CMakeLists.txt index 730f7f1..e568b38 100644 --- a/stm32h7/CMakeLists.txt +++ b/stm32h7/CMakeLists.txt @@ -1,2 +1,6 @@ add_subdirectory(spi) add_subdirectory(devicetest) + +target_sources(${TARGET_NAME} PRIVATE + interrupts.c +) diff --git a/stm32h7/interrupts.c b/stm32h7/interrupts.c new file mode 100644 index 0000000..99e0272 --- /dev/null +++ b/stm32h7/interrupts.c @@ -0,0 +1,35 @@ +#include "interrupts.h" + +#include + +void Default_Handler(); + +void (*dma2_stream3_user_handler) (void* args) = NULL; +void * dma2_stream3_user_args = NULL; + +void (*dma2_stream2_user_handler) (void* args) = NULL; +void * dma2_stream2_user_args = NULL; + +void assign_dma2_stream2_user_handler(user_handler_t user_handler, user_args_t user_args) { + dma2_stream2_user_handler = user_handler; + dma2_stream2_user_args = user_args; +} + +void assign_dma2_stream3_user_handler(user_handler_t user_handler, user_args_t user_args) { + dma2_stream3_user_handler = user_handler; + dma2_stream3_user_args = user_args; +} + +void DMA2_Stream3_IRQHandler() { + if(dma2_stream3_user_handler != NULL) { + dma2_stream3_user_handler(dma2_stream3_user_args); + } + Default_Handler(); +} + +void DMA2_Stream2_IRQHandler() { + if(dma2_stream2_user_handler != NULL) { + dma2_stream2_user_handler(dma2_stream2_user_args); + } + Default_Handler(); +} diff --git a/stm32h7/interrupts.h b/stm32h7/interrupts.h new file mode 100644 index 0000000..de4ba81 --- /dev/null +++ b/stm32h7/interrupts.h @@ -0,0 +1,23 @@ +#ifndef FSFW_HAL_STM32H7_INTERRUPTS_H_ +#define FSFW_HAL_STM32H7_INTERRUPTS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Default handler which is defined in startup file as assembly code. + */ +extern void Default_Handler(); + +typedef void (*user_handler_t) (void*); +typedef void* user_args_t; + +void assign_dma2_stream2_user_handler(user_handler_t user_handler, user_args_t user_args); +void assign_dma2_stream3_user_handler(user_handler_t user_handler, user_args_t user_args); + +#ifdef __cplusplus +} +#endif + +#endif /* FSFW_HAL_STM32H7_INTERRUPTS_H_ */ diff --git a/stm32h7/spi/CMakeLists.txt b/stm32h7/spi/CMakeLists.txt index 99d39dd..b1a3dcb 100644 --- a/stm32h7/spi/CMakeLists.txt +++ b/stm32h7/spi/CMakeLists.txt @@ -1,4 +1,5 @@ target_sources(${TARGET_NAME} PRIVATE spiCore.c spiDefinitions.cpp + interrupts.c ) diff --git a/stm32h7/spi/interrupts.c b/stm32h7/spi/interrupts.c new file mode 100644 index 0000000..bd28771 --- /dev/null +++ b/stm32h7/spi/interrupts.c @@ -0,0 +1,12 @@ +#include "interrupts.h" + +#include + +void SPI1_IRQHandler() { + +} + +void SPI2_IRQHandler() { + +} + diff --git a/stm32h7/spi/interrupts.h b/stm32h7/spi/interrupts.h new file mode 100644 index 0000000..2c7734a --- /dev/null +++ b/stm32h7/spi/interrupts.h @@ -0,0 +1,8 @@ +#ifndef FSFW_HAL_STM32H7_INTERRUPTS_H_ +#define FSFW_HAL_STM32H7_INTERRUPTS_H_ + + + + + +#endif /* FSFW_HAL_STM32H7_INTERRUPTS_H_ */ diff --git a/stm32h7/spi/spiCore.c b/stm32h7/spi/spiCore.c index ebb956d..44aa1a4 100644 --- a/stm32h7/spi/spiCore.c +++ b/stm32h7/spi/spiCore.c @@ -25,32 +25,44 @@ SPI_HandleTypeDef* getSpiHandle() { return spiHandle; } -/** - * @brief This function handles DMA Rx interrupt request. - * @param None - * @retval None - */ -void SPIx_DMA_RX_IRQHandler(void) -{ - HAL_DMA_IRQHandler(spiHandle->hdmarx); -} - -/** - * @brief This function handles DMA Tx interrupt request. - * @param None - * @retval None - */ -void SPIx_DMA_TX_IRQHandler(void) -{ - HAL_DMA_IRQHandler(spiHandle->hdmatx); -} - -/** - * @brief This function handles SPIx interrupt request. - * @param None - * @retval None - */ -void SPIx_IRQHandler(void) -{ - HAL_SPI_IRQHandler(spiHandle); -} +///** +// * @brief This function handles DMA Rx interrupt request. +// * @param None +// * @retval None +// */ +//void SPIx_DMA_RX_IRQHandler(void) +//{ +// HAL_DMA_IRQHandler(spiHandle->hdmarx); +//} +// +///** +// * @brief This function handles DMA Tx interrupt request. +// * @param None +// * @retval None +// */ +//void SPIx_DMA_TX_IRQHandler(void) +//{ +// HAL_DMA_IRQHandler(spiHandle->hdmatx); +//} +// +//void DMA2_Stream3_IRQHandler() { +// SPIx_DMA_TX_IRQHandler(); +//} +// +//void DMA2_Stream2_IRQHandler() { +// SPIx_DMA_RX_IRQHandler(); +//} +// +///** +// * @brief This function handles SPIx interrupt request. +// * @param None +// * @retval None +// */ +//void SPIx_IRQHandler(void) +//{ +// HAL_SPI_IRQHandler(spiHandle); +//} +// +//void SPI1_IRQHandler(void) { +// SPIx_IRQHandler(); +//} From abe62d807a887d5d44df7245639f211425af15d6 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 3 Jun 2021 16:11:49 +0200 Subject: [PATCH 06/35] refactored irq code --- stm32h7/CMakeLists.txt | 1 + stm32h7/dma_interrupts.c | 84 ++++++++++++++++++++++++++++++++++++++++ stm32h7/dma_interrupts.h | 39 +++++++++++++++++++ stm32h7/interrupts.c | 33 ---------------- stm32h7/interrupts.h | 3 -- stm32h7/spi/interrupts.c | 33 ++++++++++++++-- stm32h7/spi/interrupts.h | 25 ++++++++++-- stm32h7/spi/spiCore.c | 68 +++++++++++++------------------- 8 files changed, 203 insertions(+), 83 deletions(-) create mode 100644 stm32h7/dma_interrupts.c create mode 100644 stm32h7/dma_interrupts.h diff --git a/stm32h7/CMakeLists.txt b/stm32h7/CMakeLists.txt index e568b38..ed74b99 100644 --- a/stm32h7/CMakeLists.txt +++ b/stm32h7/CMakeLists.txt @@ -3,4 +3,5 @@ add_subdirectory(devicetest) target_sources(${TARGET_NAME} PRIVATE interrupts.c + dma_interrupts.c ) diff --git a/stm32h7/dma_interrupts.c b/stm32h7/dma_interrupts.c new file mode 100644 index 0000000..db51063 --- /dev/null +++ b/stm32h7/dma_interrupts.c @@ -0,0 +1,84 @@ +#include "dma_interrupts.h" + +#include +#include + +user_handler_t DMA_1_USER_HANDLERS[8]; +user_args_t DMA_1_USER_ARGS[8]; + +user_handler_t DMA_2_USER_HANDLERS[8]; +user_args_t DMA_2_USER_ARGS[8]; + +void assign_dma_user_handler(DMAIndexes dma_idx, DMAStreams stream_idx, + user_handler_t user_handler, user_args_t user_args) { + if(dma_idx == DMA_1) { + DMA_1_USER_HANDLERS[stream_idx] = user_handler; + DMA_1_USER_ARGS[stream_idx] = user_args; + } + else if(dma_idx == DMA_2) { + DMA_2_USER_HANDLERS[stream_idx] = user_handler; + DMA_2_USER_ARGS[stream_idx] = user_args; + } +} + +// The interrupt handlers in the format required for the IRQ vector table + +/* Do not change these function names! They need to be exactly equal to the name of the functions +defined in the startup_stm32h743xx.s files! */ + +#define GENERIC_DMA_IRQ_HANDLER(DMA_IDX, STREAM_IDX) \ + if(DMA_##DMA_IDX##_USER_HANDLERS[STREAM_IDX] != NULL) { \ + DMA_##DMA_IDX##_USER_HANDLERS[STREAM_IDX](DMA_##DMA_IDX##_USER_ARGS[STREAM_IDX]); \ + return; \ + } \ + Default_Handler() \ + +void DMA1_Stream0_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(1, 0); +} +void DMA1_Stream1_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(1, 1); +} +void DMA1_Stream2_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(1, 2); +} +void DMA1_Stream3_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(1, 3); +} +void DMA1_Stream4_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(1, 4); +} +void DMA1_Stream5_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(1, 5); +} +void DMA1_Stream6_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(1, 6); +} +void DMA1_Stream7_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(1, 7); +} + +void DMA2_Stream0_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(2, 0); +} +void DMA2_Stream1_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(2, 1); +} +void DMA2_Stream2_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(2, 2); +} +void DMA2_Stream3_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(2, 3); +} +void DMA2_Stream4_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(2, 4); +} +void DMA2_Stream5_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(2, 5); +} +void DMA2_Stream6_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(2, 6); +} +void DMA2_Stream7_IRQHandler() { + GENERIC_DMA_IRQ_HANDLER(2, 7); +} diff --git a/stm32h7/dma_interrupts.h b/stm32h7/dma_interrupts.h new file mode 100644 index 0000000..b28310f --- /dev/null +++ b/stm32h7/dma_interrupts.h @@ -0,0 +1,39 @@ +#ifndef FSFW_HAL_STM32H7_DMA_INTERRUPTS_H_ +#define FSFW_HAL_STM32H7_DMA_INTERRUPTS_H_ + +#include "interrupts.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + DMA_1 = 0, + DMA_2 = 1 +} DMAIndexes; + +typedef enum { + STREAM_0 = 0, + STREAM_1 = 1, + STREAM_2 = 2, + STREAM_3 = 3, + STREAM_4 = 4, + STREAM_5 = 5, + STREAM_6 = 6, + STREAM_7 = 7, +} DMAStreams; + +/** + * Assign user interrupt handlers for DMA streams, allowing to pass an + * arbitrary argument as well. Generally, this argument will be the related DMA handle. + * @param user_handler + * @param user_args + */ +void assign_dma_user_handler(DMAIndexes dma_idx, DMAStreams stream_idx, + user_handler_t user_handler, user_args_t user_args); + +#ifdef __cplusplus +} +#endif + +#endif /* FSFW_HAL_STM32H7_DMA_INTERRUPTS_H_ */ diff --git a/stm32h7/interrupts.c b/stm32h7/interrupts.c index 99e0272..4987edd 100644 --- a/stm32h7/interrupts.c +++ b/stm32h7/interrupts.c @@ -1,35 +1,2 @@ #include "interrupts.h" - #include - -void Default_Handler(); - -void (*dma2_stream3_user_handler) (void* args) = NULL; -void * dma2_stream3_user_args = NULL; - -void (*dma2_stream2_user_handler) (void* args) = NULL; -void * dma2_stream2_user_args = NULL; - -void assign_dma2_stream2_user_handler(user_handler_t user_handler, user_args_t user_args) { - dma2_stream2_user_handler = user_handler; - dma2_stream2_user_args = user_args; -} - -void assign_dma2_stream3_user_handler(user_handler_t user_handler, user_args_t user_args) { - dma2_stream3_user_handler = user_handler; - dma2_stream3_user_args = user_args; -} - -void DMA2_Stream3_IRQHandler() { - if(dma2_stream3_user_handler != NULL) { - dma2_stream3_user_handler(dma2_stream3_user_args); - } - Default_Handler(); -} - -void DMA2_Stream2_IRQHandler() { - if(dma2_stream2_user_handler != NULL) { - dma2_stream2_user_handler(dma2_stream2_user_args); - } - Default_Handler(); -} diff --git a/stm32h7/interrupts.h b/stm32h7/interrupts.h index de4ba81..00c8a79 100644 --- a/stm32h7/interrupts.h +++ b/stm32h7/interrupts.h @@ -13,9 +13,6 @@ extern void Default_Handler(); typedef void (*user_handler_t) (void*); typedef void* user_args_t; -void assign_dma2_stream2_user_handler(user_handler_t user_handler, user_args_t user_args); -void assign_dma2_stream3_user_handler(user_handler_t user_handler, user_args_t user_args); - #ifdef __cplusplus } #endif diff --git a/stm32h7/spi/interrupts.c b/stm32h7/spi/interrupts.c index bd28771..90e1047 100644 --- a/stm32h7/spi/interrupts.c +++ b/stm32h7/spi/interrupts.c @@ -2,11 +2,38 @@ #include -void SPI1_IRQHandler() { +void (*spi1_user_handler) (void* args) = NULL; +void * spi1_user_args = NULL; +void (*spi2_user_handler) (void* args) = NULL; +void * spi2_user_args = NULL; + +void assign_spi_user_handler(SpiBus spi_idx, user_handler_t user_handler, user_args_t user_args) { + if(spi_idx == SPI_1) { + spi1_user_handler = user_handler; + spi1_user_args = user_args; + } + else { + spi2_user_handler = user_handler; + spi2_user_args = user_args; + } +} + +/* Do not change these function names! They need to be exactly equal to the name of the functions +defined in the startup_stm32h743xx.s files! */ + +void SPI1_IRQHandler() { + if(spi1_user_handler != NULL) { + spi1_user_handler(spi1_user_args); + return; + } + Default_Handler(); } void SPI2_IRQHandler() { - + if(spi2_user_handler != NULL) { + spi2_user_handler(spi2_user_args); + return; + } + Default_Handler(); } - diff --git a/stm32h7/spi/interrupts.h b/stm32h7/spi/interrupts.h index 2c7734a..60d8fa0 100644 --- a/stm32h7/spi/interrupts.h +++ b/stm32h7/spi/interrupts.h @@ -1,8 +1,27 @@ -#ifndef FSFW_HAL_STM32H7_INTERRUPTS_H_ -#define FSFW_HAL_STM32H7_INTERRUPTS_H_ +#ifndef FSFW_HAL_STM32H7_SPI_INTERRUPTS_H_ +#define FSFW_HAL_STM32H7_SPI_INTERRUPTS_H_ +#include "../interrupts.h" +#ifdef __cplusplus +extern "C" { +#endif +typedef enum { + SPI_1, + SPI_2 +} SpiBus; +/** + * Assign a user interrupt handler for SPI bus 1, allowing to pass an arbitrary argument as well. + * Generally, this argument will be the related SPI handle. + * @param user_handler + * @param user_args + */ +void assign_spi_user_handler(SpiBus spiBus, user_handler_t user_handler, user_args_t user_args); -#endif /* FSFW_HAL_STM32H7_INTERRUPTS_H_ */ +#ifdef __cplusplus +} +#endif + +#endif /* FSFW_HAL_STM32H7_SPI_INTERRUPTS_H_ */ diff --git a/stm32h7/spi/spiCore.c b/stm32h7/spi/spiCore.c index 44aa1a4..1d81b5e 100644 --- a/stm32h7/spi/spiCore.c +++ b/stm32h7/spi/spiCore.c @@ -25,44 +25,30 @@ SPI_HandleTypeDef* getSpiHandle() { return spiHandle; } -///** -// * @brief This function handles DMA Rx interrupt request. -// * @param None -// * @retval None -// */ -//void SPIx_DMA_RX_IRQHandler(void) -//{ -// HAL_DMA_IRQHandler(spiHandle->hdmarx); -//} -// -///** -// * @brief This function handles DMA Tx interrupt request. -// * @param None -// * @retval None -// */ -//void SPIx_DMA_TX_IRQHandler(void) -//{ -// HAL_DMA_IRQHandler(spiHandle->hdmatx); -//} -// -//void DMA2_Stream3_IRQHandler() { -// SPIx_DMA_TX_IRQHandler(); -//} -// -//void DMA2_Stream2_IRQHandler() { -// SPIx_DMA_RX_IRQHandler(); -//} -// -///** -// * @brief This function handles SPIx interrupt request. -// * @param None -// * @retval None -// */ -//void SPIx_IRQHandler(void) -//{ -// HAL_SPI_IRQHandler(spiHandle); -//} -// -//void SPI1_IRQHandler(void) { -// SPIx_IRQHandler(); -//} +/** + * @brief This function handles DMA Rx interrupt request. + * @param None + * @retval None + */ +void dma_rx_irq_handler(void* dma_handle) { + HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dma_handle); +} + +/** + * @brief This function handles DMA Rx interrupt request. + * @param None + * @retval None + */ +void dma_tx_irq_handler(void* dma_handle) { + HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dma_handle); +} + +/** + * @brief This function handles SPIx interrupt request. + * @param None + * @retval None + */ +void spi1_irq_handler(void* spi_handle) +{ + HAL_SPI_IRQHandler((SPI_HandleTypeDef *) spi_handle); +} From a9390b145bb19e98809e36d26187be91c8cdc73c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 3 Jun 2021 16:44:02 +0200 Subject: [PATCH 07/35] stll some issues --- stm32h7/devicetest/GyroL3GD20H.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index fad9923..10e5335 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -17,12 +17,17 @@ DMA_HandleTypeDef rxDmaHandle; GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle): spiHandle(spiHandle) { setDmaHandles(&txDmaHandle, &rxDmaHandle); + GPIO_InitTypeDef chipSelect = {}; + chipSelect.Pin = GPIO_PIN_14; + chipSelect.Mode = GPIO_MODE_OUTPUT_PP; + HAL_GPIO_Init(GPIOD, &chipSelect); + HAL_GPIO_WritePin(GPIOD, 14, GPIO_PIN_SET); } ReturnValue_t GyroL3GD20H::initialize() { // Configure the SPI peripheral spiHandle->Instance = SPI1; - uint32_t test = HAL_RCC_GetHCLKFreq(); + //uint32_t test = HAL_RCC_GetHCLKFreq(); spiHandle->Init.BaudRatePrescaler = spi::getPrescaler(HAL_RCC_GetHCLKFreq(), 3900000); spiHandle->Init.Direction = SPI_DIRECTION_2LINES; spi::assignSpiMode(spi::SpiModes::MODE_3, spiHandle); @@ -47,7 +52,18 @@ ReturnValue_t GyroL3GD20H::initialize() { ReturnValue_t GyroL3GD20H::performOperation() { transferState = TransferStates::WAIT; + + const uint8_t WHO_AM_I_REG = 0b00001111; + const uint8_t STM_READ_MASK = 0b10000000; + const uint8_t EXPECTED_WHO_AM_I_VAL = 0b11010111; + + sif::printInfo("GyroL3GD20H::performOperation: Reading WHO AM I register\n"); + + txBuffer[0] = WHO_AM_I_REG | STM_READ_MASK; + txBuffer[1] = 0; + // Start SPI transfer via DMA + HAL_GPIO_WritePin(GPIOD, 14, GPIO_PIN_RESET); if(HAL_SPI_TransmitReceive_DMA(spiHandle, txBuffer.data(), rxBuffer.data(), 2) != HAL_OK) { // Transfer error in transmission process sif::printWarning("Error transmitting SPI with DMA\n"); @@ -64,6 +80,11 @@ ReturnValue_t GyroL3GD20H::performOperation() { switch(transferState) { case(TransferStates::SUCCESS): { sif::printInfo("Transfer success\n"); + uint8_t whoAmIVal = rxBuffer[1]; + if(whoAmIVal != EXPECTED_WHO_AM_I_VAL) { + sif::printDebug("GyroL3GD20H::performOperation: " + "Read WHO AM I value not equal to expected value!\n"); + } transferState = TransferStates::IDLE; break; } @@ -88,6 +109,7 @@ ReturnValue_t GyroL3GD20H::performOperation() { */ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { transferState = TransferStates::SUCCESS; + HAL_GPIO_WritePin(GPIOD, 14, GPIO_PIN_SET); } /** From 863dfa68a0bdc3a5c82c7c523762848ba14ea297 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 3 Jun 2021 21:42:52 +0200 Subject: [PATCH 08/35] added msp init functions --- stm32h7/devicetest/GyroL3GD20H.cpp | 18 +-- stm32h7/spi/CMakeLists.txt | 1 + stm32h7/spi/mspInit.c | 192 +++++++++++++++++++++++++++++ stm32h7/spi/mspInit.h | 15 +++ stm32h7/spi/spiCore.c | 73 ++++++++++- stm32h7/spi/spiCore.h | 22 +++- 6 files changed, 305 insertions(+), 16 deletions(-) create mode 100644 stm32h7/spi/mspInit.c create mode 100644 stm32h7/spi/mspInit.h diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index 10e5335..736ec2f 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -1,6 +1,6 @@ #include "GyroL3GD20H.h" -#include "stm32h7xx_spi_dma_msp.h" #include "spiConf.h" +#include "../spi/mspInit.h" #include "../spi/spiDefinitions.h" #include "../spi/spiCore.h" @@ -9,6 +9,7 @@ #include "stm32h7xx_nucleo.h" #include "stm32h7xx_hal_spi.h" +#include "stm32h7xx_hal_rcc.h" std::array GyroL3GD20H::rxBuffer; TransferStates transferState = TransferStates::IDLE; @@ -16,18 +17,19 @@ DMA_HandleTypeDef txDmaHandle; DMA_HandleTypeDef rxDmaHandle; GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle): spiHandle(spiHandle) { - setDmaHandles(&txDmaHandle, &rxDmaHandle); + set_dma_handles(&txDmaHandle, &rxDmaHandle); + set_spi_msp_functions(&hal_spi_msp_init_dma, spiHandle, &hal_spi_msp_deinit_dma, spiHandle); GPIO_InitTypeDef chipSelect = {}; + __HAL_RCC_GPIOD_CLK_ENABLE(); chipSelect.Pin = GPIO_PIN_14; chipSelect.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(GPIOD, &chipSelect); - HAL_GPIO_WritePin(GPIOD, 14, GPIO_PIN_SET); + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); } ReturnValue_t GyroL3GD20H::initialize() { // Configure the SPI peripheral spiHandle->Instance = SPI1; - //uint32_t test = HAL_RCC_GetHCLKFreq(); spiHandle->Init.BaudRatePrescaler = spi::getPrescaler(HAL_RCC_GetHCLKFreq(), 3900000); spiHandle->Init.Direction = SPI_DIRECTION_2LINES; spi::assignSpiMode(spi::SpiModes::MODE_3, spiHandle); @@ -63,7 +65,7 @@ ReturnValue_t GyroL3GD20H::performOperation() { txBuffer[1] = 0; // Start SPI transfer via DMA - HAL_GPIO_WritePin(GPIOD, 14, GPIO_PIN_RESET); + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); if(HAL_SPI_TransmitReceive_DMA(spiHandle, txBuffer.data(), rxBuffer.data(), 2) != HAL_OK) { // Transfer error in transmission process sif::printWarning("Error transmitting SPI with DMA\n"); @@ -71,7 +73,7 @@ ReturnValue_t GyroL3GD20H::performOperation() { // Wait for the transfer to complete while (transferState == TransferStates::WAIT) { - TaskFactory::delayTask(1); + //TaskFactory::delayTask(1); } // Invalidate cache prior to access by CPU @@ -83,7 +85,7 @@ ReturnValue_t GyroL3GD20H::performOperation() { uint8_t whoAmIVal = rxBuffer[1]; if(whoAmIVal != EXPECTED_WHO_AM_I_VAL) { sif::printDebug("GyroL3GD20H::performOperation: " - "Read WHO AM I value not equal to expected value!\n"); + "Read WHO AM I value %d not equal to expected value!\n", whoAmIVal); } transferState = TransferStates::IDLE; break; @@ -109,7 +111,7 @@ ReturnValue_t GyroL3GD20H::performOperation() { */ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { transferState = TransferStates::SUCCESS; - HAL_GPIO_WritePin(GPIOD, 14, GPIO_PIN_SET); + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); } /** diff --git a/stm32h7/spi/CMakeLists.txt b/stm32h7/spi/CMakeLists.txt index b1a3dcb..ea980e0 100644 --- a/stm32h7/spi/CMakeLists.txt +++ b/stm32h7/spi/CMakeLists.txt @@ -2,4 +2,5 @@ target_sources(${TARGET_NAME} PRIVATE spiCore.c spiDefinitions.cpp interrupts.c + mspInit.c ) diff --git a/stm32h7/spi/mspInit.c b/stm32h7/spi/mspInit.c new file mode 100644 index 0000000..864f3da --- /dev/null +++ b/stm32h7/spi/mspInit.c @@ -0,0 +1,192 @@ +#include "mspInit.h" +#include "spiConf.h" +#include "spiCore.h" +#include "../dma_interrupts.h" +#include "interrupts.h" + +#include "stm32h743xx.h" +#include "stm32h7xx_hal_spi.h" +#include "stm32h7xx_hal_dma.h" +#include "stm32h7xx_hal_def.h" + +#include + +void dma_rx_irq_handler(void* dma_handle); +void dma_tx_irq_handler(void* dma_handle); +void spi1_irq_handler(void* spi_handle); + +/** + * @brief SPI MSP Initialization + * This function configures the hardware resources used in this example: + * - Peripheral's clock enable + * - Peripheral's GPIO Configuration + * - DMA configuration for transmission request by peripheral + * - NVIC configuration for DMA interrupt request enable + * @param hspi: SPI handle pointer + * @retval None + */ +void hal_spi_msp_init_dma(void *spi_handle) { + SPI_HandleTypeDef* hspi = (SPI_HandleTypeDef*) spi_handle; + if(hspi == NULL) { + return; + } + if(hspi == NULL) { + printf("HAL_SPI_MspInit: Invalid SPI handle!\n"); + return; + } + assign_spi_handle(hspi); + + DMA_HandleTypeDef* hdma_tx = NULL; + DMA_HandleTypeDef* hdma_rx = NULL; + get_dma_handles(&hdma_tx, &hdma_rx); + if(hdma_tx == NULL || hdma_rx == NULL) { + printf("HAL_SPI_MspInit: Invalid DMA handles. Make sure to call setDmaHandles!\n"); + return; + } + + GPIO_InitTypeDef GPIO_InitStruct; + if (hspi->Instance == SPI1) + { + /*##-1- Enable peripherals and GPIO Clocks #################################*/ + /* Enable GPIO TX/RX clock */ + SPIx_SCK_GPIO_CLK_ENABLE(); + SPIx_MISO_GPIO_CLK_ENABLE(); + SPIx_MOSI_GPIO_CLK_ENABLE(); + /* Enable SPI1 clock */ + SPIx_CLK_ENABLE(); + /* Enable DMA clock */ + DMAx_CLK_ENABLE(); + + /*##-2- Configure peripheral GPIO ##########################################*/ + /* SPI SCK GPIO pin configuration */ + GPIO_InitStruct.Pin = SPIx_SCK_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = SPIx_SCK_AF; + HAL_GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStruct); + + /* SPI MISO GPIO pin configuration */ + GPIO_InitStruct.Pin = SPIx_MISO_PIN; + GPIO_InitStruct.Alternate = SPIx_MISO_AF; + HAL_GPIO_Init(SPIx_MISO_GPIO_PORT, &GPIO_InitStruct); + + /* SPI MOSI GPIO pin configuration */ + GPIO_InitStruct.Pin = SPIx_MOSI_PIN; + GPIO_InitStruct.Alternate = SPIx_MOSI_AF; + HAL_GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStruct); + + /*##-3- Configure the DMA ##################################################*/ + /* Configure the DMA handler for Transmission process */ + hdma_tx->Instance = SPIx_TX_DMA_STREAM; + hdma_tx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_tx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_tx->Init.MemBurst = DMA_MBURST_INC4; + hdma_tx->Init.PeriphBurst = DMA_PBURST_INC4; + hdma_tx->Init.Request = SPIx_TX_DMA_REQUEST; + hdma_tx->Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_tx->Init.PeriphInc = DMA_PINC_DISABLE; + hdma_tx->Init.MemInc = DMA_MINC_ENABLE; + hdma_tx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_tx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_tx->Init.Mode = DMA_NORMAL; + hdma_tx->Init.Priority = DMA_PRIORITY_LOW; + + HAL_DMA_Init(hdma_tx); + + /* Associate the initialized DMA handle to the the SPI handle */ + __HAL_LINKDMA(hspi, hdmatx, *hdma_tx); + + /* Configure the DMA handler for Transmission process */ + hdma_rx->Instance = SPIx_RX_DMA_STREAM; + + hdma_rx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_rx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_rx->Init.MemBurst = DMA_MBURST_INC4; + hdma_rx->Init.PeriphBurst = DMA_PBURST_INC4; + hdma_rx->Init.Request = SPIx_RX_DMA_REQUEST; + hdma_rx->Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_rx->Init.PeriphInc = DMA_PINC_DISABLE; + hdma_rx->Init.MemInc = DMA_MINC_ENABLE; + hdma_rx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_rx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_rx->Init.Mode = DMA_NORMAL; + hdma_rx->Init.Priority = DMA_PRIORITY_HIGH; + + HAL_DMA_Init(hdma_rx); + + /* Associate the initialized DMA handle to the the SPI handle */ + __HAL_LINKDMA(hspi, hdmarx, *hdma_rx); + + /*##-4- Configure the NVIC for DMA #########################################*/ + /* NVIC configuration for DMA transfer complete interrupt (SPI1_RX) */ + // Assign the interrupt handler + assign_dma_user_handler(DMA_2, 2, &dma_rx_irq_handler, hdma_rx); + HAL_NVIC_SetPriority(SPIx_DMA_RX_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(SPIx_DMA_RX_IRQn); + + /* NVIC configuration for DMA transfer complete interrupt (SPI1_TX) */ + // Assign the interrupt handler + assign_dma_user_handler(DMA_2, 3, &dma_tx_irq_handler, hdma_tx); + HAL_NVIC_SetPriority(SPIx_DMA_TX_IRQn, 1, 1); + HAL_NVIC_EnableIRQ(SPIx_DMA_TX_IRQn); + + /*##-5- Configure the NVIC for SPI #########################################*/ + /* NVIC configuration for SPI transfer complete interrupt (SPI1) */ + // Assign the interrupt handler + assign_spi_user_handler(SPI_1, &spi1_irq_handler, hspi); + HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(SPIx_IRQn); + } +} + +/** + * @brief SPI MSP De-Initialization + * This function frees the hardware resources used in this example: + * - Disable the Peripheral's clock + * - Revert GPIO, DMA and NVIC configuration to their default state + * @param hspi: SPI handle pointer + * @retval None + */ +void hal_spi_msp_deinit_dma(void *spi_handle) +{ + SPI_HandleTypeDef* hspi = (SPI_HandleTypeDef*) spi_handle; + if(hspi == NULL) { + return; + } + if(hspi->Instance == SPIx) + { + /*##-1- Reset peripherals ##################################################*/ + SPIx_FORCE_RESET(); + SPIx_RELEASE_RESET(); + + /*##-2- Disable peripherals and GPIO Clocks ################################*/ + /* Deconfigure SPI SCK */ + HAL_GPIO_DeInit(SPIx_SCK_GPIO_PORT, SPIx_SCK_PIN); + /* Deconfigure SPI MISO */ + HAL_GPIO_DeInit(SPIx_MISO_GPIO_PORT, SPIx_MISO_PIN); + /* Deconfigure SPI MOSI */ + HAL_GPIO_DeInit(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_PIN); + + DMA_HandleTypeDef* hdma_tx = NULL; + DMA_HandleTypeDef* hdma_rx = NULL; + get_dma_handles(&hdma_tx, &hdma_rx); + if(hdma_tx == NULL || hdma_rx == NULL) { + printf("HAL_SPI_MspInit: Invalid DMA handles. Make sure to call setDmaHandles!\n"); + } + else { + /*##-3- Disable the DMA ####################################################*/ + /* De-Initialize the DMA associated to transmission process */ + HAL_DMA_DeInit(hdma_tx); + /* De-Initialize the DMA associated to reception process */ + HAL_DMA_DeInit(hdma_rx); + } + + /*##-4- Disable the NVIC for DMA ###########################################*/ + HAL_NVIC_DisableIRQ(SPIx_DMA_TX_IRQn); + HAL_NVIC_DisableIRQ(SPIx_DMA_RX_IRQn); + + /*##-5- Disable the NVIC for SPI ###########################################*/ + HAL_NVIC_EnableIRQ(SPIx_IRQn); + } +} diff --git a/stm32h7/spi/mspInit.h b/stm32h7/spi/mspInit.h new file mode 100644 index 0000000..9ac8562 --- /dev/null +++ b/stm32h7/spi/mspInit.h @@ -0,0 +1,15 @@ +#ifndef FSFW_HAL_STM32H7_SPI_MSPINIT_H_ +#define FSFW_HAL_STM32H7_SPI_MSPINIT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void hal_spi_msp_init_dma(void *hspi); +void hal_spi_msp_deinit_dma(void *hspi); + +#ifdef __cplusplus +} +#endif + +#endif /* FSFW_HAL_STM32H7_SPI_MSPINIT_H_ */ diff --git a/stm32h7/spi/spiCore.c b/stm32h7/spi/spiCore.c index 1d81b5e..2516dbf 100644 --- a/stm32h7/spi/spiCore.c +++ b/stm32h7/spi/spiCore.c @@ -1,27 +1,34 @@ #include "spiCore.h" +#include SPI_HandleTypeDef* spiHandle = NULL; DMA_HandleTypeDef* hdma_tx = NULL; DMA_HandleTypeDef* hdma_rx = NULL; -void setDmaHandles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle) { +msp_func_t msp_init_func = NULL; +void* msp_init_args = NULL; + +msp_func_t msp_deinit_func = NULL; +void* msp_deinit_args = NULL; + +void set_dma_handles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle) { hdma_tx = txHandle; hdma_rx = rxHandle; } -void getDmaHandles(DMA_HandleTypeDef** txHandle, DMA_HandleTypeDef** rxHandle) { +void get_dma_handles(DMA_HandleTypeDef** txHandle, DMA_HandleTypeDef** rxHandle) { *txHandle = hdma_tx; *rxHandle = hdma_rx; } -void assignSpiHandle(SPI_HandleTypeDef *spiHandle_) { +void assign_spi_handle(SPI_HandleTypeDef *spiHandle_) { if(spiHandle_ == NULL) { return; } spiHandle = spiHandle_; } -SPI_HandleTypeDef* getSpiHandle() { +SPI_HandleTypeDef* get_spi_handle() { return spiHandle; } @@ -52,3 +59,61 @@ void spi1_irq_handler(void* spi_handle) { HAL_SPI_IRQHandler((SPI_HandleTypeDef *) spi_handle); } + +void set_spi_msp_functions(msp_func_t init_func, void* init_args, msp_func_t deinit_func, + void* deinit_args) { + msp_init_func = init_func; + msp_init_args = init_args; + msp_deinit_func = deinit_func; + msp_deinit_args = deinit_args; +} + +void get_msp_init_function(msp_func_t* init_func, void **args) { + if(init_func != NULL && args != NULL) { + *init_func = msp_init_func; + *args = msp_init_args; + } +} + +void get_msp_deinit_function(msp_func_t* deinit_func, void **args) { + if(deinit_func != NULL && args != NULL) { + *deinit_func = msp_deinit_func; + *args = msp_deinit_args; + } +} + +/** + * @brief SPI MSP Initialization + * This function configures the hardware resources used in this example: + * - Peripheral's clock enable + * - Peripheral's GPIO Configuration + * - DMA configuration for transmission request by peripheral + * - NVIC configuration for DMA interrupt request enable + * @param hspi: SPI handle pointer + * @retval None + */ +void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) { + if(msp_init_func != NULL) { + msp_init_func(msp_init_args); + } + else { + printf("HAL_SPI_MspInit: Please call set_msp_functions to assign SPI MSP functions\n"); + } +} + +/** + * @brief SPI MSP De-Initialization + * This function frees the hardware resources used in this example: + * - Disable the Peripheral's clock + * - Revert GPIO, DMA and NVIC configuration to their default state + * @param hspi: SPI handle pointer + * @retval None + */ +void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) { + if(msp_deinit_func != NULL) { + msp_deinit_func(msp_deinit_args); + } + else { + printf("HAL_SPI_MspDeInit: Please call set_msp_functions to assign SPI MSP functions\n"); + } +} diff --git a/stm32h7/spi/spiCore.h b/stm32h7/spi/spiCore.h index 9af0de0..75d4eca 100644 --- a/stm32h7/spi/spiCore.h +++ b/stm32h7/spi/spiCore.h @@ -8,26 +8,40 @@ extern "C" { #endif +typedef void (*msp_func_t) (void* args); + +/** + * Assign MSP init functions. Important for SPI configuration + * @param init_func + * @param init_args + * @param deinit_func + * @param deinit_args + */ +void set_spi_msp_functions(msp_func_t init_func, void* init_args, msp_func_t deinit_func, + void* deinit_args); + /** * Assign DMA handles. Required to use DMA for SPI transfers. * @param txHandle * @param rxHandle */ -void setDmaHandles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle); +void set_dma_handles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle); -void getDmaHandles(DMA_HandleTypeDef** txHandle, DMA_HandleTypeDef** rxHandle); +void get_dma_handles(DMA_HandleTypeDef** txHandle, DMA_HandleTypeDef** rxHandle); +void get_msp_init_function(msp_func_t* init_func, void **args); +void get_msp_deinit_function(msp_func_t* deinit_func, void **args); /** * Assign SPI handle. Needs to be done before using the SPI * @param spiHandle */ -void assignSpiHandle(SPI_HandleTypeDef *spiHandle); +void assign_spi_handle(SPI_HandleTypeDef *spiHandle); /** * Get the assigned SPI handle. * @return */ -SPI_HandleTypeDef* getSpiHandle(); +SPI_HandleTypeDef* get_spi_handle(); #ifdef __cplusplus } From 66a7a4dbbe9b6913ddab3369e2076ca9105f1336 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 3 Jun 2021 21:49:16 +0200 Subject: [PATCH 09/35] added polling msp init --- stm32h7/spi/mspInit.c | 95 +++++++++++++++++++++++-------------------- stm32h7/spi/mspInit.h | 3 ++ 2 files changed, 53 insertions(+), 45 deletions(-) diff --git a/stm32h7/spi/mspInit.c b/stm32h7/spi/mspInit.c index 864f3da..1964391 100644 --- a/stm32h7/spi/mspInit.c +++ b/stm32h7/spi/mspInit.c @@ -44,39 +44,12 @@ void hal_spi_msp_init_dma(void *spi_handle) { return; } - GPIO_InitTypeDef GPIO_InitStruct; - if (hspi->Instance == SPI1) - { - /*##-1- Enable peripherals and GPIO Clocks #################################*/ - /* Enable GPIO TX/RX clock */ - SPIx_SCK_GPIO_CLK_ENABLE(); - SPIx_MISO_GPIO_CLK_ENABLE(); - SPIx_MOSI_GPIO_CLK_ENABLE(); - /* Enable SPI1 clock */ - SPIx_CLK_ENABLE(); - /* Enable DMA clock */ + hal_spi_msp_init_polling(spi_handle); + if (hspi->Instance == SPI1) { + // DMA setup DMAx_CLK_ENABLE(); - /*##-2- Configure peripheral GPIO ##########################################*/ - /* SPI SCK GPIO pin configuration */ - GPIO_InitStruct.Pin = SPIx_SCK_PIN; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_PULLDOWN; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = SPIx_SCK_AF; - HAL_GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStruct); - - /* SPI MISO GPIO pin configuration */ - GPIO_InitStruct.Pin = SPIx_MISO_PIN; - GPIO_InitStruct.Alternate = SPIx_MISO_AF; - HAL_GPIO_Init(SPIx_MISO_GPIO_PORT, &GPIO_InitStruct); - - /* SPI MOSI GPIO pin configuration */ - GPIO_InitStruct.Pin = SPIx_MOSI_PIN; - GPIO_InitStruct.Alternate = SPIx_MOSI_AF; - HAL_GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStruct); - - /*##-3- Configure the DMA ##################################################*/ + // Configure the DMA /* Configure the DMA handler for Transmission process */ hdma_tx->Instance = SPIx_TX_DMA_STREAM; hdma_tx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; @@ -154,20 +127,8 @@ void hal_spi_msp_deinit_dma(void *spi_handle) if(hspi == NULL) { return; } - if(hspi->Instance == SPIx) - { - /*##-1- Reset peripherals ##################################################*/ - SPIx_FORCE_RESET(); - SPIx_RELEASE_RESET(); - - /*##-2- Disable peripherals and GPIO Clocks ################################*/ - /* Deconfigure SPI SCK */ - HAL_GPIO_DeInit(SPIx_SCK_GPIO_PORT, SPIx_SCK_PIN); - /* Deconfigure SPI MISO */ - HAL_GPIO_DeInit(SPIx_MISO_GPIO_PORT, SPIx_MISO_PIN); - /* Deconfigure SPI MOSI */ - HAL_GPIO_DeInit(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_PIN); - + hal_spi_msp_deinit_polling(spi_handle); + if(hspi->Instance == SPIx) { DMA_HandleTypeDef* hdma_tx = NULL; DMA_HandleTypeDef* hdma_rx = NULL; get_dma_handles(&hdma_tx, &hdma_rx); @@ -190,3 +151,47 @@ void hal_spi_msp_deinit_dma(void *spi_handle) HAL_NVIC_EnableIRQ(SPIx_IRQn); } } + +void hal_spi_msp_init_polling(void *hspi) { + GPIO_InitTypeDef GPIO_InitStruct = {}; + /*##-1- Enable peripherals and GPIO Clocks #################################*/ + /* Enable GPIO TX/RX clock */ + SPIx_SCK_GPIO_CLK_ENABLE(); + SPIx_MISO_GPIO_CLK_ENABLE(); + SPIx_MOSI_GPIO_CLK_ENABLE(); + /* Enable SPI clock */ + SPIx_CLK_ENABLE(); + + /*##-2- Configure peripheral GPIO ##########################################*/ + /* SPI SCK GPIO pin configuration */ + GPIO_InitStruct.Pin = SPIx_SCK_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = SPIx_SCK_AF; + HAL_GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStruct); + + /* SPI MISO GPIO pin configuration */ + GPIO_InitStruct.Pin = SPIx_MISO_PIN; + GPIO_InitStruct.Alternate = SPIx_MISO_AF; + HAL_GPIO_Init(SPIx_MISO_GPIO_PORT, &GPIO_InitStruct); + + /* SPI MOSI GPIO pin configuration */ + GPIO_InitStruct.Pin = SPIx_MOSI_PIN; + GPIO_InitStruct.Alternate = SPIx_MOSI_AF; + HAL_GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStruct); +} + +void hal_spi_msp_deinit_polling(void *hspi) { + /*##-1- Reset peripherals ##################################################*/ + SPIx_FORCE_RESET(); + SPIx_RELEASE_RESET(); + + /*##-2- Disable peripherals and GPIO Clocks ################################*/ + /* Configure SPI SCK as alternate function */ + HAL_GPIO_DeInit(SPIx_SCK_GPIO_PORT, SPIx_SCK_PIN); + /* Configure SPI MISO as alternate function */ + HAL_GPIO_DeInit(SPIx_MISO_GPIO_PORT, SPIx_MISO_PIN); + /* Configure SPI MOSI as alternate function */ + HAL_GPIO_DeInit(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_PIN); +} diff --git a/stm32h7/spi/mspInit.h b/stm32h7/spi/mspInit.h index 9ac8562..48ac7b1 100644 --- a/stm32h7/spi/mspInit.h +++ b/stm32h7/spi/mspInit.h @@ -8,6 +8,9 @@ extern "C" { void hal_spi_msp_init_dma(void *hspi); void hal_spi_msp_deinit_dma(void *hspi); +void hal_spi_msp_init_polling(void *hspi); +void hal_spi_msp_deinit_polling(void *hspi); + #ifdef __cplusplus } #endif From ff7421e1ddf92f6d35aae6f38dd3876ba719cdc6 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 3 Jun 2021 21:53:52 +0200 Subject: [PATCH 10/35] added spi transfer modes --- stm32h7/devicetest/GyroL3GD20H.cpp | 3 ++- stm32h7/devicetest/GyroL3GD20H.h | 4 +++- stm32h7/spi/spiDefinitions.h | 6 ++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index 736ec2f..30bd381 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -16,7 +16,8 @@ TransferStates transferState = TransferStates::IDLE; DMA_HandleTypeDef txDmaHandle; DMA_HandleTypeDef rxDmaHandle; -GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle): spiHandle(spiHandle) { +GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transferMode): + spiHandle(spiHandle), transferMode(transferMode) { set_dma_handles(&txDmaHandle, &rxDmaHandle); set_spi_msp_functions(&hal_spi_msp_init_dma, spiHandle, &hal_spi_msp_deinit_dma, spiHandle); GPIO_InitTypeDef chipSelect = {}; diff --git a/stm32h7/devicetest/GyroL3GD20H.h b/stm32h7/devicetest/GyroL3GD20H.h index 2a5b991..e9dacb0 100644 --- a/stm32h7/devicetest/GyroL3GD20H.h +++ b/stm32h7/devicetest/GyroL3GD20H.h @@ -4,6 +4,7 @@ #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_spi.h" +#include "../spi/spiDefinitions.h" #include "fsfw/returnvalues/HasReturnvaluesIF.h" #include @@ -18,7 +19,7 @@ enum class TransferStates { class GyroL3GD20H { public: - GyroL3GD20H(SPI_HandleTypeDef* spiHandle); + GyroL3GD20H(SPI_HandleTypeDef* spiHandle, spi::TransferModes transferMode); ReturnValue_t initialize(); ReturnValue_t performOperation(); @@ -26,6 +27,7 @@ public: private: SPI_HandleTypeDef* spiHandle; + spi::TransferModes transferMode; static constexpr size_t recvBufferSize = 32 * 10; static std::array rxBuffer; std::array txBuffer; diff --git a/stm32h7/spi/spiDefinitions.h b/stm32h7/spi/spiDefinitions.h index ae07c7c..e23ea2e 100644 --- a/stm32h7/spi/spiDefinitions.h +++ b/stm32h7/spi/spiDefinitions.h @@ -8,6 +8,12 @@ namespace spi { +enum TransferModes { + POLLING, + INTERRUPT, + DMA +}; + void assignSpiMode(SpiModes spiMode, SPI_HandleTypeDef* spiHandle); /** From 20815c1d6b6e5f0ce90ff5c1fcd84502fdff9f1c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 3 Jun 2021 22:07:59 +0200 Subject: [PATCH 11/35] polling transfer worked --- stm32h7/devicetest/GyroL3GD20H.cpp | 62 +++++++++++++++++++++++++----- stm32h7/devicetest/GyroL3GD20H.h | 7 ++++ 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index 30bd381..7c02e22 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -17,9 +17,15 @@ DMA_HandleTypeDef txDmaHandle; DMA_HandleTypeDef rxDmaHandle; GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transferMode): - spiHandle(spiHandle), transferMode(transferMode) { - set_dma_handles(&txDmaHandle, &rxDmaHandle); - set_spi_msp_functions(&hal_spi_msp_init_dma, spiHandle, &hal_spi_msp_deinit_dma, spiHandle); + spiHandle(spiHandle), transferMode(transferMode) { + if(transferMode == spi::TransferModes::DMA) { + set_dma_handles(&txDmaHandle, &rxDmaHandle); + set_spi_msp_functions(&hal_spi_msp_init_dma, spiHandle, &hal_spi_msp_deinit_dma, spiHandle); + } + else if(transferMode == spi::TransferModes::POLLING) { + set_spi_msp_functions(&hal_spi_msp_init_polling, spiHandle, + &hal_spi_msp_deinit_polling, spiHandle); + } GPIO_InitTypeDef chipSelect = {}; __HAL_RCC_GPIOD_CLK_ENABLE(); chipSelect.Pin = GPIO_PIN_14; @@ -53,13 +59,8 @@ ReturnValue_t GyroL3GD20H::initialize() { } ReturnValue_t GyroL3GD20H::performOperation() { - transferState = TransferStates::WAIT; - const uint8_t WHO_AM_I_REG = 0b00001111; - const uint8_t STM_READ_MASK = 0b10000000; - const uint8_t EXPECTED_WHO_AM_I_VAL = 0b11010111; - sif::printInfo("GyroL3GD20H::performOperation: Reading WHO AM I register\n"); txBuffer[0] = WHO_AM_I_REG | STM_READ_MASK; @@ -67,6 +68,21 @@ ReturnValue_t GyroL3GD20H::performOperation() { // Start SPI transfer via DMA HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); + switch(transferMode) { + case(spi::TransferModes::DMA): { + return handleDmaTransfer(); + } + case(spi::TransferModes::POLLING): { + return handlePollingTransfer(); + } + default: { + + } + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t GyroL3GD20H::handleDmaTransfer() { if(HAL_SPI_TransmitReceive_DMA(spiHandle, txBuffer.data(), rxBuffer.data(), 2) != HAL_OK) { // Transfer error in transmission process sif::printWarning("Error transmitting SPI with DMA\n"); @@ -82,7 +98,7 @@ ReturnValue_t GyroL3GD20H::performOperation() { switch(transferState) { case(TransferStates::SUCCESS): { - sif::printInfo("Transfer success\n"); + sif::printInfo("DMA transfer success\n"); uint8_t whoAmIVal = rxBuffer[1]; if(whoAmIVal != EXPECTED_WHO_AM_I_VAL) { sif::printDebug("GyroL3GD20H::performOperation: " @@ -97,7 +113,7 @@ ReturnValue_t GyroL3GD20H::performOperation() { break; } default: { - break; + return HasReturnvaluesIF::RETURN_FAILED; } } return HasReturnvaluesIF::RETURN_OK; @@ -125,3 +141,29 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { transferState = TransferStates::FAILURE; } + +ReturnValue_t GyroL3GD20H::handlePollingTransfer() { + switch(HAL_SPI_TransmitReceive(spiHandle, txBuffer.data(), rxBuffer.data(), 2, 1000)) { + case(HAL_OK): { + sif::printInfo("Polling transfer success\n"); + uint8_t whoAmIVal = rxBuffer[1]; + if(whoAmIVal != EXPECTED_WHO_AM_I_VAL) { + sif::printDebug("GyroL3GD20H::performOperation: " + "Read WHO AM I value %d not equal to expected value!\n", whoAmIVal); + } + break; + } + case(HAL_TIMEOUT): { + sif::printDebug("Polling transfer timeout\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + case(HAL_ERROR): { + sif::printDebug("Polling transfer failure\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + default: { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/stm32h7/devicetest/GyroL3GD20H.h b/stm32h7/devicetest/GyroL3GD20H.h index e9dacb0..ed2d9a2 100644 --- a/stm32h7/devicetest/GyroL3GD20H.h +++ b/stm32h7/devicetest/GyroL3GD20H.h @@ -26,11 +26,18 @@ public: private: + const uint8_t WHO_AM_I_REG = 0b00001111; + const uint8_t STM_READ_MASK = 0b10000000; + const uint8_t EXPECTED_WHO_AM_I_VAL = 0b11010111; + SPI_HandleTypeDef* spiHandle; spi::TransferModes transferMode; static constexpr size_t recvBufferSize = 32 * 10; static std::array rxBuffer; std::array txBuffer; + + ReturnValue_t handleDmaTransfer(); + ReturnValue_t handlePollingTransfer(); }; #endif /* FSFW_HAL_STM32H7_DEVICETEST_GYRO_L3GD20H_H_ */ From cf8235cedeb1fa82e594daa67211d55a51c67b11 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Jun 2021 12:58:30 +0200 Subject: [PATCH 12/35] solves issue with DMA --- stm32h7/devicetest/GyroL3GD20H.cpp | 16 ++++++++++++++-- stm32h7/devicetest/GyroL3GD20H.h | 4 +++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index 7c02e22..bf11081 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -11,7 +11,10 @@ #include "stm32h7xx_hal_spi.h" #include "stm32h7xx_hal_rcc.h" -std::array GyroL3GD20H::rxBuffer; +alignas(32) std::array GyroL3GD20H::rxBuffer; +alignas(32) std::array + GyroL3GD20H::txBuffer __attribute__((section(".dma_buffer"))); + TransferStates transferState = TransferStates::IDLE; DMA_HandleTypeDef txDmaHandle; DMA_HandleTypeDef rxDmaHandle; @@ -83,6 +86,15 @@ ReturnValue_t GyroL3GD20H::performOperation() { } ReturnValue_t GyroL3GD20H::handleDmaTransfer() { + /* Clean D-cache */ + /* Make sure the address is 32-byte aligned and add 32-bytes to length, + in case it overlaps cacheline */ + // See https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices +#if STM_USE_PERIPHERAL_TX_BUFFER_MPU_PROTECTION == 0 + SCB_CleanDCache_by_Addr((uint32_t*)(((uint32_t)txBuffer.data()) & ~(uint32_t)0x1F), + txBuffer.size()+32); +#endif + if(HAL_SPI_TransmitReceive_DMA(spiHandle, txBuffer.data(), rxBuffer.data(), 2) != HAL_OK) { // Transfer error in transmission process sif::printWarning("Error transmitting SPI with DMA\n"); @@ -90,7 +102,7 @@ ReturnValue_t GyroL3GD20H::handleDmaTransfer() { // Wait for the transfer to complete while (transferState == TransferStates::WAIT) { - //TaskFactory::delayTask(1); + TaskFactory::delayTask(1); } // Invalidate cache prior to access by CPU diff --git a/stm32h7/devicetest/GyroL3GD20H.h b/stm32h7/devicetest/GyroL3GD20H.h index ed2d9a2..59c39b9 100644 --- a/stm32h7/devicetest/GyroL3GD20H.h +++ b/stm32h7/devicetest/GyroL3GD20H.h @@ -33,8 +33,10 @@ private: SPI_HandleTypeDef* spiHandle; spi::TransferModes transferMode; static constexpr size_t recvBufferSize = 32 * 10; + static std::array rxBuffer; - std::array txBuffer; + static constexpr size_t txBufferSize = 32; + static std::array txBuffer; ReturnValue_t handleDmaTransfer(); ReturnValue_t handlePollingTransfer(); From cf1d6bad195cf3df079c3d674f1f13dd48f82e13 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Jun 2021 14:41:02 +0200 Subject: [PATCH 13/35] performed sensor readout --- stm32h7/devicetest/GyroL3GD20H.cpp | 177 +++++++++++++++++++++++++---- stm32h7/devicetest/GyroL3GD20H.h | 11 +- 2 files changed, 165 insertions(+), 23 deletions(-) diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index bf11081..6b8fcc4 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -11,6 +11,8 @@ #include "stm32h7xx_hal_spi.h" #include "stm32h7xx_hal_rcc.h" +#include + alignas(32) std::array GyroL3GD20H::rxBuffer; alignas(32) std::array GyroL3GD20H::txBuffer __attribute__((section(".dma_buffer"))); @@ -58,10 +60,7 @@ ReturnValue_t GyroL3GD20H::initialize() { sif::printWarning("Error initializing SPI\n"); return HasReturnvaluesIF::RETURN_FAILED; } - return HasReturnvaluesIF::RETURN_OK; -} -ReturnValue_t GyroL3GD20H::performOperation() { transferState = TransferStates::WAIT; sif::printInfo("GyroL3GD20H::performOperation: Reading WHO AM I register\n"); @@ -69,33 +68,85 @@ ReturnValue_t GyroL3GD20H::performOperation() { txBuffer[0] = WHO_AM_I_REG | STM_READ_MASK; txBuffer[1] = 0; - // Start SPI transfer via DMA - HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); switch(transferMode) { case(spi::TransferModes::DMA): { - return handleDmaTransfer(); + return handleDmaTransferInit(); } case(spi::TransferModes::POLLING): { return handlePollingTransfer(); } default: { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t GyroL3GD20H::performOperation() { + switch(transferMode) { + case(spi::TransferModes::DMA): { + return handleDmaSensorRead(); + } + default: { + return HasReturnvaluesIF::RETURN_FAILED; } } return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t GyroL3GD20H::handleDmaTransfer() { +ReturnValue_t GyroL3GD20H::handleDmaTransferInit() { /* Clean D-cache */ /* Make sure the address is 32-byte aligned and add 32-bytes to length, in case it overlaps cacheline */ // See https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices -#if STM_USE_PERIPHERAL_TX_BUFFER_MPU_PROTECTION == 0 - SCB_CleanDCache_by_Addr((uint32_t*)(((uint32_t)txBuffer.data()) & ~(uint32_t)0x1F), - txBuffer.size()+32); -#endif + HAL_StatusTypeDef result = performDmaTransfer(2); + if(result != HAL_OK) { + // Transfer error in transmission process + sif::printWarning("GyroL3GD20H::initialize: Error transmitting SPI with DMA\n"); + } - if(HAL_SPI_TransmitReceive_DMA(spiHandle, txBuffer.data(), rxBuffer.data(), 2) != HAL_OK) { + // Wait for the transfer to complete + while (transferState == TransferStates::WAIT) { + TaskFactory::delayTask(1); + } + + switch(transferState) { + case(TransferStates::SUCCESS): { + uint8_t whoAmIVal = rxBuffer[1]; + if(whoAmIVal != EXPECTED_WHO_AM_I_VAL) { + sif::printDebug("GyroL3GD20H::initialize: " + "Read WHO AM I value %d not equal to expected value!\n", whoAmIVal); + } + transferState = TransferStates::IDLE; + break; + } + case(TransferStates::FAILURE): { + sif::printWarning("Transfer failure\n"); + transferState = TransferStates::FAILURE; + return HasReturnvaluesIF::RETURN_FAILED; + } + default: { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + + sif::printInfo("GyroL3GD20H::initialize: Configuring device\n"); + + // Configure the 5 configuration registers + uint8_t configRegs[5]; + // Enable sensor + configRegs[0] = 0b00001111; + configRegs[1] = 0b00000000; + configRegs[2] = 0b00000000; + configRegs[3] = 0b01000000; + // Big endian select + configRegs[4] = 0b00000000; + + txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK; + std::memcpy(txBuffer.data() + 1, configRegs, 5); + result = performDmaTransfer(6); + if(result != HAL_OK) { // Transfer error in transmission process sif::printWarning("Error transmitting SPI with DMA\n"); } @@ -105,24 +156,52 @@ ReturnValue_t GyroL3GD20H::handleDmaTransfer() { TaskFactory::delayTask(1); } - // Invalidate cache prior to access by CPU - SCB_InvalidateDCache_by_Addr ((uint32_t *)rxBuffer.data(), recvBufferSize); + switch(transferState) { + case(TransferStates::SUCCESS): { + sif::printInfo("GyroL3GD20H::initialize: Configuration transfer success\n"); + transferState = TransferStates::IDLE; + break; + } + case(TransferStates::FAILURE): { + sif::printWarning("GyroL3GD20H::initialize: Configuration transfer failure\n"); + transferState = TransferStates::FAILURE; + return HasReturnvaluesIF::RETURN_FAILED; + } + default: { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + + + txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK | STM_READ_MASK; + std::memset(txBuffer.data() + 1, 0 , 5); + result = performDmaTransfer(6); + if(result != HAL_OK) { + // Transfer error in transmission process + sif::printWarning("Error transmitting SPI with DMA\n"); + } + // Wait for the transfer to complete + while (transferState == TransferStates::WAIT) { + TaskFactory::delayTask(1); + } switch(transferState) { case(TransferStates::SUCCESS): { - sif::printInfo("DMA transfer success\n"); - uint8_t whoAmIVal = rxBuffer[1]; - if(whoAmIVal != EXPECTED_WHO_AM_I_VAL) { - sif::printDebug("GyroL3GD20H::performOperation: " - "Read WHO AM I value %d not equal to expected value!\n", whoAmIVal); + if(rxBuffer[1] != configRegs[0] or rxBuffer[2] != configRegs[1] or + rxBuffer[3] != configRegs[2] or rxBuffer[4] != configRegs[3] or + rxBuffer[5] != configRegs[4]) { + sif::printWarning("GyroL3GD20H::initialize: Configuration failure\n"); + } + else { + sif::printInfo("GyroL3GD20H::initialize: Configuration success\n"); } transferState = TransferStates::IDLE; break; } case(TransferStates::FAILURE): { - sif::printWarning("Transfer failure\n"); + sif::printWarning("GyroL3GD20H::initialize: Configuration transfer failure\n"); transferState = TransferStates::FAILURE; - break; + return HasReturnvaluesIF::RETURN_FAILED; } default: { return HasReturnvaluesIF::RETURN_FAILED; @@ -131,6 +210,59 @@ ReturnValue_t GyroL3GD20H::handleDmaTransfer() { return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t GyroL3GD20H::handleDmaSensorRead() { + txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK | STM_READ_MASK; + std::memset(txBuffer.data() + 1, 0 , 14); + + HAL_StatusTypeDef result = performDmaTransfer(15); + if(result != HAL_OK) { + // Transfer error in transmission process + sif::printWarning("Error transmitting SPI with DMA\n"); + } + // Wait for the transfer to complete + while (transferState == TransferStates::WAIT) { + TaskFactory::delayTask(1); + } + + switch(transferState) { + case(TransferStates::SUCCESS): { + uint8_t statusReg = rxBuffer[8]; + int16_t gyroXRaw = rxBuffer[9] << 8 | rxBuffer[10]; + float gyroX = static_cast(gyroXRaw) / INT16_MAX * L3G_RANGE; + int16_t gyroYRaw = rxBuffer[11] << 8 | rxBuffer[12]; + float gyroY = static_cast(gyroYRaw) / INT16_MAX * L3G_RANGE; + int16_t gyroZRaw = rxBuffer[13] << 8 | rxBuffer[14]; + float gyroZ = static_cast(gyroZRaw) / INT16_MAX * L3G_RANGE; + sif::printInfo("Status register: 0b" BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(statusReg)); + sif::printInfo("Gyro X: %f\n", gyroX); + sif::printInfo("Gyro Y: %f\n", gyroY); + sif::printInfo("Gyro Z: %f\n", gyroZ); + break; + } + case(TransferStates::FAILURE): { + sif::printWarning("GyroL3GD20H::handleDmaSensorRead: Sensor read failure\n"); + transferState = TransferStates::FAILURE; + return HasReturnvaluesIF::RETURN_FAILED; + } + default: { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; +} + +HAL_StatusTypeDef GyroL3GD20H::performDmaTransfer(size_t sendSize) { + transferState = TransferStates::WAIT; +#if STM_USE_PERIPHERAL_TX_BUFFER_MPU_PROTECTION == 0 + SCB_CleanDCache_by_Addr((uint32_t*)(((uint32_t)txBuffer.data()) & ~(uint32_t)0x1F), + txBuffer.size()+32); +#endif + + // Start SPI transfer via DMA + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); + return HAL_SPI_TransmitReceive_DMA(spiHandle, txBuffer.data(), rxBuffer.data(), sendSize); +} + /** * @brief TxRx Transfer completed callback. * @param hspi: SPI handle @@ -141,6 +273,9 @@ ReturnValue_t GyroL3GD20H::handleDmaTransfer() { void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { transferState = TransferStates::SUCCESS; HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); + // Invalidate cache prior to access by CPU + SCB_InvalidateDCache_by_Addr ((uint32_t *)GyroL3GD20H::rxBuffer.data(), + GyroL3GD20H::recvBufferSize); } /** diff --git a/stm32h7/devicetest/GyroL3GD20H.h b/stm32h7/devicetest/GyroL3GD20H.h index 59c39b9..917d3ea 100644 --- a/stm32h7/devicetest/GyroL3GD20H.h +++ b/stm32h7/devicetest/GyroL3GD20H.h @@ -18,6 +18,7 @@ enum class TransferStates { }; class GyroL3GD20H { + friend void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi); public: GyroL3GD20H(SPI_HandleTypeDef* spiHandle, spi::TransferModes transferMode); @@ -28,17 +29,23 @@ private: const uint8_t WHO_AM_I_REG = 0b00001111; const uint8_t STM_READ_MASK = 0b10000000; + const uint8_t STM_AUTO_INCREMENT_MASK = 0b01000000; const uint8_t EXPECTED_WHO_AM_I_VAL = 0b11010111; + const uint8_t CTRL_REG_1 = 0b00100000; + const uint32_t L3G_RANGE = 245; SPI_HandleTypeDef* spiHandle; spi::TransferModes transferMode; - static constexpr size_t recvBufferSize = 32 * 10; + static constexpr size_t recvBufferSize = 32 * 10; static std::array rxBuffer; static constexpr size_t txBufferSize = 32; static std::array txBuffer; - ReturnValue_t handleDmaTransfer(); + ReturnValue_t handleDmaTransferInit(); + ReturnValue_t handleDmaSensorRead(); + HAL_StatusTypeDef performDmaTransfer(size_t sendSize); + ReturnValue_t handlePollingTransfer(); }; From 895ba1b455fc9e5c93f3ad6424174773584b5130 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Jun 2021 15:50:02 +0200 Subject: [PATCH 14/35] IRQ and POlling now working as well --- stm32h7/devicetest/GyroL3GD20H.cpp | 323 ++++++++++++++++++++++++----- stm32h7/devicetest/GyroL3GD20H.h | 10 +- stm32h7/spi/interrupts.c | 34 +++ stm32h7/spi/interrupts.h | 9 + stm32h7/spi/mspInit.c | 18 +- stm32h7/spi/mspInit.h | 3 + stm32h7/spi/spiCore.c | 28 --- 7 files changed, 337 insertions(+), 88 deletions(-) diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index 6b8fcc4..b0a16c1 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -18,19 +18,27 @@ alignas(32) std::array GyroL3GD20H::txBuffer __attribute__((section(".dma_buffer"))); TransferStates transferState = TransferStates::IDLE; +spi::TransferModes GyroL3GD20H::transferMode = spi::TransferModes::POLLING; + DMA_HandleTypeDef txDmaHandle; DMA_HandleTypeDef rxDmaHandle; -GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transferMode): - spiHandle(spiHandle), transferMode(transferMode) { +GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transferMode_): + spiHandle(spiHandle) { + transferMode = transferMode_; if(transferMode == spi::TransferModes::DMA) { set_dma_handles(&txDmaHandle, &rxDmaHandle); set_spi_msp_functions(&hal_spi_msp_init_dma, spiHandle, &hal_spi_msp_deinit_dma, spiHandle); } + else if(transferMode == spi::TransferModes::INTERRUPT) { + set_spi_msp_functions(&hal_spi_msp_init_interrupt, spiHandle, + &hal_spi_msp_deinit_interrupt, spiHandle); + } else if(transferMode == spi::TransferModes::POLLING) { set_spi_msp_functions(&hal_spi_msp_init_polling, spiHandle, &hal_spi_msp_deinit_polling, spiHandle); } + GPIO_InitTypeDef chipSelect = {}; __HAL_RCC_GPIOD_CLK_ENABLE(); chipSelect.Pin = GPIO_PIN_14; @@ -72,8 +80,11 @@ ReturnValue_t GyroL3GD20H::initialize() { case(spi::TransferModes::DMA): { return handleDmaTransferInit(); } + case(spi::TransferModes::INTERRUPT): { + return handleInterruptTransferInit(); + } case(spi::TransferModes::POLLING): { - return handlePollingTransfer(); + return handlePollingTransferInit(); } default: { return HasReturnvaluesIF::RETURN_FAILED; @@ -88,6 +99,12 @@ ReturnValue_t GyroL3GD20H::performOperation() { case(spi::TransferModes::DMA): { return handleDmaSensorRead(); } + case(spi::TransferModes::POLLING): { + return handlePollingSensorRead(); + } + case(spi::TransferModes::INTERRUPT): { + return handleInterruptSensorRead(); + } default: { return HasReturnvaluesIF::RETURN_FAILED; } @@ -132,19 +149,10 @@ ReturnValue_t GyroL3GD20H::handleDmaTransferInit() { } sif::printInfo("GyroL3GD20H::initialize: Configuring device\n"); - // Configure the 5 configuration registers uint8_t configRegs[5]; - // Enable sensor - configRegs[0] = 0b00001111; - configRegs[1] = 0b00000000; - configRegs[2] = 0b00000000; - configRegs[3] = 0b01000000; - // Big endian select - configRegs[4] = 0b00000000; + prepareConfigRegs(configRegs); - txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK; - std::memcpy(txBuffer.data() + 1, configRegs, 5); result = performDmaTransfer(6); if(result != HAL_OK) { // Transfer error in transmission process @@ -217,7 +225,7 @@ ReturnValue_t GyroL3GD20H::handleDmaSensorRead() { HAL_StatusTypeDef result = performDmaTransfer(15); if(result != HAL_OK) { // Transfer error in transmission process - sif::printWarning("Error transmitting SPI with DMA\n"); + sif::printDebug("GyroL3GD20H::handleDmaSensorRead: Error transmitting SPI with DMA\n"); } // Wait for the transfer to complete while (transferState == TransferStates::WAIT) { @@ -226,17 +234,7 @@ ReturnValue_t GyroL3GD20H::handleDmaSensorRead() { switch(transferState) { case(TransferStates::SUCCESS): { - uint8_t statusReg = rxBuffer[8]; - int16_t gyroXRaw = rxBuffer[9] << 8 | rxBuffer[10]; - float gyroX = static_cast(gyroXRaw) / INT16_MAX * L3G_RANGE; - int16_t gyroYRaw = rxBuffer[11] << 8 | rxBuffer[12]; - float gyroY = static_cast(gyroYRaw) / INT16_MAX * L3G_RANGE; - int16_t gyroZRaw = rxBuffer[13] << 8 | rxBuffer[14]; - float gyroZ = static_cast(gyroZRaw) / INT16_MAX * L3G_RANGE; - sif::printInfo("Status register: 0b" BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(statusReg)); - sif::printInfo("Gyro X: %f\n", gyroX); - sif::printInfo("Gyro Y: %f\n", gyroY); - sif::printInfo("Gyro Z: %f\n", gyroZ); + handleSensorReadout(); break; } case(TransferStates::FAILURE): { @@ -263,6 +261,247 @@ HAL_StatusTypeDef GyroL3GD20H::performDmaTransfer(size_t sendSize) { return HAL_SPI_TransmitReceive_DMA(spiHandle, txBuffer.data(), rxBuffer.data(), sendSize); } +ReturnValue_t GyroL3GD20H::handlePollingTransferInit() { + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); + auto result = HAL_SPI_TransmitReceive(spiHandle, txBuffer.data(), rxBuffer.data(), 2, 1000); + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); + switch(result) { + case(HAL_OK): { + sif::printInfo("GyroL3GD20H::initialize: Polling transfer success\n"); + uint8_t whoAmIVal = rxBuffer[1]; + if(whoAmIVal != EXPECTED_WHO_AM_I_VAL) { + sif::printDebug("GyroL3GD20H::performOperation: " + "Read WHO AM I value %d not equal to expected value!\n", whoAmIVal); + } + break; + } + case(HAL_TIMEOUT): { + sif::printDebug("GyroL3GD20H::initialize: Polling transfer timeout\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + case(HAL_ERROR): { + sif::printDebug("GyroL3GD20H::initialize: Polling transfer failure\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + default: { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; + + sif::printInfo("GyroL3GD20H::initialize: Configuring device\n"); + // Configure the 5 configuration registers + uint8_t configRegs[5]; + prepareConfigRegs(configRegs); + + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); + result = HAL_SPI_TransmitReceive(spiHandle, txBuffer.data(), rxBuffer.data(), 6, 1000); + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); + switch(result) { + case(HAL_OK): { + break; + } + case(HAL_TIMEOUT): { + sif::printDebug("GyroL3GD20H::initialize: Polling transfer timeout\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + case(HAL_ERROR): { + sif::printDebug("GyroL3GD20H::initialize: Polling transfer failure\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + default: { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; + + txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK | STM_READ_MASK; + std::memset(txBuffer.data() + 1, 0 , 5); + + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); + result = HAL_SPI_TransmitReceive(spiHandle, txBuffer.data(), rxBuffer.data(), 6, 1000); + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); + switch(result) { + case(HAL_OK): { + if(rxBuffer[1] != configRegs[0] or rxBuffer[2] != configRegs[1] or + rxBuffer[3] != configRegs[2] or rxBuffer[4] != configRegs[3] or + rxBuffer[5] != configRegs[4]) { + sif::printWarning("GyroL3GD20H::initialize: Configuration failure\n"); + } + else { + sif::printInfo("GyroL3GD20H::initialize: Configuration success\n"); + } + break; + } + case(HAL_TIMEOUT): { + sif::printDebug("GyroL3GD20H::initialize: Polling transfer timeout\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + case(HAL_ERROR): { + sif::printDebug("GyroL3GD20H::initialize: Polling transfer failure\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + default: { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t GyroL3GD20H::handlePollingSensorRead() { + txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK | STM_READ_MASK; + std::memset(txBuffer.data() + 1, 0 , 14); + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); + auto result = HAL_SPI_TransmitReceive(spiHandle, txBuffer.data(), rxBuffer.data(), 15, 1000); + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); + switch(result) { + case(HAL_OK): { + handleSensorReadout(); + break; + } + case(HAL_TIMEOUT): { + sif::printDebug("GyroL3GD20H::initialize: Polling transfer timeout\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + case(HAL_ERROR): { + sif::printDebug("GyroL3GD20H::initialize: Polling transfer failure\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + default: { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t GyroL3GD20H::handleInterruptTransferInit() { + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); + switch(HAL_SPI_TransmitReceive_IT(spiHandle, txBuffer.data(), rxBuffer.data(), 2)) { + case(HAL_OK): { + sif::printInfo("GyroL3GD20H::initialize: Interrupt transfer success\n"); + // Wait for the transfer to complete + while (transferState == TransferStates::WAIT) { + TaskFactory::delayTask(1); + } + + uint8_t whoAmIVal = rxBuffer[1]; + if(whoAmIVal != EXPECTED_WHO_AM_I_VAL) { + sif::printDebug("GyroL3GD20H::initialize: " + "Read WHO AM I value %d not equal to expected value!\n", whoAmIVal); + } + break; + } + case(HAL_BUSY): + case(HAL_ERROR): + case(HAL_TIMEOUT): { + sif::printDebug("GyroL3GD20H::initialize: Initialization failure using interrupts\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + } + + sif::printInfo("GyroL3GD20H::initialize: Configuring device\n"); + transferState = TransferStates::WAIT; + // Configure the 5 configuration registers + uint8_t configRegs[5]; + prepareConfigRegs(configRegs); + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); + switch(HAL_SPI_TransmitReceive_IT(spiHandle, txBuffer.data(), rxBuffer.data(), 6)) { + case(HAL_OK): { + // Wait for the transfer to complete + while (transferState == TransferStates::WAIT) { + TaskFactory::delayTask(1); + } + break; + } + case(HAL_BUSY): + case(HAL_ERROR): + case(HAL_TIMEOUT): { + sif::printDebug("GyroL3GD20H::initialize: Initialization failure using interrupts\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + } + + txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK | STM_READ_MASK; + std::memset(txBuffer.data() + 1, 0 , 5); + transferState = TransferStates::WAIT; + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); + switch(HAL_SPI_TransmitReceive_IT(spiHandle, txBuffer.data(), rxBuffer.data(), 6)) { + case(HAL_OK): { + // Wait for the transfer to complete + while (transferState == TransferStates::WAIT) { + TaskFactory::delayTask(1); + } + if(rxBuffer[1] != configRegs[0] or rxBuffer[2] != configRegs[1] or + rxBuffer[3] != configRegs[2] or rxBuffer[4] != configRegs[3] or + rxBuffer[5] != configRegs[4]) { + sif::printWarning("GyroL3GD20H::initialize: Configuration failure\n"); + } + else { + sif::printInfo("GyroL3GD20H::initialize: Configuration success\n"); + } + break; + } + case(HAL_BUSY): + case(HAL_ERROR): + case(HAL_TIMEOUT): { + sif::printDebug("GyroL3GD20H::initialize: Initialization failure using interrupts\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t GyroL3GD20H::handleInterruptSensorRead() { + transferState = TransferStates::WAIT; + txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK | STM_READ_MASK; + std::memset(txBuffer.data() + 1, 0 , 14); + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); + switch(HAL_SPI_TransmitReceive_IT(spiHandle, txBuffer.data(), rxBuffer.data(), 15)) { + case(HAL_OK): { + // Wait for the transfer to complete + while (transferState == TransferStates::WAIT) { + TaskFactory::delayTask(1); + } + handleSensorReadout(); + break; + } + case(HAL_BUSY): + case(HAL_ERROR): + case(HAL_TIMEOUT): { + sif::printDebug("GyroL3GD20H::initialize: Sensor read failure using interrupts\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; +} + +void GyroL3GD20H::prepareConfigRegs(uint8_t* configRegs) { + // Enable sensor + configRegs[0] = 0b00001111; + configRegs[1] = 0b00000000; + configRegs[2] = 0b00000000; + configRegs[3] = 0b01000000; + // Big endian select + configRegs[4] = 0b00000000; + + txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK; + std::memcpy(txBuffer.data() + 1, configRegs, 5); +} + +void GyroL3GD20H::handleSensorReadout() { + uint8_t statusReg = rxBuffer[8]; + int16_t gyroXRaw = rxBuffer[9] << 8 | rxBuffer[10]; + float gyroX = static_cast(gyroXRaw) / INT16_MAX * L3G_RANGE; + int16_t gyroYRaw = rxBuffer[11] << 8 | rxBuffer[12]; + float gyroY = static_cast(gyroYRaw) / INT16_MAX * L3G_RANGE; + int16_t gyroZRaw = rxBuffer[13] << 8 | rxBuffer[14]; + float gyroZ = static_cast(gyroZRaw) / INT16_MAX * L3G_RANGE; + sif::printInfo("Status register: 0b" BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(statusReg)); + sif::printInfo("Gyro X: %f\n", gyroX); + sif::printInfo("Gyro Y: %f\n", gyroY); + sif::printInfo("Gyro Z: %f\n", gyroZ); +} + /** * @brief TxRx Transfer completed callback. * @param hspi: SPI handle @@ -273,9 +512,11 @@ HAL_StatusTypeDef GyroL3GD20H::performDmaTransfer(size_t sendSize) { void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { transferState = TransferStates::SUCCESS; HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); - // Invalidate cache prior to access by CPU - SCB_InvalidateDCache_by_Addr ((uint32_t *)GyroL3GD20H::rxBuffer.data(), - GyroL3GD20H::recvBufferSize); + if(GyroL3GD20H::transferMode == spi::TransferModes::DMA) { + // Invalidate cache prior to access by CPU + SCB_InvalidateDCache_by_Addr ((uint32_t *)GyroL3GD20H::rxBuffer.data(), + GyroL3GD20H::recvBufferSize); + } } /** @@ -288,29 +529,3 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { transferState = TransferStates::FAILURE; } - -ReturnValue_t GyroL3GD20H::handlePollingTransfer() { - switch(HAL_SPI_TransmitReceive(spiHandle, txBuffer.data(), rxBuffer.data(), 2, 1000)) { - case(HAL_OK): { - sif::printInfo("Polling transfer success\n"); - uint8_t whoAmIVal = rxBuffer[1]; - if(whoAmIVal != EXPECTED_WHO_AM_I_VAL) { - sif::printDebug("GyroL3GD20H::performOperation: " - "Read WHO AM I value %d not equal to expected value!\n", whoAmIVal); - } - break; - } - case(HAL_TIMEOUT): { - sif::printDebug("Polling transfer timeout\n"); - return HasReturnvaluesIF::RETURN_FAILED; - } - case(HAL_ERROR): { - sif::printDebug("Polling transfer failure\n"); - return HasReturnvaluesIF::RETURN_FAILED; - } - default: { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - return HasReturnvaluesIF::RETURN_OK; -} diff --git a/stm32h7/devicetest/GyroL3GD20H.h b/stm32h7/devicetest/GyroL3GD20H.h index 917d3ea..72e9ccc 100644 --- a/stm32h7/devicetest/GyroL3GD20H.h +++ b/stm32h7/devicetest/GyroL3GD20H.h @@ -35,18 +35,24 @@ private: const uint32_t L3G_RANGE = 245; SPI_HandleTypeDef* spiHandle; - spi::TransferModes transferMode; + static spi::TransferModes transferMode; static constexpr size_t recvBufferSize = 32 * 10; static std::array rxBuffer; static constexpr size_t txBufferSize = 32; static std::array txBuffer; ReturnValue_t handleDmaTransferInit(); + ReturnValue_t handlePollingTransferInit(); + ReturnValue_t handleInterruptTransferInit(); + ReturnValue_t handleDmaSensorRead(); HAL_StatusTypeDef performDmaTransfer(size_t sendSize); + ReturnValue_t handlePollingSensorRead(); + ReturnValue_t handleInterruptSensorRead(); - ReturnValue_t handlePollingTransfer(); + void prepareConfigRegs(uint8_t* configRegs); + void handleSensorReadout(); }; #endif /* FSFW_HAL_STM32H7_DEVICETEST_GYRO_L3GD20H_H_ */ diff --git a/stm32h7/spi/interrupts.c b/stm32h7/spi/interrupts.c index 90e1047..5137f40 100644 --- a/stm32h7/spi/interrupts.c +++ b/stm32h7/spi/interrupts.c @@ -1,7 +1,12 @@ #include "interrupts.h" +#include "stm32h7xx_hal.h" +#include "stm32h7xx_hal_dma.h" +#include "stm32h7xx_hal_spi.h" + #include + void (*spi1_user_handler) (void* args) = NULL; void * spi1_user_args = NULL; @@ -37,3 +42,32 @@ void SPI2_IRQHandler() { } Default_Handler(); } + +/** + * @brief This function handles DMA Rx interrupt request. + * @param None + * @retval None + */ +void dma_rx_irq_handler(void* dma_handle) { + HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dma_handle); +} + +/** + * @brief This function handles DMA Rx interrupt request. + * @param None + * @retval None + */ +void dma_tx_irq_handler(void* dma_handle) { + HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dma_handle); +} + +/** + * @brief This function handles SPIx interrupt request. + * @param None + * @retval None + */ +void spi1_irq_handler(void* spi_handle) +{ + HAL_SPI_IRQHandler((SPI_HandleTypeDef *) spi_handle); +} + diff --git a/stm32h7/spi/interrupts.h b/stm32h7/spi/interrupts.h index 60d8fa0..060eaa1 100644 --- a/stm32h7/spi/interrupts.h +++ b/stm32h7/spi/interrupts.h @@ -20,6 +20,15 @@ typedef enum { */ void assign_spi_user_handler(SpiBus spiBus, user_handler_t user_handler, user_args_t user_args); +/** + * Generic interrupt handlers supplied for convenience. Do not call these directly! Set them + * instead with assign_dma_user_handler and assign_spi_user_handler functions. + * @param dma_handle + */ +void dma_rx_irq_handler(void* dma_handle); +void dma_tx_irq_handler(void* dma_handle); +void spi1_irq_handler(void* spi_handle); + #ifdef __cplusplus } #endif diff --git a/stm32h7/spi/mspInit.c b/stm32h7/spi/mspInit.c index 1964391..9025780 100644 --- a/stm32h7/spi/mspInit.c +++ b/stm32h7/spi/mspInit.c @@ -11,10 +11,6 @@ #include -void dma_rx_irq_handler(void* dma_handle); -void dma_tx_irq_handler(void* dma_handle); -void spi1_irq_handler(void* spi_handle); - /** * @brief SPI MSP Initialization * This function configures the hardware resources used in this example: @@ -195,3 +191,17 @@ void hal_spi_msp_deinit_polling(void *hspi) { /* Configure SPI MOSI as alternate function */ HAL_GPIO_DeInit(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_PIN); } + +void hal_spi_msp_init_interrupt(void *hspi) { + hal_spi_msp_init_polling(hspi); + // Configure the NVIC for SPI + assign_spi_user_handler(SPI_1, &spi1_irq_handler, hspi); + HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(SPIx_IRQn); +} + +void hal_spi_msp_deinit_interrupt(void *hspi) { + hal_spi_msp_deinit_polling(hspi); + // Disable the NVIC for SPI + HAL_NVIC_DisableIRQ(SPIx_IRQn); +} diff --git a/stm32h7/spi/mspInit.h b/stm32h7/spi/mspInit.h index 48ac7b1..da352f6 100644 --- a/stm32h7/spi/mspInit.h +++ b/stm32h7/spi/mspInit.h @@ -11,6 +11,9 @@ void hal_spi_msp_deinit_dma(void *hspi); void hal_spi_msp_init_polling(void *hspi); void hal_spi_msp_deinit_polling(void *hspi); +void hal_spi_msp_init_interrupt(void *hspi); +void hal_spi_msp_deinit_interrupt(void *hspi); + #ifdef __cplusplus } #endif diff --git a/stm32h7/spi/spiCore.c b/stm32h7/spi/spiCore.c index 2516dbf..f0152d2 100644 --- a/stm32h7/spi/spiCore.c +++ b/stm32h7/spi/spiCore.c @@ -32,34 +32,6 @@ SPI_HandleTypeDef* get_spi_handle() { return spiHandle; } -/** - * @brief This function handles DMA Rx interrupt request. - * @param None - * @retval None - */ -void dma_rx_irq_handler(void* dma_handle) { - HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dma_handle); -} - -/** - * @brief This function handles DMA Rx interrupt request. - * @param None - * @retval None - */ -void dma_tx_irq_handler(void* dma_handle) { - HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dma_handle); -} - -/** - * @brief This function handles SPIx interrupt request. - * @param None - * @retval None - */ -void spi1_irq_handler(void* spi_handle) -{ - HAL_SPI_IRQHandler((SPI_HandleTypeDef *) spi_handle); -} - void set_spi_msp_functions(msp_func_t init_func, void* init_args, msp_func_t deinit_func, void* deinit_args) { msp_init_func = init_func; From 39d2a49ca18718e73689f75236bfed71d83ca4db Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Jun 2021 16:01:38 +0200 Subject: [PATCH 15/35] added spi com if stubs for stm32 --- stm32h7/spi/CMakeLists.txt | 2 ++ stm32h7/spi/SpiComIF.cpp | 24 ++++++++++++++++++++++++ stm32h7/spi/SpiComIF.h | 29 +++++++++++++++++++++++++++++ stm32h7/spi/SpiCookie.cpp | 4 ++++ stm32h7/spi/SpiCookie.h | 15 +++++++++++++++ 5 files changed, 74 insertions(+) create mode 100644 stm32h7/spi/SpiComIF.cpp create mode 100644 stm32h7/spi/SpiComIF.h create mode 100644 stm32h7/spi/SpiCookie.cpp create mode 100644 stm32h7/spi/SpiCookie.h diff --git a/stm32h7/spi/CMakeLists.txt b/stm32h7/spi/CMakeLists.txt index ea980e0..1e8feb5 100644 --- a/stm32h7/spi/CMakeLists.txt +++ b/stm32h7/spi/CMakeLists.txt @@ -3,4 +3,6 @@ target_sources(${TARGET_NAME} PRIVATE spiDefinitions.cpp interrupts.c mspInit.c + SpiCookie.cpp + SpiComIF.cpp ) diff --git a/stm32h7/spi/SpiComIF.cpp b/stm32h7/spi/SpiComIF.cpp new file mode 100644 index 0000000..c3e6021 --- /dev/null +++ b/stm32h7/spi/SpiComIF.cpp @@ -0,0 +1,24 @@ +#include "SpiComIF.h" + +SpiComIF::SpiComIF(object_id_t objectId): SystemObject(objectId) { +} + +ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen) { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t SpiComIF::getSendSuccess(CookieIF *cookie) { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t SpiComIF::requestReceiveMessage(CookieIF *cookie, size_t requestLen) { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t SpiComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) { + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/stm32h7/spi/SpiComIF.h b/stm32h7/spi/SpiComIF.h new file mode 100644 index 0000000..9205b61 --- /dev/null +++ b/stm32h7/spi/SpiComIF.h @@ -0,0 +1,29 @@ +#ifndef FSFW_HAL_STM32H7_SPI_SPICOMIF_H_ +#define FSFW_HAL_STM32H7_SPI_SPICOMIF_H_ + +#include "fsfw/devicehandlers/DeviceCommunicationIF.h" +#include "fsfw/objectmanager/SystemObject.h" + +class SpiComIF: + public SystemObject, + public DeviceCommunicationIF { +public: + SpiComIF(object_id_t objectId); +protected: + + // DeviceCommunicationIF overrides + virtual ReturnValue_t initializeInterface(CookieIF * cookie) override; + virtual ReturnValue_t sendMessage(CookieIF *cookie, + const uint8_t * sendData, size_t sendLen) override; + virtual ReturnValue_t getSendSuccess(CookieIF *cookie) override; + virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie, + size_t requestLen) override; + virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, + uint8_t **buffer, size_t *size) override; +private: + +}; + + + +#endif /* FSFW_HAL_STM32H7_SPI_SPICOMIF_H_ */ diff --git a/stm32h7/spi/SpiCookie.cpp b/stm32h7/spi/SpiCookie.cpp new file mode 100644 index 0000000..d7824fd --- /dev/null +++ b/stm32h7/spi/SpiCookie.cpp @@ -0,0 +1,4 @@ +#include "SpiCookie.h" + +SpiCookie::SpiCookie() { +} diff --git a/stm32h7/spi/SpiCookie.h b/stm32h7/spi/SpiCookie.h new file mode 100644 index 0000000..7a12d91 --- /dev/null +++ b/stm32h7/spi/SpiCookie.h @@ -0,0 +1,15 @@ +#ifndef FSFW_HAL_STM32H7_SPI_SPICOOKIE_H_ +#define FSFW_HAL_STM32H7_SPI_SPICOOKIE_H_ + +#include "fsfw/devicehandlers/CookieIF.h" + +class SpiCookie: public CookieIF { +public: + SpiCookie(); +private: + +}; + + + +#endif /* FSFW_HAL_STM32H7_SPI_SPICOOKIE_H_ */ From cb121b9faf9f96818739e14bf79b48470c9f3290 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Jun 2021 16:34:38 +0200 Subject: [PATCH 16/35] converted files to cpp continued stubs --- stm32h7/CMakeLists.txt | 1 - stm32h7/dma_interrupts.h | 4 +- stm32h7/interrupts.c | 2 - stm32h7/spi/CMakeLists.txt | 6 +- stm32h7/spi/SpiComIF.cpp | 3 +- stm32h7/spi/SpiComIF.h | 9 ++- stm32h7/spi/SpiCookie.cpp | 7 +- stm32h7/spi/SpiCookie.h | 14 +++- stm32h7/spi/{mspInit.c => mspInit.cpp} | 10 +-- stm32h7/spi/{spiCore.c => spiCore.cpp} | 20 +++--- stm32h7/spi/spiCore.h | 2 +- stm32h7/spi/spiDefinitions.h | 5 ++ .../spi/{interrupts.c => spiInterrupts.cpp} | 71 ++++++++++--------- stm32h7/spi/{interrupts.h => spiInterrupts.h} | 9 +-- 14 files changed, 93 insertions(+), 70 deletions(-) delete mode 100644 stm32h7/interrupts.c rename stm32h7/spi/{mspInit.c => mspInit.cpp} (95%) rename stm32h7/spi/{spiCore.c => spiCore.cpp} (84%) rename stm32h7/spi/{interrupts.c => spiInterrupts.cpp} (75%) rename stm32h7/spi/{interrupts.h => spiInterrupts.h} (84%) diff --git a/stm32h7/CMakeLists.txt b/stm32h7/CMakeLists.txt index ed74b99..58b50fe 100644 --- a/stm32h7/CMakeLists.txt +++ b/stm32h7/CMakeLists.txt @@ -2,6 +2,5 @@ add_subdirectory(spi) add_subdirectory(devicetest) target_sources(${TARGET_NAME} PRIVATE - interrupts.c dma_interrupts.c ) diff --git a/stm32h7/dma_interrupts.h b/stm32h7/dma_interrupts.h index b28310f..b24c235 100644 --- a/stm32h7/dma_interrupts.h +++ b/stm32h7/dma_interrupts.h @@ -1,12 +1,12 @@ #ifndef FSFW_HAL_STM32H7_DMA_INTERRUPTS_H_ #define FSFW_HAL_STM32H7_DMA_INTERRUPTS_H_ -#include "interrupts.h" - #ifdef __cplusplus extern "C" { #endif +#include "interrupts.h" + typedef enum { DMA_1 = 0, DMA_2 = 1 diff --git a/stm32h7/interrupts.c b/stm32h7/interrupts.c deleted file mode 100644 index 4987edd..0000000 --- a/stm32h7/interrupts.c +++ /dev/null @@ -1,2 +0,0 @@ -#include "interrupts.h" -#include diff --git a/stm32h7/spi/CMakeLists.txt b/stm32h7/spi/CMakeLists.txt index 1e8feb5..c566f53 100644 --- a/stm32h7/spi/CMakeLists.txt +++ b/stm32h7/spi/CMakeLists.txt @@ -1,8 +1,8 @@ target_sources(${TARGET_NAME} PRIVATE - spiCore.c + spiCore.cpp spiDefinitions.cpp - interrupts.c - mspInit.c + spiInterrupts.cpp + mspInit.cpp SpiCookie.cpp SpiComIF.cpp ) diff --git a/stm32h7/spi/SpiComIF.cpp b/stm32h7/spi/SpiComIF.cpp index c3e6021..913c647 100644 --- a/stm32h7/spi/SpiComIF.cpp +++ b/stm32h7/spi/SpiComIF.cpp @@ -1,6 +1,7 @@ #include "SpiComIF.h" -SpiComIF::SpiComIF(object_id_t objectId): SystemObject(objectId) { +SpiComIF::SpiComIF(object_id_t objectId, SPI_TypeDef* spiInstance, + spi::TransferModes transferMode): SystemObject(objectId) { } ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { diff --git a/stm32h7/spi/SpiComIF.h b/stm32h7/spi/SpiComIF.h index 9205b61..bd79e0c 100644 --- a/stm32h7/spi/SpiComIF.h +++ b/stm32h7/spi/SpiComIF.h @@ -1,14 +1,19 @@ #ifndef FSFW_HAL_STM32H7_SPI_SPICOMIF_H_ #define FSFW_HAL_STM32H7_SPI_SPICOMIF_H_ + #include "fsfw/devicehandlers/DeviceCommunicationIF.h" #include "fsfw/objectmanager/SystemObject.h" +#include "fsfw_hal/stm32h7/spi/spiDefinitions.h" +#include "stm32h7xx_hal_spi.h" +#include "stm32h743xx.h" + class SpiComIF: public SystemObject, public DeviceCommunicationIF { public: - SpiComIF(object_id_t objectId); + SpiComIF(object_id_t objectId, SPI_TypeDef* spiInstance, spi::TransferModes transferMode); protected: // DeviceCommunicationIF overrides @@ -21,7 +26,7 @@ protected: virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) override; private: - + SPI_HandleTypeDef spiHandle; }; diff --git a/stm32h7/spi/SpiCookie.cpp b/stm32h7/spi/SpiCookie.cpp index d7824fd..97e5bee 100644 --- a/stm32h7/spi/SpiCookie.cpp +++ b/stm32h7/spi/SpiCookie.cpp @@ -1,4 +1,9 @@ #include "SpiCookie.h" -SpiCookie::SpiCookie() { + + +SpiCookie::SpiCookie(address_t deviceAddress, spi::SpiBus spiIdx, uint32_t spiSpeed, + spi::SpiModes spiMode, uint16_t chipSelectGpioPin, GPIO_TypeDef* chipSelectGpioPort): + deviceAddress(deviceAddress), spiIdx(spiIdx), spiSpeed(spiSpeed), spiMode(spiMode), + chipSelectGpioPin(chipSelectGpioPin), chipSelectGpioPort(chipSelectGpioPort) { } diff --git a/stm32h7/spi/SpiCookie.h b/stm32h7/spi/SpiCookie.h index 7a12d91..1bee9ba 100644 --- a/stm32h7/spi/SpiCookie.h +++ b/stm32h7/spi/SpiCookie.h @@ -1,13 +1,23 @@ #ifndef FSFW_HAL_STM32H7_SPI_SPICOOKIE_H_ #define FSFW_HAL_STM32H7_SPI_SPICOOKIE_H_ +#include "spiDefinitions.h" + #include "fsfw/devicehandlers/CookieIF.h" +#include "stm32h743xx.h" + class SpiCookie: public CookieIF { public: - SpiCookie(); + SpiCookie(address_t deviceAddress, spi::SpiBus spiIdx, uint32_t spiSpeed, spi::SpiModes spiMode, + uint16_t chipSelectGpioPin, GPIO_TypeDef* chipSelectGpioPort); private: - + address_t deviceAddress; + spi::SpiBus spiIdx; + uint32_t spiSpeed; + spi::SpiModes spiMode; + uint16_t chipSelectGpioPin; + GPIO_TypeDef* chipSelectGpioPort; }; diff --git a/stm32h7/spi/mspInit.c b/stm32h7/spi/mspInit.cpp similarity index 95% rename from stm32h7/spi/mspInit.c rename to stm32h7/spi/mspInit.cpp index 9025780..05f9522 100644 --- a/stm32h7/spi/mspInit.c +++ b/stm32h7/spi/mspInit.cpp @@ -1,8 +1,8 @@ #include "mspInit.h" #include "spiConf.h" #include "spiCore.h" +#include "spiInterrupts.h" #include "../dma_interrupts.h" -#include "interrupts.h" #include "stm32h743xx.h" #include "stm32h7xx_hal_spi.h" @@ -90,20 +90,20 @@ void hal_spi_msp_init_dma(void *spi_handle) { /*##-4- Configure the NVIC for DMA #########################################*/ /* NVIC configuration for DMA transfer complete interrupt (SPI1_RX) */ // Assign the interrupt handler - assign_dma_user_handler(DMA_2, 2, &dma_rx_irq_handler, hdma_rx); + assign_dma_user_handler(DMA_2, DMAStreams::STREAM_2, &dma_rx_irq_handler, hdma_rx); HAL_NVIC_SetPriority(SPIx_DMA_RX_IRQn, 1, 0); HAL_NVIC_EnableIRQ(SPIx_DMA_RX_IRQn); /* NVIC configuration for DMA transfer complete interrupt (SPI1_TX) */ // Assign the interrupt handler - assign_dma_user_handler(DMA_2, 3, &dma_tx_irq_handler, hdma_tx); + assign_dma_user_handler(DMA_2, DMAStreams::STREAM_3, &dma_tx_irq_handler, hdma_tx); HAL_NVIC_SetPriority(SPIx_DMA_TX_IRQn, 1, 1); HAL_NVIC_EnableIRQ(SPIx_DMA_TX_IRQn); /*##-5- Configure the NVIC for SPI #########################################*/ /* NVIC configuration for SPI transfer complete interrupt (SPI1) */ // Assign the interrupt handler - assign_spi_user_handler(SPI_1, &spi1_irq_handler, hspi); + assign_spi_user_handler(spi::SPI_1, &spi1_irq_handler, hspi); HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0); HAL_NVIC_EnableIRQ(SPIx_IRQn); } @@ -195,7 +195,7 @@ void hal_spi_msp_deinit_polling(void *hspi) { void hal_spi_msp_init_interrupt(void *hspi) { hal_spi_msp_init_polling(hspi); // Configure the NVIC for SPI - assign_spi_user_handler(SPI_1, &spi1_irq_handler, hspi); + assign_spi_user_handler(spi::SPI_1, &spi1_irq_handler, hspi); HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0); HAL_NVIC_EnableIRQ(SPIx_IRQn); } diff --git a/stm32h7/spi/spiCore.c b/stm32h7/spi/spiCore.cpp similarity index 84% rename from stm32h7/spi/spiCore.c rename to stm32h7/spi/spiCore.cpp index f0152d2..ad57f5d 100644 --- a/stm32h7/spi/spiCore.c +++ b/stm32h7/spi/spiCore.cpp @@ -1,15 +1,15 @@ #include "spiCore.h" -#include +#include -SPI_HandleTypeDef* spiHandle = NULL; -DMA_HandleTypeDef* hdma_tx = NULL; -DMA_HandleTypeDef* hdma_rx = NULL; +SPI_HandleTypeDef* spiHandle = nullptr; +DMA_HandleTypeDef* hdma_tx = nullptr; +DMA_HandleTypeDef* hdma_rx = nullptr; -msp_func_t msp_init_func = NULL; -void* msp_init_args = NULL; +msp_func_t msp_init_func = nullptr; +void* msp_init_args = nullptr; -msp_func_t msp_deinit_func = NULL; -void* msp_deinit_args = NULL; +msp_func_t msp_deinit_func = nullptr; +void* msp_deinit_args = nullptr; void set_dma_handles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle) { hdma_tx = txHandle; @@ -64,7 +64,7 @@ void get_msp_deinit_function(msp_func_t* deinit_func, void **args) { * @param hspi: SPI handle pointer * @retval None */ -void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) { +extern "C" void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) { if(msp_init_func != NULL) { msp_init_func(msp_init_args); } @@ -81,7 +81,7 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) { * @param hspi: SPI handle pointer * @retval None */ -void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) { +extern "C" void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) { if(msp_deinit_func != NULL) { msp_deinit_func(msp_deinit_args); } diff --git a/stm32h7/spi/spiCore.h b/stm32h7/spi/spiCore.h index 75d4eca..fb947be 100644 --- a/stm32h7/spi/spiCore.h +++ b/stm32h7/spi/spiCore.h @@ -8,7 +8,7 @@ extern "C" { #endif -typedef void (*msp_func_t) (void* args); +using msp_func_t = void (*) (void* args); /** * Assign MSP init functions. Important for SPI configuration diff --git a/stm32h7/spi/spiDefinitions.h b/stm32h7/spi/spiDefinitions.h index e23ea2e..b812c15 100644 --- a/stm32h7/spi/spiDefinitions.h +++ b/stm32h7/spi/spiDefinitions.h @@ -8,6 +8,11 @@ namespace spi { +enum SpiBus { + SPI_1, + SPI_2 +}; + enum TransferModes { POLLING, INTERRUPT, diff --git a/stm32h7/spi/interrupts.c b/stm32h7/spi/spiInterrupts.cpp similarity index 75% rename from stm32h7/spi/interrupts.c rename to stm32h7/spi/spiInterrupts.cpp index 5137f40..51a58eb 100644 --- a/stm32h7/spi/interrupts.c +++ b/stm32h7/spi/spiInterrupts.cpp @@ -1,4 +1,4 @@ -#include "interrupts.h" +#include "spiInterrupts.h" #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_dma.h" @@ -7,41 +7,12 @@ #include -void (*spi1_user_handler) (void* args) = NULL; -void * spi1_user_args = NULL; +void (*spi1_user_handler) (void* args) = nullptr; +void * spi1_user_args = nullptr; -void (*spi2_user_handler) (void* args) = NULL; -void * spi2_user_args = NULL; +void (*spi2_user_handler) (void* args) = nullptr; +void * spi2_user_args = nullptr; -void assign_spi_user_handler(SpiBus spi_idx, user_handler_t user_handler, user_args_t user_args) { - if(spi_idx == SPI_1) { - spi1_user_handler = user_handler; - spi1_user_args = user_args; - } - else { - spi2_user_handler = user_handler; - spi2_user_args = user_args; - } -} - -/* Do not change these function names! They need to be exactly equal to the name of the functions -defined in the startup_stm32h743xx.s files! */ - -void SPI1_IRQHandler() { - if(spi1_user_handler != NULL) { - spi1_user_handler(spi1_user_args); - return; - } - Default_Handler(); -} - -void SPI2_IRQHandler() { - if(spi2_user_handler != NULL) { - spi2_user_handler(spi2_user_args); - return; - } - Default_Handler(); -} /** * @brief This function handles DMA Rx interrupt request. @@ -71,3 +42,35 @@ void spi1_irq_handler(void* spi_handle) HAL_SPI_IRQHandler((SPI_HandleTypeDef *) spi_handle); } +void assign_spi_user_handler(spi::SpiBus spi_idx, user_handler_t user_handler, + user_args_t user_args) { + if(spi_idx == spi::SpiBus::SPI_1) { + spi1_user_handler = user_handler; + spi1_user_args = user_args; + } + else { + spi2_user_handler = user_handler; + spi2_user_args = user_args; + } +} + +/* Do not change these function names! They need to be exactly equal to the name of the functions +defined in the startup_stm32h743xx.s files! */ + +extern "C" void SPI1_IRQHandler() { + if(spi1_user_handler != NULL) { + spi1_user_handler(spi1_user_args); + return; + } + Default_Handler(); +} + +extern "C" void SPI2_IRQHandler() { + if(spi2_user_handler != NULL) { + spi2_user_handler(spi2_user_args); + return; + } + Default_Handler(); +} + + diff --git a/stm32h7/spi/interrupts.h b/stm32h7/spi/spiInterrupts.h similarity index 84% rename from stm32h7/spi/interrupts.h rename to stm32h7/spi/spiInterrupts.h index 060eaa1..49be029 100644 --- a/stm32h7/spi/interrupts.h +++ b/stm32h7/spi/spiInterrupts.h @@ -2,23 +2,20 @@ #define FSFW_HAL_STM32H7_SPI_INTERRUPTS_H_ #include "../interrupts.h" +#include "spiDefinitions.h" #ifdef __cplusplus extern "C" { #endif -typedef enum { - SPI_1, - SPI_2 -} SpiBus; - /** * Assign a user interrupt handler for SPI bus 1, allowing to pass an arbitrary argument as well. * Generally, this argument will be the related SPI handle. * @param user_handler * @param user_args */ -void assign_spi_user_handler(SpiBus spiBus, user_handler_t user_handler, user_args_t user_args); +void assign_spi_user_handler(spi::SpiBus spiBus, user_handler_t user_handler, + user_args_t user_args); /** * Generic interrupt handlers supplied for convenience. Do not call these directly! Set them From c50868c9dc46e27ae59e79f83f27723766656f08 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Jun 2021 17:13:14 +0200 Subject: [PATCH 17/35] continued spi com if --- stm32h7/spi/SpiComIF.cpp | 97 ++++++++++++++++++++++++++++++++++++++- stm32h7/spi/SpiComIF.h | 47 ++++++++++++++++++- stm32h7/spi/SpiCookie.cpp | 34 +++++++++++++- stm32h7/spi/SpiCookie.h | 12 ++++- 4 files changed, 183 insertions(+), 7 deletions(-) diff --git a/stm32h7/spi/SpiComIF.cpp b/stm32h7/spi/SpiComIF.cpp index 913c647..b47b919 100644 --- a/stm32h7/spi/SpiComIF.cpp +++ b/stm32h7/spi/SpiComIF.cpp @@ -1,10 +1,103 @@ #include "SpiComIF.h" +#include "SpiCookie.h" -SpiComIF::SpiComIF(object_id_t objectId, SPI_TypeDef* spiInstance, - spi::TransferModes transferMode): SystemObject(objectId) { +#include "fsfw/tasks/SemaphoreFactory.h" +#include "fsfw_hal/stm32h7/spi/spiCore.h" + +#include "stm32h7xx_hal_gpio.h" + +SpiComIF::SpiComIF(object_id_t objectId, SPI_TypeDef* spiInstance, SPI_HandleTypeDef* spiHandle, + spi::TransferModes transferMode): SystemObject(objectId), transferMode(transferMode), + spiHandle(spiHandle) { + if(spiHandle == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "SpiComIF::SpiComIF: Passed SPI handle invalid!" << std::endl; +#else + sif::printError("SpiComIF::SpiComIF: Passed SPI handle invalid!\n"); +#endif + return; + } + spiHandle->Instance = spiInstance; + spiHandle->Init.DataSize = SPI_DATASIZE_8BIT; + spiHandle->Init.FirstBit = SPI_FIRSTBIT_MSB; + spiHandle->Init.TIMode = SPI_TIMODE_DISABLE; + spiHandle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + spiHandle->Init.CRCPolynomial = 7; + spiHandle->Init.CRCLength = SPI_CRC_LENGTH_8BIT; + spiHandle->Init.NSS = SPI_NSS_SOFT; + spiHandle->Init.NSSPMode = SPI_NSS_PULSE_DISABLE; + spiHandle->Init.Direction = SPI_DIRECTION_2LINES; + // Recommended setting to avoid glitches + spiHandle->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; + spiHandle->Init.Mode = SPI_MODE_MASTER; + + spiSemaphore = SemaphoreFactory::instance()->createBinarySemaphore(); +} + +void SpiComIF::configureCacheMaintenanceOnTxBuffer(bool enable) { + this->cacheMaintenanceOnTxBuffer = enable; +} + +void SpiComIF::addDmaHandles(DMA_HandleTypeDef *txHandle, DMA_HandleTypeDef *rxHandle) { + set_dma_handles(txHandle, rxHandle); +} + +ReturnValue_t SpiComIF::initialize() { + if(transferMode == spi::TransferModes::DMA) { + DMA_HandleTypeDef *txHandle = nullptr; + DMA_HandleTypeDef *rxHandle = nullptr; + get_dma_handles(&txHandle, &rxHandle); + if(txHandle == nullptr or rxHandle == nullptr) { + sif::printError("SpiComIF::initialize: DMA handles not set!\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + } + if(HAL_SPI_Init(spiHandle) != HAL_OK) { + sif::printWarning("SpiComIF::initialize: Error initializing SPI\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { + SpiCookie* spiCookie = dynamic_cast(cookie); + if(spiCookie == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error < "SpiComIF::initializeInterface: Invalid cookie" << std::endl; +#else + sif::printError("SpiComIF::initializeInterface: Invalid cookie\n"); +#endif + return NULLPOINTER; + } + + address_t spiAddress = spiCookie->getDeviceAddress(); + + auto iter = spiDeviceMap.find(spiAddress); + if(iter == spiDeviceMap.end()) { + size_t bufferSize = spiCookie->getMaxRecvSize(); + SpiInstance spiInstance = {std::vector(bufferSize)}; + auto statusPair = spiDeviceMap.emplace(spiAddress, spiInstance); + if (not statusPair.second) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "SpiComIF::initializeInterface: Failed to insert device with address " << + spiAddress << "to SPI device map" << std::endl; +#else + sif::printError("SpiComIF::initializeInterface: Failed to insert device with address " + "%lu to SPI device map\n", static_cast(spiAddress)); +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ +#endif /* FSFW_VERBOSE_LEVEL >= 1 */ + return HasReturnvaluesIF::RETURN_FAILED; + } + } + auto gpioPin = spiCookie->getChipSelectGpioPin(); + auto gpioPort = spiCookie->getChipSelectGpioPort(); + + GPIO_InitTypeDef chipSelect = {}; + chipSelect.Pin = GPIO_PIN_14; + chipSelect.Mode = GPIO_MODE_OUTPUT_PP; + HAL_GPIO_Init(gpioPort, &chipSelect); + HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_SET); return HasReturnvaluesIF::RETURN_OK; } diff --git a/stm32h7/spi/SpiComIF.h b/stm32h7/spi/SpiComIF.h index bd79e0c..040cf4c 100644 --- a/stm32h7/spi/SpiComIF.h +++ b/stm32h7/spi/SpiComIF.h @@ -2,6 +2,7 @@ #define FSFW_HAL_STM32H7_SPI_SPICOMIF_H_ +#include "fsfw/tasks/SemaphoreIF.h" #include "fsfw/devicehandlers/DeviceCommunicationIF.h" #include "fsfw/objectmanager/SystemObject.h" @@ -9,11 +10,40 @@ #include "stm32h7xx_hal_spi.h" #include "stm32h743xx.h" +#include +#include + class SpiComIF: public SystemObject, public DeviceCommunicationIF { public: - SpiComIF(object_id_t objectId, SPI_TypeDef* spiInstance, spi::TransferModes transferMode); + /** + * Create a SPI communication interface for the given SPI peripheral (spiInstance) + * @param objectId + * @param spiInstance + * @param spiHandle + * @param transferMode + */ + SpiComIF(object_id_t objectId, SPI_TypeDef* spiInstance, SPI_HandleTypeDef* spiHandle, + spi::TransferModes transferMode); + + /** + * Allows the user to disable cache maintenance on the TX buffer. This can be done if the + * TX buffers are places and MPU protected properly like specified in this link: + * https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices + * The cache maintenace is enabled by default. + * @param enable + */ + void configureCacheMaintenanceOnTxBuffer(bool enable); + + /** + * Add the DMA handles. These need to be set in the DMA transfer mode is used + * @param txHandle + * @param rxHandle + */ + void addDmaHandles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle); + + ReturnValue_t initialize() override; protected: // DeviceCommunicationIF overrides @@ -25,8 +55,21 @@ protected: size_t requestLen) override; virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) override; + private: - SPI_HandleTypeDef spiHandle; + struct SpiInstance { + std::vector replyBuffer; + }; + + spi::TransferModes transferMode; + SPI_HandleTypeDef* spiHandle; + SemaphoreIF* spiSemaphore; + bool cacheMaintenanceOnTxBuffer = true; + + using SpiDeviceMap = std::map; + using SpiDeviceMapIter = SpiDeviceMap::iterator; + + SpiDeviceMap spiDeviceMap; }; diff --git a/stm32h7/spi/SpiCookie.cpp b/stm32h7/spi/SpiCookie.cpp index 97e5bee..c869510 100644 --- a/stm32h7/spi/SpiCookie.cpp +++ b/stm32h7/spi/SpiCookie.cpp @@ -3,7 +3,37 @@ SpiCookie::SpiCookie(address_t deviceAddress, spi::SpiBus spiIdx, uint32_t spiSpeed, - spi::SpiModes spiMode, uint16_t chipSelectGpioPin, GPIO_TypeDef* chipSelectGpioPort): + spi::SpiModes spiMode, uint16_t chipSelectGpioPin, GPIO_TypeDef* chipSelectGpioPort, + size_t maxRecvSize): deviceAddress(deviceAddress), spiIdx(spiIdx), spiSpeed(spiSpeed), spiMode(spiMode), - chipSelectGpioPin(chipSelectGpioPin), chipSelectGpioPort(chipSelectGpioPort) { + chipSelectGpioPin(chipSelectGpioPin), chipSelectGpioPort(chipSelectGpioPort), + maxRecvSize(maxRecvSize) { +} + +uint16_t SpiCookie::getChipSelectGpioPin() const { + return chipSelectGpioPin; +} + +GPIO_TypeDef* SpiCookie::getChipSelectGpioPort() { + return chipSelectGpioPort; +} + +address_t SpiCookie::getDeviceAddress() const { + return deviceAddress; +} + +spi::SpiBus SpiCookie::getSpiIdx() const { + return spiIdx; +} + +spi::SpiModes SpiCookie::getSpiMode() const { + return spiMode; +} + +uint32_t SpiCookie::getSpiSpeed() const { + return spiSpeed; +} + +size_t SpiCookie::getMaxRecvSize() const { + return maxRecvSize; } diff --git a/stm32h7/spi/SpiCookie.h b/stm32h7/spi/SpiCookie.h index 1bee9ba..bf9baff 100644 --- a/stm32h7/spi/SpiCookie.h +++ b/stm32h7/spi/SpiCookie.h @@ -10,7 +10,16 @@ class SpiCookie: public CookieIF { public: SpiCookie(address_t deviceAddress, spi::SpiBus spiIdx, uint32_t spiSpeed, spi::SpiModes spiMode, - uint16_t chipSelectGpioPin, GPIO_TypeDef* chipSelectGpioPort); + uint16_t chipSelectGpioPin, GPIO_TypeDef* chipSelectGpioPort, size_t maxRecvSize); + + uint16_t getChipSelectGpioPin() const; + GPIO_TypeDef* getChipSelectGpioPort(); + address_t getDeviceAddress() const; + spi::SpiBus getSpiIdx() const; + spi::SpiModes getSpiMode() const; + uint32_t getSpiSpeed() const; + size_t getMaxRecvSize() const; + private: address_t deviceAddress; spi::SpiBus spiIdx; @@ -18,6 +27,7 @@ private: spi::SpiModes spiMode; uint16_t chipSelectGpioPin; GPIO_TypeDef* chipSelectGpioPort; + const size_t maxRecvSize; }; From f7f6e4d520295083818c971c00ffbc4af6d94c76 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 5 Jun 2021 00:04:38 +0200 Subject: [PATCH 18/35] continued spi com if --- stm32h7/spi/SpiComIF.cpp | 80 +++++++++++++++++++++++++++++++++++- stm32h7/spi/SpiComIF.h | 15 ++++++- stm32h7/spi/spiDefinitions.h | 7 ++++ 3 files changed, 99 insertions(+), 3 deletions(-) diff --git a/stm32h7/spi/SpiComIF.cpp b/stm32h7/spi/SpiComIF.cpp index b47b919..8a185a2 100644 --- a/stm32h7/spi/SpiComIF.cpp +++ b/stm32h7/spi/SpiComIF.cpp @@ -30,8 +30,6 @@ SpiComIF::SpiComIF(object_id_t objectId, SPI_TypeDef* spiInstance, SPI_HandleTyp // Recommended setting to avoid glitches spiHandle->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; spiHandle->Init.Mode = SPI_MODE_MASTER; - - spiSemaphore = SemaphoreFactory::instance()->createBinarySemaphore(); } void SpiComIF::configureCacheMaintenanceOnTxBuffer(bool enable) { @@ -70,6 +68,13 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { return NULLPOINTER; } + if(transferMode == spi::TransferModes::DMA or transferMode == spi::TransferModes::INTERRUPT) { + spiSemaphore = SemaphoreFactory::instance()->createBinarySemaphore(); + } + else { + spiMutex = MutexFactory::instance()->createMutex(); + } + address_t spiAddress = spiCookie->getDeviceAddress(); auto iter = spiDeviceMap.find(spiAddress); @@ -102,6 +107,29 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { } ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen) { + SpiCookie* spiCookie = dynamic_cast(cookie); + if(spiCookie == nullptr) { + return NULLPOINTER; + } + + spi::assignSpiMode(spiCookie->getSpiMode(), spiHandle); + spiHandle->Init.BaudRatePrescaler = spi::getPrescaler(HAL_RCC_GetHCLKFreq(), + spiCookie->getSpiSpeed()); + auto iter = spiDeviceMap.find(spiCookie->getDeviceAddress()); + if(iter == spiDeviceMap.end()) { + return HasReturnvaluesIF::RETURN_FAILED; + } + switch(transferMode) { + case(spi::TransferModes::POLLING): { + return handlePollingSendOperation(iter, spiCookie, sendData, sendLen); + } + case(spi::TransferModes::INTERRUPT): { + break; + } + case(spi::TransferModes::DMA): { + break; + } + } return HasReturnvaluesIF::RETURN_OK; } @@ -113,6 +141,54 @@ ReturnValue_t SpiComIF::requestReceiveMessage(CookieIF *cookie, size_t requestLe return HasReturnvaluesIF::RETURN_OK; } +void SpiComIF::setDefaultPollingTimeout(dur_millis_t timeout) { + this->defaultPollingTimeout = timeout; +} + ReturnValue_t SpiComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) { return HasReturnvaluesIF::RETURN_OK; } + +ReturnValue_t SpiComIF::handlePollingSendOperation(SpiDeviceMapIter iter, SpiCookie *spiCookie, + const uint8_t *sendData, size_t sendLen) { + auto gpioPort = spiCookie->getChipSelectGpioPort(); + auto gpioPin = spiCookie->getChipSelectGpioPin(); + spiMutex->lockMutex(timeoutType, timeoutMs); + HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_RESET); + auto result = HAL_SPI_TransmitReceive(spiHandle, const_cast(sendData), + iter->second.replyBuffer.data(), + sendLen, defaultPollingTimeout); + HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_SET); + spiMutex->unlockMutex(); + switch(result) { + case(HAL_OK): { + break; + } + case(HAL_TIMEOUT): { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "SpiComIF::sendMessage: Polling Mode | Timeout for SPI device" << + spiCookie->getDeviceAddress() << std::endl; +#else + sif::printWarning("SpiComIF::sendMessage: Polling Mode | Timeout for SPI device %d\n", + spiCookie->getDeviceAddress()); +#endif +#endif + return spi::HAL_TIMEOUT_RETVAL; + } + case(HAL_ERROR): + default: { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "SpiComIF::sendMessage: Polling Mode | HAL error for SPI device" << + spiCookie->getDeviceAddress() << std::endl; +#else + sif::printWarning("SpiComIF::sendMessage: Polling Mode | HAL error for SPI device %d\n", + spiCookie->getDeviceAddress()); +#endif +#endif + return spi::HAL_ERROR_RETVAL; + } + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/stm32h7/spi/SpiComIF.h b/stm32h7/spi/SpiComIF.h index 040cf4c..0826e8c 100644 --- a/stm32h7/spi/SpiComIF.h +++ b/stm32h7/spi/SpiComIF.h @@ -13,6 +13,8 @@ #include #include +class SpiCookie; + class SpiComIF: public SystemObject, public DeviceCommunicationIF { @@ -36,6 +38,8 @@ public: */ void configureCacheMaintenanceOnTxBuffer(bool enable); + void setDefaultPollingTimeout(dur_millis_t timeout); + /** * Add the DMA handles. These need to be set in the DMA transfer mode is used * @param txHandle @@ -60,16 +64,25 @@ private: struct SpiInstance { std::vector replyBuffer; }; + uint32_t defaultPollingTimeout = 50; spi::TransferModes transferMode; SPI_HandleTypeDef* spiHandle; - SemaphoreIF* spiSemaphore; + + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; + dur_millis_t timeoutMs = 20; + + SemaphoreIF* spiSemaphore = nullptr; + MutexIF* spiMutex = nullptr; bool cacheMaintenanceOnTxBuffer = true; using SpiDeviceMap = std::map; using SpiDeviceMapIter = SpiDeviceMap::iterator; SpiDeviceMap spiDeviceMap; + + ReturnValue_t handlePollingSendOperation(SpiDeviceMapIter iter, SpiCookie* spiCookie, + const uint8_t * sendData, size_t sendLen); }; diff --git a/stm32h7/spi/spiDefinitions.h b/stm32h7/spi/spiDefinitions.h index b812c15..db16df4 100644 --- a/stm32h7/spi/spiDefinitions.h +++ b/stm32h7/spi/spiDefinitions.h @@ -3,11 +3,18 @@ #include "../../common/spi/spiCommon.h" +#include "fsfw/returnvalues/FwClassIds.h" +#include "fsfw/returnvalues/HasReturnvaluesIF.h" + #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_spi.h" namespace spi { +static constexpr uint8_t HAL_SPI_ID = CLASS_ID::HAL_SPI; +static constexpr ReturnValue_t HAL_TIMEOUT_RETVAL = HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 0); +static constexpr ReturnValue_t HAL_ERROR_RETVAL = HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 1); + enum SpiBus { SPI_1, SPI_2 From be88bf1d5076fab3a5184b9d86f3701591c3ce62 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 5 Jun 2021 00:11:35 +0200 Subject: [PATCH 19/35] important bugfix --- stm32h7/spi/SpiComIF.cpp | 26 +++++++++++++++++++------- stm32h7/spi/SpiComIF.h | 6 +++++- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/stm32h7/spi/SpiComIF.cpp b/stm32h7/spi/SpiComIF.cpp index 8a185a2..877c0eb 100644 --- a/stm32h7/spi/SpiComIF.cpp +++ b/stm32h7/spi/SpiComIF.cpp @@ -99,7 +99,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { auto gpioPort = spiCookie->getChipSelectGpioPort(); GPIO_InitTypeDef chipSelect = {}; - chipSelect.Pin = GPIO_PIN_14; + chipSelect.Pin = gpioPin; chipSelect.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(gpioPort, &chipSelect); HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_SET); @@ -121,13 +121,16 @@ ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, s } switch(transferMode) { case(spi::TransferModes::POLLING): { - return handlePollingSendOperation(iter, spiCookie, sendData, sendLen); + return handlePollingSendOperation(iter->second.replyBuffer.data(), spiCookie, sendData, + sendLen); } case(spi::TransferModes::INTERRUPT): { - break; + return handleInterruptSendOperation(iter->second.replyBuffer.data(), spiCookie, sendData, + sendLen); } case(spi::TransferModes::DMA): { - break; + return handleDmaSendOperation(iter->second.replyBuffer.data(), spiCookie, sendData, + sendLen); } } return HasReturnvaluesIF::RETURN_OK; @@ -149,15 +152,14 @@ ReturnValue_t SpiComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t SpiComIF::handlePollingSendOperation(SpiDeviceMapIter iter, SpiCookie *spiCookie, +ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SpiCookie *spiCookie, const uint8_t *sendData, size_t sendLen) { auto gpioPort = spiCookie->getChipSelectGpioPort(); auto gpioPin = spiCookie->getChipSelectGpioPin(); spiMutex->lockMutex(timeoutType, timeoutMs); HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_RESET); auto result = HAL_SPI_TransmitReceive(spiHandle, const_cast(sendData), - iter->second.replyBuffer.data(), - sendLen, defaultPollingTimeout); + recvPtr, sendLen, defaultPollingTimeout); HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_SET); spiMutex->unlockMutex(); switch(result) { @@ -192,3 +194,13 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(SpiDeviceMapIter iter, SpiCoo } return HasReturnvaluesIF::RETURN_OK; } + +ReturnValue_t SpiComIF::handleInterruptSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, + const uint8_t * sendData, size_t sendLen) { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t SpiComIF::handleDmaSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, + const uint8_t * sendData, size_t sendLen) { + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/stm32h7/spi/SpiComIF.h b/stm32h7/spi/SpiComIF.h index 0826e8c..d166f49 100644 --- a/stm32h7/spi/SpiComIF.h +++ b/stm32h7/spi/SpiComIF.h @@ -81,7 +81,11 @@ private: SpiDeviceMap spiDeviceMap; - ReturnValue_t handlePollingSendOperation(SpiDeviceMapIter iter, SpiCookie* spiCookie, + ReturnValue_t handlePollingSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, + const uint8_t * sendData, size_t sendLen); + ReturnValue_t handleInterruptSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, + const uint8_t * sendData, size_t sendLen); + ReturnValue_t handleDmaSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, const uint8_t * sendData, size_t sendLen); }; From 01d3bc2568c223a4efc1c854ea8d0a2e81b76154 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 5 Jun 2021 13:29:43 +0200 Subject: [PATCH 20/35] converted files to cpp --- stm32h7/CMakeLists.txt | 2 +- stm32h7/devicetest/GyroL3GD20H.cpp | 28 ++-- stm32h7/devicetest/GyroL3GD20H.h | 5 +- .../{dma_interrupts.c => dmaInterrupts.cpp} | 36 ++--- stm32h7/{dma_interrupts.h => dmaInterrupts.h} | 20 ++- stm32h7/spi/SpiComIF.cpp | 8 +- stm32h7/spi/mspInit.cpp | 39 ++--- stm32h7/spi/mspInit.h | 17 ++- stm32h7/spi/spiCore.cpp | 143 ++++++++++++++---- stm32h7/spi/spiCore.h | 24 ++- stm32h7/spi/spiInterrupts.cpp | 44 +++--- stm32h7/spi/spiInterrupts.h | 12 +- 12 files changed, 245 insertions(+), 133 deletions(-) rename stm32h7/{dma_interrupts.c => dmaInterrupts.cpp} (67%) rename stm32h7/{dma_interrupts.h => dmaInterrupts.h} (67%) diff --git a/stm32h7/CMakeLists.txt b/stm32h7/CMakeLists.txt index 58b50fe..3837285 100644 --- a/stm32h7/CMakeLists.txt +++ b/stm32h7/CMakeLists.txt @@ -2,5 +2,5 @@ add_subdirectory(spi) add_subdirectory(devicetest) target_sources(${TARGET_NAME} PRIVATE - dma_interrupts.c + dmaInterrupts.cpp ) diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index b0a16c1..d76a746 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -27,18 +27,22 @@ GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transf spiHandle(spiHandle) { transferMode = transferMode_; if(transferMode == spi::TransferModes::DMA) { - set_dma_handles(&txDmaHandle, &rxDmaHandle); - set_spi_msp_functions(&hal_spi_msp_init_dma, spiHandle, &hal_spi_msp_deinit_dma, spiHandle); + spi::setDmaHandles(&txDmaHandle, &rxDmaHandle); + spi::setSpiMspFunctions(&spi::halMspInitDma, spiHandle, + &spi::halMspDeinitDma, spiHandle); } else if(transferMode == spi::TransferModes::INTERRUPT) { - set_spi_msp_functions(&hal_spi_msp_init_interrupt, spiHandle, - &hal_spi_msp_deinit_interrupt, spiHandle); + spi::setSpiMspFunctions(&spi::halMspInitInterrupt, spiHandle, + &spi::halMspDeinitInterrupt, spiHandle); } else if(transferMode == spi::TransferModes::POLLING) { - set_spi_msp_functions(&hal_spi_msp_init_polling, spiHandle, - &hal_spi_msp_deinit_polling, spiHandle); + spi::setSpiMspFunctions(&spi::halMspInitPolling, spiHandle, + &spi::halMspDeinitPolling, spiHandle); } + spi::assignTransferRxTxCompleteCallback(&spiTransferCompleteCallback, nullptr); + spi::assignTransferErrorCallback(&spiTransferErrorCallback, nullptr); + GPIO_InitTypeDef chipSelect = {}; __HAL_RCC_GPIOD_CLK_ENABLE(); chipSelect.Pin = GPIO_PIN_14; @@ -502,14 +506,8 @@ void GyroL3GD20H::handleSensorReadout() { sif::printInfo("Gyro Z: %f\n", gyroZ); } -/** - * @brief TxRx Transfer completed callback. - * @param hspi: SPI handle - * @note This example shows a simple way to report end of DMA TxRx transfer, and - * you can add your own implementation. - * @retval None - */ -void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { + +void GyroL3GD20H::spiTransferCompleteCallback(SPI_HandleTypeDef *hspi, void* args) { transferState = TransferStates::SUCCESS; HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); if(GyroL3GD20H::transferMode == spi::TransferModes::DMA) { @@ -526,6 +524,6 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { * add your own implementation. * @retval None */ -void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { +void GyroL3GD20H::spiTransferErrorCallback(SPI_HandleTypeDef *hspi, void* args) { transferState = TransferStates::FAILURE; } diff --git a/stm32h7/devicetest/GyroL3GD20H.h b/stm32h7/devicetest/GyroL3GD20H.h index 72e9ccc..b96f203 100644 --- a/stm32h7/devicetest/GyroL3GD20H.h +++ b/stm32h7/devicetest/GyroL3GD20H.h @@ -18,7 +18,6 @@ enum class TransferStates { }; class GyroL3GD20H { - friend void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi); public: GyroL3GD20H(SPI_HandleTypeDef* spiHandle, spi::TransferModes transferMode); @@ -51,6 +50,10 @@ private: ReturnValue_t handlePollingSensorRead(); ReturnValue_t handleInterruptSensorRead(); + friend void spiTransferCompleteCallback(SPI_HandleTypeDef *hspi, void* args); + static void spiTransferCompleteCallback(SPI_HandleTypeDef *hspi, void* args); + static void spiTransferErrorCallback(SPI_HandleTypeDef *hspi, void* args); + void prepareConfigRegs(uint8_t* configRegs); void handleSensorReadout(); }; diff --git a/stm32h7/dma_interrupts.c b/stm32h7/dmaInterrupts.cpp similarity index 67% rename from stm32h7/dma_interrupts.c rename to stm32h7/dmaInterrupts.cpp index db51063..a10793d 100644 --- a/stm32h7/dma_interrupts.c +++ b/stm32h7/dmaInterrupts.cpp @@ -1,4 +1,4 @@ -#include "dma_interrupts.h" +#include "dmaInterrupts.h" #include #include @@ -9,7 +9,7 @@ user_args_t DMA_1_USER_ARGS[8]; user_handler_t DMA_2_USER_HANDLERS[8]; user_args_t DMA_2_USER_ARGS[8]; -void assign_dma_user_handler(DMAIndexes dma_idx, DMAStreams stream_idx, +void dma::assignDmaUserHandler(DMAIndexes dma_idx, DMAStreams stream_idx, user_handler_t user_handler, user_args_t user_args) { if(dma_idx == DMA_1) { DMA_1_USER_HANDLERS[stream_idx] = user_handler; @@ -33,52 +33,52 @@ defined in the startup_stm32h743xx.s files! */ } \ Default_Handler() \ -void DMA1_Stream0_IRQHandler() { +extern"C" void DMA1_Stream0_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(1, 0); } -void DMA1_Stream1_IRQHandler() { +extern"C" void DMA1_Stream1_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(1, 1); } -void DMA1_Stream2_IRQHandler() { +extern"C" void DMA1_Stream2_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(1, 2); } -void DMA1_Stream3_IRQHandler() { +extern"C" void DMA1_Stream3_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(1, 3); } -void DMA1_Stream4_IRQHandler() { +extern"C" void DMA1_Stream4_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(1, 4); } -void DMA1_Stream5_IRQHandler() { +extern"C" void DMA1_Stream5_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(1, 5); } -void DMA1_Stream6_IRQHandler() { +extern"C" void DMA1_Stream6_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(1, 6); } -void DMA1_Stream7_IRQHandler() { +extern"C" void DMA1_Stream7_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(1, 7); } -void DMA2_Stream0_IRQHandler() { +extern"C" void DMA2_Stream0_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(2, 0); } -void DMA2_Stream1_IRQHandler() { +extern"C" void DMA2_Stream1_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(2, 1); } -void DMA2_Stream2_IRQHandler() { +extern"C" void DMA2_Stream2_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(2, 2); } -void DMA2_Stream3_IRQHandler() { +extern"C" void DMA2_Stream3_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(2, 3); } -void DMA2_Stream4_IRQHandler() { +extern"C" void DMA2_Stream4_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(2, 4); } -void DMA2_Stream5_IRQHandler() { +extern"C" void DMA2_Stream5_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(2, 5); } -void DMA2_Stream6_IRQHandler() { +extern"C" void DMA2_Stream6_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(2, 6); } -void DMA2_Stream7_IRQHandler() { +extern"C" void DMA2_Stream7_IRQHandler() { GENERIC_DMA_IRQ_HANDLER(2, 7); } diff --git a/stm32h7/dma_interrupts.h b/stm32h7/dmaInterrupts.h similarity index 67% rename from stm32h7/dma_interrupts.h rename to stm32h7/dmaInterrupts.h index b24c235..49eaba7 100644 --- a/stm32h7/dma_interrupts.h +++ b/stm32h7/dmaInterrupts.h @@ -1,5 +1,5 @@ -#ifndef FSFW_HAL_STM32H7_DMA_INTERRUPTS_H_ -#define FSFW_HAL_STM32H7_DMA_INTERRUPTS_H_ +#ifndef FSFW_HAL_STM32H7_DMAINTERRUPTS_H_ +#define FSFW_HAL_STM32H7_DMAINTERRUPTS_H_ #ifdef __cplusplus extern "C" { @@ -7,12 +7,14 @@ extern "C" { #include "interrupts.h" -typedef enum { +namespace dma { + +enum DMAIndexes { DMA_1 = 0, DMA_2 = 1 -} DMAIndexes; +} ; -typedef enum { +enum DMAStreams { STREAM_0 = 0, STREAM_1 = 1, STREAM_2 = 2, @@ -21,7 +23,7 @@ typedef enum { STREAM_5 = 5, STREAM_6 = 6, STREAM_7 = 7, -} DMAStreams; +} ; /** * Assign user interrupt handlers for DMA streams, allowing to pass an @@ -29,11 +31,13 @@ typedef enum { * @param user_handler * @param user_args */ -void assign_dma_user_handler(DMAIndexes dma_idx, DMAStreams stream_idx, +void assignDmaUserHandler(DMAIndexes dma_idx, DMAStreams stream_idx, user_handler_t user_handler, user_args_t user_args); +} + #ifdef __cplusplus } #endif -#endif /* FSFW_HAL_STM32H7_DMA_INTERRUPTS_H_ */ +#endif /* FSFW_HAL_STM32H7_DMAINTERRUPTS_H_ */ diff --git a/stm32h7/spi/SpiComIF.cpp b/stm32h7/spi/SpiComIF.cpp index 877c0eb..bec47a6 100644 --- a/stm32h7/spi/SpiComIF.cpp +++ b/stm32h7/spi/SpiComIF.cpp @@ -37,14 +37,14 @@ void SpiComIF::configureCacheMaintenanceOnTxBuffer(bool enable) { } void SpiComIF::addDmaHandles(DMA_HandleTypeDef *txHandle, DMA_HandleTypeDef *rxHandle) { - set_dma_handles(txHandle, rxHandle); + spi::setDmaHandles(txHandle, rxHandle); } ReturnValue_t SpiComIF::initialize() { if(transferMode == spi::TransferModes::DMA) { DMA_HandleTypeDef *txHandle = nullptr; DMA_HandleTypeDef *rxHandle = nullptr; - get_dma_handles(&txHandle, &rxHandle); + spi::getDmaHandles(&txHandle, &rxHandle); if(txHandle == nullptr or rxHandle == nullptr) { sif::printError("SpiComIF::initialize: DMA handles not set!\n"); return HasReturnvaluesIF::RETURN_FAILED; @@ -197,6 +197,10 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SpiCookie * ReturnValue_t SpiComIF::handleInterruptSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, const uint8_t * sendData, size_t sendLen) { + auto gpioPort = spiCookie->getChipSelectGpioPort(); + auto gpioPin = spiCookie->getChipSelectGpioPin(); + spiMutex->lockMutex(timeoutType, timeoutMs); + HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_RESET); return HasReturnvaluesIF::RETURN_OK; } diff --git a/stm32h7/spi/mspInit.cpp b/stm32h7/spi/mspInit.cpp index 05f9522..5e14e8a 100644 --- a/stm32h7/spi/mspInit.cpp +++ b/stm32h7/spi/mspInit.cpp @@ -1,9 +1,8 @@ +#include #include "mspInit.h" #include "spiConf.h" #include "spiCore.h" #include "spiInterrupts.h" -#include "../dma_interrupts.h" - #include "stm32h743xx.h" #include "stm32h7xx_hal_spi.h" #include "stm32h7xx_hal_dma.h" @@ -21,7 +20,7 @@ * @param hspi: SPI handle pointer * @retval None */ -void hal_spi_msp_init_dma(void *spi_handle) { +void spi::halMspInitDma(void *spi_handle) { SPI_HandleTypeDef* hspi = (SPI_HandleTypeDef*) spi_handle; if(hspi == NULL) { return; @@ -30,17 +29,17 @@ void hal_spi_msp_init_dma(void *spi_handle) { printf("HAL_SPI_MspInit: Invalid SPI handle!\n"); return; } - assign_spi_handle(hspi); + setSpiHandle(hspi); DMA_HandleTypeDef* hdma_tx = NULL; DMA_HandleTypeDef* hdma_rx = NULL; - get_dma_handles(&hdma_tx, &hdma_rx); + spi::getDmaHandles(&hdma_tx, &hdma_rx); if(hdma_tx == NULL || hdma_rx == NULL) { printf("HAL_SPI_MspInit: Invalid DMA handles. Make sure to call setDmaHandles!\n"); return; } - hal_spi_msp_init_polling(spi_handle); + spi::halMspInitPolling(spi_handle); if (hspi->Instance == SPI1) { // DMA setup DMAx_CLK_ENABLE(); @@ -90,20 +89,22 @@ void hal_spi_msp_init_dma(void *spi_handle) { /*##-4- Configure the NVIC for DMA #########################################*/ /* NVIC configuration for DMA transfer complete interrupt (SPI1_RX) */ // Assign the interrupt handler - assign_dma_user_handler(DMA_2, DMAStreams::STREAM_2, &dma_rx_irq_handler, hdma_rx); + dma::assignDmaUserHandler(dma::DMAIndexes::DMA_2, dma::DMAStreams::STREAM_2, + &spi::dmaRxIrqHandler, hdma_rx); HAL_NVIC_SetPriority(SPIx_DMA_RX_IRQn, 1, 0); HAL_NVIC_EnableIRQ(SPIx_DMA_RX_IRQn); /* NVIC configuration for DMA transfer complete interrupt (SPI1_TX) */ // Assign the interrupt handler - assign_dma_user_handler(DMA_2, DMAStreams::STREAM_3, &dma_tx_irq_handler, hdma_tx); + dma::assignDmaUserHandler(dma::DMAIndexes::DMA_2, dma::DMAStreams::STREAM_3, + &spi::dmaTxIrqHandler, hdma_tx); HAL_NVIC_SetPriority(SPIx_DMA_TX_IRQn, 1, 1); HAL_NVIC_EnableIRQ(SPIx_DMA_TX_IRQn); /*##-5- Configure the NVIC for SPI #########################################*/ /* NVIC configuration for SPI transfer complete interrupt (SPI1) */ // Assign the interrupt handler - assign_spi_user_handler(spi::SPI_1, &spi1_irq_handler, hspi); + spi::assignSpiUserHandler(spi::SPI_1, &spi::spi1IrqHandler, hspi); HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0); HAL_NVIC_EnableIRQ(SPIx_IRQn); } @@ -117,17 +118,17 @@ void hal_spi_msp_init_dma(void *spi_handle) { * @param hspi: SPI handle pointer * @retval None */ -void hal_spi_msp_deinit_dma(void *spi_handle) +void spi::halMspDeinitDma(void *spi_handle) { SPI_HandleTypeDef* hspi = (SPI_HandleTypeDef*) spi_handle; if(hspi == NULL) { return; } - hal_spi_msp_deinit_polling(spi_handle); + spi::halMspDeinitPolling(spi_handle); if(hspi->Instance == SPIx) { DMA_HandleTypeDef* hdma_tx = NULL; DMA_HandleTypeDef* hdma_rx = NULL; - get_dma_handles(&hdma_tx, &hdma_rx); + spi::getDmaHandles(&hdma_tx, &hdma_rx); if(hdma_tx == NULL || hdma_rx == NULL) { printf("HAL_SPI_MspInit: Invalid DMA handles. Make sure to call setDmaHandles!\n"); } @@ -148,7 +149,7 @@ void hal_spi_msp_deinit_dma(void *spi_handle) } } -void hal_spi_msp_init_polling(void *hspi) { +void spi::halMspInitPolling(void *hspi) { GPIO_InitTypeDef GPIO_InitStruct = {}; /*##-1- Enable peripherals and GPIO Clocks #################################*/ /* Enable GPIO TX/RX clock */ @@ -178,7 +179,7 @@ void hal_spi_msp_init_polling(void *hspi) { HAL_GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStruct); } -void hal_spi_msp_deinit_polling(void *hspi) { +void spi::halMspDeinitPolling(void *hspi) { /*##-1- Reset peripherals ##################################################*/ SPIx_FORCE_RESET(); SPIx_RELEASE_RESET(); @@ -192,16 +193,16 @@ void hal_spi_msp_deinit_polling(void *hspi) { HAL_GPIO_DeInit(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_PIN); } -void hal_spi_msp_init_interrupt(void *hspi) { - hal_spi_msp_init_polling(hspi); +void spi::halMspInitInterrupt(void *hspi) { + spi::halMspInitPolling(hspi); // Configure the NVIC for SPI - assign_spi_user_handler(spi::SPI_1, &spi1_irq_handler, hspi); + spi::assignSpiUserHandler(spi::SPI_1, &spi::spi1IrqHandler, hspi); HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0); HAL_NVIC_EnableIRQ(SPIx_IRQn); } -void hal_spi_msp_deinit_interrupt(void *hspi) { - hal_spi_msp_deinit_polling(hspi); +void spi::halMspDeinitInterrupt(void *hspi) { + spi::halMspDeinitPolling(hspi); // Disable the NVIC for SPI HAL_NVIC_DisableIRQ(SPIx_IRQn); } diff --git a/stm32h7/spi/mspInit.h b/stm32h7/spi/mspInit.h index da352f6..fb350ca 100644 --- a/stm32h7/spi/mspInit.h +++ b/stm32h7/spi/mspInit.h @@ -5,14 +5,19 @@ extern "C" { #endif -void hal_spi_msp_init_dma(void *hspi); -void hal_spi_msp_deinit_dma(void *hspi); +namespace spi { -void hal_spi_msp_init_polling(void *hspi); -void hal_spi_msp_deinit_polling(void *hspi); +void halMspInitDma(void *hspi); +void halMspDeinitDma(void *hspi); + +void halMspInitPolling(void *hspi); +void halMspDeinitPolling(void *hspi); + +void halMspInitInterrupt(void *hspi); +void halMspDeinitInterrupt(void *hspi); + +} -void hal_spi_msp_init_interrupt(void *hspi); -void hal_spi_msp_deinit_interrupt(void *hspi); #ifdef __cplusplus } diff --git a/stm32h7/spi/spiCore.cpp b/stm32h7/spi/spiCore.cpp index ad57f5d..dd91f2d 100644 --- a/stm32h7/spi/spiCore.cpp +++ b/stm32h7/spi/spiCore.cpp @@ -2,55 +2,84 @@ #include SPI_HandleTypeDef* spiHandle = nullptr; -DMA_HandleTypeDef* hdma_tx = nullptr; -DMA_HandleTypeDef* hdma_rx = nullptr; +DMA_HandleTypeDef* hdmaTx = nullptr; +DMA_HandleTypeDef* hdmaRx = nullptr; -msp_func_t msp_init_func = nullptr; -void* msp_init_args = nullptr; +msp_func_t mspInitFunc = nullptr; +void* mspInitArgs = nullptr; -msp_func_t msp_deinit_func = nullptr; -void* msp_deinit_args = nullptr; +msp_func_t mspDeinitFunc = nullptr; +void* mspDeinitArgs = nullptr; -void set_dma_handles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle) { - hdma_tx = txHandle; - hdma_rx = rxHandle; +spi_transfer_cb_t rxTxCb = nullptr; +void* rxTxArgs = nullptr; +spi_transfer_cb_t txCb = nullptr; +void* txArgs = nullptr; +spi_transfer_cb_t rxCb = nullptr; +void* rxArgs = nullptr; +spi_transfer_cb_t errorCb = nullptr; +void* errorArgs = nullptr; + +void spi::setDmaHandles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle) { + hdmaTx = txHandle; + hdmaRx = rxHandle; } -void get_dma_handles(DMA_HandleTypeDef** txHandle, DMA_HandleTypeDef** rxHandle) { - *txHandle = hdma_tx; - *rxHandle = hdma_rx; +void spi::getDmaHandles(DMA_HandleTypeDef** txHandle, DMA_HandleTypeDef** rxHandle) { + *txHandle = hdmaTx; + *rxHandle = hdmaRx; } -void assign_spi_handle(SPI_HandleTypeDef *spiHandle_) { +void spi::setSpiHandle(SPI_HandleTypeDef *spiHandle_) { if(spiHandle_ == NULL) { return; } spiHandle = spiHandle_; } -SPI_HandleTypeDef* get_spi_handle() { +void spi::assignTransferRxTxCompleteCallback(spi_transfer_cb_t callback, void *userArgs) { + rxTxCb = callback; + rxTxArgs = userArgs; +} + +void spi::assignTransferRxCompleteCallback(spi_transfer_cb_t callback, void *userArgs) { + rxCb = callback; + rxArgs = userArgs; +} + +void spi::assignTransferTxCompleteCallback(spi_transfer_cb_t callback, void *userArgs) { + txCb = callback; + txArgs = userArgs; +} + +void spi::assignTransferErrorCallback(spi_transfer_cb_t callback, void *userArgs) { + errorCb = callback; + errorArgs = userArgs; +} + +SPI_HandleTypeDef* spi::getSpiHandle() { return spiHandle; } -void set_spi_msp_functions(msp_func_t init_func, void* init_args, msp_func_t deinit_func, +void spi::setSpiMspFunctions(msp_func_t init_func, void* init_args, msp_func_t deinit_func, void* deinit_args) { - msp_init_func = init_func; - msp_init_args = init_args; - msp_deinit_func = deinit_func; - msp_deinit_args = deinit_args; + mspInitFunc = init_func; + mspInitArgs = init_args; + mspDeinitFunc = deinit_func; + mspDeinitArgs = deinit_args; } -void get_msp_init_function(msp_func_t* init_func, void **args) { +void spi::getMspInitFunction(msp_func_t* init_func, void **args) { if(init_func != NULL && args != NULL) { - *init_func = msp_init_func; - *args = msp_init_args; + *init_func = mspInitFunc; + *args = mspInitArgs; } } -void get_msp_deinit_function(msp_func_t* deinit_func, void **args) { +void spi::getMspDeinitFunction(msp_func_t* deinit_func, void **args) { if(deinit_func != NULL && args != NULL) { - *deinit_func = msp_deinit_func; - *args = msp_deinit_args; + *deinit_func = mspDeinitFunc; + *args = mspDeinitArgs; } } @@ -65,8 +94,8 @@ void get_msp_deinit_function(msp_func_t* deinit_func, void **args) { * @retval None */ extern "C" void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) { - if(msp_init_func != NULL) { - msp_init_func(msp_init_args); + if(mspInitFunc != NULL) { + mspInitFunc(mspInitArgs); } else { printf("HAL_SPI_MspInit: Please call set_msp_functions to assign SPI MSP functions\n"); @@ -82,10 +111,66 @@ extern "C" void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) { * @retval None */ extern "C" void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) { - if(msp_deinit_func != NULL) { - msp_deinit_func(msp_deinit_args); + if(mspDeinitFunc != NULL) { + mspDeinitFunc(mspDeinitArgs); } else { printf("HAL_SPI_MspDeInit: Please call set_msp_functions to assign SPI MSP functions\n"); } } + +/** + * @brief TxRx Transfer completed callback. + * @param hspi: SPI handle + */ +extern "C" void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { + if(rxTxCb != NULL) { + rxTxCb(hspi, rxTxArgs); + } + else { + printf("HAL_SPI_TxRxCpltCallback: No user callback specified\n"); + } +} + +/** + * @brief TxRx Transfer completed callback. + * @param hspi: SPI handle + */ +extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) { + if(txCb != NULL) { + txCb(hspi, txArgs); + } + else { + printf("HAL_SPI_TxCpltCallback: No user callback specified\n"); + } +} + +/** + * @brief TxRx Transfer completed callback. + * @param hspi: SPI handle + */ +extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) { + if(rxCb != nullptr) { + rxCb(hspi, rxArgs); + } + else { + printf("HAL_SPI_RxCpltCallback: No user callback specified\n"); + } +} + +/** + * @brief SPI error callbacks. + * @param hspi: SPI handle + * @note This example shows a simple way to report transfer error, and you can + * add your own implementation. + * @retval None + */ +extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { + if(errorCb != nullptr) { + errorCb(hspi, rxArgs); + } + else { + printf("HAL_SPI_ErrorCallback: No user callback specified\n"); + } +} + diff --git a/stm32h7/spi/spiCore.h b/stm32h7/spi/spiCore.h index fb947be..3d3039a 100644 --- a/stm32h7/spi/spiCore.h +++ b/stm32h7/spi/spiCore.h @@ -9,6 +9,9 @@ extern "C" { #endif using msp_func_t = void (*) (void* args); +using spi_transfer_cb_t = void (*) (SPI_HandleTypeDef *hspi, void* userArgs); + +namespace spi { /** * Assign MSP init functions. Important for SPI configuration @@ -17,7 +20,7 @@ using msp_func_t = void (*) (void* args); * @param deinit_func * @param deinit_args */ -void set_spi_msp_functions(msp_func_t init_func, void* init_args, msp_func_t deinit_func, +void setSpiMspFunctions(msp_func_t init_func, void* init_args, msp_func_t deinit_func, void* deinit_args); /** @@ -25,23 +28,30 @@ void set_spi_msp_functions(msp_func_t init_func, void* init_args, msp_func_t dei * @param txHandle * @param rxHandle */ -void set_dma_handles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle); +void setDmaHandles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle); +void getDmaHandles(DMA_HandleTypeDef** txHandle, DMA_HandleTypeDef** rxHandle); -void get_dma_handles(DMA_HandleTypeDef** txHandle, DMA_HandleTypeDef** rxHandle); -void get_msp_init_function(msp_func_t* init_func, void **args); -void get_msp_deinit_function(msp_func_t* deinit_func, void **args); +void getMspInitFunction(msp_func_t* init_func, void **args); +void getMspDeinitFunction(msp_func_t* deinit_func, void **args); /** * Assign SPI handle. Needs to be done before using the SPI * @param spiHandle */ -void assign_spi_handle(SPI_HandleTypeDef *spiHandle); +void setSpiHandle(SPI_HandleTypeDef *spiHandle); + +void assignTransferRxTxCompleteCallback(spi_transfer_cb_t callback, void* userArgs); +void assignTransferRxCompleteCallback(spi_transfer_cb_t callback, void* userArgs); +void assignTransferTxCompleteCallback(spi_transfer_cb_t callback, void* userArgs); +void assignTransferErrorCallback(spi_transfer_cb_t callback, void* userArgs); /** * Get the assigned SPI handle. * @return */ -SPI_HandleTypeDef* get_spi_handle(); +SPI_HandleTypeDef* getSpiHandle(); + +} #ifdef __cplusplus } diff --git a/stm32h7/spi/spiInterrupts.cpp b/stm32h7/spi/spiInterrupts.cpp index 51a58eb..fe5700b 100644 --- a/stm32h7/spi/spiInterrupts.cpp +++ b/stm32h7/spi/spiInterrupts.cpp @@ -6,21 +6,19 @@ #include +user_handler_t spi1UserHandler = nullptr; +user_args_t spi1UserArgs = nullptr; -void (*spi1_user_handler) (void* args) = nullptr; -void * spi1_user_args = nullptr; - -void (*spi2_user_handler) (void* args) = nullptr; -void * spi2_user_args = nullptr; - +user_handler_t spi2UserHandler = nullptr; +user_args_t spi2UserArgs = nullptr; /** * @brief This function handles DMA Rx interrupt request. * @param None * @retval None */ -void dma_rx_irq_handler(void* dma_handle) { - HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dma_handle); +void spi::dmaRxIrqHandler(void* dmaHandle) { + HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dmaHandle); } /** @@ -28,8 +26,8 @@ void dma_rx_irq_handler(void* dma_handle) { * @param None * @retval None */ -void dma_tx_irq_handler(void* dma_handle) { - HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dma_handle); +void spi::dmaTxIrqHandler(void* dmaHandle) { + HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dmaHandle); } /** @@ -37,20 +35,20 @@ void dma_tx_irq_handler(void* dma_handle) { * @param None * @retval None */ -void spi1_irq_handler(void* spi_handle) +void spi::spi1IrqHandler(void* spiHandle) { - HAL_SPI_IRQHandler((SPI_HandleTypeDef *) spi_handle); + HAL_SPI_IRQHandler((SPI_HandleTypeDef *) spiHandle); } -void assign_spi_user_handler(spi::SpiBus spi_idx, user_handler_t user_handler, - user_args_t user_args) { - if(spi_idx == spi::SpiBus::SPI_1) { - spi1_user_handler = user_handler; - spi1_user_args = user_args; +void spi::assignSpiUserHandler(spi::SpiBus spiIdx, user_handler_t userHandler, + user_args_t userArgs) { + if(spiIdx == spi::SpiBus::SPI_1) { + spi1UserHandler = userHandler; + spi1UserArgs = userArgs; } else { - spi2_user_handler = user_handler; - spi2_user_args = user_args; + spi2UserHandler = userHandler; + spi2UserArgs = userArgs; } } @@ -58,16 +56,16 @@ void assign_spi_user_handler(spi::SpiBus spi_idx, user_handler_t user_handler, defined in the startup_stm32h743xx.s files! */ extern "C" void SPI1_IRQHandler() { - if(spi1_user_handler != NULL) { - spi1_user_handler(spi1_user_args); + if(spi1UserHandler != NULL) { + spi1UserHandler(spi1UserArgs); return; } Default_Handler(); } extern "C" void SPI2_IRQHandler() { - if(spi2_user_handler != NULL) { - spi2_user_handler(spi2_user_args); + if(spi2UserHandler != nullptr) { + spi2UserHandler(spi2UserArgs); return; } Default_Handler(); diff --git a/stm32h7/spi/spiInterrupts.h b/stm32h7/spi/spiInterrupts.h index 49be029..abfc68e 100644 --- a/stm32h7/spi/spiInterrupts.h +++ b/stm32h7/spi/spiInterrupts.h @@ -8,13 +8,15 @@ extern "C" { #endif +namespace spi { + /** * Assign a user interrupt handler for SPI bus 1, allowing to pass an arbitrary argument as well. * Generally, this argument will be the related SPI handle. * @param user_handler * @param user_args */ -void assign_spi_user_handler(spi::SpiBus spiBus, user_handler_t user_handler, +void assignSpiUserHandler(spi::SpiBus spiBus, user_handler_t user_handler, user_args_t user_args); /** @@ -22,9 +24,11 @@ void assign_spi_user_handler(spi::SpiBus spiBus, user_handler_t user_handler, * instead with assign_dma_user_handler and assign_spi_user_handler functions. * @param dma_handle */ -void dma_rx_irq_handler(void* dma_handle); -void dma_tx_irq_handler(void* dma_handle); -void spi1_irq_handler(void* spi_handle); +void dmaRxIrqHandler(void* dma_handle); +void dmaTxIrqHandler(void* dma_handle); +void spi1IrqHandler(void* spi_handle); + +} #ifdef __cplusplus } From 5ff344eee265d23c9a5d01362cd7eee428f428a2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 5 Jun 2021 14:31:49 +0200 Subject: [PATCH 21/35] spi com if finished --- linux/spi/SpiComIF.cpp | 2 +- linux/spi/SpiComIF.h | 1 + stm32h7/devicetest/GyroL3GD20H.h | 1 - stm32h7/spi/SpiComIF.cpp | 172 ++++++++++++++++++++++++++++--- stm32h7/spi/SpiComIF.h | 36 ++++++- stm32h7/spi/spiDefinitions.h | 3 +- 6 files changed, 199 insertions(+), 16 deletions(-) diff --git a/linux/spi/SpiComIF.cpp b/linux/spi/SpiComIF.cpp index c39f397..9dc4429 100644 --- a/linux/spi/SpiComIF.cpp +++ b/linux/spi/SpiComIF.cpp @@ -47,7 +47,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { auto iter = spiDeviceMap.find(spiAddress); if(iter == spiDeviceMap.end()) { size_t bufferSize = spiCookie->getMaxBufferSize(); - SpiInstance spiInstance = {std::vector(bufferSize)}; + SpiInstance spiInstance(bufferSize); auto statusPair = spiDeviceMap.emplace(spiAddress, spiInstance); if (not statusPair.second) { #if FSFW_VERBOSE_LEVEL >= 1 diff --git a/linux/spi/SpiComIF.h b/linux/spi/SpiComIF.h index d1a583b..60b250e 100644 --- a/linux/spi/SpiComIF.h +++ b/linux/spi/SpiComIF.h @@ -67,6 +67,7 @@ public: private: struct SpiInstance { + SpiInstance(size_t maxRecvSize): replyBuffer(std::vector(maxRecvSize)) {} std::vector replyBuffer; }; diff --git a/stm32h7/devicetest/GyroL3GD20H.h b/stm32h7/devicetest/GyroL3GD20H.h index b96f203..4ebed1e 100644 --- a/stm32h7/devicetest/GyroL3GD20H.h +++ b/stm32h7/devicetest/GyroL3GD20H.h @@ -50,7 +50,6 @@ private: ReturnValue_t handlePollingSensorRead(); ReturnValue_t handleInterruptSensorRead(); - friend void spiTransferCompleteCallback(SPI_HandleTypeDef *hspi, void* args); static void spiTransferCompleteCallback(SPI_HandleTypeDef *hspi, void* args); static void spiTransferErrorCallback(SPI_HandleTypeDef *hspi, void* args); diff --git a/stm32h7/spi/SpiComIF.cpp b/stm32h7/spi/SpiComIF.cpp index bec47a6..5b1b7af 100644 --- a/stm32h7/spi/SpiComIF.cpp +++ b/stm32h7/spi/SpiComIF.cpp @@ -2,6 +2,7 @@ #include "SpiCookie.h" #include "fsfw/tasks/SemaphoreFactory.h" +#include "fsfw/osal/FreeRTOS/TaskManagement.h" #include "fsfw_hal/stm32h7/spi/spiCore.h" #include "stm32h7xx_hal_gpio.h" @@ -30,6 +31,11 @@ SpiComIF::SpiComIF(object_id_t objectId, SPI_TypeDef* spiInstance, SPI_HandleTyp // Recommended setting to avoid glitches spiHandle->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; spiHandle->Init.Mode = SPI_MODE_MASTER; + + spi::assignTransferRxTxCompleteCallback(&spiTransferCompleteCallback, this); + spi::assignTransferRxCompleteCallback(&spiTransferRxCompleteCallback, this); + spi::assignTransferTxCompleteCallback(&spiTransferTxCompleteCallback, this); + spi::assignTransferErrorCallback(&spiTransferErrorCallback, this); } void SpiComIF::configureCacheMaintenanceOnTxBuffer(bool enable) { @@ -69,7 +75,8 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { } if(transferMode == spi::TransferModes::DMA or transferMode == spi::TransferModes::INTERRUPT) { - spiSemaphore = SemaphoreFactory::instance()->createBinarySemaphore(); + spiSemaphore = dynamic_cast( + SemaphoreFactory::instance()->createBinarySemaphore()); } else { spiMutex = MutexFactory::instance()->createMutex(); @@ -80,8 +87,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { auto iter = spiDeviceMap.find(spiAddress); if(iter == spiDeviceMap.end()) { size_t bufferSize = spiCookie->getMaxRecvSize(); - SpiInstance spiInstance = {std::vector(bufferSize)}; - auto statusPair = spiDeviceMap.emplace(spiAddress, spiInstance); + auto statusPair = spiDeviceMap.emplace(spiAddress, SpiInstance(bufferSize)); if (not statusPair.second) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -119,6 +125,8 @@ ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, s if(iter == spiDeviceMap.end()) { return HasReturnvaluesIF::RETURN_FAILED; } + iter->second.currentTransferLen = sendLen; + switch(transferMode) { case(spi::TransferModes::POLLING): { return handlePollingSendOperation(iter->second.replyBuffer.data(), spiCookie, sendData, @@ -144,12 +152,22 @@ ReturnValue_t SpiComIF::requestReceiveMessage(CookieIF *cookie, size_t requestLe return HasReturnvaluesIF::RETURN_OK; } -void SpiComIF::setDefaultPollingTimeout(dur_millis_t timeout) { - this->defaultPollingTimeout = timeout; +ReturnValue_t SpiComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) { + SpiCookie* spiCookie = dynamic_cast(cookie); + if(spiCookie == nullptr) { + return NULLPOINTER; + } + auto iter = spiDeviceMap.find(spiCookie->getDeviceAddress()); + if(iter == spiDeviceMap.end()) { + return HasReturnvaluesIF::RETURN_FAILED; + } + *buffer = iter->second.replyBuffer.data(); + *size = iter->second.currentTransferLen; + return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t SpiComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) { - return HasReturnvaluesIF::RETURN_OK; +void SpiComIF::setDefaultPollingTimeout(dur_millis_t timeout) { + this->defaultPollingTimeout = timeout; } ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SpiCookie *spiCookie, @@ -197,14 +215,144 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SpiCookie * ReturnValue_t SpiComIF::handleInterruptSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, const uint8_t * sendData, size_t sendLen) { - auto gpioPort = spiCookie->getChipSelectGpioPort(); - auto gpioPin = spiCookie->getChipSelectGpioPin(); - spiMutex->lockMutex(timeoutType, timeoutMs); - HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_RESET); - return HasReturnvaluesIF::RETURN_OK; + return handleIrqSendOperation(recvPtr, spiCookie, sendData, sendLen); } ReturnValue_t SpiComIF::handleDmaSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, const uint8_t * sendData, size_t sendLen) { + return handleIrqSendOperation(recvPtr, spiCookie, sendData, sendLen); +} + +ReturnValue_t SpiComIF::handleIrqSendOperation(uint8_t *recvPtr, SpiCookie *spiCookie, + const uint8_t *sendData, size_t sendLen) { + ReturnValue_t result = genericIrqSendSetup(recvPtr, spiCookie, sendData, sendLen); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + // yet another HAL driver which is not const-correct.. + HAL_StatusTypeDef status = HAL_OK; + if(transferMode == spi::TransferModes::DMA) { + status = HAL_SPI_TransmitReceive_DMA(spiHandle, const_cast(sendData), + currentRecvPtr, sendLen); + } + else { + status = HAL_SPI_TransmitReceive_IT(spiHandle, const_cast(sendData), + currentRecvPtr, sendLen); + } + switch(status) { + case(HAL_OK): { + break; + } + default: { + return halErrorHandler(status); + } + } + return result; +} + +ReturnValue_t SpiComIF::halErrorHandler(HAL_StatusTypeDef status) { + char modeString[10]; + if(transferMode == spi::TransferModes::DMA) { + std::snprintf(modeString, sizeof(modeString), "Dma"); + } + else { + std::snprintf(modeString, sizeof(modeString), "Interrupt"); + } + sif::printWarning("SpiComIF::handle%sSendOperation: HAL error %d occured\n", modeString, + status); + switch(status) { + case(HAL_BUSY): { + return spi::HAL_BUSY_RETVAL; + } + case(HAL_ERROR): { + return spi::HAL_ERROR_RETVAL; + } + case(HAL_TIMEOUT): { + return spi::HAL_TIMEOUT_RETVAL; + } + default: { + return HasReturnvaluesIF::RETURN_FAILED; + } + } +} + + +ReturnValue_t SpiComIF::genericIrqSendSetup(uint8_t *recvPtr, SpiCookie *spiCookie, + const uint8_t *sendData, size_t sendLen) { + // These are required by the callback + currentGpioPort = spiCookie->getChipSelectGpioPort(); + currentGpioPin = spiCookie->getChipSelectGpioPin(); + currentRecvPtr = recvPtr; + currentRecvBuffSize = sendLen; + + // Take the semaphore which will be released by a callback when the transfer is complete + ReturnValue_t result = spiSemaphore->acquire(SemaphoreIF::TimeoutType::WAITING, timeoutMs); + if(result != HasReturnvaluesIF::RETURN_OK) { + // Configuration error + sif::printWarning("SpiComIF::handleInterruptSendOperation: Semaphore" + "could not be acquired after %d ms\n", timeoutMs); + return result; + } + HAL_GPIO_WritePin(currentGpioPort, currentGpioPin, GPIO_PIN_RESET); return HasReturnvaluesIF::RETURN_OK; } + +void SpiComIF::spiTransferTxCompleteCallback(SPI_HandleTypeDef *hspi, void *args) { + SpiComIF* spiComIF = reinterpret_cast(args); + if(spiComIF == nullptr) { + return; + } + genericIrqHandler(spiComIF, TransferStates::FAILURE); +} + +void SpiComIF::spiTransferRxCompleteCallback(SPI_HandleTypeDef *hspi, void *args) { + SpiComIF* spiComIF = reinterpret_cast(args); + if(spiComIF == nullptr) { + return; + } + genericIrqHandler(spiComIF, TransferStates::FAILURE); +} + +void SpiComIF::spiTransferCompleteCallback(SPI_HandleTypeDef *hspi, void *args) { + SpiComIF* spiComIF = reinterpret_cast(args); + if(spiComIF == nullptr) { + return; + } + genericIrqHandler(spiComIF, TransferStates::FAILURE); +} + +void SpiComIF::spiTransferErrorCallback(SPI_HandleTypeDef *hspi, void *args) { + SpiComIF* spiComIF = reinterpret_cast(args); + if(spiComIF == nullptr) { + return; + } + genericIrqHandler(spiComIF, TransferStates::FAILURE); +} + +void SpiComIF::genericIrqHandler(SpiComIF *spiComIF, TransferStates targetState) { + spiComIF->transferState = TransferStates::SUCCESS; + + // Pull CS pin high again + HAL_GPIO_WritePin(spiComIF->currentGpioPort, spiComIF->currentGpioPin, GPIO_PIN_SET); + + // Release the task semaphore + BaseType_t taskWoken = pdFALSE; + ReturnValue_t result = BinarySemaphore::releaseFromISR(spiComIF->spiSemaphore->getSemaphore(), + &taskWoken); + if(result != HasReturnvaluesIF::RETURN_FAILED) { + // Configuration error + printf("SpiComIF::genericIrqHandler: Failure releasing Semaphore!\n"); + } + + // Perform cache maintenance operation for DMA transfers + if(spiComIF->transferMode == spi::TransferModes::DMA) { + // Invalidate cache prior to access by CPU + SCB_InvalidateDCache_by_Addr ((uint32_t *) spiComIF->currentRecvPtr, + spiComIF->currentRecvBuffSize); + } + /* Request a context switch if the SPI ComIF task was woken up and has a higher priority + than the currently running task */ + if(taskWoken == pdTRUE) { + TaskManagement::requestContextSwitch(CallContext::ISR); + } +} diff --git a/stm32h7/spi/SpiComIF.h b/stm32h7/spi/SpiComIF.h index d166f49..909e742 100644 --- a/stm32h7/spi/SpiComIF.h +++ b/stm32h7/spi/SpiComIF.h @@ -2,10 +2,12 @@ #define FSFW_HAL_STM32H7_SPI_SPICOMIF_H_ + #include "fsfw/tasks/SemaphoreIF.h" #include "fsfw/devicehandlers/DeviceCommunicationIF.h" #include "fsfw/objectmanager/SystemObject.h" +#include "fsfw/osal/FreeRTOS/BinarySemaphore.h" #include "fsfw_hal/stm32h7/spi/spiDefinitions.h" #include "stm32h7xx_hal_spi.h" #include "stm32h743xx.h" @@ -15,6 +17,13 @@ class SpiCookie; +enum class TransferStates { + IDLE, + WAIT, + SUCCESS, + FAILURE +}; + class SpiComIF: public SystemObject, public DeviceCommunicationIF { @@ -60,10 +69,15 @@ protected: virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) override; + private: + struct SpiInstance { + SpiInstance(size_t maxRecvSize): replyBuffer(std::vector(maxRecvSize)) {} std::vector replyBuffer; + size_t currentTransferLen = 0; }; + uint32_t defaultPollingTimeout = 50; spi::TransferModes transferMode; @@ -72,13 +86,19 @@ private: MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; dur_millis_t timeoutMs = 20; - SemaphoreIF* spiSemaphore = nullptr; + BinarySemaphore* spiSemaphore = nullptr; MutexIF* spiMutex = nullptr; bool cacheMaintenanceOnTxBuffer = true; using SpiDeviceMap = std::map; using SpiDeviceMapIter = SpiDeviceMap::iterator; + GPIO_TypeDef* currentGpioPort = nullptr; + uint16_t currentGpioPin = 0; + uint8_t* currentRecvPtr = nullptr; + size_t currentRecvBuffSize = 0; + volatile TransferStates transferState = TransferStates::IDLE; + SpiDeviceMap spiDeviceMap; ReturnValue_t handlePollingSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, @@ -87,6 +107,20 @@ private: const uint8_t * sendData, size_t sendLen); ReturnValue_t handleDmaSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, const uint8_t * sendData, size_t sendLen); + ReturnValue_t handleIrqSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, + const uint8_t * sendData, size_t sendLen); + ReturnValue_t genericIrqSendSetup(uint8_t* recvPtr, SpiCookie* spiCookie, + const uint8_t * sendData, size_t sendLen); + ReturnValue_t halErrorHandler(HAL_StatusTypeDef status); + + static void spiTransferTxCompleteCallback(SPI_HandleTypeDef *hspi, void* args); + static void spiTransferRxCompleteCallback(SPI_HandleTypeDef *hspi, void* args); + static void spiTransferCompleteCallback(SPI_HandleTypeDef *hspi, void* args); + static void spiTransferErrorCallback(SPI_HandleTypeDef *hspi, void* args); + + static void genericIrqHandler(SpiComIF* comIF, TransferStates targetState); + + }; diff --git a/stm32h7/spi/spiDefinitions.h b/stm32h7/spi/spiDefinitions.h index db16df4..0ea83ac 100644 --- a/stm32h7/spi/spiDefinitions.h +++ b/stm32h7/spi/spiDefinitions.h @@ -13,7 +13,8 @@ namespace spi { static constexpr uint8_t HAL_SPI_ID = CLASS_ID::HAL_SPI; static constexpr ReturnValue_t HAL_TIMEOUT_RETVAL = HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 0); -static constexpr ReturnValue_t HAL_ERROR_RETVAL = HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 1); +static constexpr ReturnValue_t HAL_BUSY_RETVAL = HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 1); +static constexpr ReturnValue_t HAL_ERROR_RETVAL = HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 2); enum SpiBus { SPI_1, From a35fdbc5dc7fa4f22cc0b949b001d85df9729dfa Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 5 Jun 2021 14:42:20 +0200 Subject: [PATCH 22/35] small fixes and refactoring --- common/gpio/GpioCookie.cpp | 3 ++- common/gpio/GpioCookie.h | 7 ++++--- common/gpio/GpioIF.h | 6 +++--- common/gpio/gpioDefinitions.h | 24 ++++++++++++++---------- linux/gpio/LinuxLibgpioIF.cpp | 12 ++++++------ linux/gpio/LinuxLibgpioIF.h | 4 ++-- linux/uart/UartComIF.cpp | 8 ++++---- 7 files changed, 35 insertions(+), 29 deletions(-) diff --git a/common/gpio/GpioCookie.cpp b/common/gpio/GpioCookie.cpp index a32519f..da765ce 100644 --- a/common/gpio/GpioCookie.cpp +++ b/common/gpio/GpioCookie.cpp @@ -1,5 +1,6 @@ #include "GpioCookie.h" -#include +#include "fsfw/serviceinterface/ServiceInterface.h" + GpioCookie::GpioCookie() { } diff --git a/common/gpio/GpioCookie.h b/common/gpio/GpioCookie.h index 4a865a3..0473fe0 100644 --- a/common/gpio/GpioCookie.h +++ b/common/gpio/GpioCookie.h @@ -1,8 +1,9 @@ -#ifndef LINUX_GPIO_GPIOCOOKIE_H_ -#define LINUX_GPIO_GPIOCOOKIE_H_ +#ifndef COMMON_GPIO_GPIOCOOKIE_H_ +#define COMMON_GPIO_GPIOCOOKIE_H_ #include "GpioIF.h" #include "gpioDefinitions.h" + #include #include @@ -37,4 +38,4 @@ private: GpioMap gpioMap; }; -#endif /* LINUX_GPIO_GPIOCOOKIE_H_ */ +#endif /* COMMON_GPIO_GPIOCOOKIE_H_ */ diff --git a/common/gpio/GpioIF.h b/common/gpio/GpioIF.h index 75feb3c..af73f94 100644 --- a/common/gpio/GpioIF.h +++ b/common/gpio/GpioIF.h @@ -1,5 +1,5 @@ -#ifndef LINUX_GPIO_GPIOIF_H_ -#define LINUX_GPIO_GPIOIF_H_ +#ifndef COMMON_GPIO_GPIOIF_H_ +#define COMMON_GPIO_GPIOIF_H_ #include "gpioDefinitions.h" #include @@ -51,4 +51,4 @@ public: virtual ReturnValue_t readGpio(gpioId_t gpioId, int* gpioState) = 0; }; -#endif /* LINUX_GPIO_GPIOIF_H_ */ +#endif /* COMMON_GPIO_GPIOIF_H_ */ diff --git a/common/gpio/gpioDefinitions.h b/common/gpio/gpioDefinitions.h index 66c0b00..b56a476 100644 --- a/common/gpio/gpioDefinitions.h +++ b/common/gpio/gpioDefinitions.h @@ -1,8 +1,9 @@ -#ifndef LINUX_GPIO_GPIODEFINITIONS_H_ -#define LINUX_GPIO_GPIODEFINITIONS_H_ +#ifndef COMMON_GPIO_GPIODEFINITIONS_H_ +#define COMMON_GPIO_GPIODEFINITIONS_H_ #include #include +#include using gpioId_t = uint16_t; @@ -25,11 +26,14 @@ enum GpioOperation { enum GpioTypes { NONE, - GPIOD_REGULAR, + GPIO_REGULAR, CALLBACK }; static constexpr gpioId_t NO_GPIO = -1; + +using gpio_cb_t = void (*) (gpioId_t gpioId, gpio::GpioOperation gpioOp, int value, void* args); + } /** @@ -66,12 +70,12 @@ public: class GpiodRegular: public GpioBase { public: - GpiodRegular(): GpioBase(gpio::GpioTypes::GPIOD_REGULAR, std::string(), + GpiodRegular(): GpioBase(gpio::GpioTypes::GPIO_REGULAR, std::string(), gpio::Direction::IN, 0) {}; GpiodRegular(std::string chipname_, int lineNum_, std::string consumer_, gpio::Direction direction_, int initValue_): - GpioBase(gpio::GpioTypes::GPIOD_REGULAR, consumer_, direction_, initValue_), + GpioBase(gpio::GpioTypes::GPIO_REGULAR, consumer_, direction_, initValue_), chipname(chipname_), lineNum(lineNum_) {} std::string chipname; int lineNum = 0; @@ -81,18 +85,18 @@ public: class GpioCallback: public GpioBase { public: GpioCallback(std::string consumer, gpio::Direction direction_, int initValue_, - void (* callback) (gpioId_t gpioId, gpio::GpioOperation gpioOp, int value, void* args), - void* callbackArgs): + gpio::gpio_cb_t callback, void* callbackArgs): GpioBase(gpio::GpioTypes::CALLBACK, consumer, direction_, initValue_), callback(callback), callbackArgs(callbackArgs) {} - void (* callback) (gpioId_t gpioId, gpio::GpioOperation gpioOp, - int value, void* args) = nullptr; + gpio::gpio_cb_t callback = nullptr; void* callbackArgs = nullptr; }; -using GpioMap = std::unordered_map; +using GpioMap = std::map; +using GpioUnorderedMap = std::unordered_map; using GpioMapIter = GpioMap::iterator; +using GpioUnorderedMapIter = GpioUnorderedMap::iterator; #endif /* LINUX_GPIO_GPIODEFINITIONS_H_ */ diff --git a/linux/gpio/LinuxLibgpioIF.cpp b/linux/gpio/LinuxLibgpioIF.cpp index 3001b8a..2a645fc 100644 --- a/linux/gpio/LinuxLibgpioIF.cpp +++ b/linux/gpio/LinuxLibgpioIF.cpp @@ -49,7 +49,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) { case(gpio::GpioTypes::NONE): { return GPIO_INVALID_INSTANCE; } - case(gpio::GpioTypes::GPIOD_REGULAR): { + case(gpio::GpioTypes::GPIO_REGULAR): { GpiodRegular* regularGpio = dynamic_cast(gpioConfig.second); if(regularGpio == nullptr) { return GPIO_INVALID_INSTANCE; @@ -145,7 +145,7 @@ ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) { return UNKNOWN_GPIO_ID; } - if(gpioMapIter->second->gpioType == gpio::GpioTypes::GPIOD_REGULAR) { + if(gpioMapIter->second->gpioType == gpio::GpioTypes::GPIO_REGULAR) { return driveGpio(gpioId, dynamic_cast(gpioMapIter->second), 1); } else { @@ -166,7 +166,7 @@ ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) { return UNKNOWN_GPIO_ID; } - if(gpioMapIter->second->gpioType == gpio::GpioTypes::GPIOD_REGULAR) { + if(gpioMapIter->second->gpioType == gpio::GpioTypes::GPIO_REGULAR) { return driveGpio(gpioId, dynamic_cast(gpioMapIter->second), 0); } else { @@ -203,7 +203,7 @@ ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, int* gpioState) { return UNKNOWN_GPIO_ID; } - if(gpioMapIter->second->gpioType == gpio::GpioTypes::GPIOD_REGULAR) { + if(gpioMapIter->second->gpioType == gpio::GpioTypes::GPIO_REGULAR) { GpiodRegular* regularGpio = dynamic_cast(gpioMapIter->second); if(regularGpio == nullptr) { return GPIO_TYPE_FAILURE; @@ -223,7 +223,7 @@ ReturnValue_t LinuxLibgpioIF::checkForConflicts(GpioMap& mapToAdd){ ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; for(auto& gpioConfig: mapToAdd) { switch(gpioConfig.second->gpioType) { - case(gpio::GpioTypes::GPIOD_REGULAR): { + case(gpio::GpioTypes::GPIO_REGULAR): { auto regularGpio = dynamic_cast(gpioConfig.second); if(regularGpio == nullptr) { return GPIO_TYPE_FAILURE; @@ -261,7 +261,7 @@ ReturnValue_t LinuxLibgpioIF::checkForConflictsRegularGpio(gpioId_t gpioIdToChec /* Cross check with private map */ gpioMapIter = gpioMap.find(gpioIdToCheck); if(gpioMapIter != gpioMap.end()) { - if(gpioMapIter->second->gpioType != gpio::GpioTypes::GPIOD_REGULAR) { + if(gpioMapIter->second->gpioType != gpio::GpioTypes::GPIO_REGULAR) { sif::warning << "LinuxLibgpioIF::checkForConflicts: ID already exists for different " "GPIO type" << gpioIdToCheck << ". Removing duplicate." << std::endl; mapToAdd.erase(gpioIdToCheck); diff --git a/linux/gpio/LinuxLibgpioIF.h b/linux/gpio/LinuxLibgpioIF.h index 7238056..093e95a 100644 --- a/linux/gpio/LinuxLibgpioIF.h +++ b/linux/gpio/LinuxLibgpioIF.h @@ -38,8 +38,8 @@ public: private: /* Holds the information and configuration of all used GPIOs */ - GpioMap gpioMap; - GpioMapIter gpioMapIter; + GpioUnorderedMap gpioMap; + GpioUnorderedMapIter gpioMapIter; /** * @brief This functions drives line of a GPIO specified by the GPIO ID. diff --git a/linux/uart/UartComIF.cpp b/linux/uart/UartComIF.cpp index 126e51d..3f389df 100644 --- a/linux/uart/UartComIF.cpp +++ b/linux/uart/UartComIF.cpp @@ -38,15 +38,15 @@ ReturnValue_t UartComIF::initializeInterface(CookieIF * cookie) { } size_t maxReplyLen = uartCookie->getMaxReplyLen(); UartElements_t uartElements = {fileDescriptor, std::vector(maxReplyLen), 0}; - std::pair status = uartDeviceMap.emplace(deviceFile, uartElements); + auto status = uartDeviceMap.emplace(deviceFile, uartElements); if (status.second == false) { - sif::debug << "UartComIF::initializeInterface: Failed to insert device " << deviceFile - << "to Uart device map" << std::endl; + sif::debug << "UartComIF::initializeInterface: Failed to insert device " << deviceFile + << "to UART device map" << std::endl; return RETURN_FAILED; } } else { - sif::debug << "UartComIF::initializeInterface: Uart device " << deviceFile << "already in " + sif::debug << "UartComIF::initializeInterface: UART device " << deviceFile << " already in " << "use" << std::endl; return RETURN_FAILED; } From 93db545a1a573d39d17a4c14db5a21255f3f89c4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 5 Jun 2021 14:50:02 +0200 Subject: [PATCH 23/35] added cache maintenance op --- stm32h7/spi/SpiComIF.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stm32h7/spi/SpiComIF.cpp b/stm32h7/spi/SpiComIF.cpp index 5b1b7af..26fb7e7 100644 --- a/stm32h7/spi/SpiComIF.cpp +++ b/stm32h7/spi/SpiComIF.cpp @@ -232,6 +232,12 @@ ReturnValue_t SpiComIF::handleIrqSendOperation(uint8_t *recvPtr, SpiCookie *spiC // yet another HAL driver which is not const-correct.. HAL_StatusTypeDef status = HAL_OK; if(transferMode == spi::TransferModes::DMA) { + if(cacheMaintenanceOnTxBuffer) { + /* Clean D-cache. Make sure the address is 32-byte aligned and add 32-bytes to length, + in case it overlaps cacheline */ + SCB_CleanDCache_by_Addr((uint32_t*)(((uint32_t) sendData ) & ~(uint32_t)0x1F), + sendLen + 32); + } status = HAL_SPI_TransmitReceive_DMA(spiHandle, const_cast(sendData), currentRecvPtr, sendLen); } From d194b759c4781f6384786010c460382de97830c2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 5 Jun 2021 14:51:31 +0200 Subject: [PATCH 24/35] added uart and i2c stub folders --- stm32h7/i2c/CMakeLists.txt | 2 ++ stm32h7/uart/CMakeLists.txt | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 stm32h7/i2c/CMakeLists.txt create mode 100644 stm32h7/uart/CMakeLists.txt diff --git a/stm32h7/i2c/CMakeLists.txt b/stm32h7/i2c/CMakeLists.txt new file mode 100644 index 0000000..8e57e01 --- /dev/null +++ b/stm32h7/i2c/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(${TARGET_NAME} PRIVATE +) diff --git a/stm32h7/uart/CMakeLists.txt b/stm32h7/uart/CMakeLists.txt new file mode 100644 index 0000000..8e57e01 --- /dev/null +++ b/stm32h7/uart/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(${TARGET_NAME} PRIVATE +) From 04166f87d82f3729b4462437677bae9105c1c88e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 9 Jun 2021 23:20:42 +0200 Subject: [PATCH 25/35] several important changes for stm32 --- CMakeLists.txt | 24 +++ devicehandlers/CMakeLists.txt | 3 + devicehandlers/GyroL3GD20Handler.cpp | 260 +++++++++++++++++++++++++++ devicehandlers/GyroL3GD20Handler.h | 80 +++++++++ linux/i2c/CMakeLists.txt | 2 +- linux/spi/CMakeLists.txt | 2 +- stm32h7/CMakeLists.txt | 2 +- stm32h7/devicetest/CMakeLists.txt | 2 +- stm32h7/i2c/CMakeLists.txt | 2 +- stm32h7/spi/CMakeLists.txt | 2 +- stm32h7/uart/CMakeLists.txt | 2 +- 11 files changed, 374 insertions(+), 7 deletions(-) create mode 100644 devicehandlers/CMakeLists.txt create mode 100644 devicehandlers/GyroL3GD20Handler.cpp create mode 100644 devicehandlers/GyroL3GD20Handler.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 72dc17b..e3b75fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,8 +34,32 @@ target_link_libraries(${LIB_FSFW_HAL_NAME} PRIVATE ${LIB_FSFW_NAME} ) +foreach(INCLUDE_PATH ${FSFW_HAL_ADDITIONAL_INC_PATHS}) + if(IS_ABSOLUTE ${INCLUDE_PATH}) + set(CURR_ABS_INC_PATH "${INCLUDE_PATH}") + else() + get_filename_component(CURR_ABS_INC_PATH + ${INCLUDE_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR}) + endif() + + if(CMAKE_VERBOSE) + message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}") + endif() + + list(APPEND FSFW_HAL_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH}) +endforeach() + target_include_directories(${LIB_FSFW_HAL_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + ${FSFW_HAL_ADD_INC_PATHS_ABS} +) + +target_compile_definitions(${LIB_FSFW_HAL_NAME} PRIVATE + ${FSFW_HAL_DEFINES} +) + +target_link_libraries(${LIB_FSFW_HAL_NAME} PRIVATE + ${FSFW_HAL_LINK_LIBS} ) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") diff --git a/devicehandlers/CMakeLists.txt b/devicehandlers/CMakeLists.txt new file mode 100644 index 0000000..1cde7e4 --- /dev/null +++ b/devicehandlers/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(${LIB_FSFW_HAL_NAME} PRIVATE + GyroL3GD20Handler.cpp +) diff --git a/devicehandlers/GyroL3GD20Handler.cpp b/devicehandlers/GyroL3GD20Handler.cpp new file mode 100644 index 0000000..5820d93 --- /dev/null +++ b/devicehandlers/GyroL3GD20Handler.cpp @@ -0,0 +1,260 @@ +#include "GyroL3GD20Handler.h" +#include + +#include + +GyroHandlerL3GD20H::GyroHandlerL3GD20H(object_id_t objectId, object_id_t deviceCommunication, + CookieIF *comCookie): + DeviceHandlerBase(objectId, deviceCommunication, comCookie), + dataset(this) { +#if L3GD20_GYRO_DEBUG == 1 + debugDivider = new PeriodicOperationDivider(5); +#endif +} + +GyroHandlerL3GD20H::~GyroHandlerL3GD20H() {} + +void GyroHandlerL3GD20H::doStartUp() { + if(internalState == InternalState::NONE) { + internalState = InternalState::CONFIGURE; + } + + if(internalState == InternalState::CONFIGURE) { + if(commandExecuted) { + internalState = InternalState::CHECK_REGS; + commandExecuted = false; + } + } + + if(internalState == InternalState::CHECK_REGS) { + if(commandExecuted) { + internalState = InternalState::NORMAL; +#if OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP == 1 + setMode(MODE_NORMAL); +#else + setMode(_MODE_TO_ON); +#endif + commandExecuted = false; + } + } +} + +void GyroHandlerL3GD20H::doShutDown() { + setMode(_MODE_POWER_DOWN); +} + +ReturnValue_t GyroHandlerL3GD20H::buildTransitionDeviceCommand(DeviceCommandId_t *id) { + switch(internalState) { + case(InternalState::NONE): + case(InternalState::NORMAL): { + return HasReturnvaluesIF::RETURN_OK; + } + case(InternalState::CONFIGURE): { + *id = L3GD20H::CONFIGURE_CTRL_REGS; + uint8_t command [5]; + command[0] = L3GD20H::CTRL_REG_1_VAL; + command[1] = L3GD20H::CTRL_REG_2_VAL; + command[2] = L3GD20H::CTRL_REG_3_VAL; + command[3] = L3GD20H::CTRL_REG_4_VAL; + command[4] = L3GD20H::CTRL_REG_5_VAL; + return buildCommandFromCommand(*id, command, 5); + } + case(InternalState::CHECK_REGS): { + *id = L3GD20H::READ_REGS; + return buildCommandFromCommand(*id, nullptr, 0); + } + default: + /* Might be a configuration error. */ + sif::debug << "GyroHandler::buildTransitionDeviceCommand: Unknown internal state!" << + std::endl; + return HasReturnvaluesIF::RETURN_OK; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t GyroHandlerL3GD20H::buildNormalDeviceCommand(DeviceCommandId_t *id) { + *id = L3GD20H::READ_REGS; + return buildCommandFromCommand(*id, nullptr, 0); +} + +ReturnValue_t GyroHandlerL3GD20H::buildCommandFromCommand( + DeviceCommandId_t deviceCommand, const uint8_t *commandData, + size_t commandDataLen) { + switch(deviceCommand) { + case(L3GD20H::READ_REGS): { + commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | + L3GD20H::READ_MASK; + + std::memset(commandBuffer + 1, 0, L3GD20H::READ_LEN); + rawPacket = commandBuffer; + rawPacketLen = L3GD20H::READ_LEN + 1; + break; + } + case(L3GD20H::CONFIGURE_CTRL_REGS): { + commandBuffer[0] = L3GD20H::CTRL_REG_1 | L3GD20H::AUTO_INCREMENT_MASK; + if(commandData == nullptr or commandDataLen != 5) { + return DeviceHandlerIF::INVALID_COMMAND_PARAMETER; + } + + ctrlReg1Value = commandData[0]; + ctrlReg2Value = commandData[1]; + ctrlReg3Value = commandData[2]; + ctrlReg4Value = commandData[3]; + ctrlReg5Value = commandData[4]; + + bool fsH = ctrlReg4Value & L3GD20H::SET_FS_1; + bool fsL = ctrlReg4Value & L3GD20H::SET_FS_0; + + if(not fsH and not fsL) { + scaleFactor = static_cast(L3GD20H::RANGE_DPS_00) / INT16_MAX; + } + else if(not fsH and fsL) { + scaleFactor = static_cast(L3GD20H::RANGE_DPS_01) / INT16_MAX; + } + else { + scaleFactor = static_cast(L3GD20H::RANGE_DPS_11) / INT16_MAX; + } + + commandBuffer[1] = ctrlReg1Value; + commandBuffer[2] = ctrlReg2Value; + commandBuffer[3] = ctrlReg3Value; + commandBuffer[4] = ctrlReg4Value; + commandBuffer[5] = ctrlReg5Value; + + rawPacket = commandBuffer; + rawPacketLen = 6; + break; + } + case(L3GD20H::READ_CTRL_REGS): { + commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | + L3GD20H::READ_MASK; + + std::memset(commandBuffer + 1, 0, 5); + rawPacket = commandBuffer; + rawPacketLen = 6; + break; + } + default: + return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t GyroHandlerL3GD20H::scanForReply(const uint8_t *start, size_t len, + DeviceCommandId_t *foundId, size_t *foundLen) { + /* For SPI, the ID will always be the one of the last sent command. */ + *foundId = this->getPendingCommand(); + *foundLen = this->rawPacketLen; + + /* Data with SPI Interface has always this answer */ + if (start[0] == 0b11111111) { + return HasReturnvaluesIF::RETURN_OK; + } + return DeviceHandlerIF::INVALID_DATA; +} + +ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id, + const uint8_t *packet) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + switch(id) { + case(L3GD20H::CONFIGURE_CTRL_REGS): { + commandExecuted = true; + break; + } + case(L3GD20H::READ_CTRL_REGS): { + if(packet[1] == ctrlReg1Value and packet[2] == ctrlReg2Value and + packet[3] == ctrlReg3Value and packet[4] == ctrlReg4Value and + packet[5] == ctrlReg5Value) { + commandExecuted = true; + } + else { + /* Attempt reconfiguration. */ + internalState = InternalState::CONFIGURE; + return DeviceHandlerIF::DEVICE_REPLY_INVALID; + } + break; + } + case(L3GD20H::READ_REGS): { + if(packet[1] != ctrlReg1Value and packet[2] != ctrlReg2Value and + packet[3] != ctrlReg3Value and packet[4] != ctrlReg4Value and + packet[5] != ctrlReg5Value) { + return DeviceHandlerIF::DEVICE_REPLY_INVALID; + } + else { + if(internalState == InternalState::CHECK_REGS) { + commandExecuted = true; + } + } + + statusReg = packet[L3GD20H::STATUS_IDX]; + + float angVelocX = (packet[L3GD20H::OUT_X_H] << 8 | + packet[L3GD20H::OUT_X_L]) * scaleFactor; + float angVelocY = (packet[L3GD20H::OUT_Y_H] << 8 | + packet[L3GD20H::OUT_Y_L]) * scaleFactor; + float angVelocZ = (packet[L3GD20H::OUT_Z_H] << 8 | + packet[L3GD20H::OUT_Z_L]) * scaleFactor; + + int8_t temperaturOffset = (-1) * packet[L3GD20H::TEMPERATURE_IDX]; + float temperature = 25.0 + temperaturOffset; +#if L3GD20_GYRO_DEBUG == 1 + if(debugDivider->checkAndIncrement()) { + /* Set terminal to utf-8 if there is an issue with micro printout. */ +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::info << "GyroHandlerL3GD20H: Angular velocities in degrees per second:" << + std::endl; + sif::info << "X: " << angVelocX << " \xC2\xB0" << std::endl; + sif::info << "Y: " << angVelocY << " \xC2\xB0" << std::endl; + sif::info << "Z: " << angVelocZ << " \xC2\xB0" << std::endl; +#else + sif::printInfo("GyroHandlerL3GD20H: Angular velocities in degrees per second:\n"); + sif::printInfo("X: %f " "\xC2\xB0" "T\n", angVelocX); + sif::printInfo("Y: %f " "\xC2\xB0" "T\n", angVelocY); + sif::printInfo("Z: %f " "\xC2\xB0" "T\n", angVelocZ); +#endif + } +#endif + + PoolReadGuard readSet(&dataset); + if(readSet.getReadResult() == HasReturnvaluesIF::RETURN_OK) { + dataset.angVelocX = angVelocX; + dataset.angVelocY = angVelocY; + dataset.angVelocZ = angVelocZ; + dataset.temperature = temperature; + dataset.setValidity(true, true); + } + break; + } + default: + return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; + } + return result; +} + + +uint32_t GyroHandlerL3GD20H::getTransitionDelayMs(Mode_t from, Mode_t to) { + return 10000; +} + +ReturnValue_t GyroHandlerL3GD20H::initializeLocalDataPool( + localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { + localDataPoolMap.emplace(L3GD20H::ANG_VELOC_X, + new PoolEntry({0.0})); + localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Y, + new PoolEntry({0.0})); + localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Z, + new PoolEntry({0.0})); + localDataPoolMap.emplace(L3GD20H::TEMPERATURE, + new PoolEntry({0.0})); + return HasReturnvaluesIF::RETURN_OK; +} + +void GyroHandlerL3GD20H::fillCommandAndReplyMap() { + insertInCommandAndReplyMap(L3GD20H::READ_REGS, 1, &dataset); + insertInCommandAndReplyMap(L3GD20H::CONFIGURE_CTRL_REGS, 1); + insertInCommandAndReplyMap(L3GD20H::READ_CTRL_REGS, 1); +} + +void GyroHandlerL3GD20H::modeChanged() { + internalState = InternalState::NONE; +} diff --git a/devicehandlers/GyroL3GD20Handler.h b/devicehandlers/GyroL3GD20Handler.h new file mode 100644 index 0000000..7f5ee1c --- /dev/null +++ b/devicehandlers/GyroL3GD20Handler.h @@ -0,0 +1,80 @@ +#ifndef MISSION_DEVICES_GYROL3GD20HANDLER_H_ +#define MISSION_DEVICES_GYROL3GD20HANDLER_H_ + +#include "devicedefinitions/GyroL3GD20Definitions.h" +#include + +#include +#include + + +/** + * @brief Device Handler for the L3GD20H gyroscope sensor + * (https://www.st.com/en/mems-and-sensors/l3gd20h.html) + * @details + * Advanced documentation: + * https://egit.irs.uni-stuttgart.de/redmine/projects/eive-flight-manual/wiki/L3GD20H_Gyro + * + * Data is read big endian with the smallest possible range of 245 degrees per second. + */ +class GyroHandlerL3GD20H: public DeviceHandlerBase { +public: + GyroHandlerL3GD20H(object_id_t objectId, object_id_t deviceCommunication, + CookieIF* comCookie); + virtual ~GyroHandlerL3GD20H(); + +protected: + + /* DeviceHandlerBase overrides */ + ReturnValue_t buildTransitionDeviceCommand( + DeviceCommandId_t *id) override; + void doStartUp() override; + void doShutDown() override; + ReturnValue_t buildNormalDeviceCommand( + DeviceCommandId_t *id) override; + ReturnValue_t buildCommandFromCommand( + DeviceCommandId_t deviceCommand, const uint8_t *commandData, + size_t commandDataLen) override; + ReturnValue_t scanForReply(const uint8_t *start, size_t len, + DeviceCommandId_t *foundId, size_t *foundLen) override; + ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, + const uint8_t *packet) override; + + void fillCommandAndReplyMap() override; + void modeChanged() override; + uint32_t getTransitionDelayMs(Mode_t from, Mode_t to) override; + ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap, + LocalDataPoolManager &poolManager) override; + +private: + GyroPrimaryDataset dataset; + + enum class InternalState { + NONE, + CONFIGURE, + CHECK_REGS, + NORMAL + }; + InternalState internalState = InternalState::NONE; + bool commandExecuted = false; + + uint8_t statusReg = 0; + + uint8_t ctrlReg1Value = L3GD20H::CTRL_REG_1_VAL; + uint8_t ctrlReg2Value = L3GD20H::CTRL_REG_2_VAL; + uint8_t ctrlReg3Value = L3GD20H::CTRL_REG_3_VAL; + uint8_t ctrlReg4Value = L3GD20H::CTRL_REG_4_VAL; + uint8_t ctrlReg5Value = L3GD20H::CTRL_REG_5_VAL; + + uint8_t commandBuffer[L3GD20H::READ_LEN + 1]; + + float scaleFactor = static_cast(L3GD20H::RANGE_DPS_00) / INT16_MAX; + +#if L3GD20_GYRO_DEBUG == 1 + PeriodicOperationDivider* debugDivider = nullptr; +#endif +}; + + + +#endif /* MISSION_DEVICES_GYROL3GD20HANDLER_H_ */ diff --git a/linux/i2c/CMakeLists.txt b/linux/i2c/CMakeLists.txt index 3f4bad3..0e50313 100644 --- a/linux/i2c/CMakeLists.txt +++ b/linux/i2c/CMakeLists.txt @@ -1,4 +1,4 @@ -target_sources(${TARGET_NAME} PUBLIC +target_sources(${LIB_FSFW_HAL_NAME} PUBLIC I2cComIF.cpp I2cCookie.cpp ) diff --git a/linux/spi/CMakeLists.txt b/linux/spi/CMakeLists.txt index cb1c927..5794547 100644 --- a/linux/spi/CMakeLists.txt +++ b/linux/spi/CMakeLists.txt @@ -1,4 +1,4 @@ -target_sources(${TARGET_NAME} PUBLIC +target_sources(${LIB_FSFW_HAL_NAME} PUBLIC SpiComIF.cpp SpiCookie.cpp ) diff --git a/stm32h7/CMakeLists.txt b/stm32h7/CMakeLists.txt index 3837285..eed01fd 100644 --- a/stm32h7/CMakeLists.txt +++ b/stm32h7/CMakeLists.txt @@ -1,6 +1,6 @@ add_subdirectory(spi) add_subdirectory(devicetest) -target_sources(${TARGET_NAME} PRIVATE +target_sources(${LIB_FSFW_HAL_NAME} PRIVATE dmaInterrupts.cpp ) diff --git a/stm32h7/devicetest/CMakeLists.txt b/stm32h7/devicetest/CMakeLists.txt index dab7eaf..1ee4313 100644 --- a/stm32h7/devicetest/CMakeLists.txt +++ b/stm32h7/devicetest/CMakeLists.txt @@ -1,3 +1,3 @@ -target_sources(${TARGET_NAME} PRIVATE +target_sources(${LIB_FSFW_HAL_NAME} PRIVATE GyroL3GD20H.cpp ) \ No newline at end of file diff --git a/stm32h7/i2c/CMakeLists.txt b/stm32h7/i2c/CMakeLists.txt index 8e57e01..aa3194a 100644 --- a/stm32h7/i2c/CMakeLists.txt +++ b/stm32h7/i2c/CMakeLists.txt @@ -1,2 +1,2 @@ -target_sources(${TARGET_NAME} PRIVATE +target_sources(${LIB_FSFW_HAL_NAME} PRIVATE ) diff --git a/stm32h7/spi/CMakeLists.txt b/stm32h7/spi/CMakeLists.txt index c566f53..ba814e2 100644 --- a/stm32h7/spi/CMakeLists.txt +++ b/stm32h7/spi/CMakeLists.txt @@ -1,4 +1,4 @@ -target_sources(${TARGET_NAME} PRIVATE +target_sources(${LIB_FSFW_HAL_NAME} PRIVATE spiCore.cpp spiDefinitions.cpp spiInterrupts.cpp diff --git a/stm32h7/uart/CMakeLists.txt b/stm32h7/uart/CMakeLists.txt index 8e57e01..aa3194a 100644 --- a/stm32h7/uart/CMakeLists.txt +++ b/stm32h7/uart/CMakeLists.txt @@ -1,2 +1,2 @@ -target_sources(${TARGET_NAME} PRIVATE +target_sources(${LIB_FSFW_HAL_NAME} PRIVATE ) From 499ff5dd120430c47ed5e2701f44b89601eb9aa5 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 9 Jun 2021 23:54:08 +0200 Subject: [PATCH 26/35] added missing definitions file --- CMakeLists.txt | 1 + devicehandlers/GyroL3GD20Handler.cpp | 5 +- devicehandlers/GyroL3GD20Handler.h | 2 +- .../devicedefinitions/GyroL3GD20Definitions.h | 140 ++++++++++++++++++ 4 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 devicehandlers/devicedefinitions/GyroL3GD20Definitions.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e3b75fc..24d7dac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ if(NOT LIB_FSFW_NAME) message(ERROR "LIB_FSFW_NAME needs to be set as a linkable target") endif() +add_subdirectory(devicehandlers) add_subdirectory(common) if(FSFW_HAL_ADD_LINUX) diff --git a/devicehandlers/GyroL3GD20Handler.cpp b/devicehandlers/GyroL3GD20Handler.cpp index 5820d93..9fe5125 100644 --- a/devicehandlers/GyroL3GD20Handler.cpp +++ b/devicehandlers/GyroL3GD20Handler.cpp @@ -1,5 +1,4 @@ #include "GyroL3GD20Handler.h" -#include #include @@ -64,9 +63,13 @@ ReturnValue_t GyroHandlerL3GD20H::buildTransitionDeviceCommand(DeviceCommandId_t return buildCommandFromCommand(*id, nullptr, 0); } default: +#if FSFW_CPP_OSTREAM_ENABLED == 1 /* Might be a configuration error. */ sif::debug << "GyroHandler::buildTransitionDeviceCommand: Unknown internal state!" << std::endl; +#else + sif::printDebug("GyroHandler::buildTransitionDeviceCommand: Unknown internal state!\n"); +#endif return HasReturnvaluesIF::RETURN_OK; } return HasReturnvaluesIF::RETURN_OK; diff --git a/devicehandlers/GyroL3GD20Handler.h b/devicehandlers/GyroL3GD20Handler.h index 7f5ee1c..b2b5691 100644 --- a/devicehandlers/GyroL3GD20Handler.h +++ b/devicehandlers/GyroL3GD20Handler.h @@ -1,8 +1,8 @@ #ifndef MISSION_DEVICES_GYROL3GD20HANDLER_H_ #define MISSION_DEVICES_GYROL3GD20HANDLER_H_ +#include "OBSWConfig.h" #include "devicedefinitions/GyroL3GD20Definitions.h" -#include #include #include diff --git a/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h b/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h new file mode 100644 index 0000000..00bb11b --- /dev/null +++ b/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h @@ -0,0 +1,140 @@ +#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_GYROL3GD20DEFINITIONS_H_ +#define MISSION_DEVICES_DEVICEDEFINITIONS_GYROL3GD20DEFINITIONS_H_ + +#include +#include +#include + +namespace L3GD20H { + +/* Actual size is 15 but we round up a bit */ +static constexpr size_t MAX_BUFFER_SIZE = 16; + +static constexpr uint8_t READ_MASK = 0b10000000; + +static constexpr uint8_t AUTO_INCREMENT_MASK = 0b01000000; + +static constexpr uint8_t WHO_AM_I_REG = 0b00001111; +static constexpr uint8_t WHO_AM_I_VAL = 0b11010111; + +/*------------------------------------------------------------------------*/ +/* Control registers */ +/*------------------------------------------------------------------------*/ +static constexpr uint8_t CTRL_REG_1 = 0b00100000; +static constexpr uint8_t CTRL_REG_2 = 0b00100001; +static constexpr uint8_t CTRL_REG_3 = 0b00100010; +static constexpr uint8_t CTRL_REG_4 = 0b00100011; +static constexpr uint8_t CTRL_REG_5 = 0b00100100; + +/* Register 1 */ +static constexpr uint8_t SET_DR_1 = 1 << 7; +static constexpr uint8_t SET_DR_0 = 1 << 6; +static constexpr uint8_t SET_BW_1 = 1 << 5; +static constexpr uint8_t SET_BW_0 = 1 << 4; +static constexpr uint8_t SET_POWER_NORMAL_MODE = 1 << 3; +static constexpr uint8_t SET_Z_ENABLE = 1 << 2; +static constexpr uint8_t SET_X_ENABLE = 1 << 1; +static constexpr uint8_t SET_Y_ENABLE = 1; + +static constexpr uint8_t CTRL_REG_1_VAL = SET_POWER_NORMAL_MODE | SET_Z_ENABLE | + SET_Y_ENABLE | SET_X_ENABLE; + +/* Register 2 */ +static constexpr uint8_t EXTERNAL_EDGE_ENB = 1 << 7; +static constexpr uint8_t LEVEL_SENSITIVE_TRIGGER = 1 << 6; +static constexpr uint8_t SET_HPM_1 = 1 << 5; +static constexpr uint8_t SET_HPM_0 = 1 << 4; +static constexpr uint8_t SET_HPCF_3 = 1 << 3; +static constexpr uint8_t SET_HPCF_2 = 1 << 2; +static constexpr uint8_t SET_HPCF_1 = 1 << 1; +static constexpr uint8_t SET_HPCF_0 = 1; + +static constexpr uint8_t CTRL_REG_2_VAL = 0b00000000; + +/* Register 3 */ +static constexpr uint8_t CTRL_REG_3_VAL = 0b00000000; + +/* Register 4 */ +static constexpr uint8_t SET_BNU = 1 << 7; +static constexpr uint8_t SET_BLE = 1 << 6; +static constexpr uint8_t SET_FS_1 = 1 << 5; +static constexpr uint8_t SET_FS_0 = 1 << 4; +static constexpr uint8_t SET_IMP_ENB = 1 << 3; +static constexpr uint8_t SET_SELF_TEST_ENB_1 = 1 << 2; +static constexpr uint8_t SET_SELF_TEST_ENB_0 = 1 << 1; +static constexpr uint8_t SET_SPI_IF_SELECT = 1; + +/* Enable big endian data format */ +static constexpr uint8_t CTRL_REG_4_VAL = SET_BLE; + +/* Register 5 */ +static constexpr uint8_t SET_REBOOT_MEM = 1 << 7; +static constexpr uint8_t SET_FIFO_ENB = 1 << 6; + +static constexpr uint8_t CTRL_REG_5_VAL = 0b00000000; + +/* Possible range values in degrees per second (DPS). */ +static constexpr uint16_t RANGE_DPS_00 = 245; +static constexpr uint16_t RANGE_DPS_01 = 500; +static constexpr uint16_t RANGE_DPS_11 = 2000; + +static constexpr uint8_t READ_START = CTRL_REG_1; +static constexpr size_t READ_LEN = 14; + +/* Indexing */ +static constexpr uint8_t REFERENCE_IDX = 6; +static constexpr uint8_t TEMPERATURE_IDX = 7; +static constexpr uint8_t STATUS_IDX = 8; +static constexpr uint8_t OUT_X_H = 9; +static constexpr uint8_t OUT_X_L = 10; +static constexpr uint8_t OUT_Y_H = 11; +static constexpr uint8_t OUT_Y_L = 12; +static constexpr uint8_t OUT_Z_H = 13; +static constexpr uint8_t OUT_Z_L = 14; + +/*------------------------------------------------------------------------*/ +/* Device Handler specific */ +/*------------------------------------------------------------------------*/ +static constexpr DeviceCommandId_t READ_REGS = 0; +static constexpr DeviceCommandId_t CONFIGURE_CTRL_REGS = 1; +static constexpr DeviceCommandId_t READ_CTRL_REGS = 2; + +static constexpr uint32_t GYRO_DATASET_ID = READ_REGS; + +enum GyroPoolIds: lp_id_t { + ANG_VELOC_X, + ANG_VELOC_Y, + ANG_VELOC_Z, + TEMPERATURE +}; + +} + +class GyroPrimaryDataset: public StaticLocalDataSet<5> { +public: + + /** Constructor for data users like controllers */ + GyroPrimaryDataset(object_id_t mgmId): + StaticLocalDataSet(sid_t(mgmId, L3GD20H::GYRO_DATASET_ID)) { + setAllVariablesReadOnly(); + } + + /* Angular velocities in degrees per second (DPS) */ + lp_var_t angVelocX = lp_var_t(sid.objectId, + L3GD20H::ANG_VELOC_X, this); + lp_var_t angVelocY = lp_var_t(sid.objectId, + L3GD20H::ANG_VELOC_Y, this); + lp_var_t angVelocZ = lp_var_t(sid.objectId, + L3GD20H::ANG_VELOC_Z, this); + lp_var_t temperature = lp_var_t(sid.objectId, + L3GD20H::TEMPERATURE, this); +private: + + friend class GyroHandlerL3GD20H; + /** Constructor for the data creator */ + GyroPrimaryDataset(HasLocalDataPoolIF* hkOwner): + StaticLocalDataSet(hkOwner, L3GD20H::GYRO_DATASET_ID) {} +}; + + +#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_GYROL3GD20DEFINITIONS_H_ */ From 5c40ca9ae85b59fd1f19115e2d02bae6df03dde7 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 10 Jun 2021 12:05:49 +0200 Subject: [PATCH 27/35] refactored spi components for stm32 --- devicehandlers/GyroL3GD20Handler.cpp | 6 +- devicehandlers/GyroL3GD20Handler.h | 3 + stm32h7/CMakeLists.txt | 1 + stm32h7/devicetest/GyroL3GD20H.cpp | 2 +- stm32h7/gpio/CMakeLists.txt | 3 + stm32h7/gpio/gpio.cpp | 69 +++++++++++++++++ stm32h7/gpio/gpio.h | 14 ++++ stm32h7/spi/SpiComIF.cpp | 108 ++++++++++++--------------- stm32h7/spi/SpiComIF.h | 24 +++--- stm32h7/spi/SpiCookie.cpp | 26 ++++++- stm32h7/spi/SpiCookie.h | 5 +- stm32h7/spi/spiDefinitions.cpp | 18 ++--- stm32h7/spi/spiDefinitions.h | 2 +- 13 files changed, 187 insertions(+), 94 deletions(-) create mode 100644 stm32h7/gpio/CMakeLists.txt create mode 100644 stm32h7/gpio/gpio.cpp create mode 100644 stm32h7/gpio/gpio.h diff --git a/devicehandlers/GyroL3GD20Handler.cpp b/devicehandlers/GyroL3GD20Handler.cpp index 9fe5125..a732daf 100644 --- a/devicehandlers/GyroL3GD20Handler.cpp +++ b/devicehandlers/GyroL3GD20Handler.cpp @@ -149,11 +149,7 @@ ReturnValue_t GyroHandlerL3GD20H::scanForReply(const uint8_t *start, size_t len, *foundId = this->getPendingCommand(); *foundLen = this->rawPacketLen; - /* Data with SPI Interface has always this answer */ - if (start[0] == 0b11111111) { - return HasReturnvaluesIF::RETURN_OK; - } - return DeviceHandlerIF::INVALID_DATA; + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id, diff --git a/devicehandlers/GyroL3GD20Handler.h b/devicehandlers/GyroL3GD20Handler.h index b2b5691..cc641c0 100644 --- a/devicehandlers/GyroL3GD20Handler.h +++ b/devicehandlers/GyroL3GD20Handler.h @@ -7,6 +7,9 @@ #include #include +#ifndef L3GD20_GYRO_DEBUG +#define L3GD20_GYRO_DEBUG 1 +#endif /** * @brief Device Handler for the L3GD20H gyroscope sensor diff --git a/stm32h7/CMakeLists.txt b/stm32h7/CMakeLists.txt index eed01fd..b98a9c3 100644 --- a/stm32h7/CMakeLists.txt +++ b/stm32h7/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(spi) +add_subdirectory(gpio) add_subdirectory(devicetest) target_sources(${LIB_FSFW_HAL_NAME} PRIVATE diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index d76a746..ffcc698 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -56,7 +56,7 @@ ReturnValue_t GyroL3GD20H::initialize() { spiHandle->Instance = SPI1; spiHandle->Init.BaudRatePrescaler = spi::getPrescaler(HAL_RCC_GetHCLKFreq(), 3900000); spiHandle->Init.Direction = SPI_DIRECTION_2LINES; - spi::assignSpiMode(spi::SpiModes::MODE_3, spiHandle); + spi::assignSpiMode(spi::SpiModes::MODE_3, *spiHandle); spiHandle->Init.DataSize = SPI_DATASIZE_8BIT; spiHandle->Init.FirstBit = SPI_FIRSTBIT_MSB; spiHandle->Init.TIMode = SPI_TIMODE_DISABLE; diff --git a/stm32h7/gpio/CMakeLists.txt b/stm32h7/gpio/CMakeLists.txt new file mode 100644 index 0000000..66027dd --- /dev/null +++ b/stm32h7/gpio/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(${LIB_FSFW_HAL_NAME} PRIVATE + gpio.cpp +) diff --git a/stm32h7/gpio/gpio.cpp b/stm32h7/gpio/gpio.cpp new file mode 100644 index 0000000..4cb74fd --- /dev/null +++ b/stm32h7/gpio/gpio.cpp @@ -0,0 +1,69 @@ +#include "gpio.h" + +void gpio::initializeGpioClock(GPIO_TypeDef* gpioPort) { +#ifdef GPIOA + if(gpioPort == GPIOA) { + __HAL_RCC_GPIOA_CLK_ENABLE(); + } +#endif + +#ifdef GPIOB + if(gpioPort == GPIOB) { + __HAL_RCC_GPIOB_CLK_ENABLE(); + } +#endif + +#ifdef GPIOC + if(gpioPort == GPIOC) { + __HAL_RCC_GPIOC_CLK_ENABLE(); + } +#endif + +#ifdef GPIOD + if(gpioPort == GPIOD) { + __HAL_RCC_GPIOD_CLK_ENABLE(); + } +#endif + +#ifdef GPIOE + if(gpioPort == GPIOE) { + __HAL_RCC_GPIOE_CLK_ENABLE(); + } +#endif + +#ifdef GPIOF + if(gpioPort == GPIOF) { + __HAL_RCC_GPIOF_CLK_ENABLE(); + } +#endif + +#ifdef GPIOG + if(gpioPort == GPIOG) { + __HAL_RCC_GPIOG_CLK_ENABLE(); + } +#endif + +#ifdef GPIOH + if(gpioPort == GPIOH) { + __HAL_RCC_GPIOH_CLK_ENABLE(); + } +#endif + +#ifdef GPIOI + if(gpioPort == GPIOI) { + __HAL_RCC_GPIOI_CLK_ENABLE(); + } +#endif + +#ifdef GPIOJ + if(gpioPort == GPIOJ) { + __HAL_RCC_GPIOJ_CLK_ENABLE(); + } +#endif + +#ifdef GPIOK + if(gpioPort == GPIOK) { + __HAL_RCC_GPIOK_CLK_ENABLE(); + } +#endif +} diff --git a/stm32h7/gpio/gpio.h b/stm32h7/gpio/gpio.h new file mode 100644 index 0000000..adb60de --- /dev/null +++ b/stm32h7/gpio/gpio.h @@ -0,0 +1,14 @@ +#ifndef FSFW_HAL_STM32H7_GPIO_GPIO_H_ +#define FSFW_HAL_STM32H7_GPIO_GPIO_H_ + +#include "stm32h7xx.h" + +namespace gpio { + +void initializeGpioClock(GPIO_TypeDef* gpioPort); + +} + + + +#endif /* FSFW_HAL_STM32H7_GPIO_GPIO_H_ */ diff --git a/stm32h7/spi/SpiComIF.cpp b/stm32h7/spi/SpiComIF.cpp index 26fb7e7..b36a09e 100644 --- a/stm32h7/spi/SpiComIF.cpp +++ b/stm32h7/spi/SpiComIF.cpp @@ -4,34 +4,13 @@ #include "fsfw/tasks/SemaphoreFactory.h" #include "fsfw/osal/FreeRTOS/TaskManagement.h" #include "fsfw_hal/stm32h7/spi/spiCore.h" +#include "fsfw_hal/stm32h7/spi/mspInit.h" +#include "fsfw_hal/stm32h7/gpio/gpio.h" #include "stm32h7xx_hal_gpio.h" -SpiComIF::SpiComIF(object_id_t objectId, SPI_TypeDef* spiInstance, SPI_HandleTypeDef* spiHandle, - spi::TransferModes transferMode): SystemObject(objectId), transferMode(transferMode), - spiHandle(spiHandle) { - if(spiHandle == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "SpiComIF::SpiComIF: Passed SPI handle invalid!" << std::endl; -#else - sif::printError("SpiComIF::SpiComIF: Passed SPI handle invalid!\n"); -#endif - return; - } - spiHandle->Instance = spiInstance; - spiHandle->Init.DataSize = SPI_DATASIZE_8BIT; - spiHandle->Init.FirstBit = SPI_FIRSTBIT_MSB; - spiHandle->Init.TIMode = SPI_TIMODE_DISABLE; - spiHandle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; - spiHandle->Init.CRCPolynomial = 7; - spiHandle->Init.CRCLength = SPI_CRC_LENGTH_8BIT; - spiHandle->Init.NSS = SPI_NSS_SOFT; - spiHandle->Init.NSSPMode = SPI_NSS_PULSE_DISABLE; - spiHandle->Init.Direction = SPI_DIRECTION_2LINES; - // Recommended setting to avoid glitches - spiHandle->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; - spiHandle->Init.Mode = SPI_MODE_MASTER; - +SpiComIF::SpiComIF(object_id_t objectId, spi::TransferModes transferMode): + SystemObject(objectId), transferMode(transferMode) { spi::assignTransferRxTxCompleteCallback(&spiTransferCompleteCallback, this); spi::assignTransferRxCompleteCallback(&spiTransferRxCompleteCallback, this); spi::assignTransferTxCompleteCallback(&spiTransferTxCompleteCallback, this); @@ -56,10 +35,7 @@ ReturnValue_t SpiComIF::initialize() { return HasReturnvaluesIF::RETURN_FAILED; } } - if(HAL_SPI_Init(spiHandle) != HAL_OK) { - sif::printWarning("SpiComIF::initialize: Error initializing SPI\n"); - return HasReturnvaluesIF::RETURN_FAILED; - } + return HasReturnvaluesIF::RETURN_OK; } @@ -104,11 +80,24 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { auto gpioPin = spiCookie->getChipSelectGpioPin(); auto gpioPort = spiCookie->getChipSelectGpioPort(); + SPI_HandleTypeDef& spiHandle = spiCookie->getSpiHandle(); + + if(transferMode == spi::TransferModes::POLLING) { + spi::setSpiMspFunctions(&spi::halMspInitPolling, &spiHandle, + &spi::halMspDeinitPolling, &spiHandle); + } + + gpio::initializeGpioClock(gpioPort); GPIO_InitTypeDef chipSelect = {}; chipSelect.Pin = gpioPin; chipSelect.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(gpioPort, &chipSelect); HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_SET); + + if(HAL_SPI_Init(&spiHandle) != HAL_OK) { + sif::printWarning("SpiComIF::initialize: Error initializing SPI\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } return HasReturnvaluesIF::RETURN_OK; } @@ -118,9 +107,8 @@ ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, s return NULLPOINTER; } - spi::assignSpiMode(spiCookie->getSpiMode(), spiHandle); - spiHandle->Init.BaudRatePrescaler = spi::getPrescaler(HAL_RCC_GetHCLKFreq(), - spiCookie->getSpiSpeed()); + SPI_HandleTypeDef& spiHandle = spiCookie->getSpiHandle(); + auto iter = spiDeviceMap.find(spiCookie->getDeviceAddress()); if(iter == spiDeviceMap.end()) { return HasReturnvaluesIF::RETURN_FAILED; @@ -129,16 +117,16 @@ ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, s switch(transferMode) { case(spi::TransferModes::POLLING): { - return handlePollingSendOperation(iter->second.replyBuffer.data(), spiCookie, sendData, - sendLen); + return handlePollingSendOperation(iter->second.replyBuffer.data(), spiHandle, *spiCookie, + sendData, sendLen); } case(spi::TransferModes::INTERRUPT): { - return handleInterruptSendOperation(iter->second.replyBuffer.data(), spiCookie, sendData, - sendLen); + return handleInterruptSendOperation(iter->second.replyBuffer.data(), spiHandle, *spiCookie, + sendData, sendLen); } case(spi::TransferModes::DMA): { - return handleDmaSendOperation(iter->second.replyBuffer.data(), spiCookie, sendData, - sendLen); + return handleDmaSendOperation(iter->second.replyBuffer.data(), spiHandle, *spiCookie, + sendData, sendLen); } } return HasReturnvaluesIF::RETURN_OK; @@ -170,13 +158,13 @@ void SpiComIF::setDefaultPollingTimeout(dur_millis_t timeout) { this->defaultPollingTimeout = timeout; } -ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SpiCookie *spiCookie, - const uint8_t *sendData, size_t sendLen) { - auto gpioPort = spiCookie->getChipSelectGpioPort(); - auto gpioPin = spiCookie->getChipSelectGpioPin(); +ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SPI_HandleTypeDef& spiHandle, + SpiCookie& spiCookie, const uint8_t *sendData, size_t sendLen) { + auto gpioPort = spiCookie.getChipSelectGpioPort(); + auto gpioPin = spiCookie.getChipSelectGpioPin(); spiMutex->lockMutex(timeoutType, timeoutMs); HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_RESET); - auto result = HAL_SPI_TransmitReceive(spiHandle, const_cast(sendData), + auto result = HAL_SPI_TransmitReceive(&spiHandle, const_cast(sendData), recvPtr, sendLen, defaultPollingTimeout); HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_SET); spiMutex->unlockMutex(); @@ -191,7 +179,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SpiCookie * spiCookie->getDeviceAddress() << std::endl; #else sif::printWarning("SpiComIF::sendMessage: Polling Mode | Timeout for SPI device %d\n", - spiCookie->getDeviceAddress()); + spiCookie.getDeviceAddress()); #endif #endif return spi::HAL_TIMEOUT_RETVAL; @@ -204,7 +192,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SpiCookie * spiCookie->getDeviceAddress() << std::endl; #else sif::printWarning("SpiComIF::sendMessage: Polling Mode | HAL error for SPI device %d\n", - spiCookie->getDeviceAddress()); + spiCookie.getDeviceAddress()); #endif #endif return spi::HAL_ERROR_RETVAL; @@ -213,19 +201,19 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SpiCookie * return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t SpiComIF::handleInterruptSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, - const uint8_t * sendData, size_t sendLen) { - return handleIrqSendOperation(recvPtr, spiCookie, sendData, sendLen); +ReturnValue_t SpiComIF::handleInterruptSendOperation(uint8_t* recvPtr, SPI_HandleTypeDef& spiHandle, + SpiCookie& spiCookie, const uint8_t * sendData, size_t sendLen) { + return handleIrqSendOperation(recvPtr, spiHandle, spiCookie, sendData, sendLen); } -ReturnValue_t SpiComIF::handleDmaSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, - const uint8_t * sendData, size_t sendLen) { - return handleIrqSendOperation(recvPtr, spiCookie, sendData, sendLen); +ReturnValue_t SpiComIF::handleDmaSendOperation(uint8_t* recvPtr, SPI_HandleTypeDef& spiHandle, + SpiCookie& spiCookie, const uint8_t * sendData, size_t sendLen) { + return handleIrqSendOperation(recvPtr, spiHandle, spiCookie, sendData, sendLen); } -ReturnValue_t SpiComIF::handleIrqSendOperation(uint8_t *recvPtr, SpiCookie *spiCookie, - const uint8_t *sendData, size_t sendLen) { - ReturnValue_t result = genericIrqSendSetup(recvPtr, spiCookie, sendData, sendLen); +ReturnValue_t SpiComIF::handleIrqSendOperation(uint8_t *recvPtr, SPI_HandleTypeDef& spiHandle, + SpiCookie& spiCookie, const uint8_t *sendData, size_t sendLen) { + ReturnValue_t result = genericIrqSendSetup(recvPtr, spiHandle, spiCookie, sendData, sendLen); if(result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -238,11 +226,11 @@ ReturnValue_t SpiComIF::handleIrqSendOperation(uint8_t *recvPtr, SpiCookie *spiC SCB_CleanDCache_by_Addr((uint32_t*)(((uint32_t) sendData ) & ~(uint32_t)0x1F), sendLen + 32); } - status = HAL_SPI_TransmitReceive_DMA(spiHandle, const_cast(sendData), + status = HAL_SPI_TransmitReceive_DMA(&spiHandle, const_cast(sendData), currentRecvPtr, sendLen); } else { - status = HAL_SPI_TransmitReceive_IT(spiHandle, const_cast(sendData), + status = HAL_SPI_TransmitReceive_IT(&spiHandle, const_cast(sendData), currentRecvPtr, sendLen); } switch(status) { @@ -283,11 +271,11 @@ ReturnValue_t SpiComIF::halErrorHandler(HAL_StatusTypeDef status) { } -ReturnValue_t SpiComIF::genericIrqSendSetup(uint8_t *recvPtr, SpiCookie *spiCookie, - const uint8_t *sendData, size_t sendLen) { +ReturnValue_t SpiComIF::genericIrqSendSetup(uint8_t *recvPtr, SPI_HandleTypeDef& spiHandle, + SpiCookie& spiCookie, const uint8_t *sendData, size_t sendLen) { // These are required by the callback - currentGpioPort = spiCookie->getChipSelectGpioPort(); - currentGpioPin = spiCookie->getChipSelectGpioPin(); + currentGpioPort = spiCookie.getChipSelectGpioPort(); + currentGpioPin = spiCookie.getChipSelectGpioPin(); currentRecvPtr = recvPtr; currentRecvBuffSize = sendLen; diff --git a/stm32h7/spi/SpiComIF.h b/stm32h7/spi/SpiComIF.h index 909e742..4b7e093 100644 --- a/stm32h7/spi/SpiComIF.h +++ b/stm32h7/spi/SpiComIF.h @@ -35,8 +35,7 @@ public: * @param spiHandle * @param transferMode */ - SpiComIF(object_id_t objectId, SPI_TypeDef* spiInstance, SPI_HandleTypeDef* spiHandle, - spi::TransferModes transferMode); + SpiComIF(object_id_t objectId, spi::TransferModes transferMode); /** * Allows the user to disable cache maintenance on the TX buffer. This can be done if the @@ -81,7 +80,6 @@ private: uint32_t defaultPollingTimeout = 50; spi::TransferModes transferMode; - SPI_HandleTypeDef* spiHandle; MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; dur_millis_t timeoutMs = 20; @@ -101,16 +99,16 @@ private: SpiDeviceMap spiDeviceMap; - ReturnValue_t handlePollingSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, - const uint8_t * sendData, size_t sendLen); - ReturnValue_t handleInterruptSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, - const uint8_t * sendData, size_t sendLen); - ReturnValue_t handleDmaSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, - const uint8_t * sendData, size_t sendLen); - ReturnValue_t handleIrqSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, - const uint8_t * sendData, size_t sendLen); - ReturnValue_t genericIrqSendSetup(uint8_t* recvPtr, SpiCookie* spiCookie, - const uint8_t * sendData, size_t sendLen); + ReturnValue_t handlePollingSendOperation(uint8_t* recvPtr, SPI_HandleTypeDef& spiHandle, + SpiCookie& spiCookie, const uint8_t * sendData, size_t sendLen); + ReturnValue_t handleInterruptSendOperation(uint8_t* recvPtr, SPI_HandleTypeDef& spiHandle, + SpiCookie& spiCookie, const uint8_t * sendData, size_t sendLen); + ReturnValue_t handleDmaSendOperation(uint8_t* recvPtr, SPI_HandleTypeDef& spiHandle, + SpiCookie& spiCookie, const uint8_t * sendData, size_t sendLen); + ReturnValue_t handleIrqSendOperation(uint8_t* recvPtr, SPI_HandleTypeDef& spiHandle, + SpiCookie& spiCookie, const uint8_t * sendData, size_t sendLen); + ReturnValue_t genericIrqSendSetup(uint8_t* recvPtr, SPI_HandleTypeDef& spiHandle, + SpiCookie& spiCookie, const uint8_t * sendData, size_t sendLen); ReturnValue_t halErrorHandler(HAL_StatusTypeDef status); static void spiTransferTxCompleteCallback(SPI_HandleTypeDef *hspi, void* args); diff --git a/stm32h7/spi/SpiCookie.cpp b/stm32h7/spi/SpiCookie.cpp index c869510..51a1807 100644 --- a/stm32h7/spi/SpiCookie.cpp +++ b/stm32h7/spi/SpiCookie.cpp @@ -1,13 +1,27 @@ #include "SpiCookie.h" - -SpiCookie::SpiCookie(address_t deviceAddress, spi::SpiBus spiIdx, uint32_t spiSpeed, - spi::SpiModes spiMode, uint16_t chipSelectGpioPin, GPIO_TypeDef* chipSelectGpioPort, - size_t maxRecvSize): +SpiCookie::SpiCookie(address_t deviceAddress, spi::SpiBus spiIdx, SPI_TypeDef* spiInstance, + uint32_t spiSpeed, spi::SpiModes spiMode, uint16_t chipSelectGpioPin, + GPIO_TypeDef* chipSelectGpioPort, size_t maxRecvSize): deviceAddress(deviceAddress), spiIdx(spiIdx), spiSpeed(spiSpeed), spiMode(spiMode), chipSelectGpioPin(chipSelectGpioPin), chipSelectGpioPort(chipSelectGpioPort), maxRecvSize(maxRecvSize) { + spiHandle.Instance = spiInstance; + spiHandle.Init.DataSize = SPI_DATASIZE_8BIT; + spiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; + spiHandle.Init.TIMode = SPI_TIMODE_DISABLE; + spiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + spiHandle.Init.CRCPolynomial = 7; + spiHandle.Init.CRCLength = SPI_CRC_LENGTH_8BIT; + spiHandle.Init.NSS = SPI_NSS_SOFT; + spiHandle.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; + spiHandle.Init.Direction = SPI_DIRECTION_2LINES; + // Recommended setting to avoid glitches + spiHandle.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; + spiHandle.Init.Mode = SPI_MODE_MASTER; + spi::assignSpiMode(spiMode, spiHandle); + spiHandle.Init.BaudRatePrescaler = spi::getPrescaler(HAL_RCC_GetHCLKFreq(), spiSpeed); } uint16_t SpiCookie::getChipSelectGpioPin() const { @@ -37,3 +51,7 @@ uint32_t SpiCookie::getSpiSpeed() const { size_t SpiCookie::getMaxRecvSize() const { return maxRecvSize; } + +SPI_HandleTypeDef& SpiCookie::getSpiHandle() { + return spiHandle; +} diff --git a/stm32h7/spi/SpiCookie.h b/stm32h7/spi/SpiCookie.h index bf9baff..00d7f10 100644 --- a/stm32h7/spi/SpiCookie.h +++ b/stm32h7/spi/SpiCookie.h @@ -9,7 +9,8 @@ class SpiCookie: public CookieIF { public: - SpiCookie(address_t deviceAddress, spi::SpiBus spiIdx, uint32_t spiSpeed, spi::SpiModes spiMode, + SpiCookie(address_t deviceAddress, spi::SpiBus spiIdx, SPI_TypeDef* spiInstance, + uint32_t spiSpeed, spi::SpiModes spiMode, uint16_t chipSelectGpioPin, GPIO_TypeDef* chipSelectGpioPort, size_t maxRecvSize); uint16_t getChipSelectGpioPin() const; @@ -19,9 +20,11 @@ public: spi::SpiModes getSpiMode() const; uint32_t getSpiSpeed() const; size_t getMaxRecvSize() const; + SPI_HandleTypeDef& getSpiHandle(); private: address_t deviceAddress; + SPI_HandleTypeDef spiHandle = {}; spi::SpiBus spiIdx; uint32_t spiSpeed; spi::SpiModes spiMode; diff --git a/stm32h7/spi/spiDefinitions.cpp b/stm32h7/spi/spiDefinitions.cpp index 4846293..fbceb93 100644 --- a/stm32h7/spi/spiDefinitions.cpp +++ b/stm32h7/spi/spiDefinitions.cpp @@ -1,25 +1,25 @@ #include "spiDefinitions.h" -void spi::assignSpiMode(SpiModes spiMode, SPI_HandleTypeDef *spiHandle) { +void spi::assignSpiMode(SpiModes spiMode, SPI_HandleTypeDef& spiHandle) { switch(spiMode) { case(SpiModes::MODE_0): { - spiHandle->Init.CLKPolarity = SPI_POLARITY_LOW; - spiHandle->Init.CLKPhase = SPI_PHASE_1EDGE; + spiHandle.Init.CLKPolarity = SPI_POLARITY_LOW; + spiHandle.Init.CLKPhase = SPI_PHASE_1EDGE; break; } case(SpiModes::MODE_1): { - spiHandle->Init.CLKPolarity = SPI_POLARITY_LOW; - spiHandle->Init.CLKPhase = SPI_PHASE_2EDGE; + spiHandle.Init.CLKPolarity = SPI_POLARITY_LOW; + spiHandle.Init.CLKPhase = SPI_PHASE_2EDGE; break; } case(SpiModes::MODE_2): { - spiHandle->Init.CLKPolarity = SPI_POLARITY_HIGH; - spiHandle->Init.CLKPhase = SPI_PHASE_1EDGE; + spiHandle.Init.CLKPolarity = SPI_POLARITY_HIGH; + spiHandle.Init.CLKPhase = SPI_PHASE_1EDGE; break; } case(SpiModes::MODE_3): { - spiHandle->Init.CLKPolarity = SPI_POLARITY_HIGH; - spiHandle->Init.CLKPhase = SPI_PHASE_2EDGE; + spiHandle.Init.CLKPolarity = SPI_POLARITY_HIGH; + spiHandle.Init.CLKPhase = SPI_PHASE_2EDGE; break; } } diff --git a/stm32h7/spi/spiDefinitions.h b/stm32h7/spi/spiDefinitions.h index 0ea83ac..c22b853 100644 --- a/stm32h7/spi/spiDefinitions.h +++ b/stm32h7/spi/spiDefinitions.h @@ -27,7 +27,7 @@ enum TransferModes { DMA }; -void assignSpiMode(SpiModes spiMode, SPI_HandleTypeDef* spiHandle); +void assignSpiMode(SpiModes spiMode, SPI_HandleTypeDef& spiHandle); /** * @brief Set SPI frequency to calculate correspondent baud-rate prescaler. From 92a3f131721da077ede6ef7c34f5837bccc58021 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 10 Jun 2021 12:17:47 +0200 Subject: [PATCH 28/35] important bugfixes --- devicehandlers/GyroL3GD20Handler.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/devicehandlers/GyroL3GD20Handler.cpp b/devicehandlers/GyroL3GD20Handler.cpp index a732daf..94e61cc 100644 --- a/devicehandlers/GyroL3GD20Handler.cpp +++ b/devicehandlers/GyroL3GD20Handler.cpp @@ -187,12 +187,12 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id, statusReg = packet[L3GD20H::STATUS_IDX]; - float angVelocX = (packet[L3GD20H::OUT_X_H] << 8 | - packet[L3GD20H::OUT_X_L]) * scaleFactor; - float angVelocY = (packet[L3GD20H::OUT_Y_H] << 8 | - packet[L3GD20H::OUT_Y_L]) * scaleFactor; - float angVelocZ = (packet[L3GD20H::OUT_Z_H] << 8 | - packet[L3GD20H::OUT_Z_L]) * scaleFactor; + int16_t angVelocXRaw = packet[L3GD20H::OUT_X_H] << 8 | packet[L3GD20H::OUT_X_L]; + int16_t angVelocYRaw = packet[L3GD20H::OUT_Y_H] << 8 | packet[L3GD20H::OUT_Y_L]; + int16_t angVelocZRaw = packet[L3GD20H::OUT_Z_H] << 8 | packet[L3GD20H::OUT_Z_L]; + float angVelocX = angVelocXRaw * scaleFactor; + float angVelocY = angVelocYRaw * scaleFactor; + float angVelocZ = angVelocZRaw * scaleFactor; int8_t temperaturOffset = (-1) * packet[L3GD20H::TEMPERATURE_IDX]; float temperature = 25.0 + temperaturOffset; @@ -207,9 +207,9 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id, sif::info << "Z: " << angVelocZ << " \xC2\xB0" << std::endl; #else sif::printInfo("GyroHandlerL3GD20H: Angular velocities in degrees per second:\n"); - sif::printInfo("X: %f " "\xC2\xB0" "T\n", angVelocX); - sif::printInfo("Y: %f " "\xC2\xB0" "T\n", angVelocY); - sif::printInfo("Z: %f " "\xC2\xB0" "T\n", angVelocZ); + sif::printInfo("X: %f \xC2\xB0\n", angVelocX); + sif::printInfo("Y: %f \xC2\xB0\n", angVelocY); + sif::printInfo("Z: %f \xC2\xB0\n", angVelocZ); #endif } #endif From 05b64b05a3b5777298b28b2fa2ba544554bb2e3b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 10 Jun 2021 14:17:13 +0200 Subject: [PATCH 29/35] important bugfixes --- devicehandlers/GyroL3GD20Handler.cpp | 346 +++++++++--------- devicehandlers/GyroL3GD20Handler.h | 79 ++-- .../devicedefinitions/GyroL3GD20Definitions.h | 3 + stm32h7/devicetest/GyroL3GD20H.cpp | 25 +- stm32h7/devicetest/GyroL3GD20H.h | 3 + 5 files changed, 236 insertions(+), 220 deletions(-) diff --git a/devicehandlers/GyroL3GD20Handler.cpp b/devicehandlers/GyroL3GD20Handler.cpp index 94e61cc..297b0d1 100644 --- a/devicehandlers/GyroL3GD20Handler.cpp +++ b/devicehandlers/GyroL3GD20Handler.cpp @@ -3,9 +3,9 @@ #include GyroHandlerL3GD20H::GyroHandlerL3GD20H(object_id_t objectId, object_id_t deviceCommunication, - CookieIF *comCookie): - DeviceHandlerBase(objectId, deviceCommunication, comCookie), - dataset(this) { + CookieIF *comCookie): + DeviceHandlerBase(objectId, deviceCommunication, comCookie), + dataset(this) { #if L3GD20_GYRO_DEBUG == 1 debugDivider = new PeriodicOperationDivider(5); #endif @@ -14,188 +14,188 @@ GyroHandlerL3GD20H::GyroHandlerL3GD20H(object_id_t objectId, object_id_t deviceC GyroHandlerL3GD20H::~GyroHandlerL3GD20H() {} void GyroHandlerL3GD20H::doStartUp() { - if(internalState == InternalState::NONE) { - internalState = InternalState::CONFIGURE; - } + if(internalState == InternalState::NONE) { + internalState = InternalState::CONFIGURE; + } - if(internalState == InternalState::CONFIGURE) { - if(commandExecuted) { - internalState = InternalState::CHECK_REGS; - commandExecuted = false; - } - } + if(internalState == InternalState::CONFIGURE) { + if(commandExecuted) { + internalState = InternalState::CHECK_REGS; + commandExecuted = false; + } + } - if(internalState == InternalState::CHECK_REGS) { - if(commandExecuted) { - internalState = InternalState::NORMAL; + if(internalState == InternalState::CHECK_REGS) { + if(commandExecuted) { + internalState = InternalState::NORMAL; #if OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP == 1 setMode(MODE_NORMAL); #else setMode(_MODE_TO_ON); #endif - commandExecuted = false; - } - } + commandExecuted = false; + } + } } void GyroHandlerL3GD20H::doShutDown() { - setMode(_MODE_POWER_DOWN); + setMode(_MODE_POWER_DOWN); } ReturnValue_t GyroHandlerL3GD20H::buildTransitionDeviceCommand(DeviceCommandId_t *id) { - switch(internalState) { - case(InternalState::NONE): - case(InternalState::NORMAL): { - return HasReturnvaluesIF::RETURN_OK; - } - case(InternalState::CONFIGURE): { - *id = L3GD20H::CONFIGURE_CTRL_REGS; - uint8_t command [5]; - command[0] = L3GD20H::CTRL_REG_1_VAL; - command[1] = L3GD20H::CTRL_REG_2_VAL; - command[2] = L3GD20H::CTRL_REG_3_VAL; - command[3] = L3GD20H::CTRL_REG_4_VAL; - command[4] = L3GD20H::CTRL_REG_5_VAL; - return buildCommandFromCommand(*id, command, 5); - } - case(InternalState::CHECK_REGS): { - *id = L3GD20H::READ_REGS; - return buildCommandFromCommand(*id, nullptr, 0); - } - default: + switch(internalState) { + case(InternalState::NONE): + case(InternalState::NORMAL): { + return HasReturnvaluesIF::RETURN_OK; + } + case(InternalState::CONFIGURE): { + *id = L3GD20H::CONFIGURE_CTRL_REGS; + uint8_t command [5]; + command[0] = L3GD20H::CTRL_REG_1_VAL; + command[1] = L3GD20H::CTRL_REG_2_VAL; + command[2] = L3GD20H::CTRL_REG_3_VAL; + command[3] = L3GD20H::CTRL_REG_4_VAL; + command[4] = L3GD20H::CTRL_REG_5_VAL; + return buildCommandFromCommand(*id, command, 5); + } + case(InternalState::CHECK_REGS): { + *id = L3GD20H::READ_REGS; + return buildCommandFromCommand(*id, nullptr, 0); + } + default: #if FSFW_CPP_OSTREAM_ENABLED == 1 - /* Might be a configuration error. */ - sif::debug << "GyroHandler::buildTransitionDeviceCommand: Unknown internal state!" << - std::endl; + /* Might be a configuration error. */ + sif::debug << "GyroHandler::buildTransitionDeviceCommand: Unknown internal state!" << + std::endl; #else - sif::printDebug("GyroHandler::buildTransitionDeviceCommand: Unknown internal state!\n"); + sif::printDebug("GyroHandler::buildTransitionDeviceCommand: Unknown internal state!\n"); #endif - return HasReturnvaluesIF::RETURN_OK; - } - return HasReturnvaluesIF::RETURN_OK; + return HasReturnvaluesIF::RETURN_OK; + } + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t GyroHandlerL3GD20H::buildNormalDeviceCommand(DeviceCommandId_t *id) { - *id = L3GD20H::READ_REGS; - return buildCommandFromCommand(*id, nullptr, 0); + *id = L3GD20H::READ_REGS; + return buildCommandFromCommand(*id, nullptr, 0); } ReturnValue_t GyroHandlerL3GD20H::buildCommandFromCommand( - DeviceCommandId_t deviceCommand, const uint8_t *commandData, - size_t commandDataLen) { - switch(deviceCommand) { - case(L3GD20H::READ_REGS): { - commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | - L3GD20H::READ_MASK; + DeviceCommandId_t deviceCommand, const uint8_t *commandData, + size_t commandDataLen) { + switch(deviceCommand) { + case(L3GD20H::READ_REGS): { + commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | + L3GD20H::READ_MASK; - std::memset(commandBuffer + 1, 0, L3GD20H::READ_LEN); - rawPacket = commandBuffer; - rawPacketLen = L3GD20H::READ_LEN + 1; - break; - } - case(L3GD20H::CONFIGURE_CTRL_REGS): { - commandBuffer[0] = L3GD20H::CTRL_REG_1 | L3GD20H::AUTO_INCREMENT_MASK; - if(commandData == nullptr or commandDataLen != 5) { - return DeviceHandlerIF::INVALID_COMMAND_PARAMETER; - } + std::memset(commandBuffer + 1, 0, L3GD20H::READ_LEN); + rawPacket = commandBuffer; + rawPacketLen = L3GD20H::READ_LEN + 1; + break; + } + case(L3GD20H::CONFIGURE_CTRL_REGS): { + commandBuffer[0] = L3GD20H::CTRL_REG_1 | L3GD20H::AUTO_INCREMENT_MASK; + if(commandData == nullptr or commandDataLen != 5) { + return DeviceHandlerIF::INVALID_COMMAND_PARAMETER; + } - ctrlReg1Value = commandData[0]; - ctrlReg2Value = commandData[1]; - ctrlReg3Value = commandData[2]; - ctrlReg4Value = commandData[3]; - ctrlReg5Value = commandData[4]; + ctrlReg1Value = commandData[0]; + ctrlReg2Value = commandData[1]; + ctrlReg3Value = commandData[2]; + ctrlReg4Value = commandData[3]; + ctrlReg5Value = commandData[4]; - bool fsH = ctrlReg4Value & L3GD20H::SET_FS_1; - bool fsL = ctrlReg4Value & L3GD20H::SET_FS_0; + bool fsH = ctrlReg4Value & L3GD20H::SET_FS_1; + bool fsL = ctrlReg4Value & L3GD20H::SET_FS_0; - if(not fsH and not fsL) { - scaleFactor = static_cast(L3GD20H::RANGE_DPS_00) / INT16_MAX; - } - else if(not fsH and fsL) { - scaleFactor = static_cast(L3GD20H::RANGE_DPS_01) / INT16_MAX; - } - else { - scaleFactor = static_cast(L3GD20H::RANGE_DPS_11) / INT16_MAX; - } + if(not fsH and not fsL) { + sensitivity = L3GD20H::SENSITIVITY_00; + } + else if(not fsH and fsL) { + sensitivity = L3GD20H::SENSITIVITY_01; + } + else { + sensitivity = L3GD20H::SENSITIVITY_11; + } - commandBuffer[1] = ctrlReg1Value; - commandBuffer[2] = ctrlReg2Value; - commandBuffer[3] = ctrlReg3Value; - commandBuffer[4] = ctrlReg4Value; - commandBuffer[5] = ctrlReg5Value; + commandBuffer[1] = ctrlReg1Value; + commandBuffer[2] = ctrlReg2Value; + commandBuffer[3] = ctrlReg3Value; + commandBuffer[4] = ctrlReg4Value; + commandBuffer[5] = ctrlReg5Value; - rawPacket = commandBuffer; - rawPacketLen = 6; - break; - } - case(L3GD20H::READ_CTRL_REGS): { - commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | - L3GD20H::READ_MASK; + rawPacket = commandBuffer; + rawPacketLen = 6; + break; + } + case(L3GD20H::READ_CTRL_REGS): { + commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | + L3GD20H::READ_MASK; - std::memset(commandBuffer + 1, 0, 5); - rawPacket = commandBuffer; - rawPacketLen = 6; - break; - } - default: - return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; - } - return HasReturnvaluesIF::RETURN_OK; + std::memset(commandBuffer + 1, 0, 5); + rawPacket = commandBuffer; + rawPacketLen = 6; + break; + } + default: + return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; + } + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t GyroHandlerL3GD20H::scanForReply(const uint8_t *start, size_t len, - DeviceCommandId_t *foundId, size_t *foundLen) { - /* For SPI, the ID will always be the one of the last sent command. */ - *foundId = this->getPendingCommand(); - *foundLen = this->rawPacketLen; + DeviceCommandId_t *foundId, size_t *foundLen) { + /* For SPI, the ID will always be the one of the last sent command. */ + *foundId = this->getPendingCommand(); + *foundLen = this->rawPacketLen; - return HasReturnvaluesIF::RETURN_OK; + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id, - const uint8_t *packet) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - switch(id) { - case(L3GD20H::CONFIGURE_CTRL_REGS): { - commandExecuted = true; - break; - } - case(L3GD20H::READ_CTRL_REGS): { - if(packet[1] == ctrlReg1Value and packet[2] == ctrlReg2Value and - packet[3] == ctrlReg3Value and packet[4] == ctrlReg4Value and - packet[5] == ctrlReg5Value) { - commandExecuted = true; - } - else { - /* Attempt reconfiguration. */ - internalState = InternalState::CONFIGURE; - return DeviceHandlerIF::DEVICE_REPLY_INVALID; - } - break; - } - case(L3GD20H::READ_REGS): { - if(packet[1] != ctrlReg1Value and packet[2] != ctrlReg2Value and - packet[3] != ctrlReg3Value and packet[4] != ctrlReg4Value and - packet[5] != ctrlReg5Value) { - return DeviceHandlerIF::DEVICE_REPLY_INVALID; - } - else { - if(internalState == InternalState::CHECK_REGS) { - commandExecuted = true; - } - } + const uint8_t *packet) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + switch(id) { + case(L3GD20H::CONFIGURE_CTRL_REGS): { + commandExecuted = true; + break; + } + case(L3GD20H::READ_CTRL_REGS): { + if(packet[1] == ctrlReg1Value and packet[2] == ctrlReg2Value and + packet[3] == ctrlReg3Value and packet[4] == ctrlReg4Value and + packet[5] == ctrlReg5Value) { + commandExecuted = true; + } + else { + /* Attempt reconfiguration. */ + internalState = InternalState::CONFIGURE; + return DeviceHandlerIF::DEVICE_REPLY_INVALID; + } + break; + } + case(L3GD20H::READ_REGS): { + if(packet[1] != ctrlReg1Value and packet[2] != ctrlReg2Value and + packet[3] != ctrlReg3Value and packet[4] != ctrlReg4Value and + packet[5] != ctrlReg5Value) { + return DeviceHandlerIF::DEVICE_REPLY_INVALID; + } + else { + if(internalState == InternalState::CHECK_REGS) { + commandExecuted = true; + } + } - statusReg = packet[L3GD20H::STATUS_IDX]; + statusReg = packet[L3GD20H::STATUS_IDX]; - int16_t angVelocXRaw = packet[L3GD20H::OUT_X_H] << 8 | packet[L3GD20H::OUT_X_L]; + int16_t angVelocXRaw = packet[L3GD20H::OUT_X_H] << 8 | packet[L3GD20H::OUT_X_L]; int16_t angVelocYRaw = packet[L3GD20H::OUT_Y_H] << 8 | packet[L3GD20H::OUT_Y_L]; int16_t angVelocZRaw = packet[L3GD20H::OUT_Z_H] << 8 | packet[L3GD20H::OUT_Z_L]; - float angVelocX = angVelocXRaw * scaleFactor; - float angVelocY = angVelocYRaw * scaleFactor; - float angVelocZ = angVelocZRaw * scaleFactor; + float angVelocX = angVelocXRaw * sensitivity; + float angVelocY = angVelocYRaw * sensitivity; + float angVelocZ = angVelocZRaw * sensitivity; - int8_t temperaturOffset = (-1) * packet[L3GD20H::TEMPERATURE_IDX]; - float temperature = 25.0 + temperaturOffset; + int8_t temperaturOffset = (-1) * packet[L3GD20H::TEMPERATURE_IDX]; + float temperature = 25.0 + temperaturOffset; #if L3GD20_GYRO_DEBUG == 1 if(debugDivider->checkAndIncrement()) { /* Set terminal to utf-8 if there is an issue with micro printout. */ @@ -214,46 +214,46 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id, } #endif - PoolReadGuard readSet(&dataset); - if(readSet.getReadResult() == HasReturnvaluesIF::RETURN_OK) { - dataset.angVelocX = angVelocX; - dataset.angVelocY = angVelocY; - dataset.angVelocZ = angVelocZ; - dataset.temperature = temperature; - dataset.setValidity(true, true); - } - break; - } - default: - return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; - } - return result; + PoolReadGuard readSet(&dataset); + if(readSet.getReadResult() == HasReturnvaluesIF::RETURN_OK) { + dataset.angVelocX = angVelocX; + dataset.angVelocY = angVelocY; + dataset.angVelocZ = angVelocZ; + dataset.temperature = temperature; + dataset.setValidity(true, true); + } + break; + } + default: + return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; + } + return result; } uint32_t GyroHandlerL3GD20H::getTransitionDelayMs(Mode_t from, Mode_t to) { - return 10000; + return 10000; } ReturnValue_t GyroHandlerL3GD20H::initializeLocalDataPool( - localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(L3GD20H::ANG_VELOC_X, - new PoolEntry({0.0})); - localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Y, - new PoolEntry({0.0})); - localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Z, - new PoolEntry({0.0})); - localDataPoolMap.emplace(L3GD20H::TEMPERATURE, - new PoolEntry({0.0})); - return HasReturnvaluesIF::RETURN_OK; + localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { + localDataPoolMap.emplace(L3GD20H::ANG_VELOC_X, + new PoolEntry({0.0})); + localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Y, + new PoolEntry({0.0})); + localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Z, + new PoolEntry({0.0})); + localDataPoolMap.emplace(L3GD20H::TEMPERATURE, + new PoolEntry({0.0})); + return HasReturnvaluesIF::RETURN_OK; } void GyroHandlerL3GD20H::fillCommandAndReplyMap() { - insertInCommandAndReplyMap(L3GD20H::READ_REGS, 1, &dataset); - insertInCommandAndReplyMap(L3GD20H::CONFIGURE_CTRL_REGS, 1); - insertInCommandAndReplyMap(L3GD20H::READ_CTRL_REGS, 1); + insertInCommandAndReplyMap(L3GD20H::READ_REGS, 1, &dataset); + insertInCommandAndReplyMap(L3GD20H::CONFIGURE_CTRL_REGS, 1); + insertInCommandAndReplyMap(L3GD20H::READ_CTRL_REGS, 1); } void GyroHandlerL3GD20H::modeChanged() { - internalState = InternalState::NONE; + internalState = InternalState::NONE; } diff --git a/devicehandlers/GyroL3GD20Handler.h b/devicehandlers/GyroL3GD20Handler.h index cc641c0..fb9baac 100644 --- a/devicehandlers/GyroL3GD20Handler.h +++ b/devicehandlers/GyroL3GD20Handler.h @@ -22,56 +22,57 @@ */ class GyroHandlerL3GD20H: public DeviceHandlerBase { public: - GyroHandlerL3GD20H(object_id_t objectId, object_id_t deviceCommunication, - CookieIF* comCookie); - virtual ~GyroHandlerL3GD20H(); + GyroHandlerL3GD20H(object_id_t objectId, object_id_t deviceCommunication, + CookieIF* comCookie); + virtual ~GyroHandlerL3GD20H(); protected: - /* DeviceHandlerBase overrides */ - ReturnValue_t buildTransitionDeviceCommand( - DeviceCommandId_t *id) override; - void doStartUp() override; - void doShutDown() override; - ReturnValue_t buildNormalDeviceCommand( - DeviceCommandId_t *id) override; - ReturnValue_t buildCommandFromCommand( - DeviceCommandId_t deviceCommand, const uint8_t *commandData, - size_t commandDataLen) override; - ReturnValue_t scanForReply(const uint8_t *start, size_t len, - DeviceCommandId_t *foundId, size_t *foundLen) override; - ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, - const uint8_t *packet) override; + /* DeviceHandlerBase overrides */ + ReturnValue_t buildTransitionDeviceCommand( + DeviceCommandId_t *id) override; + void doStartUp() override; + void doShutDown() override; + ReturnValue_t buildNormalDeviceCommand( + DeviceCommandId_t *id) override; + ReturnValue_t buildCommandFromCommand( + DeviceCommandId_t deviceCommand, const uint8_t *commandData, + size_t commandDataLen) override; + ReturnValue_t scanForReply(const uint8_t *start, size_t len, + DeviceCommandId_t *foundId, size_t *foundLen) override; + ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, + const uint8_t *packet) override; - void fillCommandAndReplyMap() override; - void modeChanged() override; - uint32_t getTransitionDelayMs(Mode_t from, Mode_t to) override; - ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap, - LocalDataPoolManager &poolManager) override; + void fillCommandAndReplyMap() override; + void modeChanged() override; + uint32_t getTransitionDelayMs(Mode_t from, Mode_t to) override; + ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap, + LocalDataPoolManager &poolManager) override; private: - GyroPrimaryDataset dataset; + GyroPrimaryDataset dataset; - enum class InternalState { - NONE, - CONFIGURE, - CHECK_REGS, - NORMAL - }; - InternalState internalState = InternalState::NONE; - bool commandExecuted = false; + enum class InternalState { + NONE, + CONFIGURE, + CHECK_REGS, + NORMAL + }; + InternalState internalState = InternalState::NONE; + bool commandExecuted = false; - uint8_t statusReg = 0; + uint8_t statusReg = 0; - uint8_t ctrlReg1Value = L3GD20H::CTRL_REG_1_VAL; - uint8_t ctrlReg2Value = L3GD20H::CTRL_REG_2_VAL; - uint8_t ctrlReg3Value = L3GD20H::CTRL_REG_3_VAL; - uint8_t ctrlReg4Value = L3GD20H::CTRL_REG_4_VAL; - uint8_t ctrlReg5Value = L3GD20H::CTRL_REG_5_VAL; + uint8_t ctrlReg1Value = L3GD20H::CTRL_REG_1_VAL; + uint8_t ctrlReg2Value = L3GD20H::CTRL_REG_2_VAL; + uint8_t ctrlReg3Value = L3GD20H::CTRL_REG_3_VAL; + uint8_t ctrlReg4Value = L3GD20H::CTRL_REG_4_VAL; + uint8_t ctrlReg5Value = L3GD20H::CTRL_REG_5_VAL; - uint8_t commandBuffer[L3GD20H::READ_LEN + 1]; + uint8_t commandBuffer[L3GD20H::READ_LEN + 1]; - float scaleFactor = static_cast(L3GD20H::RANGE_DPS_00) / INT16_MAX; + // Set default value + float sensitivity = L3GD20H::SENSITIVITY_00; #if L3GD20_GYRO_DEBUG == 1 PeriodicOperationDivider* debugDivider = nullptr; diff --git a/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h b/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h index 00bb11b..489a45d 100644 --- a/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h +++ b/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h @@ -75,8 +75,11 @@ static constexpr uint8_t CTRL_REG_5_VAL = 0b00000000; /* Possible range values in degrees per second (DPS). */ static constexpr uint16_t RANGE_DPS_00 = 245; +static constexpr float SENSITIVITY_00 = 8.75; static constexpr uint16_t RANGE_DPS_01 = 500; +static constexpr float SENSITIVITY_01 = 17.5; static constexpr uint16_t RANGE_DPS_11 = 2000; +static constexpr float SENSITIVITY_11 = 70.0; static constexpr uint8_t READ_START = CTRL_REG_1; static constexpr size_t READ_LEN = 14; diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index ffcc698..54f69bc 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -15,7 +15,7 @@ alignas(32) std::array GyroL3GD20H::rxBuffer; alignas(32) std::array - GyroL3GD20H::txBuffer __attribute__((section(".dma_buffer"))); +GyroL3GD20H::txBuffer __attribute__((section(".dma_buffer"))); TransferStates transferState = TransferStates::IDLE; spi::TransferModes GyroL3GD20H::transferMode = spi::TransferModes::POLLING; @@ -24,7 +24,7 @@ DMA_HandleTypeDef txDmaHandle; DMA_HandleTypeDef rxDmaHandle; GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transferMode_): - spiHandle(spiHandle) { + spiHandle(spiHandle) { transferMode = transferMode_; if(transferMode == spi::TransferModes::DMA) { spi::setDmaHandles(&txDmaHandle, &rxDmaHandle); @@ -291,7 +291,6 @@ ReturnValue_t GyroL3GD20H::handlePollingTransferInit() { return HasReturnvaluesIF::RETURN_FAILED; } } - return HasReturnvaluesIF::RETURN_OK; sif::printInfo("GyroL3GD20H::initialize: Configuring device\n"); // Configure the 5 configuration registers @@ -317,7 +316,6 @@ ReturnValue_t GyroL3GD20H::handlePollingTransferInit() { return HasReturnvaluesIF::RETURN_FAILED; } } - return HasReturnvaluesIF::RETURN_OK; txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK | STM_READ_MASK; std::memset(txBuffer.data() + 1, 0 , 5); @@ -358,6 +356,7 @@ ReturnValue_t GyroL3GD20H::handlePollingSensorRead() { HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); auto result = HAL_SPI_TransmitReceive(spiHandle, txBuffer.data(), rxBuffer.data(), 15, 1000); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); + switch(result) { case(HAL_OK): { handleSensorReadout(); @@ -484,22 +483,32 @@ void GyroL3GD20H::prepareConfigRegs(uint8_t* configRegs) { configRegs[0] = 0b00001111; configRegs[1] = 0b00000000; configRegs[2] = 0b00000000; - configRegs[3] = 0b01000000; // Big endian select + configRegs[3] = 0b01000000; configRegs[4] = 0b00000000; txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK; std::memcpy(txBuffer.data() + 1, configRegs, 5); } +uint8_t GyroL3GD20H::readRegPolling(uint8_t reg) { + uint8_t rxBuf[2] = {}; + uint8_t txBuf[2] = {}; + txBuf[0] = reg | STM_READ_MASK; + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); + auto result = HAL_SPI_TransmitReceive(spiHandle, txBuf, rxBuf, 2, 1000); + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); + return rxBuf[1]; +} + void GyroL3GD20H::handleSensorReadout() { uint8_t statusReg = rxBuffer[8]; int16_t gyroXRaw = rxBuffer[9] << 8 | rxBuffer[10]; - float gyroX = static_cast(gyroXRaw) / INT16_MAX * L3G_RANGE; + float gyroX = static_cast(gyroXRaw) * 0.00875; int16_t gyroYRaw = rxBuffer[11] << 8 | rxBuffer[12]; - float gyroY = static_cast(gyroYRaw) / INT16_MAX * L3G_RANGE; + float gyroY = static_cast(gyroYRaw) * 0.00875; int16_t gyroZRaw = rxBuffer[13] << 8 | rxBuffer[14]; - float gyroZ = static_cast(gyroZRaw) / INT16_MAX * L3G_RANGE; + float gyroZ = static_cast(gyroZRaw) * 0.00875; sif::printInfo("Status register: 0b" BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(statusReg)); sif::printInfo("Gyro X: %f\n", gyroX); sif::printInfo("Gyro Y: %f\n", gyroY); diff --git a/stm32h7/devicetest/GyroL3GD20H.h b/stm32h7/devicetest/GyroL3GD20H.h index 4ebed1e..641c938 100644 --- a/stm32h7/devicetest/GyroL3GD20H.h +++ b/stm32h7/devicetest/GyroL3GD20H.h @@ -50,9 +50,12 @@ private: ReturnValue_t handlePollingSensorRead(); ReturnValue_t handleInterruptSensorRead(); + uint8_t readRegPolling(uint8_t reg); + static void spiTransferCompleteCallback(SPI_HandleTypeDef *hspi, void* args); static void spiTransferErrorCallback(SPI_HandleTypeDef *hspi, void* args); + void prepareConfigRegs(uint8_t* configRegs); void handleSensorReadout(); }; From 0e79b5f4ae82f5bd358149b522b2e582b896c39d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 10 Jun 2021 14:21:59 +0200 Subject: [PATCH 30/35] fix for sensitivity --- devicehandlers/GyroL3GD20Handler.cpp | 6 +++--- devicehandlers/devicedefinitions/GyroL3GD20Definitions.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/devicehandlers/GyroL3GD20Handler.cpp b/devicehandlers/GyroL3GD20Handler.cpp index 297b0d1..4ab4724 100644 --- a/devicehandlers/GyroL3GD20Handler.cpp +++ b/devicehandlers/GyroL3GD20Handler.cpp @@ -207,9 +207,9 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id, sif::info << "Z: " << angVelocZ << " \xC2\xB0" << std::endl; #else sif::printInfo("GyroHandlerL3GD20H: Angular velocities in degrees per second:\n"); - sif::printInfo("X: %f \xC2\xB0\n", angVelocX); - sif::printInfo("Y: %f \xC2\xB0\n", angVelocY); - sif::printInfo("Z: %f \xC2\xB0\n", angVelocZ); + sif::printInfo("X: %f\n", angVelocX); + sif::printInfo("Y: %f\n", angVelocY); + sif::printInfo("Z: %f\n", angVelocZ); #endif } #endif diff --git a/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h b/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h index 489a45d..56a2468 100644 --- a/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h +++ b/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h @@ -75,11 +75,11 @@ static constexpr uint8_t CTRL_REG_5_VAL = 0b00000000; /* Possible range values in degrees per second (DPS). */ static constexpr uint16_t RANGE_DPS_00 = 245; -static constexpr float SENSITIVITY_00 = 8.75; +static constexpr float SENSITIVITY_00 = 8.75 * 0.001; static constexpr uint16_t RANGE_DPS_01 = 500; -static constexpr float SENSITIVITY_01 = 17.5; +static constexpr float SENSITIVITY_01 = 17.5 * 0.001; static constexpr uint16_t RANGE_DPS_11 = 2000; -static constexpr float SENSITIVITY_11 = 70.0; +static constexpr float SENSITIVITY_11 = 70.0 * 0.001; static constexpr uint8_t READ_START = CTRL_REG_1; static constexpr size_t READ_LEN = 14; From 8f61c23e624e55e44c3410f0204010559e2bd7d9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 10 Jun 2021 19:09:33 +0200 Subject: [PATCH 31/35] refactored everything --- devicehandlers/GyroL3GD20Handler.cpp | 23 +- devicehandlers/GyroL3GD20Handler.h | 10 +- stm32h7/CMakeLists.txt | 2 +- stm32h7/devicetest/GyroL3GD20H.cpp | 36 ++- stm32h7/devicetest/GyroL3GD20H.h | 9 +- stm32h7/{dmaInterrupts.cpp => dma.cpp} | 3 +- stm32h7/{dmaInterrupts.h => dma.h} | 20 +- stm32h7/interrupts.h | 8 + stm32h7/spi/CMakeLists.txt | 1 + stm32h7/spi/SpiComIF.cpp | 12 +- stm32h7/spi/mspInit.cpp | 365 +++++++++++++++---------- stm32h7/spi/mspInit.h | 95 ++++++- stm32h7/spi/spiCore.cpp | 257 ++++++++++++----- stm32h7/spi/spiCore.h | 18 +- stm32h7/spi/spiInterrupts.cpp | 36 ++- stm32h7/spi/spiInterrupts.h | 6 +- stm32h7/spi/stm32h743ziSpi.cpp | 81 ++++++ stm32h7/spi/stm32h743ziSpi.h | 23 ++ 18 files changed, 740 insertions(+), 265 deletions(-) rename stm32h7/{dmaInterrupts.cpp => dma.cpp} (98%) rename stm32h7/{dmaInterrupts.h => dma.h} (73%) create mode 100644 stm32h7/spi/stm32h743ziSpi.cpp create mode 100644 stm32h7/spi/stm32h743ziSpi.h diff --git a/devicehandlers/GyroL3GD20Handler.cpp b/devicehandlers/GyroL3GD20Handler.cpp index 4ab4724..79cbe43 100644 --- a/devicehandlers/GyroL3GD20Handler.cpp +++ b/devicehandlers/GyroL3GD20Handler.cpp @@ -6,7 +6,7 @@ GyroHandlerL3GD20H::GyroHandlerL3GD20H(object_id_t objectId, object_id_t deviceC CookieIF *comCookie): DeviceHandlerBase(objectId, deviceCommunication, comCookie), dataset(this) { -#if L3GD20_GYRO_DEBUG == 1 +#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1 debugDivider = new PeriodicOperationDivider(5); #endif } @@ -28,11 +28,12 @@ void GyroHandlerL3GD20H::doStartUp() { if(internalState == InternalState::CHECK_REGS) { if(commandExecuted) { internalState = InternalState::NORMAL; -#if OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP == 1 - setMode(MODE_NORMAL); -#else - setMode(_MODE_TO_ON); -#endif + if(goNormalModeImmediately) { + setMode(MODE_NORMAL); + } + else { + setMode(_MODE_TO_ON); + } commandExecuted = false; } } @@ -85,9 +86,7 @@ ReturnValue_t GyroHandlerL3GD20H::buildCommandFromCommand( size_t commandDataLen) { switch(deviceCommand) { case(L3GD20H::READ_REGS): { - commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | - L3GD20H::READ_MASK; - + commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | L3GD20H::READ_MASK; std::memset(commandBuffer + 1, 0, L3GD20H::READ_LEN); rawPacket = commandBuffer; rawPacketLen = L3GD20H::READ_LEN + 1; @@ -196,7 +195,7 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id, int8_t temperaturOffset = (-1) * packet[L3GD20H::TEMPERATURE_IDX]; float temperature = 25.0 + temperaturOffset; -#if L3GD20_GYRO_DEBUG == 1 +#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1 if(debugDivider->checkAndIncrement()) { /* Set terminal to utf-8 if there is an issue with micro printout. */ #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -235,6 +234,10 @@ uint32_t GyroHandlerL3GD20H::getTransitionDelayMs(Mode_t from, Mode_t to) { return 10000; } +void GyroHandlerL3GD20H::setGoNormalModeAtStartup() { + this->goNormalModeImmediately = true; +} + ReturnValue_t GyroHandlerL3GD20H::initializeLocalDataPool( localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { localDataPoolMap.emplace(L3GD20H::ANG_VELOC_X, diff --git a/devicehandlers/GyroL3GD20Handler.h b/devicehandlers/GyroL3GD20Handler.h index fb9baac..f82ba93 100644 --- a/devicehandlers/GyroL3GD20Handler.h +++ b/devicehandlers/GyroL3GD20Handler.h @@ -7,9 +7,9 @@ #include #include -#ifndef L3GD20_GYRO_DEBUG -#define L3GD20_GYRO_DEBUG 1 -#endif +#ifndef FSFW_HAL_L3GD20_GYRO_DEBUG +#define FSFW_HAL_L3GD20_GYRO_DEBUG 1 +#endif /* FSFW_HAL_L3GD20_GYRO_DEBUG */ /** * @brief Device Handler for the L3GD20H gyroscope sensor @@ -26,6 +26,7 @@ public: CookieIF* comCookie); virtual ~GyroHandlerL3GD20H(); + void setGoNormalModeAtStartup(); protected: /* DeviceHandlerBase overrides */ @@ -62,6 +63,7 @@ private: bool commandExecuted = false; uint8_t statusReg = 0; + bool goNormalModeImmediately = false; uint8_t ctrlReg1Value = L3GD20H::CTRL_REG_1_VAL; uint8_t ctrlReg2Value = L3GD20H::CTRL_REG_2_VAL; @@ -74,7 +76,7 @@ private: // Set default value float sensitivity = L3GD20H::SENSITIVITY_00; -#if L3GD20_GYRO_DEBUG == 1 +#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1 PeriodicOperationDivider* debugDivider = nullptr; #endif }; diff --git a/stm32h7/CMakeLists.txt b/stm32h7/CMakeLists.txt index b98a9c3..63c1373 100644 --- a/stm32h7/CMakeLists.txt +++ b/stm32h7/CMakeLists.txt @@ -3,5 +3,5 @@ add_subdirectory(gpio) add_subdirectory(devicetest) target_sources(${LIB_FSFW_HAL_NAME} PRIVATE - dmaInterrupts.cpp + dma.cpp ) diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index 54f69bc..240b159 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -3,6 +3,8 @@ #include "../spi/mspInit.h" #include "../spi/spiDefinitions.h" #include "../spi/spiCore.h" +#include "../spi/spiInterrupts.h" +#include "../spi/stm32h743ziSpi.h" #include "fsfw/tasks/TaskFactory.h" #include "fsfw/serviceinterface/ServiceInterface.h" @@ -20,24 +22,32 @@ GyroL3GD20H::txBuffer __attribute__((section(".dma_buffer"))); TransferStates transferState = TransferStates::IDLE; spi::TransferModes GyroL3GD20H::transferMode = spi::TransferModes::POLLING; -DMA_HandleTypeDef txDmaHandle; -DMA_HandleTypeDef rxDmaHandle; GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transferMode_): - spiHandle(spiHandle) { + spiHandle(spiHandle) { + txDmaHandle = new DMA_HandleTypeDef(); + rxDmaHandle = new DMA_HandleTypeDef(); + spi::setSpiHandle(spiHandle); transferMode = transferMode_; if(transferMode == spi::TransferModes::DMA) { - spi::setDmaHandles(&txDmaHandle, &rxDmaHandle); - spi::setSpiMspFunctions(&spi::halMspInitDma, spiHandle, - &spi::halMspDeinitDma, spiHandle); + mspCfg = new spi::MspDmaConfigStruct(); + auto typedCfg = dynamic_cast(mspCfg); + spi::setDmaHandles(txDmaHandle, rxDmaHandle); + spi::h743zi::standardDmaCfg(*typedCfg, IrqPriorities::HIGHEST_FREERTOS, + IrqPriorities::HIGHEST_FREERTOS, IrqPriorities::HIGHEST_FREERTOS); + spi::setSpiDmaMspFunctions(typedCfg); } else if(transferMode == spi::TransferModes::INTERRUPT) { - spi::setSpiMspFunctions(&spi::halMspInitInterrupt, spiHandle, - &spi::halMspDeinitInterrupt, spiHandle); + mspCfg = new spi::MspIrqConfigStruct(); + auto typedCfg = dynamic_cast(mspCfg); + spi::h743zi::standardInterruptCfg(*typedCfg, IrqPriorities::HIGHEST_FREERTOS); + spi::setSpiIrqMspFunctions(typedCfg); } else if(transferMode == spi::TransferModes::POLLING) { - spi::setSpiMspFunctions(&spi::halMspInitPolling, spiHandle, - &spi::halMspDeinitPolling, spiHandle); + mspCfg = new spi::MspPollingConfigStruct(); + auto typedCfg = dynamic_cast(mspCfg); + spi::h743zi::standardPollingCfg(*typedCfg); + spi::setSpiPollingMspFunctions(typedCfg); } spi::assignTransferRxTxCompleteCallback(&spiTransferCompleteCallback, nullptr); @@ -51,6 +61,12 @@ GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transf HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); } +GyroL3GD20H::~GyroL3GD20H() { + delete txDmaHandle; + delete rxDmaHandle; + delete mspCfg; +} + ReturnValue_t GyroL3GD20H::initialize() { // Configure the SPI peripheral spiHandle->Instance = SPI1; diff --git a/stm32h7/devicetest/GyroL3GD20H.h b/stm32h7/devicetest/GyroL3GD20H.h index 641c938..b65654d 100644 --- a/stm32h7/devicetest/GyroL3GD20H.h +++ b/stm32h7/devicetest/GyroL3GD20H.h @@ -3,8 +3,9 @@ #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_spi.h" - +#include "../spi/mspInit.h" #include "../spi/spiDefinitions.h" + #include "fsfw/returnvalues/HasReturnvaluesIF.h" #include @@ -20,6 +21,7 @@ enum class TransferStates { class GyroL3GD20H { public: GyroL3GD20H(SPI_HandleTypeDef* spiHandle, spi::TransferModes transferMode); + ~GyroL3GD20H(); ReturnValue_t initialize(); ReturnValue_t performOperation(); @@ -58,6 +60,11 @@ private: void prepareConfigRegs(uint8_t* configRegs); void handleSensorReadout(); + + + DMA_HandleTypeDef* txDmaHandle = {}; + DMA_HandleTypeDef* rxDmaHandle = {}; + spi::MspCfgBase* mspCfg = {}; }; #endif /* FSFW_HAL_STM32H7_DEVICETEST_GYRO_L3GD20H_H_ */ diff --git a/stm32h7/dmaInterrupts.cpp b/stm32h7/dma.cpp similarity index 98% rename from stm32h7/dmaInterrupts.cpp rename to stm32h7/dma.cpp index a10793d..91fb338 100644 --- a/stm32h7/dmaInterrupts.cpp +++ b/stm32h7/dma.cpp @@ -1,5 +1,4 @@ -#include "dmaInterrupts.h" - +#include #include #include diff --git a/stm32h7/dmaInterrupts.h b/stm32h7/dma.h similarity index 73% rename from stm32h7/dmaInterrupts.h rename to stm32h7/dma.h index 49eaba7..779a64c 100644 --- a/stm32h7/dmaInterrupts.h +++ b/stm32h7/dma.h @@ -1,18 +1,24 @@ -#ifndef FSFW_HAL_STM32H7_DMAINTERRUPTS_H_ -#define FSFW_HAL_STM32H7_DMAINTERRUPTS_H_ +#ifndef FSFW_HAL_STM32H7_DMA_H_ +#define FSFW_HAL_STM32H7_DMA_H_ #ifdef __cplusplus extern "C" { #endif #include "interrupts.h" +#include namespace dma { -enum DMAIndexes { - DMA_1 = 0, - DMA_2 = 1 -} ; +enum DMAType { + TX = 0, + RX = 1 +}; + +enum DMAIndexes: uint8_t { + DMA_1 = 1, + DMA_2 = 2 +}; enum DMAStreams { STREAM_0 = 0, @@ -40,4 +46,4 @@ void assignDmaUserHandler(DMAIndexes dma_idx, DMAStreams stream_idx, } #endif -#endif /* FSFW_HAL_STM32H7_DMAINTERRUPTS_H_ */ +#endif /* FSFW_HAL_STM32H7_DMA_H_ */ diff --git a/stm32h7/interrupts.h b/stm32h7/interrupts.h index 00c8a79..aef60bf 100644 --- a/stm32h7/interrupts.h +++ b/stm32h7/interrupts.h @@ -1,6 +1,8 @@ #ifndef FSFW_HAL_STM32H7_INTERRUPTS_H_ #define FSFW_HAL_STM32H7_INTERRUPTS_H_ +#include + #ifdef __cplusplus extern "C" { #endif @@ -13,6 +15,12 @@ extern void Default_Handler(); typedef void (*user_handler_t) (void*); typedef void* user_args_t; +enum IrqPriorities: uint8_t { + HIGHEST = 0, + HIGHEST_FREERTOS = 6, + LOWEST = 15 +}; + #ifdef __cplusplus } #endif diff --git a/stm32h7/spi/CMakeLists.txt b/stm32h7/spi/CMakeLists.txt index ba814e2..fb4f647 100644 --- a/stm32h7/spi/CMakeLists.txt +++ b/stm32h7/spi/CMakeLists.txt @@ -5,4 +5,5 @@ target_sources(${LIB_FSFW_HAL_NAME} PRIVATE mspInit.cpp SpiCookie.cpp SpiComIF.cpp + stm32h743ziSpi.cpp ) diff --git a/stm32h7/spi/SpiComIF.cpp b/stm32h7/spi/SpiComIF.cpp index b36a09e..6230c0c 100644 --- a/stm32h7/spi/SpiComIF.cpp +++ b/stm32h7/spi/SpiComIF.cpp @@ -83,8 +83,16 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { SPI_HandleTypeDef& spiHandle = spiCookie->getSpiHandle(); if(transferMode == spi::TransferModes::POLLING) { - spi::setSpiMspFunctions(&spi::halMspInitPolling, &spiHandle, - &spi::halMspDeinitPolling, &spiHandle); +// spi::setSpiMspFunctions(&spi::halMspInitPolling, &spiHandle, +// &spi::halMspDeinitPolling, &spiHandle); + } + else if(transferMode == spi::TransferModes::INTERRUPT) { +// spi::setSpiMspFunctions(&spi::halMspInitInterrupt, &spiHandle, +// &spi::halMspDeinitPolling, &spiHandle); + } + else if(transferMode == spi::TransferModes::DMA) { +// spi::setSpiMspFunctions(&spi::halMspInitDma, &spiHandle, +// &spi::halMspDeinitDma, &spiHandle); } gpio::initializeGpioClock(gpioPort); diff --git a/stm32h7/spi/mspInit.cpp b/stm32h7/spi/mspInit.cpp index 5e14e8a..ecf2a39 100644 --- a/stm32h7/spi/mspInit.cpp +++ b/stm32h7/spi/mspInit.cpp @@ -1,4 +1,4 @@ -#include +#include #include "mspInit.h" #include "spiConf.h" #include "spiCore.h" @@ -10,6 +10,12 @@ #include +spi::msp_func_t mspInitFunc = nullptr; +spi::MspCfgBase* mspInitArgs = nullptr; + +spi::msp_func_t mspDeinitFunc = nullptr; +spi::MspCfgBase* mspDeinitArgs = nullptr; + /** * @brief SPI MSP Initialization * This function configures the hardware resources used in this example: @@ -20,38 +26,44 @@ * @param hspi: SPI handle pointer * @retval None */ -void spi::halMspInitDma(void *spi_handle) { - SPI_HandleTypeDef* hspi = (SPI_HandleTypeDef*) spi_handle; - if(hspi == NULL) { - return; - } - if(hspi == NULL) { - printf("HAL_SPI_MspInit: Invalid SPI handle!\n"); +void spi::halMspInitDma(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { + auto cfg = dynamic_cast(cfgBase); + if(hspi == nullptr or cfg == nullptr) { return; } setSpiHandle(hspi); - DMA_HandleTypeDef* hdma_tx = NULL; - DMA_HandleTypeDef* hdma_rx = NULL; + DMA_HandleTypeDef* hdma_tx = nullptr; + DMA_HandleTypeDef* hdma_rx = nullptr; spi::getDmaHandles(&hdma_tx, &hdma_rx); if(hdma_tx == NULL || hdma_rx == NULL) { printf("HAL_SPI_MspInit: Invalid DMA handles. Make sure to call setDmaHandles!\n"); return; } - spi::halMspInitPolling(spi_handle); - if (hspi->Instance == SPI1) { - // DMA setup - DMAx_CLK_ENABLE(); + spi::halMspInitInterrupt(hspi, cfg); - // Configure the DMA - /* Configure the DMA handler for Transmission process */ + // DMA setup + if(cfg->dmaClkEnableWrapper == nullptr) { + mspErrorHandler("spi::halMspInitDma", "DMA Clock init invalid"); + } + cfg->dmaClkEnableWrapper(); + + // Configure the DMA + /* Configure the DMA handler for Transmission process */ + if(hdma_tx->Instance == nullptr) { + // Assume it was not configured properly + mspErrorHandler("spi::halMspInitDma", "DMA TX handle invalid"); + } hdma_tx->Instance = SPIx_TX_DMA_STREAM; + + hdma_tx->Init.Request = SPIx_TX_DMA_REQUEST; + + // offer function to configure this.. hdma_tx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; hdma_tx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_tx->Init.MemBurst = DMA_MBURST_INC4; hdma_tx->Init.PeriphBurst = DMA_PBURST_INC4; - hdma_tx->Init.Request = SPIx_TX_DMA_REQUEST; hdma_tx->Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_tx->Init.PeriphInc = DMA_PINC_DISABLE; hdma_tx->Init.MemInc = DMA_MINC_ENABLE; @@ -60,53 +72,204 @@ void spi::halMspInitDma(void *spi_handle) { hdma_tx->Init.Mode = DMA_NORMAL; hdma_tx->Init.Priority = DMA_PRIORITY_LOW; - HAL_DMA_Init(hdma_tx); + HAL_DMA_Init(hdma_tx); - /* Associate the initialized DMA handle to the the SPI handle */ - __HAL_LINKDMA(hspi, hdmatx, *hdma_tx); + /* Associate the initialized DMA handle to the the SPI handle */ + __HAL_LINKDMA(hspi, hdmatx, *hdma_tx); - /* Configure the DMA handler for Transmission process */ - hdma_rx->Instance = SPIx_RX_DMA_STREAM; + /* Configure the DMA handler for Transmission process */ + hdma_rx->Instance = SPIx_RX_DMA_STREAM; - hdma_rx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; - hdma_rx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - hdma_rx->Init.MemBurst = DMA_MBURST_INC4; - hdma_rx->Init.PeriphBurst = DMA_PBURST_INC4; - hdma_rx->Init.Request = SPIx_RX_DMA_REQUEST; - hdma_rx->Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_rx->Init.PeriphInc = DMA_PINC_DISABLE; - hdma_rx->Init.MemInc = DMA_MINC_ENABLE; - hdma_rx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - hdma_rx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - hdma_rx->Init.Mode = DMA_NORMAL; - hdma_rx->Init.Priority = DMA_PRIORITY_HIGH; + hdma_rx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_rx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_rx->Init.MemBurst = DMA_MBURST_INC4; + hdma_rx->Init.PeriphBurst = DMA_PBURST_INC4; + hdma_rx->Init.Request = SPIx_RX_DMA_REQUEST; + hdma_rx->Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_rx->Init.PeriphInc = DMA_PINC_DISABLE; + hdma_rx->Init.MemInc = DMA_MINC_ENABLE; + hdma_rx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_rx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_rx->Init.Mode = DMA_NORMAL; + hdma_rx->Init.Priority = DMA_PRIORITY_HIGH; - HAL_DMA_Init(hdma_rx); + HAL_DMA_Init(hdma_rx); - /* Associate the initialized DMA handle to the the SPI handle */ - __HAL_LINKDMA(hspi, hdmarx, *hdma_rx); + /* Associate the initialized DMA handle to the the SPI handle */ + __HAL_LINKDMA(hspi, hdmarx, *hdma_rx); - /*##-4- Configure the NVIC for DMA #########################################*/ - /* NVIC configuration for DMA transfer complete interrupt (SPI1_RX) */ - // Assign the interrupt handler - dma::assignDmaUserHandler(dma::DMAIndexes::DMA_2, dma::DMAStreams::STREAM_2, - &spi::dmaRxIrqHandler, hdma_rx); - HAL_NVIC_SetPriority(SPIx_DMA_RX_IRQn, 1, 0); - HAL_NVIC_EnableIRQ(SPIx_DMA_RX_IRQn); + /*##-4- Configure the NVIC for DMA #########################################*/ + /* NVIC configuration for DMA transfer complete interrupt (SPI1_RX) */ + // Assign the interrupt handler + dma::assignDmaUserHandler(cfg->rxDmaIndex, cfg->rxDmaStream, &spi::dmaRxIrqHandler, hdma_rx); + HAL_NVIC_SetPriority(cfg->rxDmaIrqNumber, cfg->rxPreEmptPriority, cfg->rxSubpriority); + HAL_NVIC_EnableIRQ(cfg->rxDmaIrqNumber); - /* NVIC configuration for DMA transfer complete interrupt (SPI1_TX) */ - // Assign the interrupt handler - dma::assignDmaUserHandler(dma::DMAIndexes::DMA_2, dma::DMAStreams::STREAM_3, - &spi::dmaTxIrqHandler, hdma_tx); - HAL_NVIC_SetPriority(SPIx_DMA_TX_IRQn, 1, 1); - HAL_NVIC_EnableIRQ(SPIx_DMA_TX_IRQn); + /* NVIC configuration for DMA transfer complete interrupt (SPI1_TX) */ + // Assign the interrupt handler + dma::assignDmaUserHandler(cfg->txDmaIndex, cfg->txDmaStream, + &spi::dmaTxIrqHandler, hdma_tx); + HAL_NVIC_SetPriority(cfg->txDmaIrqNumber, cfg->txPreEmptPriority, cfg->txSubpriority); + HAL_NVIC_EnableIRQ(cfg->txDmaIrqNumber); - /*##-5- Configure the NVIC for SPI #########################################*/ - /* NVIC configuration for SPI transfer complete interrupt (SPI1) */ - // Assign the interrupt handler - spi::assignSpiUserHandler(spi::SPI_1, &spi::spi1IrqHandler, hspi); - HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0); - HAL_NVIC_EnableIRQ(SPIx_IRQn); + /*##-5- Configure the NVIC for SPI #########################################*/ + /* NVIC configuration for SPI transfer complete interrupt (SPI1) */ + // Assign the interrupt handler + spi::assignSpiUserHandler(spi::SPI_1, &spi::spiIrqHandler, hspi); + HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(SPIx_IRQn); + +} + +/** + * @brief SPI MSP De-Initialization + * This function frees the hardware resources used in this example: + * - Disable the Peripheral's clock + * - Revert GPIO, DMA and NVIC configuration to their default state + * @param hspi: SPI handle pointer + * @retval None + */ +void spi::halMspDeinitDma(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { + auto cfg = dynamic_cast(cfgBase); + if(hspi == nullptr or cfg == nullptr) { + return; + } + spi::halMspDeinitInterrupt(hspi, cfgBase); + DMA_HandleTypeDef* hdma_tx = NULL; + DMA_HandleTypeDef* hdma_rx = NULL; + spi::getDmaHandles(&hdma_tx, &hdma_rx); + if(hdma_tx == NULL || hdma_rx == NULL) { + printf("HAL_SPI_MspInit: Invalid DMA handles. Make sure to call setDmaHandles!\n"); + } + else { + // Disable the DMA + /* De-Initialize the DMA associated to transmission process */ + HAL_DMA_DeInit(hdma_tx); + /* De-Initialize the DMA associated to reception process */ + HAL_DMA_DeInit(hdma_rx); + } + + // Disable the NVIC for DMA + HAL_NVIC_DisableIRQ(cfg->txDmaIrqNumber); + HAL_NVIC_DisableIRQ(cfg->rxDmaIrqNumber); + +} + +void spi::halMspInitPolling(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { + auto cfg = dynamic_cast(cfgBase); + GPIO_InitTypeDef GPIO_InitStruct = {}; + /*##-1- Enable peripherals and GPIO Clocks #################################*/ + /* Enable GPIO TX/RX clock */ + cfg->setupMacroWrapper(); + + /*##-2- Configure peripheral GPIO ##########################################*/ + /* SPI SCK GPIO pin configuration */ + GPIO_InitStruct.Pin = cfg->sckPin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = cfg->sckAlternateFunction; + HAL_GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStruct); + + /* SPI MISO GPIO pin configuration */ + GPIO_InitStruct.Pin = cfg->misoPin; + GPIO_InitStruct.Alternate = cfg->misoAlternateFunction; + HAL_GPIO_Init(cfg->misoPort, &GPIO_InitStruct); + + /* SPI MOSI GPIO pin configuration */ + GPIO_InitStruct.Pin = cfg->mosiPin; + GPIO_InitStruct.Alternate = cfg->mosiAlternateFunction; + HAL_GPIO_Init(cfg->mosiPort, &GPIO_InitStruct); +} + +void spi::halMspDeinitPolling(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { + auto cfg = reinterpret_cast(cfgBase); + // Reset peripherals + cfg->cleanUpMacroWrapper(); + + // Disable peripherals and GPIO Clocks + /* Configure SPI SCK as alternate function */ + HAL_GPIO_DeInit(cfg->sckPort, cfg->sckPin); + /* Configure SPI MISO as alternate function */ + HAL_GPIO_DeInit(cfg->misoPort, cfg->misoPin); + /* Configure SPI MOSI as alternate function */ + HAL_GPIO_DeInit(cfg->mosiPort, cfg->mosiPin); +} + +void spi::halMspInitInterrupt(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { + auto cfg = dynamic_cast(cfgBase); + if(cfg == nullptr or hspi == nullptr) { + return; + } + + spi::halMspInitPolling(hspi, cfg); + // Configure the NVIC for SPI + spi::assignSpiUserHandler(cfg->spiBus, cfg->spiIrqHandler, cfg->spiUserArgs); + HAL_NVIC_SetPriority(cfg->spiIrqNumber, cfg->preEmptPriority, cfg->subpriority); + HAL_NVIC_EnableIRQ(cfg->spiIrqNumber); +} + +void spi::halMspDeinitInterrupt(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { + auto cfg = dynamic_cast(cfgBase); + spi::halMspDeinitPolling(hspi, cfg); + // Disable the NVIC for SPI + HAL_NVIC_DisableIRQ(cfg->spiIrqNumber); +} + +void spi::getMspInitFunction(msp_func_t* init_func, MspCfgBase** args) { + if(init_func != NULL && args != NULL) { + *init_func = mspInitFunc; + *args = mspInitArgs; + } +} + +void spi::getMspDeinitFunction(msp_func_t* deinit_func, MspCfgBase** args) { + if(deinit_func != NULL && args != NULL) { + *deinit_func = mspDeinitFunc; + *args = mspDeinitArgs; + } +} + +void spi::setSpiDmaMspFunctions(MspDmaConfigStruct* cfg, + msp_func_t initFunc, msp_func_t deinitFunc) { + mspInitFunc = initFunc; + mspDeinitFunc = deinitFunc; + mspInitArgs = cfg; + mspDeinitArgs = cfg; +} + +void spi::setSpiIrqMspFunctions(MspIrqConfigStruct *cfg, msp_func_t initFunc, + msp_func_t deinitFunc) { + mspInitFunc = initFunc; + mspDeinitFunc = deinitFunc; + mspInitArgs = cfg; + mspDeinitArgs = cfg; +} + +void spi::setSpiPollingMspFunctions(MspPollingConfigStruct *cfg, msp_func_t initFunc, + msp_func_t deinitFunc) { + mspInitFunc = initFunc; + mspDeinitFunc = deinitFunc; + mspInitArgs = cfg; + mspDeinitArgs = cfg; +} + +/** + * @brief SPI MSP Initialization + * This function configures the hardware resources used in this example: + * - Peripheral's clock enable + * - Peripheral's GPIO Configuration + * - DMA configuration for transmission request by peripheral + * - NVIC configuration for DMA interrupt request enable + * @param hspi: SPI handle pointer + * @retval None + */ +extern "C" void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) { + if(mspInitFunc != NULL) { + mspInitFunc(hspi, mspInitArgs); + } + else { + printf("HAL_SPI_MspInit: Please call set_msp_functions to assign SPI MSP functions\n"); } } @@ -118,91 +281,15 @@ void spi::halMspInitDma(void *spi_handle) { * @param hspi: SPI handle pointer * @retval None */ -void spi::halMspDeinitDma(void *spi_handle) -{ - SPI_HandleTypeDef* hspi = (SPI_HandleTypeDef*) spi_handle; - if(hspi == NULL) { - return; +extern "C" void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) { + if(mspDeinitFunc != NULL) { + mspDeinitFunc(hspi, mspDeinitArgs); } - spi::halMspDeinitPolling(spi_handle); - if(hspi->Instance == SPIx) { - DMA_HandleTypeDef* hdma_tx = NULL; - DMA_HandleTypeDef* hdma_rx = NULL; - spi::getDmaHandles(&hdma_tx, &hdma_rx); - if(hdma_tx == NULL || hdma_rx == NULL) { - printf("HAL_SPI_MspInit: Invalid DMA handles. Make sure to call setDmaHandles!\n"); - } - else { - /*##-3- Disable the DMA ####################################################*/ - /* De-Initialize the DMA associated to transmission process */ - HAL_DMA_DeInit(hdma_tx); - /* De-Initialize the DMA associated to reception process */ - HAL_DMA_DeInit(hdma_rx); - } - - /*##-4- Disable the NVIC for DMA ###########################################*/ - HAL_NVIC_DisableIRQ(SPIx_DMA_TX_IRQn); - HAL_NVIC_DisableIRQ(SPIx_DMA_RX_IRQn); - - /*##-5- Disable the NVIC for SPI ###########################################*/ - HAL_NVIC_EnableIRQ(SPIx_IRQn); + else { + printf("HAL_SPI_MspDeInit: Please call set_msp_functions to assign SPI MSP functions\n"); } } -void spi::halMspInitPolling(void *hspi) { - GPIO_InitTypeDef GPIO_InitStruct = {}; - /*##-1- Enable peripherals and GPIO Clocks #################################*/ - /* Enable GPIO TX/RX clock */ - SPIx_SCK_GPIO_CLK_ENABLE(); - SPIx_MISO_GPIO_CLK_ENABLE(); - SPIx_MOSI_GPIO_CLK_ENABLE(); - /* Enable SPI clock */ - SPIx_CLK_ENABLE(); - - /*##-2- Configure peripheral GPIO ##########################################*/ - /* SPI SCK GPIO pin configuration */ - GPIO_InitStruct.Pin = SPIx_SCK_PIN; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_PULLDOWN; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = SPIx_SCK_AF; - HAL_GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStruct); - - /* SPI MISO GPIO pin configuration */ - GPIO_InitStruct.Pin = SPIx_MISO_PIN; - GPIO_InitStruct.Alternate = SPIx_MISO_AF; - HAL_GPIO_Init(SPIx_MISO_GPIO_PORT, &GPIO_InitStruct); - - /* SPI MOSI GPIO pin configuration */ - GPIO_InitStruct.Pin = SPIx_MOSI_PIN; - GPIO_InitStruct.Alternate = SPIx_MOSI_AF; - HAL_GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStruct); -} - -void spi::halMspDeinitPolling(void *hspi) { - /*##-1- Reset peripherals ##################################################*/ - SPIx_FORCE_RESET(); - SPIx_RELEASE_RESET(); - - /*##-2- Disable peripherals and GPIO Clocks ################################*/ - /* Configure SPI SCK as alternate function */ - HAL_GPIO_DeInit(SPIx_SCK_GPIO_PORT, SPIx_SCK_PIN); - /* Configure SPI MISO as alternate function */ - HAL_GPIO_DeInit(SPIx_MISO_GPIO_PORT, SPIx_MISO_PIN); - /* Configure SPI MOSI as alternate function */ - HAL_GPIO_DeInit(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_PIN); -} - -void spi::halMspInitInterrupt(void *hspi) { - spi::halMspInitPolling(hspi); - // Configure the NVIC for SPI - spi::assignSpiUserHandler(spi::SPI_1, &spi::spi1IrqHandler, hspi); - HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0); - HAL_NVIC_EnableIRQ(SPIx_IRQn); -} - -void spi::halMspDeinitInterrupt(void *hspi) { - spi::halMspDeinitPolling(hspi); - // Disable the NVIC for SPI - HAL_NVIC_DisableIRQ(SPIx_IRQn); +void spi::mspErrorHandler(const char* const function, const char *const message) { + printf("%s failure: %s\n", function, message); } diff --git a/stm32h7/spi/mspInit.h b/stm32h7/spi/mspInit.h index fb350ca..b4e900a 100644 --- a/stm32h7/spi/mspInit.h +++ b/stm32h7/spi/mspInit.h @@ -1,20 +1,103 @@ #ifndef FSFW_HAL_STM32H7_SPI_MSPINIT_H_ #define FSFW_HAL_STM32H7_SPI_MSPINIT_H_ +#include "spiDefinitions.h" +#include "../dma.h" +#include "stm32h7xx_hal_spi.h" + +#include + #ifdef __cplusplus extern "C" { #endif namespace spi { -void halMspInitDma(void *hspi); -void halMspDeinitDma(void *hspi); +struct MspCfgBase { + virtual ~MspCfgBase() = default; -void halMspInitPolling(void *hspi); -void halMspDeinitPolling(void *hspi); + void (* cleanUpMacroWrapper) (void) = nullptr; + void (* setupMacroWrapper) (void) = nullptr; -void halMspInitInterrupt(void *hspi); -void halMspDeinitInterrupt(void *hspi); + GPIO_TypeDef* sckPort = nullptr; + uint32_t sckPin = 0; + uint8_t sckAlternateFunction = 0; + GPIO_TypeDef* mosiPort = nullptr; + uint32_t mosiPin = 0; + uint8_t mosiAlternateFunction = 0; + GPIO_TypeDef* misoPort = nullptr; + uint32_t misoPin = 0; + uint8_t misoAlternateFunction = 0; +}; + +struct MspPollingConfigStruct: public MspCfgBase {}; + +/* A valid instance of this struct must be passed to the MSP initialization function as a void* +argument */ +struct MspIrqConfigStruct: public MspPollingConfigStruct { + SpiBus spiBus = SpiBus::SPI_1; + user_handler_t spiIrqHandler = nullptr; + user_args_t spiUserArgs = nullptr; + IRQn_Type spiIrqNumber = SPI1_IRQn; + // Priorities for NVIC + // Pre-Empt priority ranging from 0 to 15. If FreeRTOS calls are used, only 5-15 are allowed + IrqPriorities preEmptPriority = IrqPriorities::LOWEST; + IrqPriorities subpriority = IrqPriorities::LOWEST; +}; + +/* A valid instance of this struct must be passed to the MSP initialization function as a void* +argument */ +struct MspDmaConfigStruct: public MspIrqConfigStruct { + void (* dmaClkEnableWrapper) (void) = nullptr; + dma::DMAIndexes txDmaIndex; + dma::DMAIndexes rxDmaIndex; + dma::DMAStreams txDmaStream; + dma::DMAStreams rxDmaStream; + IRQn_Type txDmaIrqNumber = DMA1_Stream0_IRQn; + IRQn_Type rxDmaIrqNumber = DMA1_Stream1_IRQn; + // Priorities for NVIC + IrqPriorities txPreEmptPriority = IrqPriorities::LOWEST; + IrqPriorities rxPreEmptPriority = IrqPriorities::LOWEST; + IrqPriorities txSubpriority = IrqPriorities::LOWEST; + IrqPriorities rxSubpriority = IrqPriorities::LOWEST; +}; + +using msp_func_t = void (*) (SPI_HandleTypeDef* hspi, MspCfgBase* cfg); + + +void getMspInitFunction(msp_func_t* init_func, MspCfgBase **args); +void getMspDeinitFunction(msp_func_t* deinit_func, MspCfgBase **args); + +void halMspInitDma(SPI_HandleTypeDef* hspi, MspCfgBase* cfg); +void halMspDeinitDma(SPI_HandleTypeDef* hspi, MspCfgBase* cfg); + +void halMspInitInterrupt(SPI_HandleTypeDef* hspi, MspCfgBase* cfg); +void halMspDeinitInterrupt(SPI_HandleTypeDef* hspi, MspCfgBase* cfg); + +void halMspInitPolling(SPI_HandleTypeDef* hspi, MspCfgBase* cfg); +void halMspDeinitPolling(SPI_HandleTypeDef* hspi, MspCfgBase* cfg); + +/** + * Assign MSP init functions. Important for SPI configuration + * @param init_func + * @param init_args + * @param deinit_func + * @param deinit_args + */ +void setSpiDmaMspFunctions(MspDmaConfigStruct* cfg, + msp_func_t initFunc = &spi::halMspInitDma, + msp_func_t deinitFunc= &spi::halMspDeinitDma +); +void setSpiIrqMspFunctions(MspIrqConfigStruct* cfg, + msp_func_t initFunc = &spi::halMspInitInterrupt, + msp_func_t deinitFunc= &spi::halMspDeinitInterrupt +); +void setSpiPollingMspFunctions(MspPollingConfigStruct* cfg, + msp_func_t initFunc = &spi::halMspInitPolling, + msp_func_t deinitFunc= &spi::halMspDeinitPolling +); + +void mspErrorHandler(const char* const function, const char *const message); } diff --git a/stm32h7/spi/spiCore.cpp b/stm32h7/spi/spiCore.cpp index dd91f2d..1afbb84 100644 --- a/stm32h7/spi/spiCore.cpp +++ b/stm32h7/spi/spiCore.cpp @@ -5,12 +5,6 @@ SPI_HandleTypeDef* spiHandle = nullptr; DMA_HandleTypeDef* hdmaTx = nullptr; DMA_HandleTypeDef* hdmaRx = nullptr; -msp_func_t mspInitFunc = nullptr; -void* mspInitArgs = nullptr; - -msp_func_t mspDeinitFunc = nullptr; -void* mspDeinitArgs = nullptr; - spi_transfer_cb_t rxTxCb = nullptr; void* rxTxArgs = nullptr; spi_transfer_cb_t txCb = nullptr; @@ -20,6 +14,200 @@ void* rxArgs = nullptr; spi_transfer_cb_t errorCb = nullptr; void* errorArgs = nullptr; +void spi::configureDmaHandle(DMA_HandleTypeDef *handle, dma::DMAType dmaType, + dma::DMAIndexes dmaIdx, dma::DMAStreams dmaStream, IRQn_Type* dmaIrqNumber, + uint32_t dmaMode, uint32_t dmaPriority) { + using namespace dma; + if(dmaIdx == DMAIndexes::DMA_1) { +#ifdef DMA1 + switch(dmaStream) { + case(DMAStreams::STREAM_0): { +#ifdef DMA1_Stream0 + handle->Instance = DMA1_Stream0; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream0_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_1): { +#ifdef DMA1_Stream1 + handle->Instance = DMA1_Stream1; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream1_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_2): { +#ifdef DMA1_Stream2 + handle->Instance = DMA1_Stream2; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream2_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_3): { +#ifdef DMA1_Stream3 + handle->Instance = DMA1_Stream3; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream3_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_4): { +#ifdef DMA1_Stream4 + handle->Instance = DMA1_Stream4; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream4_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_5): { +#ifdef DMA1_Stream5 + handle->Instance = DMA1_Stream5; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream5_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_6): { +#ifdef DMA1_Stream6 + handle->Instance = DMA1_Stream6; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream6_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_7): { +#ifdef DMA1_Stream7 + handle->Instance = DMA1_Stream7; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream7_IRQn; + } +#endif + break; + } + } + if(dmaType == DMAType::TX) { + handle->Init.Request = DMA_REQUEST_SPI1_TX; + } + else { + handle->Init.Request = DMA_REQUEST_SPI1_RX; + } +#endif /* DMA1 */ + } + if(dmaIdx == DMAIndexes::DMA_2) { +#ifdef DMA2 + switch(dmaStream) { + case(DMAStreams::STREAM_0): { +#ifdef DMA1_Stream0 + handle->Instance = DMA2_Stream0; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream0_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_1): { +#ifdef DMA1_Stream1 + handle->Instance = DMA2_Stream1; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream1_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_2): { +#ifdef DMA1_Stream2 + handle->Instance = DMA2_Stream2; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream2_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_3): { +#ifdef DMA1_Stream3 + handle->Instance = DMA2_Stream3; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream3_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_4): { +#ifdef DMA1_Stream4 + handle->Instance = DMA1_Stream4; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream4_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_5): { +#ifdef DMA1_Stream5 + handle->Instance = DMA1_Stream5; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream5_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_6): { +#ifdef DMA1_Stream6 + handle->Instance = DMA1_Stream6; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream6_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_7): { +#ifdef DMA1_Stream7 + handle->Instance = DMA1_Stream7; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream7_IRQn; + } +#endif + break; + } + } + if(dmaType == DMAType::TX) { + handle->Init.Request = DMA_REQUEST_SPI2_TX; + } + else { + handle->Init.Request = DMA_REQUEST_SPI2_RX; + } +#endif /* DMA2 */ + } + + if(dmaType == DMAType::TX) { + handle->Init.Direction = DMA_MEMORY_TO_PERIPH; + } + else { + handle->Init.Direction = DMA_PERIPH_TO_MEMORY; + } + + handle->Init.Priority = dmaPriority; + handle->Init.Mode = dmaMode; + + // Standard settings for the rest for now + handle->Init.FIFOMode = DMA_FIFOMODE_DISABLE; + handle->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + handle->Init.MemBurst = DMA_MBURST_INC4; + handle->Init.PeriphBurst = DMA_PBURST_INC4; + handle->Init.PeriphInc = DMA_PINC_DISABLE; + handle->Init.MemInc = DMA_MINC_ENABLE; + handle->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + handle->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; +} + void spi::setDmaHandles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle) { hdmaTx = txHandle; hdmaRx = rxHandle; @@ -61,63 +249,7 @@ SPI_HandleTypeDef* spi::getSpiHandle() { return spiHandle; } -void spi::setSpiMspFunctions(msp_func_t init_func, void* init_args, msp_func_t deinit_func, - void* deinit_args) { - mspInitFunc = init_func; - mspInitArgs = init_args; - mspDeinitFunc = deinit_func; - mspDeinitArgs = deinit_args; -} -void spi::getMspInitFunction(msp_func_t* init_func, void **args) { - if(init_func != NULL && args != NULL) { - *init_func = mspInitFunc; - *args = mspInitArgs; - } -} - -void spi::getMspDeinitFunction(msp_func_t* deinit_func, void **args) { - if(deinit_func != NULL && args != NULL) { - *deinit_func = mspDeinitFunc; - *args = mspDeinitArgs; - } -} - -/** - * @brief SPI MSP Initialization - * This function configures the hardware resources used in this example: - * - Peripheral's clock enable - * - Peripheral's GPIO Configuration - * - DMA configuration for transmission request by peripheral - * - NVIC configuration for DMA interrupt request enable - * @param hspi: SPI handle pointer - * @retval None - */ -extern "C" void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) { - if(mspInitFunc != NULL) { - mspInitFunc(mspInitArgs); - } - else { - printf("HAL_SPI_MspInit: Please call set_msp_functions to assign SPI MSP functions\n"); - } -} - -/** - * @brief SPI MSP De-Initialization - * This function frees the hardware resources used in this example: - * - Disable the Peripheral's clock - * - Revert GPIO, DMA and NVIC configuration to their default state - * @param hspi: SPI handle pointer - * @retval None - */ -extern "C" void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) { - if(mspDeinitFunc != NULL) { - mspDeinitFunc(mspDeinitArgs); - } - else { - printf("HAL_SPI_MspDeInit: Please call set_msp_functions to assign SPI MSP functions\n"); - } -} /** * @brief TxRx Transfer completed callback. @@ -173,4 +305,3 @@ extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { printf("HAL_SPI_ErrorCallback: No user callback specified\n"); } } - diff --git a/stm32h7/spi/spiCore.h b/stm32h7/spi/spiCore.h index 3d3039a..5af3558 100644 --- a/stm32h7/spi/spiCore.h +++ b/stm32h7/spi/spiCore.h @@ -1,27 +1,22 @@ #ifndef FSFW_HAL_STM32H7_SPI_SPICORE_H_ #define FSFW_HAL_STM32H7_SPI_SPICORE_H_ +#include #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_dma.h" + #ifdef __cplusplus extern "C" { #endif -using msp_func_t = void (*) (void* args); using spi_transfer_cb_t = void (*) (SPI_HandleTypeDef *hspi, void* userArgs); namespace spi { -/** - * Assign MSP init functions. Important for SPI configuration - * @param init_func - * @param init_args - * @param deinit_func - * @param deinit_args - */ -void setSpiMspFunctions(msp_func_t init_func, void* init_args, msp_func_t deinit_func, - void* deinit_args); +void configureDmaHandle(DMA_HandleTypeDef* Handle, dma::DMAType dmaType, dma::DMAIndexes dmaIdx, + dma::DMAStreams dmaStream, IRQn_Type* dmaIrqNumber, uint32_t dmaMode = DMA_NORMAL, + uint32_t dmaPriority = DMA_PRIORITY_LOW); /** * Assign DMA handles. Required to use DMA for SPI transfers. @@ -31,9 +26,6 @@ void setSpiMspFunctions(msp_func_t init_func, void* init_args, msp_func_t deinit void setDmaHandles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle); void getDmaHandles(DMA_HandleTypeDef** txHandle, DMA_HandleTypeDef** rxHandle); -void getMspInitFunction(msp_func_t* init_func, void **args); -void getMspDeinitFunction(msp_func_t* deinit_func, void **args); - /** * Assign SPI handle. Needs to be done before using the SPI * @param spiHandle diff --git a/stm32h7/spi/spiInterrupts.cpp b/stm32h7/spi/spiInterrupts.cpp index fe5700b..74930e5 100644 --- a/stm32h7/spi/spiInterrupts.cpp +++ b/stm32h7/spi/spiInterrupts.cpp @@ -1,4 +1,5 @@ #include "spiInterrupts.h" +#include "spiCore.h" #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_dma.h" @@ -6,10 +7,10 @@ #include -user_handler_t spi1UserHandler = nullptr; +user_handler_t spi1UserHandler = &spi::spiIrqHandler; user_args_t spi1UserArgs = nullptr; -user_handler_t spi2UserHandler = nullptr; +user_handler_t spi2UserHandler = &spi::spiIrqHandler; user_args_t spi2UserArgs = nullptr; /** @@ -35,9 +36,10 @@ void spi::dmaTxIrqHandler(void* dmaHandle) { * @param None * @retval None */ -void spi::spi1IrqHandler(void* spiHandle) +void spi::spiIrqHandler(void* spiHandle) { - HAL_SPI_IRQHandler((SPI_HandleTypeDef *) spiHandle); + auto currentSpiHandle = spi::getSpiHandle(); + HAL_SPI_IRQHandler((SPI_HandleTypeDef *) currentSpiHandle); } void spi::assignSpiUserHandler(spi::SpiBus spiIdx, user_handler_t userHandler, @@ -52,6 +54,30 @@ void spi::assignSpiUserHandler(spi::SpiBus spiIdx, user_handler_t userHandler, } } +void spi::getSpiUserHandler(spi::SpiBus spiBus, user_handler_t *userHandler, + user_args_t *userArgs) { + if(userHandler == nullptr or userArgs == nullptr) { + return; + } + if(spiBus == spi::SpiBus::SPI_1) { + *userArgs = spi1UserArgs; + *userHandler = spi1UserHandler; + } + else { + *userArgs = spi2UserArgs; + *userHandler = spi2UserHandler; + } +} + +void assignSpiUserArgs(spi::SpiBus spiBus, user_args_t userArgs) { + if(spiBus == spi::SpiBus::SPI_1) { + spi1UserArgs = userArgs; + } + else { + spi2UserArgs = userArgs; + } +} + /* Do not change these function names! They need to be exactly equal to the name of the functions defined in the startup_stm32h743xx.s files! */ @@ -70,5 +96,3 @@ extern "C" void SPI2_IRQHandler() { } Default_Handler(); } - - diff --git a/stm32h7/spi/spiInterrupts.h b/stm32h7/spi/spiInterrupts.h index abfc68e..0b53f48 100644 --- a/stm32h7/spi/spiInterrupts.h +++ b/stm32h7/spi/spiInterrupts.h @@ -10,6 +10,8 @@ extern "C" { namespace spi { +void assignSpiUserArgs(spi::SpiBus spiBus, user_args_t userArgs); + /** * Assign a user interrupt handler for SPI bus 1, allowing to pass an arbitrary argument as well. * Generally, this argument will be the related SPI handle. @@ -18,6 +20,8 @@ namespace spi { */ void assignSpiUserHandler(spi::SpiBus spiBus, user_handler_t user_handler, user_args_t user_args); +void getSpiUserHandler(spi::SpiBus spiBus, user_handler_t* user_handler, + user_args_t* user_args); /** * Generic interrupt handlers supplied for convenience. Do not call these directly! Set them @@ -26,7 +30,7 @@ void assignSpiUserHandler(spi::SpiBus spiBus, user_handler_t user_handler, */ void dmaRxIrqHandler(void* dma_handle); void dmaTxIrqHandler(void* dma_handle); -void spi1IrqHandler(void* spi_handle); +void spiIrqHandler(void* spi_handle); } diff --git a/stm32h7/spi/stm32h743ziSpi.cpp b/stm32h7/spi/stm32h743ziSpi.cpp new file mode 100644 index 0000000..3ff4d2b --- /dev/null +++ b/stm32h7/spi/stm32h743ziSpi.cpp @@ -0,0 +1,81 @@ +#include "stm32h743ziSpi.h" +#include "spiCore.h" +#include "spiInterrupts.h" +#include "stm32h7xx_hal.h" +#include "stm32h7xx_hal_rcc.h" + +#include + +void spiSetupWrapper() { + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_SPI1_CLK_ENABLE(); +} + +void spiCleanUpWrapper() { + __HAL_RCC_SPI1_FORCE_RESET(); + __HAL_RCC_SPI1_RELEASE_RESET(); +} + +void spiDmaClockEnableWrapper() { + __HAL_RCC_SPI1_CLK_ENABLE(); +} + +void spi::h743zi::standardPollingCfg(MspPollingConfigStruct& cfg) { + cfg.setupMacroWrapper = &spiSetupWrapper; + cfg.cleanUpMacroWrapper = &spiCleanUpWrapper; + cfg.sckPort = GPIOA; + cfg.sckPin = GPIO_PIN_5; + cfg.misoPort = GPIOA; + cfg.misoPin = GPIO_PIN_6; + cfg.mosiPort = GPIOA; + cfg.mosiPin = GPIO_PIN_7; + cfg.sckAlternateFunction = GPIO_AF5_SPI1; + cfg.mosiAlternateFunction = GPIO_AF5_SPI1; + cfg.misoAlternateFunction = GPIO_AF5_SPI1; +} + +void spi::h743zi::standardInterruptCfg(MspIrqConfigStruct& cfg, IrqPriorities spiIrqPrio, + IrqPriorities spiSubprio) { + // High, but works on FreeRTOS as well (priorities range from 0 to 15) + cfg.preEmptPriority = spiIrqPrio; + cfg.subpriority = spiSubprio; + cfg.spiIrqNumber = SPI1_IRQn; + cfg.spiBus = SpiBus::SPI_1; + user_handler_t spiUserHandler = nullptr; + user_args_t spiUserArgs = nullptr; + getSpiUserHandler(spi::SpiBus::SPI_1, &spiUserHandler, &spiUserArgs); + if(spiUserHandler == nullptr) { + printf("spi::h743zi::standardInterruptCfg: Invalid SPI user handlers\n"); + return; + } + cfg.spiUserArgs = spiUserArgs; + cfg.spiIrqHandler = spiUserHandler; + standardPollingCfg(cfg); +} + +void spi::h743zi::standardDmaCfg(MspDmaConfigStruct& cfg, IrqPriorities spiIrqPrio, + IrqPriorities txIrqPrio, IrqPriorities rxIrqPrio, IrqPriorities spiSubprio, + IrqPriorities txSubprio, IrqPriorities rxSubprio) { + cfg.dmaClkEnableWrapper = &spiDmaClockEnableWrapper; + cfg.rxDmaIndex = dma::DMAIndexes::DMA_1; + cfg.txDmaIndex = dma::DMAIndexes::DMA_1; + cfg.txDmaStream = dma::DMAStreams::STREAM_3; + cfg.rxDmaStream = dma::DMAStreams::STREAM_2; + DMA_HandleTypeDef* txHandle; + DMA_HandleTypeDef* rxHandle; + spi::getDmaHandles(&txHandle, &rxHandle); + if(txHandle == nullptr or rxHandle == nullptr) { + printf("spi::h743zi::standardDmaCfg: Invalid DMA handles"); + return; + } + spi::configureDmaHandle(txHandle, dma::DMAType::TX, cfg.txDmaIndex, cfg.txDmaStream, + &cfg.txDmaIrqNumber); + spi::configureDmaHandle(rxHandle, dma::DMAType::RX, cfg.rxDmaIndex, cfg.rxDmaStream, + &cfg.rxDmaIrqNumber); + cfg.txPreEmptPriority = txIrqPrio; + cfg.rxPreEmptPriority = txSubprio; + cfg.txSubpriority = rxIrqPrio; + cfg.rxSubpriority = rxSubprio; + standardInterruptCfg(cfg, spiIrqPrio, spiSubprio); +} diff --git a/stm32h7/spi/stm32h743ziSpi.h b/stm32h7/spi/stm32h743ziSpi.h new file mode 100644 index 0000000..87689ad --- /dev/null +++ b/stm32h7/spi/stm32h743ziSpi.h @@ -0,0 +1,23 @@ +#ifndef FSFW_HAL_STM32H7_SPI_STM32H743ZISPI_H_ +#define FSFW_HAL_STM32H7_SPI_STM32H743ZISPI_H_ + +#include "mspInit.h" + +namespace spi { + +namespace h743zi { + +void standardPollingCfg(MspPollingConfigStruct& cfg); +void standardInterruptCfg(MspIrqConfigStruct& cfg, IrqPriorities spiIrqPrio, + IrqPriorities spiSubprio = HIGHEST); +void standardDmaCfg(MspDmaConfigStruct& cfg, IrqPriorities spiIrqPrio, + IrqPriorities txIrqPrio, IrqPriorities rxIrqPrio, + IrqPriorities spiSubprio = HIGHEST, IrqPriorities txSubPrio = HIGHEST, + IrqPriorities rxSubprio = HIGHEST); + +} +} + + + +#endif /* FSFW_HAL_STM32H7_SPI_STM32H743ZISPI_H_ */ From 1611099cb2a6d86be56115124f25536280cc3936 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 10 Jun 2021 19:11:02 +0200 Subject: [PATCH 32/35] indentation --- stm32h7/spi/mspInit.cpp | 54 ++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/stm32h7/spi/mspInit.cpp b/stm32h7/spi/mspInit.cpp index ecf2a39..fa91825 100644 --- a/stm32h7/spi/mspInit.cpp +++ b/stm32h7/spi/mspInit.cpp @@ -55,22 +55,22 @@ void spi::halMspInitDma(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { // Assume it was not configured properly mspErrorHandler("spi::halMspInitDma", "DMA TX handle invalid"); } - hdma_tx->Instance = SPIx_TX_DMA_STREAM; + hdma_tx->Instance = SPIx_TX_DMA_STREAM; - hdma_tx->Init.Request = SPIx_TX_DMA_REQUEST; + hdma_tx->Init.Request = SPIx_TX_DMA_REQUEST; - // offer function to configure this.. - hdma_tx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; - hdma_tx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - hdma_tx->Init.MemBurst = DMA_MBURST_INC4; - hdma_tx->Init.PeriphBurst = DMA_PBURST_INC4; - hdma_tx->Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_tx->Init.PeriphInc = DMA_PINC_DISABLE; - hdma_tx->Init.MemInc = DMA_MINC_ENABLE; - hdma_tx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - hdma_tx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - hdma_tx->Init.Mode = DMA_NORMAL; - hdma_tx->Init.Priority = DMA_PRIORITY_LOW; + // offer function to configure this.. + hdma_tx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_tx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_tx->Init.MemBurst = DMA_MBURST_INC4; + hdma_tx->Init.PeriphBurst = DMA_PBURST_INC4; + hdma_tx->Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_tx->Init.PeriphInc = DMA_PINC_DISABLE; + hdma_tx->Init.MemInc = DMA_MINC_ENABLE; + hdma_tx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_tx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_tx->Init.Mode = DMA_NORMAL; + hdma_tx->Init.Priority = DMA_PRIORITY_LOW; HAL_DMA_Init(hdma_tx); @@ -78,20 +78,20 @@ void spi::halMspInitDma(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { __HAL_LINKDMA(hspi, hdmatx, *hdma_tx); /* Configure the DMA handler for Transmission process */ - hdma_rx->Instance = SPIx_RX_DMA_STREAM; + hdma_rx->Instance = SPIx_RX_DMA_STREAM; - hdma_rx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; - hdma_rx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - hdma_rx->Init.MemBurst = DMA_MBURST_INC4; - hdma_rx->Init.PeriphBurst = DMA_PBURST_INC4; - hdma_rx->Init.Request = SPIx_RX_DMA_REQUEST; - hdma_rx->Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_rx->Init.PeriphInc = DMA_PINC_DISABLE; - hdma_rx->Init.MemInc = DMA_MINC_ENABLE; - hdma_rx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - hdma_rx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - hdma_rx->Init.Mode = DMA_NORMAL; - hdma_rx->Init.Priority = DMA_PRIORITY_HIGH; + hdma_rx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_rx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_rx->Init.MemBurst = DMA_MBURST_INC4; + hdma_rx->Init.PeriphBurst = DMA_PBURST_INC4; + hdma_rx->Init.Request = SPIx_RX_DMA_REQUEST; + hdma_rx->Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_rx->Init.PeriphInc = DMA_PINC_DISABLE; + hdma_rx->Init.MemInc = DMA_MINC_ENABLE; + hdma_rx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_rx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_rx->Init.Mode = DMA_NORMAL; + hdma_rx->Init.Priority = DMA_PRIORITY_HIGH; HAL_DMA_Init(hdma_rx); From 621fe97d5d06cc358e46caf76e8a9f8826e5b919 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 10 Jun 2021 21:31:21 +0200 Subject: [PATCH 33/35] its working --- stm32h7/devicetest/GyroL3GD20H.cpp | 5 +- stm32h7/spi/SpiComIF.cpp | 119 ++++++--- stm32h7/spi/SpiComIF.h | 30 ++- stm32h7/spi/SpiCookie.cpp | 27 ++- stm32h7/spi/SpiCookie.h | 37 ++- stm32h7/spi/mspInit.cpp | 44 +--- stm32h7/spi/mspInit.h | 5 + stm32h7/spi/spiCore.cpp | 371 ++++++++++++++++------------- stm32h7/spi/spiCore.h | 3 +- stm32h7/spi/spiInterrupts.cpp | 15 +- stm32h7/spi/stm32h743ziSpi.cpp | 18 +- 11 files changed, 396 insertions(+), 278 deletions(-) diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index 240b159..08d73fb 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -64,7 +64,9 @@ GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transf GyroL3GD20H::~GyroL3GD20H() { delete txDmaHandle; delete rxDmaHandle; - delete mspCfg; + if(mspCfg != nullptr) { + delete mspCfg; + } } ReturnValue_t GyroL3GD20H::initialize() { @@ -89,6 +91,7 @@ ReturnValue_t GyroL3GD20H::initialize() { return HasReturnvaluesIF::RETURN_FAILED; } + delete mspCfg; transferState = TransferStates::WAIT; sif::printInfo("GyroL3GD20H::performOperation: Reading WHO AM I register\n"); diff --git a/stm32h7/spi/SpiComIF.cpp b/stm32h7/spi/SpiComIF.cpp index 6230c0c..5f21115 100644 --- a/stm32h7/spi/SpiComIF.cpp +++ b/stm32h7/spi/SpiComIF.cpp @@ -4,13 +4,13 @@ #include "fsfw/tasks/SemaphoreFactory.h" #include "fsfw/osal/FreeRTOS/TaskManagement.h" #include "fsfw_hal/stm32h7/spi/spiCore.h" +#include "fsfw_hal/stm32h7/spi/spiInterrupts.h" #include "fsfw_hal/stm32h7/spi/mspInit.h" #include "fsfw_hal/stm32h7/gpio/gpio.h" #include "stm32h7xx_hal_gpio.h" -SpiComIF::SpiComIF(object_id_t objectId, spi::TransferModes transferMode): - SystemObject(objectId), transferMode(transferMode) { +SpiComIF::SpiComIF(object_id_t objectId): SystemObject(objectId) { spi::assignTransferRxTxCompleteCallback(&spiTransferCompleteCallback, this); spi::assignTransferRxCompleteCallback(&spiTransferRxCompleteCallback, this); spi::assignTransferTxCompleteCallback(&spiTransferTxCompleteCallback, this); @@ -26,16 +26,6 @@ void SpiComIF::addDmaHandles(DMA_HandleTypeDef *txHandle, DMA_HandleTypeDef *rxH } ReturnValue_t SpiComIF::initialize() { - if(transferMode == spi::TransferModes::DMA) { - DMA_HandleTypeDef *txHandle = nullptr; - DMA_HandleTypeDef *rxHandle = nullptr; - spi::getDmaHandles(&txHandle, &rxHandle); - if(txHandle == nullptr or rxHandle == nullptr) { - sif::printError("SpiComIF::initialize: DMA handles not set!\n"); - return HasReturnvaluesIF::RETURN_FAILED; - } - } - return HasReturnvaluesIF::RETURN_OK; } @@ -49,15 +39,20 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { #endif return NULLPOINTER; } + auto transferMode = spiCookie->getTransferMode(); - if(transferMode == spi::TransferModes::DMA or transferMode == spi::TransferModes::INTERRUPT) { - spiSemaphore = dynamic_cast( - SemaphoreFactory::instance()->createBinarySemaphore()); + if(transferMode == spi::TransferModes::DMA) { + DMA_HandleTypeDef *txHandle = nullptr; + DMA_HandleTypeDef *rxHandle = nullptr; + spi::getDmaHandles(&txHandle, &rxHandle); + if(txHandle == nullptr or rxHandle == nullptr) { + sif::printError("SpiComIF::initialize: DMA handles not set!\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } } - else { - spiMutex = MutexFactory::instance()->createMutex(); - } - + // This semaphore ensures thread-safety for a given bus + spiSemaphore = dynamic_cast( + SemaphoreFactory::instance()->createBinarySemaphore()); address_t spiAddress = spiCookie->getDeviceAddress(); auto iter = spiDeviceMap.find(spiAddress); @@ -82,17 +77,55 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { SPI_HandleTypeDef& spiHandle = spiCookie->getSpiHandle(); + auto spiIdx = spiCookie->getSpiIdx(); + if(spiIdx == spi::SpiBus::SPI_1) { +#ifdef SPI1 + spiHandle.Instance = SPI1; +#endif + } + else if(spiIdx == spi::SpiBus::SPI_2) { +#ifdef SPI2 + spiHandle.Instance = SPI2; +#endif + } + else { + printCfgError("SPI Bus Index"); + return HasReturnvaluesIF::RETURN_FAILED; + } + + auto mspCfg = spiCookie->getMspCfg(); + if(transferMode == spi::TransferModes::POLLING) { -// spi::setSpiMspFunctions(&spi::halMspInitPolling, &spiHandle, -// &spi::halMspDeinitPolling, &spiHandle); + auto typedCfg = dynamic_cast(mspCfg); + if(typedCfg == nullptr) { + printCfgError("Polling MSP"); + return HasReturnvaluesIF::RETURN_FAILED; + } + spi::setSpiPollingMspFunctions(typedCfg); } else if(transferMode == spi::TransferModes::INTERRUPT) { -// spi::setSpiMspFunctions(&spi::halMspInitInterrupt, &spiHandle, -// &spi::halMspDeinitPolling, &spiHandle); + auto typedCfg = dynamic_cast(mspCfg); + if(typedCfg == nullptr) { + printCfgError("IRQ MSP"); + return HasReturnvaluesIF::RETURN_FAILED; + } + spi::setSpiIrqMspFunctions(typedCfg); } else if(transferMode == spi::TransferModes::DMA) { -// spi::setSpiMspFunctions(&spi::halMspInitDma, &spiHandle, -// &spi::halMspDeinitDma, &spiHandle); + auto typedCfg = dynamic_cast(mspCfg); + if(typedCfg == nullptr) { + printCfgError("DMA MSP"); + return HasReturnvaluesIF::RETURN_FAILED; + } + // Check DMA handles + DMA_HandleTypeDef* txHandle = nullptr; + DMA_HandleTypeDef* rxHandle = nullptr; + spi::getDmaHandles(&txHandle, &rxHandle); + if(txHandle == nullptr or rxHandle == nullptr) { + printCfgError("DMA Handle"); + return HasReturnvaluesIF::RETURN_FAILED; + } + spi::setSpiDmaMspFunctions(typedCfg); } gpio::initializeGpioClock(gpioPort); @@ -106,6 +139,9 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { sif::printWarning("SpiComIF::initialize: Error initializing SPI\n"); return HasReturnvaluesIF::RETURN_FAILED; } + // The MSP configuration struct is not required anymore + spiCookie->deleteMspCfg(); + return HasReturnvaluesIF::RETURN_OK; } @@ -123,6 +159,8 @@ ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, s } iter->second.currentTransferLen = sendLen; + auto transferMode = spiCookie->getTransferMode(); + switch(transferMode) { case(spi::TransferModes::POLLING): { return handlePollingSendOperation(iter->second.replyBuffer.data(), spiHandle, *spiCookie, @@ -170,12 +208,15 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SPI_HandleT SpiCookie& spiCookie, const uint8_t *sendData, size_t sendLen) { auto gpioPort = spiCookie.getChipSelectGpioPort(); auto gpioPin = spiCookie.getChipSelectGpioPin(); - spiMutex->lockMutex(timeoutType, timeoutMs); + auto returnval = spiSemaphore->acquire(timeoutType, timeoutMs); + if(returnval != HasReturnvaluesIF::RETURN_OK) { + return returnval; + } HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_RESET); auto result = HAL_SPI_TransmitReceive(&spiHandle, const_cast(sendData), recvPtr, sendLen, defaultPollingTimeout); HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_SET); - spiMutex->unlockMutex(); + spiSemaphore->release(); switch(result) { case(HAL_OK): { break; @@ -227,6 +268,7 @@ ReturnValue_t SpiComIF::handleIrqSendOperation(uint8_t *recvPtr, SPI_HandleTypeD } // yet another HAL driver which is not const-correct.. HAL_StatusTypeDef status = HAL_OK; + auto transferMode = spiCookie.getTransferMode(); if(transferMode == spi::TransferModes::DMA) { if(cacheMaintenanceOnTxBuffer) { /* Clean D-cache. Make sure the address is 32-byte aligned and add 32-bytes to length, @@ -246,13 +288,13 @@ ReturnValue_t SpiComIF::handleIrqSendOperation(uint8_t *recvPtr, SPI_HandleTypeD break; } default: { - return halErrorHandler(status); + return halErrorHandler(status, transferMode); } } return result; } -ReturnValue_t SpiComIF::halErrorHandler(HAL_StatusTypeDef status) { +ReturnValue_t SpiComIF::halErrorHandler(HAL_StatusTypeDef status, spi::TransferModes transferMode) { char modeString[10]; if(transferMode == spi::TransferModes::DMA) { std::snprintf(modeString, sizeof(modeString), "Dma"); @@ -291,10 +333,14 @@ ReturnValue_t SpiComIF::genericIrqSendSetup(uint8_t *recvPtr, SPI_HandleTypeDef& ReturnValue_t result = spiSemaphore->acquire(SemaphoreIF::TimeoutType::WAITING, timeoutMs); if(result != HasReturnvaluesIF::RETURN_OK) { // Configuration error - sif::printWarning("SpiComIF::handleInterruptSendOperation: Semaphore" + sif::printWarning("SpiComIF::handleInterruptSendOperation: Semaphore " "could not be acquired after %d ms\n", timeoutMs); return result; } + // Cache the current SPI handle in any case + spi::setSpiHandle(&spiHandle); + // The SPI handle is passed to the default SPI callback as a void argument + spi::assignSpiUserArgs(spiCookie.getSpiIdx(), reinterpret_cast(&spiHandle)); HAL_GPIO_WritePin(currentGpioPort, currentGpioPin, GPIO_PIN_RESET); return HasReturnvaluesIF::RETURN_OK; } @@ -341,13 +387,13 @@ void SpiComIF::genericIrqHandler(SpiComIF *spiComIF, TransferStates targetState) BaseType_t taskWoken = pdFALSE; ReturnValue_t result = BinarySemaphore::releaseFromISR(spiComIF->spiSemaphore->getSemaphore(), &taskWoken); - if(result != HasReturnvaluesIF::RETURN_FAILED) { + if(result != HasReturnvaluesIF::RETURN_OK) { // Configuration error printf("SpiComIF::genericIrqHandler: Failure releasing Semaphore!\n"); } // Perform cache maintenance operation for DMA transfers - if(spiComIF->transferMode == spi::TransferModes::DMA) { + if(spiComIF->currentTransferMode == spi::TransferModes::DMA) { // Invalidate cache prior to access by CPU SCB_InvalidateDCache_by_Addr ((uint32_t *) spiComIF->currentRecvPtr, spiComIF->currentRecvBuffSize); @@ -358,3 +404,12 @@ void SpiComIF::genericIrqHandler(SpiComIF *spiComIF, TransferStates targetState) TaskManagement::requestContextSwitch(CallContext::ISR); } } + +void SpiComIF::printCfgError(const char *const type) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "SpiComIF::initializeInterface: Invalid " << type << " configuration" + << std::endl; +#else + sif::printWarning("SpiComIF::initializeInterface: Invalid %s configuration\n", type); +#endif +} diff --git a/stm32h7/spi/SpiComIF.h b/stm32h7/spi/SpiComIF.h index 4b7e093..2a40a43 100644 --- a/stm32h7/spi/SpiComIF.h +++ b/stm32h7/spi/SpiComIF.h @@ -1,8 +1,6 @@ #ifndef FSFW_HAL_STM32H7_SPI_SPICOMIF_H_ #define FSFW_HAL_STM32H7_SPI_SPICOMIF_H_ - - #include "fsfw/tasks/SemaphoreIF.h" #include "fsfw/devicehandlers/DeviceCommunicationIF.h" #include "fsfw/objectmanager/SystemObject.h" @@ -24,6 +22,19 @@ enum class TransferStates { FAILURE }; +/** + * @brief This communication interface allows using generic device handlers with using + * the STM32H7 SPI peripherals + * @details + * This communication interface supports all three major communcation modes: + * - Polling: Simple, but not recommended to real use-cases, blocks the CPU + * - Interrupt: Good for small data only arriving occasionally + * - DMA: Good for large data which also occur regularly. Please note that the number + * of DMA channels in limited + * The device specific information is usually kept in the SpiCookie class. The current + * implementation limits the transfer mode for a given SPI bus. + * @author R. Mueller + */ class SpiComIF: public SystemObject, public DeviceCommunicationIF { @@ -35,7 +46,7 @@ public: * @param spiHandle * @param transferMode */ - SpiComIF(object_id_t objectId, spi::TransferModes transferMode); + SpiComIF(object_id_t objectId); /** * Allows the user to disable cache maintenance on the TX buffer. This can be done if the @@ -49,7 +60,7 @@ public: void setDefaultPollingTimeout(dur_millis_t timeout); /** - * Add the DMA handles. These need to be set in the DMA transfer mode is used + * Add the DMA handles. These need to be set in the DMA transfer mode is used. * @param txHandle * @param rxHandle */ @@ -68,7 +79,6 @@ protected: virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) override; - private: struct SpiInstance { @@ -79,13 +89,11 @@ private: uint32_t defaultPollingTimeout = 50; - spi::TransferModes transferMode; - - MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; + SemaphoreIF::TimeoutType timeoutType = SemaphoreIF::TimeoutType::WAITING; dur_millis_t timeoutMs = 20; + spi::TransferModes currentTransferMode = spi::TransferModes::POLLING; BinarySemaphore* spiSemaphore = nullptr; - MutexIF* spiMutex = nullptr; bool cacheMaintenanceOnTxBuffer = true; using SpiDeviceMap = std::map; @@ -109,7 +117,7 @@ private: SpiCookie& spiCookie, const uint8_t * sendData, size_t sendLen); ReturnValue_t genericIrqSendSetup(uint8_t* recvPtr, SPI_HandleTypeDef& spiHandle, SpiCookie& spiCookie, const uint8_t * sendData, size_t sendLen); - ReturnValue_t halErrorHandler(HAL_StatusTypeDef status); + ReturnValue_t halErrorHandler(HAL_StatusTypeDef status, spi::TransferModes transferMode); static void spiTransferTxCompleteCallback(SPI_HandleTypeDef *hspi, void* args); static void spiTransferRxCompleteCallback(SPI_HandleTypeDef *hspi, void* args); @@ -118,7 +126,7 @@ private: static void genericIrqHandler(SpiComIF* comIF, TransferStates targetState); - + void printCfgError(const char* const type); }; diff --git a/stm32h7/spi/SpiCookie.cpp b/stm32h7/spi/SpiCookie.cpp index 51a1807..f28df27 100644 --- a/stm32h7/spi/SpiCookie.cpp +++ b/stm32h7/spi/SpiCookie.cpp @@ -1,13 +1,12 @@ #include "SpiCookie.h" -SpiCookie::SpiCookie(address_t deviceAddress, spi::SpiBus spiIdx, SPI_TypeDef* spiInstance, - uint32_t spiSpeed, spi::SpiModes spiMode, uint16_t chipSelectGpioPin, - GPIO_TypeDef* chipSelectGpioPort, size_t maxRecvSize): - deviceAddress(deviceAddress), spiIdx(spiIdx), spiSpeed(spiSpeed), spiMode(spiMode), - chipSelectGpioPin(chipSelectGpioPin), chipSelectGpioPort(chipSelectGpioPort), - maxRecvSize(maxRecvSize) { - spiHandle.Instance = spiInstance; +SpiCookie::SpiCookie(address_t deviceAddress, spi::SpiBus spiIdx, spi::TransferModes transferMode, + spi::MspCfgBase* mspCfg, uint32_t spiSpeed, spi::SpiModes spiMode, + uint16_t chipSelectGpioPin, GPIO_TypeDef* chipSelectGpioPort, size_t maxRecvSize): + deviceAddress(deviceAddress), spiIdx(spiIdx), transferMode(transferMode), + spiSpeed(spiSpeed), spiMode(spiMode), chipSelectGpioPin(chipSelectGpioPin), + chipSelectGpioPort(chipSelectGpioPort), mspCfg(mspCfg), maxRecvSize(maxRecvSize) { spiHandle.Init.DataSize = SPI_DATASIZE_8BIT; spiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; spiHandle.Init.TIMode = SPI_TIMODE_DISABLE; @@ -55,3 +54,17 @@ size_t SpiCookie::getMaxRecvSize() const { SPI_HandleTypeDef& SpiCookie::getSpiHandle() { return spiHandle; } + +spi::MspCfgBase* SpiCookie::getMspCfg() { + return mspCfg; +} + +void SpiCookie::deleteMspCfg() { + if(mspCfg != nullptr) { + delete mspCfg; + } +} + +spi::TransferModes SpiCookie::getTransferMode() const { + return transferMode; +} diff --git a/stm32h7/spi/SpiCookie.h b/stm32h7/spi/SpiCookie.h index 00d7f10..cb84ffd 100644 --- a/stm32h7/spi/SpiCookie.h +++ b/stm32h7/spi/SpiCookie.h @@ -2,15 +2,39 @@ #define FSFW_HAL_STM32H7_SPI_SPICOOKIE_H_ #include "spiDefinitions.h" +#include "mspInit.h" #include "fsfw/devicehandlers/CookieIF.h" #include "stm32h743xx.h" +/** + * @brief SPI cookie implementation for the STM32H7 device family + * @details + * This cookie contains and caches device specific information to be used by the + * SPI communication interface + * @author R. Mueller + */ class SpiCookie: public CookieIF { + friend class SpiComIF; public: - SpiCookie(address_t deviceAddress, spi::SpiBus spiIdx, SPI_TypeDef* spiInstance, - uint32_t spiSpeed, spi::SpiModes spiMode, + /** + * Allows construction of a SPI cookie for a connected SPI device + * @param deviceAddress + * @param spiIdx SPI bus, e.g. SPI1 or SPI2 + * @param transferMode + * @param mspCfg This is the MSP configuration. The user is expected to supply + * a valid MSP configuration. See mspInit.h for functions + * to create one. + * @param spiSpeed + * @param spiMode + * @param chipSelectGpioPin GPIO port. Don't use a number here, use the 16 bit type + * definitions supplied in the MCU header file! (e.g. GPIO_PIN_X) + * @param chipSelectGpioPort GPIO port (e.g. GPIOA) + * @param maxRecvSize Maximum expected receive size. Chose as small as possible. + */ + SpiCookie(address_t deviceAddress, spi::SpiBus spiIdx, spi::TransferModes transferMode, + spi::MspCfgBase* mspCfg, uint32_t spiSpeed, spi::SpiModes spiMode, uint16_t chipSelectGpioPin, GPIO_TypeDef* chipSelectGpioPort, size_t maxRecvSize); uint16_t getChipSelectGpioPin() const; @@ -18,6 +42,7 @@ public: address_t getDeviceAddress() const; spi::SpiBus getSpiIdx() const; spi::SpiModes getSpiMode() const; + spi::TransferModes getTransferMode() const; uint32_t getSpiSpeed() const; size_t getMaxRecvSize() const; SPI_HandleTypeDef& getSpiHandle(); @@ -28,9 +53,17 @@ private: spi::SpiBus spiIdx; uint32_t spiSpeed; spi::SpiModes spiMode; + spi::TransferModes transferMode; uint16_t chipSelectGpioPin; GPIO_TypeDef* chipSelectGpioPort; + // The MSP configuration is cached here. Be careful when using this, it is automatically + // deleted by the SPI communication interface if it is not required anymore! + spi::MspCfgBase* mspCfg = nullptr; const size_t maxRecvSize; + + // Only the SpiComIF is allowed to use this to prevent dangling pointers issues + spi::MspCfgBase* getMspCfg(); + void deleteMspCfg(); }; diff --git a/stm32h7/spi/mspInit.cpp b/stm32h7/spi/mspInit.cpp index fa91825..540dd80 100644 --- a/stm32h7/spi/mspInit.cpp +++ b/stm32h7/spi/mspInit.cpp @@ -36,7 +36,7 @@ void spi::halMspInitDma(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { DMA_HandleTypeDef* hdma_tx = nullptr; DMA_HandleTypeDef* hdma_rx = nullptr; spi::getDmaHandles(&hdma_tx, &hdma_rx); - if(hdma_tx == NULL || hdma_rx == NULL) { + if(hdma_tx == nullptr or hdma_rx == nullptr) { printf("HAL_SPI_MspInit: Invalid DMA handles. Make sure to call setDmaHandles!\n"); return; } @@ -55,46 +55,12 @@ void spi::halMspInitDma(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { // Assume it was not configured properly mspErrorHandler("spi::halMspInitDma", "DMA TX handle invalid"); } - hdma_tx->Instance = SPIx_TX_DMA_STREAM; - - hdma_tx->Init.Request = SPIx_TX_DMA_REQUEST; - - // offer function to configure this.. - hdma_tx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; - hdma_tx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - hdma_tx->Init.MemBurst = DMA_MBURST_INC4; - hdma_tx->Init.PeriphBurst = DMA_PBURST_INC4; - hdma_tx->Init.Direction = DMA_MEMORY_TO_PERIPH; - hdma_tx->Init.PeriphInc = DMA_PINC_DISABLE; - hdma_tx->Init.MemInc = DMA_MINC_ENABLE; - hdma_tx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - hdma_tx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - hdma_tx->Init.Mode = DMA_NORMAL; - hdma_tx->Init.Priority = DMA_PRIORITY_LOW; HAL_DMA_Init(hdma_tx); - /* Associate the initialized DMA handle to the the SPI handle */ __HAL_LINKDMA(hspi, hdmatx, *hdma_tx); - /* Configure the DMA handler for Transmission process */ - hdma_rx->Instance = SPIx_RX_DMA_STREAM; - - hdma_rx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; - hdma_rx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - hdma_rx->Init.MemBurst = DMA_MBURST_INC4; - hdma_rx->Init.PeriphBurst = DMA_PBURST_INC4; - hdma_rx->Init.Request = SPIx_RX_DMA_REQUEST; - hdma_rx->Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_rx->Init.PeriphInc = DMA_PINC_DISABLE; - hdma_rx->Init.MemInc = DMA_MINC_ENABLE; - hdma_rx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - hdma_rx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - hdma_rx->Init.Mode = DMA_NORMAL; - hdma_rx->Init.Priority = DMA_PRIORITY_HIGH; - HAL_DMA_Init(hdma_rx); - /* Associate the initialized DMA handle to the the SPI handle */ __HAL_LINKDMA(hspi, hdmarx, *hdma_rx); @@ -111,14 +77,6 @@ void spi::halMspInitDma(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { &spi::dmaTxIrqHandler, hdma_tx); HAL_NVIC_SetPriority(cfg->txDmaIrqNumber, cfg->txPreEmptPriority, cfg->txSubpriority); HAL_NVIC_EnableIRQ(cfg->txDmaIrqNumber); - - /*##-5- Configure the NVIC for SPI #########################################*/ - /* NVIC configuration for SPI transfer complete interrupt (SPI1) */ - // Assign the interrupt handler - spi::assignSpiUserHandler(spi::SPI_1, &spi::spiIrqHandler, hspi); - HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0); - HAL_NVIC_EnableIRQ(SPIx_IRQn); - } /** diff --git a/stm32h7/spi/mspInit.h b/stm32h7/spi/mspInit.h index b4e900a..e6de2f8 100644 --- a/stm32h7/spi/mspInit.h +++ b/stm32h7/spi/mspInit.h @@ -3,6 +3,7 @@ #include "spiDefinitions.h" #include "../dma.h" + #include "stm32h7xx_hal_spi.h" #include @@ -11,6 +12,10 @@ extern "C" { #endif +/** + * @brief This file provides MSP implementation for DMA, IRQ and Polling mode for the + * SPI peripheral. This configuration is required for the SPI communication to work. + */ namespace spi { struct MspCfgBase { diff --git a/stm32h7/spi/spiCore.cpp b/stm32h7/spi/spiCore.cpp index 1afbb84..feec65f 100644 --- a/stm32h7/spi/spiCore.cpp +++ b/stm32h7/spi/spiCore.cpp @@ -1,3 +1,4 @@ +#include "spiDefinitions.h" #include "spiCore.h" #include @@ -14,178 +15,16 @@ void* rxArgs = nullptr; spi_transfer_cb_t errorCb = nullptr; void* errorArgs = nullptr; -void spi::configureDmaHandle(DMA_HandleTypeDef *handle, dma::DMAType dmaType, +void mapIndexAndStream(DMA_HandleTypeDef* handle, dma::DMAType dmaType, dma::DMAIndexes dmaIdx, + dma::DMAStreams dmaStream, IRQn_Type* dmaIrqNumber); +void mapSpiBus(DMA_HandleTypeDef *handle, dma::DMAType dmaType, spi::SpiBus spiBus); + +void spi::configureDmaHandle(DMA_HandleTypeDef *handle, spi::SpiBus spiBus, dma::DMAType dmaType, dma::DMAIndexes dmaIdx, dma::DMAStreams dmaStream, IRQn_Type* dmaIrqNumber, uint32_t dmaMode, uint32_t dmaPriority) { using namespace dma; - if(dmaIdx == DMAIndexes::DMA_1) { -#ifdef DMA1 - switch(dmaStream) { - case(DMAStreams::STREAM_0): { -#ifdef DMA1_Stream0 - handle->Instance = DMA1_Stream0; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA1_Stream0_IRQn; - } -#endif - break; - } - case(DMAStreams::STREAM_1): { -#ifdef DMA1_Stream1 - handle->Instance = DMA1_Stream1; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA1_Stream1_IRQn; - } -#endif - break; - } - case(DMAStreams::STREAM_2): { -#ifdef DMA1_Stream2 - handle->Instance = DMA1_Stream2; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA1_Stream2_IRQn; - } -#endif - break; - } - case(DMAStreams::STREAM_3): { -#ifdef DMA1_Stream3 - handle->Instance = DMA1_Stream3; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA1_Stream3_IRQn; - } -#endif - break; - } - case(DMAStreams::STREAM_4): { -#ifdef DMA1_Stream4 - handle->Instance = DMA1_Stream4; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA1_Stream4_IRQn; - } -#endif - break; - } - case(DMAStreams::STREAM_5): { -#ifdef DMA1_Stream5 - handle->Instance = DMA1_Stream5; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA1_Stream5_IRQn; - } -#endif - break; - } - case(DMAStreams::STREAM_6): { -#ifdef DMA1_Stream6 - handle->Instance = DMA1_Stream6; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA1_Stream6_IRQn; - } -#endif - break; - } - case(DMAStreams::STREAM_7): { -#ifdef DMA1_Stream7 - handle->Instance = DMA1_Stream7; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA1_Stream7_IRQn; - } -#endif - break; - } - } - if(dmaType == DMAType::TX) { - handle->Init.Request = DMA_REQUEST_SPI1_TX; - } - else { - handle->Init.Request = DMA_REQUEST_SPI1_RX; - } -#endif /* DMA1 */ - } - if(dmaIdx == DMAIndexes::DMA_2) { -#ifdef DMA2 - switch(dmaStream) { - case(DMAStreams::STREAM_0): { -#ifdef DMA1_Stream0 - handle->Instance = DMA2_Stream0; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA2_Stream0_IRQn; - } -#endif - break; - } - case(DMAStreams::STREAM_1): { -#ifdef DMA1_Stream1 - handle->Instance = DMA2_Stream1; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA2_Stream1_IRQn; - } -#endif - break; - } - case(DMAStreams::STREAM_2): { -#ifdef DMA1_Stream2 - handle->Instance = DMA2_Stream2; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA2_Stream2_IRQn; - } -#endif - break; - } - case(DMAStreams::STREAM_3): { -#ifdef DMA1_Stream3 - handle->Instance = DMA2_Stream3; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA2_Stream3_IRQn; - } -#endif - break; - } - case(DMAStreams::STREAM_4): { -#ifdef DMA1_Stream4 - handle->Instance = DMA1_Stream4; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA2_Stream4_IRQn; - } -#endif - break; - } - case(DMAStreams::STREAM_5): { -#ifdef DMA1_Stream5 - handle->Instance = DMA1_Stream5; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA2_Stream5_IRQn; - } -#endif - break; - } - case(DMAStreams::STREAM_6): { -#ifdef DMA1_Stream6 - handle->Instance = DMA1_Stream6; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA2_Stream6_IRQn; - } -#endif - break; - } - case(DMAStreams::STREAM_7): { -#ifdef DMA1_Stream7 - handle->Instance = DMA1_Stream7; - if(dmaIrqNumber != nullptr) { - *dmaIrqNumber = DMA2_Stream7_IRQn; - } -#endif - break; - } - } - if(dmaType == DMAType::TX) { - handle->Init.Request = DMA_REQUEST_SPI2_TX; - } - else { - handle->Init.Request = DMA_REQUEST_SPI2_RX; - } -#endif /* DMA2 */ - } + mapIndexAndStream(handle, dmaType, dmaIdx, dmaStream, dmaIrqNumber); + mapSpiBus(handle, dmaType, spiBus); if(dmaType == DMAType::TX) { handle->Init.Direction = DMA_MEMORY_TO_PERIPH; @@ -305,3 +144,197 @@ extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { printf("HAL_SPI_ErrorCallback: No user callback specified\n"); } } + +void mapIndexAndStream(DMA_HandleTypeDef* handle, dma::DMAType dmaType, dma::DMAIndexes dmaIdx, + dma::DMAStreams dmaStream, IRQn_Type* dmaIrqNumber) { + using namespace dma; + if(dmaIdx == DMAIndexes::DMA_1) { +#ifdef DMA1 + switch(dmaStream) { + case(DMAStreams::STREAM_0): { +#ifdef DMA1_Stream0 + handle->Instance = DMA1_Stream0; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream0_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_1): { +#ifdef DMA1_Stream1 + handle->Instance = DMA1_Stream1; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream1_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_2): { +#ifdef DMA1_Stream2 + handle->Instance = DMA1_Stream2; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream2_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_3): { +#ifdef DMA1_Stream3 + handle->Instance = DMA1_Stream3; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream3_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_4): { +#ifdef DMA1_Stream4 + handle->Instance = DMA1_Stream4; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream4_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_5): { +#ifdef DMA1_Stream5 + handle->Instance = DMA1_Stream5; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream5_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_6): { +#ifdef DMA1_Stream6 + handle->Instance = DMA1_Stream6; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream6_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_7): { +#ifdef DMA1_Stream7 + handle->Instance = DMA1_Stream7; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream7_IRQn; + } +#endif + break; + } + } + if(dmaType == DMAType::TX) { + handle->Init.Request = DMA_REQUEST_SPI1_TX; + } + else { + handle->Init.Request = DMA_REQUEST_SPI1_RX; + } +#endif /* DMA1 */ + } + if(dmaIdx == DMAIndexes::DMA_2) { +#ifdef DMA2 + switch(dmaStream) { + case(DMAStreams::STREAM_0): { +#ifdef DMA2_Stream0 + handle->Instance = DMA2_Stream0; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream0_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_1): { +#ifdef DMA2_Stream1 + handle->Instance = DMA2_Stream1; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream1_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_2): { +#ifdef DMA2_Stream2 + handle->Instance = DMA2_Stream2; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream2_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_3): { +#ifdef DMA2_Stream3 + handle->Instance = DMA2_Stream3; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream3_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_4): { +#ifdef DMA2_Stream4 + handle->Instance = DMA2_Stream4; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream4_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_5): { +#ifdef DMA2_Stream5 + handle->Instance = DMA2_Stream5; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream5_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_6): { +#ifdef DMA2_Stream6 + handle->Instance = DMA2_Stream6; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream6_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_7): { +#ifdef DMA2_Stream7 + handle->Instance = DMA2_Stream7; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream7_IRQn; + } +#endif + break; + } + } +#endif /* DMA2 */ + } +} + +void mapSpiBus(DMA_HandleTypeDef *handle, dma::DMAType dmaType, spi::SpiBus spiBus) { + if(dmaType == dma::DMAType::TX) { + if(spiBus == spi::SpiBus::SPI_1) { +#ifdef DMA_REQUEST_SPI1_TX + handle->Init.Request = DMA_REQUEST_SPI1_TX; +#endif + } + else if(spiBus == spi::SpiBus::SPI_2) { +#ifdef DMA_REQUEST_SPI2_TX + handle->Init.Request = DMA_REQUEST_SPI2_TX; +#endif + } + } + else { + if(spiBus == spi::SpiBus::SPI_1) { +#ifdef DMA_REQUEST_SPI1_RX + handle->Init.Request = DMA_REQUEST_SPI1_RX; +#endif + } + else if(spiBus == spi::SpiBus::SPI_2) { +#ifdef DMA_REQUEST_SPI2_RX + handle->Init.Request = DMA_REQUEST_SPI2_RX; +#endif + } + } +} diff --git a/stm32h7/spi/spiCore.h b/stm32h7/spi/spiCore.h index 5af3558..7a9a0e1 100644 --- a/stm32h7/spi/spiCore.h +++ b/stm32h7/spi/spiCore.h @@ -14,7 +14,8 @@ using spi_transfer_cb_t = void (*) (SPI_HandleTypeDef *hspi, void* userArgs); namespace spi { -void configureDmaHandle(DMA_HandleTypeDef* Handle, dma::DMAType dmaType, dma::DMAIndexes dmaIdx, +void configureDmaHandle(DMA_HandleTypeDef* handle, spi::SpiBus spiBus, + dma::DMAType dmaType, dma::DMAIndexes dmaIdx, dma::DMAStreams dmaStream, IRQn_Type* dmaIrqNumber, uint32_t dmaMode = DMA_NORMAL, uint32_t dmaPriority = DMA_PRIORITY_LOW); diff --git a/stm32h7/spi/spiInterrupts.cpp b/stm32h7/spi/spiInterrupts.cpp index 74930e5..49182b8 100644 --- a/stm32h7/spi/spiInterrupts.cpp +++ b/stm32h7/spi/spiInterrupts.cpp @@ -19,6 +19,9 @@ user_args_t spi2UserArgs = nullptr; * @retval None */ void spi::dmaRxIrqHandler(void* dmaHandle) { + if(dmaHandle == nullptr) { + return; + } HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dmaHandle); } @@ -28,6 +31,9 @@ void spi::dmaRxIrqHandler(void* dmaHandle) { * @retval None */ void spi::dmaTxIrqHandler(void* dmaHandle) { + if(dmaHandle == nullptr) { + return; + } HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dmaHandle); } @@ -38,8 +44,11 @@ void spi::dmaTxIrqHandler(void* dmaHandle) { */ void spi::spiIrqHandler(void* spiHandle) { - auto currentSpiHandle = spi::getSpiHandle(); - HAL_SPI_IRQHandler((SPI_HandleTypeDef *) currentSpiHandle); + if(spiHandle == nullptr) { + return; + } + //auto currentSpiHandle = spi::getSpiHandle(); + HAL_SPI_IRQHandler((SPI_HandleTypeDef *) spiHandle); } void spi::assignSpiUserHandler(spi::SpiBus spiIdx, user_handler_t userHandler, @@ -69,7 +78,7 @@ void spi::getSpiUserHandler(spi::SpiBus spiBus, user_handler_t *userHandler, } } -void assignSpiUserArgs(spi::SpiBus spiBus, user_args_t userArgs) { +void spi::assignSpiUserArgs(spi::SpiBus spiBus, user_args_t userArgs) { if(spiBus == spi::SpiBus::SPI_1) { spi1UserArgs = userArgs; } diff --git a/stm32h7/spi/stm32h743ziSpi.cpp b/stm32h7/spi/stm32h743ziSpi.cpp index 3ff4d2b..826ecb2 100644 --- a/stm32h7/spi/stm32h743ziSpi.cpp +++ b/stm32h7/spi/stm32h743ziSpi.cpp @@ -18,7 +18,7 @@ void spiCleanUpWrapper() { } void spiDmaClockEnableWrapper() { - __HAL_RCC_SPI1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); } void spi::h743zi::standardPollingCfg(MspPollingConfigStruct& cfg) { @@ -55,24 +55,24 @@ void spi::h743zi::standardInterruptCfg(MspIrqConfigStruct& cfg, IrqPriorities sp } void spi::h743zi::standardDmaCfg(MspDmaConfigStruct& cfg, IrqPriorities spiIrqPrio, - IrqPriorities txIrqPrio, IrqPriorities rxIrqPrio, IrqPriorities spiSubprio, + IrqPriorities txIrqPrio, IrqPriorities rxIrqPrio, IrqPriorities spiSubprio, IrqPriorities txSubprio, IrqPriorities rxSubprio) { cfg.dmaClkEnableWrapper = &spiDmaClockEnableWrapper; - cfg.rxDmaIndex = dma::DMAIndexes::DMA_1; - cfg.txDmaIndex = dma::DMAIndexes::DMA_1; + cfg.rxDmaIndex = dma::DMAIndexes::DMA_2; + cfg.txDmaIndex = dma::DMAIndexes::DMA_2; cfg.txDmaStream = dma::DMAStreams::STREAM_3; cfg.rxDmaStream = dma::DMAStreams::STREAM_2; DMA_HandleTypeDef* txHandle; DMA_HandleTypeDef* rxHandle; spi::getDmaHandles(&txHandle, &rxHandle); if(txHandle == nullptr or rxHandle == nullptr) { - printf("spi::h743zi::standardDmaCfg: Invalid DMA handles"); + printf("spi::h743zi::standardDmaCfg: Invalid DMA handles\n"); return; } - spi::configureDmaHandle(txHandle, dma::DMAType::TX, cfg.txDmaIndex, cfg.txDmaStream, - &cfg.txDmaIrqNumber); - spi::configureDmaHandle(rxHandle, dma::DMAType::RX, cfg.rxDmaIndex, cfg.rxDmaStream, - &cfg.rxDmaIrqNumber); + spi::configureDmaHandle(txHandle, spi::SpiBus::SPI_1, dma::DMAType::TX, cfg.txDmaIndex, + cfg.txDmaStream, &cfg.txDmaIrqNumber); + spi::configureDmaHandle(rxHandle, spi::SpiBus::SPI_1, dma::DMAType::RX, cfg.rxDmaIndex, + cfg.rxDmaStream, &cfg.rxDmaIrqNumber, DMA_NORMAL, DMA_PRIORITY_HIGH); cfg.txPreEmptPriority = txIrqPrio; cfg.rxPreEmptPriority = txSubprio; cfg.txSubpriority = rxIrqPrio; From 543ee54ccaf7336b0789d378c8c598676c8f90a6 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 10 Jun 2021 21:35:26 +0200 Subject: [PATCH 34/35] and now the cfg file not needed anymore --- stm32h7/devicetest/GyroL3GD20H.cpp | 2 +- stm32h7/spi/mspInit.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index 08d73fb..7abdd5f 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -1,5 +1,5 @@ #include "GyroL3GD20H.h" -#include "spiConf.h" + #include "../spi/mspInit.h" #include "../spi/spiDefinitions.h" #include "../spi/spiCore.h" diff --git a/stm32h7/spi/mspInit.cpp b/stm32h7/spi/mspInit.cpp index 540dd80..80d2ffe 100644 --- a/stm32h7/spi/mspInit.cpp +++ b/stm32h7/spi/mspInit.cpp @@ -1,6 +1,5 @@ #include #include "mspInit.h" -#include "spiConf.h" #include "spiCore.h" #include "spiInterrupts.h" #include "stm32h743xx.h" @@ -127,7 +126,7 @@ void spi::halMspInitPolling(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = cfg->sckAlternateFunction; - HAL_GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStruct); + HAL_GPIO_Init(cfg->sckPort, &GPIO_InitStruct); /* SPI MISO GPIO pin configuration */ GPIO_InitStruct.Pin = cfg->misoPin; From 3e8de10866ca3976e14a2937679e27d0338d67ee Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 11 Jun 2021 10:37:48 +0200 Subject: [PATCH 35/35] refactored some components --- stm32h7/spi/SpiComIF.cpp | 146 +++++++++++++++++++++------------- stm32h7/spi/SpiComIF.h | 20 ++--- stm32h7/spi/SpiCookie.cpp | 8 ++ stm32h7/spi/SpiCookie.h | 4 + stm32h7/spi/spiDefinitions.h | 7 ++ stm32h7/spi/spiInterrupts.cpp | 3 +- 6 files changed, 120 insertions(+), 68 deletions(-) diff --git a/stm32h7/spi/SpiComIF.cpp b/stm32h7/spi/SpiComIF.cpp index 5f21115..732fb5e 100644 --- a/stm32h7/spi/SpiComIF.cpp +++ b/stm32h7/spi/SpiComIF.cpp @@ -11,10 +11,11 @@ #include "stm32h7xx_hal_gpio.h" SpiComIF::SpiComIF(object_id_t objectId): SystemObject(objectId) { - spi::assignTransferRxTxCompleteCallback(&spiTransferCompleteCallback, this); - spi::assignTransferRxCompleteCallback(&spiTransferRxCompleteCallback, this); - spi::assignTransferTxCompleteCallback(&spiTransferTxCompleteCallback, this); - spi::assignTransferErrorCallback(&spiTransferErrorCallback, this); + void* irqArgsVoided = reinterpret_cast(&irqArgs); + spi::assignTransferRxTxCompleteCallback(&spiTransferCompleteCallback, irqArgsVoided); + spi::assignTransferRxCompleteCallback(&spiTransferRxCompleteCallback, irqArgsVoided); + spi::assignTransferTxCompleteCallback(&spiTransferTxCompleteCallback, irqArgsVoided); + spi::assignTransferErrorCallback(&spiTransferErrorCallback, irqArgsVoided); } void SpiComIF::configureCacheMaintenanceOnTxBuffer(bool enable) { @@ -112,20 +113,20 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { spi::setSpiIrqMspFunctions(typedCfg); } else if(transferMode == spi::TransferModes::DMA) { - auto typedCfg = dynamic_cast(mspCfg); - if(typedCfg == nullptr) { - printCfgError("DMA MSP"); - return HasReturnvaluesIF::RETURN_FAILED; - } - // Check DMA handles - DMA_HandleTypeDef* txHandle = nullptr; - DMA_HandleTypeDef* rxHandle = nullptr; - spi::getDmaHandles(&txHandle, &rxHandle); - if(txHandle == nullptr or rxHandle == nullptr) { - printCfgError("DMA Handle"); - return HasReturnvaluesIF::RETURN_FAILED; - } - spi::setSpiDmaMspFunctions(typedCfg); + auto typedCfg = dynamic_cast(mspCfg); + if(typedCfg == nullptr) { + printCfgError("DMA MSP"); + return HasReturnvaluesIF::RETURN_FAILED; + } + // Check DMA handles + DMA_HandleTypeDef* txHandle = nullptr; + DMA_HandleTypeDef* rxHandle = nullptr; + spi::getDmaHandles(&txHandle, &rxHandle); + if(txHandle == nullptr or rxHandle == nullptr) { + printCfgError("DMA Handle"); + return HasReturnvaluesIF::RETURN_FAILED; + } + spi::setSpiDmaMspFunctions(typedCfg); } gpio::initializeGpioClock(gpioPort); @@ -160,6 +161,17 @@ ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, s iter->second.currentTransferLen = sendLen; auto transferMode = spiCookie->getTransferMode(); + switch(spiCookie->getTransferState()) { + case(spi::TransferStates::IDLE): { + break; + } + case(spi::TransferStates::WAIT): + case(spi::TransferStates::FAILURE): + case(spi::TransferStates::SUCCESS): + default: { + return HasReturnvaluesIF::RETURN_FAILED; + } + } switch(transferMode) { case(spi::TransferModes::POLLING): { @@ -191,12 +203,37 @@ ReturnValue_t SpiComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, if(spiCookie == nullptr) { return NULLPOINTER; } - auto iter = spiDeviceMap.find(spiCookie->getDeviceAddress()); - if(iter == spiDeviceMap.end()) { + switch(spiCookie->getTransferState()) { + case(spi::TransferStates::SUCCESS): { + auto iter = spiDeviceMap.find(spiCookie->getDeviceAddress()); + if(iter == spiDeviceMap.end()) { + return HasReturnvaluesIF::RETURN_FAILED; + } + *buffer = iter->second.replyBuffer.data(); + *size = iter->second.currentTransferLen; + spiCookie->setTransferState(spi::TransferStates::IDLE); + break; + } + case(spi::TransferStates::FAILURE): { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "SpiComIF::readReceivedMessage: Transfer failure" << std::endl; +#else + sif::printWarning("SpiComIF::readReceivedMessage: Transfer failure\n"); +#endif +#endif + spiCookie->setTransferState(spi::TransferStates::IDLE); return HasReturnvaluesIF::RETURN_FAILED; } - *buffer = iter->second.replyBuffer.data(); - *size = iter->second.currentTransferLen; + case(spi::TransferStates::WAIT): + case(spi::TransferStates::IDLE): { + break; + } + default: { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; } @@ -212,6 +249,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SPI_HandleT if(returnval != HasReturnvaluesIF::RETURN_OK) { return returnval; } + spiCookie.setTransferState(spi::TransferStates::WAIT); HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_RESET); auto result = HAL_SPI_TransmitReceive(&spiHandle, const_cast(sendData), recvPtr, sendLen, defaultPollingTimeout); @@ -219,6 +257,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SPI_HandleT spiSemaphore->release(); switch(result) { case(HAL_OK): { + spiCookie.setTransferState(spi::TransferStates::SUCCESS); break; } case(HAL_TIMEOUT): { @@ -231,6 +270,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SPI_HandleT spiCookie.getDeviceAddress()); #endif #endif + spiCookie.setTransferState(spi::TransferStates::FAILURE); return spi::HAL_TIMEOUT_RETVAL; } case(HAL_ERROR): @@ -244,6 +284,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SPI_HandleT spiCookie.getDeviceAddress()); #endif #endif + spiCookie.setTransferState(spi::TransferStates::FAILURE); return spi::HAL_ERROR_RETVAL; } } @@ -323,9 +364,6 @@ ReturnValue_t SpiComIF::halErrorHandler(HAL_StatusTypeDef status, spi::TransferM ReturnValue_t SpiComIF::genericIrqSendSetup(uint8_t *recvPtr, SPI_HandleTypeDef& spiHandle, SpiCookie& spiCookie, const uint8_t *sendData, size_t sendLen) { - // These are required by the callback - currentGpioPort = spiCookie.getChipSelectGpioPort(); - currentGpioPin = spiCookie.getChipSelectGpioPin(); currentRecvPtr = recvPtr; currentRecvBuffSize = sendLen; @@ -339,53 +377,53 @@ ReturnValue_t SpiComIF::genericIrqSendSetup(uint8_t *recvPtr, SPI_HandleTypeDef& } // Cache the current SPI handle in any case spi::setSpiHandle(&spiHandle); - // The SPI handle is passed to the default SPI callback as a void argument + // Assign the IRQ arguments for the user callbacks + irqArgs.comIF = this; + irqArgs.spiCookie = &spiCookie; + // The SPI handle is passed to the default SPI callback as a void argument. This callback + // is different from the user callbacks specified above! spi::assignSpiUserArgs(spiCookie.getSpiIdx(), reinterpret_cast(&spiHandle)); - HAL_GPIO_WritePin(currentGpioPort, currentGpioPin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(spiCookie.getChipSelectGpioPort(), spiCookie.getChipSelectGpioPin(), + GPIO_PIN_RESET); return HasReturnvaluesIF::RETURN_OK; } void SpiComIF::spiTransferTxCompleteCallback(SPI_HandleTypeDef *hspi, void *args) { - SpiComIF* spiComIF = reinterpret_cast(args); - if(spiComIF == nullptr) { - return; - } - genericIrqHandler(spiComIF, TransferStates::FAILURE); + genericIrqHandler(args, spi::TransferStates::SUCCESS); } void SpiComIF::spiTransferRxCompleteCallback(SPI_HandleTypeDef *hspi, void *args) { - SpiComIF* spiComIF = reinterpret_cast(args); - if(spiComIF == nullptr) { - return; - } - genericIrqHandler(spiComIF, TransferStates::FAILURE); + genericIrqHandler(args, spi::TransferStates::SUCCESS); } void SpiComIF::spiTransferCompleteCallback(SPI_HandleTypeDef *hspi, void *args) { - SpiComIF* spiComIF = reinterpret_cast(args); - if(spiComIF == nullptr) { - return; - } - genericIrqHandler(spiComIF, TransferStates::FAILURE); + genericIrqHandler(args, spi::TransferStates::SUCCESS); } void SpiComIF::spiTransferErrorCallback(SPI_HandleTypeDef *hspi, void *args) { - SpiComIF* spiComIF = reinterpret_cast(args); - if(spiComIF == nullptr) { - return; - } - genericIrqHandler(spiComIF, TransferStates::FAILURE); + genericIrqHandler(args, spi::TransferStates::FAILURE); } -void SpiComIF::genericIrqHandler(SpiComIF *spiComIF, TransferStates targetState) { - spiComIF->transferState = TransferStates::SUCCESS; +void SpiComIF::genericIrqHandler(void *irqArgsVoid, spi::TransferStates targetState) { + IrqArgs* irqArgs = reinterpret_cast(irqArgsVoid); + if(irqArgs == nullptr) { + return; + } + SpiCookie* spiCookie = irqArgs->spiCookie; + SpiComIF* comIF = irqArgs->comIF; + if(spiCookie == nullptr or comIF == nullptr) { + return; + } + + spiCookie->setTransferState(targetState); // Pull CS pin high again - HAL_GPIO_WritePin(spiComIF->currentGpioPort, spiComIF->currentGpioPin, GPIO_PIN_SET); + HAL_GPIO_WritePin(spiCookie->getChipSelectGpioPort(), spiCookie->getChipSelectGpioPin(), + GPIO_PIN_SET); // Release the task semaphore BaseType_t taskWoken = pdFALSE; - ReturnValue_t result = BinarySemaphore::releaseFromISR(spiComIF->spiSemaphore->getSemaphore(), + ReturnValue_t result = BinarySemaphore::releaseFromISR(comIF->spiSemaphore->getSemaphore(), &taskWoken); if(result != HasReturnvaluesIF::RETURN_OK) { // Configuration error @@ -393,10 +431,10 @@ void SpiComIF::genericIrqHandler(SpiComIF *spiComIF, TransferStates targetState) } // Perform cache maintenance operation for DMA transfers - if(spiComIF->currentTransferMode == spi::TransferModes::DMA) { + if(spiCookie->getTransferMode() == spi::TransferModes::DMA) { // Invalidate cache prior to access by CPU - SCB_InvalidateDCache_by_Addr ((uint32_t *) spiComIF->currentRecvPtr, - spiComIF->currentRecvBuffSize); + SCB_InvalidateDCache_by_Addr ((uint32_t *) comIF->currentRecvPtr, + comIF->currentRecvBuffSize); } /* Request a context switch if the SPI ComIF task was woken up and has a higher priority than the currently running task */ diff --git a/stm32h7/spi/SpiComIF.h b/stm32h7/spi/SpiComIF.h index 2a40a43..4b1ef80 100644 --- a/stm32h7/spi/SpiComIF.h +++ b/stm32h7/spi/SpiComIF.h @@ -15,13 +15,6 @@ class SpiCookie; -enum class TransferStates { - IDLE, - WAIT, - SUCCESS, - FAILURE -}; - /** * @brief This communication interface allows using generic device handlers with using * the STM32H7 SPI peripherals @@ -87,11 +80,17 @@ private: size_t currentTransferLen = 0; }; + struct IrqArgs { + SpiComIF* comIF = nullptr; + SpiCookie* spiCookie = nullptr; + }; + + IrqArgs irqArgs; + uint32_t defaultPollingTimeout = 50; SemaphoreIF::TimeoutType timeoutType = SemaphoreIF::TimeoutType::WAITING; dur_millis_t timeoutMs = 20; - spi::TransferModes currentTransferMode = spi::TransferModes::POLLING; BinarySemaphore* spiSemaphore = nullptr; bool cacheMaintenanceOnTxBuffer = true; @@ -99,11 +98,8 @@ private: using SpiDeviceMap = std::map; using SpiDeviceMapIter = SpiDeviceMap::iterator; - GPIO_TypeDef* currentGpioPort = nullptr; - uint16_t currentGpioPin = 0; uint8_t* currentRecvPtr = nullptr; size_t currentRecvBuffSize = 0; - volatile TransferStates transferState = TransferStates::IDLE; SpiDeviceMap spiDeviceMap; @@ -124,7 +120,7 @@ private: static void spiTransferCompleteCallback(SPI_HandleTypeDef *hspi, void* args); static void spiTransferErrorCallback(SPI_HandleTypeDef *hspi, void* args); - static void genericIrqHandler(SpiComIF* comIF, TransferStates targetState); + static void genericIrqHandler(void* irqArgs, spi::TransferStates targetState); void printCfgError(const char* const type); }; diff --git a/stm32h7/spi/SpiCookie.cpp b/stm32h7/spi/SpiCookie.cpp index f28df27..d583c41 100644 --- a/stm32h7/spi/SpiCookie.cpp +++ b/stm32h7/spi/SpiCookie.cpp @@ -68,3 +68,11 @@ void SpiCookie::deleteMspCfg() { spi::TransferModes SpiCookie::getTransferMode() const { return transferMode; } + +void SpiCookie::setTransferState(spi::TransferStates transferState) { + this->transferState = transferState; +} + +spi::TransferStates SpiCookie::getTransferState() const { + return this->transferState; +} diff --git a/stm32h7/spi/SpiCookie.h b/stm32h7/spi/SpiCookie.h index cb84ffd..45226b4 100644 --- a/stm32h7/spi/SpiCookie.h +++ b/stm32h7/spi/SpiCookie.h @@ -54,6 +54,7 @@ private: uint32_t spiSpeed; spi::SpiModes spiMode; spi::TransferModes transferMode; + volatile spi::TransferStates transferState = spi::TransferStates::IDLE; uint16_t chipSelectGpioPin; GPIO_TypeDef* chipSelectGpioPort; // The MSP configuration is cached here. Be careful when using this, it is automatically @@ -64,6 +65,9 @@ private: // Only the SpiComIF is allowed to use this to prevent dangling pointers issues spi::MspCfgBase* getMspCfg(); void deleteMspCfg(); + + void setTransferState(spi::TransferStates transferState); + spi::TransferStates getTransferState() const; }; diff --git a/stm32h7/spi/spiDefinitions.h b/stm32h7/spi/spiDefinitions.h index c22b853..772bf32 100644 --- a/stm32h7/spi/spiDefinitions.h +++ b/stm32h7/spi/spiDefinitions.h @@ -16,6 +16,13 @@ static constexpr ReturnValue_t HAL_TIMEOUT_RETVAL = HasReturnvaluesIF::makeRetur static constexpr ReturnValue_t HAL_BUSY_RETVAL = HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 1); static constexpr ReturnValue_t HAL_ERROR_RETVAL = HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 2); +enum class TransferStates { + IDLE, + WAIT, + SUCCESS, + FAILURE +}; + enum SpiBus { SPI_1, SPI_2 diff --git a/stm32h7/spi/spiInterrupts.cpp b/stm32h7/spi/spiInterrupts.cpp index 49182b8..83ba732 100644 --- a/stm32h7/spi/spiInterrupts.cpp +++ b/stm32h7/spi/spiInterrupts.cpp @@ -42,8 +42,7 @@ void spi::dmaTxIrqHandler(void* dmaHandle) { * @param None * @retval None */ -void spi::spiIrqHandler(void* spiHandle) -{ +void spi::spiIrqHandler(void* spiHandle) { if(spiHandle == nullptr) { return; }