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>
This commit is contained in:
Sergey Gavrilov 2023-03-20 06:09:10 -07:00 committed by GitHub
parent 6ec62f48f9
commit f7024cff78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 154 additions and 418 deletions

View File

@ -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) { static StorageFile* storage_get_file(const File* file, StorageData* storage) {
bool result = false; 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_path_already_open(FuriString* path, StorageFileList_t array) { bool storage_has_file(const File* file, StorageData* storage) {
return storage_get_file(file, storage) != NULL;
}
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; StorageFile* storage_file_ref = storage_get_file(file, storage);
furi_check(storage_file_ref != NULL);
StorageFileList_it_t it; storage_file_ref->file_data = file_data;
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;
} }
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; StorageFile* storage_file_ref = storage_get_file(file, storage);
furi_check(storage_file_ref != NULL);
StorageFileList_it_t it; return storage_file_ref->file_data;
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;
} }
void storage_push_storage_file(File* file, FuriString* path, StorageData* storage) { void storage_push_storage_file(File* file, FuriString* path, StorageData* storage) {

View File

@ -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);

View File

@ -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;
} }

View File

@ -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;

View File

@ -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) {

View File

@ -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 */ /** logical drive path */
char USERPath[4]; /* USER logical drive path */ char fatfs_path[4];
FATFS USERFatFS; /* File system object for USER logical drive */ /** File system object */
FIL USERFile; /* File object for USER */ FATFS fatfs_object;
/* USER CODE BEGIN Variables */ void fatfs_init(void) {
FATFS_LinkDriver(&sd_fatfs_driver, fatfs_path);
/* USER CODE END Variables */
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 */
} }
/** /**
@ -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****/

View File

@ -1,49 +1,19 @@
/** #pragma once
******************************************************************************
* @file fatfs.h #include "fatfs/ff.h"
* @brief Header for fatfs applications #include "fatfs/ff_gen_drv.h"
****************************************************************************** #include "user_diskio.h"
* @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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "fatfs/ff.h" /** File system object */
#include "fatfs/ff_gen_drv.h" extern FATFS fatfs_object;
#include "user_diskio.h" /* defines USER_Driver as external */
/* USER CODE BEGIN Includes */ /** Init file system driver */
void fatfs_init(void);
/* USER CODE END Includes */
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 */
void MX_FATFS_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /*__fatfs_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -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

View File

@ -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

View File

@ -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 */ 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);
/* Private function prototypes -----------------------------------------------*/ Diskio_drvTypeDef sd_fatfs_driver = {
DSTATUS USER_initialize(BYTE pdrv); driver_initialize,
DSTATUS USER_status(BYTE pdrv); driver_status,
DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count); driver_read,
#if _USE_WRITE == 1 driver_write,
DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); driver_ioctl,
#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 */
}; };
/* 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) { static DSTATUS driver_initialize(BYTE pdrv) {
/* USER CODE BEGIN INIT */
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) { static DSTATUS driver_status(BYTE pdrv) {
/* USER CODE BEGIN STATUS */
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) { static DRESULT driver_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
/* USER CODE BEGIN READ */
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); result = sd_device_read((uint32_t*)buff, (uint32_t)(sector), count);
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
if(sd_read_blocks((uint32_t*)buff, (uint32_t)(sector), count, SD_TIMEOUT_MS) == if(!result) {
SdSpiStatusOK) { uint8_t counter = sd_max_mount_retry_count();
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(SD_TIMEOUT_MS * 1000);
/* wait until the read operation is finished */ while(result == false && counter > 0 && hal_sd_detect()) {
res = RES_OK; SdSpiStatus status;
while(sd_get_card_state() != SdSpiStatusOK) {
if(furi_hal_cortex_timer_is_expired(timer)) { if((counter % 2) == 0) {
res = RES_ERROR; // power reset sd card
break; status = sd_init(true);
} } else {
} status = sd_init(false);
} }
furi_hal_sd_spi_handle = NULL; if(status == SdSpiStatusOK) {
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast); result = sd_device_read((uint32_t*)buff, (uint32_t)(sector), count);
}
counter--;
}
}
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; return result ? RES_OK : RES_ERROR;
/* USER CODE END READ */
} }
/** /**
@ -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 static DRESULT driver_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
/* USER CODE BEGIN WRITE */
/* USER CODE HERE */
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); result = sd_device_write((uint32_t*)buff, (uint32_t)(sector), count);
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
if(sd_write_blocks((uint32_t*)buff, (uint32_t)(sector), count, SD_TIMEOUT_MS) == if(!result) {
SdSpiStatusOK) { uint8_t counter = sd_max_mount_retry_count();
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(SD_TIMEOUT_MS * 1000);
/* wait until the Write operation is finished */ while(result == false && counter > 0 && hal_sd_detect()) {
res = RES_OK; SdSpiStatus status;
while(sd_get_card_state() != SdSpiStatusOK) {
if(furi_hal_cortex_timer_is_expired(timer)) {
sd_cache_invalidate_all();
res = RES_ERROR; if((counter % 2) == 0) {
break; // power reset sd card
} status = sd_init(true);
} } else {
status = sd_init(false);
} }
furi_hal_sd_spi_handle = NULL; if(status == SdSpiStatusOK) {
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast); result = sd_device_write((uint32_t*)buff, (uint32_t)(sector), count);
}
return res; counter--;
/* 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 static DRESULT driver_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
/* USER CODE BEGIN IOCTL */
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****/

View File

@ -1,48 +1,14 @@
/* USER CODE BEGIN Header */ #pragma once
/**
******************************************************************************
* @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
#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
#endif /* __USER_DISKIO_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -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) {

View File

@ -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;
} }