fsfw-hal/stm32h7/spi/SpiComIF.h

131 lines
4.8 KiB
C
Raw Normal View History

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 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-10 21:31:21 +02:00
/**
* @brief This communication interface allows using generic device handlers with using
* the STM32H7 SPI peripherals
* @details
* This communication interface supports all three major communcation modes:
* - Polling: Simple, but not recommended to real use-cases, blocks the CPU
* - Interrupt: Good for small data only arriving occasionally
* - DMA: Good for large data which also occur regularly. Please note that the number
* of DMA channels in limited
* The device specific information is usually kept in the SpiCookie class. The current
* implementation limits the transfer mode for a given SPI bus.
* @author R. Mueller
*/
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 21:31:21 +02:00
SpiComIF(object_id_t objectId);
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
/**
2021-06-10 21:31:21 +02:00
* Add the DMA handles. These need to be set in the DMA transfer mode is used.
2021-06-04 17:13:14 +02:00
* @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-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-11 10:37:48 +02:00
struct IrqArgs {
SpiComIF* comIF = nullptr;
SpiCookie* spiCookie = nullptr;
};
IrqArgs irqArgs;
2021-06-05 00:04:38 +02:00
uint32_t defaultPollingTimeout = 50;
2021-06-04 17:13:14 +02:00
2021-06-10 21:31:21 +02:00
SemaphoreIF::TimeoutType timeoutType = SemaphoreIF::TimeoutType::WAITING;
2021-06-05 00:04:38 +02:00
dur_millis_t timeoutMs = 20;
2021-06-05 14:31:49 +02:00
BinarySemaphore* spiSemaphore = 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
uint8_t* currentRecvPtr = nullptr;
size_t currentRecvBuffSize = 0;
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-10 21:31:21 +02:00
ReturnValue_t halErrorHandler(HAL_StatusTypeDef status, spi::TransferModes transferMode);
2021-06-05 14:31:49 +02:00
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);
2021-06-11 10:37:48 +02:00
static void genericIrqHandler(void* irqArgs, spi::TransferStates targetState);
2021-06-05 14:31:49 +02:00
2021-06-10 21:31:21 +02:00
void printCfgError(const char* const type);
2021-06-04 16:01:38 +02:00
};
#endif /* FSFW_HAL_STM32H7_SPI_SPICOMIF_H_ */