refactored some components

This commit is contained in:
Robin Müller 2021-06-11 10:37:48 +02:00
parent 543ee54cca
commit 3e8de10866
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
6 changed files with 120 additions and 68 deletions

View File

@ -11,10 +11,11 @@
#include "stm32h7xx_hal_gpio.h" #include "stm32h7xx_hal_gpio.h"
SpiComIF::SpiComIF(object_id_t objectId): SystemObject(objectId) { SpiComIF::SpiComIF(object_id_t objectId): SystemObject(objectId) {
spi::assignTransferRxTxCompleteCallback(&spiTransferCompleteCallback, this); void* irqArgsVoided = reinterpret_cast<void*>(&irqArgs);
spi::assignTransferRxCompleteCallback(&spiTransferRxCompleteCallback, this); spi::assignTransferRxTxCompleteCallback(&spiTransferCompleteCallback, irqArgsVoided);
spi::assignTransferTxCompleteCallback(&spiTransferTxCompleteCallback, this); spi::assignTransferRxCompleteCallback(&spiTransferRxCompleteCallback, irqArgsVoided);
spi::assignTransferErrorCallback(&spiTransferErrorCallback, this); spi::assignTransferTxCompleteCallback(&spiTransferTxCompleteCallback, irqArgsVoided);
spi::assignTransferErrorCallback(&spiTransferErrorCallback, irqArgsVoided);
} }
void SpiComIF::configureCacheMaintenanceOnTxBuffer(bool enable) { void SpiComIF::configureCacheMaintenanceOnTxBuffer(bool enable) {
@ -112,20 +113,20 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) {
spi::setSpiIrqMspFunctions(typedCfg); spi::setSpiIrqMspFunctions(typedCfg);
} }
else if(transferMode == spi::TransferModes::DMA) { else if(transferMode == spi::TransferModes::DMA) {
auto typedCfg = dynamic_cast<spi::MspDmaConfigStruct*>(mspCfg); auto typedCfg = dynamic_cast<spi::MspDmaConfigStruct*>(mspCfg);
if(typedCfg == nullptr) { if(typedCfg == nullptr) {
printCfgError("DMA MSP"); printCfgError("DMA MSP");
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
// Check DMA handles // Check DMA handles
DMA_HandleTypeDef* txHandle = nullptr; DMA_HandleTypeDef* txHandle = nullptr;
DMA_HandleTypeDef* rxHandle = nullptr; DMA_HandleTypeDef* rxHandle = nullptr;
spi::getDmaHandles(&txHandle, &rxHandle); spi::getDmaHandles(&txHandle, &rxHandle);
if(txHandle == nullptr or rxHandle == nullptr) { if(txHandle == nullptr or rxHandle == nullptr) {
printCfgError("DMA Handle"); printCfgError("DMA Handle");
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
spi::setSpiDmaMspFunctions(typedCfg); spi::setSpiDmaMspFunctions(typedCfg);
} }
gpio::initializeGpioClock(gpioPort); gpio::initializeGpioClock(gpioPort);
@ -160,6 +161,17 @@ ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, s
iter->second.currentTransferLen = sendLen; iter->second.currentTransferLen = sendLen;
auto transferMode = spiCookie->getTransferMode(); auto transferMode = spiCookie->getTransferMode();
switch(spiCookie->getTransferState()) {
case(spi::TransferStates::IDLE): {
break;
}
case(spi::TransferStates::WAIT):
case(spi::TransferStates::FAILURE):
case(spi::TransferStates::SUCCESS):
default: {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
switch(transferMode) { switch(transferMode) {
case(spi::TransferModes::POLLING): { case(spi::TransferModes::POLLING): {
@ -191,12 +203,37 @@ ReturnValue_t SpiComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buffer,
if(spiCookie == nullptr) { if(spiCookie == nullptr) {
return NULLPOINTER; return NULLPOINTER;
} }
auto iter = spiDeviceMap.find(spiCookie->getDeviceAddress()); switch(spiCookie->getTransferState()) {
if(iter == spiDeviceMap.end()) { case(spi::TransferStates::SUCCESS): {
auto iter = spiDeviceMap.find(spiCookie->getDeviceAddress());
if(iter == spiDeviceMap.end()) {
return HasReturnvaluesIF::RETURN_FAILED;
}
*buffer = iter->second.replyBuffer.data();
*size = iter->second.currentTransferLen;
spiCookie->setTransferState(spi::TransferStates::IDLE);
break;
}
case(spi::TransferStates::FAILURE): {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "SpiComIF::readReceivedMessage: Transfer failure" << std::endl;
#else
sif::printWarning("SpiComIF::readReceivedMessage: Transfer failure\n");
#endif
#endif
spiCookie->setTransferState(spi::TransferStates::IDLE);
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
*buffer = iter->second.replyBuffer.data(); case(spi::TransferStates::WAIT):
*size = iter->second.currentTransferLen; case(spi::TransferStates::IDLE): {
break;
}
default: {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -212,6 +249,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SPI_HandleT
if(returnval != HasReturnvaluesIF::RETURN_OK) { if(returnval != HasReturnvaluesIF::RETURN_OK) {
return returnval; return returnval;
} }
spiCookie.setTransferState(spi::TransferStates::WAIT);
HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_RESET); HAL_GPIO_WritePin(gpioPort, gpioPin, GPIO_PIN_RESET);
auto result = HAL_SPI_TransmitReceive(&spiHandle, const_cast<uint8_t*>(sendData), auto result = HAL_SPI_TransmitReceive(&spiHandle, const_cast<uint8_t*>(sendData),
recvPtr, sendLen, defaultPollingTimeout); recvPtr, sendLen, defaultPollingTimeout);
@ -219,6 +257,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SPI_HandleT
spiSemaphore->release(); spiSemaphore->release();
switch(result) { switch(result) {
case(HAL_OK): { case(HAL_OK): {
spiCookie.setTransferState(spi::TransferStates::SUCCESS);
break; break;
} }
case(HAL_TIMEOUT): { case(HAL_TIMEOUT): {
@ -231,6 +270,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SPI_HandleT
spiCookie.getDeviceAddress()); spiCookie.getDeviceAddress());
#endif #endif
#endif #endif
spiCookie.setTransferState(spi::TransferStates::FAILURE);
return spi::HAL_TIMEOUT_RETVAL; return spi::HAL_TIMEOUT_RETVAL;
} }
case(HAL_ERROR): case(HAL_ERROR):
@ -244,6 +284,7 @@ ReturnValue_t SpiComIF::handlePollingSendOperation(uint8_t* recvPtr, SPI_HandleT
spiCookie.getDeviceAddress()); spiCookie.getDeviceAddress());
#endif #endif
#endif #endif
spiCookie.setTransferState(spi::TransferStates::FAILURE);
return spi::HAL_ERROR_RETVAL; return spi::HAL_ERROR_RETVAL;
} }
} }
@ -323,9 +364,6 @@ ReturnValue_t SpiComIF::halErrorHandler(HAL_StatusTypeDef status, spi::TransferM
ReturnValue_t SpiComIF::genericIrqSendSetup(uint8_t *recvPtr, SPI_HandleTypeDef& spiHandle, ReturnValue_t SpiComIF::genericIrqSendSetup(uint8_t *recvPtr, SPI_HandleTypeDef& spiHandle,
SpiCookie& spiCookie, const uint8_t *sendData, size_t sendLen) { SpiCookie& spiCookie, const uint8_t *sendData, size_t sendLen) {
// These are required by the callback
currentGpioPort = spiCookie.getChipSelectGpioPort();
currentGpioPin = spiCookie.getChipSelectGpioPin();
currentRecvPtr = recvPtr; currentRecvPtr = recvPtr;
currentRecvBuffSize = sendLen; currentRecvBuffSize = sendLen;
@ -339,53 +377,53 @@ ReturnValue_t SpiComIF::genericIrqSendSetup(uint8_t *recvPtr, SPI_HandleTypeDef&
} }
// Cache the current SPI handle in any case // Cache the current SPI handle in any case
spi::setSpiHandle(&spiHandle); spi::setSpiHandle(&spiHandle);
// The SPI handle is passed to the default SPI callback as a void argument // Assign the IRQ arguments for the user callbacks
irqArgs.comIF = this;
irqArgs.spiCookie = &spiCookie;
// The SPI handle is passed to the default SPI callback as a void argument. This callback
// is different from the user callbacks specified above!
spi::assignSpiUserArgs(spiCookie.getSpiIdx(), reinterpret_cast<void*>(&spiHandle)); spi::assignSpiUserArgs(spiCookie.getSpiIdx(), reinterpret_cast<void*>(&spiHandle));
HAL_GPIO_WritePin(currentGpioPort, currentGpioPin, GPIO_PIN_RESET); HAL_GPIO_WritePin(spiCookie.getChipSelectGpioPort(), spiCookie.getChipSelectGpioPin(),
GPIO_PIN_RESET);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void SpiComIF::spiTransferTxCompleteCallback(SPI_HandleTypeDef *hspi, void *args) { void SpiComIF::spiTransferTxCompleteCallback(SPI_HandleTypeDef *hspi, void *args) {
SpiComIF* spiComIF = reinterpret_cast<SpiComIF*>(args); genericIrqHandler(args, spi::TransferStates::SUCCESS);
if(spiComIF == nullptr) {
return;
}
genericIrqHandler(spiComIF, TransferStates::FAILURE);
} }
void SpiComIF::spiTransferRxCompleteCallback(SPI_HandleTypeDef *hspi, void *args) { void SpiComIF::spiTransferRxCompleteCallback(SPI_HandleTypeDef *hspi, void *args) {
SpiComIF* spiComIF = reinterpret_cast<SpiComIF*>(args); genericIrqHandler(args, spi::TransferStates::SUCCESS);
if(spiComIF == nullptr) {
return;
}
genericIrqHandler(spiComIF, TransferStates::FAILURE);
} }
void SpiComIF::spiTransferCompleteCallback(SPI_HandleTypeDef *hspi, void *args) { void SpiComIF::spiTransferCompleteCallback(SPI_HandleTypeDef *hspi, void *args) {
SpiComIF* spiComIF = reinterpret_cast<SpiComIF*>(args); genericIrqHandler(args, spi::TransferStates::SUCCESS);
if(spiComIF == nullptr) {
return;
}
genericIrqHandler(spiComIF, TransferStates::FAILURE);
} }
void SpiComIF::spiTransferErrorCallback(SPI_HandleTypeDef *hspi, void *args) { void SpiComIF::spiTransferErrorCallback(SPI_HandleTypeDef *hspi, void *args) {
SpiComIF* spiComIF = reinterpret_cast<SpiComIF*>(args); genericIrqHandler(args, spi::TransferStates::FAILURE);
if(spiComIF == nullptr) {
return;
}
genericIrqHandler(spiComIF, TransferStates::FAILURE);
} }
void SpiComIF::genericIrqHandler(SpiComIF *spiComIF, TransferStates targetState) { void SpiComIF::genericIrqHandler(void *irqArgsVoid, spi::TransferStates targetState) {
spiComIF->transferState = TransferStates::SUCCESS; IrqArgs* irqArgs = reinterpret_cast<IrqArgs*>(irqArgsVoid);
if(irqArgs == nullptr) {
return;
}
SpiCookie* spiCookie = irqArgs->spiCookie;
SpiComIF* comIF = irqArgs->comIF;
if(spiCookie == nullptr or comIF == nullptr) {
return;
}
spiCookie->setTransferState(targetState);
// Pull CS pin high again // Pull CS pin high again
HAL_GPIO_WritePin(spiComIF->currentGpioPort, spiComIF->currentGpioPin, GPIO_PIN_SET); HAL_GPIO_WritePin(spiCookie->getChipSelectGpioPort(), spiCookie->getChipSelectGpioPin(),
GPIO_PIN_SET);
// Release the task semaphore // Release the task semaphore
BaseType_t taskWoken = pdFALSE; BaseType_t taskWoken = pdFALSE;
ReturnValue_t result = BinarySemaphore::releaseFromISR(spiComIF->spiSemaphore->getSemaphore(), ReturnValue_t result = BinarySemaphore::releaseFromISR(comIF->spiSemaphore->getSemaphore(),
&taskWoken); &taskWoken);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
// Configuration error // Configuration error
@ -393,10 +431,10 @@ void SpiComIF::genericIrqHandler(SpiComIF *spiComIF, TransferStates targetState)
} }
// Perform cache maintenance operation for DMA transfers // Perform cache maintenance operation for DMA transfers
if(spiComIF->currentTransferMode == spi::TransferModes::DMA) { if(spiCookie->getTransferMode() == spi::TransferModes::DMA) {
// Invalidate cache prior to access by CPU // Invalidate cache prior to access by CPU
SCB_InvalidateDCache_by_Addr ((uint32_t *) spiComIF->currentRecvPtr, SCB_InvalidateDCache_by_Addr ((uint32_t *) comIF->currentRecvPtr,
spiComIF->currentRecvBuffSize); comIF->currentRecvBuffSize);
} }
/* Request a context switch if the SPI ComIF task was woken up and has a higher priority /* Request a context switch if the SPI ComIF task was woken up and has a higher priority
than the currently running task */ than the currently running task */

View File

@ -15,13 +15,6 @@
class SpiCookie; class SpiCookie;
enum class TransferStates {
IDLE,
WAIT,
SUCCESS,
FAILURE
};
/** /**
* @brief This communication interface allows using generic device handlers with using * @brief This communication interface allows using generic device handlers with using
* the STM32H7 SPI peripherals * the STM32H7 SPI peripherals
@ -87,11 +80,17 @@ private:
size_t currentTransferLen = 0; size_t currentTransferLen = 0;
}; };
struct IrqArgs {
SpiComIF* comIF = nullptr;
SpiCookie* spiCookie = nullptr;
};
IrqArgs irqArgs;
uint32_t defaultPollingTimeout = 50; uint32_t defaultPollingTimeout = 50;
SemaphoreIF::TimeoutType timeoutType = SemaphoreIF::TimeoutType::WAITING; SemaphoreIF::TimeoutType timeoutType = SemaphoreIF::TimeoutType::WAITING;
dur_millis_t timeoutMs = 20; dur_millis_t timeoutMs = 20;
spi::TransferModes currentTransferMode = spi::TransferModes::POLLING;
BinarySemaphore* spiSemaphore = nullptr; BinarySemaphore* spiSemaphore = nullptr;
bool cacheMaintenanceOnTxBuffer = true; bool cacheMaintenanceOnTxBuffer = true;
@ -99,11 +98,8 @@ private:
using SpiDeviceMap = std::map<address_t, SpiInstance>; using SpiDeviceMap = std::map<address_t, SpiInstance>;
using SpiDeviceMapIter = SpiDeviceMap::iterator; using SpiDeviceMapIter = SpiDeviceMap::iterator;
GPIO_TypeDef* currentGpioPort = nullptr;
uint16_t currentGpioPin = 0;
uint8_t* currentRecvPtr = nullptr; uint8_t* currentRecvPtr = nullptr;
size_t currentRecvBuffSize = 0; size_t currentRecvBuffSize = 0;
volatile TransferStates transferState = TransferStates::IDLE;
SpiDeviceMap spiDeviceMap; SpiDeviceMap spiDeviceMap;
@ -124,7 +120,7 @@ private:
static void spiTransferCompleteCallback(SPI_HandleTypeDef *hspi, void* args); static void spiTransferCompleteCallback(SPI_HandleTypeDef *hspi, void* args);
static void spiTransferErrorCallback(SPI_HandleTypeDef *hspi, void* args); static void spiTransferErrorCallback(SPI_HandleTypeDef *hspi, void* args);
static void genericIrqHandler(SpiComIF* comIF, TransferStates targetState); static void genericIrqHandler(void* irqArgs, spi::TransferStates targetState);
void printCfgError(const char* const type); void printCfgError(const char* const type);
}; };

View File

@ -68,3 +68,11 @@ void SpiCookie::deleteMspCfg() {
spi::TransferModes SpiCookie::getTransferMode() const { spi::TransferModes SpiCookie::getTransferMode() const {
return transferMode; return transferMode;
} }
void SpiCookie::setTransferState(spi::TransferStates transferState) {
this->transferState = transferState;
}
spi::TransferStates SpiCookie::getTransferState() const {
return this->transferState;
}

View File

@ -54,6 +54,7 @@ private:
uint32_t spiSpeed; uint32_t spiSpeed;
spi::SpiModes spiMode; spi::SpiModes spiMode;
spi::TransferModes transferMode; spi::TransferModes transferMode;
volatile spi::TransferStates transferState = spi::TransferStates::IDLE;
uint16_t chipSelectGpioPin; uint16_t chipSelectGpioPin;
GPIO_TypeDef* chipSelectGpioPort; GPIO_TypeDef* chipSelectGpioPort;
// The MSP configuration is cached here. Be careful when using this, it is automatically // The MSP configuration is cached here. Be careful when using this, it is automatically
@ -64,6 +65,9 @@ private:
// Only the SpiComIF is allowed to use this to prevent dangling pointers issues // Only the SpiComIF is allowed to use this to prevent dangling pointers issues
spi::MspCfgBase* getMspCfg(); spi::MspCfgBase* getMspCfg();
void deleteMspCfg(); void deleteMspCfg();
void setTransferState(spi::TransferStates transferState);
spi::TransferStates getTransferState() const;
}; };

View File

@ -16,6 +16,13 @@ static constexpr ReturnValue_t HAL_TIMEOUT_RETVAL = HasReturnvaluesIF::makeRetur
static constexpr ReturnValue_t HAL_BUSY_RETVAL = HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 1); static constexpr ReturnValue_t HAL_BUSY_RETVAL = HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 1);
static constexpr ReturnValue_t HAL_ERROR_RETVAL = HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 2); static constexpr ReturnValue_t HAL_ERROR_RETVAL = HasReturnvaluesIF::makeReturnCode(HAL_SPI_ID, 2);
enum class TransferStates {
IDLE,
WAIT,
SUCCESS,
FAILURE
};
enum SpiBus { enum SpiBus {
SPI_1, SPI_1,
SPI_2 SPI_2

View File

@ -42,8 +42,7 @@ void spi::dmaTxIrqHandler(void* dmaHandle) {
* @param None * @param None
* @retval None * @retval None
*/ */
void spi::spiIrqHandler(void* spiHandle) void spi::spiIrqHandler(void* spiHandle) {
{
if(spiHandle == nullptr) { if(spiHandle == nullptr) {
return; return;
} }