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_ */