fsfw/src/fsfw_hal/linux/spi/SpiComIF.h

106 lines
3.9 KiB
C
Raw Normal View History

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"
#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;
2022-08-22 15:02:16 +02:00
static constexpr ReturnValue_t OPENING_FILE_FAILED = returnvalue::makeCode(spiRetvalId, 0);
2022-02-02 10:29:30 +01:00
/* Full duplex (ioctl) transfer failure */
static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED =
2022-08-16 12:29:53 +02:00
returnvalue::makeCode(spiRetvalId, 1);
2022-02-02 10:29:30 +01:00
/* Half duplex (read/write) transfer failure */
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED =
2022-08-16 12:29:53 +02:00
returnvalue::makeCode(spiRetvalId, 2);
2022-02-02 10:29:30 +01:00
2022-10-26 17:06:24 +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.
*/
2022-05-14 11:33:43 +02:00
MutexIF* getCsMutex();
2022-05-14 09:40:31 +02:00
void setMutexParams(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
2022-02-02 10:29:30 +01:00
/**
* 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);
2022-10-26 17:06:24 +02:00
GpioIF& getGpioInterface();
2022-02-02 10:29:30 +01:00
void setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed);
2022-05-14 09:40:31 +02:00
void getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& speed) const;
/**
* 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.
*
2022-05-11 11:29:28 +02:00
* It is recommended to call this function after #setSpiSpeedAndMode and after locking the
* CS mutex if the SPI bus has multiple SPI devices with different speed and SPI modes attached.
* @param spiFd
*/
void updateLinePolarity(int spiFd);
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;
};
2022-10-26 17:06:24 +02:00
GpioIF& gpioComIF;
std::string dev = "";
/**
* Protects the chip select operations. Lock when GPIO is pulled low, unlock after it was
* pulled high
*/
MutexIF* csMutex = nullptr;
2022-05-14 11:33:43 +02:00
// MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
// uint32_t timeoutMs = DEFAULT_MUTEX_TIMEOUT;
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_ */