2021-06-04 16:01:38 +02:00
|
|
|
#ifndef FSFW_HAL_STM32H7_SPI_SPICOMIF_H_
|
|
|
|
#define FSFW_HAL_STM32H7_SPI_SPICOMIF_H_
|
|
|
|
|
2021-06-04 16:34:38 +02:00
|
|
|
|
2021-06-05 14:31:49 +02:00
|
|
|
|
2021-06-04 17:13:14 +02:00
|
|
|
#include "fsfw/tasks/SemaphoreIF.h"
|
2021-06-04 16:01:38 +02:00
|
|
|
#include "fsfw/devicehandlers/DeviceCommunicationIF.h"
|
|
|
|
#include "fsfw/objectmanager/SystemObject.h"
|
|
|
|
|
2021-06-05 14:31:49 +02:00
|
|
|
#include "fsfw/osal/FreeRTOS/BinarySemaphore.h"
|
2021-06-04 16:34:38 +02:00
|
|
|
#include "fsfw_hal/stm32h7/spi/spiDefinitions.h"
|
|
|
|
#include "stm32h7xx_hal_spi.h"
|
|
|
|
#include "stm32h743xx.h"
|
|
|
|
|
2021-06-04 17:13:14 +02:00
|
|
|
#include <vector>
|
|
|
|
#include <map>
|
|
|
|
|
2021-06-05 00:04:38 +02:00
|
|
|
class SpiCookie;
|
|
|
|
|
2021-06-05 14:31:49 +02:00
|
|
|
enum class TransferStates {
|
|
|
|
IDLE,
|
|
|
|
WAIT,
|
|
|
|
SUCCESS,
|
|
|
|
FAILURE
|
|
|
|
};
|
|
|
|
|
2021-06-04 16:01:38 +02:00
|
|
|
class SpiComIF:
|
|
|
|
public SystemObject,
|
|
|
|
public DeviceCommunicationIF {
|
|
|
|
public:
|
2021-06-04 17:13:14 +02:00
|
|
|
/**
|
|
|
|
* Create a SPI communication interface for the given SPI peripheral (spiInstance)
|
|
|
|
* @param objectId
|
|
|
|
* @param spiInstance
|
|
|
|
* @param spiHandle
|
|
|
|
* @param transferMode
|
|
|
|
*/
|
2021-06-10 12:05:49 +02:00
|
|
|
SpiComIF(object_id_t objectId, spi::TransferModes transferMode);
|
2021-06-04 17:13:14 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
|
2021-06-05 00:04:38 +02:00
|
|
|
void setDefaultPollingTimeout(dur_millis_t timeout);
|
|
|
|
|
2021-06-04 17:13:14 +02:00
|
|
|
/**
|
|
|
|
* 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;
|
2021-06-04 16:01:38 +02:00
|
|
|
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;
|
2021-06-04 17:13:14 +02:00
|
|
|
|
2021-06-05 14:31:49 +02:00
|
|
|
|
2021-06-04 16:01:38 +02:00
|
|
|
private:
|
2021-06-05 14:31:49 +02:00
|
|
|
|
2021-06-04 17:13:14 +02:00
|
|
|
struct SpiInstance {
|
2021-06-05 14:31:49 +02:00
|
|
|
SpiInstance(size_t maxRecvSize): replyBuffer(std::vector<uint8_t>(maxRecvSize)) {}
|
2021-06-04 17:13:14 +02:00
|
|
|
std::vector<uint8_t> replyBuffer;
|
2021-06-05 14:31:49 +02:00
|
|
|
size_t currentTransferLen = 0;
|
2021-06-04 17:13:14 +02:00
|
|
|
};
|
2021-06-05 14:31:49 +02:00
|
|
|
|
2021-06-05 00:04:38 +02:00
|
|
|
uint32_t defaultPollingTimeout = 50;
|
2021-06-04 17:13:14 +02:00
|
|
|
|
|
|
|
spi::TransferModes transferMode;
|
2021-06-05 00:04:38 +02:00
|
|
|
|
|
|
|
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
|
|
|
dur_millis_t timeoutMs = 20;
|
|
|
|
|
2021-06-05 14:31:49 +02:00
|
|
|
BinarySemaphore* spiSemaphore = nullptr;
|
2021-06-05 00:04:38 +02:00
|
|
|
MutexIF* spiMutex = nullptr;
|
2021-06-04 17:13:14 +02:00
|
|
|
bool cacheMaintenanceOnTxBuffer = true;
|
|
|
|
|
|
|
|
using SpiDeviceMap = std::map<address_t, SpiInstance>;
|
|
|
|
using SpiDeviceMapIter = SpiDeviceMap::iterator;
|
|
|
|
|
2021-06-05 14:31:49 +02:00
|
|
|
GPIO_TypeDef* currentGpioPort = nullptr;
|
|
|
|
uint16_t currentGpioPin = 0;
|
|
|
|
uint8_t* currentRecvPtr = nullptr;
|
|
|
|
size_t currentRecvBuffSize = 0;
|
|
|
|
volatile TransferStates transferState = TransferStates::IDLE;
|
|
|
|
|
2021-06-04 17:13:14 +02:00
|
|
|
SpiDeviceMap spiDeviceMap;
|
2021-06-05 00:04:38 +02:00
|
|
|
|
2021-06-10 12:05:49 +02:00
|
|
|
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);
|
2021-06-05 14:31:49 +02:00
|
|
|
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);
|
|
|
|
|
|
|
|
|
2021-06-04 16:01:38 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* FSFW_HAL_STM32H7_SPI_SPICOMIF_H_ */
|