Merge pull request #9453 from etracer65/use_blackbox_compiler_warning
[betaflight.git] / src / main / drivers / bus_spi.c
blob1ddbb288a8f982363ca21f8b25ac682a30f1f7df
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <string.h>
25 #include "platform.h"
27 #ifdef USE_SPI
29 #include "drivers/bus.h"
30 #include "drivers/bus_spi.h"
31 #include "drivers/bus_spi_impl.h"
32 #include "drivers/exti.h"
33 #include "drivers/io.h"
34 #include "drivers/rcc.h"
36 spiDevice_t spiDevice[SPIDEV_COUNT];
38 SPIDevice spiDeviceByInstance(SPI_TypeDef *instance)
40 #ifdef USE_SPI_DEVICE_1
41 if (instance == SPI1)
42 return SPIDEV_1;
43 #endif
45 #ifdef USE_SPI_DEVICE_2
46 if (instance == SPI2)
47 return SPIDEV_2;
48 #endif
50 #ifdef USE_SPI_DEVICE_3
51 if (instance == SPI3)
52 return SPIDEV_3;
53 #endif
55 #ifdef USE_SPI_DEVICE_4
56 if (instance == SPI4)
57 return SPIDEV_4;
58 #endif
60 return SPIINVALID;
63 SPI_TypeDef *spiInstanceByDevice(SPIDevice device)
65 if (device == SPIINVALID || device >= SPIDEV_COUNT) {
66 return NULL;
69 return spiDevice[device].dev;
72 bool spiInit(SPIDevice device, bool leadingEdge)
74 switch (device) {
75 case SPIINVALID:
76 return false;
78 case SPIDEV_1:
79 #ifdef USE_SPI_DEVICE_1
80 spiInitDevice(device, leadingEdge);
81 return true;
82 #else
83 break;
84 #endif
86 case SPIDEV_2:
87 #ifdef USE_SPI_DEVICE_2
88 spiInitDevice(device, leadingEdge);
89 return true;
90 #else
91 break;
92 #endif
94 case SPIDEV_3:
95 #if defined(USE_SPI_DEVICE_3) && !defined(STM32F1)
96 spiInitDevice(device, leadingEdge);
97 return true;
98 #else
99 break;
100 #endif
102 case SPIDEV_4:
103 #if defined(USE_SPI_DEVICE_4)
104 spiInitDevice(device, leadingEdge);
105 return true;
106 #else
107 break;
108 #endif
110 case SPIDEV_5:
111 #if defined(USE_SPI_DEVICE_5)
112 spiInitDevice(device, leadingEdge);
113 return true;
114 #else
115 break;
116 #endif
118 case SPIDEV_6:
119 #if defined(USE_SPI_DEVICE_6)
120 spiInitDevice(device, leadingEdge);
121 return true;
122 #else
123 break;
124 #endif
126 return false;
129 uint32_t spiTimeoutUserCallback(SPI_TypeDef *instance)
131 SPIDevice device = spiDeviceByInstance(instance);
132 if (device == SPIINVALID) {
133 return -1;
135 spiDevice[device].errorCount++;
136 return spiDevice[device].errorCount;
139 bool spiBusTransfer(const busDevice_t *bus, const uint8_t *txData, uint8_t *rxData, int length)
141 IOLo(bus->busdev_u.spi.csnPin);
142 spiTransfer(bus->busdev_u.spi.instance, txData, rxData, length);
143 IOHi(bus->busdev_u.spi.csnPin);
144 return true;
147 uint16_t spiGetErrorCounter(SPI_TypeDef *instance)
149 SPIDevice device = spiDeviceByInstance(instance);
150 if (device == SPIINVALID) {
151 return 0;
153 return spiDevice[device].errorCount;
156 void spiResetErrorCounter(SPI_TypeDef *instance)
158 SPIDevice device = spiDeviceByInstance(instance);
159 if (device != SPIINVALID) {
160 spiDevice[device].errorCount = 0;
164 bool spiBusIsBusBusy(const busDevice_t *bus)
166 return spiIsBusBusy(bus->busdev_u.spi.instance);
169 uint8_t spiBusTransferByte(const busDevice_t *bus, uint8_t data)
171 return spiTransferByte(bus->busdev_u.spi.instance, data);
174 void spiBusWriteByte(const busDevice_t *bus, uint8_t data)
176 IOLo(bus->busdev_u.spi.csnPin);
177 spiBusTransferByte(bus, data);
178 IOHi(bus->busdev_u.spi.csnPin);
181 bool spiBusRawTransfer(const busDevice_t *bus, const uint8_t *txData, uint8_t *rxData, int len)
183 return spiTransfer(bus->busdev_u.spi.instance, txData, rxData, len);
186 bool spiBusWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t data)
188 IOLo(bus->busdev_u.spi.csnPin);
189 spiTransferByte(bus->busdev_u.spi.instance, reg);
190 spiTransferByte(bus->busdev_u.spi.instance, data);
191 IOHi(bus->busdev_u.spi.csnPin);
193 return true;
196 bool spiBusRawReadRegisterBuffer(const busDevice_t *bus, uint8_t reg, uint8_t *data, uint8_t length)
198 IOLo(bus->busdev_u.spi.csnPin);
199 spiTransferByte(bus->busdev_u.spi.instance, reg);
200 spiTransfer(bus->busdev_u.spi.instance, NULL, data, length);
201 IOHi(bus->busdev_u.spi.csnPin);
203 return true;
206 bool spiBusReadRegisterBuffer(const busDevice_t *bus, uint8_t reg, uint8_t *data, uint8_t length)
208 return spiBusRawReadRegisterBuffer(bus, reg | 0x80, data, length);
211 void spiBusWriteRegisterBuffer(const busDevice_t *bus, uint8_t reg, const uint8_t *data, uint8_t length)
213 IOLo(bus->busdev_u.spi.csnPin);
214 spiTransferByte(bus->busdev_u.spi.instance, reg);
215 spiTransfer(bus->busdev_u.spi.instance, data, NULL, length);
216 IOHi(bus->busdev_u.spi.csnPin);
219 uint8_t spiBusRawReadRegister(const busDevice_t *bus, uint8_t reg)
221 uint8_t data;
222 IOLo(bus->busdev_u.spi.csnPin);
223 spiTransferByte(bus->busdev_u.spi.instance, reg);
224 spiTransfer(bus->busdev_u.spi.instance, NULL, &data, 1);
225 IOHi(bus->busdev_u.spi.csnPin);
227 return data;
230 uint8_t spiBusReadRegister(const busDevice_t *bus, uint8_t reg)
232 return spiBusRawReadRegister(bus, reg | 0x80);
235 void spiBusSetInstance(busDevice_t *bus, SPI_TypeDef *instance)
237 bus->bustype = BUSTYPE_SPI;
238 bus->busdev_u.spi.instance = instance;
241 void spiBusSetDivisor(busDevice_t *bus, uint16_t divisor)
243 spiSetDivisor(bus->busdev_u.spi.instance, divisor);
244 // bus->busdev_u.spi.modeCache = bus->busdev_u.spi.instance->CR1;
247 #ifdef USE_SPI_TRANSACTION
248 // Separate set of spiBusTransactionXXX to keep fast path for acc/gyros.
250 void spiBusTransactionBegin(const busDevice_t *bus)
252 spiBusTransactionSetup(bus);
253 IOLo(bus->busdev_u.spi.csnPin);
256 void spiBusTransactionEnd(const busDevice_t *bus)
258 IOHi(bus->busdev_u.spi.csnPin);
261 bool spiBusTransactionTransfer(const busDevice_t *bus, const uint8_t *txData, uint8_t *rxData, int length)
263 spiBusTransactionSetup(bus);
264 return spiBusTransfer(bus, txData, rxData, length);
267 bool spiBusTransactionWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t data)
269 spiBusTransactionSetup(bus);
270 return spiBusWriteRegister(bus, reg, data);
273 uint8_t spiBusTransactionReadRegister(const busDevice_t *bus, uint8_t reg)
275 spiBusTransactionSetup(bus);
276 return spiBusReadRegister(bus, reg);
279 bool spiBusTransactionReadRegisterBuffer(const busDevice_t *bus, uint8_t reg, uint8_t *data, uint8_t length)
281 spiBusTransactionSetup(bus);
282 return spiBusReadRegisterBuffer(bus, reg, data, length);
284 #endif // USE_SPI_TRANSACTION
285 #endif