From c50868c9dc46e27ae59e79f83f27723766656f08 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Jun 2021 17:13:14 +0200 Subject: [PATCH] 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; };