Compare commits

2 Commits

Author SHA1 Message Date
895ba1b455 IRQ and POlling now working as well 2021-06-04 15:50:02 +02:00
cf1d6bad19 performed sensor readout 2021-06-04 14:41:02 +02:00
7 changed files with 477 additions and 86 deletions

View File

@ -11,24 +11,34 @@
#include "stm32h7xx_hal_spi.h" #include "stm32h7xx_hal_spi.h"
#include "stm32h7xx_hal_rcc.h" #include "stm32h7xx_hal_rcc.h"
#include <cstring>
alignas(32) std::array<uint8_t, GyroL3GD20H::recvBufferSize> GyroL3GD20H::rxBuffer; alignas(32) std::array<uint8_t, GyroL3GD20H::recvBufferSize> GyroL3GD20H::rxBuffer;
alignas(32) std::array<uint8_t, GyroL3GD20H::txBufferSize> alignas(32) std::array<uint8_t, GyroL3GD20H::txBufferSize>
GyroL3GD20H::txBuffer __attribute__((section(".dma_buffer"))); GyroL3GD20H::txBuffer __attribute__((section(".dma_buffer")));
TransferStates transferState = TransferStates::IDLE; TransferStates transferState = TransferStates::IDLE;
spi::TransferModes GyroL3GD20H::transferMode = spi::TransferModes::POLLING;
DMA_HandleTypeDef txDmaHandle; DMA_HandleTypeDef txDmaHandle;
DMA_HandleTypeDef rxDmaHandle; DMA_HandleTypeDef rxDmaHandle;
GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transferMode): GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transferMode_):
spiHandle(spiHandle), transferMode(transferMode) { spiHandle(spiHandle) {
transferMode = transferMode_;
if(transferMode == spi::TransferModes::DMA) { if(transferMode == spi::TransferModes::DMA) {
set_dma_handles(&txDmaHandle, &rxDmaHandle); set_dma_handles(&txDmaHandle, &rxDmaHandle);
set_spi_msp_functions(&hal_spi_msp_init_dma, spiHandle, &hal_spi_msp_deinit_dma, spiHandle); set_spi_msp_functions(&hal_spi_msp_init_dma, spiHandle, &hal_spi_msp_deinit_dma, spiHandle);
} }
else if(transferMode == spi::TransferModes::INTERRUPT) {
set_spi_msp_functions(&hal_spi_msp_init_interrupt, spiHandle,
&hal_spi_msp_deinit_interrupt, spiHandle);
}
else if(transferMode == spi::TransferModes::POLLING) { else if(transferMode == spi::TransferModes::POLLING) {
set_spi_msp_functions(&hal_spi_msp_init_polling, spiHandle, set_spi_msp_functions(&hal_spi_msp_init_polling, spiHandle,
&hal_spi_msp_deinit_polling, spiHandle); &hal_spi_msp_deinit_polling, spiHandle);
} }
GPIO_InitTypeDef chipSelect = {}; GPIO_InitTypeDef chipSelect = {};
__HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE();
chipSelect.Pin = GPIO_PIN_14; chipSelect.Pin = GPIO_PIN_14;
@ -58,10 +68,7 @@ ReturnValue_t GyroL3GD20H::initialize() {
sif::printWarning("Error initializing SPI\n"); sif::printWarning("Error initializing SPI\n");
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t GyroL3GD20H::performOperation() {
transferState = TransferStates::WAIT; transferState = TransferStates::WAIT;
sif::printInfo("GyroL3GD20H::performOperation: Reading WHO AM I register\n"); sif::printInfo("GyroL3GD20H::performOperation: Reading WHO AM I register\n");
@ -69,33 +76,85 @@ ReturnValue_t GyroL3GD20H::performOperation() {
txBuffer[0] = WHO_AM_I_REG | STM_READ_MASK; txBuffer[0] = WHO_AM_I_REG | STM_READ_MASK;
txBuffer[1] = 0; txBuffer[1] = 0;
// Start SPI transfer via DMA
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
switch(transferMode) { switch(transferMode) {
case(spi::TransferModes::DMA): { case(spi::TransferModes::DMA): {
return handleDmaTransfer(); return handleDmaTransferInit();
}
case(spi::TransferModes::INTERRUPT): {
return handleInterruptTransferInit();
} }
case(spi::TransferModes::POLLING): { case(spi::TransferModes::POLLING): {
return handlePollingTransfer(); return handlePollingTransferInit();
} }
default: { default: {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t GyroL3GD20H::performOperation() {
switch(transferMode) {
case(spi::TransferModes::DMA): {
return handleDmaSensorRead();
}
case(spi::TransferModes::POLLING): {
return handlePollingSensorRead();
}
case(spi::TransferModes::INTERRUPT): {
return handleInterruptSensorRead();
}
default: {
return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t GyroL3GD20H::handleDmaTransfer() { ReturnValue_t GyroL3GD20H::handleDmaTransferInit() {
/* Clean D-cache */ /* Clean D-cache */
/* Make sure the address is 32-byte aligned and add 32-bytes to length, /* Make sure the address is 32-byte aligned and add 32-bytes to length,
in case it overlaps cacheline */ in case it overlaps cacheline */
// See https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices // See https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices
#if STM_USE_PERIPHERAL_TX_BUFFER_MPU_PROTECTION == 0 HAL_StatusTypeDef result = performDmaTransfer(2);
SCB_CleanDCache_by_Addr((uint32_t*)(((uint32_t)txBuffer.data()) & ~(uint32_t)0x1F), if(result != HAL_OK) {
txBuffer.size()+32); // Transfer error in transmission process
#endif sif::printWarning("GyroL3GD20H::initialize: Error transmitting SPI with DMA\n");
}
if(HAL_SPI_TransmitReceive_DMA(spiHandle, txBuffer.data(), rxBuffer.data(), 2) != HAL_OK) { // Wait for the transfer to complete
while (transferState == TransferStates::WAIT) {
TaskFactory::delayTask(1);
}
switch(transferState) {
case(TransferStates::SUCCESS): {
uint8_t whoAmIVal = rxBuffer[1];
if(whoAmIVal != EXPECTED_WHO_AM_I_VAL) {
sif::printDebug("GyroL3GD20H::initialize: "
"Read WHO AM I value %d not equal to expected value!\n", whoAmIVal);
}
transferState = TransferStates::IDLE;
break;
}
case(TransferStates::FAILURE): {
sif::printWarning("Transfer failure\n");
transferState = TransferStates::FAILURE;
return HasReturnvaluesIF::RETURN_FAILED;
}
default: {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
sif::printInfo("GyroL3GD20H::initialize: Configuring device\n");
// Configure the 5 configuration registers
uint8_t configRegs[5];
prepareConfigRegs(configRegs);
result = performDmaTransfer(6);
if(result != HAL_OK) {
// Transfer error in transmission process // Transfer error in transmission process
sif::printWarning("Error transmitting SPI with DMA\n"); sif::printWarning("Error transmitting SPI with DMA\n");
} }
@ -105,24 +164,52 @@ ReturnValue_t GyroL3GD20H::handleDmaTransfer() {
TaskFactory::delayTask(1); TaskFactory::delayTask(1);
} }
// Invalidate cache prior to access by CPU switch(transferState) {
SCB_InvalidateDCache_by_Addr ((uint32_t *)rxBuffer.data(), recvBufferSize); case(TransferStates::SUCCESS): {
sif::printInfo("GyroL3GD20H::initialize: Configuration transfer success\n");
transferState = TransferStates::IDLE;
break;
}
case(TransferStates::FAILURE): {
sif::printWarning("GyroL3GD20H::initialize: Configuration transfer failure\n");
transferState = TransferStates::FAILURE;
return HasReturnvaluesIF::RETURN_FAILED;
}
default: {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK | STM_READ_MASK;
std::memset(txBuffer.data() + 1, 0 , 5);
result = performDmaTransfer(6);
if(result != HAL_OK) {
// Transfer error in transmission process
sif::printWarning("Error transmitting SPI with DMA\n");
}
// Wait for the transfer to complete
while (transferState == TransferStates::WAIT) {
TaskFactory::delayTask(1);
}
switch(transferState) { switch(transferState) {
case(TransferStates::SUCCESS): { case(TransferStates::SUCCESS): {
sif::printInfo("DMA transfer success\n"); if(rxBuffer[1] != configRegs[0] or rxBuffer[2] != configRegs[1] or
uint8_t whoAmIVal = rxBuffer[1]; rxBuffer[3] != configRegs[2] or rxBuffer[4] != configRegs[3] or
if(whoAmIVal != EXPECTED_WHO_AM_I_VAL) { rxBuffer[5] != configRegs[4]) {
sif::printDebug("GyroL3GD20H::performOperation: " sif::printWarning("GyroL3GD20H::initialize: Configuration failure\n");
"Read WHO AM I value %d not equal to expected value!\n", whoAmIVal); }
else {
sif::printInfo("GyroL3GD20H::initialize: Configuration success\n");
} }
transferState = TransferStates::IDLE; transferState = TransferStates::IDLE;
break; break;
} }
case(TransferStates::FAILURE): { case(TransferStates::FAILURE): {
sif::printWarning("Transfer failure\n"); sif::printWarning("GyroL3GD20H::initialize: Configuration transfer failure\n");
transferState = TransferStates::FAILURE; transferState = TransferStates::FAILURE;
break; return HasReturnvaluesIF::RETURN_FAILED;
} }
default: { default: {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
@ -131,6 +218,290 @@ ReturnValue_t GyroL3GD20H::handleDmaTransfer() {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t GyroL3GD20H::handleDmaSensorRead() {
txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK | STM_READ_MASK;
std::memset(txBuffer.data() + 1, 0 , 14);
HAL_StatusTypeDef result = performDmaTransfer(15);
if(result != HAL_OK) {
// Transfer error in transmission process
sif::printDebug("GyroL3GD20H::handleDmaSensorRead: Error transmitting SPI with DMA\n");
}
// Wait for the transfer to complete
while (transferState == TransferStates::WAIT) {
TaskFactory::delayTask(1);
}
switch(transferState) {
case(TransferStates::SUCCESS): {
handleSensorReadout();
break;
}
case(TransferStates::FAILURE): {
sif::printWarning("GyroL3GD20H::handleDmaSensorRead: Sensor read failure\n");
transferState = TransferStates::FAILURE;
return HasReturnvaluesIF::RETURN_FAILED;
}
default: {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
HAL_StatusTypeDef GyroL3GD20H::performDmaTransfer(size_t sendSize) {
transferState = TransferStates::WAIT;
#if STM_USE_PERIPHERAL_TX_BUFFER_MPU_PROTECTION == 0
SCB_CleanDCache_by_Addr((uint32_t*)(((uint32_t)txBuffer.data()) & ~(uint32_t)0x1F),
txBuffer.size()+32);
#endif
// Start SPI transfer via DMA
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
return HAL_SPI_TransmitReceive_DMA(spiHandle, txBuffer.data(), rxBuffer.data(), sendSize);
}
ReturnValue_t GyroL3GD20H::handlePollingTransferInit() {
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
auto result = HAL_SPI_TransmitReceive(spiHandle, txBuffer.data(), rxBuffer.data(), 2, 1000);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
switch(result) {
case(HAL_OK): {
sif::printInfo("GyroL3GD20H::initialize: Polling transfer success\n");
uint8_t whoAmIVal = rxBuffer[1];
if(whoAmIVal != EXPECTED_WHO_AM_I_VAL) {
sif::printDebug("GyroL3GD20H::performOperation: "
"Read WHO AM I value %d not equal to expected value!\n", whoAmIVal);
}
break;
}
case(HAL_TIMEOUT): {
sif::printDebug("GyroL3GD20H::initialize: Polling transfer timeout\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
case(HAL_ERROR): {
sif::printDebug("GyroL3GD20H::initialize: Polling transfer failure\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
default: {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK;
sif::printInfo("GyroL3GD20H::initialize: Configuring device\n");
// Configure the 5 configuration registers
uint8_t configRegs[5];
prepareConfigRegs(configRegs);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
result = HAL_SPI_TransmitReceive(spiHandle, txBuffer.data(), rxBuffer.data(), 6, 1000);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
switch(result) {
case(HAL_OK): {
break;
}
case(HAL_TIMEOUT): {
sif::printDebug("GyroL3GD20H::initialize: Polling transfer timeout\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
case(HAL_ERROR): {
sif::printDebug("GyroL3GD20H::initialize: Polling transfer failure\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
default: {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK;
txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK | STM_READ_MASK;
std::memset(txBuffer.data() + 1, 0 , 5);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
result = HAL_SPI_TransmitReceive(spiHandle, txBuffer.data(), rxBuffer.data(), 6, 1000);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
switch(result) {
case(HAL_OK): {
if(rxBuffer[1] != configRegs[0] or rxBuffer[2] != configRegs[1] or
rxBuffer[3] != configRegs[2] or rxBuffer[4] != configRegs[3] or
rxBuffer[5] != configRegs[4]) {
sif::printWarning("GyroL3GD20H::initialize: Configuration failure\n");
}
else {
sif::printInfo("GyroL3GD20H::initialize: Configuration success\n");
}
break;
}
case(HAL_TIMEOUT): {
sif::printDebug("GyroL3GD20H::initialize: Polling transfer timeout\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
case(HAL_ERROR): {
sif::printDebug("GyroL3GD20H::initialize: Polling transfer failure\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
default: {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t GyroL3GD20H::handlePollingSensorRead() {
txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK | STM_READ_MASK;
std::memset(txBuffer.data() + 1, 0 , 14);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
auto result = HAL_SPI_TransmitReceive(spiHandle, txBuffer.data(), rxBuffer.data(), 15, 1000);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
switch(result) {
case(HAL_OK): {
handleSensorReadout();
break;
}
case(HAL_TIMEOUT): {
sif::printDebug("GyroL3GD20H::initialize: Polling transfer timeout\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
case(HAL_ERROR): {
sif::printDebug("GyroL3GD20H::initialize: Polling transfer failure\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
default: {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t GyroL3GD20H::handleInterruptTransferInit() {
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
switch(HAL_SPI_TransmitReceive_IT(spiHandle, txBuffer.data(), rxBuffer.data(), 2)) {
case(HAL_OK): {
sif::printInfo("GyroL3GD20H::initialize: Interrupt transfer success\n");
// Wait for the transfer to complete
while (transferState == TransferStates::WAIT) {
TaskFactory::delayTask(1);
}
uint8_t whoAmIVal = rxBuffer[1];
if(whoAmIVal != EXPECTED_WHO_AM_I_VAL) {
sif::printDebug("GyroL3GD20H::initialize: "
"Read WHO AM I value %d not equal to expected value!\n", whoAmIVal);
}
break;
}
case(HAL_BUSY):
case(HAL_ERROR):
case(HAL_TIMEOUT): {
sif::printDebug("GyroL3GD20H::initialize: Initialization failure using interrupts\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
}
sif::printInfo("GyroL3GD20H::initialize: Configuring device\n");
transferState = TransferStates::WAIT;
// Configure the 5 configuration registers
uint8_t configRegs[5];
prepareConfigRegs(configRegs);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
switch(HAL_SPI_TransmitReceive_IT(spiHandle, txBuffer.data(), rxBuffer.data(), 6)) {
case(HAL_OK): {
// Wait for the transfer to complete
while (transferState == TransferStates::WAIT) {
TaskFactory::delayTask(1);
}
break;
}
case(HAL_BUSY):
case(HAL_ERROR):
case(HAL_TIMEOUT): {
sif::printDebug("GyroL3GD20H::initialize: Initialization failure using interrupts\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
}
txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK | STM_READ_MASK;
std::memset(txBuffer.data() + 1, 0 , 5);
transferState = TransferStates::WAIT;
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
switch(HAL_SPI_TransmitReceive_IT(spiHandle, txBuffer.data(), rxBuffer.data(), 6)) {
case(HAL_OK): {
// Wait for the transfer to complete
while (transferState == TransferStates::WAIT) {
TaskFactory::delayTask(1);
}
if(rxBuffer[1] != configRegs[0] or rxBuffer[2] != configRegs[1] or
rxBuffer[3] != configRegs[2] or rxBuffer[4] != configRegs[3] or
rxBuffer[5] != configRegs[4]) {
sif::printWarning("GyroL3GD20H::initialize: Configuration failure\n");
}
else {
sif::printInfo("GyroL3GD20H::initialize: Configuration success\n");
}
break;
}
case(HAL_BUSY):
case(HAL_ERROR):
case(HAL_TIMEOUT): {
sif::printDebug("GyroL3GD20H::initialize: Initialization failure using interrupts\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t GyroL3GD20H::handleInterruptSensorRead() {
transferState = TransferStates::WAIT;
txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK | STM_READ_MASK;
std::memset(txBuffer.data() + 1, 0 , 14);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
switch(HAL_SPI_TransmitReceive_IT(spiHandle, txBuffer.data(), rxBuffer.data(), 15)) {
case(HAL_OK): {
// Wait for the transfer to complete
while (transferState == TransferStates::WAIT) {
TaskFactory::delayTask(1);
}
handleSensorReadout();
break;
}
case(HAL_BUSY):
case(HAL_ERROR):
case(HAL_TIMEOUT): {
sif::printDebug("GyroL3GD20H::initialize: Sensor read failure using interrupts\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
void GyroL3GD20H::prepareConfigRegs(uint8_t* configRegs) {
// Enable sensor
configRegs[0] = 0b00001111;
configRegs[1] = 0b00000000;
configRegs[2] = 0b00000000;
configRegs[3] = 0b01000000;
// Big endian select
configRegs[4] = 0b00000000;
txBuffer[0] = CTRL_REG_1 | STM_AUTO_INCREMENT_MASK;
std::memcpy(txBuffer.data() + 1, configRegs, 5);
}
void GyroL3GD20H::handleSensorReadout() {
uint8_t statusReg = rxBuffer[8];
int16_t gyroXRaw = rxBuffer[9] << 8 | rxBuffer[10];
float gyroX = static_cast<float>(gyroXRaw) / INT16_MAX * L3G_RANGE;
int16_t gyroYRaw = rxBuffer[11] << 8 | rxBuffer[12];
float gyroY = static_cast<float>(gyroYRaw) / INT16_MAX * L3G_RANGE;
int16_t gyroZRaw = rxBuffer[13] << 8 | rxBuffer[14];
float gyroZ = static_cast<float>(gyroZRaw) / INT16_MAX * L3G_RANGE;
sif::printInfo("Status register: 0b" BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(statusReg));
sif::printInfo("Gyro X: %f\n", gyroX);
sif::printInfo("Gyro Y: %f\n", gyroY);
sif::printInfo("Gyro Z: %f\n", gyroZ);
}
/** /**
* @brief TxRx Transfer completed callback. * @brief TxRx Transfer completed callback.
* @param hspi: SPI handle * @param hspi: SPI handle
@ -141,6 +512,11 @@ ReturnValue_t GyroL3GD20H::handleDmaTransfer() {
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
transferState = TransferStates::SUCCESS; transferState = TransferStates::SUCCESS;
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
if(GyroL3GD20H::transferMode == spi::TransferModes::DMA) {
// Invalidate cache prior to access by CPU
SCB_InvalidateDCache_by_Addr ((uint32_t *)GyroL3GD20H::rxBuffer.data(),
GyroL3GD20H::recvBufferSize);
}
} }
/** /**
@ -153,29 +529,3 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) {
transferState = TransferStates::FAILURE; transferState = TransferStates::FAILURE;
} }
ReturnValue_t GyroL3GD20H::handlePollingTransfer() {
switch(HAL_SPI_TransmitReceive(spiHandle, txBuffer.data(), rxBuffer.data(), 2, 1000)) {
case(HAL_OK): {
sif::printInfo("Polling transfer success\n");
uint8_t whoAmIVal = rxBuffer[1];
if(whoAmIVal != EXPECTED_WHO_AM_I_VAL) {
sif::printDebug("GyroL3GD20H::performOperation: "
"Read WHO AM I value %d not equal to expected value!\n", whoAmIVal);
}
break;
}
case(HAL_TIMEOUT): {
sif::printDebug("Polling transfer timeout\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
case(HAL_ERROR): {
sif::printDebug("Polling transfer failure\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
default: {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -18,6 +18,7 @@ enum class TransferStates {
}; };
class GyroL3GD20H { class GyroL3GD20H {
friend void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi);
public: public:
GyroL3GD20H(SPI_HandleTypeDef* spiHandle, spi::TransferModes transferMode); GyroL3GD20H(SPI_HandleTypeDef* spiHandle, spi::TransferModes transferMode);
@ -28,18 +29,30 @@ private:
const uint8_t WHO_AM_I_REG = 0b00001111; const uint8_t WHO_AM_I_REG = 0b00001111;
const uint8_t STM_READ_MASK = 0b10000000; const uint8_t STM_READ_MASK = 0b10000000;
const uint8_t STM_AUTO_INCREMENT_MASK = 0b01000000;
const uint8_t EXPECTED_WHO_AM_I_VAL = 0b11010111; const uint8_t EXPECTED_WHO_AM_I_VAL = 0b11010111;
const uint8_t CTRL_REG_1 = 0b00100000;
const uint32_t L3G_RANGE = 245;
SPI_HandleTypeDef* spiHandle; SPI_HandleTypeDef* spiHandle;
spi::TransferModes transferMode;
static constexpr size_t recvBufferSize = 32 * 10;
static spi::TransferModes transferMode;
static constexpr size_t recvBufferSize = 32 * 10;
static std::array<uint8_t, recvBufferSize> rxBuffer; static std::array<uint8_t, recvBufferSize> rxBuffer;
static constexpr size_t txBufferSize = 32; static constexpr size_t txBufferSize = 32;
static std::array<uint8_t, txBufferSize> txBuffer; static std::array<uint8_t, txBufferSize> txBuffer;
ReturnValue_t handleDmaTransfer(); ReturnValue_t handleDmaTransferInit();
ReturnValue_t handlePollingTransfer(); ReturnValue_t handlePollingTransferInit();
ReturnValue_t handleInterruptTransferInit();
ReturnValue_t handleDmaSensorRead();
HAL_StatusTypeDef performDmaTransfer(size_t sendSize);
ReturnValue_t handlePollingSensorRead();
ReturnValue_t handleInterruptSensorRead();
void prepareConfigRegs(uint8_t* configRegs);
void handleSensorReadout();
}; };
#endif /* FSFW_HAL_STM32H7_DEVICETEST_GYRO_L3GD20H_H_ */ #endif /* FSFW_HAL_STM32H7_DEVICETEST_GYRO_L3GD20H_H_ */

View File

@ -1,7 +1,12 @@
#include "interrupts.h" #include "interrupts.h"
#include "stm32h7xx_hal.h"
#include "stm32h7xx_hal_dma.h"
#include "stm32h7xx_hal_spi.h"
#include <stddef.h> #include <stddef.h>
void (*spi1_user_handler) (void* args) = NULL; void (*spi1_user_handler) (void* args) = NULL;
void * spi1_user_args = NULL; void * spi1_user_args = NULL;
@ -37,3 +42,32 @@ void SPI2_IRQHandler() {
} }
Default_Handler(); Default_Handler();
} }
/**
* @brief This function handles DMA Rx interrupt request.
* @param None
* @retval None
*/
void dma_rx_irq_handler(void* dma_handle) {
HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dma_handle);
}
/**
* @brief This function handles DMA Rx interrupt request.
* @param None
* @retval None
*/
void dma_tx_irq_handler(void* dma_handle) {
HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dma_handle);
}
/**
* @brief This function handles SPIx interrupt request.
* @param None
* @retval None
*/
void spi1_irq_handler(void* spi_handle)
{
HAL_SPI_IRQHandler((SPI_HandleTypeDef *) spi_handle);
}

View File

@ -20,6 +20,15 @@ typedef enum {
*/ */
void assign_spi_user_handler(SpiBus spiBus, user_handler_t user_handler, user_args_t user_args); void assign_spi_user_handler(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
* instead with assign_dma_user_handler and assign_spi_user_handler functions.
* @param dma_handle
*/
void dma_rx_irq_handler(void* dma_handle);
void dma_tx_irq_handler(void* dma_handle);
void spi1_irq_handler(void* spi_handle);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -11,10 +11,6 @@
#include <stdio.h> #include <stdio.h>
void dma_rx_irq_handler(void* dma_handle);
void dma_tx_irq_handler(void* dma_handle);
void spi1_irq_handler(void* spi_handle);
/** /**
* @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:
@ -195,3 +191,17 @@ void hal_spi_msp_deinit_polling(void *hspi) {
/* Configure SPI MOSI as alternate function */ /* Configure SPI MOSI as alternate function */
HAL_GPIO_DeInit(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_PIN); HAL_GPIO_DeInit(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_PIN);
} }
void hal_spi_msp_init_interrupt(void *hspi) {
hal_spi_msp_init_polling(hspi);
// Configure the NVIC for SPI
assign_spi_user_handler(SPI_1, &spi1_irq_handler, hspi);
HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(SPIx_IRQn);
}
void hal_spi_msp_deinit_interrupt(void *hspi) {
hal_spi_msp_deinit_polling(hspi);
// Disable the NVIC for SPI
HAL_NVIC_DisableIRQ(SPIx_IRQn);
}

View File

@ -11,6 +11,9 @@ void hal_spi_msp_deinit_dma(void *hspi);
void hal_spi_msp_init_polling(void *hspi); void hal_spi_msp_init_polling(void *hspi);
void hal_spi_msp_deinit_polling(void *hspi); void hal_spi_msp_deinit_polling(void *hspi);
void hal_spi_msp_init_interrupt(void *hspi);
void hal_spi_msp_deinit_interrupt(void *hspi);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -32,34 +32,6 @@ SPI_HandleTypeDef* get_spi_handle() {
return spiHandle; return spiHandle;
} }
/**
* @brief This function handles DMA Rx interrupt request.
* @param None
* @retval None
*/
void dma_rx_irq_handler(void* dma_handle) {
HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dma_handle);
}
/**
* @brief This function handles DMA Rx interrupt request.
* @param None
* @retval None
*/
void dma_tx_irq_handler(void* dma_handle) {
HAL_DMA_IRQHandler((DMA_HandleTypeDef *) dma_handle);
}
/**
* @brief This function handles SPIx interrupt request.
* @param None
* @retval None
*/
void spi1_irq_handler(void* spi_handle)
{
HAL_SPI_IRQHandler((SPI_HandleTypeDef *) spi_handle);
}
void set_spi_msp_functions(msp_func_t init_func, void* init_args, msp_func_t deinit_func, void set_spi_msp_functions(msp_func_t init_func, void* init_args, msp_func_t deinit_func,
void* deinit_args) { void* deinit_args) {
msp_init_func = init_func; msp_init_func = init_func;