2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @file mmc_card.cpp
|
|
|
|
*
|
|
|
|
* @date Dec 28, 2013
|
|
|
|
* @author Kot_dnz
|
2020-01-13 18:57:43 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
2015-07-10 06:01:56 -07:00
|
|
|
*
|
|
|
|
* default pinouts in case of SPI2 connected to MMC: PB13 - SCK, PB14 - MISO, PB15 - MOSI, PD4 - CS, 3.3v
|
|
|
|
* default pinouts in case of SPI3 connected to MMC: PB3 - SCK, PB4 - MISO, PB5 - MOSI, PD4 - CS, 3.3v
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* todo: extract some logic into a controller file
|
|
|
|
*/
|
|
|
|
|
2021-08-03 19:05:01 -07:00
|
|
|
#include "pch.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-04-12 17:52:51 -07:00
|
|
|
#if EFI_FILE_LOGGING
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2021-11-23 08:42:45 -08:00
|
|
|
#include "buffered_writer.h"
|
|
|
|
#include "status_loop.h"
|
|
|
|
|
|
|
|
static bool fs_ready = false;
|
|
|
|
|
|
|
|
int totalLoggedBytes = 0;
|
|
|
|
static int fileCreatedCounter = 0;
|
|
|
|
static int writeCounter = 0;
|
|
|
|
static int totalWritesCounter = 0;
|
|
|
|
static int totalSyncCounter = 0;
|
|
|
|
|
|
|
|
#if EFI_PROD_CODE
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "mmc_card.h"
|
|
|
|
#include "ff.h"
|
2021-04-10 05:35:41 -07:00
|
|
|
#include "mass_storage_init.h"
|
2016-07-05 06:01:23 -07:00
|
|
|
|
2016-08-08 21:03:08 -07:00
|
|
|
#include "rtc_helper.h"
|
2016-07-05 06:01:23 -07:00
|
|
|
|
2017-02-08 20:03:36 -08:00
|
|
|
#define SD_STATE_INIT "init"
|
|
|
|
#define SD_STATE_MOUNTED "MOUNTED"
|
|
|
|
#define SD_STATE_MOUNT_FAILED "MOUNT_FAILED"
|
|
|
|
#define SD_STATE_OPEN_FAILED "OPEN_FAILED"
|
|
|
|
#define SD_STATE_SEEK_FAILED "SEEK_FAILED"
|
|
|
|
#define SD_STATE_NOT_INSERTED "NOT_INSERTED"
|
|
|
|
#define SD_STATE_CONNECTING "CONNECTING"
|
2021-04-03 16:42:54 -07:00
|
|
|
#define SD_STATE_MSD "MSD"
|
2017-02-08 20:03:36 -08:00
|
|
|
#define SD_STATE_NOT_CONNECTED "NOT_CONNECTED"
|
|
|
|
|
2021-04-03 16:42:54 -07:00
|
|
|
// todo: shall we migrate to enum with enum2string for consistency? maybe not until we start reading sdStatus?
|
2017-02-08 20:03:36 -08:00
|
|
|
static const char *sdStatus = SD_STATE_INIT;
|
|
|
|
|
2021-04-15 06:42:22 -07:00
|
|
|
// at about 20Hz we write about 2Kb per second, looks like we flush once every ~2 seconds
|
2021-04-15 06:31:38 -07:00
|
|
|
#define F_SYNC_FREQUENCY 10
|
2019-09-20 22:55:27 -07:00
|
|
|
|
2020-11-17 05:25:50 -08:00
|
|
|
/**
|
|
|
|
* on't re-read SD card spi device after boot - it could change mid transaction (TS thread could preempt),
|
|
|
|
* which will cause disaster (usually multiple-unlock of the same mutex in UNLOCK_SD_SPI)
|
|
|
|
*/
|
2020-11-17 04:48:43 -08:00
|
|
|
spi_device_e mmcSpiDevice = SPI_NONE;
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
#define LOG_INDEX_FILENAME "index.txt"
|
2016-08-08 21:03:08 -07:00
|
|
|
|
2020-08-02 14:58:57 -07:00
|
|
|
#define RUSEFI_LOG_PREFIX "re_"
|
|
|
|
#define PREFIX_LEN 3
|
2020-05-17 14:02:22 -07:00
|
|
|
#define SHORT_TIME_LEN 13
|
2016-08-08 21:03:08 -07:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
#define LS_RESPONSE "ls_result"
|
|
|
|
#define FILE_LIST_MAX_COUNT 20
|
|
|
|
|
2021-02-24 22:37:44 -08:00
|
|
|
#if HAL_USE_MMC_SPI
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* MMC driver instance.
|
|
|
|
*/
|
|
|
|
MMCDriver MMCD1;
|
|
|
|
|
|
|
|
/* MMC/SD over SPI driver configuration.*/
|
2021-02-24 05:14:21 -08:00
|
|
|
static MMCConfig mmccfg = { NULL, &mmc_ls_spicfg, &mmc_hs_spicfg };
|
2021-02-25 10:37:41 -08:00
|
|
|
|
|
|
|
#define LOCK_SD_SPI lockSpi(mmcSpiDevice)
|
|
|
|
#define UNLOCK_SD_SPI unlockSpi(mmcSpiDevice)
|
|
|
|
|
2021-02-24 22:37:44 -08:00
|
|
|
#endif /* HAL_USE_MMC_SPI */
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* fatfs MMC/SPI
|
|
|
|
*/
|
2021-02-25 10:37:41 -08:00
|
|
|
static NO_CACHE FATFS MMC_FS;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2018-01-24 18:50:56 -08:00
|
|
|
static int fatFsErrors = 0;
|
|
|
|
|
2021-11-15 04:02:34 -08:00
|
|
|
static void mmcUnMount();
|
2019-09-21 09:41:17 -07:00
|
|
|
|
2019-09-21 08:20:04 -07:00
|
|
|
static void setSdCardReady(bool value) {
|
|
|
|
fs_ready = value;
|
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
// print FAT error function
|
|
|
|
static void printError(const char *str, FRESULT f_error) {
|
2018-01-24 18:50:56 -08:00
|
|
|
if (fatFsErrors++ > 16) {
|
|
|
|
// no reason to spam the console
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("FATfs Error \"%s\" %d", str, f_error);
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2020-01-28 21:32:43 -08:00
|
|
|
static FIL FDLogFile NO_CACHE;
|
2020-08-07 12:53:11 -07:00
|
|
|
|
|
|
|
// 10 because we want at least 4 character name
|
|
|
|
#define MIN_FILE_INDEX 10
|
|
|
|
static int logFileIndex = MIN_FILE_INDEX;
|
2016-08-09 21:04:24 -07:00
|
|
|
static char logName[_MAX_FILLER + 20];
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2021-11-15 04:02:34 -08:00
|
|
|
static void printMmcPinout() {
|
2021-11-17 00:54:21 -08:00
|
|
|
efiPrintf("MMC CS %s", hwPortname(engineConfiguration->sdCardCsPin));
|
2015-07-10 06:01:56 -07:00
|
|
|
// todo: we need to figure out the right SPI pinout, not just SPI2
|
2021-04-19 05:11:59 -07:00
|
|
|
// efiPrintf("MMC SCK %s:%d", portname(EFI_SPI2_SCK_PORT), EFI_SPI2_SCK_PIN);
|
|
|
|
// efiPrintf("MMC MISO %s:%d", portname(EFI_SPI2_MISO_PORT), EFI_SPI2_MISO_PIN);
|
|
|
|
// efiPrintf("MMC MOSI %s:%d", portname(EFI_SPI2_MOSI_PORT), EFI_SPI2_MOSI_PIN);
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2021-11-15 04:02:34 -08:00
|
|
|
static void sdStatistics() {
|
2015-07-10 06:01:56 -07:00
|
|
|
printMmcPinout();
|
2021-11-17 00:54:21 -08:00
|
|
|
efiPrintf("SD enabled=%s status=%s", boolToString(engineConfiguration->isSdCardEnabled),
|
2017-02-08 20:03:36 -08:00
|
|
|
sdStatus);
|
2021-04-21 11:28:48 -07:00
|
|
|
printSpiConfig("SD", mmcSpiDevice);
|
2019-09-21 08:20:04 -07:00
|
|
|
if (isSdCardAlive()) {
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("filename=%s size=%d", logName, totalLoggedBytes);
|
2017-02-08 20:03:36 -08:00
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2021-11-15 04:02:34 -08:00
|
|
|
static void incLogFileName() {
|
2021-08-27 03:18:05 -07:00
|
|
|
memset(&FDLogFile, 0, sizeof(FIL)); // clear the memory
|
|
|
|
FRESULT err = f_open(&FDLogFile, LOG_INDEX_FILENAME, FA_READ); // This file has the index for next log file name
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2016-08-09 21:04:24 -07:00
|
|
|
char data[_MAX_FILLER];
|
2015-07-10 06:01:56 -07:00
|
|
|
UINT result = 0;
|
|
|
|
if (err != FR_OK && err != FR_EXIST) {
|
2020-08-07 12:53:11 -07:00
|
|
|
logFileIndex = MIN_FILE_INDEX;
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("%s: not found or error: %d", LOG_INDEX_FILENAME, err);
|
2015-07-10 06:01:56 -07:00
|
|
|
} else {
|
2021-08-27 03:18:05 -07:00
|
|
|
f_read(&FDLogFile, (void*)data, sizeof(data), &result);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("Got content [%s] size %d", data, result);
|
2021-08-27 03:18:05 -07:00
|
|
|
f_close(&FDLogFile);
|
2015-07-10 06:01:56 -07:00
|
|
|
if (result < 5) {
|
2019-09-21 09:41:17 -07:00
|
|
|
data[result] = 0;
|
2020-08-07 12:53:11 -07:00
|
|
|
logFileIndex = maxI(MIN_FILE_INDEX, atoi(data));
|
2015-07-10 06:01:56 -07:00
|
|
|
if (absI(logFileIndex) == ERROR_CODE) {
|
2020-08-07 12:53:11 -07:00
|
|
|
logFileIndex = MIN_FILE_INDEX;
|
2015-07-10 06:01:56 -07:00
|
|
|
} else {
|
|
|
|
logFileIndex++; // next file would use next file name
|
|
|
|
}
|
|
|
|
} else {
|
2020-08-07 12:53:11 -07:00
|
|
|
logFileIndex = MIN_FILE_INDEX;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-27 03:18:05 -07:00
|
|
|
err = f_open(&FDLogFile, LOG_INDEX_FILENAME, FA_OPEN_ALWAYS | FA_WRITE);
|
2015-07-10 06:01:56 -07:00
|
|
|
itoa10(data, logFileIndex);
|
2021-08-27 03:18:05 -07:00
|
|
|
f_write(&FDLogFile, (void*)data, strlen(data), &result);
|
|
|
|
f_close(&FDLogFile);
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("Done %d", logFileIndex);
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2021-11-15 04:02:34 -08:00
|
|
|
static void prepareLogFileName() {
|
2016-08-08 21:03:08 -07:00
|
|
|
strcpy(logName, RUSEFI_LOG_PREFIX);
|
|
|
|
char *ptr;
|
2020-08-02 14:58:57 -07:00
|
|
|
|
2021-02-14 12:03:07 -08:00
|
|
|
#if HAL_USE_USB_MSD
|
2020-08-02 14:58:57 -07:00
|
|
|
bool result = dateToStringShort(&logName[PREFIX_LEN]);
|
2021-02-14 12:03:07 -08:00
|
|
|
#else
|
|
|
|
// TS SD protocol supports only short 8 symbol file names :(
|
|
|
|
bool result = false;
|
|
|
|
#endif
|
|
|
|
|
2016-08-09 22:01:43 -07:00
|
|
|
if (result) {
|
|
|
|
ptr = &logName[PREFIX_LEN + SHORT_TIME_LEN];
|
|
|
|
} else {
|
2016-08-08 21:03:08 -07:00
|
|
|
ptr = itoa10(&logName[PREFIX_LEN], logFileIndex);
|
2021-02-14 12:03:07 -08:00
|
|
|
}
|
|
|
|
|
2020-08-02 14:58:57 -07:00
|
|
|
strcat(ptr, DOT_MLG);
|
2016-08-08 21:03:08 -07:00
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @brief Create a new file with the specified name
|
|
|
|
*
|
|
|
|
* This function saves the name of the file in a global variable
|
|
|
|
* so that we can later append to that file
|
|
|
|
*/
|
2021-11-15 04:02:34 -08:00
|
|
|
static void createLogFile() {
|
2015-07-10 06:01:56 -07:00
|
|
|
memset(&FDLogFile, 0, sizeof(FIL)); // clear the memory
|
2016-08-08 21:03:08 -07:00
|
|
|
prepareLogFileName();
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
FRESULT err = f_open(&FDLogFile, logName, FA_OPEN_ALWAYS | FA_WRITE); // Create new file
|
|
|
|
if (err != FR_OK && err != FR_EXIST) {
|
2017-02-08 20:03:36 -08:00
|
|
|
sdStatus = SD_STATE_OPEN_FAILED;
|
2017-03-05 11:13:47 -08:00
|
|
|
warning(CUSTOM_ERR_SD_MOUNT_FAILED, "SD: mount failed");
|
2015-07-10 06:01:56 -07:00
|
|
|
printError("FS mount failed", err); // else - show error
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = f_lseek(&FDLogFile, f_size(&FDLogFile)); // Move to end of the file to append data
|
|
|
|
if (err) {
|
2017-02-08 20:03:36 -08:00
|
|
|
sdStatus = SD_STATE_SEEK_FAILED;
|
2017-03-05 11:13:47 -08:00
|
|
|
warning(CUSTOM_ERR_SD_SEEK_FAILED, "SD: seek failed");
|
2015-07-10 06:01:56 -07:00
|
|
|
printError("Seek error", err);
|
|
|
|
return;
|
|
|
|
}
|
2019-09-21 08:09:03 -07:00
|
|
|
f_sync(&FDLogFile);
|
2019-09-21 08:20:04 -07:00
|
|
|
setSdCardReady(true); // everything Ok
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void removeFile(const char *pathx) {
|
2019-09-21 08:20:04 -07:00
|
|
|
if (!isSdCardAlive()) {
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("Error: No File system is mounted");
|
2015-07-10 06:01:56 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-02-25 10:37:41 -08:00
|
|
|
f_unlink(pathx);
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2021-04-13 20:29:39 -07:00
|
|
|
int mystrncasecmp(const char *s1, const char *s2, size_t n) {
|
2016-08-10 05:03:48 -07:00
|
|
|
if (n != 0) {
|
2016-08-20 19:02:12 -07:00
|
|
|
const char *us1 = (const char *)s1;
|
|
|
|
const char *us2 = (const char *)s2;
|
2016-08-10 05:03:48 -07:00
|
|
|
|
|
|
|
do {
|
|
|
|
if (mytolower(*us1) != mytolower(*us2))
|
|
|
|
return (mytolower(*us1) - mytolower(*us2));
|
|
|
|
if (*us1++ == '\0')
|
|
|
|
break;
|
|
|
|
us2++;
|
|
|
|
} while (--n != 0);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
static void listDirectory(const char *path) {
|
|
|
|
|
2019-09-21 08:20:04 -07:00
|
|
|
if (!isSdCardAlive()) {
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("Error: No File system is mounted");
|
2015-07-10 06:01:56 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DIR dir;
|
|
|
|
FRESULT res = f_opendir(&dir, path);
|
|
|
|
|
|
|
|
if (res != FR_OK) {
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("Error opening directory %s", path);
|
2015-07-10 06:01:56 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf(LS_RESPONSE);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
for (int count = 0;count < FILE_LIST_MAX_COUNT;) {
|
|
|
|
FILINFO fno;
|
2018-01-23 19:24:11 -08:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
res = f_readdir(&dir, &fno);
|
2020-08-07 12:53:11 -07:00
|
|
|
if (res != FR_OK || fno.fname[0] == 0) {
|
2015-07-10 06:01:56 -07:00
|
|
|
break;
|
2020-08-07 12:53:11 -07:00
|
|
|
}
|
|
|
|
if (fno.fname[0] == '.') {
|
2015-07-10 06:01:56 -07:00
|
|
|
continue;
|
2020-08-07 12:53:11 -07:00
|
|
|
}
|
2016-08-10 05:03:48 -07:00
|
|
|
if ((fno.fattrib & AM_DIR) || mystrncasecmp(RUSEFI_LOG_PREFIX, fno.fname, sizeof(RUSEFI_LOG_PREFIX) - 1)) {
|
2015-07-10 06:01:56 -07:00
|
|
|
continue;
|
|
|
|
}
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("logfile%lu:%s", fno.fsize, fno.fname);
|
2015-07-10 06:01:56 -07:00
|
|
|
count++;
|
|
|
|
|
2021-04-19 05:11:59 -07:00
|
|
|
// efiPrintf("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu %-12s", (fno.fattrib & AM_DIR) ? 'D' : '-',
|
2015-07-10 06:01:56 -07:00
|
|
|
// (fno.fattrib & AM_RDO) ? 'R' : '-', (fno.fattrib & AM_HID) ? 'H' : '-',
|
|
|
|
// (fno.fattrib & AM_SYS) ? 'S' : '-', (fno.fattrib & AM_ARC) ? 'A' : '-', (fno.fdate >> 9) + 1980,
|
|
|
|
// (fno.fdate >> 5) & 15, fno.fdate & 31, (fno.ftime >> 11), (fno.ftime >> 5) & 63, fno.fsize,
|
|
|
|
// fno.fname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2019-09-21 08:34:28 -07:00
|
|
|
* MMC card un-mount.
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
2021-11-15 04:02:34 -08:00
|
|
|
static void mmcUnMount() {
|
2019-09-21 08:20:04 -07:00
|
|
|
if (!isSdCardAlive()) {
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("Error: No File system is mounted. \"mountsd\" first");
|
2015-07-10 06:01:56 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
f_close(&FDLogFile); // close file
|
|
|
|
f_sync(&FDLogFile); // sync ALL
|
2021-02-24 22:37:44 -08:00
|
|
|
|
|
|
|
#if HAL_USE_MMC_SPI
|
2015-07-10 06:01:56 -07:00
|
|
|
mmcDisconnect(&MMCD1); // Brings the driver in a state safe for card removal.
|
|
|
|
mmcStop(&MMCD1); // Disables the MMC peripheral.
|
2021-02-25 10:37:41 -08:00
|
|
|
UNLOCK_SD_SPI;
|
2021-02-24 22:37:44 -08:00
|
|
|
#endif
|
|
|
|
#ifdef EFI_SDC_DEVICE
|
|
|
|
sdcDisconnect(&EFI_SDC_DEVICE);
|
|
|
|
sdcStop(&EFI_SDC_DEVICE);
|
|
|
|
#endif
|
2017-04-02 20:28:05 -07:00
|
|
|
f_mount(NULL, 0, 0); // FATFS: Unregister work area prior to discard it
|
2015-07-10 06:01:56 -07:00
|
|
|
memset(&FDLogFile, 0, sizeof(FIL)); // clear FDLogFile
|
2019-09-21 08:20:04 -07:00
|
|
|
setSdCardReady(false); // status = false
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("MMC/SD card removed");
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2019-11-17 05:44:07 -08:00
|
|
|
#if HAL_USE_USB_MSD
|
2021-02-14 05:10:39 -08:00
|
|
|
|
2021-03-25 15:12:17 -07:00
|
|
|
static chibios_rt::BinarySemaphore usbConnectedSemaphore(/* taken =*/ true);
|
2021-02-14 05:10:39 -08:00
|
|
|
|
|
|
|
void onUsbConnectedNotifyMmcI() {
|
2021-03-25 15:12:17 -07:00
|
|
|
usbConnectedSemaphore.signalI();
|
2021-02-14 05:10:39 -08:00
|
|
|
}
|
|
|
|
|
2019-11-17 05:44:07 -08:00
|
|
|
#endif /* HAL_USE_USB_MSD */
|
2017-06-19 20:04:06 -07:00
|
|
|
|
2021-02-24 22:37:44 -08:00
|
|
|
#if HAL_USE_MMC_SPI
|
2015-07-10 06:01:56 -07:00
|
|
|
/*
|
2021-02-13 18:26:11 -08:00
|
|
|
* Attempts to initialize the MMC card.
|
|
|
|
* Returns a BaseBlockDevice* corresponding to the SD card if successful, otherwise nullptr.
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
2021-02-13 18:26:11 -08:00
|
|
|
static BaseBlockDevice* initializeMmcBlockDevice() {
|
2021-05-10 11:31:40 -07:00
|
|
|
// Don't try to mount SD card in case of fatal error - hardware may be in an unexpected state
|
|
|
|
if (hasFirmwareError()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-11-17 00:54:21 -08:00
|
|
|
if (!engineConfiguration->isSdCardEnabled) {
|
2021-02-13 18:26:11 -08:00
|
|
|
return nullptr;
|
2017-04-01 19:58:15 -07:00
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2021-02-13 18:26:11 -08:00
|
|
|
// Configures and activates the MMC peripheral.
|
2021-11-17 00:54:21 -08:00
|
|
|
mmcSpiDevice = engineConfiguration->sdCardSpiDevice;
|
2021-02-13 18:26:11 -08:00
|
|
|
|
|
|
|
efiAssert(OBD_PCM_Processor_Fault, mmcSpiDevice != SPI_NONE, "SD card enabled, but no SPI device configured!", nullptr);
|
|
|
|
|
|
|
|
// todo: reuse initSpiCs method?
|
2021-11-17 00:54:21 -08:00
|
|
|
mmc_hs_spicfg.ssport = mmc_ls_spicfg.ssport = getHwPort("mmc", engineConfiguration->sdCardCsPin);
|
|
|
|
mmc_hs_spicfg.sspad = mmc_ls_spicfg.sspad = getHwPin("mmc", engineConfiguration->sdCardCsPin);
|
2021-02-13 18:26:11 -08:00
|
|
|
mmccfg.spip = getSpiDevice(mmcSpiDevice);
|
|
|
|
|
2021-03-17 06:24:13 -07:00
|
|
|
// Invalid SPI device, abort.
|
|
|
|
if (!mmccfg.spip) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-02-13 18:26:11 -08:00
|
|
|
// We think we have everything for the card, let's try to mount it!
|
|
|
|
mmcObjectInit(&MMCD1);
|
|
|
|
mmcStart(&MMCD1, &mmccfg);
|
2021-02-13 12:06:05 -08:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
// Performs the initialization procedure on the inserted card.
|
2021-02-13 18:26:11 -08:00
|
|
|
LOCK_SD_SPI;
|
2017-02-08 20:03:36 -08:00
|
|
|
sdStatus = SD_STATE_CONNECTING;
|
2017-03-21 11:58:14 -07:00
|
|
|
if (mmcConnect(&MMCD1) != HAL_SUCCESS) {
|
2017-02-08 20:03:36 -08:00
|
|
|
sdStatus = SD_STATE_NOT_CONNECTED;
|
2020-08-02 14:58:57 -07:00
|
|
|
UNLOCK_SD_SPI;
|
2021-02-13 18:26:11 -08:00
|
|
|
return nullptr;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
2021-04-01 13:21:19 -07:00
|
|
|
// We intentionally never unlock in case of success, we take exclusive access of that spi device for SD use
|
2016-07-05 06:01:23 -07:00
|
|
|
|
2021-02-24 22:37:44 -08:00
|
|
|
return reinterpret_cast<BaseBlockDevice*>(&MMCD1);
|
|
|
|
}
|
|
|
|
#endif /* HAL_USE_MMC_SPI */
|
|
|
|
|
|
|
|
// Some ECUs are wired for SDIO/SDMMC instead of SPI
|
|
|
|
#ifdef EFI_SDC_DEVICE
|
|
|
|
static const SDCConfig sdcConfig = {
|
|
|
|
SDC_MODE_4BIT
|
|
|
|
};
|
|
|
|
|
|
|
|
static BaseBlockDevice* initializeMmcBlockDevice() {
|
2021-11-17 00:54:21 -08:00
|
|
|
if (!engineConfiguration->isSdCardEnabled) {
|
2021-02-24 22:37:44 -08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
sdcStart(&EFI_SDC_DEVICE, &sdcConfig);
|
|
|
|
sdStatus = SD_STATE_CONNECTING;
|
|
|
|
if (sdcConnect(&EFI_SDC_DEVICE) != HAL_SUCCESS) {
|
|
|
|
sdStatus = SD_STATE_NOT_CONNECTED;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return reinterpret_cast<BaseBlockDevice*>(&EFI_SDC_DEVICE);
|
2021-02-13 18:26:11 -08:00
|
|
|
}
|
2021-02-24 22:37:44 -08:00
|
|
|
#endif /* EFI_SDC_DEVICE */
|
2021-02-13 18:26:11 -08:00
|
|
|
|
|
|
|
// Initialize and mount the SD card.
|
|
|
|
// Returns true if the filesystem was successfully mounted for writing.
|
|
|
|
static bool mountMmc() {
|
|
|
|
auto cardBlockDevice = initializeMmcBlockDevice();
|
|
|
|
|
2021-07-20 18:29:24 -07:00
|
|
|
#if EFI_TUNER_STUDIO
|
|
|
|
// If not null, card is present
|
2021-12-07 17:18:47 -08:00
|
|
|
engine->outputChannels.sd_present = cardBlockDevice != nullptr;
|
2021-07-20 18:29:24 -07:00
|
|
|
#endif
|
|
|
|
|
2017-06-19 20:04:06 -07:00
|
|
|
#if HAL_USE_USB_MSD
|
2021-02-14 05:10:39 -08:00
|
|
|
// Wait for the USB stack to wake up, or a 5 second timeout, whichever occurs first
|
2021-03-25 15:12:17 -07:00
|
|
|
msg_t usbResult = usbConnectedSemaphore.wait(TIME_MS2I(5000));
|
2021-02-14 05:10:39 -08:00
|
|
|
|
|
|
|
bool hasUsb = usbResult == MSG_OK;
|
|
|
|
|
|
|
|
// If we have a device AND USB is connected, mount the card to USB, otherwise
|
|
|
|
// mount the null device and try to mount the filesystem ourselves
|
|
|
|
if (cardBlockDevice && hasUsb) {
|
2021-02-13 18:26:11 -08:00
|
|
|
// Mount the real card to USB
|
2021-04-10 05:35:41 -07:00
|
|
|
attachMsdSdCard(cardBlockDevice);
|
2021-02-14 05:10:39 -08:00
|
|
|
|
2021-04-03 16:42:54 -07:00
|
|
|
sdStatus = SD_STATE_MSD;
|
2021-02-14 05:10:39 -08:00
|
|
|
// At this point we're done: don't try to write files ourselves
|
|
|
|
return false;
|
2021-02-13 18:26:11 -08:00
|
|
|
}
|
2017-06-19 20:04:06 -07:00
|
|
|
#endif
|
|
|
|
|
2021-02-13 18:26:11 -08:00
|
|
|
// if no card, don't try to mount FS
|
|
|
|
if (!cardBlockDevice) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-02-14 05:10:39 -08:00
|
|
|
// We were able to connect the SD card, mount the filesystem
|
2015-07-10 06:01:56 -07:00
|
|
|
memset(&MMC_FS, 0, sizeof(FATFS));
|
2017-04-02 20:28:05 -07:00
|
|
|
if (f_mount(&MMC_FS, "/", 1) == FR_OK) {
|
2017-02-08 20:03:36 -08:00
|
|
|
sdStatus = SD_STATE_MOUNTED;
|
2015-07-10 06:01:56 -07:00
|
|
|
incLogFileName();
|
|
|
|
createLogFile();
|
2019-09-21 09:41:17 -07:00
|
|
|
fileCreatedCounter++;
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("MMC/SD mounted!");
|
2021-02-13 18:26:11 -08:00
|
|
|
return true;
|
2017-02-08 20:03:36 -08:00
|
|
|
} else {
|
|
|
|
sdStatus = SD_STATE_MOUNT_FAILED;
|
2021-02-13 18:26:11 -08:00
|
|
|
return false;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-13 18:26:11 -08:00
|
|
|
struct SdLogBufferWriter final : public BufferedWriter<512> {
|
|
|
|
bool failed = false;
|
|
|
|
|
2020-10-14 17:06:05 -07:00
|
|
|
size_t writeInternal(const char* buffer, size_t count) override {
|
|
|
|
size_t bytesWritten;
|
|
|
|
|
|
|
|
totalLoggedBytes += count;
|
|
|
|
|
|
|
|
FRESULT err = f_write(&FDLogFile, buffer, count, &bytesWritten);
|
|
|
|
|
|
|
|
if (bytesWritten != count) {
|
2021-04-13 20:29:39 -07:00
|
|
|
printError("write error or disk full", err);
|
2021-02-13 18:26:11 -08:00
|
|
|
|
|
|
|
// Close file and unmount volume
|
2020-10-14 17:06:05 -07:00
|
|
|
mmcUnMount();
|
2021-02-13 18:26:11 -08:00
|
|
|
failed = true;
|
|
|
|
return 0;
|
2020-10-14 17:06:05 -07:00
|
|
|
} else {
|
|
|
|
writeCounter++;
|
|
|
|
totalWritesCounter++;
|
|
|
|
if (writeCounter >= F_SYNC_FREQUENCY) {
|
|
|
|
/**
|
|
|
|
* Performance optimization: not f_sync after each line, f_sync is probably a heavy operation
|
|
|
|
* todo: one day someone should actually measure the relative cost of f_sync
|
|
|
|
*/
|
|
|
|
f_sync(&FDLogFile);
|
|
|
|
totalSyncCounter++;
|
|
|
|
writeCounter = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bytesWritten;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-11-23 08:42:45 -08:00
|
|
|
#else // not EFI_PROD_CODE (simulator)
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
|
|
|
|
bool mountMmc() {
|
|
|
|
// Stub so the loop thinks the MMC mounted OK
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
class SdLogBufferWriter final : public BufferedWriter<512> {
|
|
|
|
public:
|
|
|
|
bool failed = false;
|
|
|
|
|
|
|
|
SdLogBufferWriter()
|
|
|
|
: m_stream("rusefi_simulator_log.mlg", std::ios::binary | std::ios::trunc)
|
|
|
|
{
|
|
|
|
fs_ready = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t writeInternal(const char* buffer, size_t count) override {
|
|
|
|
m_stream.write(buffer, count);
|
|
|
|
m_stream.flush();
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::ofstream m_stream;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // EFI_PROD_CODE
|
|
|
|
|
2021-02-15 14:39:11 -08:00
|
|
|
static NO_CACHE SdLogBufferWriter logBuffer;
|
2020-10-14 17:06:05 -07:00
|
|
|
|
2021-11-23 08:42:45 -08:00
|
|
|
|
|
|
|
static THD_WORKING_AREA(mmcThreadStack, 3 * UTILITY_THREAD_STACK_SIZE); // MMC monitor thread
|
2016-01-15 20:01:43 -08:00
|
|
|
static THD_FUNCTION(MMCmonThread, arg) {
|
2019-11-17 05:44:07 -08:00
|
|
|
(void)arg;
|
2021-02-14 05:10:39 -08:00
|
|
|
chRegSetThreadName("MMC Card Logger");
|
|
|
|
|
|
|
|
if (!mountMmc()) {
|
|
|
|
// no card present (or mounted via USB), don't do internal logging
|
|
|
|
return;
|
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2021-07-20 18:29:24 -07:00
|
|
|
#if EFI_TUNER_STUDIO
|
2021-12-07 17:18:47 -08:00
|
|
|
engine->outputChannels.sd_logging_internal = true;
|
2021-07-20 18:29:24 -07:00
|
|
|
#endif
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
while (true) {
|
2020-11-15 17:44:36 -08:00
|
|
|
// if the SPI device got un-picked somehow, cancel SD card
|
2022-02-01 15:40:40 -08:00
|
|
|
// Don't do this check at all if using SDMMC interface instead of SPI
|
|
|
|
#if EFI_PROD_CODE && !defined(EFI_SDC_DEVICE)
|
2021-11-17 00:54:21 -08:00
|
|
|
if (engineConfiguration->sdCardSpiDevice == SPI_NONE) {
|
2020-11-15 17:44:36 -08:00
|
|
|
return;
|
|
|
|
}
|
2021-11-23 08:42:45 -08:00
|
|
|
#endif
|
2020-11-15 17:44:36 -08:00
|
|
|
|
2021-11-17 00:54:21 -08:00
|
|
|
if (engineConfiguration->debugMode == DBG_SD_CARD) {
|
2021-12-07 17:18:47 -08:00
|
|
|
engine->outputChannels.debugIntField1 = totalLoggedBytes;
|
|
|
|
engine->outputChannels.debugIntField2 = totalWritesCounter;
|
|
|
|
engine->outputChannels.debugIntField3 = totalSyncCounter;
|
|
|
|
engine->outputChannels.debugIntField4 = fileCreatedCounter;
|
2019-09-21 09:41:17 -07:00
|
|
|
}
|
|
|
|
|
2021-02-13 18:26:11 -08:00
|
|
|
writeLogLine(logBuffer);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2021-02-13 18:26:11 -08:00
|
|
|
// Something went wrong (already handled), so cancel further writes
|
|
|
|
if (logBuffer.failed) {
|
|
|
|
return;
|
2019-09-21 08:09:03 -07:00
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2021-11-17 00:54:21 -08:00
|
|
|
auto period = engineConfiguration->sdCardPeriodMs;
|
2020-09-30 22:36:33 -07:00
|
|
|
if (period > 0) {
|
|
|
|
chThdSleepMilliseconds(period);
|
2019-09-21 08:09:03 -07:00
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isSdCardAlive(void) {
|
|
|
|
return fs_ready;
|
|
|
|
}
|
|
|
|
|
2021-03-25 13:22:03 -07:00
|
|
|
// Pre-config load init
|
|
|
|
void initEarlyMmcCard() {
|
2021-11-23 08:42:45 -08:00
|
|
|
#if EFI_PROD_CODE
|
2015-07-10 06:01:56 -07:00
|
|
|
logName[0] = 0;
|
2021-02-13 18:26:11 -08:00
|
|
|
|
|
|
|
addConsoleAction("sdinfo", sdStatistics);
|
2015-07-10 06:01:56 -07:00
|
|
|
addConsoleActionS("ls", listDirectory);
|
|
|
|
addConsoleActionS("del", removeFile);
|
|
|
|
addConsoleAction("incfilename", incLogFileName);
|
2021-11-23 08:42:45 -08:00
|
|
|
#endif // EFI_PROD_CODE
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2021-03-25 13:22:03 -07:00
|
|
|
void initMmcCard() {
|
|
|
|
chThdCreateStatic(mmcThreadStack, sizeof(mmcThreadStack), PRIO_MMC, (tfunc_t)(void*) MMCmonThread, NULL);
|
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
#endif /* EFI_FILE_LOGGING */
|