Line data Source code
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 "sensor_chart.h"
25 : #include "serial_hw.h"
26 : #include "idle_thread.h"
27 : #include "odometer.h"
28 : #include "kline.h"
29 : #include "dac.h"
30 :
31 : #if EFI_PROD_CODE
32 : #include "mpu_util.h"
33 : #endif /* EFI_PROD_CODE */
34 :
35 : #include "mmc_card.h"
36 :
37 : #include "AdcDevice.h"
38 : #include "idle_hardware.h"
39 : #include "mcp3208.h"
40 : #include "hip9011.h"
41 : #include "histogram.h"
42 : #include "gps_uart.h"
43 : #include "sent.h"
44 : #include "cdm_ion_sense.h"
45 : #include "trigger_central.h"
46 : #include "vvt.h"
47 : #include "trigger_emulator_algo.h"
48 : #include "boost_control.h"
49 : #include "software_knock.h"
50 : #include "trigger_scope.h"
51 : #include "init.h"
52 : #if EFI_MC33816
53 : #include "mc33816.h"
54 : #endif /* EFI_MC33816 */
55 : #if EFI_WS2812
56 : #include "WS2812.h"
57 : #endif /* EFI_WS2812 */
58 :
59 : #if EFI_MAP_AVERAGING
60 : #include "map_averaging.h"
61 : #endif
62 :
63 : #if EFI_CONFIGURATION_STORAGE
64 : #include "flash_main.h"
65 : #endif
66 :
67 : #if HAL_USE_PAL && EFI_PROD_CODE
68 : #include "digital_input_exti.h"
69 : #endif // HAL_USE_PAL
70 :
71 : #if EFI_CAN_SUPPORT
72 : #include "can_vss.h"
73 : #endif
74 :
75 : #if HAL_USE_SPI
76 : /* zero index is SPI_NONE */
77 : extern bool isSpiInitialized[SPI_TOTAL_COUNT + 1];
78 :
79 : /* these are common adapters for engineConfiguration access, move to some common file? */
80 : brain_pin_e getMisoPin(spi_device_e device) {
81 : switch(device) {
82 : case SPI_DEVICE_1:
83 : return engineConfiguration->spi1misoPin;
84 : case SPI_DEVICE_2:
85 : return engineConfiguration->spi2misoPin;
86 : case SPI_DEVICE_3:
87 : return engineConfiguration->spi3misoPin;
88 : case SPI_DEVICE_4:
89 : return engineConfiguration->spi4misoPin;
90 : case SPI_DEVICE_5:
91 : return engineConfiguration->spi5misoPin;
92 : case SPI_DEVICE_6:
93 : return engineConfiguration->spi6misoPin;
94 : default:
95 : break;
96 : }
97 : return Gpio::Unassigned;
98 : }
99 :
100 : brain_pin_e getMosiPin(spi_device_e device) {
101 : switch(device) {
102 : case SPI_DEVICE_1:
103 : return engineConfiguration->spi1mosiPin;
104 : case SPI_DEVICE_2:
105 : return engineConfiguration->spi2mosiPin;
106 : case SPI_DEVICE_3:
107 : return engineConfiguration->spi3mosiPin;
108 : case SPI_DEVICE_4:
109 : return engineConfiguration->spi4mosiPin;
110 : case SPI_DEVICE_5:
111 : return engineConfiguration->spi5mosiPin;
112 : case SPI_DEVICE_6:
113 : return engineConfiguration->spi6mosiPin;
114 : default:
115 : break;
116 : }
117 : return Gpio::Unassigned;
118 : }
119 :
120 : brain_pin_e getSckPin(spi_device_e device) {
121 : switch(device) {
122 : case SPI_DEVICE_1:
123 : return engineConfiguration->spi1sckPin;
124 : case SPI_DEVICE_2:
125 : return engineConfiguration->spi2sckPin;
126 : case SPI_DEVICE_3:
127 : return engineConfiguration->spi3sckPin;
128 : case SPI_DEVICE_4:
129 : return engineConfiguration->spi4sckPin;
130 : case SPI_DEVICE_5:
131 : return engineConfiguration->spi5sckPin;
132 : case SPI_DEVICE_6:
133 : return engineConfiguration->spi6sckPin;
134 : default:
135 : break;
136 : }
137 : return Gpio::Unassigned;
138 : }
139 :
140 : /**
141 : * @return NULL if SPI device not specified
142 : */
143 : SPIDriver * getSpiDevice(spi_device_e spiDevice) {
144 : if (spiDevice == SPI_NONE) {
145 : return NULL;
146 : }
147 : #if STM32_SPI_USE_SPI1
148 : if (spiDevice == SPI_DEVICE_1) {
149 : return &SPID1;
150 : }
151 : #endif
152 : #if STM32_SPI_USE_SPI2
153 : if (spiDevice == SPI_DEVICE_2) {
154 : return &SPID2;
155 : }
156 : #endif
157 : #if STM32_SPI_USE_SPI3
158 : if (spiDevice == SPI_DEVICE_3) {
159 : return &SPID3;
160 : }
161 : #endif
162 : #if STM32_SPI_USE_SPI4
163 : if (spiDevice == SPI_DEVICE_4) {
164 : return &SPID4;
165 : }
166 : #endif
167 : #if STM32_SPI_USE_SPI5
168 : if (spiDevice == SPI_DEVICE_5) {
169 : return &SPID5;
170 : }
171 : #endif
172 : #if STM32_SPI_USE_SPI6
173 : if (spiDevice == SPI_DEVICE_6) {
174 : return &SPID6;
175 : }
176 : #endif
177 : firmwareError(ObdCode::CUSTOM_ERR_UNEXPECTED_SPI, "Unexpected SPI device: %d", spiDevice);
178 : return NULL;
179 : }
180 :
181 : /**
182 : * Only one consumer can use SPI bus at a given time
183 : */
184 : void lockSpi(spi_device_e device) {
185 : efiAssertVoid(ObdCode::CUSTOM_STACK_SPI, hasLotsOfRemainingStack(), "lockSpi");
186 : spiAcquireBus(getSpiDevice(device));
187 : }
188 :
189 : void unlockSpi(spi_device_e device) {
190 : spiReleaseBus(getSpiDevice(device));
191 : }
192 :
193 : static void initSpiModules() {
194 : if (engineConfiguration->is_enabled_spi_1) {
195 : turnOnSpi(SPI_DEVICE_1);
196 : }
197 : if (engineConfiguration->is_enabled_spi_2) {
198 : turnOnSpi(SPI_DEVICE_2);
199 : }
200 : if (engineConfiguration->is_enabled_spi_3) {
201 : turnOnSpi(SPI_DEVICE_3);
202 : }
203 : if (engineConfiguration->is_enabled_spi_4) {
204 : turnOnSpi(SPI_DEVICE_4);
205 : }
206 : if (engineConfiguration->is_enabled_spi_5) {
207 : turnOnSpi(SPI_DEVICE_5);
208 : }
209 : if (engineConfiguration->is_enabled_spi_6) {
210 : turnOnSpi(SPI_DEVICE_6);
211 : }
212 : }
213 :
214 : void stopSpi(spi_device_e device) {
215 : if (!isSpiInitialized[device]) {
216 : return; // not turned on
217 : }
218 : isSpiInitialized[device] = false;
219 : efiSetPadUnused(getSckPin(device));
220 : efiSetPadUnused(getMisoPin(device));
221 : efiSetPadUnused(getMosiPin(device));
222 : }
223 :
224 : static void stopSpiModules() {
225 : if (isConfigurationChanged(is_enabled_spi_1)) {
226 : stopSpi(SPI_DEVICE_1);
227 : }
228 :
229 : if (isConfigurationChanged(is_enabled_spi_2)) {
230 : stopSpi(SPI_DEVICE_2);
231 : }
232 :
233 : if (isConfigurationChanged(is_enabled_spi_3)) {
234 : stopSpi(SPI_DEVICE_3);
235 : }
236 :
237 : if (isConfigurationChanged(is_enabled_spi_4)) {
238 : stopSpi(SPI_DEVICE_4);
239 : }
240 :
241 : if (isConfigurationChanged(is_enabled_spi_5)) {
242 : stopSpi(SPI_DEVICE_5);
243 : }
244 :
245 : if (isConfigurationChanged(is_enabled_spi_6)) {
246 : stopSpi(SPI_DEVICE_6);
247 : }
248 : }
249 :
250 : void printSpiConfig(const char *msg, spi_device_e device) {
251 : efiPrintf("%s %s mosi=%s", msg, getSpi_device_e(device), hwPortname(getMosiPin(device)));
252 : efiPrintf("%s %s miso=%s", msg, getSpi_device_e(device), hwPortname(getMisoPin(device)));
253 : efiPrintf("%s %s sck=%s", msg, getSpi_device_e(device), hwPortname(getSckPin(device)));
254 : }
255 :
256 : #endif // HAL_USE_SPI
257 :
258 : #if HAL_USE_ADC
259 :
260 : static AdcToken fastMapSampleIndex;
261 : static AdcToken hipSampleIndex;
262 :
263 : #if HAL_TRIGGER_USE_ADC
264 : static AdcToken triggerSampleIndex;
265 : #endif // HAL_TRIGGER_USE_ADC
266 :
267 : #ifdef FAST_ADC_SKIP
268 : // No reason to enable if N = 1
269 : static_assert(FAST_ADC_SKIP > 1);
270 : static size_t fastAdcSkipCount = 0;
271 : #endif // FAST_ADC_SKIP
272 :
273 : /**
274 : * This method is not in the adc* lower-level file because it is more business logic then hardware.
275 : */
276 : void onFastAdcComplete(adcsample_t*) {
277 : ScopePerf perf(PE::AdcCallbackFast);
278 :
279 : #if HAL_TRIGGER_USE_ADC
280 : // we need to call this ASAP, because trigger processing is time-critical
281 : triggerAdcCallback(getFastAdc(triggerSampleIndex));
282 : #endif /* HAL_TRIGGER_USE_ADC */
283 :
284 : #ifdef FAST_ADC_SKIP
285 : // If we run the fast ADC _very_ fast for triggerAdcCallback's benefit, we may want to
286 : // skip most of the samples for the rest of the callback.
287 : if (fastAdcSkipCount++ == FAST_ADC_SKIP) {
288 : fastAdcSkipCount = 0;
289 : } else {
290 : return;
291 : }
292 : #endif
293 :
294 : /**
295 : * this callback is executed 10 000 times a second, it needs to be as fast as possible
296 : */
297 : efiAssertVoid(ObdCode::CUSTOM_STACK_ADC, hasLotsOfRemainingStack(), "lowstck#9b");
298 :
299 : #if EFI_SENSOR_CHART && EFI_SHAFT_POSITION_INPUT
300 : if (getEngineState()->sensorChartMode == SC_AUX_FAST1) {
301 : float voltage = getAdcValue("fAux1", engineConfiguration->auxFastSensor1_adcChannel);
302 : scAddData(engine->triggerCentral.getCurrentEnginePhase(getTimeNowNt()).value_or(0), voltage);
303 : }
304 : #endif /* EFI_SENSOR_CHART */
305 :
306 : #if EFI_MAP_AVERAGING
307 : mapAveragingAdcCallback(adcToVoltsDivided(getFastAdc(fastMapSampleIndex), engineConfiguration->map.sensor.hwChannel));
308 : #endif /* EFI_MAP_AVERAGING */
309 : #if EFI_HIP_9011
310 : if (engineConfiguration->isHip9011Enabled) {
311 : hipAdcCallback(adcToVoltsDivided(getFastAdc(hipSampleIndex), engineConfiguration->hipOutputChannel));
312 : }
313 : #endif /* EFI_HIP_9011 */
314 : }
315 : #endif /* HAL_USE_ADC */
316 :
317 514 : static void calcFastAdcIndexes() {
318 : #if HAL_USE_ADC
319 : fastMapSampleIndex = enableFastAdcChannel("Fast MAP", engineConfiguration->map.sensor.hwChannel);
320 : hipSampleIndex = enableFastAdcChannel("HIP9011", engineConfiguration->hipOutputChannel);
321 : #if HAL_TRIGGER_USE_ADC
322 : triggerSampleIndex = enableFastAdcChannel("Trigger ADC", getAdcChannelForTrigger());
323 : #endif /* HAL_TRIGGER_USE_ADC */
324 :
325 : #endif/* HAL_USE_ADC */
326 514 : }
327 :
328 161 : static void adcConfigListener() {
329 : // todo: something is not right here - looks like should be a callback for each configuration change?
330 161 : calcFastAdcIndexes();
331 161 : }
332 :
333 : /**
334 : * this method is NOT currently invoked on ECU start
335 : * todo: reduce code duplication by moving more logic into startHardware method
336 : */
337 :
338 161 : void applyNewHardwareSettings() {
339 : /**
340 : * All 'stop' methods need to go before we begin starting pins.
341 : *
342 : * We take settings from 'activeConfiguration' not 'engineConfiguration' while stopping hardware.
343 : * Some hardware is restart unconditionally on change of parameters while for some systems we make extra effort and restart only
344 : * relevant settings were changes.
345 : *
346 : */
347 161 : ButtonDebounce::stopConfigurationList();
348 :
349 : #if EFI_PROD_CODE
350 : stopSensors();
351 : #endif // EFI_PROD_CODE
352 :
353 : #if EFI_PROD_CODE && EFI_SHAFT_POSITION_INPUT
354 : stopTriggerInputPins();
355 : #endif /* EFI_SHAFT_POSITION_INPUT */
356 :
357 : #if EFI_SENT_SUPPORT
358 : stopSent();
359 : #endif // EFI_SENT_SUPPORT
360 :
361 : #if EFI_CAN_SUPPORT
362 : stopCanPins();
363 : #endif /* EFI_CAN_SUPPORT */
364 :
365 161 : stopKLine();
366 :
367 : #if EFI_AUX_SERIAL
368 : stopAuxSerialPins();
369 : #endif /* EFI_AUX_SERIAL */
370 :
371 : #if EFI_HIP_9011
372 : stopHip9011_pins();
373 : #endif /* EFI_HIP_9011 */
374 :
375 161 : stopHardware();
376 :
377 : #if HAL_USE_SPI
378 : stopSpiModules();
379 : #endif /* HAL_USE_SPI */
380 :
381 161 : if (isPinOrModeChanged(clutchUpPin, clutchUpPinMode)) {
382 : // bug? duplication with stopSwitchPins?
383 0 : efiSetPadUnused(activeConfiguration.clutchUpPin);
384 : }
385 :
386 : #if EFI_SHAFT_POSITION_INPUT
387 161 : stopTriggerDebugPins();
388 : #endif // EFI_SHAFT_POSITION_INPUT
389 :
390 161 : enginePins.unregisterPins();
391 :
392 : #if EFI_PROD_CODE
393 : reconfigureSensors();
394 : #endif /* EFI_PROD_CODE */
395 :
396 161 : ButtonDebounce::startConfigurationList();
397 :
398 : /*******************************************
399 : * Start everything back with new settings *
400 : ******************************************/
401 161 : startHardware();
402 :
403 : #if EFI_PROD_CODE && (BOARD_EXT_GPIOCHIPS > 0)
404 : /* TODO: properly restart gpio chips...
405 : * This is only workaround for "CS pin lost" bug
406 : * see: https://github.com/rusefi/rusefi/issues/2107
407 : * We should provide better way to gracefully stop all
408 : * gpio chips: set outputs to safe state, release all
409 : * on-chip resources (gpios, SPIs, etc) and then restart
410 : * with updated settings.
411 : * Following code just re-inits CS pins for all external
412 : * gpio chips, but does not update CS pin definition in
413 : * gpio chips private data/settings. So changing CS pin
414 : * on-fly does not work */
415 : startSmartCsPins();
416 : #endif /* (BOARD_EXT_GPIOCHIPS > 0) */
417 :
418 : #if EFI_AUX_SERIAL
419 : startAuxSerialPins();
420 : #endif /* EFI_AUX_SERIAL */
421 :
422 161 : startKLine();
423 :
424 :
425 : #if EFI_HIP_9011
426 : startHip9011_pins();
427 : #endif /* EFI_HIP_9011 */
428 :
429 :
430 : #if EFI_PROD_CODE && EFI_IDLE_CONTROL
431 : if (isIdleHardwareRestartNeeded()) {
432 : initIdleHardware();
433 : }
434 : #endif
435 :
436 : #if EFI_BOOST_CONTROL
437 161 : startBoostPin();
438 : #endif
439 : #if EFI_EMULATE_POSITION_SENSORS
440 161 : startTriggerEmulatorPins();
441 : #endif /* EFI_EMULATE_POSITION_SENSORS */
442 : #if EFI_LOGIC_ANALYZER
443 : startLogicAnalyzerPins();
444 : #endif /* EFI_LOGIC_ANALYZER */
445 : #if EFI_VVT_PID
446 : startVvtControlPins();
447 : #endif /* EFI_VVT_PID */
448 :
449 : #if EFI_SENT_SUPPORT
450 : startSent();
451 : #endif
452 :
453 161 : adcConfigListener();
454 161 : }
455 :
456 : #if EFI_PROD_CODE && EFI_BOR_LEVEL
457 : void setBor(int borValue) {
458 : efiPrintf("setting BOR to %d", borValue);
459 : BOR_Set((BOR_Level_t)borValue);
460 : }
461 : #endif /* EFI_BOR_LEVEL */
462 :
463 : // This function initializes hardware that can do so before configuration is loaded
464 0 : void initHardwareNoConfig() {
465 : efiAssertVoid(ObdCode::CUSTOM_IH_STACK, hasLotsOfRemainingStack(), "init h");
466 :
467 0 : efiPrintf("initHardware()");
468 :
469 : #if EFI_PROD_CODE
470 : initPinRepository();
471 : #endif
472 :
473 : #if EFI_HISTOGRAMS
474 : /**
475 : * histograms is a data structure for CPU monitor, it does not depend on configuration
476 : */
477 : initHistogramsModule();
478 : #endif /* EFI_HISTOGRAMS */
479 :
480 : #if EFI_GPIO_HARDWARE
481 : /**
482 : * We need the LED_ERROR pin even before we read configuration
483 : */
484 0 : initPrimaryPins();
485 : #endif // EFI_GPIO_HARDWARE
486 :
487 : #if EFI_PROD_CODE && EFI_SIGNAL_EXECUTOR_ONE_TIMER
488 : // it's important to initialize this pretty early in the game before any scheduling usages
489 : initSingleTimerExecutorHardware();
490 : #endif // EFI_PROD_CODE && EFI_SIGNAL_EXECUTOR_ONE_TIMER
491 :
492 : #if EFI_PROD_CODE && EFI_RTC
493 : initRtc();
494 : #endif // EFI_PROD_CODE && EFI_RTC
495 :
496 : #if EFI_CONFIGURATION_STORAGE
497 : initFlash();
498 : #endif
499 :
500 : #if EFI_FILE_LOGGING
501 : initEarlyMmcCard();
502 : #endif // EFI_FILE_LOGGING
503 :
504 : #if HAL_USE_PAL && EFI_PROD_CODE
505 : // this should be initialized before detectBoardType()
506 : efiExtiInit();
507 : #endif // HAL_USE_PAL
508 : }
509 :
510 161 : void stopHardware() {
511 161 : stopSwitchPins();
512 :
513 : #if EFI_PROD_CODE && (BOARD_EXT_GPIOCHIPS > 0)
514 : stopSmartCsPins();
515 : #endif /* (BOARD_EXT_GPIOCHIPS > 0) */
516 :
517 : #if EFI_LOGIC_ANALYZER
518 : stopLogicAnalyzerPins();
519 : #endif /* EFI_LOGIC_ANALYZER */
520 :
521 : #if EFI_EMULATE_POSITION_SENSORS
522 161 : stopTriggerEmulatorPins();
523 : #endif /* EFI_EMULATE_POSITION_SENSORS */
524 :
525 : #if EFI_VVT_PID
526 : stopVvtControlPins();
527 : #endif /* EFI_VVT_PID */
528 161 : }
529 :
530 : /**
531 : * This method is invoked both on ECU start and configuration change
532 : * At the moment we have too many system which handle ECU start and configuration change separately
533 : * TODO: move move hardware code here
534 : */
535 514 : void startHardware() {
536 : #if EFI_SHAFT_POSITION_INPUT
537 514 : initStartStopButton();
538 : #endif
539 :
540 : #if EFI_PROD_CODE && EFI_SHAFT_POSITION_INPUT
541 : startTriggerInputPins();
542 : #endif /* EFI_SHAFT_POSITION_INPUT */
543 :
544 : #if EFI_ENGINE_CONTROL
545 514 : enginePins.startPins();
546 : #endif /* EFI_ENGINE_CONTROL */
547 :
548 : #if EFI_SHAFT_POSITION_INPUT
549 514 : validateTriggerInputs();
550 :
551 514 : startTriggerDebugPins();
552 :
553 : #endif // EFI_SHAFT_POSITION_INPUT
554 :
555 514 : startSwitchPins();
556 :
557 : #if EFI_CAN_SUPPORT
558 : startCanPins();
559 : #endif /* EFI_CAN_SUPPORT */
560 514 : }
561 :
562 : // Weak link a stub so that every board doesn't have to implement this function
563 353 : PUBLIC_API_WEAK void boardInitHardware() { }
564 353 : PUBLIC_API_WEAK void boardInitHardwareExtra() { }
565 :
566 0 : PUBLIC_API_WEAK void setPinConfigurationOverrides() { }
567 :
568 : #if HAL_USE_I2C
569 : const I2CConfig i2cfg = {
570 : OPMODE_I2C,
571 : 400000,
572 : FAST_DUTY_CYCLE_2,
573 : };
574 : #endif
575 :
576 353 : void initHardware() {
577 353 : if (hasFirmwareError()) {
578 0 : return;
579 : }
580 :
581 : #if EFI_PROD_CODE && STM32_I2C_USE_I2C3
582 : if (engineConfiguration->useEeprom) {
583 : i2cStart(&EE_U2CD, &i2cfg);
584 : }
585 : #endif // STM32_I2C_USE_I2C3
586 :
587 353 : boardInitHardware();
588 353 : boardInitHardwareExtra();
589 :
590 : #if HAL_USE_ADC
591 : initAdcInputs();
592 :
593 : // wait for first set of ADC values so that we do not produce invalid sensor data
594 : waitForSlowAdc();
595 : #endif /* HAL_USE_ADC */
596 :
597 : #if EFI_SOFTWARE_KNOCK
598 : initSoftwareKnock();
599 : #endif /* EFI_SOFTWARE_KNOCK */
600 :
601 : #ifdef TRIGGER_SCOPE
602 : initTriggerScope();
603 : #endif // TRIGGER_SCOPE
604 :
605 : #if HAL_USE_SPI
606 : initSpiModules();
607 : #endif /* HAL_USE_SPI */
608 :
609 : #if (EFI_PROD_CODE && BOARD_EXT_GPIOCHIPS > 0) || EFI_SIMULATOR
610 : // initSmartGpio depends on 'initSpiModules'
611 : initSmartGpio();
612 : #endif
613 :
614 : // output pins potentially depend on 'initSmartGpio'
615 353 : initMiscOutputPins();
616 :
617 : #if EFI_MC33816
618 : initMc33816();
619 : #endif /* EFI_MC33816 */
620 :
621 : #if EFI_CAN_SUPPORT
622 : #if EFI_SIMULATOR
623 : // Set CAN device name
624 : CAND1.deviceName = "can0";
625 : #endif
626 :
627 : initCan();
628 : #endif /* EFI_CAN_SUPPORT */
629 :
630 :
631 : #if EFI_PROD_CODE && EFI_SHAFT_POSITION_INPUT
632 : onEcuStartTriggerImplementation();
633 : #endif /* EFI_SHAFT_POSITION_INPUT */
634 353 : onEcuStartDoSomethingTriggerInputPins();
635 :
636 : #if EFI_HIP_9011
637 : initHip9011();
638 : #endif /* EFI_HIP_9011 */
639 :
640 : #if EFI_WS2812
641 : initWS2812();
642 : #endif /* EFI_LED_WS2812 */
643 :
644 : #if EFI_ONBOARD_MEMS
645 : initAccelerometer();
646 : #endif
647 :
648 : #if EFI_BOSCH_YAW
649 : initBoschYawRateSensor();
650 : #endif /* EFI_BOSCH_YAW */
651 :
652 : #if EFI_UART_GPS
653 : initGps();
654 : #endif
655 :
656 : #if EFI_AUX_SERIAL
657 : initAuxSerial();
658 : #endif /* EFI_AUX_SERIAL */
659 :
660 : #if EFI_CAN_SUPPORT
661 : initCanVssSupport();
662 : #endif // EFI_CAN_SUPPORT
663 :
664 : #if EFI_CDM_INTEGRATION
665 : cdmIonInit();
666 : #endif // EFI_CDM_INTEGRATION
667 :
668 : #if EFI_SENT_SUPPORT
669 : initSent();
670 : #endif
671 :
672 353 : initKLine();
673 :
674 : #if EFI_DAC
675 : initDac();
676 : #endif
677 :
678 353 : calcFastAdcIndexes();
679 :
680 353 : startHardware();
681 :
682 353 : efiPrintf("initHardware() OK!");
683 : }
684 :
685 : #if HAL_USE_SPI
686 : // this is F4 implementation but we will keep it here for now for simplicity
687 : int getSpiPrescaler(spi_speed_e speed, spi_device_e device) {
688 : switch (speed) {
689 : case _5MHz:
690 : return device == SPI_DEVICE_1 ? SPI_BaudRatePrescaler_16 : SPI_BaudRatePrescaler_8;
691 : case _2_5MHz:
692 : return device == SPI_DEVICE_1 ? SPI_BaudRatePrescaler_32 : SPI_BaudRatePrescaler_16;
693 : case _1_25MHz:
694 : return device == SPI_DEVICE_1 ? SPI_BaudRatePrescaler_64 : SPI_BaudRatePrescaler_32;
695 :
696 : case _150KHz:
697 : // SPI1 does not support 150KHz, it would be 300KHz for SPI1
698 : return SPI_BaudRatePrescaler_256;
699 : default:
700 : // unexpected
701 : return 0;
702 : }
703 : }
704 :
705 : #endif /* HAL_USE_SPI */
706 :
707 0 : void checkLastResetCause() {
708 : #if EFI_PROD_CODE
709 : Reset_Cause_t cause = getMCUResetCause();
710 : const char *causeStr = getMCUResetCause(cause);
711 : efiPrintf("Last Reset Cause: %s", causeStr);
712 :
713 : // if reset by watchdog, signal a fatal error
714 : if (cause == Reset_Cause_IWatchdog || cause == Reset_Cause_WWatchdog) {
715 : firmwareError(ObdCode::OBD_PCM_Processor_Fault, "Watchdog Reset");
716 : }
717 : #endif // EFI_PROD_CODE
718 0 : }
|