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/>.
23 #include <build/debug.h>
27 #include "drivers/io.h"
28 #include "drivers/bus.h"
29 #include "drivers/bus_spi.h"
30 #include "drivers/time.h"
32 void spiChipSelectSetupDelay(void)
34 // CS->CLK delay, MPU6000 - 8ns
38 void spiChipSelectHoldTime(void)
40 // CLK->CS delay, MPU6000 - 500ns
44 bool spiBusInitHost(const busDevice_t
* dev
)
46 const bool spiLeadingEdge
= (dev
->flags
& DEVFLAGS_SPI_MODE_0
);
47 return spiInitDevice(dev
->busdev
.spi
.spiBus
, spiLeadingEdge
);
50 void spiBusSelectDevice(const busDevice_t
* dev
)
52 IOLo(dev
->busdev
.spi
.csnPin
);
53 spiChipSelectSetupDelay();
56 void spiBusDeselectDevice(const busDevice_t
* dev
)
58 spiChipSelectHoldTime();
59 IOHi(dev
->busdev
.spi
.csnPin
);
62 void spiBusSetSpeed(const busDevice_t
* dev
, busSpeed_e speed
)
64 const SPIClockSpeed_e spiClock
[] = { SPI_CLOCK_INITIALIZATON
, SPI_CLOCK_SLOW
, SPI_CLOCK_STANDARD
, SPI_CLOCK_FAST
, SPI_CLOCK_ULTRAFAST
};
67 spi_type
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
69 SPI_TypeDef
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
72 #ifdef BUS_SPI_SPEED_MAX
73 if (speed
> BUS_SPI_SPEED_MAX
)
74 speed
= BUS_SPI_SPEED_MAX
;
77 spiSetSpeed(instance
, spiClock
[speed
]);
81 bool spiBusTransfer(const busDevice_t
* dev
, uint8_t * rxBuf
, const uint8_t * txBuf
, int length
)
84 spi_type
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
86 SPI_TypeDef
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
89 if (!(dev
->flags
& DEVFLAGS_USE_MANUAL_DEVICE_SELECT
)) {
90 spiBusSelectDevice(dev
);
93 spiTransfer(instance
, rxBuf
, txBuf
, length
);
95 if (!(dev
->flags
& DEVFLAGS_USE_MANUAL_DEVICE_SELECT
)) {
96 spiBusDeselectDevice(dev
);
102 bool spiBusTransferMultiple(const busDevice_t
* dev
, busTransferDescriptor_t
* dsc
, int count
)
104 #if defined(AT32F43x)
105 spi_type
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
107 SPI_TypeDef
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
110 if (!(dev
->flags
& DEVFLAGS_USE_MANUAL_DEVICE_SELECT
)) {
111 spiBusSelectDevice(dev
);
114 for (int n
= 0; n
< count
; n
++) {
115 spiTransfer(instance
, dsc
[n
].rxBuf
, dsc
[n
].txBuf
, dsc
[n
].length
);
118 if (!(dev
->flags
& DEVFLAGS_USE_MANUAL_DEVICE_SELECT
)) {
119 spiBusDeselectDevice(dev
);
125 bool spiBusWriteRegister(const busDevice_t
* dev
, uint8_t reg
, uint8_t data
)
127 #if defined(AT32F43x)
128 spi_type
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
130 SPI_TypeDef
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
133 if (!(dev
->flags
& DEVFLAGS_USE_MANUAL_DEVICE_SELECT
)) {
134 spiBusSelectDevice(dev
);
137 spiTransferByte(instance
, reg
);
138 spiTransferByte(instance
, data
);
140 if (!(dev
->flags
& DEVFLAGS_USE_MANUAL_DEVICE_SELECT
)) {
141 spiBusDeselectDevice(dev
);
147 bool spiBusWriteBuffer(const busDevice_t
* dev
, uint8_t reg
, const uint8_t * data
, uint8_t length
)
149 #if defined(AT32F43x)
150 spi_type
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
152 SPI_TypeDef
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
155 if (!(dev
->flags
& DEVFLAGS_USE_MANUAL_DEVICE_SELECT
)) {
156 spiBusSelectDevice(dev
);
159 spiTransferByte(instance
, reg
);
160 spiTransfer(instance
, NULL
, data
, length
);
162 if (!(dev
->flags
& DEVFLAGS_USE_MANUAL_DEVICE_SELECT
)) {
163 spiBusDeselectDevice(dev
);
169 bool spiBusReadBuffer(const busDevice_t
* dev
, uint8_t reg
, uint8_t * data
, uint8_t length
)
171 #if defined(AT32F43x)
172 spi_type
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
174 SPI_TypeDef
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
177 if (!(dev
->flags
& DEVFLAGS_USE_MANUAL_DEVICE_SELECT
)) {
178 spiBusSelectDevice(dev
);
181 spiTransferByte(instance
, reg
);
182 spiTransfer(instance
, data
, NULL
, length
);
184 if (!(dev
->flags
& DEVFLAGS_USE_MANUAL_DEVICE_SELECT
)) {
185 spiBusDeselectDevice(dev
);
191 bool spiBusReadRegister(const busDevice_t
* dev
, uint8_t reg
, uint8_t * data
)
193 #if defined(AT32F43x)
194 spi_type
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
196 SPI_TypeDef
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
199 if (!(dev
->flags
& DEVFLAGS_USE_MANUAL_DEVICE_SELECT
)) {
200 spiBusSelectDevice(dev
);
203 spiTransferByte(instance
, reg
);
204 spiTransfer(instance
, data
, NULL
, 1);
206 if (!(dev
->flags
& DEVFLAGS_USE_MANUAL_DEVICE_SELECT
)) {
207 spiBusDeselectDevice(dev
);
213 bool spiBusIsBusy(const busDevice_t
* dev
)
215 #if defined(AT32F43x)
216 spi_type
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
218 SPI_TypeDef
* instance
= spiInstanceByDevice(dev
->busdev
.spi
.spiBus
);
220 return spiIsBusBusy(instance
);