2021-07-13 19:19:25 +02:00
|
|
|
#ifndef LINUX_SPI_SPICOMIF_H_
|
|
|
|
#define LINUX_SPI_SPICOMIF_H_
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
#include <unordered_map>
|
|
|
|
#include <vector>
|
2021-07-13 19:19:25 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
#include "fsfw/FSFW.h"
|
2021-07-16 12:22:14 +02:00
|
|
|
#include "fsfw/devicehandlers/DeviceCommunicationIF.h"
|
|
|
|
#include "fsfw/objectmanager/SystemObject.h"
|
2022-02-02 10:29:30 +01:00
|
|
|
#include "fsfw_hal/common/gpio/GpioIF.h"
|
|
|
|
#include "returnvalues/classIds.h"
|
|
|
|
#include "spiDefinitions.h"
|
2021-07-13 19:19:25 +02:00
|
|
|
|
|
|
|
class SpiCookie;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Encapsulates access to linux SPI driver for FSFW objects
|
|
|
|
* @details
|
|
|
|
* Right now, only full-duplex SPI is supported. Most device specific transfer properties
|
|
|
|
* are contained in the SPI cookie.
|
|
|
|
* @author R. Mueller
|
|
|
|
*/
|
2022-02-02 10:29:30 +01:00
|
|
|
class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
|
|
|
public:
|
|
|
|
static constexpr uint8_t spiRetvalId = CLASS_ID::HAL_SPI;
|
|
|
|
static constexpr ReturnValue_t OPENING_FILE_FAILED =
|
|
|
|
HasReturnvaluesIF::makeReturnCode(spiRetvalId, 0);
|
|
|
|
/* Full duplex (ioctl) transfer failure */
|
|
|
|
static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED =
|
|
|
|
HasReturnvaluesIF::makeReturnCode(spiRetvalId, 1);
|
|
|
|
/* Half duplex (read/write) transfer failure */
|
|
|
|
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED =
|
|
|
|
HasReturnvaluesIF::makeReturnCode(spiRetvalId, 2);
|
|
|
|
|
2022-05-11 11:11:39 +02:00
|
|
|
SpiComIF(object_id_t objectId, std::string devname, GpioIF* gpioComIF);
|
2022-02-02 10:29:30 +01:00
|
|
|
|
|
|
|
ReturnValue_t initializeInterface(CookieIF* cookie) override;
|
|
|
|
ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override;
|
|
|
|
ReturnValue_t getSendSuccess(CookieIF* cookie) override;
|
|
|
|
ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override;
|
|
|
|
ReturnValue_t readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) override;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This function returns the mutex which can be used to protect the spi bus when
|
|
|
|
* the chip select must be driven from outside of the com if.
|
|
|
|
*/
|
|
|
|
MutexIF* getMutex(MutexIF::TimeoutType* timeoutType = nullptr, uint32_t* timeoutMs = nullptr);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Perform a regular send operation using Linux iotcl. This is public so it can be used
|
|
|
|
* in functions like a user callback if special handling is only necessary for certain commands.
|
|
|
|
* @param spiCookie
|
|
|
|
* @param sendData
|
|
|
|
* @param sendLen
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
ReturnValue_t performRegularSendOperation(SpiCookie* spiCookie, const uint8_t* sendData,
|
|
|
|
size_t sendLen);
|
|
|
|
|
|
|
|
GpioIF* getGpioInterface();
|
|
|
|
void setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed);
|
2022-05-11 11:24:06 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This updates the SPI clock default polarity. Only setting the mode does not update
|
|
|
|
* the line state, which can be an issue on mode switches because the clock line will
|
|
|
|
* switch the state after the chip select is pulled low.
|
|
|
|
*
|
|
|
|
* It is recommended to call this function after #setSpiSpeedAndMode if the SPI bus
|
|
|
|
* has multiple SPI devices with different speed and SPI modes attached.
|
|
|
|
* @param spiFd
|
|
|
|
*/
|
|
|
|
void updateLinePolarity(int spiFd);
|
2022-05-11 10:54:13 +02:00
|
|
|
void getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& speed) const;
|
2022-05-11 11:11:39 +02:00
|
|
|
|
|
|
|
const std::string& getSpiDev() const;
|
2022-02-02 10:29:30 +01:00
|
|
|
void performSpiWiretapping(SpiCookie* spiCookie);
|
|
|
|
|
|
|
|
ReturnValue_t getReadBuffer(address_t spiAddress, uint8_t** buffer);
|
|
|
|
|
|
|
|
private:
|
|
|
|
struct SpiInstance {
|
|
|
|
SpiInstance(size_t maxRecvSize) : replyBuffer(std::vector<uint8_t>(maxRecvSize)) {}
|
|
|
|
std::vector<uint8_t> replyBuffer;
|
|
|
|
};
|
|
|
|
|
|
|
|
GpioIF* gpioComIF = nullptr;
|
2022-05-11 11:11:39 +02:00
|
|
|
std::string dev = "";
|
2022-05-11 11:24:06 +02:00
|
|
|
/**
|
|
|
|
* Protects the chip select operations. Lock when GPIO is pulled low, unlock after it was
|
|
|
|
* pulled high
|
|
|
|
*/
|
|
|
|
MutexIF* csMutex = nullptr;
|
2022-02-02 10:29:30 +01:00
|
|
|
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
|
|
|
uint32_t timeoutMs = 20;
|
2022-03-07 16:13:04 +01:00
|
|
|
spi_ioc_transfer clockUpdateTransfer = {};
|
2022-02-02 10:29:30 +01:00
|
|
|
|
|
|
|
using SpiDeviceMap = std::unordered_map<address_t, SpiInstance>;
|
|
|
|
using SpiDeviceMapIter = SpiDeviceMap::iterator;
|
|
|
|
|
|
|
|
SpiDeviceMap spiDeviceMap;
|
|
|
|
|
|
|
|
ReturnValue_t performHalfDuplexReception(SpiCookie* spiCookie);
|
2021-07-13 19:19:25 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* LINUX_SPI_SPICOMIF_H_ */
|