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)
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/>.
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
45 #ifdef USE_SPI_DEVICE_2
50 #ifdef USE_SPI_DEVICE_3
55 #ifdef USE_SPI_DEVICE_4
63 SPI_TypeDef
*spiInstanceByDevice(SPIDevice device
)
65 if (device
== SPIINVALID
|| device
>= SPIDEV_COUNT
) {
69 return spiDevice
[device
].dev
;
72 bool spiInit(SPIDevice device
, bool leadingEdge
)
79 #ifdef USE_SPI_DEVICE_1
80 spiInitDevice(device
, leadingEdge
);
87 #ifdef USE_SPI_DEVICE_2
88 spiInitDevice(device
, leadingEdge
);
95 #if defined(USE_SPI_DEVICE_3) && !defined(STM32F1)
96 spiInitDevice(device
, leadingEdge
);
103 #if defined(USE_SPI_DEVICE_4)
104 spiInitDevice(device
, leadingEdge
);
111 #if defined(USE_SPI_DEVICE_5)
112 spiInitDevice(device
, leadingEdge
);
119 #if defined(USE_SPI_DEVICE_6)
120 spiInitDevice(device
, leadingEdge
);
129 uint32_t spiTimeoutUserCallback(SPI_TypeDef
*instance
)
131 SPIDevice device
= spiDeviceByInstance(instance
);
132 if (device
== SPIINVALID
) {
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
);
147 uint16_t spiGetErrorCounter(SPI_TypeDef
*instance
)
149 SPIDevice device
= spiDeviceByInstance(instance
);
150 if (device
== SPIINVALID
) {
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
);
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
);
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
)
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
);
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