rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
hardware.cpp
Go to the documentation of this file.
1/**
2 * @file hardware.cpp
3 * @brief Hardware package entry point
4 *
5 * @date May 27, 2013
6 * @author Andrey Belomutskiy, (c) 2012-2020
7 */
8
9#include "pch.h"
10
11
12#include "trigger_input.h"
13#include "can_hw.h"
14#include "hardware.h"
15#include "rtc_helper.h"
16#include "bench_test.h"
17#include "yaw_rate_sensor.h"
18#include "pin_repository.h"
19#include "logic_analyzer.h"
20#include "smart_gpio.h"
21#include "accelerometer.h"
22#include "eficonsole.h"
23#include "console_io.h"
24#include "idle_thread.h"
25#include "odometer.h"
26#include "kline.h"
27#include "dac.h"
28
29#if EFI_PROD_CODE
30#include "mpu_util.h"
31#endif /* EFI_PROD_CODE */
32
33#include "mmc_card.h"
34
35#include "adc_device.h"
36#include "idle_hardware.h"
37
38#include "histogram.h"
39#include "gps_uart.h"
40#include "sent.h"
41#include "cdm_ion_sense.h"
42#include "trigger_central.h"
43#include "vvt.h"
45#include "boost_control.h"
46#if EFI_SOFTWARE_KNOCK
47#include "software_knock.h"
48#endif
49#include "trigger_scope.h"
50#include "init.h"
51#if EFI_MC33816
52#include "mc33816.h"
53#endif /* EFI_MC33816 */
54#if EFI_WS2812
55#include "WS2812.h"
56#endif /* EFI_WS2812 */
57
58#if EFI_MAP_AVERAGING && defined (MODULE_MAP_AVERAGING)
59#include "map_averaging.h"
60#endif
61
62#if EFI_CONFIGURATION_STORAGE
63#include "flash_main.h"
64#endif
65
66#if HAL_USE_PAL && EFI_PROD_CODE
67#include "digital_input_exti.h"
68#endif // HAL_USE_PAL
69
70#if EFI_CAN_SUPPORT
71#include "can_vss.h"
72#endif
73
74#include "board_overrides.h"
75
76std::optional<setup_custom_board_overrides_type> custom_board_InitHardwareEarly;
77std::optional<setup_custom_board_overrides_type> custom_board_InitHardware;
78std::optional<setup_custom_board_overrides_type> custom_board_InitHardwareExtra;
79
80
81#if HAL_USE_SPI
82/* zero index is SPI_NONE */
83extern bool isSpiInitialized[SPI_TOTAL_COUNT + 1];
84
85/* these are common adapters for engineConfiguration access, move to some common file? */
87 switch(device) {
88 case SPI_DEVICE_1:
90 case SPI_DEVICE_2:
92 case SPI_DEVICE_3:
94 case SPI_DEVICE_4:
96 case SPI_DEVICE_5:
98 case SPI_DEVICE_6:
100 default:
101 break;
102 }
103 return Gpio::Unassigned;
104}
105
107 switch(device) {
108 case SPI_DEVICE_1:
110 case SPI_DEVICE_2:
112 case SPI_DEVICE_3:
114 case SPI_DEVICE_4:
116 case SPI_DEVICE_5:
118 case SPI_DEVICE_6:
120 default:
121 break;
122 }
123 return Gpio::Unassigned;
124}
125
127 switch(device) {
128 case SPI_DEVICE_1:
130 case SPI_DEVICE_2:
132 case SPI_DEVICE_3:
134 case SPI_DEVICE_4:
136 case SPI_DEVICE_5:
138 case SPI_DEVICE_6:
140 default:
141 break;
142 }
143 return Gpio::Unassigned;
144}
145
146/**
147 * @return NULL if SPI device not specified
148 */
149SPIDriver * getSpiDevice(spi_device_e spiDevice) {
150 if (spiDevice == SPI_NONE) {
151 return nullptr;
152 }
153#if STM32_SPI_USE_SPI1
154 if (spiDevice == SPI_DEVICE_1) {
155 return &SPID1;
156 }
157#endif
158#if STM32_SPI_USE_SPI2
159 if (spiDevice == SPI_DEVICE_2) {
160 return &SPID2;
161 }
162#endif
163#if STM32_SPI_USE_SPI3
164 if (spiDevice == SPI_DEVICE_3) {
165 return &SPID3;
166 }
167#endif
168#if STM32_SPI_USE_SPI4
169 if (spiDevice == SPI_DEVICE_4) {
170 return &SPID4;
171 }
172#endif
173#if STM32_SPI_USE_SPI5
174 if (spiDevice == SPI_DEVICE_5) {
175 return &SPID5;
176 }
177#endif
178#if STM32_SPI_USE_SPI6
179 if (spiDevice == SPI_DEVICE_6) {
180 return &SPID6;
181 }
182#endif
183 firmwareError(ObdCode::CUSTOM_ERR_UNEXPECTED_SPI, "Unexpected SPI device: %d", spiDevice);
184 return nullptr;
185}
186
187/**
188 * Only one consumer can use SPI bus at a given time
189 */
191 efiAssertVoid(ObdCode::CUSTOM_STACK_SPI, hasLotsOfRemainingStack(), "lockSpi");
192 spiAcquireBus(getSpiDevice(device));
193}
194
196 spiReleaseBus(getSpiDevice(device));
197}
198
199static void initSpiModules() {
201 turnOnSpi(SPI_DEVICE_1);
202 }
204 turnOnSpi(SPI_DEVICE_2);
205 }
207 turnOnSpi(SPI_DEVICE_3);
208 }
210 turnOnSpi(SPI_DEVICE_4);
211 }
213 turnOnSpi(SPI_DEVICE_5);
214 }
216 turnOnSpi(SPI_DEVICE_6);
217 }
218}
219
221 if (!isSpiInitialized[device]) {
222 return; // not turned on
223 }
224 isSpiInitialized[device] = false;
228}
229
230static void stopSpiModules() {
231 if (isConfigurationChanged(is_enabled_spi_1)) {
232 stopSpi(SPI_DEVICE_1);
233 }
234
235 if (isConfigurationChanged(is_enabled_spi_2)) {
236 stopSpi(SPI_DEVICE_2);
237 }
238
239 if (isConfigurationChanged(is_enabled_spi_3)) {
240 stopSpi(SPI_DEVICE_3);
241 }
242
243 if (isConfigurationChanged(is_enabled_spi_4)) {
244 stopSpi(SPI_DEVICE_4);
245 }
246
247 if (isConfigurationChanged(is_enabled_spi_5)) {
248 stopSpi(SPI_DEVICE_5);
249 }
250
251 if (isConfigurationChanged(is_enabled_spi_6)) {
252 stopSpi(SPI_DEVICE_6);
253 }
254}
255
256void printSpiConfig(const char *msg, spi_device_e device) {
257 efiPrintf("%s %s mosi=%s", msg, getSpi_device_e(device), hwPortname(getMosiPin(device)));
258 efiPrintf("%s %s miso=%s", msg, getSpi_device_e(device), hwPortname(getMisoPin(device)));
259 efiPrintf("%s %s sck=%s", msg, getSpi_device_e(device), hwPortname(getSckPin(device)));
260}
261
262#endif // HAL_USE_SPI
263
264#if HAL_USE_ADC
265
267
268#if HAL_TRIGGER_USE_ADC
270#endif // HAL_TRIGGER_USE_ADC
271
272/**
273 * This method is not in the adc* lower-level file because it is more business logic then hardware.
274 */
277
278#if HAL_TRIGGER_USE_ADC
279 // we need to call this ASAP, because trigger processing is time-critical
281#endif /* HAL_TRIGGER_USE_ADC */
282
283 /**
284 * this callback is executed 10 000 times a second, it needs to be as fast as possible
285 */
286 efiAssertVoid(ObdCode::CUSTOM_STACK_ADC, hasLotsOfRemainingStack(), "lowstck#9b");
287
288 auto mapRaw = adcRawValueToScaledVoltage(getFastAdc(fastMapSampleIndex), engineConfiguration->map.sensor.hwChannel);
290#if EFI_MAP_AVERAGING && defined (MODULE_MAP_AVERAGING)
292#endif /* EFI_MAP_AVERAGING */
293}
294#endif /* HAL_USE_ADC */
295
296static void calcFastAdcIndexes() {
297#if HAL_USE_ADC
299
300#if HAL_TRIGGER_USE_ADC
302#endif /* HAL_TRIGGER_USE_ADC */
303
304#endif/* HAL_USE_ADC */
305}
306
307/**
308 * this method is NOT currently invoked on ECU start
309 * todo: reduce code duplication by moving more logic into startHardware method
310 */
312 /**
313 * All 'stop' methods need to go before we begin starting pins.
314 *
315 * We take settings from 'activeConfiguration' not 'engineConfiguration' while stopping hardware.
316 * Some hardware is restart unconditionally on change of parameters while for some systems we make extra effort and restart only
317 * relevant settings were changes.
318 *
319 */
321
322#if EFI_PROD_CODE
323 stopSensors();
324#endif // EFI_PROD_CODE
325
326#if EFI_PROD_CODE && EFI_SHAFT_POSITION_INPUT
328#endif /* EFI_SHAFT_POSITION_INPUT */
329
330#if EFI_PROD_CODE && EFI_SENT_SUPPORT
331 stopSent();
332#endif // EFI_SENT_SUPPORT
333
334#if EFI_CAN_SUPPORT
335 stopCanPins();
336#endif /* EFI_CAN_SUPPORT */
337
338 stopKLine();
339
340
341 stopHardware();
342
343#if HAL_USE_SPI
345#endif /* HAL_USE_SPI */
346
347 if (isPinOrModeChanged(clutchUpPin, clutchUpPinMode)) {
348 // bug? duplication with stopSwitchPins?
350 }
351
353
354#if EFI_PROD_CODE
356#endif /* EFI_PROD_CODE */
357
359
360 /*******************************************
361 * Start everything back with new settings *
362 ******************************************/
364
365#if EFI_PROD_CODE && (BOARD_EXT_GPIOCHIPS > 0)
366 /* TODO: properly restart gpio chips...
367 * This is only workaround for "CS pin lost" bug
368 * see: https://github.com/rusefi/rusefi/issues/2107
369 * We should provide better way to gracefully stop all
370 * gpio chips: set outputs to safe state, release all
371 * on-chip resources (gpios, SPIs, etc) and then restart
372 * with updated settings.
373 * Following code just re-inits CS pins for all external
374 * gpio chips, but does not update CS pin definition in
375 * gpio chips private data/settings. So changing CS pin
376 * on-fly does not work */
378#endif /* (BOARD_EXT_GPIOCHIPS > 0) */
379
380 startKLine();
381
382#if EFI_PROD_CODE && EFI_IDLE_CONTROL
385 }
386#endif
387
388#if EFI_BOOST_CONTROL
390#endif
391#if EFI_EMULATE_POSITION_SENSORS
393#endif /* EFI_EMULATE_POSITION_SENSORS */
394#if EFI_LOGIC_ANALYZER
396#endif /* EFI_LOGIC_ANALYZER */
397#if EFI_VVT_PID
399#endif /* EFI_VVT_PID */
400
401#if EFI_PROD_CODE && EFI_SENT_SUPPORT
402 startSent();
403#endif
404
406}
407
408#if EFI_PROD_CODE && EFI_BOR_LEVEL
409void setBor(int borValue) {
410 efiPrintf("setting BOR to %d", borValue);
411 BOR_Set((BOR_Level_t)borValue);
412}
413#endif /* EFI_BOR_LEVEL */
414
415// Called before configuration is loaded
417 // forcing migration to custom_board_InitHardwareEarly
418}
420 // time to force migration to custom_board_InitHardware
421}
423 // forcing migration to custom_board_InitHardwareExtra
424}
425
426// This function initializes hardware that can do so before configuration is loaded
428 efiAssertVoid(ObdCode::CUSTOM_IH_STACK, hasLotsOfRemainingStack(), "init h");
429
430 efiPrintf("initHardware()");
431
432#if EFI_PROD_CODE
434#endif
435
436#if EFI_PROD_CODE
439#endif
440
441#if EFI_HISTOGRAMS
442 /**
443 * histograms is a data structure for CPU monitor, it does not depend on configuration
444 */
446#endif /* EFI_HISTOGRAMS */
447
448#if EFI_GPIO_HARDWARE
449 /**
450 * We need the LED_ERROR pin even before we read configuration
451 */
453#endif // EFI_GPIO_HARDWARE
454
455#if EFI_PROD_CODE && EFI_SIGNAL_EXECUTOR_ONE_TIMER
456 // it's important to initialize this pretty early in the game before any scheduling usages
458#endif // EFI_PROD_CODE && EFI_SIGNAL_EXECUTOR_ONE_TIMER
459
460#if EFI_PROD_CODE && EFI_RTC
461 initRtc();
462#endif // EFI_PROD_CODE && EFI_RTC
463
464#if EFI_CONFIGURATION_STORAGE
465 initFlash();
466#endif
467
468#if EFI_FILE_LOGGING
470#endif // EFI_FILE_LOGGING
471
472#if HAL_USE_PAL && EFI_PROD_CODE
473 // this should be initialized before detectBoardType()
474 efiExtiInit();
475#endif // HAL_USE_PAL
476}
477
480
481#if EFI_PROD_CODE && (BOARD_EXT_GPIOCHIPS > 0)
483#endif /* (BOARD_EXT_GPIOCHIPS > 0) */
484
485#if EFI_LOGIC_ANALYZER
487#endif /* EFI_LOGIC_ANALYZER */
488
489#if EFI_EMULATE_POSITION_SENSORS
491#endif /* EFI_EMULATE_POSITION_SENSORS */
492
493#if EFI_VVT_PID
495#endif /* EFI_VVT_PID */
496}
497
498/**
499 * This method is invoked both on ECU start and configuration change
500 * At the moment we have too many system which handle ECU start and configuration change separately
501 * TODO: move move hardware code here
502 */
504#if EFI_SHAFT_POSITION_INPUT
506#endif
507
508#if EFI_PROD_CODE && EFI_SHAFT_POSITION_INPUT
510#endif /* EFI_SHAFT_POSITION_INPUT */
511
512#if EFI_ENGINE_CONTROL
514#endif /* EFI_ENGINE_CONTROL */
515
516#if EFI_SHAFT_POSITION_INPUT
518
519#endif // EFI_SHAFT_POSITION_INPUT
520
522
523#if EFI_CAN_SUPPORT
524 startCanPins();
525#endif /* EFI_CAN_SUPPORT */
526}
527
528PUBLIC_API_WEAK void setPinConfigurationOverrides() { }
529
530#if HAL_USE_I2C
531const I2CConfig i2cfg = {
532 OPMODE_I2C,
533 400000,
534 FAST_DUTY_CYCLE_2,
535};
536#endif
537
539 if (hasFirmwareError()) {
540 return;
541 }
542
543#if EFI_PROD_CODE && STM32_I2C_USE_I2C3
545 i2cStart(&EE_U2CD, &i2cfg);
546 }
547#endif // STM32_I2C_USE_I2C3
548
551#if EFI_PROD_CODE
552 // this applies some board configurations
554#endif // EFI_PROD_CODE
557
558#if HAL_USE_ADC
560#endif /* HAL_USE_ADC */
561
562#if EFI_SOFTWARE_KNOCK
564#endif /* EFI_SOFTWARE_KNOCK */
565
566#ifdef TRIGGER_SCOPE
568#endif // TRIGGER_SCOPE
569
570#if HAL_USE_SPI
572#endif /* HAL_USE_SPI */
573
574#if (EFI_PROD_CODE && BOARD_EXT_GPIOCHIPS > 0) || EFI_SIMULATOR
575 // initSmartGpio depends on 'initSpiModules'
577#endif
578
579 // output pins potentially depend on 'initSmartGpio'
581
582#if EFI_MC33816
583 initMc33816();
584#endif /* EFI_MC33816 */
585
586#if EFI_CAN_SUPPORT
587#if EFI_SIMULATOR
588 // Set CAN device name
589 CAND1.deviceName = "can0";
590#endif
591
592 initCan();
593#endif /* EFI_CAN_SUPPORT */
594
595
596#if EFI_PROD_CODE && EFI_SHAFT_POSITION_INPUT
598#endif /* EFI_SHAFT_POSITION_INPUT */
600
601#if EFI_WS2812
602 initWS2812();
603#endif /* EFI_LED_WS2812 */
604
605#if EFI_ONBOARD_MEMS
607#endif
608
609#if EFI_BOSCH_YAW
611#endif /* EFI_BOSCH_YAW */
612
613#if EFI_UART_GPS
614 initGps();
615#endif
616
617#if EFI_CAN_SUPPORT
619#endif // EFI_CAN_SUPPORT
620
621#if EFI_CDM_INTEGRATION
622 cdmIonInit();
623#endif // EFI_CDM_INTEGRATION
624
625#if EFI_PROD_CODE && EFI_SENT_SUPPORT
626 initSent();
627#endif
628
629 initKLine();
630
631#if EFI_DAC
632 initDac();
633#endif
634
636
638
639 efiPrintf("initHardware() OK!");
640}
void initWS2812()
Definition WS2812.cpp:21
void initAccelerometer()
void initAdcInputs()
AdcToken enableFastAdcChannel(const char *msg, adc_channel_e channel)
Definition mpu_util.cpp:279
adcsample_t getFastAdc(AdcToken token)
Definition mpu_util.cpp:288
uint32_t AdcToken
Definition adc_inputs.h:98
BOR_Result_t BOR_Set(BOR_Level_t BORValue)
const char * getSpi_device_e(spi_device_e value)
Utility methods related to bench testing.
static bool call_board_override(std::optional< setup_custom_board_overrides_type > board_override)
void startBoostPin()
void stopCanPins()
Definition can_hw.cpp:114
void initCan()
Definition can_hw.cpp:166
void startCanPins()
Definition can_hw.cpp:122
void initCanVssSupport()
Definition can_vss.cpp:199
void cdmIonInit(void)
static void startConfigurationList()
Definition debounce.cpp:49
static void stopConfigurationList()
Definition debounce.cpp:39
TunerStudioOutputChannels outputChannels
Definition engine.h:109
void startPins()
Definition efi_gpio.cpp:258
void unregisterPins()
Definition efi_gpio.cpp:228
@ Unassigned
BOR_Level_t
void initDac()
Definition dac.cpp:42
void efiExtiInit()
void initPrimaryPins()
Definition efi_gpio.cpp:842
EnginePins enginePins
Definition efi_gpio.cpp:24
void initMiscOutputPins()
Definition efi_gpio.cpp:690
Console package entry point header.
static EngineAccessor engine
Definition engine.h:413
engine_configuration_s & activeConfiguration
static constexpr engine_configuration_s * engineConfiguration
void initStartStopButton()
void firmwareError(ObdCode code, const char *fmt,...)
void initFlash()
void initGps(void)
Definition gps_uart.cpp:102
uint16_t adcsample_t
ADC sample data type.
SPIDriver SPID1
SPI0 driver identifier.
Definition hal_spi_lld.c:42
SPIDriver SPID2
SPI1 driver identifier.
Definition hal_spi_lld.c:47
void boardInitHardwareExtra()
Definition hardware.cpp:422
void unlockSpi(spi_device_e device)
Definition hardware.cpp:195
static AdcToken triggerSampleIndex
Definition hardware.cpp:269
static void calcFastAdcIndexes()
Definition hardware.cpp:296
static AdcToken fastMapSampleIndex
Definition hardware.cpp:266
std::optional< setup_custom_board_overrides_type > custom_board_InitHardware
Definition hardware.cpp:77
static void initSpiModules()
Definition hardware.cpp:199
void stopHardware()
Definition hardware.cpp:478
const I2CConfig i2cfg
Definition hardware.cpp:531
void initHardwareNoConfig()
Definition hardware.cpp:427
brain_pin_e getSckPin(spi_device_e device)
Definition hardware.cpp:126
void stopSpi(spi_device_e device)
Definition hardware.cpp:220
void boardInitHardwareEarly()
Definition hardware.cpp:416
void initHardware()
Definition hardware.cpp:538
void printSpiConfig(const char *msg, spi_device_e device)
Definition hardware.cpp:256
bool isSpiInitialized[SPI_TOTAL_COUNT+1]
Definition at32_spi.cpp:13
void startHardware()
Definition hardware.cpp:503
brain_pin_e getMosiPin(spi_device_e device)
Definition hardware.cpp:106
PUBLIC_API_WEAK void setPinConfigurationOverrides()
Definition hardware.cpp:528
SPIDriver * getSpiDevice(spi_device_e spiDevice)
Definition hardware.cpp:149
std::optional< setup_custom_board_overrides_type > custom_board_InitHardwareExtra
Definition hardware.cpp:78
static void stopSpiModules()
Definition hardware.cpp:230
void onFastAdcComplete(adcsample_t *)
Definition hardware.cpp:275
void setBor(int borValue)
Definition hardware.cpp:409
void lockSpi(spi_device_e device)
Definition hardware.cpp:190
brain_pin_e getMisoPin(spi_device_e device)
Definition hardware.cpp:86
std::optional< setup_custom_board_overrides_type > custom_board_InitHardwareEarly
Definition hardware.cpp:76
void boardInitHardware()
Definition hardware.cpp:419
void applyNewHardwareSettings()
Definition hardware.cpp:311
void turnOnSpi(spi_device_e device)
Definition at32_spi.cpp:151
void boardOnConfigurationChange(engine_configuration_s *)
void initHistogramsModule(void)
Definition histogram.cpp:44
This data structure is used to analyze CPU performance.
Idle Air Control valve hardware.
bool isIdleHardwareRestartNeeded()
void initIdleHardware()
Idle Valve Control thread.
void stopSwitchPins()
void startSwitchPins()
void reconfigureSensors()
void stopSensors()
static Lps25 device
Definition init_baro.cpp:4
void efiSetPadUnused(brain_pin_e brainPin)
Definition io_pins.cpp:20
void stopKLine()
Definition kline.cpp:184
void startKLine()
Definition kline.cpp:157
void initKLine()
Definition kline.cpp:198
void stopLogicAnalyzerPins()
void startLogicAnalyzerPins()
void mapAveragingAdcCallback(float instantVoltage)
void initMc33816()
Definition mc33816.cpp:280
void initEarlyMmcCard()
@ CUSTOM_ERR_UNEXPECTED_SPI
@ CUSTOM_STACK_SPI
@ CUSTOM_IH_STACK
@ CUSTOM_STACK_ADC
@ AdcCallbackFast
void initPinRepository(void)
const char * hwPortname(brain_pin_e brainPin)
I/O pin registry header.
void initRtc()
Real Time Clock helper.
spi_device_e
void initSent(void)
Definition sent.cpp:167
void stopSent()
void startSent()
void initSingleTimerExecutorHardware()
void startSmartCsPins()
void initSmartGpio()
void stopSmartCsPins()
void initSoftwareKnock()
scaled_channel< uint16_t, 1000, 1 > rawMapFast
void validateTriggerInputs()
void startTriggerEmulatorPins()
void stopTriggerEmulatorPins()
void stopTriggerInputPins()
void onEcuStartTriggerImplementation()
void onEcuStartDoSomethingTriggerInputPins()
void startTriggerInputPins()
Position sensor hardware layer.
void triggerAdcCallback(triggerAdcSample_t value)
adc_channel_e getAdcChannelForTrigger(void)
void initTriggerScope()
void stopVvtControlPins()
Definition vvt.cpp:186
void startVvtControlPins()
Definition vvt.cpp:180
void initBoschYawRateSensor()