Преглед изворни кода

SD Driver: reinit sd card on error (#2493)

* SD Driver: reinit sd card on error
* SD Driver: cleanup fatfs bindings
* Storage: optimized glue
* Storage: move fatfs initialization to appropriate subsystems, minor code cleanup
* SD Driver: minor code cleanup

Co-authored-by: あく <alleteam@gmail.com>
Sergey Gavrilov пре 2 година
родитељ
комит
f7024cff78

+ 19 - 42
applications/services/storage/storage_glue.c

@@ -73,29 +73,34 @@ uint32_t storage_data_get_timestamp(StorageData* storage) {
 
 
 /****************** storage glue ******************/
 /****************** storage glue ******************/
 
 
-bool storage_has_file(const File* file, StorageData* storage_data) {
-    bool result = false;
+static StorageFile* storage_get_file(const File* file, StorageData* storage) {
+    StorageFile* storage_file_ref = NULL;
 
 
     StorageFileList_it_t it;
     StorageFileList_it_t it;
-    for(StorageFileList_it(it, storage_data->files); !StorageFileList_end_p(it);
+    for(StorageFileList_it(it, storage->files); !StorageFileList_end_p(it);
         StorageFileList_next(it)) {
         StorageFileList_next(it)) {
-        const StorageFile* storage_file = StorageFileList_cref(it);
+        StorageFile* storage_file = StorageFileList_ref(it);
 
 
         if(storage_file->file->file_id == file->file_id) {
         if(storage_file->file->file_id == file->file_id) {
-            result = true;
+            storage_file_ref = storage_file;
             break;
             break;
         }
         }
     }
     }
 
 
-    return result;
+    return storage_file_ref;
+}
+
+bool storage_has_file(const File* file, StorageData* storage) {
+    return storage_get_file(file, storage) != NULL;
 }
 }
 
 
-bool storage_path_already_open(FuriString* path, StorageFileList_t array) {
+bool storage_path_already_open(FuriString* path, StorageData* storage) {
     bool open = false;
     bool open = false;
 
 
     StorageFileList_it_t it;
     StorageFileList_it_t it;
 
 
-    for(StorageFileList_it(it, array); !StorageFileList_end_p(it); StorageFileList_next(it)) {
+    for(StorageFileList_it(it, storage->files); !StorageFileList_end_p(it);
+        StorageFileList_next(it)) {
         const StorageFile* storage_file = StorageFileList_cref(it);
         const StorageFile* storage_file = StorageFileList_cref(it);
 
 
         if(furi_string_cmp(storage_file->path, path) == 0) {
         if(furi_string_cmp(storage_file->path, path) == 0) {
@@ -108,43 +113,15 @@ bool storage_path_already_open(FuriString* path, StorageFileList_t array) {
 }
 }
 
 
 void storage_set_storage_file_data(const File* file, void* file_data, StorageData* storage) {
 void storage_set_storage_file_data(const File* file, void* file_data, StorageData* storage) {
-    StorageFile* founded_file = NULL;
-
-    StorageFileList_it_t it;
-
-    for(StorageFileList_it(it, storage->files); !StorageFileList_end_p(it);
-        StorageFileList_next(it)) {
-        StorageFile* storage_file = StorageFileList_ref(it);
-
-        if(storage_file->file->file_id == file->file_id) {
-            founded_file = storage_file;
-            break;
-        }
-    }
-
-    furi_check(founded_file != NULL);
-
-    founded_file->file_data = file_data;
+    StorageFile* storage_file_ref = storage_get_file(file, storage);
+    furi_check(storage_file_ref != NULL);
+    storage_file_ref->file_data = file_data;
 }
 }
 
 
 void* storage_get_storage_file_data(const File* file, StorageData* storage) {
 void* storage_get_storage_file_data(const File* file, StorageData* storage) {
-    const StorageFile* founded_file = NULL;
-
-    StorageFileList_it_t it;
-
-    for(StorageFileList_it(it, storage->files); !StorageFileList_end_p(it);
-        StorageFileList_next(it)) {
-        const StorageFile* storage_file = StorageFileList_cref(it);
-
-        if(storage_file->file->file_id == file->file_id) {
-            founded_file = storage_file;
-            break;
-        }
-    }
-
-    furi_check(founded_file != NULL);
-
-    return founded_file->file_data;
+    StorageFile* storage_file_ref = storage_get_file(file, storage);
+    furi_check(storage_file_ref != NULL);
+    return storage_file_ref->file_data;
 }
 }
 
 
 void storage_push_storage_file(File* file, FuriString* path, StorageData* storage) {
 void storage_push_storage_file(File* file, FuriString* path, StorageData* storage) {

+ 1 - 1
applications/services/storage/storage_glue.h

@@ -60,7 +60,7 @@ struct StorageData {
 };
 };
 
 
 bool storage_has_file(const File* file, StorageData* storage_data);
 bool storage_has_file(const File* file, StorageData* storage_data);
-bool storage_path_already_open(FuriString* path, StorageFileList_t files);
+bool storage_path_already_open(FuriString* path, StorageData* storage_data);
 
 
 void storage_set_storage_file_data(const File* file, void* file_data, StorageData* storage);
 void storage_set_storage_file_data(const File* file, void* file_data, StorageData* storage);
 void* storage_get_storage_file_data(const File* file, StorageData* storage);
 void* storage_get_storage_file_data(const File* file, StorageData* storage);

+ 4 - 4
applications/services/storage/storage_processing.c

@@ -77,7 +77,7 @@ static void storage_path_change_to_real_storage(FuriString* path, StorageType re
     }
     }
 }
 }
 
 
-FS_Error storage_get_data(Storage* app, FuriString* path, StorageData** storage) {
+static FS_Error storage_get_data(Storage* app, FuriString* path, StorageData** storage) {
     StorageType type = storage_get_type_by_path(path);
     StorageType type = storage_get_type_by_path(path);
 
 
     if(storage_type_is_valid(type)) {
     if(storage_type_is_valid(type)) {
@@ -111,7 +111,7 @@ bool storage_process_file_open(
     file->error_id = storage_get_data(app, path, &storage);
     file->error_id = storage_get_data(app, path, &storage);
 
 
     if(file->error_id == FSE_OK) {
     if(file->error_id == FSE_OK) {
-        if(storage_path_already_open(path, storage->files)) {
+        if(storage_path_already_open(path, storage)) {
             file->error_id = FSE_ALREADY_OPEN;
             file->error_id = FSE_ALREADY_OPEN;
         } else {
         } else {
             if(access_mode & FSAM_WRITE) {
             if(access_mode & FSAM_WRITE) {
@@ -268,7 +268,7 @@ bool storage_process_dir_open(Storage* app, File* file, FuriString* path) {
     file->error_id = storage_get_data(app, path, &storage);
     file->error_id = storage_get_data(app, path, &storage);
 
 
     if(file->error_id == FSE_OK) {
     if(file->error_id == FSE_OK) {
-        if(storage_path_already_open(path, storage->files)) {
+        if(storage_path_already_open(path, storage)) {
             file->error_id = FSE_ALREADY_OPEN;
             file->error_id = FSE_ALREADY_OPEN;
         } else {
         } else {
             storage_push_storage_file(file, path, storage);
             storage_push_storage_file(file, path, storage);
@@ -357,7 +357,7 @@ static FS_Error storage_process_common_remove(Storage* app, FuriString* path) {
     FS_Error ret = storage_get_data(app, path, &storage);
     FS_Error ret = storage_get_data(app, path, &storage);
 
 
     do {
     do {
-        if(storage_path_already_open(path, storage->files)) {
+        if(storage_path_already_open(path, storage)) {
             ret = FSE_ALREADY_OPEN;
             ret = FSE_ALREADY_OPEN;
             break;
             break;
         }
         }

+ 3 - 1
applications/services/storage/storages/storage_ext.c

@@ -618,8 +618,10 @@ static const FS_Api fs_api = {
 };
 };
 
 
 void storage_ext_init(StorageData* storage) {
 void storage_ext_init(StorageData* storage) {
+    fatfs_init();
+
     SDData* sd_data = malloc(sizeof(SDData));
     SDData* sd_data = malloc(sizeof(SDData));
-    sd_data->fs = &USERFatFS;
+    sd_data->fs = &fatfs_object;
     sd_data->path = "0:/";
     sd_data->path = "0:/";
     sd_data->sd_was_present = true;
     sd_data->sd_was_present = true;
 
 

+ 0 - 6
firmware/targets/f18/furi_hal/furi_hal.c

@@ -3,8 +3,6 @@
 
 
 #include <stm32wbxx_ll_cortex.h>
 #include <stm32wbxx_ll_cortex.h>
 
 
-#include <fatfs.h>
-
 #define TAG "FuriHal"
 #define TAG "FuriHal"
 
 
 void furi_hal_init_early() {
 void furi_hal_init_early() {
@@ -74,10 +72,6 @@ void furi_hal_init() {
 #endif
 #endif
     furi_hal_bt_init();
     furi_hal_bt_init();
     furi_hal_compress_icon_init();
     furi_hal_compress_icon_init();
-
-    // FatFS driver initialization
-    MX_FATFS_Init();
-    FURI_LOG_I(TAG, "FATFS OK");
 }
 }
 
 
 void furi_hal_switch(void* address) {
 void furi_hal_switch(void* address) {

+ 6 - 41
firmware/targets/f7/fatfs/fatfs.c

@@ -1,39 +1,12 @@
-/**
-  ******************************************************************************
-  * @file   fatfs.c
-  * @brief  Code for fatfs applications
-  ******************************************************************************
-  * @attention
-  *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
-  * All rights reserved.</center></h2>
-  *
-  * This software component is licensed by ST under Ultimate Liberty license
-  * SLA0044, the "License"; You may not use this file except in compliance with
-  * the License. You may obtain a copy of the License at:
-  *                             www.st.com/SLA0044
-  *
-  ******************************************************************************
-  */
-
 #include "fatfs.h"
 #include "fatfs.h"
 
 
-uint8_t retUSER; /* Return value for USER */
-char USERPath[4]; /* USER logical drive path */
-FATFS USERFatFS; /* File system object for USER logical drive */
-FIL USERFile; /* File object for USER */
-
-/* USER CODE BEGIN Variables */
-
-/* USER CODE END Variables */
+/** logical drive path */
+char fatfs_path[4];
+/** File system object */
+FATFS fatfs_object;
 
 
-void MX_FATFS_Init(void) {
-    /*## FatFS: Link the USER driver ###########################*/
-    retUSER = FATFS_LinkDriver(&USER_Driver, USERPath);
-
-    /* USER CODE BEGIN Init */
-    /* additional user code for init */
-    /* USER CODE END Init */
+void fatfs_init(void) {
+    FATFS_LinkDriver(&sd_fatfs_driver, fatfs_path);
 }
 }
 
 
 /**
 /**
@@ -42,13 +15,5 @@ void MX_FATFS_Init(void) {
   * @retval Time in DWORD
   * @retval Time in DWORD
   */
   */
 DWORD get_fattime(void) {
 DWORD get_fattime(void) {
-    /* USER CODE BEGIN get_fattime */
     return 0;
     return 0;
-    /* USER CODE END get_fattime */
 }
 }
-
-/* USER CODE BEGIN Application */
-
-/* USER CODE END Application */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 10 - 40
firmware/targets/f7/fatfs/fatfs.h

@@ -1,49 +1,19 @@
-/**
-  ******************************************************************************
-  * @file   fatfs.h
-  * @brief  Header for fatfs applications
-  ******************************************************************************
-  * @attention
-  *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
-  * All rights reserved.</center></h2>
-  *
-  * This software component is licensed by ST under Ultimate Liberty license
-  * SLA0044, the "License"; You may not use this file except in compliance with
-  * the License. You may obtain a copy of the License at:
-  *                             www.st.com/SLA0044
-  *
-  ******************************************************************************
-  */
-
-/* Define to prevent recursive inclusion -------------------------------------*/
-#ifndef __fatfs_H
-#define __fatfs_H
-#ifdef __cplusplus
-extern "C" {
-#endif
+#pragma once
 
 
 #include "fatfs/ff.h"
 #include "fatfs/ff.h"
 #include "fatfs/ff_gen_drv.h"
 #include "fatfs/ff_gen_drv.h"
-#include "user_diskio.h" /* defines USER_Driver as external */
-
-/* USER CODE BEGIN Includes */
-
-/* USER CODE END Includes */
+#include "user_diskio.h"
 
 
-extern uint8_t retUSER; /* Return value for USER */
-extern char USERPath[4]; /* USER logical drive path */
-extern FATFS USERFatFS; /* File system object for USER logical drive */
-extern FIL USERFile; /* File object for USER */
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 
-void MX_FATFS_Init(void);
+/** File system object */
+extern FATFS fatfs_object;
 
 
-/* USER CODE BEGIN Prototypes */
+/** Init file system driver */
+void fatfs_init(void);
 
 
-/* USER CODE END Prototypes */
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
-#endif
-#endif /*__fatfs_H */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+#endif

+ 1 - 1
firmware/targets/f7/fatfs/ffconf.h

@@ -164,7 +164,7 @@
 
 
 /* USER CODE BEGIN Volumes */
 /* USER CODE BEGIN Volumes */
 #define _STR_VOLUME_ID 0 /* 0:Use only 0-9 for drive ID, 1:Use strings for drive ID */
 #define _STR_VOLUME_ID 0 /* 0:Use only 0-9 for drive ID, 1:Use strings for drive ID */
-#define _VOLUME_STRS "RAM", "NAND", "CF", "SD1", "SD2", "USB1", "USB2", "USB3"
+#define _VOLUME_STRS "SD"
 /* _STR_VOLUME_ID switches string support of volume ID.
 /* _STR_VOLUME_ID switches string support of volume ID.
 /  When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
 /  When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
 /  number in the path name. _VOLUME_STRS defines the drive ID strings for each
 /  number in the path name. _VOLUME_STRS defines the drive ID strings for each

+ 0 - 116
firmware/targets/f7/fatfs/syscall.c

@@ -1,116 +0,0 @@
-/*------------------------------------------------------------------------*/
-/* Sample code of OS dependent controls for FatFs                         */
-/* (C)ChaN, 2014                                                          */
-/*   Portions COPYRIGHT 2017 STMicroelectronics                           */
-/*   Portions Copyright (C) 2014, ChaN, all right reserved                */
-/*------------------------------------------------------------------------*/
-
-/**
-  ******************************************************************************
-  * @attention
-  *
-  * Copyright (c) 2017 STMicroelectronics. All rights reserved.
-  *
-  * This software component is licensed by ST under BSD 3-Clause license,
-  * the "License"; You may not use this file except in compliance with the
-  * License. You may obtain a copy of the License at:
-  *                       opensource.org/licenses/BSD-3-Clause
-  *
-  ******************************************************************************
-**/
-
-#include "fatfs/ff.h"
-
-#if _FS_REENTRANT
-/*------------------------------------------------------------------------*/
-/* Create a Synchronization Object                                        */
-/*------------------------------------------------------------------------*/
-/* This function is called in f_mount() function to create a new
-/  synchronization object, such as semaphore and mutex. When a 0 is returned,
-/  the f_mount() function fails with FR_INT_ERR.
-*/
-
-int ff_cre_syncobj(/* 1:Function succeeded, 0:Could not create the sync object */
-                   BYTE vol, /* Corresponding volume (logical drive number) */
-                   _SYNC_t* sobj /* Pointer to return the created sync object */
-) {
-    int ret;
-
-    //osSemaphoreDef(SEM);
-    //*sobj = osSemaphoreCreate(osSemaphore(SEM), 1);
-    *sobj = furi_mutex_alloc(FuriMutexTypeNormal);
-    ret = (*sobj != NULL);
-
-    return ret;
-}
-
-/*------------------------------------------------------------------------*/
-/* Delete a Synchronization Object                                        */
-/*------------------------------------------------------------------------*/
-/* This function is called in f_mount() function to delete a synchronization
-/  object that created with ff_cre_syncobj() function. When a 0 is returned,
-/  the f_mount() function fails with FR_INT_ERR.
-*/
-
-int ff_del_syncobj(/* 1:Function succeeded, 0:Could not delete due to any error */
-                   _SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
-) {
-    furi_mutex_free(sobj);
-    return 1;
-}
-
-/*------------------------------------------------------------------------*/
-/* Request Grant to Access the Volume                                     */
-/*------------------------------------------------------------------------*/
-/* This function is called on entering file functions to lock the volume.
-/  When a 0 is returned, the file function fails with FR_TIMEOUT.
-*/
-
-int ff_req_grant(/* 1:Got a grant to access the volume, 0:Could not get a grant */
-                 _SYNC_t sobj /* Sync object to wait */
-) {
-    int ret = 0;
-
-    if(furi_mutex_acquire(sobj, _FS_TIMEOUT) == FuriStatusOk) {
-        ret = 1;
-    }
-
-    return ret;
-}
-
-/*------------------------------------------------------------------------*/
-/* Release Grant to Access the Volume                                     */
-/*------------------------------------------------------------------------*/
-/* This function is called on leaving file functions to unlock the volume.
-*/
-
-void ff_rel_grant(_SYNC_t sobj /* Sync object to be signaled */
-) {
-    furi_mutex_release(sobj);
-}
-
-#endif
-
-#if _USE_LFN == 3 /* LFN with a working buffer on the heap */
-/*------------------------------------------------------------------------*/
-/* Allocate a memory block                                                */
-/*------------------------------------------------------------------------*/
-/* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE.
-*/
-
-void* ff_memalloc(/* Returns pointer to the allocated memory block */
-                  UINT msize /* Number of bytes to allocate */
-) {
-    return ff_malloc(msize); /* Allocate a new memory block with POSIX API */
-}
-
-/*------------------------------------------------------------------------*/
-/* Free a memory block                                                    */
-/*------------------------------------------------------------------------*/
-
-void ff_memfree(void* mblock /* Pointer to the memory block to free */
-) {
-    ff_free(mblock); /* Discard the memory block with POSIX API */
-}
-
-#endif

+ 107 - 123
firmware/targets/f7/fatfs/user_diskio.c

@@ -1,50 +1,10 @@
-/* USER CODE BEGIN Header */
-/**
- ******************************************************************************
- * @file    user_diskio.c
- * @brief   This file includes a diskio driver skeleton to be completed by the user.
- ******************************************************************************
- * @attention
- *
- * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
- * All rights reserved.</center></h2>
- *
- * This software component is licensed by ST under Ultimate Liberty license
- * SLA0044, the "License"; You may not use this file except in compliance with
- * the License. You may obtain a copy of the License at:
- *                             www.st.com/SLA0044
- *
- ******************************************************************************
- */
-/* USER CODE END Header */
-
-#ifdef USE_OBSOLETE_USER_CODE_SECTION_0
-/* 
- * Warning: the user section 0 is no more in use (starting from CubeMx version 4.16.0)
- * To be suppressed in the future. 
- * Kept to ensure backward compatibility with previous CubeMx versions when 
- * migrating projects. 
- * User code previously added there should be copied in the new user sections before 
- * the section contents can be deleted.
- */
-/* USER CODE BEGIN 0 */
-/* USER CODE END 0 */
-#endif
-
-/* USER CODE BEGIN DECL */
-
-/* Includes ------------------------------------------------------------------*/
 #include "user_diskio.h"
 #include "user_diskio.h"
 #include <furi_hal.h>
 #include <furi_hal.h>
 #include "sector_cache.h"
 #include "sector_cache.h"
-/* Private typedef -----------------------------------------------------------*/
-/* Private define ------------------------------------------------------------*/
 
 
-/* Private variables ---------------------------------------------------------*/
-/* Disk status */
 static volatile DSTATUS Stat = STA_NOINIT;
 static volatile DSTATUS Stat = STA_NOINIT;
 
 
-static DSTATUS User_CheckStatus(BYTE lun) {
+static DSTATUS driver_check_status(BYTE lun) {
     UNUSED(lun);
     UNUSED(lun);
     Stat = STA_NOINIT;
     Stat = STA_NOINIT;
     if(sd_get_card_state() == SdSpiStatusOK) {
     if(sd_get_card_state() == SdSpiStatusOK) {
@@ -54,32 +14,20 @@ static DSTATUS User_CheckStatus(BYTE lun) {
     return Stat;
     return Stat;
 }
 }
 
 
-/* USER CODE END DECL */
-
-/* Private function prototypes -----------------------------------------------*/
-DSTATUS USER_initialize(BYTE pdrv);
-DSTATUS USER_status(BYTE pdrv);
-DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
-#if _USE_WRITE == 1
-DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
-#endif /* _USE_WRITE == 1 */
-#if _USE_IOCTL == 1
-DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff);
-#endif /* _USE_IOCTL == 1 */
-
-Diskio_drvTypeDef USER_Driver = {
-    USER_initialize,
-    USER_status,
-    USER_read,
-#if _USE_WRITE
-    USER_write,
-#endif /* _USE_WRITE == 1 */
-#if _USE_IOCTL == 1
-    USER_ioctl,
-#endif /* _USE_IOCTL == 1 */
+static DSTATUS driver_initialize(BYTE pdrv);
+static DSTATUS driver_status(BYTE pdrv);
+static DRESULT driver_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
+static DRESULT driver_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
+static DRESULT driver_ioctl(BYTE pdrv, BYTE cmd, void* buff);
+
+Diskio_drvTypeDef sd_fatfs_driver = {
+    driver_initialize,
+    driver_status,
+    driver_read,
+    driver_write,
+    driver_ioctl,
 };
 };
 
 
-/* Private functions ---------------------------------------------------------*/
 static inline bool sd_cache_get(uint32_t address, uint32_t* data) {
 static inline bool sd_cache_get(uint32_t address, uint32_t* data) {
     uint8_t* cached_data = sector_cache_get(address);
     uint8_t* cached_data = sector_cache_get(address);
     if(cached_data) {
     if(cached_data) {
@@ -101,24 +49,73 @@ static inline void sd_cache_invalidate_all() {
     sector_cache_init();
     sector_cache_init();
 }
 }
 
 
+static bool sd_device_read(uint32_t* buff, uint32_t sector, uint32_t count) {
+    bool result = false;
+
+    furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
+    furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
+
+    if(sd_read_blocks(buff, sector, count, SD_TIMEOUT_MS) == SdSpiStatusOK) {
+        FuriHalCortexTimer timer = furi_hal_cortex_timer_get(SD_TIMEOUT_MS * 1000);
+
+        /* wait until the read operation is finished */
+        result = true;
+        while(sd_get_card_state() != SdSpiStatusOK) {
+            if(furi_hal_cortex_timer_is_expired(timer)) {
+                result = false;
+                break;
+            }
+        }
+    }
+
+    furi_hal_sd_spi_handle = NULL;
+    furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
+
+    return result;
+}
+
+static bool sd_device_write(uint32_t* buff, uint32_t sector, uint32_t count) {
+    bool result = false;
+
+    furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
+    furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
+
+    if(sd_write_blocks(buff, sector, count, SD_TIMEOUT_MS) == SdSpiStatusOK) {
+        FuriHalCortexTimer timer = furi_hal_cortex_timer_get(SD_TIMEOUT_MS * 1000);
+
+        /* wait until the Write operation is finished */
+        result = true;
+        while(sd_get_card_state() != SdSpiStatusOK) {
+            if(furi_hal_cortex_timer_is_expired(timer)) {
+                sd_cache_invalidate_all();
+
+                result = false;
+                break;
+            }
+        }
+    }
+
+    furi_hal_sd_spi_handle = NULL;
+    furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
+
+    return result;
+}
+
 /**
 /**
   * @brief  Initializes a Drive
   * @brief  Initializes a Drive
   * @param  pdrv: Physical drive number (0..)
   * @param  pdrv: Physical drive number (0..)
   * @retval DSTATUS: Operation status
   * @retval DSTATUS: Operation status
   */
   */
-DSTATUS USER_initialize(BYTE pdrv) {
-    /* USER CODE BEGIN INIT */
-
+static DSTATUS driver_initialize(BYTE pdrv) {
     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
     furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
     furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
 
 
-    DSTATUS status = User_CheckStatus(pdrv);
+    DSTATUS status = driver_check_status(pdrv);
 
 
     furi_hal_sd_spi_handle = NULL;
     furi_hal_sd_spi_handle = NULL;
     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
 
 
     return status;
     return status;
-    /* USER CODE END INIT */
 }
 }
 
 
 /**
 /**
@@ -126,11 +123,9 @@ DSTATUS USER_initialize(BYTE pdrv) {
   * @param  pdrv: Physical drive number (0..)
   * @param  pdrv: Physical drive number (0..)
   * @retval DSTATUS: Operation status
   * @retval DSTATUS: Operation status
   */
   */
-DSTATUS USER_status(BYTE pdrv) {
-    /* USER CODE BEGIN STATUS */
+static DSTATUS driver_status(BYTE pdrv) {
     UNUSED(pdrv);
     UNUSED(pdrv);
     return Stat;
     return Stat;
-    /* USER CODE END STATUS */
 }
 }
 
 
 /**
 /**
@@ -141,11 +136,10 @@ DSTATUS USER_status(BYTE pdrv) {
   * @param  count: Number of sectors to read (1..128)
   * @param  count: Number of sectors to read (1..128)
   * @retval DRESULT: Operation result
   * @retval DRESULT: Operation result
   */
   */
-DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
-    /* USER CODE BEGIN READ */
+static DRESULT driver_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
     UNUSED(pdrv);
     UNUSED(pdrv);
-    DRESULT res = RES_ERROR;
 
 
+    bool result;
     bool single_sector = count == 1;
     bool single_sector = count == 1;
 
 
     if(single_sector) {
     if(single_sector) {
@@ -154,32 +148,33 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
         }
         }
     }
     }
 
 
-    furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
-    furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
+    result = sd_device_read((uint32_t*)buff, (uint32_t)(sector), count);
 
 
-    if(sd_read_blocks((uint32_t*)buff, (uint32_t)(sector), count, SD_TIMEOUT_MS) ==
-       SdSpiStatusOK) {
-        FuriHalCortexTimer timer = furi_hal_cortex_timer_get(SD_TIMEOUT_MS * 1000);
+    if(!result) {
+        uint8_t counter = sd_max_mount_retry_count();
 
 
-        /* wait until the read operation is finished */
-        res = RES_OK;
-        while(sd_get_card_state() != SdSpiStatusOK) {
-            if(furi_hal_cortex_timer_is_expired(timer)) {
-                res = RES_ERROR;
-                break;
+        while(result == false && counter > 0 && hal_sd_detect()) {
+            SdSpiStatus status;
+
+            if((counter % 2) == 0) {
+                // power reset sd card
+                status = sd_init(true);
+            } else {
+                status = sd_init(false);
             }
             }
+
+            if(status == SdSpiStatusOK) {
+                result = sd_device_read((uint32_t*)buff, (uint32_t)(sector), count);
+            }
+            counter--;
         }
         }
     }
     }
 
 
-    furi_hal_sd_spi_handle = NULL;
-    furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
-
-    if(single_sector && res == RES_OK) {
+    if(single_sector && result == true) {
         sd_cache_put(sector, (uint32_t*)buff);
         sd_cache_put(sector, (uint32_t*)buff);
     }
     }
 
 
-    return res;
-    /* USER CODE END READ */
+    return result ? RES_OK : RES_ERROR;
 }
 }
 
 
 /**
 /**
@@ -190,41 +185,36 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
   * @param  count: Number of sectors to write (1..128)
   * @param  count: Number of sectors to write (1..128)
   * @retval DRESULT: Operation result
   * @retval DRESULT: Operation result
   */
   */
-#if _USE_WRITE == 1
-DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
-    /* USER CODE BEGIN WRITE */
-    /* USER CODE HERE */
+static DRESULT driver_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
     UNUSED(pdrv);
     UNUSED(pdrv);
-    DRESULT res = RES_ERROR;
+    bool result;
 
 
     sd_cache_invalidate_range(sector, sector + count);
     sd_cache_invalidate_range(sector, sector + count);
 
 
-    furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
-    furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
+    result = sd_device_write((uint32_t*)buff, (uint32_t)(sector), count);
 
 
-    if(sd_write_blocks((uint32_t*)buff, (uint32_t)(sector), count, SD_TIMEOUT_MS) ==
-       SdSpiStatusOK) {
-        FuriHalCortexTimer timer = furi_hal_cortex_timer_get(SD_TIMEOUT_MS * 1000);
+    if(!result) {
+        uint8_t counter = sd_max_mount_retry_count();
 
 
-        /* wait until the Write operation is finished */
-        res = RES_OK;
-        while(sd_get_card_state() != SdSpiStatusOK) {
-            if(furi_hal_cortex_timer_is_expired(timer)) {
-                sd_cache_invalidate_all();
+        while(result == false && counter > 0 && hal_sd_detect()) {
+            SdSpiStatus status;
 
 
-                res = RES_ERROR;
-                break;
+            if((counter % 2) == 0) {
+                // power reset sd card
+                status = sd_init(true);
+            } else {
+                status = sd_init(false);
             }
             }
+
+            if(status == SdSpiStatusOK) {
+                result = sd_device_write((uint32_t*)buff, (uint32_t)(sector), count);
+            }
+            counter--;
         }
         }
     }
     }
 
 
-    furi_hal_sd_spi_handle = NULL;
-    furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
-
-    return res;
-    /* USER CODE END WRITE */
+    return result ? RES_OK : RES_ERROR;
 }
 }
-#endif /* _USE_WRITE == 1 */
 
 
 /**
 /**
   * @brief  I/O control operation  
   * @brief  I/O control operation  
@@ -233,9 +223,7 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
   * @param  *buff: Buffer to send/receive control data
   * @param  *buff: Buffer to send/receive control data
   * @retval DRESULT: Operation result
   * @retval DRESULT: Operation result
   */
   */
-#if _USE_IOCTL == 1
-DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
-    /* USER CODE BEGIN IOCTL */
+static DRESULT driver_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
     UNUSED(pdrv);
     UNUSED(pdrv);
     DRESULT res = RES_ERROR;
     DRESULT res = RES_ERROR;
     SD_CardInfo CardInfo;
     SD_CardInfo CardInfo;
@@ -280,8 +268,4 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
 
 
     return res;
     return res;
-    /* USER CODE END IOCTL */
 }
 }
-#endif /* _USE_IOCTL == 1 */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 3 - 37
firmware/targets/f7/fatfs/user_diskio.h

@@ -1,48 +1,14 @@
-/* USER CODE BEGIN Header */
-/**
- ******************************************************************************
-  * @file    user_diskio.h
-  * @brief   This file contains the common defines and functions prototypes for  
-  *          the user_diskio driver.
-  ******************************************************************************
-  * @attention
-  *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
-  * All rights reserved.</center></h2>
-  *
-  * This software component is licensed by ST under Ultimate Liberty license
-  * SLA0044, the "License"; You may not use this file except in compliance with
-  * the License. You may obtain a copy of the License at:
-  *                             www.st.com/SLA0044
-  *
-  ******************************************************************************
-  */
-/* USER CODE END Header */
-
-/* Define to prevent recursive inclusion -------------------------------------*/
-#ifndef __USER_DISKIO_H
-#define __USER_DISKIO_H
+#pragma once
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-/* USER CODE BEGIN 0 */
-
-/* Includes ------------------------------------------------------------------*/
 #include "sd_spi_io.h"
 #include "sd_spi_io.h"
 #include "fatfs/ff_gen_drv.h"
 #include "fatfs/ff_gen_drv.h"
-/* Exported types ------------------------------------------------------------*/
-/* Exported constants --------------------------------------------------------*/
-/* Exported functions ------------------------------------------------------- */
-extern Diskio_drvTypeDef USER_Driver;
 
 
-/* USER CODE END 0 */
+extern Diskio_drvTypeDef sd_fatfs_driver;
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
-#endif
-
-#endif /* __USER_DISKIO_H */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+#endif

+ 0 - 6
firmware/targets/f7/furi_hal/furi_hal.c

@@ -4,8 +4,6 @@
 
 
 #include <stm32wbxx_ll_cortex.h>
 #include <stm32wbxx_ll_cortex.h>
 
 
-#include <fatfs.h>
-
 #define TAG "FuriHal"
 #define TAG "FuriHal"
 
 
 void furi_hal_init_early() {
 void furi_hal_init_early() {
@@ -81,10 +79,6 @@ void furi_hal_init() {
     furi_hal_nfc_init();
     furi_hal_nfc_init();
     furi_hal_rfid_init();
     furi_hal_rfid_init();
 #endif
 #endif
-
-    // FatFS driver initialization
-    MX_FATFS_Init();
-    FURI_LOG_I(TAG, "FATFS OK");
 }
 }
 
 
 void furi_hal_switch(void* address) {
 void furi_hal_switch(void* address) {

+ 1 - 1
firmware/targets/f7/src/update.c

@@ -44,7 +44,7 @@ static bool flipper_update_init() {
 
 
     furi_hal_spi_config_init();
     furi_hal_spi_config_init();
 
 
-    MX_FATFS_Init();
+    fatfs_init();
     if(!hal_sd_detect()) {
     if(!hal_sd_detect()) {
         return false;
         return false;
     }
     }