Low level driver for SPI for F7
[betaflight.git] / src / main / drivers / bus_spi_hal.c
blob805c3bf2f81d2711b658fd93b4c8d1963659b848
1 /*
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/>.
18 #include <stdbool.h>
19 #include <stdint.h>
20 #include <string.h>
22 #include <platform.h>
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];
38 #ifndef SPI2_SCK_PIN
39 #define SPI2_NSS_PIN PB12
40 #define SPI2_SCK_PIN PB13
41 #define SPI2_MISO_PIN PB14
42 #define SPI2_MOSI_PIN PB15
43 #endif
45 #ifndef SPI3_SCK_PIN
46 #define SPI3_NSS_PIN PA15
47 #define SPI3_SCK_PIN PB3
48 #define SPI3_MISO_PIN PB4
49 #define SPI3_MOSI_PIN PB5
50 #endif
52 #ifndef SPI4_SCK_PIN
53 #define SPI4_NSS_PIN PA15
54 #define SPI4_SCK_PIN PB3
55 #define SPI4_MISO_PIN PB4
56 #define SPI4_MOSI_PIN PB5
57 #endif
59 #ifndef SPI1_NSS_PIN
60 #define SPI1_NSS_PIN NONE
61 #endif
62 #ifndef SPI2_NSS_PIN
63 #define SPI2_NSS_PIN NONE
64 #endif
65 #ifndef SPI3_NSS_PIN
66 #define SPI3_NSS_PIN NONE
67 #endif
68 #ifndef SPI4_NSS_PIN
69 #define SPI4_NSS_PIN NONE
70 #endif
72 #define SPI_DEFAULT_TIMEOUT 10
74 SPIDevice spiDeviceByInstance(SPI_TypeDef *instance)
76 #ifdef USE_SPI_DEVICE_1
77 if (instance == SPI1)
78 return SPIDEV_1;
79 #endif
81 #ifdef USE_SPI_DEVICE_2
82 if (instance == SPI2)
83 return SPIDEV_2;
84 #endif
86 #ifdef USE_SPI_DEVICE_3
87 if (instance == SPI3)
88 return SPIDEV_3;
89 #endif
91 #ifdef USE_SPI_DEVICE_4
92 if (instance == SPI4)
93 return SPIDEV_4;
94 #endif
96 return SPIINVALID;
99 SPI_HandleTypeDef* spiHandleByInstance(SPI_TypeDef *instance)
101 return &spiDevice[spiDeviceByInstance(instance)].hspi;
104 SPI_TypeDef *spiInstanceByDevice(SPIDevice device)
106 if (device >= SPIDEV_COUNT) {
107 return NULL;
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;
147 #endif
148 #ifdef RX_SPI_INSTANCE
149 if (spi->dev == RX_SPI_INSTANCE) {
150 spi->leadingEdge = true;
152 #endif
153 #ifdef MPU6500_SPI_INSTANCE
154 if (spi->dev == MPU6500_SPI_INSTANCE) {
155 spi->leadingEdge = true;
157 #endif
159 // Enable SPI clock
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));
167 #if defined(STM32F7)
168 if (spi->leadingEdge == true)
169 IOConfigGPIOAF(IOGetByTag(spi->sck), SPI_IO_AF_SCK_CFG_LOW, spi->sckAF);
170 else
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);
174 #endif
175 #if defined(STM32F3) || defined(STM32F4)
176 if (spi->leadingEdge == true)
177 IOConfigGPIOAF(IOGetByTag(spi->sck), SPI_IO_AF_SCK_CFG_LOW, spi->af);
178 else
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);
182 #endif
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);
187 #endif
188 spiDevice[device].hspi.Instance = spi->dev;
189 // Init SPI hardware
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;
206 else {
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)
218 switch (device) {
219 case SPIINVALID:
220 return false;
221 case SPIDEV_1:
222 #if defined(USE_SPI_DEVICE_1)
223 spiInitDevice(device);
224 return true;
225 #else
226 break;
227 #endif
228 case SPIDEV_2:
229 #if defined(USE_SPI_DEVICE_2)
230 spiInitDevice(device);
231 return true;
232 #else
233 break;
234 #endif
235 case SPIDEV_3:
236 #if defined(USE_SPI_DEVICE_3)
237 spiInitDevice(device);
238 return true;
239 #else
240 break;
241 #endif
242 case SPIDEV_4:
243 #if defined(USE_SPI_DEVICE_4)
244 spiInitDevice(device);
245 return true;
246 #else
247 break;
248 #endif
250 return false;
253 uint32_t spiTimeoutUserCallback(SPI_TypeDef *instance)
255 SPIDevice device = spiDeviceByInstance(instance);
256 if (device == SPIINVALID) {
257 return -1;
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)
270 return true;
271 else
272 return false;
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);
290 return true;
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);
299 return true;
302 uint8_t spiTransferByte(SPI_TypeDef *instance, uint8_t txByte)
304 uint8_t rxByte;
306 spiTransfer(instance, &txByte, &rxByte, 1);
307 return rxByte;
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);
316 return in;
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);
327 return true;
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 []) {
338 0, 0,
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) {
354 return 0;
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);
374 return true;
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);
384 return true;
387 uint8_t spiBusReadRegister(const busDevice_t *bus, uint8_t reg)
389 uint8_t data;
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);
395 return data;
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);
440 // DMA TX Interrupt
441 dmaSetHandler(spiDevice[device].dmaIrqHandler, dmaSPIIRQHandler, NVIC_BUILD_PRIORITY(3, 0), (uint32_t)device);
443 //HAL_CLEANCACHE(pData,Size);
444 // And Transmit
445 HAL_SPI_Transmit_DMA(&spiDevice[device].hspi, CONST_CAST(uint8_t*, pData), Size);
447 return &spiDevice[device].hdma;
449 #endif