2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
24 #if defined(USE_SPI) && !defined(USE_LOWLEVEL_DRIVER)
26 #include "common/utils.h"
28 #include "drivers/bus.h"
29 #include "drivers/bus_spi.h"
30 #include "drivers/bus_spi_impl.h"
31 #include "drivers/dma.h"
32 #include "drivers/io.h"
33 #include "drivers/nvic.h"
34 #include "drivers/rcc.h"
36 spiDevice_t spiDevice
[SPIDEV_COUNT
];
39 #define SPI2_NSS_PIN PB12
40 #define SPI2_SCK_PIN PB13
41 #define SPI2_MISO_PIN PB14
42 #define SPI2_MOSI_PIN PB15
46 #define SPI3_NSS_PIN PA15
47 #define SPI3_SCK_PIN PB3
48 #define SPI3_MISO_PIN PB4
49 #define SPI3_MOSI_PIN PB5
53 #define SPI4_NSS_PIN PA15
54 #define SPI4_SCK_PIN PB3
55 #define SPI4_MISO_PIN PB4
56 #define SPI4_MOSI_PIN PB5
60 #define SPI1_NSS_PIN NONE
63 #define SPI2_NSS_PIN NONE
66 #define SPI3_NSS_PIN NONE
69 #define SPI4_NSS_PIN NONE
72 #define SPI_DEFAULT_TIMEOUT 10
74 SPIDevice
spiDeviceByInstance(SPI_TypeDef
*instance
)
76 #ifdef USE_SPI_DEVICE_1
81 #ifdef USE_SPI_DEVICE_2
86 #ifdef USE_SPI_DEVICE_3
91 #ifdef USE_SPI_DEVICE_4
99 SPI_HandleTypeDef
* spiHandleByInstance(SPI_TypeDef
*instance
)
101 return &spiDevice
[spiDeviceByInstance(instance
)].hspi
;
104 SPI_TypeDef
*spiInstanceByDevice(SPIDevice device
)
106 if (device
>= SPIDEV_COUNT
) {
110 return spiDevice
[device
].dev
;
113 DMA_HandleTypeDef
* dmaHandleByInstance(SPI_TypeDef
*instance
)
115 return &spiDevice
[spiDeviceByInstance(instance
)].hdma
;
118 void SPI1_IRQHandler(void)
120 HAL_SPI_IRQHandler(&spiDevice
[SPIDEV_1
].hspi
);
123 void SPI2_IRQHandler(void)
125 HAL_SPI_IRQHandler(&spiDevice
[SPIDEV_2
].hspi
);
128 void SPI3_IRQHandler(void)
130 HAL_SPI_IRQHandler(&spiDevice
[SPIDEV_3
].hspi
);
133 void SPI4_IRQHandler(void)
135 HAL_SPI_IRQHandler(&spiDevice
[SPIDEV_4
].hspi
);
139 void spiInitDevice(SPIDevice device
)
141 spiDevice_t
*spi
= &(spiDevice
[device
]);
143 #ifdef SDCARD_SPI_INSTANCE
144 if (spi
->dev
== SDCARD_SPI_INSTANCE
) {
145 spi
->leadingEdge
= true;
148 #ifdef RX_SPI_INSTANCE
149 if (spi
->dev
== RX_SPI_INSTANCE
) {
150 spi
->leadingEdge
= true;
153 #ifdef MPU6500_SPI_INSTANCE
154 if (spi
->dev
== MPU6500_SPI_INSTANCE
) {
155 spi
->leadingEdge
= true;
160 RCC_ClockCmd(spi
->rcc
, ENABLE
);
161 RCC_ResetCmd(spi
->rcc
, ENABLE
);
163 IOInit(IOGetByTag(spi
->sck
), OWNER_SPI_SCK
, RESOURCE_INDEX(device
));
164 IOInit(IOGetByTag(spi
->miso
), OWNER_SPI_MISO
, RESOURCE_INDEX(device
));
165 IOInit(IOGetByTag(spi
->mosi
), OWNER_SPI_MOSI
, RESOURCE_INDEX(device
));
168 if (spi
->leadingEdge
== true)
169 IOConfigGPIOAF(IOGetByTag(spi
->sck
), SPI_IO_AF_SCK_CFG_LOW
, spi
->sckAF
);
171 IOConfigGPIOAF(IOGetByTag(spi
->sck
), SPI_IO_AF_SCK_CFG_HIGH
, spi
->sckAF
);
172 IOConfigGPIOAF(IOGetByTag(spi
->miso
), SPI_IO_AF_MISO_CFG
, spi
->misoAF
);
173 IOConfigGPIOAF(IOGetByTag(spi
->mosi
), SPI_IO_AF_CFG
, spi
->mosiAF
);
175 #if defined(STM32F3) || defined(STM32F4)
176 if (spi
->leadingEdge
== true)
177 IOConfigGPIOAF(IOGetByTag(spi
->sck
), SPI_IO_AF_SCK_CFG_LOW
, spi
->af
);
179 IOConfigGPIOAF(IOGetByTag(spi
->sck
), SPI_IO_AF_SCK_CFG_HIGH
, spi
->af
);
180 IOConfigGPIOAF(IOGetByTag(spi
->miso
), SPI_IO_AF_MISO_CFG
, spi
->af
);
181 IOConfigGPIOAF(IOGetByTag(spi
->mosi
), SPI_IO_AF_CFG
, spi
->af
);
183 #if defined(STM32F10X)
184 IOConfigGPIO(IOGetByTag(spi
->sck
), SPI_IO_AF_SCK_CFG
);
185 IOConfigGPIO(IOGetByTag(spi
->miso
), SPI_IO_AF_MISO_CFG
);
186 IOConfigGPIO(IOGetByTag(spi
->mosi
), SPI_IO_AF_MOSI_CFG
);
188 spiDevice
[device
].hspi
.Instance
= spi
->dev
;
190 HAL_SPI_DeInit(&spiDevice
[device
].hspi
);
192 spiDevice
[device
].hspi
.Init
.Mode
= SPI_MODE_MASTER
;
193 spiDevice
[device
].hspi
.Init
.Direction
= SPI_DIRECTION_2LINES
;
194 spiDevice
[device
].hspi
.Init
.DataSize
= SPI_DATASIZE_8BIT
;
195 spiDevice
[device
].hspi
.Init
.NSS
= SPI_NSS_SOFT
;
196 spiDevice
[device
].hspi
.Init
.FirstBit
= SPI_FIRSTBIT_MSB
;
197 spiDevice
[device
].hspi
.Init
.CRCPolynomial
= 7;
198 spiDevice
[device
].hspi
.Init
.BaudRatePrescaler
= SPI_BAUDRATEPRESCALER_256
;
199 spiDevice
[device
].hspi
.Init
.CRCCalculation
= SPI_CRCCALCULATION_DISABLE
;
200 spiDevice
[device
].hspi
.Init
.TIMode
= SPI_TIMODE_DISABLED
;
202 if (spi
->leadingEdge
) {
203 spiDevice
[device
].hspi
.Init
.CLKPolarity
= SPI_POLARITY_LOW
;
204 spiDevice
[device
].hspi
.Init
.CLKPhase
= SPI_PHASE_1EDGE
;
207 spiDevice
[device
].hspi
.Init
.CLKPolarity
= SPI_POLARITY_HIGH
;
208 spiDevice
[device
].hspi
.Init
.CLKPhase
= SPI_PHASE_2EDGE
;
211 if (HAL_SPI_Init(&spiDevice
[device
].hspi
) == HAL_OK
)
216 bool spiInit(SPIDevice device
)
222 #if defined(USE_SPI_DEVICE_1)
223 spiInitDevice(device
);
229 #if defined(USE_SPI_DEVICE_2)
230 spiInitDevice(device
);
236 #if defined(USE_SPI_DEVICE_3)
237 spiInitDevice(device
);
243 #if defined(USE_SPI_DEVICE_4)
244 spiInitDevice(device
);
253 uint32_t spiTimeoutUserCallback(SPI_TypeDef
*instance
)
255 SPIDevice device
= spiDeviceByInstance(instance
);
256 if (device
== SPIINVALID
) {
259 spiDevice
[device
].errorCount
++;
260 return spiDevice
[device
].errorCount
;
264 * Return true if the bus is currently in the middle of a transmission.
266 bool spiIsBusBusy(SPI_TypeDef
*instance
)
268 SPIDevice device
= spiDeviceByInstance(instance
);
269 if (spiDevice
[device
].hspi
.State
== HAL_SPI_STATE_BUSY
)
275 bool spiTransfer(SPI_TypeDef
*instance
, const uint8_t *txData
, uint8_t *rxData
, int len
)
277 SPIDevice device
= spiDeviceByInstance(instance
);
278 HAL_StatusTypeDef status
;
280 if (!rxData
) { // Tx only
281 status
= HAL_SPI_Transmit(&spiDevice
[device
].hspi
, txData
, len
, SPI_DEFAULT_TIMEOUT
);
282 } else if (!txData
) { // Rx only
283 status
= HAL_SPI_Receive(&spiDevice
[device
].hspi
, rxData
, len
, SPI_DEFAULT_TIMEOUT
);
284 } else { // Tx and Rx
285 status
= HAL_SPI_TransmitReceive(&spiDevice
[device
].hspi
, txData
, rxData
, len
, SPI_DEFAULT_TIMEOUT
);
287 if (status
!= HAL_OK
) {
288 spiTimeoutUserCallback(instance
);
293 static bool spiBusReadBuffer(const busDevice_t
*bus
, uint8_t *out
, int len
)
295 const HAL_StatusTypeDef status
= HAL_SPI_Receive(bus
->busdev_u
.spi
.handle
, out
, len
, SPI_DEFAULT_TIMEOUT
);
296 if (status
!= HAL_OK
) {
297 spiTimeoutUserCallback(bus
->busdev_u
.spi
.instance
);
302 uint8_t spiTransferByte(SPI_TypeDef
*instance
, uint8_t txByte
)
306 spiTransfer(instance
, &txByte
, &rxByte
, 1);
310 static uint8_t spiBusTransferByte(const busDevice_t
*bus
, uint8_t in
)
312 const HAL_StatusTypeDef status
= HAL_SPI_TransmitReceive(bus
->busdev_u
.spi
.handle
, &in
, &in
, 1, SPI_DEFAULT_TIMEOUT
);
313 if (status
!= HAL_OK
) {
314 spiTimeoutUserCallback(bus
->busdev_u
.spi
.instance
);
319 bool spiBusTransfer(const busDevice_t
*bus
, const uint8_t *txData
, uint8_t *rxData
, int len
)
321 IOLo(bus
->busdev_u
.spi
.csnPin
);
322 const HAL_StatusTypeDef status
= HAL_SPI_TransmitReceive(bus
->busdev_u
.spi
.handle
, txData
, rxData
, len
, SPI_DEFAULT_TIMEOUT
);
323 IOHi(bus
->busdev_u
.spi
.csnPin
);
324 if (status
!= HAL_OK
) {
325 spiTimeoutUserCallback(bus
->busdev_u
.spi
.instance
);
330 void spiSetDivisor(SPI_TypeDef
*instance
, uint16_t divisor
)
332 SPIDevice device
= spiDeviceByInstance(instance
);
333 if (HAL_SPI_DeInit(&spiDevice
[device
].hspi
) == HAL_OK
)
337 spiDevice
[device
].hspi
.Init
.BaudRatePrescaler
= (uint8_t []) {
339 SPI_BAUDRATEPRESCALER_2
, SPI_BAUDRATEPRESCALER_4
,
340 SPI_BAUDRATEPRESCALER_8
, SPI_BAUDRATEPRESCALER_16
,
341 SPI_BAUDRATEPRESCALER_32
, SPI_BAUDRATEPRESCALER_64
,
342 SPI_BAUDRATEPRESCALER_128
, SPI_BAUDRATEPRESCALER_256
343 }[ffs(divisor
| 0x100)];
345 if (HAL_SPI_Init(&spiDevice
[device
].hspi
) == HAL_OK
)
350 uint16_t spiGetErrorCounter(SPI_TypeDef
*instance
)
352 SPIDevice device
= spiDeviceByInstance(instance
);
353 if (device
== SPIINVALID
) {
356 return spiDevice
[device
].errorCount
;
359 void spiResetErrorCounter(SPI_TypeDef
*instance
)
361 SPIDevice device
= spiDeviceByInstance(instance
);
362 if (device
!= SPIINVALID
) {
363 spiDevice
[device
].errorCount
= 0;
367 bool spiBusWriteRegister(const busDevice_t
*bus
, uint8_t reg
, uint8_t data
)
369 IOLo(bus
->busdev_u
.spi
.csnPin
);
370 spiBusTransferByte(bus
, reg
);
371 spiBusTransferByte(bus
, data
);
372 IOHi(bus
->busdev_u
.spi
.csnPin
);
377 bool spiBusReadRegisterBuffer(const busDevice_t
*bus
, uint8_t reg
, uint8_t *data
, uint8_t length
)
379 IOLo(bus
->busdev_u
.spi
.csnPin
);
380 spiBusTransferByte(bus
, reg
| 0x80); // read transaction
381 spiBusReadBuffer(bus
, data
, length
);
382 IOHi(bus
->busdev_u
.spi
.csnPin
);
387 uint8_t spiBusReadRegister(const busDevice_t
*bus
, uint8_t reg
)
390 IOLo(bus
->busdev_u
.spi
.csnPin
);
391 spiBusTransferByte(bus
, reg
| 0x80); // read transaction
392 spiBusReadBuffer(bus
, &data
, 1);
393 IOHi(bus
->busdev_u
.spi
.csnPin
);
398 void spiBusSetInstance(busDevice_t
*bus
, SPI_TypeDef
*instance
)
400 bus
->busdev_u
.spi
.instance
= instance
;
401 bus
->busdev_u
.spi
.handle
= spiHandleByInstance(instance
);
404 void dmaSPIIRQHandler(dmaChannelDescriptor_t
* descriptor
)
406 SPIDevice device
= descriptor
->userParam
;
407 if (device
!= SPIINVALID
) {
408 HAL_DMA_IRQHandler(&spiDevice
[device
].hdma
);
413 DMA_HandleTypeDef
* spiSetDMATransmit(DMA_Stream_TypeDef
*Stream
, uint32_t Channel
, SPI_TypeDef
*Instance
, const uint8_t *pData
, uint16_t Size
)
415 SPIDevice device
= spiDeviceByInstance(Instance
);
417 spiDevice
[device
].hdma
.Instance
= Stream
;
418 spiDevice
[device
].hdma
.Init
.Channel
= Channel
;
419 spiDevice
[device
].hdma
.Init
.Direction
= DMA_MEMORY_TO_PERIPH
;
420 spiDevice
[device
].hdma
.Init
.PeriphInc
= DMA_PINC_DISABLE
;
421 spiDevice
[device
].hdma
.Init
.MemInc
= DMA_MINC_ENABLE
;
422 spiDevice
[device
].hdma
.Init
.PeriphDataAlignment
= DMA_PDATAALIGN_BYTE
;
423 spiDevice
[device
].hdma
.Init
.MemDataAlignment
= DMA_MDATAALIGN_BYTE
;
424 spiDevice
[device
].hdma
.Init
.Mode
= DMA_NORMAL
;
425 spiDevice
[device
].hdma
.Init
.FIFOMode
= DMA_FIFOMODE_DISABLE
;
426 spiDevice
[device
].hdma
.Init
.FIFOThreshold
= DMA_FIFO_THRESHOLD_1QUARTERFULL
;
427 spiDevice
[device
].hdma
.Init
.PeriphBurst
= DMA_PBURST_SINGLE
;
428 spiDevice
[device
].hdma
.Init
.MemBurst
= DMA_MBURST_SINGLE
;
429 spiDevice
[device
].hdma
.Init
.Priority
= DMA_PRIORITY_LOW
;
431 HAL_DMA_DeInit(&spiDevice
[device
].hdma
);
432 HAL_DMA_Init(&spiDevice
[device
].hdma
);
434 __HAL_DMA_ENABLE(&spiDevice
[device
].hdma
);
435 __HAL_SPI_ENABLE(&spiDevice
[device
].hspi
);
437 /* Associate the initialized DMA handle to the spi handle */
438 __HAL_LINKDMA(&spiDevice
[device
].hspi
, hdmatx
, spiDevice
[device
].hdma
);
441 dmaSetHandler(spiDevice
[device
].dmaIrqHandler
, dmaSPIIRQHandler
, NVIC_BUILD_PRIORITY(3, 0), (uint32_t)device
);
443 //HAL_CLEANCACHE(pData,Size);
445 HAL_SPI_Transmit_DMA(&spiDevice
[device
].hspi
, CONST_CAST(uint8_t*, pData
), Size
);
447 return &spiDevice
[device
].hdma
;