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/**
200 * on't re-read SD card spi device after boot - it could change mid transaction (TS thread could preempt),
201 * which will cause disaster (usually multiple-unlock of the same mutex in UNLOCK_SD_SPI)
202 */
203static spi_device_e mmcSpiDevice = SPI_NONE;
204
205#define RUSEFI_LOG_PREFIX "re_"
206#define PREFIX_LEN 3
207#define SHORT_TIME_LEN 13
208
209#define FILE_LIST_MAX_COUNT 20
210
211#if HAL_USE_MMC_SPI
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 efiPrintf("MMC CS %s", hwPortname(engineConfiguration->sdCardCsPin));
300 // todo: we need to figure out the right SPI pinout, not just SPI2
301// efiPrintf("MMC SCK %s:%d", portname(EFI_SPI2_SCK_PORT), EFI_SPI2_SCK_PIN);
302// efiPrintf("MMC MISO %s:%d", portname(EFI_SPI2_MISO_PORT), EFI_SPI2_MISO_PIN);
303// efiPrintf("MMC MOSI %s:%d", portname(EFI_SPI2_MOSI_PORT), EFI_SPI2_MOSI_PIN);
304}
305
306static void sdStatistics() {
308 efiPrintf("SD enabled=%s status=%s", boolToString(engineConfiguration->isSdCardEnabled),
311#if HAL_USE_MMC_SPI && (defined(STM32F4XX) || defined(STM32F7XX))
312 efiPrintf("HS clock %d Hz", spiGetBaseClock(mmccfg.spip) / (2 << ((mmc_hs_spicfg.cr1 & SPI_CR1_BR_Msk) >> SPI_CR1_BR_Pos)));
313 efiPrintf("LS clock %d Hz", spiGetBaseClock(mmccfg.spip) / (2 << ((mmc_ls_spicfg.cr1 & SPI_CR1_BR_Msk) >> SPI_CR1_BR_Pos)));
314#endif
315 if (sdLoggerIsReady()) {
316 efiPrintf("filename=%s size=%d", logName, logBuffer.writen());
317 }
318#if EFI_FILE_LOGGING
319 efiPrintf("%d SD card fields", MLG::getSdCardFieldsCount());
320#endif
321}
322
323static void sdSetMode(const char *mode) {
324 if (strcmp(mode, "pc") == 0) {
326 } else if (strcmp(mode, "ecu") == 0) {
328 } else {
329 efiPrintf("Invalid mode %s allowed modes pc and ecu", mode);
330 }
331}
332
333static void prepareLogFileName() {
334 strcpy(logName, RUSEFI_LOG_PREFIX);
335 char *ptr;
336
337 // TS SD protocol supports only short 8 symbol file names, good thing that we do not use TS SD protocol!
338 bool result = dateToStringShort(&logName[PREFIX_LEN]);
339
340 if (result) {
341 ptr = &logName[PREFIX_LEN + SHORT_TIME_LEN];
342 } else {
343 ptr = itoa10(&logName[PREFIX_LEN], logFileIndex);
344 }
345
347 strcat(ptr, ".teeth");
348 } else {
349 strcat(ptr, DOT_MLG);
350 }
351}
352
353/**
354 * @brief Create a new file with the specified name
355 *
356 * This function saves the name of the file in a global variable
357 * so that we can later append to that file
358 */
359static int sdLoggerCreateFile(FIL *fd) {
360 // turn off indicator
361 sdLoggerSetReady(false);
362
363 // clear the memory
364 memset(fd, 0, sizeof(FIL));
366
367 efiPrintf("starting log file %s", logName);
368 // Create new file. If file is exist - truncate and overwrite, we need header to be at zero offset.
369 FRESULT err = f_open(fd, logName, FA_CREATE_ALWAYS | FA_WRITE);
370 if (err == FR_EXIST) {
371 err = FR_OK;
372 }
373#if EFI_TUNER_STUDIO
374 // Show error to TS
375 engine->outputChannels.sd_error = (uint8_t)err;
376#endif
377 if (err != FR_OK) {
379 warning(ObdCode::CUSTOM_ERR_SD_MOUNT_FAILED, "SD: file open failed");
380 printFatFsError("log file create", err);
381 return -1;
382 }
383
384#ifdef LOGGER_MAX_FILE_SIZE
385 //pre-allocate data ahead
386 err = f_expand(fd, LOGGER_MAX_FILE_SIZE, /* Find and allocate */ 1);
387 if (err != FR_OK) {
388 printFatFsError("pre-allocate", err);
389 // this is not critical
390 }
391#endif
392
393 // SD logger is ok
394 sdLoggerSetReady(true);
395
396 return 0;
397}
398
399static void sdLoggerCloseFile(FIL *fd)
400{
401#ifdef LOGGER_MAX_FILE_SIZE
402 // truncate file to actual size
403 f_truncate(fd);
404#endif
405
406 // close file
407 f_close(fd);
408
409 // SD logger is inactive
410 sdLoggerSetReady(false);
411}
412
413static void removeFile(const char *pathx) {
414 if (sdMode != SD_MODE_ECU) {
415 efiPrintf("SD card should be mounted to ECU");
416 return;
417 }
418
419 f_unlink(pathx);
420}
421
422#if HAL_USE_USB_MSD
423
424static chibios_rt::BinarySemaphore usbConnectedSemaphore(/* taken =*/ true);
425
429
430#endif /* HAL_USE_USB_MSD */
431
432#if HAL_USE_MMC_SPI
433
439
440/*
441 * Attempts to initialize the MMC card connected over SPI.
442 * Returns a BaseBlockDevice* corresponding to the SD card if successful, otherwise nullptr.
443 */
444static BaseBlockDevice* initializeMmcBlockDevice() {
445 // Configures and activates the MMC peripheral.
447
448 // todo: reuse initSpiCs method?
452
453 // Invalid SPI device, abort.
454 if (!mmccfg.spip) {
455 return nullptr;
456 }
457
458 // max SPI rate is 25 MHz after init
459 spiCalcClockDiv(mmccfg.spip, &mmc_hs_spicfg, 25 * 1000 * 1000);
460 // and 250 KHz during initialization
461 spiCalcClockDiv(mmccfg.spip, &mmc_ls_spicfg, 250 * 1000);
462
463 // We think we have everything for the card, let's try to mount it!
464 mmcObjectInit(&MMCD1, mmcbuf);
465 mmcStart(&MMCD1, &mmccfg);
466
467 // Performs the initialization procedure on the inserted card.
468 LOCK_SD_SPI();
469 if (blkConnect(&MMCD1) != HAL_SUCCESS) {
471 UNLOCK_SD_SPI();
472 return nullptr;
473 }
474 // We intentionally never unlock in case of success, we take exclusive access of that spi device for SD use
475
476 return reinterpret_cast<BaseBlockDevice*>(&MMCD1);
477}
478
480 blkDisconnect(&MMCD1); // Brings the driver in a state safe for card removal.
481 mmcStop(&MMCD1); // Disables the MMC peripheral.
482 UNLOCK_SD_SPI();
483}
484#endif /* HAL_USE_MMC_SPI */
485
486// Some ECUs are wired for SDIO/SDMMC instead of SPI
487#ifdef EFI_SDC_DEVICE
488
489#ifndef RE_SDC_MODE
490 #define RE_SDC_MODE SDC_MODE_4BIT
491#endif // RE_SDC_MODE
492
493static const SDCConfig sdcConfig = {
494 .bus_width = RE_SDC_MODE,
495 .slowdown = 0U
496};
497
498static bool isSdCardEnabled() {
500}
501
502/*
503 * Attempts to initialize the MMC card connected over SDIO.
504 * Returns a BaseBlockDevice* corresponding to the SD card if successful, otherwise nullptr.
505 */
506static BaseBlockDevice* initializeMmcBlockDevice() {
507 sdcStart(&EFI_SDC_DEVICE, &sdcConfig);
508 if (blkConnect(&EFI_SDC_DEVICE) != HAL_SUCCESS) {
509 return nullptr;
510 }
511
512 return reinterpret_cast<BaseBlockDevice*>(&EFI_SDC_DEVICE);
513}
514
515static void deinitializeMmcBlockDevide() {
516 blkDisconnect(&EFI_SDC_DEVICE);
517 sdcStop(&EFI_SDC_DEVICE);
518}
519
520#endif /* EFI_SDC_DEVICE */
521
522#if HAL_USE_USB_MSD
523static bool useMsdMode() {
525 return false;
526 }
527 if (isIgnVoltage()) {
528 // if we have battery voltage let's give priority to logging not reading
529 // this gives us a chance to SD card log cranking
530 return false;
531 }
532 // Wait for the USB stack to wake up, or a 15 second timeout, whichever occurs first
533 msg_t usbResult = usbConnectedSemaphore.wait(TIME_MS2I(15000));
534
535 return usbResult == MSG_OK;
536}
537#endif // HAL_USE_USB_MSD
538
539static BaseBlockDevice* cardBlockDevice = nullptr;
540
541// Initialize SD card.
542static bool initMmc() {
543 // Don't try to mount SD card in case of fatal error - hardware may be in an unexpected state
544 if (hasFirmwareError()) {
545 return false;
546 }
547
549
550#if EFI_TUNER_STUDIO
551 // If not null, card is present
553#endif
554
555 return (cardBlockDevice != nullptr);
556}
557
558static void deinitMmc() {
559 if (cardBlockDevice) {
561 }
562 cardBlockDevice = nullptr;
564}
565
566// Mount the SD card.
567// Returns true if the filesystem was successfully mounted for writing.
568static bool mountMmc() {
569 bool ret = false;
570
571 // if no card, don't try to mount FS
572 if (cardBlockDevice != nullptr) {
573 // clean shared buffer
574 memset(&resources, 0x00, sizeof(resources));
575 // We were able to connect the SD card, mount the filesystem
576 memset(&MMC_FS, 0, sizeof(FATFS));
577 ret = (f_mount(&MMC_FS, "", /* Mount immediately */ 1) == FR_OK);
578
579 if (ret == false) {
581 efiPrintf("SD card mount failed!");
582 }
583 }
584
585 if (ret) {
587 efiPrintf("SD card mounted!");
588 }
589
590#if EFI_STORAGE_SD == TRUE
591 // notificate storage subsystem
593#endif // EFI_STORAGE_SD
594
595#if EFI_TUNER_STUDIO
597#endif
598
599 return ret;
600}
601
602/*
603 * SD card un-mount.
604 * @return true if we had SD card alive
605 */
606static void unmountMmc() {
607 FRESULT ret;
608
609#if EFI_STORAGE_SD == TRUE
610 // notificate storage subsystem
612#endif // EFI_STORAGE_SD
613
614 // FATFS: Unregister work area prior to discard it
615 ret = f_unmount("");
616 if (ret != FR_OK) {
617 printFatFsError("Umount failed", ret);
618 }
619
620#if EFI_TUNER_STUDIO
622#endif
623
624 efiPrintf("SD card unmounted");
625}
626
627#else // not EFI_PROD_CODE (simulator)
628
629bool initMmc() {
630 // Stub so the loop thinks the SD is present
631 return true;
632}
633
634bool mountMmc() {
635 // Stub so the loop thinks the SD mounted OK
636 return true;
637}
638
639#endif // EFI_PROD_CODE
640
641#if EFI_PROD_CODE
642
643// Log 'regular' ECU log to MLG file
644static int mlgLogger();
645
646// Log binary trigger log
647static int sdTriggerLogger();
648
649static bool sdLoggerInitDone = false;
650static bool sdLoggerFailed = false;
651
652static int sdLogger(FIL *fd)
653{
654 int ret = 0;
655
656 if (!sdLoggerInitDone) {
659
660 ret = sdLoggerCreateFile(fd);
661 if (ret == 0) {
662 ret = logBuffer.start(fd);
663 }
664
665 sdLoggerInitDone = true;
666
667 if (ret < 0) {
668 sdLoggerFailed = true;
669 return ret;
670 }
671 }
672
673 if (!sdLoggerFailed) {
675 ret = sdTriggerLogger();
676 } else {
677 ret = mlgLogger();
678 }
679 }
680
681 if (ret < 0) {
682 sdLoggerFailed = true;
683 return ret;
684 }
685
686 if (sdLoggerFailed) {
687 // logger is dead until restart, do not waste CPU
688 chThdSleepMilliseconds(100);
689 return -1;
690 }
691
692#ifdef LOGGER_MAX_FILE_SIZE
693 // check if we need to start next log file
694 // in next write (assume same size as current) will cross LOGGER_MAX_FILE_SIZE boundary
695 // TODO: use f_tell() instead ?
696 if (logBuffer.writen() + ret > LOGGER_MAX_FILE_SIZE) {
697 logBuffer.stop();
699
700 //need to start new file
701 sdLoggerInitDone = false;
702 }
703#endif
704
705 return ret;
706}
707
708static void sdLoggerStart(void)
709{
710 sdLoggerInitDone = false;
711 sdLoggerFailed = false;
712
713#if EFI_TOOTH_LOGGER
714 // TODO: cache this config option untill sdLoggerStop()
717 }
718#endif
719}
720
721static void sdLoggerStop(void)
722{
723 sdLoggerCloseFile(&resources.fd);
724#if EFI_TOOTH_LOGGER
725 // TODO: cache this config option untill sdLoggerStop()
728 }
729#endif
730}
731
732static bool sdFormat()
733{
734#if EFI_TUNER_STUDIO
737#endif
738 //FRESULT ret = f_mkfs("", nullptr, resources.formatBuff, sizeof(resources.formatBuff));
739 FRESULT ret = f_mkfs("", nullptr, resources.formatBuff, sizeof(resources.formatBuff));
740
741 if (ret) {
742 printFatFsError("format failed", ret);
743 warning(ObdCode::CUSTOM_ERR_SD_MOUNT_FAILED, "SD: format failed");
744 goto exit;
745 }
746 ret = f_setlabel(SD_CARD_LABEL);
747 if (ret) {
748 printFatFsError("setlabel failed", ret);
749 // this is not critical
750 ret = FR_OK;
751 }
752
753exit:
754#if EFI_TUNER_STUDIO
756 engine->outputChannels.sd_error = (uint8_t) ret;
757#endif
758
759 return (ret ? false : true);
760}
761
763{
764 switch (from) {
765 case SD_MODE_IDLE:
766 return 0;
767 case SD_MODE_ECU:
768 sdLoggerStop();
769 unmountMmc();
770 return 0;
771 case SD_MODE_PC:
773 return 0;
774 case SD_MODE_UNMOUNT:
775 return 0;
776 case SD_MODE_FORMAT:
777 //not allowed to interrupt formating process
778 return -1;
779 }
780
781 efiPrintf("Invalid SD card thread state: %d", static_cast<int>(from));
782 return -1;
783}
784
785static int sdModeSwitcher()
786{
787 if (sdTargetMode == SD_MODE_IDLE) {
788 return 0;
789 }
790
791 if (sdMode == sdTargetMode) {
792 // already here
794 return 0;
795 }
796
797 if (sdMode != SD_MODE_IDLE) {
798 int ret = sdModeSwitchToIdle(sdMode);
799 if (ret) {
800 return ret;
801 }
803 }
804
805 if (sdMode != SD_MODE_IDLE) {
806 return -1;
807 }
808
809 // Now SD card is in idle state, we can switch into target state
810 switch (sdTargetMode) {
811 case SD_MODE_IDLE:
812 return 0;
813 case SD_MODE_UNMOUNT:
814 // everithing is done in sdModeSwitchToIdle();
817 return 0;
818 case SD_MODE_ECU:
819 if (mountMmc()) {
822 } else {
823 // failed to mount SD card to ECU, go to idle
825 }
827 return 0;
828 case SD_MODE_PC:
829 attachMsdSdCard(cardBlockDevice, resources.blkbuf, sizeof(resources.blkbuf));
833 return 0;
834 case SD_MODE_FORMAT:
835 if (sdFormat()) {
836 // formated ok
837 }
839 // TODO: return to mode that was used before format was requested!
841 return 0;
842 }
843
844 // should not happen
845 return -1;
846}
847
848static int sdModeExecuter()
849{
850 switch (sdMode) {
851 case SD_MODE_IDLE:
852 case SD_MODE_PC:
853 case SD_MODE_UNMOUNT:
854 case SD_MODE_FORMAT:
855 // nothing to do in these state, just sleep
856 chThdSleepMilliseconds(100);
857 return 0;
858 case SD_MODE_ECU:
861 sdNeedRemoveReports = false;
862 }
863 // execute logger
864 return sdLogger(&resources.fd);
865 }
866
867 return 0;
868}
869
871{
872 // write error report file if needed
873 errorHandlerWriteReportFile(&resources.fd);
874
875 // check for any exist reports
877
878 return 0;
879}
880
881PUBLIC_API_WEAK bool boardSdCardEnable() {
882 // assume powered and ready
883 return true;
884}
885
886PUBLIC_API_WEAK bool boardSdCardDisable() {
887 return true;
888}
889
890static THD_WORKING_AREA(mmcThreadStack, 3 * UTILITY_THREAD_STACK_SIZE); // MMC monitor thread
891static THD_FUNCTION(MMCmonThread, arg) {
892 (void)arg;
893
894 chRegSetThreadName("SD Card Logger");
895
896 while (!boardSdCardEnable()) {
897 // wait until board enables peripheral
898 chThdSleepMilliseconds(100);
899 }
900
902 if (!initMmc()) {
903 efiPrintf("Card is not preset/failed to init");
905 // give up until next boot
906 goto die;
907 }
908
909 // Try to mount SD card, drop critical report if needed and check for previously stored reports
910 if (mountMmc()) {
912
914
915#if EFI_STORAGE_SD == TRUE
916 // Give some time for storage manager to load settings from SD
917 chThdSleepMilliseconds(1000);
918#endif
919 }
920
921#if HAL_USE_USB_MSD
922 // Wait for the USB stack to wake up, or a 15 second timeout, whichever occurs first
923 // If we have a device AND USB is connected, mount the card to USB, otherwise
924 // mount the null device and try to mount the filesystem ourselves
925 if (useMsdMode()) {
927 }
928#endif
929
930 while (1) {
933 }
934
935die:
936 // bring SD interface to safe state
937 deinitMmc();
939
940 efiPrintf("SD logger has died!");
941
942 // exiting thread will create zombie!
943 while(1) {
944 chThdSleepMilliseconds(100);
945 }
946}
947
948static int mlgLogger() {
949 // TODO: move this check somewhere out of here!
950 // if the SPI device got un-picked somehow, cancel SD card
951 // Don't do this check at all if using SDMMC interface instead of SPI
952#if EFI_PROD_CODE && !defined(EFI_SDC_DEVICE)
953 if (engineConfiguration->sdCardSpiDevice == SPI_NONE) {
954 return 0;
955 }
956#endif
957
958 systime_t before = chVTGetSystemTime();
959
960 size_t writen = MLG::writeSdLogLine(logBuffer);
961
962 // Something went wrong (already handled), so cancel further writes
963 if (logBuffer.failed) {
964 return -1;
965 }
966
968 if (freq > 250) {
969 freq = 250;
970 } else if (freq < 1) {
971 freq = 1;
972 }
973
974 systime_t period = CH_CFG_ST_FREQUENCY / freq;
975 chThdSleepUntilWindowed(before, before + period);
976
977 return writen;
978}
979
980static int sdTriggerLogger() {
981 size_t toWrite = 0;
982#if EFI_TOOTH_LOGGER
984
985 // can return nullptr
986 if (buffer) {
987 toWrite = buffer->nextIdx * sizeof(composite_logger_s);
988 logBuffer.write(reinterpret_cast<const char*>(buffer->buffer), toWrite);
989 if (logBuffer.failed) {
990 return -1;
991 }
992
994 }
995#endif /* EFI_TOOTH_LOGGER */
996 return toWrite;
997}
998
999#endif // EFI_PROD_CODE
1000
1002#if EFI_PROD_CODE
1003 if (cardBlockDevice) {
1004 engine->outputChannels.sd_active_wr = (blkGetDriverState(cardBlockDevice) == BLK_WRITING);
1005 engine->outputChannels.sd_active_rd = (blkGetDriverState(cardBlockDevice) == BLK_READING);
1006 } else
1007#endif // EFI_PROD_CODE
1008 {
1011 }
1012}
1013
1014// Pre-config load init
1016#if EFI_PROD_CODE
1017 logName[0] = 0;
1018
1019 addConsoleAction("sdinfo", sdStatistics);
1021 addConsoleActionS("sdmode", sdSetMode);
1023 //incLogFileName() use same shared FDLogFile, calling it while FDLogFile is used by log writer will cause damage
1024 //addConsoleAction("incfilename", incLogFileName);
1025#endif // EFI_PROD_CODE
1026}
1027
1029#if EFI_PROD_CODE
1030 if (!isSdCardEnabled()) {
1031 // do not even bother starting the thread if SD card is not enabled & configured on start-up
1032 return;
1033 }
1034 chThdCreateStatic(mmcThreadStack, sizeof(mmcThreadStack), PRIO_MMC, (tfunc_t)(void*) MMCmonThread, NULL);
1035#endif // EFI_PROD_CODE
1036}
1037
1038#if EFI_PROD_CODE
1039
1041{
1042 // Check if SD is not in transition state...
1043 if (sdTargetMode == SD_MODE_IDLE) {
1044 efiPrintf("sdCardRequestMode %d", (int)mode);
1045 sdTargetMode = mode;
1046 }
1047}
1048
1050{
1051 return sdMode;
1052}
1053
1055 if (sdMode != SD_MODE_ECU) {
1056 efiPrintf("SD card should be mounted to ECU");
1057 return;
1058 }
1059
1060 sdNeedRemoveReports = true;
1061}
1062
1063#endif // EFI_PROD_CODE
1064
1065#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:256
SPIDriver * getSpiDevice(spi_device_e spiDevice)
Definition hardware.cpp:149
bool isIgnVoltage()
void deattachMsdSdCard(void)
void attachMsdSdCard(BaseBlockDevice *blkdev, uint8_t *blkbuf, size_t blkbufsize)
static bool useMsdMode()
Definition mmc_card.cpp:523
static THD_FUNCTION(MMCmonThread, arg)
Definition mmc_card.cpp:891
static void unmountMmc()
Definition mmc_card.cpp:606
static bool sdLoggerFailed
Definition mmc_card.cpp:650
static int sdTriggerLogger()
Definition mmc_card.cpp:980
static void sdStatistics()
Definition mmc_card.cpp:306
void initEarlyMmcCard()
PUBLIC_API_WEAK bool boardSdCardEnable()
Definition mmc_card.cpp:881
static void deinitializeMmcBlockDevide()
Definition mmc_card.cpp:479
int errorHandlerCheckReportFiles()
static spi_device_e mmcSpiDevice
Definition mmc_card.cpp:203
static chibios_rt::BinarySemaphore usbConnectedSemaphore(true)
static int sdReportStorageInit()
Definition mmc_card.cpp:870
BYTE formatBuff[FATFS_CLUSTER_SIZE]
Definition mmc_card.cpp:290
static bool sdFormat()
Definition mmc_card.cpp:732
static int sdModeExecuter()
Definition mmc_card.cpp:848
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:568
static int sdModeSwitcher()
Definition mmc_card.cpp:785
static int sdLogger(FIL *fd)
Definition mmc_card.cpp:652
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:434
void sdCardRequestMode(SD_MODE mode)
static void sdLoggerCloseFile(FIL *fd)
Definition mmc_card.cpp:399
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:558
static int sdModeSwitchToIdle(SD_MODE from)
Definition mmc_card.cpp:762
static const SDCConfig sdcConfig
Definition mmc_card.cpp:493
static SD_STATUS sdStatus
Definition mmc_card.cpp:191
void onUsbConnectedNotifyMmcI()
Definition mmc_card.cpp:426
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:323
SD_MODE sdCardGetCurrentMode(void)
static bool initMmc()
Definition mmc_card.cpp:542
static SD_MODE sdMode
Definition mmc_card.cpp:193
static bool sdLoggerInitDone
Definition mmc_card.cpp:649
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:413
static void prepareLogFileName()
Definition mmc_card.cpp:333
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:359
static int mlgLogger()
Definition mmc_card.cpp:948
PUBLIC_API_WEAK bool boardSdCardDisable()
Definition mmc_card.cpp:886
uint8_t blkbuf[4 *MMCSD_BLOCK_SIZE]
Definition mmc_card.cpp:292
static void sdLoggerStart(void)
Definition mmc_card.cpp:708
static void sdLoggerStop(void)
Definition mmc_card.cpp:721
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:444
static NO_CACHE FATFS MMC_FS
Definition mmc_card.cpp:238
void initMmcCard()
static BaseBlockDevice * cardBlockDevice
Definition mmc_card.cpp:539
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