continued spi com if

This commit is contained in:
Robin Müller 2021-06-04 17:13:14 +02:00
parent cb121b9faf
commit c50868c9dc
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
4 changed files with 183 additions and 7 deletions

View File

@ -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<SpiCookie*>(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<uint8_t>(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<unsigned long>(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;
}

View File

@ -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 <vector>
#include <map>
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<uint8_t> replyBuffer;
};
spi::TransferModes transferMode;
SPI_HandleTypeDef* spiHandle;
SemaphoreIF* spiSemaphore;
bool cacheMaintenanceOnTxBuffer = true;
using SpiDeviceMap = std::map<address_t, SpiInstance>;
using SpiDeviceMapIter = SpiDeviceMap::iterator;
SpiDeviceMap spiDeviceMap;
};

View File

@ -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;
}

View File

@ -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;
};