rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
mmc_card.cpp
Go to the documentation of this file.
1/**
2 * @file mmc_card.cpp
3 *
4 * @date Dec 28, 2013
5 * @author Kot_dnz
6 * @author Andrey Belomutskiy, (c) 2012-2020
7 *
8 * default pinouts in case of SPI2 connected to MMC: PB13 - SCK, PB14 - MISO, PB15 - MOSI, PD4 - CS, 3.3v
9 * default pinouts in case of SPI3 connected to MMC: PB3 - SCK, PB4 - MISO, PB5 - MOSI, PD4 - CS, 3.3v
10 *
11 *
12 * todo: extract some logic into a controller file
13 */
14
15#include "pch.h"
16
17#if EFI_FILE_LOGGING
18
19#include "buffered_writer.h"
20#include "status_loop.h"
21#include "binary_mlg_logging.h"
22
23// Divide logs into 32Mb chunks.
24// With this opstion defined SW will pre-allocate file with given size and
25// should not touch FAT structures until file is fully filled
26// This should protect FS from corruption at sudden power loss
27#define LOGGER_MAX_FILE_SIZE (32 * 1024 * 1024)
28
29// at about 20Hz we write about 2Kb per second, looks like we flush once every ~2 seconds
30#define F_SYNC_FREQUENCY 10
31
32static bool sdLoggerReady = false;
33
34#if EFI_PROD_CODE
35
36#include <cstdio>
37#include <cstring>
38#include "mmc_card.h"
39#include "ff.h"
40#include "mmc_card_util.h"
41#include "mass_storage_init.h"
42#include "hellen_meta.h"
43
44#include "rtc_helper.h"
45
46#if EFI_STORAGE_SD == TRUE
47#include "storage_sd.h"
48#endif // EFI_STORAGE_SD
49
50// TODO: do we need this additioal layer of buffering?
51// FIL structure already have buffer of FF_MAX_SS size
52// check if it is better to increase FF_MAX_SS and drop BufferedWriter?
53struct SdLogBufferWriter final : public BufferedWriter<512> {
54 bool failed = false;
55
56 int start(FIL *fd) {
57 if (m_fd) {
58 efiPrintf("SD logger already started!");
59 return -1;
60 }
61
62 totalLoggedBytes = 0;
63 writeCounter = 0;
64
65 m_fd = fd;
66
67 return 0;
68 }
69
70 void stop() {
71 m_fd = nullptr;
72
73 flush();
74
75 totalLoggedBytes = 0;
76 writeCounter = 0;
77 }
78
79 size_t writen() {
80 return totalLoggedBytes;
81 }
82
83 size_t writeInternal(const char* buffer, size_t count) override {
84 if ((!m_fd) || (failed)) {
85 return 0;
86 }
87
88 size_t bytesWritten;
89 efiAssert(ObdCode::CUSTOM_STACK_6627, hasLotsOfRemainingStack(), "sdlow#3", 0);
90 FRESULT err = f_write(m_fd, buffer, count, &bytesWritten);
91
92 if (err) {
93 printFatFsError("log file write", err);
94 failed = true;
95 return 0;
96 } else if (bytesWritten != count) {
97 printFatFsError("log file write partitial", err);
98 failed = true;
99 return 0;
100 } else {
101 writeCounter++;
102 totalLoggedBytes += count;
103 if (writeCounter >= F_SYNC_FREQUENCY) {
104 /**
105 * Performance optimization: not f_sync after each line, f_sync is probably a heavy operation
106 * todo: one day someone should actually measure the relative cost of f_sync
107 */
108 f_sync(m_fd);
109 writeCounter = 0;
110 }
111 }
112
113 return bytesWritten;
114 }
115
116private:
117 FIL *m_fd = nullptr;
118
119 size_t totalLoggedBytes = 0;
120 size_t writeCounter = 0;
121};
122
123#else // not EFI_PROD_CODE (simulator)
124
125#include <fstream>
126
127class SdLogBufferWriter final : public BufferedWriter<512> {
128public:
129 bool failed = false;
130
131 SdLogBufferWriter()
132 : m_stream("rusefi_simulator_log.mlg", std::ios::binary | std::ios::trunc)
133 {
134 sdLoggerReady = true;
135 }
136
137 size_t writeInternal(const char* buffer, size_t count) override {
138 m_stream.write(buffer, count);
139 m_stream.flush();
140 return count;
141 }
142
143private:
144 std::ofstream m_stream;
145};
146
147#endif
148
149static NO_CACHE SdLogBufferWriter logBuffer;
150
151#if EFI_PROD_CODE
152
153// This is dirty workaround to fix compilation without adding this function prototype
154// to error_handling.h file that will also need to add "ff.h" include to same file and
155// cause simulator fail to build.
156extern void errorHandlerWriteReportFile(FIL *fd);
158extern void errorHandlerDeleteReports();
159
171
172// todo: shall we migrate to enum with enum2string for consistency? maybe not until we start reading sdStatus?
173static const char *sdStatusNames[] =
174{
175 "INIT",
176 "MOUNTED",
177 "MOUNT_FAILED",
178 "OPEN_FAILED",
179 "SEEK_FAILED",
180 "NOT_INSERTED",
181 "CONNECTING",
182 "MSD",
183 "MMC_CONNECT_FAILED"
184};
185
186static const char *sdStatusName(SD_STATUS status)
187{
188 return sdStatusNames[status];
189}
190
192
194// by default we want SD card for logs
196
197static bool sdNeedRemoveReports = false;
198
199#define RUSEFI_LOG_PREFIX "re_"
200#define PREFIX_LEN 3
201#define SHORT_TIME_LEN 13
202
203#define FILE_LIST_MAX_COUNT 20
204
205#if HAL_USE_MMC_SPI
206/**
207 * on't re-read SD card spi device after boot - it could change mid transaction (TS thread could preempt),
208 * which will cause disaster (usually multiple-unlock of the same mutex in UNLOCK_SD_SPI)
209 */
210static spi_device_e mmcSpiDevice = SPI_NONE;
211
212/**
213 * MMC driver instance.
214 */
215static NO_CACHE uint8_t mmcbuf[MMC_BUFFER_SIZE];
216MMCDriver MMCD1;
217
218/* MMC/SD over SPI driver configuration.*/
219static MMCConfig mmccfg = {
220 .spip = NULL,
221 .lscfg = &mmc_ls_spicfg,
222 .hscfg = &mmc_hs_spicfg
223};
224
225#if MMC_USE_MUTUAL_EXCLUSION == TRUE
226#define LOCK_SD_SPI()
227#define UNLOCK_SD_SPI()
228#else
229#define LOCK_SD_SPI() lockSpi(mmcSpiDevice)
230#define UNLOCK_SD_SPI() unlockSpi(mmcSpiDevice)
231#endif
232
233#endif /* HAL_USE_MMC_SPI */
234
235/**
236 * fatfs MMC/SPI
237 */
238static NO_CACHE FATFS MMC_FS;
239
240static void sdLoggerSetReady(bool value) {
241 sdLoggerReady = value;
242}
243
244static bool sdLoggerIsReady(void) {
245 return sdLoggerReady;
246}
247
248/* See ff.h FRESULT enum */
249static const char *fatErrors[] = {
250 "FR_OK: Succeeded",
251 "FR_DISK_ERR: A hard error occurred in the low level disk I/O layer",
252 "FR_INT_ERR: Assertion failed",
253 "FR_NOT_READY: The physical drive cannot work",
254 "FR_NO_FILE: Could not find the file",
255 "FR_NO_PATH: Could not find the path",
256 "FR_INVALID_NAME: The path name format is invalid",
257 "FR_DENIED: Access denied due to prohibited access or directory full",
258 "FR_EXIST: Access denied due to prohibited access",
259 "FR_INVALID_OBJECT: The file/directory object is invalid",
260 "FR_WRITE_PROTECTED: The physical drive is write protected",
261 "FR_INVALID_DRIVE: The logical drive number is invalid",
262 "FR_NOT_ENABLED: The volume has no work area",
263 "FR_NO_FILESYSTEM: There is no valid FAT volume",
264 "FR_MKFS_ABORTED: The f_mkfs() aborted due to any problem",
265 "FR_TIMEOUT: Could not get a grant to access the volume within defined period",
266 "FR_LOCKED: The operation is rejected according to the file sharing policy",
267 "FR_NOT_ENOUGH_CORE: LFN working buffer could not be allocated",
268 "FR_TOO_MANY_OPEN_FILES: Number of open files > FF_FS_LOCK",
269 "FR_INVALID_PARAMETER: Given parameter is invalid"
270};
271
272// print FAT error function
273void printFatFsError(const char *str, FRESULT f_error) {
274 static int fatFsErrors = 0;
275
276 if (fatFsErrors++ > 16) {
277 // no reason to spam the console
278 return;
279 }
280
281 efiPrintf("%s FATfs Error %d %s", str, f_error, f_error <= FR_INVALID_PARAMETER ? fatErrors[f_error] : "unknown");
282}
283
284// format, file access and MSD are used exclusively, we can union.
285static union {
286 // Warning: shared between all FS users, please release it after use
287 FIL fd;
288 // TODO: optimal cluster size?
289 #define FATFS_CLUSTER_SIZE 1024
290 BYTE formatBuff[FATFS_CLUSTER_SIZE];
291 // MSD read/write buffer
292 uint8_t blkbuf[4 * MMCSD_BLOCK_SIZE];
293} resources NO_CACHE;
294
295extern int logFileIndex;
296static char logName[_MAX_FILLER + 20];
297
298static void printMmcPinout() {
299#if HAL_USE_MMC_SPI
300 efiPrintf("MMC CS %s", hwPortname(engineConfiguration->sdCardCsPin));
301 // todo: we need to figure out the right SPI pinout, not just SPI2
302// efiPrintf("MMC SCK %s:%d", portname(EFI_SPI2_SCK_PORT), EFI_SPI2_SCK_PIN);
303// efiPrintf("MMC MISO %s:%d", portname(EFI_SPI2_MISO_PORT), EFI_SPI2_MISO_PIN);
304// efiPrintf("MMC MOSI %s:%d", portname(EFI_SPI2_MOSI_PORT), EFI_SPI2_MOSI_PIN);
305#else
306 // not sure if we need to print SDIO pinout
307#endif
308}
309
310static void sdStatistics() {
312 efiPrintf("SD enabled=%s status=%s", boolToString(engineConfiguration->isSdCardEnabled),
314#if HAL_USE_MMC_SPI
316 #if defined(STM32F4XX) || defined(STM32F7XX)
317 efiPrintf("HS clock %d Hz", spiGetBaseClock(mmccfg.spip) / (2 << ((mmc_hs_spicfg.cr1 & SPI_CR1_BR_Msk) >> SPI_CR1_BR_Pos)));
318 efiPrintf("LS clock %d Hz", spiGetBaseClock(mmccfg.spip) / (2 << ((mmc_ls_spicfg.cr1 & SPI_CR1_BR_Msk) >> SPI_CR1_BR_Pos)));
319 #else
320 efiPrintf("not implemented");
321 #endif
322#else
323 efiPrintf("SDIO mode");
324#endif
325 if (sdLoggerIsReady()) {
326 efiPrintf("filename=%s size=%d", logName, logBuffer.writen());
327 }
328#if EFI_FILE_LOGGING
329 efiPrintf("%d SD card fields", MLG::getSdCardFieldsCount());
330#endif
331}
332
333static void sdSetMode(const char *mode) {
334 if (strcmp(mode, "pc") == 0) {
336 } else if (strcmp(mode, "ecu") == 0) {
338 } else {
339 efiPrintf("Invalid mode %s allowed modes pc and ecu", mode);
340 }
341}
342
343static void prepareLogFileName() {
344 strcpy(logName, RUSEFI_LOG_PREFIX);
345 char *ptr;
346
347 // TS SD protocol supports only short 8 symbol file names, good thing that we do not use TS SD protocol!
348 bool result = dateToStringShort(&logName[PREFIX_LEN]);
349
350 if (result) {
351 ptr = &logName[PREFIX_LEN + SHORT_TIME_LEN];
352 } else {
353 ptr = itoa10(&logName[PREFIX_LEN], logFileIndex);
354 }
355
357 strcat(ptr, ".teeth");
358 } else {
359 strcat(ptr, DOT_MLG);
360 }
361}
362
363/**
364 * @brief Create a new file with the specified name
365 *
366 * This function saves the name of the file in a global variable
367 * so that we can later append to that file
368 */
369static int sdLoggerCreateFile(FIL *fd) {
370 // turn off indicator
371 sdLoggerSetReady(false);
372
373 // clear the memory
374 memset(fd, 0, sizeof(FIL));
376
377 efiPrintf("starting log file %s", logName);
378 // Create new file. If file is exist - truncate and overwrite, we need header to be at zero offset.
379 FRESULT err = f_open(fd, logName, FA_CREATE_ALWAYS | FA_WRITE);
380 if (err == FR_EXIST) {
381 err = FR_OK;
382 }
383#if EFI_TUNER_STUDIO
384 // Show error to TS
385 engine->outputChannels.sd_error = (uint8_t)err;
386#endif
387 if (err != FR_OK) {
389 warning(ObdCode::CUSTOM_ERR_SD_MOUNT_FAILED, "SD: file open failed");
390 printFatFsError("log file create", err);
391 return -1;
392 }
393
394#ifdef LOGGER_MAX_FILE_SIZE
395 //pre-allocate data ahead
396 err = f_expand(fd, LOGGER_MAX_FILE_SIZE, /* Find and allocate */ 1);
397 if (err != FR_OK) {
398 printFatFsError("pre-allocate", err);
399 // this is not critical
400 }
401#endif
402
403 // SD logger is ok
404 sdLoggerSetReady(true);
405
406 return 0;
407}
408
409static void sdLoggerCloseFile(FIL *fd)
410{
411#ifdef LOGGER_MAX_FILE_SIZE
412 // truncate file to actual size
413 f_truncate(fd);
414#endif
415
416 // close file
417 f_close(fd);
418
419 // SD logger is inactive
420 sdLoggerSetReady(false);
421}
422
423static void removeFile(const char *pathx) {
424 if (sdMode != SD_MODE_ECU) {
425 efiPrintf("SD card should be mounted to ECU");
426 return;
427 }
428
429 f_unlink(pathx);
430}
431
432#if HAL_USE_USB_MSD
433
434static chibios_rt::BinarySemaphore usbConnectedSemaphore(/* taken =*/ true);
435
439
440#endif /* HAL_USE_USB_MSD */
441
442#if HAL_USE_MMC_SPI
443
449
450/*
451 * Attempts to initialize the MMC card connected over SPI.
452 * Returns a BaseBlockDevice* corresponding to the SD card if successful, otherwise nullptr.
453 */
454static BaseBlockDevice* initializeMmcBlockDevice() {
455 // Configures and activates the MMC peripheral.
457
458 // todo: reuse initSpiCs method?
462
463 // Invalid SPI device, abort.
464 if (!mmccfg.spip) {
465 return nullptr;
466 }
467
468 // max SPI rate is 25 MHz after init
469 spiCalcClockDiv(mmccfg.spip, &mmc_hs_spicfg, 25 * 1000 * 1000);
470 // and 250 KHz during initialization
471 spiCalcClockDiv(mmccfg.spip, &mmc_ls_spicfg, 250 * 1000);
472
473 // We think we have everything for the card, let's try to mount it!
474 mmcObjectInit(&MMCD1, mmcbuf);
475 mmcStart(&MMCD1, &mmccfg);
476
477 // Performs the initialization procedure on the inserted card.
478 LOCK_SD_SPI();
479 if (blkConnect(&MMCD1) != HAL_SUCCESS) {
481 UNLOCK_SD_SPI();
482 return nullptr;
483 }
484 // We intentionally never unlock in case of success, we take exclusive access of that spi device for SD use
485
486 return reinterpret_cast<BaseBlockDevice*>(&MMCD1);
487}
488
490 blkDisconnect(&MMCD1); // Brings the driver in a state safe for card removal.
491 mmcStop(&MMCD1); // Disables the MMC peripheral.
492 UNLOCK_SD_SPI();
493}
494#endif /* HAL_USE_MMC_SPI */
495
496// Some ECUs are wired for SDIO/SDMMC instead of SPI
497#ifdef EFI_SDC_DEVICE
498
499#ifndef RE_SDC_MODE
500 #define RE_SDC_MODE SDC_MODE_4BIT
501#endif // RE_SDC_MODE
502
503static const SDCConfig sdcConfig = {
504 .bus_width = RE_SDC_MODE,
505 .slowdown = 0U
506};
507
508static bool isSdCardEnabled() {
510}
511
512/*
513 * Attempts to initialize the MMC card connected over SDIO.
514 * Returns a BaseBlockDevice* corresponding to the SD card if successful, otherwise nullptr.
515 */
516static BaseBlockDevice* initializeMmcBlockDevice() {
517 sdcStart(&EFI_SDC_DEVICE, &sdcConfig);
518 if (blkConnect(&EFI_SDC_DEVICE) != HAL_SUCCESS) {
519 return nullptr;
520 }
521
522 return reinterpret_cast<BaseBlockDevice*>(&EFI_SDC_DEVICE);
523}
524
525static void deinitializeMmcBlockDevide() {
526 blkDisconnect(&EFI_SDC_DEVICE);
527 sdcStop(&EFI_SDC_DEVICE);
528}
529
530#endif /* EFI_SDC_DEVICE */
531
532#if HAL_USE_USB_MSD
533static bool useMsdMode() {
535 return false;
536 }
537 if (isIgnVoltage()) {
538 // if we have battery voltage let's give priority to logging not reading
539 // this gives us a chance to SD card log cranking
540 return false;
541 }
542 // Wait for the USB stack to wake up, or a 15 second timeout, whichever occurs first
543 msg_t usbResult = usbConnectedSemaphore.wait(TIME_MS2I(15000));
544
545 return usbResult == MSG_OK;
546}
547#endif // HAL_USE_USB_MSD
548
549static BaseBlockDevice* cardBlockDevice = nullptr;
550
551// Initialize SD card.
552static bool initMmc() {
553 // Don't try to mount SD card in case of fatal error - hardware may be in an unexpected state
554 if (hasFirmwareError()) {
555 return false;
556 }
557
559
560#if EFI_TUNER_STUDIO
561 // If not null, card is present
563#endif
564
565 return (cardBlockDevice != nullptr);
566}
567
568static void deinitMmc() {
569 if (cardBlockDevice) {
571 }
572 cardBlockDevice = nullptr;
574}
575
576// Mount the SD card.
577// Returns true if the filesystem was successfully mounted for writing.
578static bool mountMmc() {
579 bool ret = false;
580
581 // if no card, don't try to mount FS
582 if (cardBlockDevice != nullptr) {
583 // clean shared buffer
584 memset(&resources, 0x00, sizeof(resources));
585 // We were able to connect the SD card, mount the filesystem
586 memset(&MMC_FS, 0, sizeof(FATFS));
587 ret = (f_mount(&MMC_FS, "", /* Mount immediately */ 1) == FR_OK);
588
589 if (ret == false) {
591 efiPrintf("SD card mount failed!");
592 }
593 }
594
595 if (ret) {
597 efiPrintf("SD card mounted!");
598 }
599
600#if EFI_STORAGE_SD == TRUE
601 // notificate storage subsystem
603#endif // EFI_STORAGE_SD
604
605#if EFI_TUNER_STUDIO
607#endif
608
609 return ret;
610}
611
612/*
613 * SD card un-mount.
614 * @return true if we had SD card alive
615 */
616static void unmountMmc() {
617 FRESULT ret;
618
619#if EFI_STORAGE_SD == TRUE
620 // notificate storage subsystem
622#endif // EFI_STORAGE_SD
623
624 // FATFS: Unregister work area prior to discard it
625 ret = f_unmount("");
626 if (ret != FR_OK) {
627 printFatFsError("Umount failed", ret);
628 }
629
630#if EFI_TUNER_STUDIO
632#endif
633
634 efiPrintf("SD card unmounted");
635}
636
637#else // not EFI_PROD_CODE (simulator)
638
639bool initMmc() {
640 // Stub so the loop thinks the SD is present
641 return true;
642}
643
644bool mountMmc() {
645 // Stub so the loop thinks the SD mounted OK
646 return true;
647}
648
649#endif // EFI_PROD_CODE
650
651#if EFI_PROD_CODE
652
653// Log 'regular' ECU log to MLG file
654static int mlgLogger();
655
656// Log binary trigger log
657static int sdTriggerLogger();
658
659static bool sdLoggerInitDone = false;
660static bool sdLoggerFailed = false;
661
662static int sdLogger(FIL *fd)
663{
664 int ret = 0;
665
666 if (!sdLoggerInitDone) {
669
670 ret = sdLoggerCreateFile(fd);
671 if (ret == 0) {
672 ret = logBuffer.start(fd);
673 }
674
675 sdLoggerInitDone = true;
676
677 if (ret < 0) {
678 sdLoggerFailed = true;
679 return ret;
680 }
681 }
682
683 if (!sdLoggerFailed) {
685 ret = sdTriggerLogger();
686 } else {
687 ret = mlgLogger();
688 }
689 }
690
691 if (ret < 0) {
692 sdLoggerFailed = true;
693 return ret;
694 }
695
696 if (sdLoggerFailed) {
697 // logger is dead until restart, do not waste CPU
698 chThdSleepMilliseconds(100);
699 return -1;
700 }
701
702#ifdef LOGGER_MAX_FILE_SIZE
703 // check if we need to start next log file
704 // in next write (assume same size as current) will cross LOGGER_MAX_FILE_SIZE boundary
705 // TODO: use f_tell() instead ?
706 if (logBuffer.writen() + ret > LOGGER_MAX_FILE_SIZE) {
707 logBuffer.stop();
709
710 //need to start new file
711 sdLoggerInitDone = false;
712 }
713#endif
714
715 return ret;
716}
717
718static void sdLoggerStart(void)
719{
720 sdLoggerInitDone = false;
721 sdLoggerFailed = false;
722
723#if EFI_TOOTH_LOGGER
724 // TODO: cache this config option untill sdLoggerStop()
727 }
728#endif
729}
730
731static void sdLoggerStop(void)
732{
733 sdLoggerCloseFile(&resources.fd);
734#if EFI_TOOTH_LOGGER
735 // TODO: cache this config option untill sdLoggerStop()
738 }
739#endif
740}
741
742static bool sdFormat()
743{
744#if EFI_TUNER_STUDIO
747#endif
748 //FRESULT ret = f_mkfs("", nullptr, resources.formatBuff, sizeof(resources.formatBuff));
749 FRESULT ret = f_mkfs("", nullptr, resources.formatBuff, sizeof(resources.formatBuff));
750
751 if (ret) {
752 printFatFsError("format failed", ret);
753 warning(ObdCode::CUSTOM_ERR_SD_MOUNT_FAILED, "SD: format failed");
754 goto exit;
755 }
756 ret = f_setlabel(SD_CARD_LABEL);
757 if (ret) {
758 printFatFsError("setlabel failed", ret);
759 // this is not critical
760 ret = FR_OK;
761 }
762
763exit:
764#if EFI_TUNER_STUDIO
766 engine->outputChannels.sd_error = (uint8_t) ret;
767#endif
768
769 return (ret ? false : true);
770}
771
773{
774 switch (from) {
775 case SD_MODE_IDLE:
776 return 0;
777 case SD_MODE_ECU:
778 sdLoggerStop();
779 unmountMmc();
780 return 0;
781 case SD_MODE_PC:
783 return 0;
784 case SD_MODE_UNMOUNT:
785 return 0;
786 case SD_MODE_FORMAT:
787 //not allowed to interrupt formating process
788 return -1;
789 }
790
791 efiPrintf("Invalid SD card thread state: %d", static_cast<int>(from));
792 return -1;
793}
794
795static int sdModeSwitcher()
796{
797 if (sdTargetMode == SD_MODE_IDLE) {
798 return 0;
799 }
800
801 if (sdMode == sdTargetMode) {
802 // already here
804 return 0;
805 }
806
807 if (sdMode != SD_MODE_IDLE) {
808 int ret = sdModeSwitchToIdle(sdMode);
809 if (ret) {
810 return ret;
811 }
813 }
814
815 if (sdMode != SD_MODE_IDLE) {
816 return -1;
817 }
818
819 // Now SD card is in idle state, we can switch into target state
820 switch (sdTargetMode) {
821 case SD_MODE_IDLE:
822 return 0;
823 case SD_MODE_UNMOUNT:
824 // everithing is done in sdModeSwitchToIdle();
827 return 0;
828 case SD_MODE_ECU:
829 if (mountMmc()) {
832 } else {
833 // failed to mount SD card to ECU, go to idle
835 }
837 return 0;
838 case SD_MODE_PC:
839 attachMsdSdCard(cardBlockDevice, resources.blkbuf, sizeof(resources.blkbuf));
843 return 0;
844 case SD_MODE_FORMAT:
845 if (sdFormat()) {
846 // formated ok
847 }
849 // TODO: return to mode that was used before format was requested!
851 return 0;
852 }
853
854 // should not happen
855 return -1;
856}
857
858static int sdModeExecuter()
859{
860 switch (sdMode) {
861 case SD_MODE_IDLE:
862 case SD_MODE_PC:
863 case SD_MODE_UNMOUNT:
864 case SD_MODE_FORMAT:
865 // nothing to do in these state, just sleep
866 chThdSleepMilliseconds(100);
867 return 0;
868 case SD_MODE_ECU:
871 sdNeedRemoveReports = false;
872 }
873 // execute logger
874 return sdLogger(&resources.fd);
875 }
876
877 return 0;
878}
879
881{
882 // write error report file if needed
883 errorHandlerWriteReportFile(&resources.fd);
884
885 // check for any exist reports
887
888 return 0;
889}
890
891PUBLIC_API_WEAK bool boardSdCardEnable() {
892 // assume powered and ready
893 return true;
894}
895
896PUBLIC_API_WEAK bool boardSdCardDisable() {
897 return true;
898}
899
900static THD_WORKING_AREA(mmcThreadStack, 3 * UTILITY_THREAD_STACK_SIZE); // MMC monitor thread
901static THD_FUNCTION(MMCmonThread, arg) {
902 (void)arg;
903
904 chRegSetThreadName("SD Card Logger");
905
906 while (!boardSdCardEnable()) {
907 // wait until board enables peripheral
908 chThdSleepMilliseconds(100);
909 }
910
912 if (!initMmc()) {
913 efiPrintf("Card is not preset/failed to init");
915 // give up until next boot
916 goto die;
917 }
918
919 // Try to mount SD card, drop critical report if needed and check for previously stored reports
920 if (mountMmc()) {
922
924
925#if EFI_STORAGE_SD == TRUE
926 // Give some time for storage manager to load settings from SD
927 chThdSleepMilliseconds(1000);
928#endif
929 }
930
931#if HAL_USE_USB_MSD
932 // Wait for the USB stack to wake up, or a 15 second timeout, whichever occurs first
933 // If we have a device AND USB is connected, mount the card to USB, otherwise
934 // mount the null device and try to mount the filesystem ourselves
935 if (useMsdMode()) {
937 }
938#endif
939
940 while (1) {
943 }
944
945die:
946 // bring SD interface to safe state
947 deinitMmc();
949
950 efiPrintf("SD logger has died!");
951
952 // exiting thread will create zombie!
953 while(1) {
954 chThdSleepMilliseconds(100);
955 }
956}
957
958static int mlgLogger() {
959 // TODO: move this check somewhere out of here!
960 // if the SPI device got un-picked somehow, cancel SD card
961 // Don't do this check at all if using SDMMC interface instead of SPI
962#if EFI_PROD_CODE && !defined(EFI_SDC_DEVICE)
963 if (engineConfiguration->sdCardSpiDevice == SPI_NONE) {
964 return 0;
965 }
966#endif
967
968 systime_t before = chVTGetSystemTime();
969
970 size_t writen = MLG::writeSdLogLine(logBuffer);
971
972 // Something went wrong (already handled), so cancel further writes
973 if (logBuffer.failed) {
974 return -1;
975 }
976
978 if (freq > 250) {
979 freq = 250;
980 } else if (freq < 1) {
981 freq = 1;
982 }
983
984 systime_t period = CH_CFG_ST_FREQUENCY / freq;
985 chThdSleepUntilWindowed(before, before + period);
986
987 return writen;
988}
989
990static int sdTriggerLogger() {
991 size_t toWrite = 0;
992#if EFI_TOOTH_LOGGER
994
995 // can return nullptr
996 if (buffer) {
997 toWrite = buffer->nextIdx * sizeof(composite_logger_s);
998 logBuffer.write(reinterpret_cast<const char*>(buffer->buffer), toWrite);
999 if (logBuffer.failed) {
1000 return -1;
1001 }
1002
1004 }
1005#endif /* EFI_TOOTH_LOGGER */
1006 return toWrite;
1007}
1008
1009#endif // EFI_PROD_CODE
1010
1012#if EFI_PROD_CODE
1013 if (cardBlockDevice) {
1014 engine->outputChannels.sd_active_wr = (blkGetDriverState(cardBlockDevice) == BLK_WRITING);
1015 engine->outputChannels.sd_active_rd = (blkGetDriverState(cardBlockDevice) == BLK_READING);
1016 } else
1017#endif // EFI_PROD_CODE
1018 {
1021 }
1022}
1023
1024// Pre-config load init
1026#if EFI_PROD_CODE
1027 logName[0] = 0;
1028
1029 addConsoleAction("sdinfo", sdStatistics);
1031 addConsoleActionS("sdmode", sdSetMode);
1033 //incLogFileName() use same shared FDLogFile, calling it while FDLogFile is used by log writer will cause damage
1034 //addConsoleAction("incfilename", incLogFileName);
1035#endif // EFI_PROD_CODE
1036}
1037
1039#if EFI_PROD_CODE
1040 if (!isSdCardEnabled()) {
1041 // do not even bother starting the thread if SD card is not enabled & configured on start-up
1042 return;
1043 }
1044 chThdCreateStatic(mmcThreadStack, sizeof(mmcThreadStack), PRIO_MMC, (tfunc_t)(void*) MMCmonThread, NULL);
1045#endif // EFI_PROD_CODE
1046}
1047
1048#if EFI_PROD_CODE
1049
1051{
1052 // Check if SD is not in transition state...
1053 if (sdTargetMode == SD_MODE_IDLE) {
1054 efiPrintf("sdCardRequestMode %d", (int)mode);
1055 sdTargetMode = mode;
1056 }
1057}
1058
1060{
1061 return sdMode;
1062}
1063
1065 if (sdMode != SD_MODE_ECU) {
1066 efiPrintf("SD card should be mounted to ECU");
1067 return;
1068 }
1069
1070 sdNeedRemoveReports = true;
1071}
1072
1073#endif // EFI_PROD_CODE
1074
1075#endif /* EFI_FILE_LOGGING */
int spiCalcClockDiv(SPIDriver *, SPIConfig *, unsigned int)
Definition at32_spi.cpp:260
SPIConfig mmc_hs_spicfg
Definition at32_spi.cpp:273
int spiGetBaseClock(SPIDriver *)
Definition at32_spi.cpp:254
SPIConfig mmc_ls_spicfg
Definition at32_spi.cpp:288
beuint32_t period
size_t flush() override
virtual size_t writeInternal(const char *buffer, size_t count)=0
TunerStudioOutputChannels outputChannels
Definition engine.h:109
void addConsoleActionS(const char *token, VoidCharPtr callback)
void addConsoleAction(const char *token, Void callback)
Register console action without parameters.
ioportid_t getHwPort(const char *msg, brain_pin_e brainPin)
ioportmask_t getHwPin(const char *msg, brain_pin_e brainPin)
const char * boolToString(bool value)
Definition efilib.cpp:19
char * itoa10(char *p, int num)
Definition efilib.cpp:107
static EngineAccessor engine
Definition engine.h:413
static constexpr engine_configuration_s * engineConfiguration
bool warning(ObdCode code, const char *fmt,...)
void printSpiConfig(const char *msg, spi_device_e device)
Definition hardware.cpp:259
SPIDriver * getSpiDevice(spi_device_e spiDevice)
Definition hardware.cpp:152
bool isIgnVoltage()
void deattachMsdSdCard(void)
void attachMsdSdCard(BaseBlockDevice *blkdev, uint8_t *blkbuf, size_t blkbufsize)
static bool useMsdMode()
Definition mmc_card.cpp:533
static THD_FUNCTION(MMCmonThread, arg)
Definition mmc_card.cpp:901
static void unmountMmc()
Definition mmc_card.cpp:616
static bool sdLoggerFailed
Definition mmc_card.cpp:660
static int sdTriggerLogger()
Definition mmc_card.cpp:990
static void sdStatistics()
Definition mmc_card.cpp:310
void initEarlyMmcCard()
PUBLIC_API_WEAK bool boardSdCardEnable()
Definition mmc_card.cpp:891
static void deinitializeMmcBlockDevide()
Definition mmc_card.cpp:489
int errorHandlerCheckReportFiles()
static spi_device_e mmcSpiDevice
Definition mmc_card.cpp:210
static chibios_rt::BinarySemaphore usbConnectedSemaphore(true)
static int sdReportStorageInit()
Definition mmc_card.cpp:880
BYTE formatBuff[FATFS_CLUSTER_SIZE]
Definition mmc_card.cpp:290
static bool sdFormat()
Definition mmc_card.cpp:742
static int sdModeExecuter()
Definition mmc_card.cpp:858
static NO_CACHE SdLogBufferWriter logBuffer
Definition mmc_card.cpp:149
MMCDriver MMCD1
Definition mmc_card.cpp:216
void sdCardRemoveReportFiles()
static bool sdLoggerReady
Definition mmc_card.cpp:32
static bool mountMmc()
Definition mmc_card.cpp:578
static int sdModeSwitcher()
Definition mmc_card.cpp:795
static int sdLogger(FIL *fd)
Definition mmc_card.cpp:662
void updateSdCardLiveFlags()
SD_STATUS
Definition mmc_card.cpp:160
@ SD_STATUS_INIT
Definition mmc_card.cpp:161
@ SD_STATUS_MSD
Definition mmc_card.cpp:168
@ SD_STATUS_MOUNT_FAILED
Definition mmc_card.cpp:163
@ SD_STATUS_CONNECTING
Definition mmc_card.cpp:167
@ SD_STATUS_OPEN_FAILED
Definition mmc_card.cpp:164
@ SD_STATUS_MMC_FAILED
Definition mmc_card.cpp:169
@ SD_STATUS_NOT_INSERTED
Definition mmc_card.cpp:166
@ SD_STATUS_SEEK_FAILED
Definition mmc_card.cpp:165
@ SD_STATUS_MOUNTED
Definition mmc_card.cpp:162
static bool isSdCardEnabled()
Definition mmc_card.cpp:444
void sdCardRequestMode(SD_MODE mode)
static void sdLoggerCloseFile(FIL *fd)
Definition mmc_card.cpp:409
static const char * sdStatusName(SD_STATUS status)
Definition mmc_card.cpp:186
static union @47 NO_CACHE
static THD_WORKING_AREA(mmcThreadStack, 3 *UTILITY_THREAD_STACK_SIZE)
static NO_CACHE uint8_t mmcbuf[MMC_BUFFER_SIZE]
Definition mmc_card.cpp:215
static const char * fatErrors[]
Definition mmc_card.cpp:249
static bool sdNeedRemoveReports
Definition mmc_card.cpp:197
static void deinitMmc()
Definition mmc_card.cpp:568
static int sdModeSwitchToIdle(SD_MODE from)
Definition mmc_card.cpp:772
static const SDCConfig sdcConfig
Definition mmc_card.cpp:503
static SD_STATUS sdStatus
Definition mmc_card.cpp:191
void onUsbConnectedNotifyMmcI()
Definition mmc_card.cpp:436
void errorHandlerDeleteReports()
static MMCConfig mmccfg
Definition mmc_card.cpp:219
static void sdLoggerSetReady(bool value)
Definition mmc_card.cpp:240
static const char * sdStatusNames[]
Definition mmc_card.cpp:173
static void sdSetMode(const char *mode)
Definition mmc_card.cpp:333
SD_MODE sdCardGetCurrentMode(void)
static bool initMmc()
Definition mmc_card.cpp:552
static SD_MODE sdMode
Definition mmc_card.cpp:193
static bool sdLoggerInitDone
Definition mmc_card.cpp:659
static char logName[_MAX_FILLER+20]
Definition mmc_card.cpp:296
void printFatFsError(const char *str, FRESULT f_error)
Definition mmc_card.cpp:273
static void removeFile(const char *pathx)
Definition mmc_card.cpp:423
static void prepareLogFileName()
Definition mmc_card.cpp:343
FIL fd
Definition mmc_card.cpp:287
int logFileIndex
static int sdLoggerCreateFile(FIL *fd)
Create a new file with the specified name.
Definition mmc_card.cpp:369
static int mlgLogger()
Definition mmc_card.cpp:958
PUBLIC_API_WEAK bool boardSdCardDisable()
Definition mmc_card.cpp:896
uint8_t blkbuf[4 *MMCSD_BLOCK_SIZE]
Definition mmc_card.cpp:292
static void sdLoggerStart(void)
Definition mmc_card.cpp:718
static void sdLoggerStop(void)
Definition mmc_card.cpp:731
static SD_MODE sdTargetMode
Definition mmc_card.cpp:195
void errorHandlerWriteReportFile(FIL *fd)
static bool sdLoggerIsReady(void)
Definition mmc_card.cpp:244
static BaseBlockDevice * initializeMmcBlockDevice()
Definition mmc_card.cpp:454
static NO_CACHE FATFS MMC_FS
Definition mmc_card.cpp:238
void initMmcCard()
static BaseBlockDevice * cardBlockDevice
Definition mmc_card.cpp:549
static void printMmcPinout()
Definition mmc_card.cpp:298
SD_MODE
Definition mmc_card.h:16
@ SD_MODE_UNMOUNT
Definition mmc_card.h:20
@ SD_MODE_PC
Definition mmc_card.h:19
@ SD_MODE_ECU
Definition mmc_card.h:18
@ SD_MODE_IDLE
Definition mmc_card.h:17
@ SD_MODE_FORMAT
Definition mmc_card.h:21
void incLogFileName(FIL *fd)
void resetFileLogging()
int getSdCardFieldsCount()
size_t writeSdLogLine(Writer &bufferedWriter)
@ CUSTOM_ERR_SD_MOUNT_FAILED
@ CUSTOM_STACK_6627
const char * hwPortname(brain_pin_e brainPin)
bool isBrainPinValid(brain_pin_e brainPin)
bool dateToStringShort(char *destination)
Real Time Clock helper.
spi_device_e
bool deinitStorageSD()
bool initStorageSD()
static NO_CACHE FIL fd
Storage interface to FatFS header.
void DisableToothLogger()
void EnableToothLogger()
void ReturnToothLoggerBuffer(CompositeBuffer *buffer)
CompositeBuffer * GetToothLoggerBufferBlocking()
composite_logger_s
static BigBufferHandle buffer
uint16_t count
Definition tunerstudio.h:1