rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
at32_spi.cpp
Go to the documentation of this file.
1/**
2 * @file stm32_common_spi.cpp
3 * @brief Low level common STM32 code
4 *
5 * @date Mar 28, 2019
6 * @author Andrey Belomutskiy, (c) 2012-2020
7 */
8
9#include "pch.h"
10
11#if HAL_USE_SPI
12/* zero index is SPI_NONE */
13bool isSpiInitialized[SPI_TOTAL_COUNT + 1] = { true, false, false, false, false, false, false };
14
15struct af_pairs {
17 uint8_t af;
18};
19
20#define AT32_SPI_MAX_POSSIBLE_PINS_FOR_FX 9
21
22struct spi_af {
23 af_pairs cs[AT32_SPI_MAX_POSSIBLE_PINS_FOR_FX]; /* full or Gpio::Invalid terminated list of possible pins & af for CS function */
24 af_pairs sck[AT32_SPI_MAX_POSSIBLE_PINS_FOR_FX]; /* full or Gpio::Invalid terminated list of possible pins & af for SCK function */
25 af_pairs miso[AT32_SPI_MAX_POSSIBLE_PINS_FOR_FX]; /* full or Gpio::Invalid terminated list of possible pins & af for MISO function */
26 af_pairs mosi[AT32_SPI_MAX_POSSIBLE_PINS_FOR_FX]; /* full or Gpio::Invalid terminated list of possible pins & af for MOSI function */
27};
28
29#if STM32_SPI_USE_SPI1
30static const struct spi_af spi1_af = {
31 .cs = {{Gpio::A4, 5}, {Gpio::A15, 5}, {Gpio::E12, 4}, {Gpio::Invalid, 0}},
32 .sck = {{Gpio::A5, 5}, {Gpio::B3, 5}, {Gpio::E13, 4}, {Gpio::Invalid, 0}},
33 .miso = {{Gpio::A6, 5}, {Gpio::B4, 5}, {Gpio::E14, 4}, {Gpio::G0, 5}, {Gpio::Invalid, 0}},
34 .mosi = {{Gpio::A7, 5}, {Gpio::B5, 5}, {Gpio::E15, 4}, {Gpio::G1, 5}, {Gpio::Invalid, 0}}
35};
36#endif
37
38#if STM32_SPI_USE_SPI2
39static const struct spi_af spi2_af = {
40 .cs = {{Gpio::A11, 5}, {Gpio::B9, 5}, {Gpio::B12, 5}, {Gpio::D1, 7}, {Gpio::D2, 7}, {Gpio::Invalid, 0}},
41 .sck = {{Gpio::A9, 5}, {Gpio::B1, 6}, {Gpio::B10, 5}, {Gpio::B13, 5}, {Gpio::C7, 5}, {Gpio::D1, 6}, {Gpio::D3, 5}, {Gpio::Invalid, 0}},
42 .miso = {{Gpio::A12, 5}, {Gpio::B14, 5}, {Gpio::C2, 5}, {Gpio::D3, 6}, {Gpio::Invalid, 0}},
43 .mosi = {{Gpio::A10, 5}, {Gpio::B15, 5}, {Gpio::C1, 7}, {Gpio::C3, 5}, {Gpio::D4, 6}, {Gpio::Invalid, 0}}
44};
45#endif
46
47#if STM32_SPI_USE_SPI3
48static const struct spi_af spi3_af = {
49 .cs = {{Gpio::A4, 6}, {Gpio::A15, 6}, {Gpio::Invalid, 0}},
50 .sck = {{Gpio::B3, 6}, {Gpio::B12, 7}, {Gpio::C10, 6}, {Gpio::Invalid, 0}},
51 .miso = {{Gpio::A13, 6}, {Gpio::B4, 6}, {Gpio::C11, 6}, {Gpio::Invalid, 0}},
52 .mosi = {{Gpio::A14, 6}, {Gpio::B0, 7}, {Gpio::B2, 7}, {Gpio::B5, 6}, {Gpio::C1, 5}, {Gpio::C12, 6}, {Gpio::D0, 6}, {Gpio::D6, 5}, {Gpio::Invalid, 0}}
53};
54#endif
55
56#if STM32_SPI_USE_SPI4
57static const struct spi_af spi4_af = {
58 .cs = {{Gpio::B6, 6}, {Gpio::B12, 6}, {Gpio::E4, 5}, {Gpio::E11, 5}, {Gpio::G14, 6}, {Gpio::Invalid, 0}},
59 .sck = {{Gpio::B7, 6}, {Gpio::B13, 6}, {Gpio::E2, 5}, {Gpio::E12, 5}, {Gpio::G11, 6}, {Gpio::Invalid, 0}},
60 .miso = {{Gpio::A11, 6}, {Gpio::B8, 6}, {Gpio::D0, 5}, {Gpio::E5, 5}, {Gpio::E13, 5}, {Gpio::G12, 6}, {Gpio::Invalid, 0}},
61 .mosi = {{Gpio::A1, 5}, {Gpio::B9, 6}, {Gpio::E6, 5}, {Gpio::E14, 5}, {Gpio::G13, 6}, {Gpio::Invalid, 0}}
62};
63#endif
64
65static int findAfForPin(const struct af_pairs *list, brain_pin_e pin)
66{
67 int i;
68
69 if (list == NULL) {
70 return -1;
71 }
72
73 /* scan all list or until Gpio::Invalid */
74 for (i = 0; (i < AT32_SPI_MAX_POSSIBLE_PINS_FOR_FX) && (list[i].pin != Gpio::Invalid); i++) {
75 if (list[i].pin == pin) {
76 return list[i].af;
77 }
78 }
79 return -1;
80}
81
82static const struct spi_af *getAfListForSpi(SPIDriver *driver)
83{
84#if STM32_SPI_USE_SPI1
85 if (driver == &SPID1) {
86 return &spi1_af;
87 }
88#endif
89#if STM32_SPI_USE_SPI2
90 if (driver == &SPID2) {
91 return &spi2_af;
92 }
93#endif
94#if STM32_SPI_USE_SPI3
95 if (driver == &SPID3) {
96 return &spi3_af;
97 }
98#endif
99#if STM32_SPI_USE_SPI4
100 if (driver == &SPID4) {
101 return &spi4_af;
102 }
103#endif
104 criticalError("SPI interface is not available");
105 return NULL;
106}
107
108#if 0
109/* Currenty unused */
110static int getSpiCsAf(SPIDriver *driver, brain_pin_e pin)
111{
112 const struct spi_af *af = getAfListForSpi(driver);
113
114 if (af == NULL)
115 return -1;
116
117 return findAfForPin(af->cs, pin);
118}
119#endif
120
121static int getSpiSckAf(SPIDriver *driver, brain_pin_e pin)
122{
123 const struct spi_af *af = getAfListForSpi(driver);
124
125 if (af == NULL)
126 return -1;
127
128 return findAfForPin(af->sck, pin);
129}
130
131static int getSpiMisoAf(SPIDriver *driver, brain_pin_e pin)
132{
133 const struct spi_af *af = getAfListForSpi(driver);
134
135 if (af == NULL)
136 return -1;
137
138 return findAfForPin(af->miso, pin);
139}
140
141static int getSpiMosiAf(SPIDriver *driver, brain_pin_e pin)
142{
143 const struct spi_af *af = getAfListForSpi(driver);
144
145 if (af == NULL)
146 return -1;
147
148 return findAfForPin(af->mosi, pin);
149}
150
153 return; // already initialized
154 isSpiInitialized[device] = true;
155 if (device == SPI_DEVICE_1) {
156// todo: introduce a nice structure with all fields for same SPI
157#if STM32_SPI_USE_SPI1
158// scheduleMsg(&logging, "Turning on SPI1 pins");
165#else
166 criticalError("SPI1 not available in this binary");
167#endif /* STM32_SPI_USE_SPI1 */
168 }
169 if (device == SPI_DEVICE_2) {
170#if STM32_SPI_USE_SPI2
171 //scheduleMsg(&logging, "Turning on SPI2 pins");
178#else
179 criticalError("SPI2 not available in this binary");
180#endif /* STM32_SPI_USE_SPI2 */
181 }
182 if (device == SPI_DEVICE_3) {
183#if STM32_SPI_USE_SPI3
184 //scheduleMsg(&logging, "Turning on SPI3 pins");
191#else
192 criticalError("SPI3 not available in this binary");
193#endif /* STM32_SPI_USE_SPI3 */
194 }
195 if (device == SPI_DEVICE_4) {
196#if STM32_SPI_USE_SPI4
197 //scheduleMsg(&logging, "Turning on SPI4 pins");
198 /* there are no configuration fields for SPI4 in engineConfiguration, rely on board init code
199 * it should set proper functions for SPI4 pins */
200#else
201 criticalError("SPI4 not available in this binary");
202#endif /* STM32_SPI_USE_SPI4 */
203 }
204}
205
206void initSpiModule(SPIDriver *driver, brain_pin_e sck, brain_pin_e miso,
207 brain_pin_e mosi,
208 int sckMode,
209 int mosiMode,
210 int misoMode) {
211
212 int sckAf = getSpiSckAf(driver, sck);
213 int mosiAf = getSpiMosiAf(driver, mosi);
214 int misoAf = getSpiMisoAf(driver, miso);
215
216 if ((sckAf < 0) || (mosiAf < 0) || (misoAf < 0)) {
217 criticalError("Incorrect SPI pin configuration");
218 }
219
220 efiSetPadMode("SPI CLK ", sck,
221 PAL_MODE_ALTERNATE(sckAf) | sckMode | PAL_STM32_OSPEED_HIGHEST);
222
223 efiSetPadMode("SPI MOSI", mosi,
224 PAL_MODE_ALTERNATE(mosiAf) | mosiMode | PAL_STM32_OSPEED_HIGHEST);
225
226 // Activate the internal pullup on MISO: SD cards indicate "busy" by holding MOSI low,
227 // so in case there is no SD card installed, the line could float low and indicate that
228 // the (non existent) card is busy. We pull the line high to indicate "not busy" in case
229 // of a missing card.
230 efiSetPadMode("SPI MISO ", miso,
231 PAL_MODE_ALTERNATE(misoAf) | misoMode | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUPDR_PULLUP);
232}
233
234void initSpiCsNoOccupy(SPIConfig *spiConfig, brain_pin_e csPin) {
235 ioportid_t port = getHwPort("spi", csPin);
236 ioportmask_t pin = getHwPin("spi", csPin);
237 spiConfig->ssport = port;
238 spiConfig->sspad = pin;
239}
240
241void initSpiCs(SPIConfig *spiConfig, brain_pin_e csPin) {
242 /* TODO: why this is here? */
243#if !defined(HAL_LLD_SELECT_SPI_V2)
244 spiConfig->end_cb = nullptr;
245#else
246 spiConfig->data_cb = nullptr;
247 spiConfig->error_cb = nullptr;
248#endif
249
250 initSpiCsNoOccupy(spiConfig, csPin);
251 efiSetPadMode("chip select", csPin, PAL_STM32_MODE_OUTPUT);
252}
253
254int spiGetBaseClock(SPIDriver*)
255{
256 // TODO: implement
257 return 0;
258}
259
260int spiCalcClockDiv(SPIDriver*, SPIConfig*, unsigned int)
261{
262 // TODO: implement
263 return -1;
264}
265
266// SD cards are good up to 25MHz in "slow" mode, and 50MHz in "fast" mode
267// 168mhz F4:
268// Slow mode is 10.5 or 5.25 MHz, depending on which SPI device
269// Fast mode is 42 or 21 MHz
270// 216mhz F7:
271// Slow mode is 13.5 or 6.75 MHz
272// Fast mode is 54 or 27 MHz (technically out of spec, needs testing!)
273SPIConfig mmc_hs_spicfg = {
274 .circular = false,
275#if !defined(HAL_LLD_SELECT_SPI_V2)
276 .end_cb = NULL,
277#else
278 .slave = false,
279 .data_cb = NULL,
280 .error_cb = NULL,
281#endif
282 .ssport = NULL,
283 .sspad = 0,
284 .cr1 = SPI_BaudRatePrescaler_2,
285 .cr2 = 0
286};
287
288SPIConfig mmc_ls_spicfg = {
289 .circular = false,
290#if !defined(HAL_LLD_SELECT_SPI_V2)
291 .end_cb = NULL,
292#else
293 .slave = false,
294 .data_cb = NULL,
295 .error_cb = NULL,
296#endif
297 .ssport = NULL,
298 .sspad = 0,
299 .cr1 = SPI_BaudRatePrescaler_8,
300 .cr2 = 0
301};
302
303#endif /* HAL_USE_SPI */
static int getSpiSckAf(SPIDriver *driver, brain_pin_e pin)
Definition at32_spi.cpp:121
int spiCalcClockDiv(SPIDriver *, SPIConfig *, unsigned int)
Definition at32_spi.cpp:260
SPIConfig mmc_hs_spicfg
Definition at32_spi.cpp:273
static const struct spi_af * getAfListForSpi(SPIDriver *driver)
Definition at32_spi.cpp:82
int spiGetBaseClock(SPIDriver *)
Definition at32_spi.cpp:254
void initSpiModule(SPIDriver *driver, brain_pin_e sck, brain_pin_e miso, brain_pin_e mosi, int sckMode, int mosiMode, int misoMode)
Definition at32_spi.cpp:206
static const struct spi_af spi2_af
Definition at32_spi.cpp:39
SPIConfig mmc_ls_spicfg
Definition at32_spi.cpp:288
static int getSpiMosiAf(SPIDriver *driver, brain_pin_e pin)
Definition at32_spi.cpp:141
void initSpiCsNoOccupy(SPIConfig *spiConfig, brain_pin_e csPin)
Definition at32_spi.cpp:234
static const struct spi_af spi4_af
Definition at32_spi.cpp:57
static int findAfForPin(const struct af_pairs *list, brain_pin_e pin)
Definition at32_spi.cpp:65
static const struct spi_af spi1_af
Definition at32_spi.cpp:30
bool isSpiInitialized[SPI_TOTAL_COUNT+1]
Definition at32_spi.cpp:13
void turnOnSpi(spi_device_e device)
Definition at32_spi.cpp:151
static int getSpiMisoAf(SPIDriver *driver, brain_pin_e pin)
Definition at32_spi.cpp:131
static const struct spi_af spi3_af
Definition at32_spi.cpp:48
void initSpiCs(SPIConfig *spiConfig, brain_pin_e csPin)
Definition at32_spi.cpp:241
static int getSpiCsAf(SPIDriver *driver, brain_pin_e pin)
Definition at32_spi.cpp:110
void efiSetPadMode(const char *msg, brain_pin_e brainPin, iomode_t mode)
@ Invalid
ioportid_t getHwPort(const char *msg, brain_pin_e brainPin)
ioportmask_t getHwPin(const char *msg, brain_pin_e brainPin)
static constexpr engine_configuration_s * engineConfiguration
uint32_t ioportmask_t
Digital I/O port sized unsigned type.
Definition hal_pal_lld.h:78
GPIO_TypeDef * ioportid_t
Port Identifier.
SPIDriver SPID1
SPI0 driver identifier.
Definition hal_spi_lld.c:42
SPIDriver SPID2
SPI1 driver identifier.
Definition hal_spi_lld.c:47
brain_pin_e getSckPin(spi_device_e device)
Definition hardware.cpp:126
brain_pin_e getMosiPin(spi_device_e device)
Definition hardware.cpp:106
brain_pin_e getMisoPin(spi_device_e device)
Definition hardware.cpp:86
static Lps25 device
Definition init_baro.cpp:4
spi_device_e
brain_pin_e pin
Definition stm32_adc.cpp:15