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/>.
25 #include "drivers/bus_spi.h"
26 #include "drivers/exti.h"
27 #include "drivers/io.h"
28 #include "drivers/io_impl.h"
29 #include "drivers/rcc.h"
32 #define SPI1_NSS_PIN PA4
33 #define SPI1_SCK_PIN PA5
34 #define SPI1_MISO_PIN PA6
35 #define SPI1_MOSI_PIN PA7
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 PC10
48 #define SPI3_MISO_PIN PC11
49 #define SPI3_MOSI_PIN PC12
53 #define SPI1_NSS_PIN NONE
56 #define SPI2_NSS_PIN NONE
59 #define SPI3_NSS_PIN NONE
63 #if defined(USE_SPI_DEVICE_1)
64 static const uint32_t spiDivisorMapFast
[] = {
65 SPI_MCLK_DIV_256
, // SPI_CLOCK_INITIALIZATON 328.125 KBits/s
66 SPI_MCLK_DIV_128
, // SPI_CLOCK_SLOW 656.25 KBits/s
67 SPI_MCLK_DIV_16
, // SPI_CLOCK_STANDARD 10.5 MBits/s
68 SPI_MCLK_DIV_8
, // SPI_CLOCK_FAST 21.0 MBits/s
69 SPI_MCLK_DIV_4
// SPI_CLOCK_ULTRAFAST 42.0 MBits/s
73 #if defined(USE_SPI_DEVICE_2) || defined(USE_SPI_DEVICE_3)
74 static const uint32_t spiDivisorMapSlow
[] = {
75 SPI_MCLK_DIV_256
, // SPI_CLOCK_INITIALIZATON 164.062 KBits/s
76 SPI_MCLK_DIV_128
, // SPI_CLOCK_SLOW 656.25 KBits/s
77 SPI_MCLK_DIV_16
, // SPI_CLOCK_STANDARD 10.5 MBits/s
78 SPI_MCLK_DIV_8
, // SPI_CLOCK_FAST 21.0 MBits/s
79 SPI_MCLK_DIV_8
// SPI_CLOCK_ULTRAFAST 21.0 MBits/s
83 static spiDevice_t spiHardwareMap
[] = {
84 #ifdef USE_SPI_DEVICE_1
85 { .dev
= SPI1
, .nss
= IO_TAG(SPI1_NSS_PIN
), .sck
= IO_TAG(SPI1_SCK_PIN
), .miso
= IO_TAG(SPI1_MISO_PIN
), .mosi
= IO_TAG(SPI1_MOSI_PIN
), .rcc
= RCC_APB2(SPI1
), .af
= GPIO_MUX_5
, .divisorMap
= spiDivisorMapFast
},
87 { .dev
= NULL
}, // No SPI1
89 #ifdef USE_SPI_DEVICE_2
90 { .dev
= SPI2
, .nss
= IO_TAG(SPI2_NSS_PIN
), .sck
= IO_TAG(SPI2_SCK_PIN
), .miso
= IO_TAG(SPI2_MISO_PIN
), .mosi
= IO_TAG(SPI2_MOSI_PIN
), .rcc
= RCC_APB1(SPI2
), .af
= GPIO_MUX_6
, .divisorMap
= spiDivisorMapSlow
},
92 { .dev
= NULL
}, // No SPI2
94 #ifdef USE_SPI_DEVICE_3
95 { .dev
= SPI3
, .nss
= IO_TAG(SPI3_NSS_PIN
), .sck
= IO_TAG(SPI3_SCK_PIN
), .miso
= IO_TAG(SPI3_MISO_PIN
), .mosi
= IO_TAG(SPI3_MOSI_PIN
), .rcc
= RCC_APB1(SPI3
), .af
= GPIO_MUX_6
, .divisorMap
= spiDivisorMapSlow
},
97 { .dev
= NULL
}, // No SPI3
99 { .dev
= NULL
}, // No SPI4
105 SPIDevice
spiDeviceByInstance(spi_type
*instance
)
107 if (instance
== SPI1
)
110 if (instance
== SPI2
)
113 if (instance
== SPI3
)
119 bool spiInitDevice(SPIDevice device
, bool leadingEdge
)
121 spiDevice_t
*spi
= &(spiHardwareMap
[device
]);
131 RCC_ClockCmd(spi
->rcc
, ENABLE
);
132 RCC_ResetCmd(spi
->rcc
, ENABLE
);
134 IOInit(IOGetByTag(spi
->sck
), OWNER_SPI
, RESOURCE_SPI_SCK
, device
+ 1);
135 IOInit(IOGetByTag(spi
->miso
), OWNER_SPI
, RESOURCE_SPI_MISO
, device
+ 1);
136 IOInit(IOGetByTag(spi
->mosi
), OWNER_SPI
, RESOURCE_SPI_MOSI
, device
+ 1);
138 IOConfigGPIOAF(IOGetByTag(spi
->sck
), SPI_IO_AF_SCK_CFG
, spi
->af
);
139 IOConfigGPIOAF(IOGetByTag(spi
->miso
), SPI_IO_AF_MISO_CFG
, spi
->af
);
140 IOConfigGPIOAF(IOGetByTag(spi
->mosi
), SPI_IO_AF_CFG
, spi
->af
);
143 IOConfigGPIOAF(IOGetByTag(spi
->nss
), SPI_IO_CS_CFG
, spi
->af
);
146 spi_i2s_reset(spi
->dev
);
147 spi_init_type spi_init_struct
;
148 spi_default_para_init (&spi_init_struct
);
149 spi_init_struct
.master_slave_mode
= SPI_MODE_MASTER
;
150 spi_init_struct
.transmission_mode
= SPI_TRANSMIT_FULL_DUPLEX
;
151 spi_init_struct
.first_bit_transmission
= SPI_FIRST_BIT_MSB
;
152 spi_init_struct
.mclk_freq_division
= SPI_MCLK_DIV_8
;
153 spi_init_struct
.frame_bit_num
= SPI_FRAME_8BIT
;
154 spi_init_struct
.cs_mode_selection
= SPI_CS_SOFTWARE_MODE
;
156 spi_init_struct
.clock_polarity
= SPI_CLOCK_POLARITY_HIGH
;
157 spi_init_struct
.clock_phase
= SPI_CLOCK_PHASE_2EDGE
;
161 spi_init_struct
.clock_polarity
= SPI_CLOCK_POLARITY_LOW
;
162 spi_init_struct
.clock_phase
= SPI_CLOCK_PHASE_1EDGE
;
165 spi_init_struct
.clock_polarity
= SPI_CLOCK_POLARITY_HIGH
;
166 spi_init_struct
.clock_phase
= SPI_CLOCK_PHASE_2EDGE
;
169 spi_init(spi
->dev
, &spi_init_struct
);
170 spi_crc_polynomial_set (spi
->dev
, 0x07);
171 spi_crc_enable (spi
->dev
, TRUE
); // enable crc
172 spi_enable (spi
->dev
, TRUE
);
175 // Drive NSS high to disable connected SPI device.
176 IOHi(IOGetByTag(spi
->nss
));
178 spi
->initDone
= true;
182 uint32_t spiTimeoutUserCallback(spi_type
*instance
)
184 SPIDevice device
= spiDeviceByInstance(instance
);
185 if (device
== SPIINVALID
) {
188 spiHardwareMap
[device
].errorCount
++;
189 return spiHardwareMap
[device
].errorCount
;
192 // return uint8_t value or -1 when failure
193 uint8_t spiTransferByte(spi_type
*instance
, uint8_t data
)
195 uint16_t spiTimeout
= 1000;
197 //while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_TXE) == RESET)
198 while (spi_i2s_flag_get(instance
, SPI_I2S_TDBE_FLAG
) == RESET
)
199 if ((spiTimeout
--) == 0)
200 return spiTimeoutUserCallback(instance
);
202 //SPI_I2S_SendData(instance, data);
203 spi_i2s_data_transmit(instance
, data
);
206 //while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_RXNE) == RESET)
207 while (spi_i2s_flag_get(instance
, SPI_I2S_RDBF_FLAG
) == RESET
)
208 if ((spiTimeout
--) == 0)
209 return spiTimeoutUserCallback(instance
);
211 return ((uint8_t) spi_i2s_data_receive(instance
));
215 * Return true if the bus is currently in the middle of a transmission.
217 bool spiIsBusBusy(spi_type
*instance
)
219 //return SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_TXE) == RESET || SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_BSY) == SET;
220 return spi_i2s_flag_get(instance
, SPI_I2S_TDBE_FLAG
) == RESET
|| spi_i2s_flag_get(instance
, SPI_I2S_BF_FLAG
) == SET
;
223 bool spiTransfer(spi_type
*instance
, uint8_t *out
, const uint8_t *in
, int len
)
225 uint16_t spiTimeout
= 1000;
229 uint8_t b
= in
? *(in
++) : 0xFF;
230 while (spi_i2s_flag_get(instance
, SPI_I2S_TDBE_FLAG
) == RESET
) {
231 if ((spiTimeout
--) == 0)
232 return spiTimeoutUserCallback(instance
);
234 spi_i2s_data_transmit(instance
, b
);
236 while (spi_i2s_flag_get(instance
, SPI_I2S_RDBF_FLAG
) == RESET
) {
237 if ((spiTimeout
--) == 0)
238 return spiTimeoutUserCallback(instance
);
240 b
= spi_i2s_data_receive(instance
);
248 void spiSetSpeed(spi_type
*instance
, SPIClockSpeed_e speed
)
250 #define BR_CLEAR_MASK 0xFFC7
251 SPIDevice device
= spiDeviceByInstance(instance
);
252 if (device
== SPIINVALID
) {
256 spi_enable (instance
, FALSE
);
258 // #define BR_BITS ((BIT(5) | BIT(4) | BIT(3)))
259 // const uint16_t tempRegister = (instance->ctrl1 & ~BR_BITS);
260 // instance->ctrl1 = tempRegister | (spiHardwareMap[device].divisorMap[speed] << 3);
263 uint16_t tempRegister
= instance
->ctrl1
;
264 tempRegister
&= BR_CLEAR_MASK
;
265 tempRegister
|= (spiHardwareMap
[device
].divisorMap
[speed
] << 3);
266 instance
->ctrl1
= tempRegister
;
268 spi_enable (instance
, TRUE
);
271 uint16_t spiGetErrorCounter(spi_type
*instance
)
273 SPIDevice device
= spiDeviceByInstance(instance
);
274 if (device
== SPIINVALID
) {
277 return spiHardwareMap
[device
].errorCount
;
280 void spiResetErrorCounter(spi_type
*instance
)
282 SPIDevice device
= spiDeviceByInstance(instance
);
283 if (device
!= SPIINVALID
) {
284 spiHardwareMap
[device
].errorCount
= 0;
288 spi_type
* spiInstanceByDevice( SPIDevice device
)
290 return spiHardwareMap
[device
].dev
;