rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
smart_gpio.cpp
Go to the documentation of this file.
1/*
2 * @file smart_gpio.cpp
3 *
4 * @date Apr 13, 2019
5 * @author Andrey Belomutskiy, (c) 2012-2020
6 */
7
8#include "pch.h"
9
10#include "smart_gpio.h"
11#include "hardware.h"
12#include "gpio_ext.h"
18#include "drivers/gpio/l9779.h"
21
22#if EFI_PROD_CODE
23
24#if (BOARD_TLE6240_COUNT > 0)
25// todo: migrate to TS or board config
26#ifndef TLE6240_RESET_PORT
27#define TLE6240_RESET_PORT GPIOG
28#endif /* TLE6240_RESET_PORT */
29#ifndef TLE6240_RESET_PAD
30#define TLE6240_RESET_PAD 3U
31#endif /* TLE6240_RESET_PAD */
32#ifndef TLE6240_DIRECT_IO
33#define TLE6240_DIRECT_IO \
34 /* IN1 - D_TACH_OUT */ \
35 [0] = {.port = GPIOG, .pad = 2}, \
36 /* IN2..4 grounded */ \
37 [1] = {.port = NULL, .pad = 0}, \
38 [2] = {.port = NULL, .pad = 0}, \
39 [3] = {.port = NULL, .pad = 0}, \
40 /* IN9 - D_INJ_5 */ \
41 [4] = {.port = GPIOD, .pad = 15}, \
42 /* IN10 - D_WASTGATE */ \
43 [5] = {.port = GPIOD, .pad = 14}, \
44 /* IN11 - D_IDLE_OPEN */ \
45 [6] = {.port = GPIOC, .pad = 6}, \
46 /* IN12 - D_IDLE_CLOSE */ \
47 [7] = {.port = GPIOC, .pad = 7},
48#endif /* TLE6240_DIRECT_IO */
49
52 .spi_bus = NULL,
53 .spi_config = {
54 .circular = false,
55#ifdef _CHIBIOS_RT_CONF_VER_6_1_
56 .end_cb = NULL,
57#else
58 .slave = false,
59 .data_cb = NULL,
60 .error_cb = NULL,
61#endif
62 .ssport = NULL,
63 .sspad = 0,
64 .cr1 =
65 SPI_CR1_16BIT_MODE |
66 SPI_CR1_SSM |
67 SPI_CR1_SSI |
68 /* SPI_CR1_LSBFIRST | */
69 ((3 << SPI_CR1_BR_Pos) & SPI_CR1_BR) | /* div = 16 */
70 SPI_CR1_MSTR |
71 /* SPI_CR1_CPOL | */ // = 0
72 SPI_CR1_CPHA | // = 1
73 0,
74 .cr2 = SPI_CR2_16BIT_MODE
75 },
76 .direct_io = {
77 TLE6240_DIRECT_IO
78 },
79 .reset = {.port = TLE6240_RESET_PORT, .pad = TLE6240_RESET_PAD}
80};
81#endif /* (BOARD_TLE6240_COUNT > 0) */
82
83#if (BOARD_MC33972_COUNT > 0)
86 .spi_bus = NULL,
87 .spi_config = {
88 .circular = false,
89#ifdef _CHIBIOS_RT_CONF_VER_6_1_
90 .end_cb = NULL,
91#else
92 .slave = false,
93 .data_cb = NULL,
94 .error_cb = NULL,
95#endif
96 .ssport = NULL,
97 .sspad = 0,
98 .cr1 =
99 SPI_CR1_8BIT_MODE |
100 SPI_CR1_SSM |
101 SPI_CR1_SSI |
102 /* SPI_CR1_LSBFIRST | */
103 ((3 << SPI_CR1_BR_Pos) & SPI_CR1_BR) | /* div = 16 */
104 SPI_CR1_MSTR |
105 /* SPI_CR1_CPOL | */ /* = 0 */
106 SPI_CR1_CPHA | /* = 1 */
107 0,
108 .cr2 = SPI_CR2_8BIT_MODE
109 },
110};
111#endif /* (BOARD_MC33972_COUNT > 0) */
112
113#if (BOARD_L9779_COUNT > 0)
116 .spi_bus = NULL,
117 .spi_config = {
118 .circular = false,
119#ifdef _CHIBIOS_RT_CONF_VER_6_1_
120 .end_cb = NULL,
121#else
122 .slave = false,
123 .data_cb = NULL,
124 .error_cb = NULL,
125#endif
126 .ssport = NULL,
127 .sspad = 0,
128 .cr1 =
129 SPI_CR1_16BIT_MODE |
130 SPI_CR1_SSM |
131 SPI_CR1_SSI |
132 //SPI_CR1_LSBFIRST | //MSB first
133 ((3 << SPI_CR1_BR_Pos) & SPI_CR1_BR) | // div = 16, up to 8 MHz
134 SPI_CR1_MSTR |
135 SPI_CR1_CPHA |
136 0,
137 .cr2 = SPI_CR2_16BIT_MODE
138 },
139 .direct_gpio = {
140 /* IGNI1..IGNI4 */
141 [0] = {.port = NULL, .pad = 0},
142 [1] = {.port = NULL, .pad = 0},
143 [2] = {.port = NULL, .pad = 0},
144 [3] = {.port = NULL, .pad = 0},
145 /* IN1..IN7 */
146 [4] = {.port = NULL, .pad = 0},
147 [5] = {.port = NULL, .pad = 0},
148 [6] = {.port = NULL, .pad = 0},
149 [7] = {.port = NULL, .pad = 0},
150 [8] = {.port = NULL, .pad = 0},
151 [9] = {.port = NULL, .pad = 0},
152 [10] = {.port = NULL, .pad = 0},
153 },
154 /* PWM (IN8) */
155 .pwm_gpio = {.port = NULL, .pad = 0},
156};
157#endif /* (BOARD_L9779_COUNT > 0) */
158
159#if (BOARD_TLE8888_COUNT > 0)
162 .spi_bus = NULL,
163 .spi_config = {
164 .circular = false,
165#ifdef _CHIBIOS_RT_CONF_VER_6_1_
166 .end_cb = NULL,
167#else
168 .slave = false,
169 .data_cb = NULL,
170 .error_cb = NULL,
171#endif
172 .ssport = NULL,
173 .sspad = 0,
174 .cr1 =
175 SPI_CR1_16BIT_MODE |
176 SPI_CR1_SSM |
177 SPI_CR1_SSI |
178 SPI_CR1_LSBFIRST | //LSB first
179 ((3 << SPI_CR1_BR_Pos) & SPI_CR1_BR) | // div = 16
180 SPI_CR1_MSTR |
181 SPI_CR1_CPHA |
182 0,
183 .cr2 = SPI_CR2_16BIT_MODE
184 },
185 .reset = {.port = NULL, .pad = 0},
186 .direct_gpio = {
187 /* IN1..4 -> OUT1..OUT4 (Injectors) */
188 [0] = {.port = GPIOE, .pad = 14},
189 [1] = {.port = GPIOE, .pad = 13},
190 [2] = {.port = GPIOE, .pad = 12},
191 [3] = {.port = GPIOE, .pad = 11},
192 /* IN5..8 -> IGN1..IGN4 (Ignitors) */
193 /* Not used */
194 [4] = {.port = NULL, .pad = 0},
195 [5] = {.port = NULL, .pad = 0},
196 [6] = {.port = NULL, .pad = 0},
197 [7] = {.port = NULL, .pad = 0},
198 /* Remapable IN9..12 */
199 [8] = {.port = GPIOE, .pad = 10},
200 [9] = {.port = GPIOE, .pad = 9},
201 [10] = {.port = GPIOE, .pad = 8},
202 [11] = {.port = GPIOE, .pad = 7},
203 },
204 .direct_maps = {
205 [0] = {.output = 5}, /* MRE: LS2 */
206 [1] = {.output = 6}, /* MRE: LS1 */
207 [2] = {.output = 21}, /* MRE: GP1 - not used when stepper = true */
208 [3] = {.output = 22}, /* MRE: GP2 - not used when stepper = true */
209 },
210 .ign_en = {.port = GPIOD, .pad = 10},
211 .inj_en = {.port = GPIOD, .pad = 11},
212 .mode = TL_AUTO,
213 .stepper = false
214};
215#endif
216
217#if (BOARD_MC33810_COUNT > 0)
218static OutputPin mc33810Cs[C_MC33810_COUNT];
219#endif /* (BOARD_MC33810_COUNT > 0) */
220
221#if (BOARD_DRV8860_COUNT > 0)
224 .spi_bus = NULL,
225 .spi_config = {
226 .circular = false,
227#ifdef _CHIBIOS_RT_CONF_VER_6_1_
228 .end_cb = NULL,
229#else
230 .slave = false,
231 .data_cb = NULL,
232 .error_cb = NULL,
233#endif
234 .ssport = NULL,
235 .sspad = 0,
236 .cr1 =
237 SPI_CR1_16BIT_MODE |
238 SPI_CR1_SSM |
239 SPI_CR1_SSI |
240 ((7 << SPI_CR1_BR_Pos) & SPI_CR1_BR) | /* div = 32 */
241 SPI_CR1_MSTR |
242 SPI_CR1_CPOL |
243 0,
244 .cr2 = SPI_CR2_16BIT_MODE
245 },
246 .reset = {.port = DRV8860_RESET_PORT, .pad = DRV8860_RESET_PAD}
247};
248#endif /* (BOARD_DRV8860_COUNT > 0) */
249
250#endif // EFI_PROD_CODE
251
254#if EFI_PROD_CODE
255#if (BOARD_TLE6240_COUNT > 0)
261
262 criticalAssertVoid(ret == (int)Gpio::TLE6240_PIN_1, "tle6240");
263 }
264#endif /* (BOARD_TLE6240_COUNT > 0) */
265
266#if (BOARD_MC33972_COUNT > 0)
268 // todo: reuse initSpiCs method?
272 // todo: propogate 'basePinOffset' parameter
274
275 criticalAssertVoid(ret == (int)Gpio::MC33972_PIN_1, "mc33972");
276 }
277#endif /* (BOARD_MC33972_COUNT > 0) */
278
279#if (BOARD_L9779_COUNT > 0)
281 // todo: reuse initSpiCs method?
285 // todo: propogate 'basePinOffset' parameter
286 int ret = l9779_add(Gpio::L9779_IGN_1, 0, &l9779_cfg);
287
288 criticalAssertVoid(ret == (int)Gpio::L9779_IGN_1, "l9779");
289 }
290#endif /* (BOARD_L9779_COUNT > 0) */
291
292#if (BOARD_TLE8888_COUNT > 0)
294 // todo: reuse initSpiCs method?
298
301
302 /* spi_bus == null checked in _add function */
304
305 criticalAssertVoid(ret == (int)Gpio::TLE8888_PIN_1, "tle8888");
306 }
307#endif /* (BOARD_TLE8888_COUNT > 0) */
308
309#if EFI_PROD_CODE && (BOARD_DRV8860_COUNT > 0)
315
316 criticalAssertVoid(ret == (int)Gpio::DRV8860_PIN_1, "drv8860");
317 }
318#endif /* (BOARD_DRV8860_COUNT > 0) */
319
320#if EFI_CAN_GPIO
322#endif // EFI_CAN_GPIO
323
324#if (BOARD_MC33810_COUNT > 0)
325 /* none of official boards has this IC */
326#endif /* (BOARD_MC33810_COUNT > 0) */
327
328#if (BOARD_TLE9104_COUNT > 0)
329 // No official boards have this IC
330#endif
331
332#endif // EFI_PROD_CODE
333
334 /* external chip init */
336}
337
339#if EFI_PROD_CODE && (BOARD_TLE8888_COUNT > 0)
340 // TODO: use a timer instead
341 static efitick_t tle8888CrankingResetTime = 0;
342
344 efitick_t nowNt = getTimeNowNt();
345 if (nowNt - tle8888CrankingResetTime > MS2NT(300)) {
347 // let's reset TLE8888 every 300ms while cranking since that's the best we can do to deal with undervoltage reset
348 // PS: oh yes, it's a horrible design! Please suggest something better!
349 tle8888CrankingResetTime = nowNt;
350 }
351 }
352#endif /* BOARD_TLE8888_COUNT */
353}
354
356#if EFI_PROD_CODE
357#if (BOARD_TLE8888_COUNT > 0)
359#endif /* BOARD_TLE8888_COUNT */
360#if (BOARD_TLE6240_COUNT > 0)
362#endif /* BOARD_TLE6240_COUNT */
363#if (BOARD_MC33972_COUNT > 0)
365#endif /* BOARD_MC33972_COUNT */
366#if (BOARD_DRV8860_COUNT > 0)
367
368#endif /* BOARD_DRV8860_COUNT */
369#if (BOARD_MC33810_COUNT > 0)
370 for (size_t i = 0;i<C_MC33810_COUNT;i++) {
372 }
373#endif /* (BOARD_MC33810_COUNT > 0) */
374#if (BOARD_TLE9104_COUNT > 0)
375 // No official boards have this IC
376#endif
377#endif // EFI_PROD_CODE
378}
379
381#if EFI_PROD_CODE
382#if (BOARD_TLE8888_COUNT > 0)
385 tle8888Cs.setValue(true);
386#endif /* BOARD_TLE8888_COUNT */
387#if (BOARD_TLE6240_COUNT > 0)
388 // todo: any way to reduce copy-paste? some convention between pin property name and pin mode property name?
391 tle6240Cs.setValue(true);
392#endif /* BOARD_TLE6240_COUNT */
393#if (BOARD_MC33972_COUNT > 0)
394 // todo: any way to reduce copy-paste? some convention between pin property name and pin mode property name?
397 mc33972Cs.setValue(true);
398#endif /* BOARD_MC33972_COUNT */
399#if (BOARD_DRV8860_COUNT > 0)
400 // todo: any way to reduce copy-paste? some convention between pin property name and pin mode property name?
403 drv8860Cs.setValue(true);
404#endif /* BOARD_DRV8860_COUNT */
405#if (BOARD_MC33810_COUNT > 0)
406 for (size_t i = 0;i<C_MC33810_COUNT;i++) {
407 // huh?! most boards are NOT using mc33810_cs we are directly initializing CS pin(s)?!
408 mc33810Cs[i].initPin("mc33810 CS", engineConfiguration->mc33810_cs[i],
410 mc33810Cs[i].setValue(true);
411 }
412#endif /* (BOARD_MC33810_COUNT > 0) */
413#if (BOARD_TLE9104_COUNT > 0)
414 // todo: no official boards have this IC yet
415#endif
416#if (BOARD_L9779_COUNT > 0)
417 // todo: use existing l9779_cs and l9779_csPinMode settings
418 // todo: no official boards have this IC yet
419#endif
420#endif // EFI_PROD_CODE
421}
void initCanGpioMsiobox()
RpmCalculator rpmCalculator
Definition engine.h:306
Single output pin reference and state.
Definition efi_output.h:49
void initPin(const char *msg, brain_pin_e brainPin, pin_output_mode_e outputMode, bool forceInitWithFatalError=false)
Definition efi_gpio.cpp:711
void setValue(const char *msg, int logicValue, bool isForce=false)
Definition efi_gpio.cpp:604
bool isCranking() const override
@ L9779_IGN_1
@ TLE6240_PIN_1
@ DRV8860_PIN_1
@ TLE8888_PIN_1
@ MC33972_PIN_1
int gpiochips_init(void)
Init all registered gpiochips.
Definition core.cpp:284
int drv8860_add(brain_pin_e base, unsigned int index, const drv8860_config *cfg)
DRV8860 driver add.
Definition drv8860.cpp:235
ioportid_t getHwPort(const char *msg, brain_pin_e brainPin)
ioportmask_t getHwPin(const char *msg, brain_pin_e brainPin)
efitick_t getTimeNowNt()
Definition efitime.cpp:19
static EngineAccessor engine
Definition engine.h:413
engine_configuration_s & activeConfiguration
static constexpr engine_configuration_s * engineConfiguration
SPIDriver * getSpiDevice(spi_device_e spiDevice)
Definition hardware.cpp:149
void efiSetPadUnused(brain_pin_e brainPin)
Definition io_pins.cpp:20
int l9779_add(brain_pin_e base, unsigned int index, const l9779_config *cfg)
L9779 driver add.
Definition l9779.cpp:733
int mc33972_add(brain_pin_e base, unsigned int index, const struct mc33972_config *cfg)
MC33972 driver add.
Definition mc33972.cpp:414
bool isBrainPinValid(brain_pin_e brainPin)
static OutputPin mc33972Cs
struct drv8860_config drv8860
struct tle6240_config tle6240
struct tle8888_config tle8888_cfg
void startSmartCsPins()
static OutputPin tle8888Cs
static OutputPin mc33810Cs[C_MC33810_COUNT]
static OutputPin l9779Cs
struct mc33972_config mc33972
static OutputPin drv8860Cs
void tle8888startup()
void initSmartGpio()
static OutputPin tle6240Cs
struct l9779_config l9779_cfg
void stopSmartCsPins()
SPIDriver * spi_bus
Definition drv8860.h:24
SPIConfig spi_config
Definition drv8860.h:25
SPIConfig spi_config
Definition l9779.h:27
SPIDriver * spi_bus
Definition l9779.h:26
SPIConfig spi_config
Definition mc33972.h:23
SPIDriver * spi_bus
Definition mc33972.h:22
SPIConfig spi_config
Definition tle6240.h:24
SPIDriver * spi_bus
Definition tle6240.h:23
SPIConfig spi_config
Definition tle8888.h:44
tle8888_mode_e mode
Definition tle8888.h:69
SPIDriver * spi_bus
Definition tle8888.h:43
int tle6240_add(brain_pin_e base, unsigned int index, const tle6240_config *cfg)
TLE6240 driver add.
Definition tle6240.cpp:450
int tle8888_add(brain_pin_e base, unsigned int index, const tle8888_config *cfg)
TLE8888 driver add.
Definition tle8888.cpp:1228
void tle8888_req_init()
Definition tle8888.cpp:1272