rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
stm32_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
15static int getSpiAf(SPIDriver *driver) {
16#if STM32_SPI_USE_SPI1
17 if (driver == &SPID1) {
18 return EFI_SPI1_AF;
19 }
20#endif
21#if STM32_SPI_USE_SPI2
22 if (driver == &SPID2) {
23 return EFI_SPI2_AF;
24 }
25#endif
26#if STM32_SPI_USE_SPI3
27 if (driver == &SPID3) {
28 return EFI_SPI3_AF;
29 }
30#endif
31#if STM32_SPI_USE_SPI4
32 if (driver == &SPID4) {
33 return EFI_SPI4_AF;
34 }
35#endif
36#if STM32_SPI_USE_SPI5
37 if (driver == &SPID5) {
38 return EFI_SPI5_AF;
39 }
40#endif
41#if STM32_SPI_USE_SPI6
42 if (driver == &SPID6) {
43 return EFI_SPI6_AF;
44 }
45#endif
46 criticalError("SPI AF not available");
47 return -1;
48}
49
52 return; // already initialized
54 if (device == SPI_DEVICE_1) {
55// todo: introduce a nice structure with all fields for same SPI
56#if STM32_SPI_USE_SPI1
57// scheduleMsg(&logging, "Turning on SPI1 pins");
64#else
65 criticalError("SPI1 not available in this binary");
66#endif /* STM32_SPI_USE_SPI1 */
67 }
68 if (device == SPI_DEVICE_2) {
69#if STM32_SPI_USE_SPI2
70// scheduleMsg(&logging, "Turning on SPI2 pins");
77#else
78 criticalError("SPI2 not available in this binary");
79#endif /* STM32_SPI_USE_SPI2 */
80 }
81 if (device == SPI_DEVICE_3) {
82#if STM32_SPI_USE_SPI3
83// scheduleMsg(&logging, "Turning on SPI3 pins");
90#else
91 criticalError("SPI3 not available in this binary");
92#endif /* STM32_SPI_USE_SPI3 */
93 }
94 if (device == SPI_DEVICE_4) {
95#if STM32_SPI_USE_SPI4
102#else
103 criticalError("SPI4 not available in this binary");
104#endif /* STM32_SPI_USE_SPI4 */
105 }
106 if (device == SPI_DEVICE_5) {
107#if STM32_SPI_USE_SPI5
114#else
115 criticalError("SPI5 not available in this binary");
116#endif /* STM32_SPI_USE_SPI5 */
117 }
118 if (device == SPI_DEVICE_6) {
119#if STM32_SPI_USE_SPI6
126#else
127 criticalError("SPI6 not available in this binary");
128#endif /* STM32_SPI_USE_SPI6 */
129 }
130}
131
132void initSpiModule(SPIDriver *driver,
133 brain_pin_e sck, brain_pin_e miso, brain_pin_e mosi,
134 int sckMode, int mosiMode, int misoMode) {
135
136 /**
137 * See https://github.com/rusefi/rusefi/pull/664/
138 *
139 * Info on the silicon defect can be found in this document, section 2.5.2:
140 * https://www.st.com/content/ccc/resource/technical/document/errata_sheet/0a/98/58/84/86/b6/47/a2/DM00037591.pdf/files/DM00037591.pdf/jcr:content/translations/en.DM00037591.pdf
141 */
142 efiSetPadMode("SPI CLK ", sck, PAL_MODE_ALTERNATE(getSpiAf(driver)) | sckMode | PAL_STM32_OSPEED_HIGHEST);
143
144 efiSetPadMode("SPI MOSI", mosi, PAL_MODE_ALTERNATE(getSpiAf(driver)) | mosiMode | PAL_STM32_OSPEED_HIGHEST);
145
146 // Activate the internal pullup on MISO: SD cards indicate "busy" by holding MOSI low,
147 // so in case there is no SD card installed, the line could float low and indicate that
148 // the (non existent) card is busy. We pull the line high to indicate "not busy" in case
149 // of a missing card.
150 efiSetPadMode("SPI MISO", miso, PAL_MODE_ALTERNATE(getSpiAf(driver)) | misoMode | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUPDR_PULLUP);
151}
152
153void initSpiCsNoOccupy(SPIConfig *spiConfig, brain_pin_e csPin) {
154 ioportid_t port = getHwPort("spi", csPin);
155 ioportmask_t pin = getHwPin("spi", csPin);
156 spiConfig->ssport = port;
157 spiConfig->sspad = pin;
158}
159
160void initSpiCs(SPIConfig *spiConfig, brain_pin_e csPin) {
161 /* TODO: why this is here? */
162#ifdef _CHIBIOS_RT_CONF_VER_6_1_
163 spiConfig->end_cb = nullptr;
164#else
165 spiConfig->data_cb = nullptr;
166 spiConfig->error_cb = nullptr;
167#endif
168
169 initSpiCsNoOccupy(spiConfig, csPin);
170 efiSetPadMode("chip select", csPin, PAL_STM32_MODE_OUTPUT);
171}
172
173int spiGetBaseClock(SPIDriver *spip)
174{
175#if STM32_SPI_USE_SPI1
176 if (spip == &SPID1) {
177 // APB2
178 return STM32_PCLK2;
179 }
180#endif
181#if STM32_SPI_USE_SPI2
182 if (spip == &SPID2) {
183 // APB1
184 return STM32_PCLK1;
185 }
186#endif
187#if STM32_SPI_USE_SPI3
188 if (spip == &SPID3) {
189 // APB1
190 return STM32_PCLK1;
191 }
192#endif
193#if STM32_SPI_USE_SPI4
194 if (spip == &SPID4) {
195 // APB2
196 return STM32_PCLK2;
197 }
198#endif
199#if STM32_SPI_USE_SPI5
200 if (spip == &SPID5) {
201 // APB2
202 return STM32_PCLK2;
203 }
204#endif
205#if STM32_SPI_USE_SPI6
206 if (spip == &SPID6) {
207 // APB2
208 return STM32_PCLK2;
209 }
210#endif
211
212 return 0;
213}
214
215#ifdef STM32H7XX
216
217int spiCalcClockDiv(SPIDriver*, SPIConfig*, unsigned int)
218{
219 // TODO: implement
220 return -1;
221}
222
223#else
224
225int spiCalcClockDiv(SPIDriver *spip, SPIConfig *spiConfig, unsigned int clk)
226{
227 if (clk == 0) {
228 return -1;
229 }
230
231 unsigned int baseClock = spiGetBaseClock(spip);
232
233 if (baseClock == 0) {
234 return -1;
235 }
236
237 // round down
238 int div = (baseClock + clk - 1) / clk;
239
240 spiConfig->cr1 &= ~SPI_CR1_BR_Msk;
241 if (div <= 2) {
242 spiConfig->cr1 |= SPI_BaudRatePrescaler_2;
243 } else if (div <= 4) {
244 spiConfig->cr1 |= SPI_BaudRatePrescaler_4;
245 } else if (div <= 8) {
246 spiConfig->cr1 |= SPI_BaudRatePrescaler_8;
247 } else if (div <= 16) {
248 spiConfig->cr1 |= SPI_BaudRatePrescaler_16;
249 } else if (div <= 32) {
250 spiConfig->cr1 |= SPI_BaudRatePrescaler_32;
251 } else if (div <= 64) {
252 spiConfig->cr1 |= SPI_BaudRatePrescaler_64;
253 } else if (div <= 128) {
254 spiConfig->cr1 |= SPI_BaudRatePrescaler_128;
255 } else {
256 spiConfig->cr1 |= SPI_BaudRatePrescaler_256;
257 }
258
259 return 0;
260}
261
262#endif
263
264#ifdef STM32H7XX
265// H7 SPI clock is set to 80MHz
266// fast mode is 80mhz/2 = 40MHz
267SPIConfig mmc_hs_spicfg = {
268 .circular = false,
269#ifdef _CHIBIOS_RT_CONF_VER_6_1_
270 .end_cb = NULL,
271#else
272 .slave = false,
273 .data_cb = NULL,
274 .error_cb = NULL,
275#endif
276 .ssport = NULL,
277 .sspad = 0,
278 .cfg1 = 7 // 8 bits per byte
279 | 0 /* MBR = 0, divider = 2 */,
280 .cfg2 = 0
281};
282
283// Slow mode is 80mhz/4 = 20MHz
284SPIConfig mmc_ls_spicfg = {
285 .circular = false,
286#ifdef _CHIBIOS_RT_CONF_VER_6_1_
287 .end_cb = NULL,
288#else
289 .slave = false,
290 .data_cb = NULL,
291 .error_cb = NULL,
292#endif
293 .ssport = NULL,
294 .sspad = 0,
295 .cfg1 = 7 // 8 bits per byte
296 | SPI_CFG1_MBR_0 /* MBR = 001, divider = 4 */,
297 .cfg2 = 0
298};
299
300#else /* not STM32H7XX */
301
302// SD cards are good up to 25MHz in "slow" mode, and 50MHz in "fast" mode
303// 168mhz F4:
304// Slow mode is 10.5 or 5.25 MHz, depending on which SPI device
305// Fast mode is 42 or 21 MHz
306// 216mhz F7:
307// Slow mode is 13.5 or 6.75 MHz
308// Fast mode is 54 or 27 MHz (technically out of spec, needs testing!)
309SPIConfig mmc_hs_spicfg = {
310 .circular = false,
311#ifdef _CHIBIOS_RT_CONF_VER_6_1_
312 .end_cb = NULL,
313#else
314 .slave = false,
315 .data_cb = NULL,
316 .error_cb = NULL,
317#endif
318 .ssport = NULL,
319 .sspad = 0,
320 .cr1 = SPI_BaudRatePrescaler_2,
321 .cr2 = 0
322};
323
324SPIConfig mmc_ls_spicfg = {
325 .circular = false,
326#ifdef _CHIBIOS_RT_CONF_VER_6_1_
327 .end_cb = NULL,
328#else
329 .slave = false,
330 .data_cb = NULL,
331 .error_cb = NULL,
332#endif
333 .ssport = NULL,
334 .sspad = 0,
335 .cr1 = SPI_BaudRatePrescaler_8,
336 .cr2 = 0
337};
338#endif
339
340#endif /* HAL_USE_SPI */
void efiSetPadMode(const char *msg, brain_pin_e brainPin, iomode_t mode)
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
int spiCalcClockDiv(SPIDriver *, SPIConfig *, unsigned int)
int spiGetBaseClock(SPIDriver *spip)
SPIConfig mmc_hs_spicfg
static int getSpiAf(SPIDriver *driver)
Definition stm32_spi.cpp:15
void initSpiModule(SPIDriver *driver, brain_pin_e sck, brain_pin_e miso, brain_pin_e mosi, int sckMode, int mosiMode, int misoMode)
SPIConfig mmc_ls_spicfg
void initSpiCsNoOccupy(SPIConfig *spiConfig, brain_pin_e csPin)
bool isSpiInitialized[SPI_TOTAL_COUNT+1]
Definition stm32_spi.cpp:13
void turnOnSpi(spi_device_e device)
Definition stm32_spi.cpp:50
void initSpiCs(SPIConfig *spiConfig, brain_pin_e csPin)