170 lines
5.8 KiB
C++
170 lines
5.8 KiB
C++
#include "GyroL3GD20H.h"
|
|
#include "spiConf.h"
|
|
#include "../spi/mspInit.h"
|
|
#include "../spi/spiDefinitions.h"
|
|
#include "../spi/spiCore.h"
|
|
|
|
#include "fsfw/tasks/TaskFactory.h"
|
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
|
|
|
#include "stm32h7xx_nucleo.h"
|
|
#include "stm32h7xx_hal_spi.h"
|
|
#include "stm32h7xx_hal_rcc.h"
|
|
|
|
std::array<uint8_t, GyroL3GD20H::recvBufferSize> GyroL3GD20H::rxBuffer;
|
|
TransferStates transferState = TransferStates::IDLE;
|
|
DMA_HandleTypeDef txDmaHandle;
|
|
DMA_HandleTypeDef rxDmaHandle;
|
|
|
|
GyroL3GD20H::GyroL3GD20H(SPI_HandleTypeDef *spiHandle, spi::TransferModes transferMode):
|
|
spiHandle(spiHandle), transferMode(transferMode) {
|
|
if(transferMode == spi::TransferModes::DMA) {
|
|
set_dma_handles(&txDmaHandle, &rxDmaHandle);
|
|
set_spi_msp_functions(&hal_spi_msp_init_dma, spiHandle, &hal_spi_msp_deinit_dma, spiHandle);
|
|
}
|
|
else if(transferMode == spi::TransferModes::POLLING) {
|
|
set_spi_msp_functions(&hal_spi_msp_init_polling, spiHandle,
|
|
&hal_spi_msp_deinit_polling, spiHandle);
|
|
}
|
|
GPIO_InitTypeDef chipSelect = {};
|
|
__HAL_RCC_GPIOD_CLK_ENABLE();
|
|
chipSelect.Pin = GPIO_PIN_14;
|
|
chipSelect.Mode = GPIO_MODE_OUTPUT_PP;
|
|
HAL_GPIO_Init(GPIOD, &chipSelect);
|
|
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
|
|
}
|
|
|
|
ReturnValue_t GyroL3GD20H::initialize() {
|
|
// Configure the SPI peripheral
|
|
spiHandle->Instance = SPI1;
|
|
spiHandle->Init.BaudRatePrescaler = spi::getPrescaler(HAL_RCC_GetHCLKFreq(), 3900000);
|
|
spiHandle->Init.Direction = SPI_DIRECTION_2LINES;
|
|
spi::assignSpiMode(spi::SpiModes::MODE_3, spiHandle);
|
|
spiHandle->Init.DataSize = SPI_DATASIZE_8BIT;
|
|
spiHandle->Init.FirstBit = SPI_FIRSTBIT_MSB;
|
|
spiHandle->Init.TIMode = SPI_TIMODE_DISABLE;
|
|
spiHandle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
|
|
spiHandle->Init.CRCPolynomial = 7;
|
|
spiHandle->Init.CRCLength = SPI_CRC_LENGTH_8BIT;
|
|
spiHandle->Init.NSS = SPI_NSS_SOFT;
|
|
spiHandle->Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
|
|
// Recommended setting to avoid glitches
|
|
spiHandle->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
|
|
spiHandle->Init.Mode = SPI_MODE_MASTER;
|
|
if(HAL_SPI_Init(spiHandle) != HAL_OK) {
|
|
sif::printWarning("Error initializing SPI\n");
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
}
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
}
|
|
|
|
ReturnValue_t GyroL3GD20H::performOperation() {
|
|
transferState = TransferStates::WAIT;
|
|
|
|
sif::printInfo("GyroL3GD20H::performOperation: Reading WHO AM I register\n");
|
|
|
|
txBuffer[0] = WHO_AM_I_REG | STM_READ_MASK;
|
|
txBuffer[1] = 0;
|
|
|
|
// Start SPI transfer via DMA
|
|
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
|
|
switch(transferMode) {
|
|
case(spi::TransferModes::DMA): {
|
|
return handleDmaTransfer();
|
|
}
|
|
case(spi::TransferModes::POLLING): {
|
|
return handlePollingTransfer();
|
|
}
|
|
default: {
|
|
|
|
}
|
|
}
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
}
|
|
|
|
ReturnValue_t GyroL3GD20H::handleDmaTransfer() {
|
|
if(HAL_SPI_TransmitReceive_DMA(spiHandle, txBuffer.data(), rxBuffer.data(), 2) != 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);
|
|
}
|
|
|
|
// Invalidate cache prior to access by CPU
|
|
SCB_InvalidateDCache_by_Addr ((uint32_t *)rxBuffer.data(), recvBufferSize);
|
|
|
|
switch(transferState) {
|
|
case(TransferStates::SUCCESS): {
|
|
sif::printInfo("DMA 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);
|
|
}
|
|
transferState = TransferStates::IDLE;
|
|
break;
|
|
}
|
|
case(TransferStates::FAILURE): {
|
|
sif::printWarning("Transfer failure\n");
|
|
transferState = TransferStates::FAILURE;
|
|
break;
|
|
}
|
|
default: {
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
}
|
|
}
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief TxRx Transfer completed callback.
|
|
* @param hspi: SPI handle
|
|
* @note This example shows a simple way to report end of DMA TxRx transfer, and
|
|
* you can add your own implementation.
|
|
* @retval None
|
|
*/
|
|
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
|
|
transferState = TransferStates::SUCCESS;
|
|
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
|
|
}
|
|
|
|
/**
|
|
* @brief SPI error callbacks.
|
|
* @param hspi: SPI handle
|
|
* @note This example shows a simple way to report transfer error, and you can
|
|
* add your own implementation.
|
|
* @retval None
|
|
*/
|
|
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) {
|
|
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;
|
|
}
|