diff --git a/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp b/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp index da95bfcb..12d95f0d 100644 --- a/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp +++ b/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp @@ -27,7 +27,7 @@ SpiComIF::SpiComIF(object_id_t objectId, std::string devname, GpioIF* gpioComIF) #endif /* FSFW_VERBOSE_LEVEL >= 1 */ } - spiMutex = MutexFactory::instance()->createMutex(); + csMutex = MutexFactory::instance()->createMutex(); } ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) { @@ -197,7 +197,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const /* Pull SPI CS low. For now, no support for active high given */ if (gpioId != gpio::NO_GPIO) { - result = spiMutex->lockMutex(timeoutType, timeoutMs); + result = csMutex->lockMutex(timeoutType, timeoutMs); if (result != RETURN_OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -208,6 +208,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const #endif return result; } + updateLinePolarity(fileDescriptor); ReturnValue_t result = gpioComIF->pullLow(gpioId); if (result != HasReturnvaluesIF::RETURN_OK) { #if FSFW_VERBOSE_LEVEL >= 1 @@ -219,6 +220,8 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const #endif return result; } + } else { + updateLinePolarity(fileDescriptor); } /* Execute transfer */ @@ -248,7 +251,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const if (gpioId != gpio::NO_GPIO) { gpioComIF->pullHigh(gpioId); - result = spiMutex->unlockMutex(); + result = csMutex->unlockMutex(); if (result != RETURN_OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "SpiComIF::sendMessage: Failed to unlock mutex" << std::endl; @@ -291,7 +294,7 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) { gpioId_t gpioId = spiCookie->getChipSelectPin(); if (gpioId != gpio::NO_GPIO) { - result = spiMutex->lockMutex(timeoutType, timeoutMs); + result = csMutex->lockMutex(timeoutType, timeoutMs); if (result != RETURN_OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "SpiComIF::getSendSuccess: Failed to lock mutex" << std::endl; @@ -314,7 +317,7 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) { if (gpioId != gpio::NO_GPIO) { gpioComIF->pullHigh(gpioId); - result = spiMutex->unlockMutex(); + result = csMutex->unlockMutex(); if (result != RETURN_OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "SpiComIF::getSendSuccess: Failed to unlock mutex" << std::endl; @@ -350,7 +353,7 @@ MutexIF* SpiComIF::getMutex(MutexIF::TimeoutType* timeoutType, uint32_t* timeout if (timeoutMs != nullptr) { *timeoutMs = this->timeoutMs; } - return spiMutex; + return csMutex; } void SpiComIF::performSpiWiretapping(SpiCookie* spiCookie) { @@ -398,14 +401,6 @@ void SpiComIF::setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed) if (retval != 0) { utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Setting SPI speed failed"); } - // 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 - clockUpdateTransfer.len = 0; - retval = ioctl(spiFd, SPI_IOC_MESSAGE(1), &clockUpdateTransfer); - if (retval != 0) { - utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Updating SPI default clock failed"); - } } void SpiComIF::getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& speed) const { @@ -422,4 +417,14 @@ void SpiComIF::getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& spee } } -const std::string& SpiComIF::getSpiDev() const { return dev; } +const std::string& SpiComIF::getSpiDev() const { + return dev; +} + +void SpiComIF::updateLinePolarity(int spiFd) { + clockUpdateTransfer.len = 0; + int retval = ioctl(spiFd, SPI_IOC_MESSAGE(1), &clockUpdateTransfer); + if (retval != 0) { + utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Updating SPI default clock failed"); + } +} diff --git a/hal/src/fsfw_hal/linux/spi/SpiComIF.h b/hal/src/fsfw_hal/linux/spi/SpiComIF.h index 881af8c4..aca94765 100644 --- a/hal/src/fsfw_hal/linux/spi/SpiComIF.h +++ b/hal/src/fsfw_hal/linux/spi/SpiComIF.h @@ -59,6 +59,17 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject { GpioIF* getGpioInterface(); void setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed); + + /** + * 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); void getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& speed) const; const std::string& getSpiDev() const; @@ -74,7 +85,11 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject { GpioIF* gpioComIF = nullptr; std::string dev = ""; - MutexIF* spiMutex = nullptr; + /** + * Protects the chip select operations. Lock when GPIO is pulled low, unlock after it was + * pulled high + */ + MutexIF* csMutex = nullptr; MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; uint32_t timeoutMs = 20; spi_ioc_transfer clockUpdateTransfer = {};