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_TypeDef
*spiInstanceByDevice(SPIDevice device
)
101 if (device
>= SPIDEV_COUNT
) {
105 return spiDevice
[device
].dev
;
108 void spiInitDevice(SPIDevice device
)
110 spiDevice_t
*spi
= &(spiDevice
[device
]);
112 #ifdef SDCARD_SPI_INSTANCE
113 if (spi
->dev
== SDCARD_SPI_INSTANCE
) {
114 spi
->leadingEdge
= true;
117 #ifdef RX_SPI_INSTANCE
118 if (spi
->dev
== RX_SPI_INSTANCE
) {
119 spi
->leadingEdge
= true;
124 RCC_ClockCmd(spi
->rcc
, ENABLE
);
125 RCC_ResetCmd(spi
->rcc
, ENABLE
);
127 IOInit(IOGetByTag(spi
->sck
), OWNER_SPI_SCK
, RESOURCE_INDEX(device
));
128 IOInit(IOGetByTag(spi
->miso
), OWNER_SPI_MISO
, RESOURCE_INDEX(device
));
129 IOInit(IOGetByTag(spi
->mosi
), OWNER_SPI_MOSI
, RESOURCE_INDEX(device
));
131 if (spi
->leadingEdge
== true)
132 IOConfigGPIOAF(IOGetByTag(spi
->sck
), SPI_IO_AF_SCK_CFG_LOW
, spi
->sckAF
);
134 IOConfigGPIOAF(IOGetByTag(spi
->sck
), SPI_IO_AF_SCK_CFG_HIGH
, spi
->sckAF
);
135 IOConfigGPIOAF(IOGetByTag(spi
->miso
), SPI_IO_AF_MISO_CFG
, spi
->misoAF
);
136 IOConfigGPIOAF(IOGetByTag(spi
->mosi
), SPI_IO_AF_CFG
, spi
->mosiAF
);
138 LL_SPI_Disable(spi
->dev
);
139 LL_SPI_DeInit(spi
->dev
);
141 LL_SPI_InitTypeDef init
=
143 .TransferDirection
= SPI_DIRECTION_2LINES
,
144 .Mode
= SPI_MODE_MASTER
,
145 .DataWidth
= SPI_DATASIZE_8BIT
,
146 .ClockPolarity
= spi
->leadingEdge
? SPI_POLARITY_LOW
: SPI_POLARITY_HIGH
,
147 .ClockPhase
= spi
->leadingEdge
? SPI_PHASE_1EDGE
: SPI_PHASE_2EDGE
,
149 .BaudRate
= SPI_BAUDRATEPRESCALER_8
,
150 .BitOrder
= SPI_FIRSTBIT_MSB
,
152 .CRCCalculation
= SPI_CRCCALCULATION_DISABLE
,
154 LL_SPI_SetRxFIFOThreshold(spi
->dev
, SPI_RXFIFO_THRESHOLD_QF
);
156 LL_SPI_Init(spi
->dev
, &init
);
157 LL_SPI_Enable(spi
->dev
);
160 bool spiInit(SPIDevice device
)
166 #if defined(USE_SPI_DEVICE_1)
167 spiInitDevice(device
);
173 #if defined(USE_SPI_DEVICE_2)
174 spiInitDevice(device
);
180 #if defined(USE_SPI_DEVICE_3)
181 spiInitDevice(device
);
187 #if defined(USE_SPI_DEVICE_4)
188 spiInitDevice(device
);
197 uint32_t spiTimeoutUserCallback(SPI_TypeDef
*instance
)
199 SPIDevice device
= spiDeviceByInstance(instance
);
200 if (device
== SPIINVALID
) {
203 spiDevice
[device
].errorCount
++;
204 return spiDevice
[device
].errorCount
;
207 uint8_t spiTransferByte(SPI_TypeDef
*instance
, uint8_t txByte
)
209 uint16_t spiTimeout
= 1000;
211 while (!LL_SPI_IsActiveFlag_TXE(instance
))
212 if ((spiTimeout
--) == 0)
213 return spiTimeoutUserCallback(instance
);
215 LL_SPI_TransmitData8(instance
, txByte
);
218 while (!LL_SPI_IsActiveFlag_RXNE(instance
))
219 if ((spiTimeout
--) == 0)
220 return spiTimeoutUserCallback(instance
);
222 return (uint8_t)LL_SPI_ReceiveData8(instance
);
226 * Return true if the bus is currently in the middle of a transmission.
228 bool spiIsBusBusy(SPI_TypeDef
*instance
)
230 return LL_SPI_GetTxFIFOLevel(instance
) != LL_SPI_TX_FIFO_EMPTY
231 || LL_SPI_IsActiveFlag_BSY(instance
);
234 bool spiTransfer(SPI_TypeDef
*instance
, const uint8_t *txData
, uint8_t *rxData
, int len
)
236 uint16_t spiTimeout
= 1000;
241 b
= txData
? *(txData
++) : 0xFF;
242 while (!LL_SPI_IsActiveFlag_TXE(instance
)) {
243 if ((spiTimeout
--) == 0)
244 return spiTimeoutUserCallback(instance
);
246 LL_SPI_TransmitData8(instance
, b
);
249 while (!LL_SPI_IsActiveFlag_RXNE(instance
)) {
250 if ((spiTimeout
--) == 0)
251 return spiTimeoutUserCallback(instance
);
253 b
= LL_SPI_ReceiveData8(instance
);
262 bool spiBusTransfer(const busDevice_t
*bus
, const uint8_t *txData
, uint8_t *rxData
, int length
)
264 IOLo(bus
->busdev_u
.spi
.csnPin
);
265 spiTransfer(bus
->busdev_u
.spi
.instance
, txData
, rxData
, length
);
266 IOHi(bus
->busdev_u
.spi
.csnPin
);
270 void spiSetDivisor(SPI_TypeDef
*instance
, uint16_t divisor
)
272 LL_SPI_Disable(instance
);
273 #define BR_CLEAR_MASK 0xFFC7
275 const uint16_t tempRegister
= (instance
->CR1
& BR_CLEAR_MASK
);
276 instance
->CR1
= (tempRegister
| ((ffs(divisor
| 0x100) - 2) << 3));
278 //LL_SPI_SetBaudRatePrescaler(instance, baudRatePrescaler);
279 LL_SPI_Enable(instance
);
282 uint16_t spiGetErrorCounter(SPI_TypeDef
*instance
)
284 SPIDevice device
= spiDeviceByInstance(instance
);
285 if (device
== SPIINVALID
) {
288 return spiDevice
[device
].errorCount
;
291 void spiResetErrorCounter(SPI_TypeDef
*instance
)
293 SPIDevice device
= spiDeviceByInstance(instance
);
294 if (device
!= SPIINVALID
) {
295 spiDevice
[device
].errorCount
= 0;
299 bool spiBusWriteRegister(const busDevice_t
*bus
, uint8_t reg
, uint8_t data
)
301 IOLo(bus
->busdev_u
.spi
.csnPin
);
302 spiTransferByte(bus
->busdev_u
.spi
.instance
, reg
);
303 spiTransferByte(bus
->busdev_u
.spi
.instance
, data
);
304 IOHi(bus
->busdev_u
.spi
.csnPin
);
309 bool spiBusReadRegisterBuffer(const busDevice_t
*bus
, uint8_t reg
, uint8_t *data
, uint8_t length
)
311 IOLo(bus
->busdev_u
.spi
.csnPin
);
312 spiTransferByte(bus
->busdev_u
.spi
.instance
, reg
| 0x80); // read transaction
313 spiTransfer(bus
->busdev_u
.spi
.instance
, NULL
, data
, length
);
314 IOHi(bus
->busdev_u
.spi
.csnPin
);
319 uint8_t spiBusReadRegister(const busDevice_t
*bus
, uint8_t reg
)
322 IOLo(bus
->busdev_u
.spi
.csnPin
);
323 spiTransferByte(bus
->busdev_u
.spi
.instance
, reg
| 0x80); // read transaction
324 spiTransfer(bus
->busdev_u
.spi
.instance
, NULL
, &data
, 1);
325 IOHi(bus
->busdev_u
.spi
.csnPin
);
330 void spiBusSetInstance(busDevice_t
*bus
, SPI_TypeDef
*instance
)
332 bus
->busdev_u
.spi
.instance
= instance
;