#include "SpiComIF.h" #include "SpiCookie.h" #include "fsfw/tasks/SemaphoreFactory.h" #include "fsfw_hal/stm32h7/spi/spiCore.h" #include "stm32h7xx_hal_gpio.h" SpiComIF::SpiComIF(object_id_t objectId, SPI_TypeDef* spiInstance, SPI_HandleTypeDef* spiHandle, spi::TransferModes transferMode): SystemObject(objectId), transferMode(transferMode), spiHandle(spiHandle) { if(spiHandle == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "SpiComIF::SpiComIF: Passed SPI handle invalid!" << std::endl; #else sif::printError("SpiComIF::SpiComIF: Passed SPI handle invalid!\n"); #endif return; } spiHandle->Instance = spiInstance; spiHandle->Init.DataSize = SPI_DATASIZE_8BIT; spiHandle->Init.FirstBit = SPI_FIRSTBIT_MSB; spiHandle->Init.TIMode = SPI_TIMODE_DISABLE; spiHandle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; spiHandle->Init.CRCPolynomial = 7; spiHandle->Init.CRCLength = SPI_CRC_LENGTH_8BIT; spiHandle->Init.NSS = SPI_NSS_SOFT; spiHandle->Init.NSSPMode = SPI_NSS_PULSE_DISABLE; spiHandle->Init.Direction = SPI_DIRECTION_2LINES; // Recommended setting to avoid glitches spiHandle->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; spiHandle->Init.Mode = SPI_MODE_MASTER; } void SpiComIF::configureCacheMaintenanceOnTxBuffer(bool enable) { this->cacheMaintenanceOnTxBuffer = enable; } void SpiComIF::addDmaHandles(DMA_HandleTypeDef *txHandle, DMA_HandleTypeDef *rxHandle) { set_dma_handles(txHandle, rxHandle); } ReturnValue_t SpiComIF::initialize() { if(transferMode == spi::TransferModes::DMA) { DMA_HandleTypeDef *txHandle = nullptr; DMA_HandleTypeDef *rxHandle = nullptr; get_dma_handles(&txHandle, &rxHandle); if(txHandle == nullptr or rxHandle == nullptr) { sif::printError("SpiComIF::initialize: DMA handles not set!\n"); return HasReturnvaluesIF::RETURN_FAILED; } } if(HAL_SPI_Init(spiHandle) != HAL_OK) { sif::printWarning("SpiComIF::initialize: Error initializing SPI\n"); return HasReturnvaluesIF::RETURN_FAILED; } return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { SpiCookie* spiCookie = dynamic_cast(cookie); if(spiCookie == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error < "SpiComIF::initializeInterface: Invalid cookie" << std::endl; #else sif::printError("SpiComIF::initializeInterface: Invalid cookie\n"); #endif return NULLPOINTER; } if(transferMode == spi::TransferModes::DMA or transferMode == spi::TransferModes::INTERRUPT) { spiSemaphore = SemaphoreFactory::instance()->createBinarySemaphore(); } else { spiMutex = MutexFactory::instance()->createMutex(); } address_t spiAddress = spiCookie->getDeviceAddress(); auto iter = spiDeviceMap.find(spiAddress); if(iter == spiDeviceMap.end()) { size_t bufferSize = spiCookie->getMaxRecvSize(); SpiInstance spiInstance = {std::vector(bufferSize)}; auto statusPair = spiDeviceMap.emplace(spiAddress, spiInstance); if (not statusPair.second) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "SpiComIF::initializeInterface: Failed to insert device with address " << spiAddress << "to SPI device map" << std::endl; #else sif::printError("SpiComIF::initializeInterface: Failed to insert device with address " "%lu to SPI device map\n", static_cast(spiAddress)); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ return HasReturnvaluesIF::RETURN_FAILED; } } auto gpioPin = spiCookie->getChipSelectGpioPin(); auto gpioPort = spiCookie->getChipSelectGpioPort(); GPIO_InitTypeDef chipSelect = {}; chipSelect.Pin = gpioPin; chipSelect.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(gpioPort, &chipSelect); HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_SET); return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen) { SpiCookie* spiCookie = dynamic_cast(cookie); if(spiCookie == nullptr) { return NULLPOINTER; } spi::assignSpiMode(spiCookie->getSpiMode(), spiHandle); spiHandle->Init.BaudRatePrescaler = spi::getPrescaler(HAL_RCC_GetHCLKFreq(), spiCookie->getSpiSpeed()); auto iter = spiDeviceMap.find(spiCookie->getDeviceAddress()); if(iter == spiDeviceMap.end()) { return HasReturnvaluesIF::RETURN_FAILED; } switch(transferMode) { case(spi::TransferModes::POLLING): { return handlePollingSendOperation(iter->second.replyBuffer.data(), spiCookie, sendData, sendLen); } case(spi::TransferModes::INTERRUPT): { return handleInterruptSendOperation(iter->second.replyBuffer.data(), spiCookie, sendData, sendLen); } case(spi::TransferModes::DMA): { return handleDmaSendOperation(iter->second.replyBuffer.data(), spiCookie, sendData, sendLen); } } return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t SpiComIF::getSendSuccess(CookieIF *cookie) { return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t SpiComIF::requestReceiveMessage(CookieIF *cookie, size_t requestLen) { return HasReturnvaluesIF::RETURN_OK; } void SpiComIF::setDefaultPollingTimeout(dur_millis_t timeout) { this->defaultPollingTimeout = timeout; } ReturnValue_t SpiComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) { return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SpiCookie *spiCookie, const uint8_t *sendData, size_t sendLen) { auto gpioPort = spiCookie->getChipSelectGpioPort(); auto gpioPin = spiCookie->getChipSelectGpioPin(); spiMutex->lockMutex(timeoutType, timeoutMs); HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_RESET); auto result = HAL_SPI_TransmitReceive(spiHandle, const_cast(sendData), recvPtr, sendLen, defaultPollingTimeout); HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_SET); spiMutex->unlockMutex(); switch(result) { case(HAL_OK): { break; } case(HAL_TIMEOUT): { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "SpiComIF::sendMessage: Polling Mode | Timeout for SPI device" << spiCookie->getDeviceAddress() << std::endl; #else sif::printWarning("SpiComIF::sendMessage: Polling Mode | Timeout for SPI device %d\n", spiCookie->getDeviceAddress()); #endif #endif return spi::HAL_TIMEOUT_RETVAL; } case(HAL_ERROR): default: { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "SpiComIF::sendMessage: Polling Mode | HAL error for SPI device" << spiCookie->getDeviceAddress() << std::endl; #else sif::printWarning("SpiComIF::sendMessage: Polling Mode | HAL error for SPI device %d\n", spiCookie->getDeviceAddress()); #endif #endif return spi::HAL_ERROR_RETVAL; } } return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t SpiComIF::handleInterruptSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, const uint8_t * sendData, size_t sendLen) { return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t SpiComIF::handleDmaSendOperation(uint8_t* recvPtr, SpiCookie* spiCookie, const uint8_t * sendData, size_t sendLen) { return HasReturnvaluesIF::RETURN_OK; }