Blackbox device type 'file' (SITL) considered working when file handler is available
[inav.git] / src / main / drivers / bus_spi_at32f43x.c
blob6a30f0d0d03dc217691664f76a62a0dccd3d3ecd
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>
21 #include <platform.h>
23 #ifdef USE_SPI
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"
31 #ifndef SPI1_SCK_PIN
32 #define SPI1_NSS_PIN PA4
33 #define SPI1_SCK_PIN PA5
34 #define SPI1_MISO_PIN PA6
35 #define SPI1_MOSI_PIN PA7
36 #endif
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 PC10
48 #define SPI3_MISO_PIN PC11
49 #define SPI3_MOSI_PIN PC12
50 #endif
52 #ifndef SPI1_NSS_PIN
53 #define SPI1_NSS_PIN NONE
54 #endif
55 #ifndef SPI2_NSS_PIN
56 #define SPI2_NSS_PIN NONE
57 #endif
58 #ifndef SPI3_NSS_PIN
59 #define SPI3_NSS_PIN NONE
60 #endif
62 #if defined(AT32F43x)
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
71 #endif
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
81 #endif
83 //MAP spi pin config and af
84 static spiDevice_t spiHardwareMap[] = {
85 #ifdef USE_SPI_DEVICE_1
86 #if defined(SPI1_SCK_AF) || defined(SPI1_MISO_AF) || defined(SPI1_MOSI_AF)
87 #if !defined(SPI1_SCK_AF) || !defined(SPI1_MISO_AF) || !defined(SPI1_MOSI_AF)
88 #error SPI1: SCK, MISO and MOSI AFs should be defined together in target.h!
89 #endif
90 { .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), .sckAF = SPI1_SCK_AF, .misoAF = SPI1_MISO_AF, .mosiAF = SPI1_MOSI_AF, .divisorMap = spiDivisorMapFast },
91 #else
92 { .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), .sckAF = GPIO_MUX_5, .misoAF = GPIO_MUX_5, .mosiAF = GPIO_MUX_5, .divisorMap = spiDivisorMapFast },
93 #endif
94 #else
95 { .dev = NULL }, // No SPI1
96 #endif
98 #ifdef USE_SPI_DEVICE_2
99 #if defined(SPI2_SCK_AF) || defined(SPI2_MISO_AF) || defined(SPI2_MOSI_AF)
100 #if !defined(SPI2_SCK_AF) || !defined(SPI2_MISO_AF) || !defined(SPI2_MOSI_AF)
101 #error SPI2: SCK, MISO and MOSI AFs should be defined together in target.h!
102 #endif
103 { .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), .sckAF = SPI2_SCK_AF, .misoAF = SPI2_MISO_AF, .mosiAF = SPI2_MOSI_AF, .divisorMap = spiDivisorMapSlow },
104 #else
105 { .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), .sckAF = GPIO_MUX_5, .misoAF = GPIO_MUX_5, .mosiAF = GPIO_MUX_5, .divisorMap = spiDivisorMapSlow },
106 #endif
107 #else
108 { .dev = NULL }, // No SPI2
109 #endif
111 #ifdef USE_SPI_DEVICE_3
112 #if defined(SPI3_SCK_AF) || defined(SPI3_MISO_AF) || defined(SPI3_MOSI_AF)
113 #if !defined(SPI3_SCK_AF) || !defined(SPI3_MISO_AF) || !defined(SPI3_MOSI_AF)
114 #error SPI3: SCK, MISO and MOSI AFs should be defined together in target.h!
115 #endif
116 { .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), .sckAF = SPI3_SCK_AF, .misoAF = SPI3_MISO_AF, .mosiAF = SPI3_MOSI_AF, .divisorMap = spiDivisorMapSlow },
117 #else
118 { .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), .sckAF = GPIO_MUX_6, .misoAF = GPIO_MUX_6, .mosiAF = GPIO_MUX_6, .divisorMap = spiDivisorMapSlow },
119 #endif
120 #else
121 { .dev = NULL }, // No SPI3
122 #endif
124 #ifdef USE_SPI_DEVICE_4
125 #if defined(SPI4_SCK_AF) || defined(SPI4_MISO_AF) || defined(SPI4_MOSI_AF)
126 #if !defined(SPI4_SCK_AF) || !defined(SPI4_MISO_AF) || !defined(SPI4_MOSI_AF)
127 #error SPI4: SCK, MISO and MOSI AFs should be defined together in target.h!
128 #endif
129 { .dev = SPI4, .nss = IO_TAG(SPI4_NSS_PIN), .sck = IO_TAG(SPI4_SCK_PIN), .miso = IO_TAG(SPI4_MISO_PIN), .mosi = IO_TAG(SPI4_MOSI_PIN), .rcc = RCC_APB2(SPI4), .sckAF = SPI4_SCK_AF, .misoAF = SPI4_MISO_AF, .mosiAF = SPI4_MOSI_AF, .divisorMap = spiDivisorMapSlow }
130 #else
131 { .dev = SPI4, .nss = IO_TAG(SPI4_NSS_PIN), .sck = IO_TAG(SPI4_SCK_PIN), .miso = IO_TAG(SPI4_MISO_PIN), .mosi = IO_TAG(SPI4_MOSI_PIN), .rcc = RCC_APB2(SPI4), .sckAF = GPIO_MUX_6, .misoAF = GPIO_MUX_6, .mosiAF = GPIO_MUX_6, .divisorMap = spiDivisorMapSlow }
132 #endif
133 #else
134 { .dev = NULL } // No SPI4
135 #endif
137 #else
138 #error "Invalid CPU"
139 #endif
141 SPIDevice spiDeviceByInstance(spi_type *instance)
143 if (instance == SPI1)
144 return SPIDEV_1;
146 if (instance == SPI2)
147 return SPIDEV_2;
149 if (instance == SPI3)
150 return SPIDEV_3;
152 return SPIINVALID;
155 bool spiInitDevice(SPIDevice device, bool leadingEdge)
157 spiDevice_t *spi = &(spiHardwareMap[device]);
159 if (!spi->dev) {
160 return false;
163 if (spi->initDone) {
164 return true;
166 // Enable SPI clock
167 RCC_ClockCmd(spi->rcc, ENABLE);
168 RCC_ResetCmd(spi->rcc, ENABLE);
170 IOInit(IOGetByTag(spi->sck), OWNER_SPI, RESOURCE_SPI_SCK, device + 1);
171 IOInit(IOGetByTag(spi->miso), OWNER_SPI, RESOURCE_SPI_MISO, device + 1);
172 IOInit(IOGetByTag(spi->mosi), OWNER_SPI, RESOURCE_SPI_MOSI, device + 1);
174 IOConfigGPIOAF(IOGetByTag(spi->sck), SPI_IO_AF_SCK_CFG, spi->sckAF);
175 IOConfigGPIOAF(IOGetByTag(spi->miso), SPI_IO_AF_MISO_CFG, spi->misoAF);
176 IOConfigGPIOAF(IOGetByTag(spi->mosi), SPI_IO_AF_CFG, spi->mosiAF);
178 if (spi->nss) {
179 IOInit(IOGetByTag(spi->nss), OWNER_SPI, RESOURCE_SPI_CS, device + 1);
180 IOConfigGPIO(IOGetByTag(spi->nss), SPI_IO_CS_CFG);
183 spi_i2s_reset(spi->dev);
184 spi_init_type spi_init_struct;
185 spi_default_para_init (&spi_init_struct);
186 spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
187 spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
188 spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
189 spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_8;
190 spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
191 spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
193 spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;
194 spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;
196 if (leadingEdge) {
197 // SPI_MODE0
198 spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_LOW;
199 spi_init_struct.clock_phase = SPI_CLOCK_PHASE_1EDGE;
200 } else {
201 // SPI_MODE3
202 spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;
203 spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;
206 spi_init(spi->dev, &spi_init_struct);
207 spi_crc_polynomial_set (spi->dev, 0x07);
208 spi_crc_enable (spi->dev, TRUE); // enable crc
209 spi_enable (spi->dev, TRUE);
211 if (spi->nss) {
212 // Drive NSS high to disable connected SPI device.
213 IOHi(IOGetByTag(spi->nss));
215 spi->initDone = true;
216 return true;
219 uint32_t spiTimeoutUserCallback(spi_type *instance)
221 SPIDevice device = spiDeviceByInstance(instance);
222 if (device == SPIINVALID) {
223 return -1;
225 spiHardwareMap[device].errorCount++;
226 return spiHardwareMap[device].errorCount;
229 // return uint8_t value or -1 when failure
230 uint8_t spiTransferByte(spi_type *instance, uint8_t data)
232 uint16_t spiTimeout = 1000;
234 //while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_TXE) == RESET)
235 while (spi_i2s_flag_get(instance, SPI_I2S_TDBE_FLAG) == RESET)
236 if ((spiTimeout--) == 0)
237 return spiTimeoutUserCallback(instance);
239 //SPI_I2S_SendData(instance, data);
240 spi_i2s_data_transmit(instance, data);
242 spiTimeout = 1000;
243 //while (SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_RXNE) == RESET)
244 while (spi_i2s_flag_get(instance, SPI_I2S_RDBF_FLAG) == RESET)
245 if ((spiTimeout--) == 0)
246 return spiTimeoutUserCallback(instance);
248 return ((uint8_t) spi_i2s_data_receive(instance));
252 * Return true if the bus is currently in the middle of a transmission.
254 bool spiIsBusBusy(spi_type *instance)
256 //return SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_TXE) == RESET || SPI_I2S_GetFlagStatus(instance, SPI_I2S_FLAG_BSY) == SET;
257 return spi_i2s_flag_get(instance, SPI_I2S_TDBE_FLAG) == RESET || spi_i2s_flag_get(instance, SPI_I2S_BF_FLAG) == SET;
260 bool spiTransfer(spi_type *instance, uint8_t *out, const uint8_t *in, int len)
262 uint16_t spiTimeout = 1000;
264 instance->dt;
265 while (len--) {
266 uint8_t b = in ? *(in++) : 0xFF;
267 while (spi_i2s_flag_get(instance, SPI_I2S_TDBE_FLAG) == RESET) {
268 if ((spiTimeout--) == 0)
269 return spiTimeoutUserCallback(instance);
271 spi_i2s_data_transmit(instance, b);
272 spiTimeout = 1000;
273 while (spi_i2s_flag_get(instance, SPI_I2S_RDBF_FLAG) == RESET) {
274 if ((spiTimeout--) == 0)
275 return spiTimeoutUserCallback(instance);
277 b = spi_i2s_data_receive(instance);
278 if (out)
279 *(out++) = b;
282 return true;
285 void spiSetSpeed(spi_type *instance, SPIClockSpeed_e speed)
287 #define BR_CLEAR_MASK 0xFFC7
288 SPIDevice device = spiDeviceByInstance(instance);
289 if (device == SPIINVALID) {
290 return;
293 spi_enable (instance, FALSE);
295 // #define BR_BITS ((BIT(5) | BIT(4) | BIT(3)))
296 // const uint16_t tempRegister = (instance->ctrl1 & ~BR_BITS);
297 // instance->ctrl1 = tempRegister | (spiHardwareMap[device].divisorMap[speed] << 3);
298 // #undef BR_BITS
300 uint16_t tempRegister = instance->ctrl1;
301 tempRegister &= BR_CLEAR_MASK;
302 tempRegister |= (spiHardwareMap[device].divisorMap[speed] << 3);
303 instance->ctrl1 = tempRegister;
305 spi_enable (instance, TRUE);
308 uint16_t spiGetErrorCounter(spi_type *instance)
310 SPIDevice device = spiDeviceByInstance(instance);
311 if (device == SPIINVALID) {
312 return 0;
314 return spiHardwareMap[device].errorCount;
317 void spiResetErrorCounter(spi_type *instance)
319 SPIDevice device = spiDeviceByInstance(instance);
320 if (device != SPIINVALID) {
321 spiHardwareMap[device].errorCount = 0;
325 spi_type * spiInstanceByDevice( SPIDevice device )
327 return spiHardwareMap[device].dev;
329 #endif // USE_SPI