continued spi com if
This commit is contained in:
parent
cb121b9faf
commit
c50868c9dc
@ -1,10 +1,103 @@
|
|||||||
#include "SpiComIF.h"
|
#include "SpiComIF.h"
|
||||||
|
#include "SpiCookie.h"
|
||||||
|
|
||||||
SpiComIF::SpiComIF(object_id_t objectId, SPI_TypeDef* spiInstance,
|
#include "fsfw/tasks/SemaphoreFactory.h"
|
||||||
spi::TransferModes transferMode): SystemObject(objectId) {
|
#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) {
|
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;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define 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/devicehandlers/DeviceCommunicationIF.h"
|
||||||
#include "fsfw/objectmanager/SystemObject.h"
|
#include "fsfw/objectmanager/SystemObject.h"
|
||||||
|
|
||||||
@ -9,11 +10,40 @@
|
|||||||
#include "stm32h7xx_hal_spi.h"
|
#include "stm32h7xx_hal_spi.h"
|
||||||
#include "stm32h743xx.h"
|
#include "stm32h743xx.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
class SpiComIF:
|
class SpiComIF:
|
||||||
public SystemObject,
|
public SystemObject,
|
||||||
public DeviceCommunicationIF {
|
public DeviceCommunicationIF {
|
||||||
public:
|
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:
|
protected:
|
||||||
|
|
||||||
// DeviceCommunicationIF overrides
|
// DeviceCommunicationIF overrides
|
||||||
@ -25,8 +55,21 @@ protected:
|
|||||||
size_t requestLen) override;
|
size_t requestLen) override;
|
||||||
virtual ReturnValue_t readReceivedMessage(CookieIF *cookie,
|
virtual ReturnValue_t readReceivedMessage(CookieIF *cookie,
|
||||||
uint8_t **buffer, size_t *size) override;
|
uint8_t **buffer, size_t *size) override;
|
||||||
|
|
||||||
private:
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,7 +3,37 @@
|
|||||||
|
|
||||||
|
|
||||||
SpiCookie::SpiCookie(address_t deviceAddress, spi::SpiBus spiIdx, uint32_t spiSpeed,
|
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),
|
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;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,16 @@
|
|||||||
class SpiCookie: public CookieIF {
|
class SpiCookie: public CookieIF {
|
||||||
public:
|
public:
|
||||||
SpiCookie(address_t deviceAddress, spi::SpiBus spiIdx, uint32_t spiSpeed, spi::SpiModes spiMode,
|
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:
|
private:
|
||||||
address_t deviceAddress;
|
address_t deviceAddress;
|
||||||
spi::SpiBus spiIdx;
|
spi::SpiBus spiIdx;
|
||||||
@ -18,6 +27,7 @@ private:
|
|||||||
spi::SpiModes spiMode;
|
spi::SpiModes spiMode;
|
||||||
uint16_t chipSelectGpioPin;
|
uint16_t chipSelectGpioPin;
|
||||||
GPIO_TypeDef* chipSelectGpioPort;
|
GPIO_TypeDef* chipSelectGpioPort;
|
||||||
|
const size_t maxRecvSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user