refactored everything

This commit is contained in:
Robin Müller 2021-06-10 19:09:33 +02:00
parent 0e79b5f4ae
commit 8f61c23e62
No known key found for this signature in database
GPG Key ID: BE6480244DFE612C
18 changed files with 740 additions and 265 deletions

View File

@ -6,7 +6,7 @@ GyroHandlerL3GD20H::GyroHandlerL3GD20H(object_id_t objectId, object_id_t deviceC
CookieIF *comCookie): CookieIF *comCookie):
DeviceHandlerBase(objectId, deviceCommunication, comCookie), DeviceHandlerBase(objectId, deviceCommunication, comCookie),
dataset(this) { dataset(this) {
#if L3GD20_GYRO_DEBUG == 1 #if FSFW_HAL_L3GD20_GYRO_DEBUG == 1
debugDivider = new PeriodicOperationDivider(5); debugDivider = new PeriodicOperationDivider(5);
#endif #endif
} }
@ -28,11 +28,12 @@ void GyroHandlerL3GD20H::doStartUp() {
if(internalState == InternalState::CHECK_REGS) { if(internalState == InternalState::CHECK_REGS) {
if(commandExecuted) { if(commandExecuted) {
internalState = InternalState::NORMAL; internalState = InternalState::NORMAL;
#if OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP == 1 if(goNormalModeImmediately) {
setMode(MODE_NORMAL); setMode(MODE_NORMAL);
#else }
setMode(_MODE_TO_ON); else {
#endif setMode(_MODE_TO_ON);
}
commandExecuted = false; commandExecuted = false;
} }
} }
@ -85,9 +86,7 @@ ReturnValue_t GyroHandlerL3GD20H::buildCommandFromCommand(
size_t commandDataLen) { size_t commandDataLen) {
switch(deviceCommand) { switch(deviceCommand) {
case(L3GD20H::READ_REGS): { case(L3GD20H::READ_REGS): {
commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | L3GD20H::READ_MASK;
L3GD20H::READ_MASK;
std::memset(commandBuffer + 1, 0, L3GD20H::READ_LEN); std::memset(commandBuffer + 1, 0, L3GD20H::READ_LEN);
rawPacket = commandBuffer; rawPacket = commandBuffer;
rawPacketLen = L3GD20H::READ_LEN + 1; rawPacketLen = L3GD20H::READ_LEN + 1;
@ -196,7 +195,7 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id,
int8_t temperaturOffset = (-1) * packet[L3GD20H::TEMPERATURE_IDX]; int8_t temperaturOffset = (-1) * packet[L3GD20H::TEMPERATURE_IDX];
float temperature = 25.0 + temperaturOffset; float temperature = 25.0 + temperaturOffset;
#if L3GD20_GYRO_DEBUG == 1 #if FSFW_HAL_L3GD20_GYRO_DEBUG == 1
if(debugDivider->checkAndIncrement()) { if(debugDivider->checkAndIncrement()) {
/* Set terminal to utf-8 if there is an issue with micro printout. */ /* Set terminal to utf-8 if there is an issue with micro printout. */
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
@ -235,6 +234,10 @@ uint32_t GyroHandlerL3GD20H::getTransitionDelayMs(Mode_t from, Mode_t to) {
return 10000; return 10000;
} }
void GyroHandlerL3GD20H::setGoNormalModeAtStartup() {
this->goNormalModeImmediately = true;
}
ReturnValue_t GyroHandlerL3GD20H::initializeLocalDataPool( ReturnValue_t GyroHandlerL3GD20H::initializeLocalDataPool(
localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(L3GD20H::ANG_VELOC_X, localDataPoolMap.emplace(L3GD20H::ANG_VELOC_X,

View File

@ -7,9 +7,9 @@
#include <fsfw/devicehandlers/DeviceHandlerBase.h> #include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <fsfw/globalfunctions/PeriodicOperationDivider.h> #include <fsfw/globalfunctions/PeriodicOperationDivider.h>
#ifndef L3GD20_GYRO_DEBUG #ifndef FSFW_HAL_L3GD20_GYRO_DEBUG
#define L3GD20_GYRO_DEBUG 1 #define FSFW_HAL_L3GD20_GYRO_DEBUG 1
#endif #endif /* FSFW_HAL_L3GD20_GYRO_DEBUG */
/** /**
* @brief Device Handler for the L3GD20H gyroscope sensor * @brief Device Handler for the L3GD20H gyroscope sensor
@ -26,6 +26,7 @@ public:
CookieIF* comCookie); CookieIF* comCookie);
virtual ~GyroHandlerL3GD20H(); virtual ~GyroHandlerL3GD20H();
void setGoNormalModeAtStartup();
protected: protected:
/* DeviceHandlerBase overrides */ /* DeviceHandlerBase overrides */
@ -62,6 +63,7 @@ private:
bool commandExecuted = false; bool commandExecuted = false;
uint8_t statusReg = 0; uint8_t statusReg = 0;
bool goNormalModeImmediately = false;
uint8_t ctrlReg1Value = L3GD20H::CTRL_REG_1_VAL; uint8_t ctrlReg1Value = L3GD20H::CTRL_REG_1_VAL;
uint8_t ctrlReg2Value = L3GD20H::CTRL_REG_2_VAL; uint8_t ctrlReg2Value = L3GD20H::CTRL_REG_2_VAL;
@ -74,7 +76,7 @@ private:
// Set default value // Set default value
float sensitivity = L3GD20H::SENSITIVITY_00; float sensitivity = L3GD20H::SENSITIVITY_00;
#if L3GD20_GYRO_DEBUG == 1 #if FSFW_HAL_L3GD20_GYRO_DEBUG == 1
PeriodicOperationDivider* debugDivider = nullptr; PeriodicOperationDivider* debugDivider = nullptr;
#endif #endif
}; };

View File

@ -3,5 +3,5 @@ add_subdirectory(gpio)
add_subdirectory(devicetest) add_subdirectory(devicetest)
target_sources(${LIB_FSFW_HAL_NAME} PRIVATE target_sources(${LIB_FSFW_HAL_NAME} PRIVATE
dmaInterrupts.cpp dma.cpp
) )

View File

@ -3,6 +3,8 @@
#include "../spi/mspInit.h" #include "../spi/mspInit.h"
#include "../spi/spiDefinitions.h" #include "../spi/spiDefinitions.h"
#include "../spi/spiCore.h" #include "../spi/spiCore.h"
#include "../spi/spiInterrupts.h"
#include "../spi/stm32h743ziSpi.h"
#include "fsfw/tasks/TaskFactory.h" #include "fsfw/tasks/TaskFactory.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
@ -20,24 +22,32 @@ GyroL3GD20H::txBuffer __attribute__((section(".dma_buffer")));
TransferStates transferState = TransferStates::IDLE; TransferStates transferState = TransferStates::IDLE;
spi::TransferModes GyroL3GD20H::transferMode = spi::TransferModes::POLLING; spi::TransferModes GyroL3GD20H::transferMode = spi::TransferModes::POLLING;
DMA_HandleTypeDef txDmaHandle;
DMA_HandleTypeDef rxDmaHandle;
GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transferMode_): 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_; transferMode = transferMode_;
if(transferMode == spi::TransferModes::DMA) { if(transferMode == spi::TransferModes::DMA) {
spi::setDmaHandles(&txDmaHandle, &rxDmaHandle); mspCfg = new spi::MspDmaConfigStruct();
spi::setSpiMspFunctions(&spi::halMspInitDma, spiHandle, auto typedCfg = dynamic_cast<spi::MspDmaConfigStruct*>(mspCfg);
&spi::halMspDeinitDma, spiHandle); 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) { else if(transferMode == spi::TransferModes::INTERRUPT) {
spi::setSpiMspFunctions(&spi::halMspInitInterrupt, spiHandle, mspCfg = new spi::MspIrqConfigStruct();
&spi::halMspDeinitInterrupt, spiHandle); auto typedCfg = dynamic_cast<spi::MspIrqConfigStruct*>(mspCfg);
spi::h743zi::standardInterruptCfg(*typedCfg, IrqPriorities::HIGHEST_FREERTOS);
spi::setSpiIrqMspFunctions(typedCfg);
} }
else if(transferMode == spi::TransferModes::POLLING) { else if(transferMode == spi::TransferModes::POLLING) {
spi::setSpiMspFunctions(&spi::halMspInitPolling, spiHandle, mspCfg = new spi::MspPollingConfigStruct();
&spi::halMspDeinitPolling, spiHandle); auto typedCfg = dynamic_cast<spi::MspPollingConfigStruct*>(mspCfg);
spi::h743zi::standardPollingCfg(*typedCfg);
spi::setSpiPollingMspFunctions(typedCfg);
} }
spi::assignTransferRxTxCompleteCallback(&spiTransferCompleteCallback, nullptr); 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); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
} }
GyroL3GD20H::~GyroL3GD20H() {
delete txDmaHandle;
delete rxDmaHandle;
delete mspCfg;
}
ReturnValue_t GyroL3GD20H::initialize() { ReturnValue_t GyroL3GD20H::initialize() {
// Configure the SPI peripheral // Configure the SPI peripheral
spiHandle->Instance = SPI1; spiHandle->Instance = SPI1;

View File

@ -3,8 +3,9 @@
#include "stm32h7xx_hal.h" #include "stm32h7xx_hal.h"
#include "stm32h7xx_hal_spi.h" #include "stm32h7xx_hal_spi.h"
#include "../spi/mspInit.h"
#include "../spi/spiDefinitions.h" #include "../spi/spiDefinitions.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h" #include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include <cstdint> #include <cstdint>
@ -20,6 +21,7 @@ enum class TransferStates {
class GyroL3GD20H { class GyroL3GD20H {
public: public:
GyroL3GD20H(SPI_HandleTypeDef* spiHandle, spi::TransferModes transferMode); GyroL3GD20H(SPI_HandleTypeDef* spiHandle, spi::TransferModes transferMode);
~GyroL3GD20H();
ReturnValue_t initialize(); ReturnValue_t initialize();
ReturnValue_t performOperation(); ReturnValue_t performOperation();
@ -58,6 +60,11 @@ private:
void prepareConfigRegs(uint8_t* configRegs); void prepareConfigRegs(uint8_t* configRegs);
void handleSensorReadout(); void handleSensorReadout();
DMA_HandleTypeDef* txDmaHandle = {};
DMA_HandleTypeDef* rxDmaHandle = {};
spi::MspCfgBase* mspCfg = {};
}; };
#endif /* FSFW_HAL_STM32H7_DEVICETEST_GYRO_L3GD20H_H_ */ #endif /* FSFW_HAL_STM32H7_DEVICETEST_GYRO_L3GD20H_H_ */

View File

@ -1,5 +1,4 @@
#include "dmaInterrupts.h" #include <fsfw_hal/stm32h7/dma.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>

View File

@ -1,18 +1,24 @@
#ifndef FSFW_HAL_STM32H7_DMAINTERRUPTS_H_ #ifndef FSFW_HAL_STM32H7_DMA_H_
#define FSFW_HAL_STM32H7_DMAINTERRUPTS_H_ #define FSFW_HAL_STM32H7_DMA_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "interrupts.h" #include "interrupts.h"
#include <cstdint>
namespace dma { namespace dma {
enum DMAIndexes { enum DMAType {
DMA_1 = 0, TX = 0,
DMA_2 = 1 RX = 1
} ; };
enum DMAIndexes: uint8_t {
DMA_1 = 1,
DMA_2 = 2
};
enum DMAStreams { enum DMAStreams {
STREAM_0 = 0, STREAM_0 = 0,
@ -40,4 +46,4 @@ void assignDmaUserHandler(DMAIndexes dma_idx, DMAStreams stream_idx,
} }
#endif #endif
#endif /* FSFW_HAL_STM32H7_DMAINTERRUPTS_H_ */ #endif /* FSFW_HAL_STM32H7_DMA_H_ */

View File

@ -1,6 +1,8 @@
#ifndef FSFW_HAL_STM32H7_INTERRUPTS_H_ #ifndef FSFW_HAL_STM32H7_INTERRUPTS_H_
#define FSFW_HAL_STM32H7_INTERRUPTS_H_ #define FSFW_HAL_STM32H7_INTERRUPTS_H_
#include <cstdint>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -13,6 +15,12 @@ extern void Default_Handler();
typedef void (*user_handler_t) (void*); typedef void (*user_handler_t) (void*);
typedef void* user_args_t; typedef void* user_args_t;
enum IrqPriorities: uint8_t {
HIGHEST = 0,
HIGHEST_FREERTOS = 6,
LOWEST = 15
};
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -5,4 +5,5 @@ target_sources(${LIB_FSFW_HAL_NAME} PRIVATE
mspInit.cpp mspInit.cpp
SpiCookie.cpp SpiCookie.cpp
SpiComIF.cpp SpiComIF.cpp
stm32h743ziSpi.cpp
) )

View File

@ -83,8 +83,16 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) {
SPI_HandleTypeDef& spiHandle = spiCookie->getSpiHandle(); SPI_HandleTypeDef& spiHandle = spiCookie->getSpiHandle();
if(transferMode == spi::TransferModes::POLLING) { if(transferMode == spi::TransferModes::POLLING) {
spi::setSpiMspFunctions(&spi::halMspInitPolling, &spiHandle, // spi::setSpiMspFunctions(&spi::halMspInitPolling, &spiHandle,
&spi::halMspDeinitPolling, &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); gpio::initializeGpioClock(gpioPort);

View File

@ -1,4 +1,4 @@
#include <fsfw_hal/stm32h7/dmaInterrupts.h> #include <fsfw_hal/stm32h7/dma.h>
#include "mspInit.h" #include "mspInit.h"
#include "spiConf.h" #include "spiConf.h"
#include "spiCore.h" #include "spiCore.h"
@ -10,6 +10,12 @@
#include <stdio.h> #include <stdio.h>
spi::msp_func_t mspInitFunc = nullptr;
spi::MspCfgBase* mspInitArgs = nullptr;
spi::msp_func_t mspDeinitFunc = nullptr;
spi::MspCfgBase* mspDeinitArgs = nullptr;
/** /**
* @brief SPI MSP Initialization * @brief SPI MSP Initialization
* This function configures the hardware resources used in this example: * This function configures the hardware resources used in this example:
@ -20,38 +26,44 @@
* @param hspi: SPI handle pointer * @param hspi: SPI handle pointer
* @retval None * @retval None
*/ */
void spi::halMspInitDma(void *spi_handle) { void spi::halMspInitDma(SPI_HandleTypeDef* hspi, MspCfgBase* cfgBase) {
SPI_HandleTypeDef* hspi = (SPI_HandleTypeDef*) spi_handle; auto cfg = dynamic_cast<MspDmaConfigStruct*>(cfgBase);
if(hspi == NULL) { if(hspi == nullptr or cfg == nullptr) {
return;
}
if(hspi == NULL) {
printf("HAL_SPI_MspInit: Invalid SPI handle!\n");
return; return;
} }
setSpiHandle(hspi); setSpiHandle(hspi);
DMA_HandleTypeDef* hdma_tx = NULL; DMA_HandleTypeDef* hdma_tx = nullptr;
DMA_HandleTypeDef* hdma_rx = NULL; DMA_HandleTypeDef* hdma_rx = nullptr;
spi::getDmaHandles(&hdma_tx, &hdma_rx); spi::getDmaHandles(&hdma_tx, &hdma_rx);
if(hdma_tx == NULL || hdma_rx == NULL) { if(hdma_tx == NULL || hdma_rx == NULL) {
printf("HAL_SPI_MspInit: Invalid DMA handles. Make sure to call setDmaHandles!\n"); printf("HAL_SPI_MspInit: Invalid DMA handles. Make sure to call setDmaHandles!\n");
return; return;
} }
spi::halMspInitPolling(spi_handle); spi::halMspInitInterrupt(hspi, cfg);
if (hspi->Instance == SPI1) {
// DMA setup
DMAx_CLK_ENABLE();
// Configure the DMA // DMA setup
/* Configure the DMA handler for Transmission process */ 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->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.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_tx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_tx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_tx->Init.MemBurst = DMA_MBURST_INC4; hdma_tx->Init.MemBurst = DMA_MBURST_INC4;
hdma_tx->Init.PeriphBurst = DMA_PBURST_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.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tx->Init.PeriphInc = DMA_PINC_DISABLE; hdma_tx->Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tx->Init.MemInc = DMA_MINC_ENABLE; 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.Mode = DMA_NORMAL;
hdma_tx->Init.Priority = DMA_PRIORITY_LOW; 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 */ /* Associate the initialized DMA handle to the the SPI handle */
__HAL_LINKDMA(hspi, hdmatx, *hdma_tx); __HAL_LINKDMA(hspi, hdmatx, *hdma_tx);
/* Configure the DMA handler for Transmission process */ /* Configure the DMA handler for Transmission process */
hdma_rx->Instance = SPIx_RX_DMA_STREAM; hdma_rx->Instance = SPIx_RX_DMA_STREAM;
hdma_rx->Init.FIFOMode = DMA_FIFOMODE_DISABLE; hdma_rx->Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_rx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_rx->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_rx->Init.MemBurst = DMA_MBURST_INC4; hdma_rx->Init.MemBurst = DMA_MBURST_INC4;
hdma_rx->Init.PeriphBurst = DMA_PBURST_INC4; hdma_rx->Init.PeriphBurst = DMA_PBURST_INC4;
hdma_rx->Init.Request = SPIx_RX_DMA_REQUEST; hdma_rx->Init.Request = SPIx_RX_DMA_REQUEST;
hdma_rx->Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_rx->Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_rx->Init.PeriphInc = DMA_PINC_DISABLE; hdma_rx->Init.PeriphInc = DMA_PINC_DISABLE;
hdma_rx->Init.MemInc = DMA_MINC_ENABLE; hdma_rx->Init.MemInc = DMA_MINC_ENABLE;
hdma_rx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_rx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_rx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_rx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_rx->Init.Mode = DMA_NORMAL; hdma_rx->Init.Mode = DMA_NORMAL;
hdma_rx->Init.Priority = DMA_PRIORITY_HIGH; 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 */ /* Associate the initialized DMA handle to the the SPI handle */
__HAL_LINKDMA(hspi, hdmarx, *hdma_rx); __HAL_LINKDMA(hspi, hdmarx, *hdma_rx);
/*##-4- Configure the NVIC for DMA #########################################*/ /*##-4- Configure the NVIC for DMA #########################################*/
/* NVIC configuration for DMA transfer complete interrupt (SPI1_RX) */ /* NVIC configuration for DMA transfer complete interrupt (SPI1_RX) */
// Assign the interrupt handler // Assign the interrupt handler
dma::assignDmaUserHandler(dma::DMAIndexes::DMA_2, dma::DMAStreams::STREAM_2, dma::assignDmaUserHandler(cfg->rxDmaIndex, cfg->rxDmaStream, &spi::dmaRxIrqHandler, hdma_rx);
&spi::dmaRxIrqHandler, hdma_rx); HAL_NVIC_SetPriority(cfg->rxDmaIrqNumber, cfg->rxPreEmptPriority, cfg->rxSubpriority);
HAL_NVIC_SetPriority(SPIx_DMA_RX_IRQn, 1, 0); HAL_NVIC_EnableIRQ(cfg->rxDmaIrqNumber);
HAL_NVIC_EnableIRQ(SPIx_DMA_RX_IRQn);
/* NVIC configuration for DMA transfer complete interrupt (SPI1_TX) */ /* NVIC configuration for DMA transfer complete interrupt (SPI1_TX) */
// Assign the interrupt handler // Assign the interrupt handler
dma::assignDmaUserHandler(dma::DMAIndexes::DMA_2, dma::DMAStreams::STREAM_3, dma::assignDmaUserHandler(cfg->txDmaIndex, cfg->txDmaStream,
&spi::dmaTxIrqHandler, hdma_tx); &spi::dmaTxIrqHandler, hdma_tx);
HAL_NVIC_SetPriority(SPIx_DMA_TX_IRQn, 1, 1); HAL_NVIC_SetPriority(cfg->txDmaIrqNumber, cfg->txPreEmptPriority, cfg->txSubpriority);
HAL_NVIC_EnableIRQ(SPIx_DMA_TX_IRQn); HAL_NVIC_EnableIRQ(cfg->txDmaIrqNumber);
/*##-5- Configure the NVIC for SPI #########################################*/ /*##-5- Configure the NVIC for SPI #########################################*/
/* NVIC configuration for SPI transfer complete interrupt (SPI1) */ /* NVIC configuration for SPI transfer complete interrupt (SPI1) */
// Assign the interrupt handler // Assign the interrupt handler
spi::assignSpiUserHandler(spi::SPI_1, &spi::spi1IrqHandler, hspi); spi::assignSpiUserHandler(spi::SPI_1, &spi::spiIrqHandler, hspi);
HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0); HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(SPIx_IRQn); 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<MspDmaConfigStruct*>(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<MspPollingConfigStruct*>(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<MspPollingConfigStruct*>(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<MspIrqConfigStruct*>(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<MspIrqConfigStruct*>(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 * @param hspi: SPI handle pointer
* @retval None * @retval None
*/ */
void spi::halMspDeinitDma(void *spi_handle) extern "C" void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) {
{ if(mspDeinitFunc != NULL) {
SPI_HandleTypeDef* hspi = (SPI_HandleTypeDef*) spi_handle; mspDeinitFunc(hspi, mspDeinitArgs);
if(hspi == NULL) {
return;
} }
spi::halMspDeinitPolling(spi_handle); else {
if(hspi->Instance == SPIx) { printf("HAL_SPI_MspDeInit: Please call set_msp_functions to assign SPI MSP functions\n");
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);
} }
} }
void spi::halMspInitPolling(void *hspi) { void spi::mspErrorHandler(const char* const function, const char *const message) {
GPIO_InitTypeDef GPIO_InitStruct = {}; printf("%s failure: %s\n", function, message);
/*##-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);
} }

View File

@ -1,20 +1,103 @@
#ifndef FSFW_HAL_STM32H7_SPI_MSPINIT_H_ #ifndef FSFW_HAL_STM32H7_SPI_MSPINIT_H_
#define 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 <cstdint>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
namespace spi { namespace spi {
void halMspInitDma(void *hspi); struct MspCfgBase {
void halMspDeinitDma(void *hspi); virtual ~MspCfgBase() = default;
void halMspInitPolling(void *hspi); void (* cleanUpMacroWrapper) (void) = nullptr;
void halMspDeinitPolling(void *hspi); void (* setupMacroWrapper) (void) = nullptr;
void halMspInitInterrupt(void *hspi); GPIO_TypeDef* sckPort = nullptr;
void halMspDeinitInterrupt(void *hspi); 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);
} }

View File

@ -5,12 +5,6 @@ SPI_HandleTypeDef* spiHandle = nullptr;
DMA_HandleTypeDef* hdmaTx = nullptr; DMA_HandleTypeDef* hdmaTx = nullptr;
DMA_HandleTypeDef* hdmaRx = 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; spi_transfer_cb_t rxTxCb = nullptr;
void* rxTxArgs = nullptr; void* rxTxArgs = nullptr;
spi_transfer_cb_t txCb = nullptr; spi_transfer_cb_t txCb = nullptr;
@ -20,6 +14,200 @@ void* rxArgs = nullptr;
spi_transfer_cb_t errorCb = nullptr; spi_transfer_cb_t errorCb = nullptr;
void* errorArgs = 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) { void spi::setDmaHandles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle) {
hdmaTx = txHandle; hdmaTx = txHandle;
hdmaRx = rxHandle; hdmaRx = rxHandle;
@ -61,63 +249,7 @@ SPI_HandleTypeDef* spi::getSpiHandle() {
return spiHandle; 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. * @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"); printf("HAL_SPI_ErrorCallback: No user callback specified\n");
} }
} }

View File

@ -1,27 +1,22 @@
#ifndef FSFW_HAL_STM32H7_SPI_SPICORE_H_ #ifndef FSFW_HAL_STM32H7_SPI_SPICORE_H_
#define FSFW_HAL_STM32H7_SPI_SPICORE_H_ #define FSFW_HAL_STM32H7_SPI_SPICORE_H_
#include <fsfw_hal/stm32h7/dma.h>
#include "stm32h7xx_hal.h" #include "stm32h7xx_hal.h"
#include "stm32h7xx_hal_dma.h" #include "stm32h7xx_hal_dma.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
using msp_func_t = void (*) (void* args);
using spi_transfer_cb_t = void (*) (SPI_HandleTypeDef *hspi, void* userArgs); using spi_transfer_cb_t = void (*) (SPI_HandleTypeDef *hspi, void* userArgs);
namespace spi { namespace spi {
/** void configureDmaHandle(DMA_HandleTypeDef* Handle, dma::DMAType dmaType, dma::DMAIndexes dmaIdx,
* Assign MSP init functions. Important for SPI configuration dma::DMAStreams dmaStream, IRQn_Type* dmaIrqNumber, uint32_t dmaMode = DMA_NORMAL,
* @param init_func uint32_t dmaPriority = DMA_PRIORITY_LOW);
* @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);
/** /**
* Assign DMA handles. Required to use DMA for SPI transfers. * 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 setDmaHandles(DMA_HandleTypeDef* txHandle, DMA_HandleTypeDef* rxHandle);
void getDmaHandles(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 * Assign SPI handle. Needs to be done before using the SPI
* @param spiHandle * @param spiHandle

View File

@ -1,4 +1,5 @@
#include "spiInterrupts.h" #include "spiInterrupts.h"
#include "spiCore.h"
#include "stm32h7xx_hal.h" #include "stm32h7xx_hal.h"
#include "stm32h7xx_hal_dma.h" #include "stm32h7xx_hal_dma.h"
@ -6,10 +7,10 @@
#include <stddef.h> #include <stddef.h>
user_handler_t spi1UserHandler = nullptr; user_handler_t spi1UserHandler = &spi::spiIrqHandler;
user_args_t spi1UserArgs = nullptr; user_args_t spi1UserArgs = nullptr;
user_handler_t spi2UserHandler = nullptr; user_handler_t spi2UserHandler = &spi::spiIrqHandler;
user_args_t spi2UserArgs = nullptr; user_args_t spi2UserArgs = nullptr;
/** /**
@ -35,9 +36,10 @@ void spi::dmaTxIrqHandler(void* dmaHandle) {
* @param None * @param None
* @retval 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, 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 /* 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! */ defined in the startup_stm32h743xx.s files! */
@ -70,5 +96,3 @@ extern "C" void SPI2_IRQHandler() {
} }
Default_Handler(); Default_Handler();
} }

View File

@ -10,6 +10,8 @@ extern "C" {
namespace spi { 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. * 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. * 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, void assignSpiUserHandler(spi::SpiBus spiBus, user_handler_t user_handler,
user_args_t user_args); 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 * 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 dmaRxIrqHandler(void* dma_handle);
void dmaTxIrqHandler(void* dma_handle); void dmaTxIrqHandler(void* dma_handle);
void spi1IrqHandler(void* spi_handle); void spiIrqHandler(void* spi_handle);
} }

View File

@ -0,0 +1,81 @@
#include "stm32h743ziSpi.h"
#include "spiCore.h"
#include "spiInterrupts.h"
#include "stm32h7xx_hal.h"
#include "stm32h7xx_hal_rcc.h"
#include <cstdio>
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);
}

View File

@ -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_ */