diff --git a/devicehandlers/GyroL3GD20Handler.cpp b/devicehandlers/GyroL3GD20Handler.cpp index 4ab4724..79cbe43 100644 --- a/devicehandlers/GyroL3GD20Handler.cpp +++ b/devicehandlers/GyroL3GD20Handler.cpp @@ -6,7 +6,7 @@ GyroHandlerL3GD20H::GyroHandlerL3GD20H(object_id_t objectId, object_id_t deviceC CookieIF *comCookie): DeviceHandlerBase(objectId, deviceCommunication, comCookie), dataset(this) { -#if L3GD20_GYRO_DEBUG == 1 +#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1 debugDivider = new PeriodicOperationDivider(5); #endif } @@ -28,11 +28,12 @@ void GyroHandlerL3GD20H::doStartUp() { if(internalState == InternalState::CHECK_REGS) { if(commandExecuted) { internalState = InternalState::NORMAL; -#if OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP == 1 - setMode(MODE_NORMAL); -#else - setMode(_MODE_TO_ON); -#endif + if(goNormalModeImmediately) { + setMode(MODE_NORMAL); + } + else { + setMode(_MODE_TO_ON); + } commandExecuted = false; } } @@ -85,9 +86,7 @@ ReturnValue_t GyroHandlerL3GD20H::buildCommandFromCommand( size_t commandDataLen) { switch(deviceCommand) { case(L3GD20H::READ_REGS): { - commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | - L3GD20H::READ_MASK; - + commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | L3GD20H::READ_MASK; std::memset(commandBuffer + 1, 0, L3GD20H::READ_LEN); rawPacket = commandBuffer; rawPacketLen = L3GD20H::READ_LEN + 1; @@ -196,7 +195,7 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id, int8_t temperaturOffset = (-1) * packet[L3GD20H::TEMPERATURE_IDX]; float temperature = 25.0 + temperaturOffset; -#if L3GD20_GYRO_DEBUG == 1 +#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1 if(debugDivider->checkAndIncrement()) { /* Set terminal to utf-8 if there is an issue with micro printout. */ #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -235,6 +234,10 @@ uint32_t GyroHandlerL3GD20H::getTransitionDelayMs(Mode_t from, Mode_t to) { return 10000; } +void GyroHandlerL3GD20H::setGoNormalModeAtStartup() { + this->goNormalModeImmediately = true; +} + ReturnValue_t GyroHandlerL3GD20H::initializeLocalDataPool( localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { localDataPoolMap.emplace(L3GD20H::ANG_VELOC_X, diff --git a/devicehandlers/GyroL3GD20Handler.h b/devicehandlers/GyroL3GD20Handler.h index fb9baac..f82ba93 100644 --- a/devicehandlers/GyroL3GD20Handler.h +++ b/devicehandlers/GyroL3GD20Handler.h @@ -7,9 +7,9 @@ #include #include -#ifndef L3GD20_GYRO_DEBUG -#define L3GD20_GYRO_DEBUG 1 -#endif +#ifndef FSFW_HAL_L3GD20_GYRO_DEBUG +#define FSFW_HAL_L3GD20_GYRO_DEBUG 1 +#endif /* FSFW_HAL_L3GD20_GYRO_DEBUG */ /** * @brief Device Handler for the L3GD20H gyroscope sensor @@ -26,6 +26,7 @@ public: CookieIF* comCookie); virtual ~GyroHandlerL3GD20H(); + void setGoNormalModeAtStartup(); protected: /* DeviceHandlerBase overrides */ @@ -62,6 +63,7 @@ private: bool commandExecuted = false; uint8_t statusReg = 0; + bool goNormalModeImmediately = false; uint8_t ctrlReg1Value = L3GD20H::CTRL_REG_1_VAL; uint8_t ctrlReg2Value = L3GD20H::CTRL_REG_2_VAL; @@ -74,7 +76,7 @@ private: // Set default value float sensitivity = L3GD20H::SENSITIVITY_00; -#if L3GD20_GYRO_DEBUG == 1 +#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1 PeriodicOperationDivider* debugDivider = nullptr; #endif }; diff --git a/stm32h7/CMakeLists.txt b/stm32h7/CMakeLists.txt index b98a9c3..63c1373 100644 --- a/stm32h7/CMakeLists.txt +++ b/stm32h7/CMakeLists.txt @@ -3,5 +3,5 @@ add_subdirectory(gpio) add_subdirectory(devicetest) target_sources(${LIB_FSFW_HAL_NAME} PRIVATE - dmaInterrupts.cpp + dma.cpp ) diff --git a/stm32h7/devicetest/GyroL3GD20H.cpp b/stm32h7/devicetest/GyroL3GD20H.cpp index 54f69bc..240b159 100644 --- a/stm32h7/devicetest/GyroL3GD20H.cpp +++ b/stm32h7/devicetest/GyroL3GD20H.cpp @@ -3,6 +3,8 @@ #include "../spi/mspInit.h" #include "../spi/spiDefinitions.h" #include "../spi/spiCore.h" +#include "../spi/spiInterrupts.h" +#include "../spi/stm32h743ziSpi.h" #include "fsfw/tasks/TaskFactory.h" #include "fsfw/serviceinterface/ServiceInterface.h" @@ -20,24 +22,32 @@ GyroL3GD20H::txBuffer __attribute__((section(".dma_buffer"))); TransferStates transferState = TransferStates::IDLE; spi::TransferModes GyroL3GD20H::transferMode = spi::TransferModes::POLLING; -DMA_HandleTypeDef txDmaHandle; -DMA_HandleTypeDef rxDmaHandle; GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transferMode_): - spiHandle(spiHandle) { + spiHandle(spiHandle) { + txDmaHandle = new DMA_HandleTypeDef(); + rxDmaHandle = new DMA_HandleTypeDef(); + spi::setSpiHandle(spiHandle); transferMode = transferMode_; if(transferMode == spi::TransferModes::DMA) { - spi::setDmaHandles(&txDmaHandle, &rxDmaHandle); - spi::setSpiMspFunctions(&spi::halMspInitDma, spiHandle, - &spi::halMspDeinitDma, spiHandle); + mspCfg = new spi::MspDmaConfigStruct(); + auto typedCfg = dynamic_cast(mspCfg); + spi::setDmaHandles(txDmaHandle, rxDmaHandle); + spi::h743zi::standardDmaCfg(*typedCfg, IrqPriorities::HIGHEST_FREERTOS, + IrqPriorities::HIGHEST_FREERTOS, IrqPriorities::HIGHEST_FREERTOS); + spi::setSpiDmaMspFunctions(typedCfg); } else if(transferMode == spi::TransferModes::INTERRUPT) { - spi::setSpiMspFunctions(&spi::halMspInitInterrupt, spiHandle, - &spi::halMspDeinitInterrupt, spiHandle); + mspCfg = new spi::MspIrqConfigStruct(); + auto typedCfg = dynamic_cast(mspCfg); + spi::h743zi::standardInterruptCfg(*typedCfg, IrqPriorities::HIGHEST_FREERTOS); + spi::setSpiIrqMspFunctions(typedCfg); } else if(transferMode == spi::TransferModes::POLLING) { - spi::setSpiMspFunctions(&spi::halMspInitPolling, spiHandle, - &spi::halMspDeinitPolling, spiHandle); + mspCfg = new spi::MspPollingConfigStruct(); + auto typedCfg = dynamic_cast(mspCfg); + spi::h743zi::standardPollingCfg(*typedCfg); + spi::setSpiPollingMspFunctions(typedCfg); } spi::assignTransferRxTxCompleteCallback(&spiTransferCompleteCallback, nullptr); @@ -51,6 +61,12 @@ GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transf HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); } +GyroL3GD20H::~GyroL3GD20H() { + delete txDmaHandle; + delete rxDmaHandle; + delete mspCfg; +} + ReturnValue_t GyroL3GD20H::initialize() { // Configure the SPI peripheral spiHandle->Instance = SPI1; diff --git a/stm32h7/devicetest/GyroL3GD20H.h b/stm32h7/devicetest/GyroL3GD20H.h index 641c938..b65654d 100644 --- a/stm32h7/devicetest/GyroL3GD20H.h +++ b/stm32h7/devicetest/GyroL3GD20H.h @@ -3,8 +3,9 @@ #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_spi.h" - +#include "../spi/mspInit.h" #include "../spi/spiDefinitions.h" + #include "fsfw/returnvalues/HasReturnvaluesIF.h" #include @@ -20,6 +21,7 @@ enum class TransferStates { class GyroL3GD20H { public: GyroL3GD20H(SPI_HandleTypeDef* spiHandle, spi::TransferModes transferMode); + ~GyroL3GD20H(); ReturnValue_t initialize(); ReturnValue_t performOperation(); @@ -58,6 +60,11 @@ private: void prepareConfigRegs(uint8_t* configRegs); void handleSensorReadout(); + + + DMA_HandleTypeDef* txDmaHandle = {}; + DMA_HandleTypeDef* rxDmaHandle = {}; + spi::MspCfgBase* mspCfg = {}; }; #endif /* FSFW_HAL_STM32H7_DEVICETEST_GYRO_L3GD20H_H_ */ diff --git a/stm32h7/dmaInterrupts.cpp b/stm32h7/dma.cpp similarity index 98% rename from stm32h7/dmaInterrupts.cpp rename to stm32h7/dma.cpp index a10793d..91fb338 100644 --- a/stm32h7/dmaInterrupts.cpp +++ b/stm32h7/dma.cpp @@ -1,5 +1,4 @@ -#include "dmaInterrupts.h" - +#include #include #include diff --git a/stm32h7/dmaInterrupts.h b/stm32h7/dma.h similarity index 73% rename from stm32h7/dmaInterrupts.h rename to stm32h7/dma.h index 49eaba7..779a64c 100644 --- a/stm32h7/dmaInterrupts.h +++ b/stm32h7/dma.h @@ -1,18 +1,24 @@ -#ifndef FSFW_HAL_STM32H7_DMAINTERRUPTS_H_ -#define FSFW_HAL_STM32H7_DMAINTERRUPTS_H_ +#ifndef FSFW_HAL_STM32H7_DMA_H_ +#define FSFW_HAL_STM32H7_DMA_H_ #ifdef __cplusplus extern "C" { #endif #include "interrupts.h" +#include namespace dma { -enum DMAIndexes { - DMA_1 = 0, - DMA_2 = 1 -} ; +enum DMAType { + TX = 0, + RX = 1 +}; + +enum DMAIndexes: uint8_t { + DMA_1 = 1, + DMA_2 = 2 +}; enum DMAStreams { STREAM_0 = 0, @@ -40,4 +46,4 @@ void assignDmaUserHandler(DMAIndexes dma_idx, DMAStreams stream_idx, } #endif -#endif /* FSFW_HAL_STM32H7_DMAINTERRUPTS_H_ */ +#endif /* FSFW_HAL_STM32H7_DMA_H_ */ diff --git a/stm32h7/interrupts.h b/stm32h7/interrupts.h index 00c8a79..aef60bf 100644 --- a/stm32h7/interrupts.h +++ b/stm32h7/interrupts.h @@ -1,6 +1,8 @@ #ifndef FSFW_HAL_STM32H7_INTERRUPTS_H_ #define FSFW_HAL_STM32H7_INTERRUPTS_H_ +#include + #ifdef __cplusplus extern "C" { #endif @@ -13,6 +15,12 @@ extern void Default_Handler(); typedef void (*user_handler_t) (void*); typedef void* user_args_t; +enum IrqPriorities: uint8_t { + HIGHEST = 0, + HIGHEST_FREERTOS = 6, + LOWEST = 15 +}; + #ifdef __cplusplus } #endif diff --git a/stm32h7/spi/CMakeLists.txt b/stm32h7/spi/CMakeLists.txt index ba814e2..fb4f647 100644 --- a/stm32h7/spi/CMakeLists.txt +++ b/stm32h7/spi/CMakeLists.txt @@ -5,4 +5,5 @@ target_sources(${LIB_FSFW_HAL_NAME} PRIVATE mspInit.cpp SpiCookie.cpp SpiComIF.cpp + stm32h743ziSpi.cpp ) diff --git a/stm32h7/spi/SpiComIF.cpp b/stm32h7/spi/SpiComIF.cpp index b36a09e..6230c0c 100644 --- a/stm32h7/spi/SpiComIF.cpp +++ b/stm32h7/spi/SpiComIF.cpp @@ -83,8 +83,16 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) { SPI_HandleTypeDef& spiHandle = spiCookie->getSpiHandle(); if(transferMode == spi::TransferModes::POLLING) { - spi::setSpiMspFunctions(&spi::halMspInitPolling, &spiHandle, - &spi::halMspDeinitPolling, &spiHandle); +// spi::setSpiMspFunctions(&spi::halMspInitPolling, &spiHandle, +// &spi::halMspDeinitPolling, &spiHandle); + } + else if(transferMode == spi::TransferModes::INTERRUPT) { +// spi::setSpiMspFunctions(&spi::halMspInitInterrupt, &spiHandle, +// &spi::halMspDeinitPolling, &spiHandle); + } + else if(transferMode == spi::TransferModes::DMA) { +// spi::setSpiMspFunctions(&spi::halMspInitDma, &spiHandle, +// &spi::halMspDeinitDma, &spiHandle); } gpio::initializeGpioClock(gpioPort); diff --git a/stm32h7/spi/mspInit.cpp b/stm32h7/spi/mspInit.cpp index 5e14e8a..ecf2a39 100644 --- a/stm32h7/spi/mspInit.cpp +++ b/stm32h7/spi/mspInit.cpp @@ -1,4 +1,4 @@ -#include +#include #include "mspInit.h" #include "spiConf.h" #include "spiCore.h" @@ -10,6 +10,12 @@ #include +spi::msp_func_t mspInitFunc = nullptr; +spi::MspCfgBase* mspInitArgs = nullptr; + +spi::msp_func_t mspDeinitFunc = nullptr; +spi::MspCfgBase* mspDeinitArgs = nullptr; + /** * @brief SPI MSP Initialization * This function configures the hardware resources used in this example: @@ -20,38 +26,44 @@ * @param hspi: SPI handle pointer * @retval None */ -void spi::halMspInitDma(void *spi_handle) { - SPI_HandleTypeDef* hspi = (SPI_HandleTypeDef*) spi_handle; - if(hspi == NULL) { - return; - } - if(hspi == NULL) { - printf("HAL_SPI_MspInit: Invalid SPI handle!\n"); +void spi::halMspInitDma(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { + auto cfg = dynamic_cast(cfgBase); + if(hspi == nullptr or cfg == nullptr) { return; } setSpiHandle(hspi); - DMA_HandleTypeDef* hdma_tx = NULL; - DMA_HandleTypeDef* hdma_rx = NULL; + DMA_HandleTypeDef* hdma_tx = nullptr; + DMA_HandleTypeDef* hdma_rx = nullptr; spi::getDmaHandles(&hdma_tx, &hdma_rx); if(hdma_tx == NULL || hdma_rx == NULL) { printf("HAL_SPI_MspInit: Invalid DMA handles. Make sure to call setDmaHandles!\n"); return; } - spi::halMspInitPolling(spi_handle); - if (hspi->Instance == SPI1) { - // DMA setup - DMAx_CLK_ENABLE(); + spi::halMspInitInterrupt(hspi, cfg); - // Configure the DMA - /* Configure the DMA handler for Transmission process */ + // DMA setup + if(cfg->dmaClkEnableWrapper == nullptr) { + mspErrorHandler("spi::halMspInitDma", "DMA Clock init invalid"); + } + cfg->dmaClkEnableWrapper(); + + // Configure the DMA + /* Configure the DMA handler for Transmission process */ + if(hdma_tx->Instance == nullptr) { + // Assume it was not configured properly + mspErrorHandler("spi::halMspInitDma", "DMA TX handle invalid"); + } hdma_tx->Instance = SPIx_TX_DMA_STREAM; + + hdma_tx->Init.Request = SPIx_TX_DMA_REQUEST; + + // offer function to configure this.. hdma_tx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; hdma_tx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_tx->Init.MemBurst = DMA_MBURST_INC4; hdma_tx->Init.PeriphBurst = DMA_PBURST_INC4; - hdma_tx->Init.Request = SPIx_TX_DMA_REQUEST; hdma_tx->Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_tx->Init.PeriphInc = DMA_PINC_DISABLE; hdma_tx->Init.MemInc = DMA_MINC_ENABLE; @@ -60,53 +72,204 @@ void spi::halMspInitDma(void *spi_handle) { hdma_tx->Init.Mode = DMA_NORMAL; hdma_tx->Init.Priority = DMA_PRIORITY_LOW; - HAL_DMA_Init(hdma_tx); + HAL_DMA_Init(hdma_tx); - /* Associate the initialized DMA handle to the the SPI handle */ - __HAL_LINKDMA(hspi, hdmatx, *hdma_tx); + /* Associate the initialized DMA handle to the the SPI handle */ + __HAL_LINKDMA(hspi, hdmatx, *hdma_tx); - /* Configure the DMA handler for Transmission process */ - hdma_rx->Instance = SPIx_RX_DMA_STREAM; + /* Configure the DMA handler for Transmission process */ + hdma_rx->Instance = SPIx_RX_DMA_STREAM; - hdma_rx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; - hdma_rx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - hdma_rx->Init.MemBurst = DMA_MBURST_INC4; - hdma_rx->Init.PeriphBurst = DMA_PBURST_INC4; - hdma_rx->Init.Request = SPIx_RX_DMA_REQUEST; - hdma_rx->Init.Direction = DMA_PERIPH_TO_MEMORY; - hdma_rx->Init.PeriphInc = DMA_PINC_DISABLE; - hdma_rx->Init.MemInc = DMA_MINC_ENABLE; - hdma_rx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - hdma_rx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - hdma_rx->Init.Mode = DMA_NORMAL; - hdma_rx->Init.Priority = DMA_PRIORITY_HIGH; + hdma_rx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_rx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_rx->Init.MemBurst = DMA_MBURST_INC4; + hdma_rx->Init.PeriphBurst = DMA_PBURST_INC4; + hdma_rx->Init.Request = SPIx_RX_DMA_REQUEST; + hdma_rx->Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_rx->Init.PeriphInc = DMA_PINC_DISABLE; + hdma_rx->Init.MemInc = DMA_MINC_ENABLE; + hdma_rx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_rx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_rx->Init.Mode = DMA_NORMAL; + hdma_rx->Init.Priority = DMA_PRIORITY_HIGH; - HAL_DMA_Init(hdma_rx); + HAL_DMA_Init(hdma_rx); - /* Associate the initialized DMA handle to the the SPI handle */ - __HAL_LINKDMA(hspi, hdmarx, *hdma_rx); + /* Associate the initialized DMA handle to the the SPI handle */ + __HAL_LINKDMA(hspi, hdmarx, *hdma_rx); - /*##-4- Configure the NVIC for DMA #########################################*/ - /* NVIC configuration for DMA transfer complete interrupt (SPI1_RX) */ - // Assign the interrupt handler - dma::assignDmaUserHandler(dma::DMAIndexes::DMA_2, dma::DMAStreams::STREAM_2, - &spi::dmaRxIrqHandler, hdma_rx); - HAL_NVIC_SetPriority(SPIx_DMA_RX_IRQn, 1, 0); - HAL_NVIC_EnableIRQ(SPIx_DMA_RX_IRQn); + /*##-4- Configure the NVIC for DMA #########################################*/ + /* NVIC configuration for DMA transfer complete interrupt (SPI1_RX) */ + // Assign the interrupt handler + dma::assignDmaUserHandler(cfg->rxDmaIndex, cfg->rxDmaStream, &spi::dmaRxIrqHandler, hdma_rx); + HAL_NVIC_SetPriority(cfg->rxDmaIrqNumber, cfg->rxPreEmptPriority, cfg->rxSubpriority); + HAL_NVIC_EnableIRQ(cfg->rxDmaIrqNumber); - /* NVIC configuration for DMA transfer complete interrupt (SPI1_TX) */ - // Assign the interrupt handler - dma::assignDmaUserHandler(dma::DMAIndexes::DMA_2, dma::DMAStreams::STREAM_3, - &spi::dmaTxIrqHandler, hdma_tx); - HAL_NVIC_SetPriority(SPIx_DMA_TX_IRQn, 1, 1); - HAL_NVIC_EnableIRQ(SPIx_DMA_TX_IRQn); + /* NVIC configuration for DMA transfer complete interrupt (SPI1_TX) */ + // Assign the interrupt handler + dma::assignDmaUserHandler(cfg->txDmaIndex, cfg->txDmaStream, + &spi::dmaTxIrqHandler, hdma_tx); + HAL_NVIC_SetPriority(cfg->txDmaIrqNumber, cfg->txPreEmptPriority, cfg->txSubpriority); + HAL_NVIC_EnableIRQ(cfg->txDmaIrqNumber); - /*##-5- Configure the NVIC for SPI #########################################*/ - /* NVIC configuration for SPI transfer complete interrupt (SPI1) */ - // Assign the interrupt handler - spi::assignSpiUserHandler(spi::SPI_1, &spi::spi1IrqHandler, hspi); - HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0); - HAL_NVIC_EnableIRQ(SPIx_IRQn); + /*##-5- Configure the NVIC for SPI #########################################*/ + /* NVIC configuration for SPI transfer complete interrupt (SPI1) */ + // Assign the interrupt handler + spi::assignSpiUserHandler(spi::SPI_1, &spi::spiIrqHandler, hspi); + HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(SPIx_IRQn); + +} + +/** + * @brief SPI MSP De-Initialization + * This function frees the hardware resources used in this example: + * - Disable the Peripheral's clock + * - Revert GPIO, DMA and NVIC configuration to their default state + * @param hspi: SPI handle pointer + * @retval None + */ +void spi::halMspDeinitDma(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { + auto cfg = dynamic_cast(cfgBase); + if(hspi == nullptr or cfg == nullptr) { + return; + } + spi::halMspDeinitInterrupt(hspi, cfgBase); + DMA_HandleTypeDef* hdma_tx = NULL; + DMA_HandleTypeDef* hdma_rx = NULL; + spi::getDmaHandles(&hdma_tx, &hdma_rx); + if(hdma_tx == NULL || hdma_rx == NULL) { + printf("HAL_SPI_MspInit: Invalid DMA handles. Make sure to call setDmaHandles!\n"); + } + else { + // Disable the DMA + /* De-Initialize the DMA associated to transmission process */ + HAL_DMA_DeInit(hdma_tx); + /* De-Initialize the DMA associated to reception process */ + HAL_DMA_DeInit(hdma_rx); + } + + // Disable the NVIC for DMA + HAL_NVIC_DisableIRQ(cfg->txDmaIrqNumber); + HAL_NVIC_DisableIRQ(cfg->rxDmaIrqNumber); + +} + +void spi::halMspInitPolling(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { + auto cfg = dynamic_cast(cfgBase); + GPIO_InitTypeDef GPIO_InitStruct = {}; + /*##-1- Enable peripherals and GPIO Clocks #################################*/ + /* Enable GPIO TX/RX clock */ + cfg->setupMacroWrapper(); + + /*##-2- Configure peripheral GPIO ##########################################*/ + /* SPI SCK GPIO pin configuration */ + GPIO_InitStruct.Pin = cfg->sckPin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = cfg->sckAlternateFunction; + HAL_GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStruct); + + /* SPI MISO GPIO pin configuration */ + GPIO_InitStruct.Pin = cfg->misoPin; + GPIO_InitStruct.Alternate = cfg->misoAlternateFunction; + HAL_GPIO_Init(cfg->misoPort, &GPIO_InitStruct); + + /* SPI MOSI GPIO pin configuration */ + GPIO_InitStruct.Pin = cfg->mosiPin; + GPIO_InitStruct.Alternate = cfg->mosiAlternateFunction; + HAL_GPIO_Init(cfg->mosiPort, &GPIO_InitStruct); +} + +void spi::halMspDeinitPolling(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { + auto cfg = reinterpret_cast(cfgBase); + // Reset peripherals + cfg->cleanUpMacroWrapper(); + + // Disable peripherals and GPIO Clocks + /* Configure SPI SCK as alternate function */ + HAL_GPIO_DeInit(cfg->sckPort, cfg->sckPin); + /* Configure SPI MISO as alternate function */ + HAL_GPIO_DeInit(cfg->misoPort, cfg->misoPin); + /* Configure SPI MOSI as alternate function */ + HAL_GPIO_DeInit(cfg->mosiPort, cfg->mosiPin); +} + +void spi::halMspInitInterrupt(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { + auto cfg = dynamic_cast(cfgBase); + if(cfg == nullptr or hspi == nullptr) { + return; + } + + spi::halMspInitPolling(hspi, cfg); + // Configure the NVIC for SPI + spi::assignSpiUserHandler(cfg->spiBus, cfg->spiIrqHandler, cfg->spiUserArgs); + HAL_NVIC_SetPriority(cfg->spiIrqNumber, cfg->preEmptPriority, cfg->subpriority); + HAL_NVIC_EnableIRQ(cfg->spiIrqNumber); +} + +void spi::halMspDeinitInterrupt(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) { + auto cfg = dynamic_cast(cfgBase); + spi::halMspDeinitPolling(hspi, cfg); + // Disable the NVIC for SPI + HAL_NVIC_DisableIRQ(cfg->spiIrqNumber); +} + +void spi::getMspInitFunction(msp_func_t* init_func, MspCfgBase** args) { + if(init_func != NULL && args != NULL) { + *init_func = mspInitFunc; + *args = mspInitArgs; + } +} + +void spi::getMspDeinitFunction(msp_func_t* deinit_func, MspCfgBase** args) { + if(deinit_func != NULL && args != NULL) { + *deinit_func = mspDeinitFunc; + *args = mspDeinitArgs; + } +} + +void spi::setSpiDmaMspFunctions(MspDmaConfigStruct* cfg, + msp_func_t initFunc, msp_func_t deinitFunc) { + mspInitFunc = initFunc; + mspDeinitFunc = deinitFunc; + mspInitArgs = cfg; + mspDeinitArgs = cfg; +} + +void spi::setSpiIrqMspFunctions(MspIrqConfigStruct *cfg, msp_func_t initFunc, + msp_func_t deinitFunc) { + mspInitFunc = initFunc; + mspDeinitFunc = deinitFunc; + mspInitArgs = cfg; + mspDeinitArgs = cfg; +} + +void spi::setSpiPollingMspFunctions(MspPollingConfigStruct *cfg, msp_func_t initFunc, + msp_func_t deinitFunc) { + mspInitFunc = initFunc; + mspDeinitFunc = deinitFunc; + mspInitArgs = cfg; + mspDeinitArgs = cfg; +} + +/** + * @brief SPI MSP Initialization + * This function configures the hardware resources used in this example: + * - Peripheral's clock enable + * - Peripheral's GPIO Configuration + * - DMA configuration for transmission request by peripheral + * - NVIC configuration for DMA interrupt request enable + * @param hspi: SPI handle pointer + * @retval None + */ +extern "C" void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) { + if(mspInitFunc != NULL) { + mspInitFunc(hspi, mspInitArgs); + } + else { + printf("HAL_SPI_MspInit: Please call set_msp_functions to assign SPI MSP functions\n"); } } @@ -118,91 +281,15 @@ void spi::halMspInitDma(void *spi_handle) { * @param hspi: SPI handle pointer * @retval None */ -void spi::halMspDeinitDma(void *spi_handle) -{ - SPI_HandleTypeDef* hspi = (SPI_HandleTypeDef*) spi_handle; - if(hspi == NULL) { - return; +extern "C" void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) { + if(mspDeinitFunc != NULL) { + mspDeinitFunc(hspi, mspDeinitArgs); } - spi::halMspDeinitPolling(spi_handle); - if(hspi->Instance == SPIx) { - DMA_HandleTypeDef* hdma_tx = NULL; - DMA_HandleTypeDef* hdma_rx = NULL; - spi::getDmaHandles(&hdma_tx, &hdma_rx); - if(hdma_tx == NULL || hdma_rx == NULL) { - printf("HAL_SPI_MspInit: Invalid DMA handles. Make sure to call setDmaHandles!\n"); - } - else { - /*##-3- Disable the DMA ####################################################*/ - /* De-Initialize the DMA associated to transmission process */ - HAL_DMA_DeInit(hdma_tx); - /* De-Initialize the DMA associated to reception process */ - HAL_DMA_DeInit(hdma_rx); - } - - /*##-4- Disable the NVIC for DMA ###########################################*/ - HAL_NVIC_DisableIRQ(SPIx_DMA_TX_IRQn); - HAL_NVIC_DisableIRQ(SPIx_DMA_RX_IRQn); - - /*##-5- Disable the NVIC for SPI ###########################################*/ - HAL_NVIC_EnableIRQ(SPIx_IRQn); + else { + printf("HAL_SPI_MspDeInit: Please call set_msp_functions to assign SPI MSP functions\n"); } } -void spi::halMspInitPolling(void *hspi) { - GPIO_InitTypeDef GPIO_InitStruct = {}; - /*##-1- Enable peripherals and GPIO Clocks #################################*/ - /* Enable GPIO TX/RX clock */ - SPIx_SCK_GPIO_CLK_ENABLE(); - SPIx_MISO_GPIO_CLK_ENABLE(); - SPIx_MOSI_GPIO_CLK_ENABLE(); - /* Enable SPI clock */ - SPIx_CLK_ENABLE(); - - /*##-2- Configure peripheral GPIO ##########################################*/ - /* SPI SCK GPIO pin configuration */ - GPIO_InitStruct.Pin = SPIx_SCK_PIN; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_PULLDOWN; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = SPIx_SCK_AF; - HAL_GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStruct); - - /* SPI MISO GPIO pin configuration */ - GPIO_InitStruct.Pin = SPIx_MISO_PIN; - GPIO_InitStruct.Alternate = SPIx_MISO_AF; - HAL_GPIO_Init(SPIx_MISO_GPIO_PORT, &GPIO_InitStruct); - - /* SPI MOSI GPIO pin configuration */ - GPIO_InitStruct.Pin = SPIx_MOSI_PIN; - GPIO_InitStruct.Alternate = SPIx_MOSI_AF; - HAL_GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStruct); -} - -void spi::halMspDeinitPolling(void *hspi) { - /*##-1- Reset peripherals ##################################################*/ - SPIx_FORCE_RESET(); - SPIx_RELEASE_RESET(); - - /*##-2- Disable peripherals and GPIO Clocks ################################*/ - /* Configure SPI SCK as alternate function */ - HAL_GPIO_DeInit(SPIx_SCK_GPIO_PORT, SPIx_SCK_PIN); - /* Configure SPI MISO as alternate function */ - HAL_GPIO_DeInit(SPIx_MISO_GPIO_PORT, SPIx_MISO_PIN); - /* Configure SPI MOSI as alternate function */ - HAL_GPIO_DeInit(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_PIN); -} - -void spi::halMspInitInterrupt(void *hspi) { - spi::halMspInitPolling(hspi); - // Configure the NVIC for SPI - spi::assignSpiUserHandler(spi::SPI_1, &spi::spi1IrqHandler, hspi); - HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0); - HAL_NVIC_EnableIRQ(SPIx_IRQn); -} - -void spi::halMspDeinitInterrupt(void *hspi) { - spi::halMspDeinitPolling(hspi); - // Disable the NVIC for SPI - HAL_NVIC_DisableIRQ(SPIx_IRQn); +void spi::mspErrorHandler(const char* const function, const char *const message) { + printf("%s failure: %s\n", function, message); } diff --git a/stm32h7/spi/mspInit.h b/stm32h7/spi/mspInit.h index fb350ca..b4e900a 100644 --- a/stm32h7/spi/mspInit.h +++ b/stm32h7/spi/mspInit.h @@ -1,20 +1,103 @@ #ifndef FSFW_HAL_STM32H7_SPI_MSPINIT_H_ #define FSFW_HAL_STM32H7_SPI_MSPINIT_H_ +#include "spiDefinitions.h" +#include "../dma.h" +#include "stm32h7xx_hal_spi.h" + +#include + #ifdef __cplusplus extern "C" { #endif namespace spi { -void halMspInitDma(void *hspi); -void halMspDeinitDma(void *hspi); +struct MspCfgBase { + virtual ~MspCfgBase() = default; -void halMspInitPolling(void *hspi); -void halMspDeinitPolling(void *hspi); + void (* cleanUpMacroWrapper) (void) = nullptr; + void (* setupMacroWrapper) (void) = nullptr; -void halMspInitInterrupt(void *hspi); -void halMspDeinitInterrupt(void *hspi); + GPIO_TypeDef* sckPort = nullptr; + uint32_t sckPin = 0; + uint8_t sckAlternateFunction = 0; + GPIO_TypeDef* mosiPort = nullptr; + uint32_t mosiPin = 0; + uint8_t mosiAlternateFunction = 0; + GPIO_TypeDef* misoPort = nullptr; + uint32_t misoPin = 0; + uint8_t misoAlternateFunction = 0; +}; + +struct MspPollingConfigStruct: public MspCfgBase {}; + +/* A valid instance of this struct must be passed to the MSP initialization function as a void* +argument */ +struct MspIrqConfigStruct: public MspPollingConfigStruct { + SpiBus spiBus = SpiBus::SPI_1; + user_handler_t spiIrqHandler = nullptr; + user_args_t spiUserArgs = nullptr; + IRQn_Type spiIrqNumber = SPI1_IRQn; + // Priorities for NVIC + // Pre-Empt priority ranging from 0 to 15. If FreeRTOS calls are used, only 5-15 are allowed + IrqPriorities preEmptPriority = IrqPriorities::LOWEST; + IrqPriorities subpriority = IrqPriorities::LOWEST; +}; + +/* A valid instance of this struct must be passed to the MSP initialization function as a void* +argument */ +struct MspDmaConfigStruct: public MspIrqConfigStruct { + void (* dmaClkEnableWrapper) (void) = nullptr; + dma::DMAIndexes txDmaIndex; + dma::DMAIndexes rxDmaIndex; + dma::DMAStreams txDmaStream; + dma::DMAStreams rxDmaStream; + IRQn_Type txDmaIrqNumber = DMA1_Stream0_IRQn; + IRQn_Type rxDmaIrqNumber = DMA1_Stream1_IRQn; + // Priorities for NVIC + IrqPriorities txPreEmptPriority = IrqPriorities::LOWEST; + IrqPriorities rxPreEmptPriority = IrqPriorities::LOWEST; + IrqPriorities txSubpriority = IrqPriorities::LOWEST; + IrqPriorities rxSubpriority = IrqPriorities::LOWEST; +}; + +using msp_func_t = void (*) (SPI_HandleTypeDef* hspi, MspCfgBase* cfg); + + +void getMspInitFunction(msp_func_t* init_func, MspCfgBase **args); +void getMspDeinitFunction(msp_func_t* deinit_func, MspCfgBase **args); + +void halMspInitDma(SPI_HandleTypeDef* hspi, MspCfgBase* cfg); +void halMspDeinitDma(SPI_HandleTypeDef* hspi, MspCfgBase* cfg); + +void halMspInitInterrupt(SPI_HandleTypeDef* hspi, MspCfgBase* cfg); +void halMspDeinitInterrupt(SPI_HandleTypeDef* hspi, MspCfgBase* cfg); + +void halMspInitPolling(SPI_HandleTypeDef* hspi, MspCfgBase* cfg); +void halMspDeinitPolling(SPI_HandleTypeDef* hspi, MspCfgBase* cfg); + +/** + * Assign MSP init functions. Important for SPI configuration + * @param init_func + * @param init_args + * @param deinit_func + * @param deinit_args + */ +void setSpiDmaMspFunctions(MspDmaConfigStruct* cfg, + msp_func_t initFunc = &spi::halMspInitDma, + msp_func_t deinitFunc= &spi::halMspDeinitDma +); +void setSpiIrqMspFunctions(MspIrqConfigStruct* cfg, + msp_func_t initFunc = &spi::halMspInitInterrupt, + msp_func_t deinitFunc= &spi::halMspDeinitInterrupt +); +void setSpiPollingMspFunctions(MspPollingConfigStruct* cfg, + msp_func_t initFunc = &spi::halMspInitPolling, + msp_func_t deinitFunc= &spi::halMspDeinitPolling +); + +void mspErrorHandler(const char* const function, const char *const message); } diff --git a/stm32h7/spi/spiCore.cpp b/stm32h7/spi/spiCore.cpp index dd91f2d..1afbb84 100644 --- a/stm32h7/spi/spiCore.cpp +++ b/stm32h7/spi/spiCore.cpp @@ -5,12 +5,6 @@ SPI_HandleTypeDef* spiHandle = nullptr; DMA_HandleTypeDef* hdmaTx = nullptr; DMA_HandleTypeDef* hdmaRx = nullptr; -msp_func_t mspInitFunc = nullptr; -void* mspInitArgs = nullptr; - -msp_func_t mspDeinitFunc = nullptr; -void* mspDeinitArgs = nullptr; - spi_transfer_cb_t rxTxCb = nullptr; void* rxTxArgs = nullptr; spi_transfer_cb_t txCb = nullptr; @@ -20,6 +14,200 @@ void* rxArgs = nullptr; spi_transfer_cb_t errorCb = nullptr; void* errorArgs = nullptr; +void spi::configureDmaHandle(DMA_HandleTypeDef *handle, dma::DMAType dmaType, + dma::DMAIndexes dmaIdx, dma::DMAStreams dmaStream, IRQn_Type* dmaIrqNumber, + uint32_t dmaMode, uint32_t dmaPriority) { + using namespace dma; + if(dmaIdx == DMAIndexes::DMA_1) { +#ifdef DMA1 + switch(dmaStream) { + case(DMAStreams::STREAM_0): { +#ifdef DMA1_Stream0 + handle->Instance = DMA1_Stream0; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream0_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_1): { +#ifdef DMA1_Stream1 + handle->Instance = DMA1_Stream1; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream1_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_2): { +#ifdef DMA1_Stream2 + handle->Instance = DMA1_Stream2; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream2_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_3): { +#ifdef DMA1_Stream3 + handle->Instance = DMA1_Stream3; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream3_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_4): { +#ifdef DMA1_Stream4 + handle->Instance = DMA1_Stream4; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream4_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_5): { +#ifdef DMA1_Stream5 + handle->Instance = DMA1_Stream5; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream5_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_6): { +#ifdef DMA1_Stream6 + handle->Instance = DMA1_Stream6; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream6_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_7): { +#ifdef DMA1_Stream7 + handle->Instance = DMA1_Stream7; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA1_Stream7_IRQn; + } +#endif + break; + } + } + if(dmaType == DMAType::TX) { + handle->Init.Request = DMA_REQUEST_SPI1_TX; + } + else { + handle->Init.Request = DMA_REQUEST_SPI1_RX; + } +#endif /* DMA1 */ + } + if(dmaIdx == DMAIndexes::DMA_2) { +#ifdef DMA2 + switch(dmaStream) { + case(DMAStreams::STREAM_0): { +#ifdef DMA1_Stream0 + handle->Instance = DMA2_Stream0; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream0_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_1): { +#ifdef DMA1_Stream1 + handle->Instance = DMA2_Stream1; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream1_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_2): { +#ifdef DMA1_Stream2 + handle->Instance = DMA2_Stream2; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream2_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_3): { +#ifdef DMA1_Stream3 + handle->Instance = DMA2_Stream3; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream3_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_4): { +#ifdef DMA1_Stream4 + handle->Instance = DMA1_Stream4; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream4_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_5): { +#ifdef DMA1_Stream5 + handle->Instance = DMA1_Stream5; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream5_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_6): { +#ifdef DMA1_Stream6 + handle->Instance = DMA1_Stream6; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream6_IRQn; + } +#endif + break; + } + case(DMAStreams::STREAM_7): { +#ifdef DMA1_Stream7 + handle->Instance = DMA1_Stream7; + if(dmaIrqNumber != nullptr) { + *dmaIrqNumber = DMA2_Stream7_IRQn; + } +#endif + break; + } + } + if(dmaType == DMAType::TX) { + handle->Init.Request = DMA_REQUEST_SPI2_TX; + } + else { + handle->Init.Request = DMA_REQUEST_SPI2_RX; + } +#endif /* DMA2 */ + } + + if(dmaType == DMAType::TX) { + handle->Init.Direction = DMA_MEMORY_TO_PERIPH; + } + else { + handle->Init.Direction = DMA_PERIPH_TO_MEMORY; + } + + handle->Init.Priority = dmaPriority; + handle->Init.Mode = dmaMode; + + // Standard settings for the rest for now + handle->Init.FIFOMode = DMA_FIFOMODE_DISABLE; + handle->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + handle->Init.MemBurst = DMA_MBURST_INC4; + handle->Init.PeriphBurst = DMA_PBURST_INC4; + handle->Init.PeriphInc = DMA_PINC_DISABLE; + handle->Init.MemInc = DMA_MINC_ENABLE; + handle->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + handle->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; +} + void spi::setDmaHandles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle) { hdmaTx = txHandle; hdmaRx = rxHandle; @@ -61,63 +249,7 @@ SPI_HandleTypeDef* spi::getSpiHandle() { return spiHandle; } -void spi::setSpiMspFunctions(msp_func_t init_func, void* init_args, msp_func_t deinit_func, - void* deinit_args) { - mspInitFunc = init_func; - mspInitArgs = init_args; - mspDeinitFunc = deinit_func; - mspDeinitArgs = deinit_args; -} -void spi::getMspInitFunction(msp_func_t* init_func, void **args) { - if(init_func != NULL && args != NULL) { - *init_func = mspInitFunc; - *args = mspInitArgs; - } -} - -void spi::getMspDeinitFunction(msp_func_t* deinit_func, void **args) { - if(deinit_func != NULL && args != NULL) { - *deinit_func = mspDeinitFunc; - *args = mspDeinitArgs; - } -} - -/** - * @brief SPI MSP Initialization - * This function configures the hardware resources used in this example: - * - Peripheral's clock enable - * - Peripheral's GPIO Configuration - * - DMA configuration for transmission request by peripheral - * - NVIC configuration for DMA interrupt request enable - * @param hspi: SPI handle pointer - * @retval None - */ -extern "C" void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) { - if(mspInitFunc != NULL) { - mspInitFunc(mspInitArgs); - } - else { - printf("HAL_SPI_MspInit: Please call set_msp_functions to assign SPI MSP functions\n"); - } -} - -/** - * @brief SPI MSP De-Initialization - * This function frees the hardware resources used in this example: - * - Disable the Peripheral's clock - * - Revert GPIO, DMA and NVIC configuration to their default state - * @param hspi: SPI handle pointer - * @retval None - */ -extern "C" void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) { - if(mspDeinitFunc != NULL) { - mspDeinitFunc(mspDeinitArgs); - } - else { - printf("HAL_SPI_MspDeInit: Please call set_msp_functions to assign SPI MSP functions\n"); - } -} /** * @brief TxRx Transfer completed callback. @@ -173,4 +305,3 @@ extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { printf("HAL_SPI_ErrorCallback: No user callback specified\n"); } } - diff --git a/stm32h7/spi/spiCore.h b/stm32h7/spi/spiCore.h index 3d3039a..5af3558 100644 --- a/stm32h7/spi/spiCore.h +++ b/stm32h7/spi/spiCore.h @@ -1,27 +1,22 @@ #ifndef FSFW_HAL_STM32H7_SPI_SPICORE_H_ #define FSFW_HAL_STM32H7_SPI_SPICORE_H_ +#include #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_dma.h" + #ifdef __cplusplus extern "C" { #endif -using msp_func_t = void (*) (void* args); using spi_transfer_cb_t = void (*) (SPI_HandleTypeDef *hspi, void* userArgs); namespace spi { -/** - * Assign MSP init functions. Important for SPI configuration - * @param init_func - * @param init_args - * @param deinit_func - * @param deinit_args - */ -void setSpiMspFunctions(msp_func_t init_func, void* init_args, msp_func_t deinit_func, - void* deinit_args); +void configureDmaHandle(DMA_HandleTypeDef* Handle, dma::DMAType dmaType, dma::DMAIndexes dmaIdx, + dma::DMAStreams dmaStream, IRQn_Type* dmaIrqNumber, uint32_t dmaMode = DMA_NORMAL, + uint32_t dmaPriority = DMA_PRIORITY_LOW); /** * Assign DMA handles. Required to use DMA for SPI transfers. @@ -31,9 +26,6 @@ void setSpiMspFunctions(msp_func_t init_func, void* init_args, msp_func_t deinit void setDmaHandles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle); void getDmaHandles(DMA_HandleTypeDef** txHandle, DMA_HandleTypeDef** rxHandle); -void getMspInitFunction(msp_func_t* init_func, void **args); -void getMspDeinitFunction(msp_func_t* deinit_func, void **args); - /** * Assign SPI handle. Needs to be done before using the SPI * @param spiHandle diff --git a/stm32h7/spi/spiInterrupts.cpp b/stm32h7/spi/spiInterrupts.cpp index fe5700b..74930e5 100644 --- a/stm32h7/spi/spiInterrupts.cpp +++ b/stm32h7/spi/spiInterrupts.cpp @@ -1,4 +1,5 @@ #include "spiInterrupts.h" +#include "spiCore.h" #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_dma.h" @@ -6,10 +7,10 @@ #include -user_handler_t spi1UserHandler = nullptr; +user_handler_t spi1UserHandler = &spi::spiIrqHandler; user_args_t spi1UserArgs = nullptr; -user_handler_t spi2UserHandler = nullptr; +user_handler_t spi2UserHandler = &spi::spiIrqHandler; user_args_t spi2UserArgs = nullptr; /** @@ -35,9 +36,10 @@ void spi::dmaTxIrqHandler(void* dmaHandle) { * @param None * @retval None */ -void spi::spi1IrqHandler(void* spiHandle) +void spi::spiIrqHandler(void* spiHandle) { - HAL_SPI_IRQHandler((SPI_HandleTypeDef *) spiHandle); + auto currentSpiHandle = spi::getSpiHandle(); + HAL_SPI_IRQHandler((SPI_HandleTypeDef *) currentSpiHandle); } void spi::assignSpiUserHandler(spi::SpiBus spiIdx, user_handler_t userHandler, @@ -52,6 +54,30 @@ void spi::assignSpiUserHandler(spi::SpiBus spiIdx, user_handler_t userHandler, } } +void spi::getSpiUserHandler(spi::SpiBus spiBus, user_handler_t *userHandler, + user_args_t *userArgs) { + if(userHandler == nullptr or userArgs == nullptr) { + return; + } + if(spiBus == spi::SpiBus::SPI_1) { + *userArgs = spi1UserArgs; + *userHandler = spi1UserHandler; + } + else { + *userArgs = spi2UserArgs; + *userHandler = spi2UserHandler; + } +} + +void assignSpiUserArgs(spi::SpiBus spiBus, user_args_t userArgs) { + if(spiBus == spi::SpiBus::SPI_1) { + spi1UserArgs = userArgs; + } + else { + spi2UserArgs = userArgs; + } +} + /* Do not change these function names! They need to be exactly equal to the name of the functions defined in the startup_stm32h743xx.s files! */ @@ -70,5 +96,3 @@ extern "C" void SPI2_IRQHandler() { } Default_Handler(); } - - diff --git a/stm32h7/spi/spiInterrupts.h b/stm32h7/spi/spiInterrupts.h index abfc68e..0b53f48 100644 --- a/stm32h7/spi/spiInterrupts.h +++ b/stm32h7/spi/spiInterrupts.h @@ -10,6 +10,8 @@ extern "C" { namespace spi { +void assignSpiUserArgs(spi::SpiBus spiBus, user_args_t userArgs); + /** * Assign a user interrupt handler for SPI bus 1, allowing to pass an arbitrary argument as well. * Generally, this argument will be the related SPI handle. @@ -18,6 +20,8 @@ namespace spi { */ void assignSpiUserHandler(spi::SpiBus spiBus, user_handler_t user_handler, user_args_t user_args); +void getSpiUserHandler(spi::SpiBus spiBus, user_handler_t* user_handler, + user_args_t* user_args); /** * Generic interrupt handlers supplied for convenience. Do not call these directly! Set them @@ -26,7 +30,7 @@ void assignSpiUserHandler(spi::SpiBus spiBus, user_handler_t user_handler, */ void dmaRxIrqHandler(void* dma_handle); void dmaTxIrqHandler(void* dma_handle); -void spi1IrqHandler(void* spi_handle); +void spiIrqHandler(void* spi_handle); } diff --git a/stm32h7/spi/stm32h743ziSpi.cpp b/stm32h7/spi/stm32h743ziSpi.cpp new file mode 100644 index 0000000..3ff4d2b --- /dev/null +++ b/stm32h7/spi/stm32h743ziSpi.cpp @@ -0,0 +1,81 @@ +#include "stm32h743ziSpi.h" +#include "spiCore.h" +#include "spiInterrupts.h" +#include "stm32h7xx_hal.h" +#include "stm32h7xx_hal_rcc.h" + +#include + +void spiSetupWrapper() { + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_SPI1_CLK_ENABLE(); +} + +void spiCleanUpWrapper() { + __HAL_RCC_SPI1_FORCE_RESET(); + __HAL_RCC_SPI1_RELEASE_RESET(); +} + +void spiDmaClockEnableWrapper() { + __HAL_RCC_SPI1_CLK_ENABLE(); +} + +void spi::h743zi::standardPollingCfg(MspPollingConfigStruct& cfg) { + cfg.setupMacroWrapper = &spiSetupWrapper; + cfg.cleanUpMacroWrapper = &spiCleanUpWrapper; + cfg.sckPort = GPIOA; + cfg.sckPin = GPIO_PIN_5; + cfg.misoPort = GPIOA; + cfg.misoPin = GPIO_PIN_6; + cfg.mosiPort = GPIOA; + cfg.mosiPin = GPIO_PIN_7; + cfg.sckAlternateFunction = GPIO_AF5_SPI1; + cfg.mosiAlternateFunction = GPIO_AF5_SPI1; + cfg.misoAlternateFunction = GPIO_AF5_SPI1; +} + +void spi::h743zi::standardInterruptCfg(MspIrqConfigStruct& cfg, IrqPriorities spiIrqPrio, + IrqPriorities spiSubprio) { + // High, but works on FreeRTOS as well (priorities range from 0 to 15) + cfg.preEmptPriority = spiIrqPrio; + cfg.subpriority = spiSubprio; + cfg.spiIrqNumber = SPI1_IRQn; + cfg.spiBus = SpiBus::SPI_1; + user_handler_t spiUserHandler = nullptr; + user_args_t spiUserArgs = nullptr; + getSpiUserHandler(spi::SpiBus::SPI_1, &spiUserHandler, &spiUserArgs); + if(spiUserHandler == nullptr) { + printf("spi::h743zi::standardInterruptCfg: Invalid SPI user handlers\n"); + return; + } + cfg.spiUserArgs = spiUserArgs; + cfg.spiIrqHandler = spiUserHandler; + standardPollingCfg(cfg); +} + +void spi::h743zi::standardDmaCfg(MspDmaConfigStruct& cfg, IrqPriorities spiIrqPrio, + IrqPriorities txIrqPrio, IrqPriorities rxIrqPrio, IrqPriorities spiSubprio, + IrqPriorities txSubprio, IrqPriorities rxSubprio) { + cfg.dmaClkEnableWrapper = &spiDmaClockEnableWrapper; + cfg.rxDmaIndex = dma::DMAIndexes::DMA_1; + cfg.txDmaIndex = dma::DMAIndexes::DMA_1; + cfg.txDmaStream = dma::DMAStreams::STREAM_3; + cfg.rxDmaStream = dma::DMAStreams::STREAM_2; + DMA_HandleTypeDef* txHandle; + DMA_HandleTypeDef* rxHandle; + spi::getDmaHandles(&txHandle, &rxHandle); + if(txHandle == nullptr or rxHandle == nullptr) { + printf("spi::h743zi::standardDmaCfg: Invalid DMA handles"); + return; + } + spi::configureDmaHandle(txHandle, dma::DMAType::TX, cfg.txDmaIndex, cfg.txDmaStream, + &cfg.txDmaIrqNumber); + spi::configureDmaHandle(rxHandle, dma::DMAType::RX, cfg.rxDmaIndex, cfg.rxDmaStream, + &cfg.rxDmaIrqNumber); + cfg.txPreEmptPriority = txIrqPrio; + cfg.rxPreEmptPriority = txSubprio; + cfg.txSubpriority = rxIrqPrio; + cfg.rxSubpriority = rxSubprio; + standardInterruptCfg(cfg, spiIrqPrio, spiSubprio); +} diff --git a/stm32h7/spi/stm32h743ziSpi.h b/stm32h7/spi/stm32h743ziSpi.h new file mode 100644 index 0000000..87689ad --- /dev/null +++ b/stm32h7/spi/stm32h743ziSpi.h @@ -0,0 +1,23 @@ +#ifndef FSFW_HAL_STM32H7_SPI_STM32H743ZISPI_H_ +#define FSFW_HAL_STM32H7_SPI_STM32H743ZISPI_H_ + +#include "mspInit.h" + +namespace spi { + +namespace h743zi { + +void standardPollingCfg(MspPollingConfigStruct& cfg); +void standardInterruptCfg(MspIrqConfigStruct& cfg, IrqPriorities spiIrqPrio, + IrqPriorities spiSubprio = HIGHEST); +void standardDmaCfg(MspDmaConfigStruct& cfg, IrqPriorities spiIrqPrio, + IrqPriorities txIrqPrio, IrqPriorities rxIrqPrio, + IrqPriorities spiSubprio = HIGHEST, IrqPriorities txSubPrio = HIGHEST, + IrqPriorities rxSubprio = HIGHEST); + +} +} + + + +#endif /* FSFW_HAL_STM32H7_SPI_STM32H743ZISPI_H_ */