[SITL] Enable telemetry: LTM and MAVLink (#8940)
[inav.git] / src / main / drivers / bus_spi_at32f43x.c
blob55947c1913f283ef047c9c9e1da9573d30fc0494
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 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 },
86 #else
87 { .dev = NULL }, // No SPI1
88 #endif
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 },
91 #else
92 { .dev = NULL }, // No SPI2
93 #endif
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 },
96 #else
97 { .dev = NULL }, // No SPI3
98 #endif
99 { .dev = NULL }, // No SPI4
101 #else
102 #error "Invalid CPU"
103 #endif
105 SPIDevice spiDeviceByInstance(spi_type *instance)
107 if (instance == SPI1)
108 return SPIDEV_1;
110 if (instance == SPI2)
111 return SPIDEV_2;
113 if (instance == SPI3)
114 return SPIDEV_3;
116 return SPIINVALID;
119 bool spiInitDevice(SPIDevice device, bool leadingEdge)
121 spiDevice_t *spi = &(spiHardwareMap[device]);
123 if (!spi->dev) {
124 return false;
127 if (spi->initDone) {
128 return true;
130 // Enable SPI clock
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);
142 if (spi->nss) {
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;
159 if (leadingEdge) {
160 // SPI_MODE0
161 spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_LOW;
162 spi_init_struct.clock_phase = SPI_CLOCK_PHASE_1EDGE;
163 } else {
164 // SPI_MODE3
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);
174 if (spi->nss) {
175 // Drive NSS high to disable connected SPI device.
176 IOHi(IOGetByTag(spi->nss));
178 spi->initDone = true;
179 return true;
182 uint32_t spiTimeoutUserCallback(spi_type *instance)
184 SPIDevice device = spiDeviceByInstance(instance);
185 if (device == SPIINVALID) {
186 return -1;
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);
205 spiTimeout = 1000;
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;
227 instance->dt;
228 while (len--) {
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);
235 spiTimeout = 1000;
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);
241 if (out)
242 *(out++) = b;
245 return true;
248 void spiSetSpeed(spi_type *instance, SPIClockSpeed_e speed)
250 #define BR_CLEAR_MASK 0xFFC7
251 SPIDevice device = spiDeviceByInstance(instance);
252 if (device == SPIINVALID) {
253 return;
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);
261 // #undef BR_BITS
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) {
275 return 0;
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;
292 #endif // USE_SPI