1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-23 16:25:31 +03:00

Fix SPI timeout

This commit is contained in:
Hans Christian Olaussen 2021-04-01 12:46:16 +02:00
parent 025ee87a7a
commit ff95fc6471
4 changed files with 60 additions and 42 deletions

View file

@ -36,6 +36,8 @@
#include "nvic.h" #include "nvic.h"
#include "rcc.h" #include "rcc.h"
#define SPI_TIMEOUT_SYS_TICKS (SPI_TIMEOUT_US / 1000)
void spiInitDevice(SPIDevice device, bool leadingEdge) void spiInitDevice(SPIDevice device, bool leadingEdge)
{ {
spiDevice_t *spi = &(spiDevice[device]); spiDevice_t *spi = &(spiDevice[device]);
@ -93,8 +95,7 @@ void spiInitDevice(SPIDevice device, bool leadingEdge)
if (spi->leadingEdge) { if (spi->leadingEdge) {
spi->hspi.Init.CLKPolarity = SPI_POLARITY_LOW; spi->hspi.Init.CLKPolarity = SPI_POLARITY_LOW;
spi->hspi.Init.CLKPhase = SPI_PHASE_1EDGE; spi->hspi.Init.CLKPhase = SPI_PHASE_1EDGE;
} } else {
else {
spi->hspi.Init.CLKPolarity = SPI_POLARITY_HIGH; spi->hspi.Init.CLKPolarity = SPI_POLARITY_HIGH;
spi->hspi.Init.CLKPhase = SPI_PHASE_2EDGE; spi->hspi.Init.CLKPhase = SPI_PHASE_2EDGE;
} }
@ -118,10 +119,11 @@ uint8_t spiTransferByte(SPI_TypeDef *instance, uint8_t out)
bool spiIsBusBusy(SPI_TypeDef *instance) bool spiIsBusBusy(SPI_TypeDef *instance)
{ {
SPIDevice device = spiDeviceByInstance(instance); SPIDevice device = spiDeviceByInstance(instance);
if(spiDevice[device].hspi.State == HAL_SPI_STATE_BUSY) if (spiDevice[device].hspi.State == HAL_SPI_STATE_BUSY) {
return true; return true;
else } else {
return false; return false;
}
} }
bool spiTransfer(SPI_TypeDef *instance, const uint8_t *out, uint8_t *in, int len) bool spiTransfer(SPI_TypeDef *instance, const uint8_t *out, uint8_t *in, int len)
@ -129,20 +131,18 @@ bool spiTransfer(SPI_TypeDef *instance, const uint8_t *out, uint8_t *in, int len
SPIDevice device = spiDeviceByInstance(instance); SPIDevice device = spiDeviceByInstance(instance);
HAL_StatusTypeDef status; HAL_StatusTypeDef status;
#define SPI_DEFAULT_TIMEOUT 10
if (!in) { if (!in) {
// Tx only // Tx only
status = HAL_SPI_Transmit(&spiDevice[device].hspi, out, len, SPI_DEFAULT_TIMEOUT); status = HAL_SPI_Transmit(&spiDevice[device].hspi, out, len, SPI_TIMEOUT_SYS_TICKS);
} else if(!out) { } else if (!out) {
// Rx only // Rx only
status = HAL_SPI_Receive(&spiDevice[device].hspi, in, len, SPI_DEFAULT_TIMEOUT); status = HAL_SPI_Receive(&spiDevice[device].hspi, in, len, SPI_TIMEOUT_SYS_TICKS);
} else { } else {
// Tx and Rx // Tx and Rx
status = HAL_SPI_TransmitReceive(&spiDevice[device].hspi, out, in, len, SPI_DEFAULT_TIMEOUT); status = HAL_SPI_TransmitReceive(&spiDevice[device].hspi, out, in, len, SPI_TIMEOUT_SYS_TICKS);
} }
if(status != HAL_OK) { if (status != HAL_OK) {
spiTimeoutUserCallback(instance); spiTimeoutUserCallback(instance);
} }
@ -210,8 +210,9 @@ void SPI4_IRQHandler(void)
void dmaSPIIRQHandler(dmaChannelDescriptor_t* descriptor) void dmaSPIIRQHandler(dmaChannelDescriptor_t* descriptor)
{ {
SPIDevice device = descriptor->userParam; SPIDevice device = descriptor->userParam;
if (device != SPIINVALID) if (device != SPIINVALID) {
HAL_DMA_IRQHandler(&spiDevice[device].hdma); HAL_DMA_IRQHandler(&spiDevice[device].hdma);
}
} }
#endif // USE_DMA #endif // USE_DMA
#endif #endif

View file

@ -20,6 +20,8 @@
#pragma once #pragma once
#define SPI_TIMEOUT_US 10000
#if defined(STM32F1) || defined(STM32F3) || defined(STM32F4) || defined(STM32G4) #if defined(STM32F1) || defined(STM32F3) || defined(STM32F4) || defined(STM32G4)
#define MAX_SPI_PIN_SEL 2 #define MAX_SPI_PIN_SEL 2
#elif defined(STM32F7) #elif defined(STM32F7)

View file

@ -36,6 +36,7 @@
#include "drivers/io.h" #include "drivers/io.h"
#include "drivers/nvic.h" #include "drivers/nvic.h"
#include "drivers/rcc.h" #include "drivers/rcc.h"
#include "drivers/time.h"
#ifndef SPI2_SCK_PIN #ifndef SPI2_SCK_PIN
#define SPI2_NSS_PIN PB12 #define SPI2_NSS_PIN PB12
@ -71,8 +72,6 @@
#define SPI4_NSS_PIN NONE #define SPI4_NSS_PIN NONE
#endif #endif
#define SPI_DEFAULT_TIMEOUT 10
static LL_SPI_InitTypeDef defaultInit = static LL_SPI_InitTypeDef defaultInit =
{ {
.TransferDirection = SPI_DIRECTION_2LINES, .TransferDirection = SPI_DIRECTION_2LINES,
@ -107,10 +106,12 @@ void spiInitDevice(SPIDevice device, bool leadingEdge)
IOInit(IOGetByTag(spi->miso), OWNER_SPI_MISO, RESOURCE_INDEX(device)); IOInit(IOGetByTag(spi->miso), OWNER_SPI_MISO, RESOURCE_INDEX(device));
IOInit(IOGetByTag(spi->mosi), OWNER_SPI_MOSI, RESOURCE_INDEX(device)); IOInit(IOGetByTag(spi->mosi), OWNER_SPI_MOSI, RESOURCE_INDEX(device));
if (spi->leadingEdge == true) if (spi->leadingEdge == true) {
IOConfigGPIOAF(IOGetByTag(spi->sck), SPI_IO_AF_SCK_CFG_LOW, spi->sckAF); IOConfigGPIOAF(IOGetByTag(spi->sck), SPI_IO_AF_SCK_CFG_LOW, spi->sckAF);
else } else {
IOConfigGPIOAF(IOGetByTag(spi->sck), SPI_IO_AF_SCK_CFG_HIGH, spi->sckAF); IOConfigGPIOAF(IOGetByTag(spi->sck), SPI_IO_AF_SCK_CFG_HIGH, spi->sckAF);
}
IOConfigGPIOAF(IOGetByTag(spi->miso), SPI_IO_AF_MISO_CFG, spi->misoAF); IOConfigGPIOAF(IOGetByTag(spi->miso), SPI_IO_AF_MISO_CFG, spi->misoAF);
IOConfigGPIOAF(IOGetByTag(spi->mosi), SPI_IO_AF_CFG, spi->mosiAF); IOConfigGPIOAF(IOGetByTag(spi->mosi), SPI_IO_AF_CFG, spi->mosiAF);
@ -136,18 +137,21 @@ void spiInitDevice(SPIDevice device, bool leadingEdge)
uint8_t spiTransferByte(SPI_TypeDef *instance, uint8_t txByte) uint8_t spiTransferByte(SPI_TypeDef *instance, uint8_t txByte)
{ {
uint16_t spiTimeout = 1000; timeUs_t timeoutStartUs = microsISR();
while (!LL_SPI_IsActiveFlag_TXE(instance)) while (!LL_SPI_IsActiveFlag_TXE(instance)) {
if ((spiTimeout--) == 0) if (cmpTimeUs(microsISR(), timeoutStartUs) >= SPI_TIMEOUT_US) {
return spiTimeoutUserCallback(instance); return spiTimeoutUserCallback(instance);
}
}
LL_SPI_TransmitData8(instance, txByte); LL_SPI_TransmitData8(instance, txByte);
spiTimeout = 1000; timeoutStartUs = microsISR();
while (!LL_SPI_IsActiveFlag_RXNE(instance)) while (!LL_SPI_IsActiveFlag_RXNE(instance)) {
if ((spiTimeout--) == 0) if (cmpTimeUs(microsISR(), timeoutStartUs) >= SPI_TIMEOUT_US) {
return spiTimeoutUserCallback(instance); return spiTimeoutUserCallback(instance);
}
}
return (uint8_t)LL_SPI_ReceiveData8(instance); return (uint8_t)LL_SPI_ReceiveData8(instance);
} }
@ -163,12 +167,14 @@ bool spiIsBusBusy(SPI_TypeDef *instance)
bool spiTransfer(SPI_TypeDef *instance, const uint8_t *txData, uint8_t *rxData, int len) bool spiTransfer(SPI_TypeDef *instance, const uint8_t *txData, uint8_t *rxData, int len)
{ {
timeUs_t timeoutStartUs;
// set 16-bit transfer // set 16-bit transfer
CLEAR_BIT(instance->CR2, SPI_RXFIFO_THRESHOLD); CLEAR_BIT(instance->CR2, SPI_RXFIFO_THRESHOLD);
while (len > 1) { while (len > 1) {
int spiTimeout = 1000; timeoutStartUs = microsISR();
while (!LL_SPI_IsActiveFlag_TXE(instance)) { while (!LL_SPI_IsActiveFlag_TXE(instance)) {
if ((spiTimeout--) == 0) { if (cmpTimeUs(microsISR(), timeoutStartUs) >= SPI_TIMEOUT_US) {
return spiTimeoutUserCallback(instance); return spiTimeoutUserCallback(instance);
} }
} }
@ -181,9 +187,9 @@ bool spiTransfer(SPI_TypeDef *instance, const uint8_t *txData, uint8_t *rxData,
} }
LL_SPI_TransmitData16(instance, w); LL_SPI_TransmitData16(instance, w);
spiTimeout = 1000; timeoutStartUs = microsISR();
while (!LL_SPI_IsActiveFlag_RXNE(instance)) { while (!LL_SPI_IsActiveFlag_RXNE(instance)) {
if ((spiTimeout--) == 0) { if (cmpTimeUs(microsISR(), timeoutStartUs) >= SPI_TIMEOUT_US) {
return spiTimeoutUserCallback(instance); return spiTimeoutUserCallback(instance);
} }
} }
@ -197,18 +203,18 @@ bool spiTransfer(SPI_TypeDef *instance, const uint8_t *txData, uint8_t *rxData,
// set 8-bit transfer // set 8-bit transfer
SET_BIT(instance->CR2, SPI_RXFIFO_THRESHOLD); SET_BIT(instance->CR2, SPI_RXFIFO_THRESHOLD);
if (len) { if (len) {
int spiTimeout = 1000; timeoutStartUs = microsISR();
while (!LL_SPI_IsActiveFlag_TXE(instance)) { while (!LL_SPI_IsActiveFlag_TXE(instance)) {
if ((spiTimeout--) == 0) { if (cmpTimeUs(microsISR(), timeoutStartUs) >= SPI_TIMEOUT_US) {
return spiTimeoutUserCallback(instance); return spiTimeoutUserCallback(instance);
} }
} }
uint8_t b = txData ? *(txData++) : 0xFF; uint8_t b = txData ? *(txData++) : 0xFF;
LL_SPI_TransmitData8(instance, b); LL_SPI_TransmitData8(instance, b);
spiTimeout = 1000; timeoutStartUs = microsISR();
while (!LL_SPI_IsActiveFlag_RXNE(instance)) { while (!LL_SPI_IsActiveFlag_RXNE(instance)) {
if ((spiTimeout--) == 0) { if (cmpTimeUs(microsISR(), timeoutStartUs) >= SPI_TIMEOUT_US) {
return spiTimeoutUserCallback(instance); return spiTimeoutUserCallback(instance);
} }
} }

View file

@ -33,6 +33,7 @@
#include "drivers/exti.h" #include "drivers/exti.h"
#include "drivers/io.h" #include "drivers/io.h"
#include "drivers/rcc.h" #include "drivers/rcc.h"
#include "drivers/time.h"
static SPI_InitTypeDef defaultInit = { static SPI_InitTypeDef defaultInit = {
.SPI_Mode = SPI_Mode_Master, .SPI_Mode = SPI_Mode_Master,
@ -104,23 +105,27 @@ void spiInitDevice(SPIDevice device, bool leadingEdge)
// return uint8_t value or -1 when failure // return uint8_t value or -1 when failure
uint8_t spiTransferByte(SPI_TypeDef *instance, uint8_t txByte) uint8_t spiTransferByte(SPI_TypeDef *instance, uint8_t txByte)
{ {
uint16_t spiTimeout = 1000; timeUs_t timeoutStartUs = microsISR();
DISCARD(instance->DR); DISCARD(instance->DR);
while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_TXE) == RESET) while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_TXE) == RESET) {
if ((spiTimeout--) == 0) if (cmpTimeUs(microsISR(), timeoutStartUs) >= SPI_TIMEOUT_US) {
return spiTimeoutUserCallback(instance); return spiTimeoutUserCallback(instance);
}
}
#ifdef STM32F303xC #ifdef STM32F303xC
SPI_SendData8(instance, txByte); SPI_SendData8(instance, txByte);
#else #else
SPI_I2S_SendData(instance, txByte); SPI_I2S_SendData(instance, txByte);
#endif #endif
spiTimeout = 1000; timeoutStartUs = microsISR();
while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_RXNE) == RESET) while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_RXNE) == RESET) {
if ((spiTimeout--) == 0) if (cmpTimeUs(microsISR(), timeoutStartUs) >= SPI_TIMEOUT_US) {
return spiTimeoutUserCallback(instance); return spiTimeoutUserCallback(instance);
}
}
#ifdef STM32F303xC #ifdef STM32F303xC
return ((uint8_t)SPI_ReceiveData8(instance)); return ((uint8_t)SPI_ReceiveData8(instance));
@ -144,15 +149,17 @@ bool spiIsBusBusy(SPI_TypeDef *instance)
bool spiTransfer(SPI_TypeDef *instance, const uint8_t *txData, uint8_t *rxData, int len) bool spiTransfer(SPI_TypeDef *instance, const uint8_t *txData, uint8_t *rxData, int len)
{ {
uint16_t spiTimeout = 1000; timeUs_t timeoutStartUs;
uint8_t b; uint8_t b;
DISCARD(instance->DR); DISCARD(instance->DR);
while (len--) { while (len--) {
b = txData ? *(txData++) : 0xFF; b = txData ? *(txData++) : 0xFF;
timeoutStartUs = microsISR();
while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_TXE) == RESET) { while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_TXE) == RESET) {
if ((spiTimeout--) == 0) if (cmpTimeUs(microsISR(), timeoutStartUs) >= SPI_TIMEOUT_US) {
return spiTimeoutUserCallback(instance); return spiTimeoutUserCallback(instance);
}
} }
#ifdef STM32F303xC #ifdef STM32F303xC
SPI_SendData8(instance, b); SPI_SendData8(instance, b);
@ -160,19 +167,21 @@ bool spiTransfer(SPI_TypeDef *instance, const uint8_t *txData, uint8_t *rxData,
SPI_I2S_SendData(instance, b); SPI_I2S_SendData(instance, b);
#endif #endif
spiTimeout = 1000; timeoutStartUs = microsISR();
while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_RXNE) == RESET) { while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_RXNE) == RESET) {
if ((spiTimeout--) == 0) if (cmpTimeUs(microsISR(), timeoutStartUs) >= SPI_TIMEOUT_US) {
return spiTimeoutUserCallback(instance); return spiTimeoutUserCallback(instance);
}
} }
#ifdef STM32F303xC #ifdef STM32F303xC
b = SPI_ReceiveData8(instance); b = SPI_ReceiveData8(instance);
#else #else
b = SPI_I2S_ReceiveData(instance); b = SPI_I2S_ReceiveData(instance);
#endif #endif
if (rxData) if (rxData) {
*(rxData++) = b; *(rxData++) = b;
}
} }
return true; return true;