diff --git a/firmware/hw_layer/mmc_card.cpp b/firmware/hw_layer/mmc_card.cpp index 923af208cf..d087ddc4c1 100644 --- a/firmware/hw_layer/mmc_card.cpp +++ b/firmware/hw_layer/mmc_card.cpp @@ -355,53 +355,67 @@ static const scsi_inquiry_response_t scsi_inquiry_response = { #endif /* HAL_USE_USB_MSD */ /* - * MMC card mount. + * Attempts to initialize the MMC card. + * Returns a BaseBlockDevice* corresponding to the SD card if successful, otherwise nullptr. */ -static void MMCmount(void) { -// printMmcPinout(); - - if (isSdCardAlive()) { - scheduleMsg(&logger, "Error: Already mounted. \"umountsd\" first"); - return; - } - if ((MMCD1.state == BLK_STOP) || (MMCD1.state == BLK_ACTIVE)) { - // looks like we would only get here after manual unmount with mmcStop? Do we really need to ever mmcStop? - // not sure if this code is needed - // start to initialize MMC/SD - mmcStart(&MMCD1, &mmccfg); // Configures and activates the MMC peripheral. +static BaseBlockDevice* initializeMmcBlockDevice() { + if (!CONFIG(isSdCardEnabled)) { + return nullptr; } - #if HAL_USE_USB_MSD - msdObjectInit(&USBMSD1); - #endif + // Configures and activates the MMC peripheral. + mmcSpiDevice = CONFIG(sdCardSpiDevice); + + efiAssert(OBD_PCM_Processor_Fault, mmcSpiDevice != SPI_NONE, "SD card enabled, but no SPI device configured!", nullptr); + + // todo: reuse initSpiCs method? + hs_spicfg.ssport = ls_spicfg.ssport = getHwPort("mmc", CONFIG(sdCardCsPin)); + hs_spicfg.sspad = ls_spicfg.sspad = getHwPin("mmc", CONFIG(sdCardCsPin)); + mmccfg.spip = getSpiDevice(mmcSpiDevice); + + // We think we have everything for the card, let's try to mount it! + mmcObjectInit(&MMCD1); + mmcStart(&MMCD1, &mmccfg); // Performs the initialization procedure on the inserted card. - LOCK_SD_SPI; + LOCK_SD_SPI; sdStatus = SD_STATE_CONNECTING; if (mmcConnect(&MMCD1) != HAL_SUCCESS) { - - #if HAL_USE_USB_MSD - // mount a null device to USB - msdMountNullDevice(&USBMSD1, &USBD2, blkbuf, &scsi_inquiry_response); - #endif - sdStatus = SD_STATE_NOT_CONNECTED; warning(CUSTOM_OBD_MMC_ERROR, "Can't connect or mount MMC/SD"); UNLOCK_SD_SPI; - return; + return nullptr; } - #if HAL_USE_USB_MSD - BaseBlockDevice *bbdp = (BaseBlockDevice*)&MMCD1; - msdStart(&USBMSD1, usb_driver, bbdp, blkbuf, &scsi_inquiry_response, NULL); - #endif - UNLOCK_SD_SPI; + return (BaseBlockDevice*)&MMCD1; +} + +// Initialize and mount the SD card. +// Returns true if the filesystem was successfully mounted for writing. +static bool mountMmc() { + auto cardBlockDevice = initializeMmcBlockDevice(); + #if HAL_USE_USB_MSD - sdStatus = SD_STATE_MOUNTED; - return; + msdObjectInit(&USBMSD1); + + if (cardBlockDevice) { + // Mount the real card to USB + msdStart(&USBMSD1, usb_driver, cardBlockDevice, blkbuf, &scsi_inquiry_response, NULL); + } else { + // Mount a "no media" device to USB + msdMountNullDevice(&USBMSD1, usb_driver, blkbuf, &scsi_inquiry_response); + } + + // TODO: local mount and log if USB not connected + return false; #endif + // if no card, don't try to mount FS + if (!cardBlockDevice) { + return false; + } + // if Ok - mount FS now memset(&MMC_FS, 0, sizeof(FATFS)); if (f_mount(&MMC_FS, "/", 1) == FR_OK) { @@ -410,12 +424,16 @@ static void MMCmount(void) { createLogFile(); fileCreatedCounter++; scheduleMsg(&logger, "MMC/SD mounted!"); + return true; } else { sdStatus = SD_STATE_MOUNT_FAILED; + return false; } } -class SdLogBufferWriter final : public BufferedWriter<512> { +struct SdLogBufferWriter final : public BufferedWriter<512> { + bool failed = false; + size_t writeInternal(const char* buffer, size_t count) override { size_t bytesWritten; @@ -426,7 +444,12 @@ class SdLogBufferWriter final : public BufferedWriter<512> { if (bytesWritten != count) { printError("write error or disk full", err); // error or disk full + + // Close file and unmount volume mmcUnMount(); + UNLOCK_SD_SPI; + failed = true; + return 0; } else { writeCounter++; totalWritesCounter++; @@ -465,20 +488,11 @@ static THD_FUNCTION(MMCmonThread, arg) { tsOutputChannels.debugIntField4 = fileCreatedCounter; } - // this returns TRUE if SD module is there, even without an SD card? - if (blkIsInserted(&MMCD1)) { + writeLogLine(logBuffer); - if (!isSdCardAlive()) { - MMCmount(); - } - } else { - sdStatus = SD_STATE_NOT_INSERTED; - } - - if (isSdCardAlive()) { - writeLogLine(logBuffer); - } else { - chThdSleepMilliseconds(100); + // Something went wrong (already handled), so cancel further writes + if (logBuffer.failed) { + return; } auto period = CONFIG(sdCardPeriodMs); @@ -494,32 +508,15 @@ bool isSdCardAlive(void) { void initMmcCard(void) { logName[0] = 0; - addConsoleAction("sdinfo", sdStatistics); - if (!CONFIG(isSdCardEnabled)) { + + if (!mountMmc()) { + // no card present, don't start thread return; } - mmcSpiDevice = CONFIG(sdCardSpiDevice); - - efiAssertVoid(OBD_PCM_Processor_Fault, mmcSpiDevice != SPI_NONE, "SD card enabled, but no SPI device configured!"); - - // todo: reuse initSpiCs method? - hs_spicfg.ssport = ls_spicfg.ssport = getHwPort("mmc", CONFIG(sdCardCsPin)); - hs_spicfg.sspad = ls_spicfg.sspad = getHwPin("mmc", CONFIG(sdCardCsPin)); - mmccfg.spip = getSpiDevice(mmcSpiDevice); - - /** - * FYI: SPI does not work with CCM memory, be sure to have main() stack in RAM, not in CCMRAM - */ - - // start to initialize MMC/SD - mmcObjectInit(&MMCD1); // Initializes an instance. - mmcStart(&MMCD1, &mmccfg); - chThdCreateStatic(mmcThreadStack, sizeof(mmcThreadStack), LOWPRIO, (tfunc_t)(void*) MMCmonThread, NULL); - addConsoleAction("mountsd", MMCmount); - addConsoleAction("umountsd", mmcUnMount); + addConsoleAction("sdinfo", sdStatistics); addConsoleActionS("ls", listDirectory); addConsoleActionS("del", removeFile); addConsoleAction("incfilename", incLogFileName);