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 ******************/
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;
for(StorageFileList_it(it, storage_data->files); !StorageFileList_end_p(it);
for(StorageFileList_it(it, storage->files); !StorageFileList_end_p(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) {
result = true;
storage_file_ref = storage_file;
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;
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);
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) {
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) {
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) {

View File

@ -60,7 +60,7 @@ struct StorageData {
};
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_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);
if(storage_type_is_valid(type)) {
@ -111,7 +111,7 @@ bool storage_process_file_open(
file->error_id = storage_get_data(app, path, &storage);
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;
} else {
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);
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;
} else {
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);
do {
if(storage_path_already_open(path, storage->files)) {
if(storage_path_already_open(path, storage)) {
ret = FSE_ALREADY_OPEN;
break;
}

View File

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

View File

@ -3,8 +3,6 @@
#include <stm32wbxx_ll_cortex.h>
#include <fatfs.h>
#define TAG "FuriHal"
void furi_hal_init_early() {
@ -74,10 +72,6 @@ void furi_hal_init() {
#endif
furi_hal_bt_init();
furi_hal_compress_icon_init();
// FatFS driver initialization
MX_FATFS_Init();
FURI_LOG_I(TAG, "FATFS OK");
}
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"
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 */
/** logical drive path */
char fatfs_path[4];
/** File system object */
FATFS fatfs_object;
/* USER CODE BEGIN Variables */
/* 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 */
void fatfs_init(void) {
FATFS_LinkDriver(&sd_fatfs_driver, fatfs_path);
}
/**
@ -42,13 +15,5 @@ void MX_FATFS_Init(void) {
* @retval Time in DWORD
*/
DWORD get_fattime(void) {
/* USER CODE BEGIN get_fattime */
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 @@
/**
******************************************************************************
* @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
*
******************************************************************************
*/
#pragma once
#include "fatfs/ff.h"
#include "fatfs/ff_gen_drv.h"
#include "user_diskio.h"
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __fatfs_H
#define __fatfs_H
#ifdef __cplusplus
extern "C" {
#endif
#include "fatfs/ff.h"
#include "fatfs/ff_gen_drv.h"
#include "user_diskio.h" /* defines USER_Driver as external */
/** File system object */
extern FATFS fatfs_object;
/* 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
}
#endif
#endif /*__fatfs_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
#endif

View File

@ -164,7 +164,7 @@
/* USER CODE BEGIN Volumes */
#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.
/ 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

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 <furi_hal.h>
#include "sector_cache.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Disk status */
static volatile DSTATUS Stat = STA_NOINIT;
static DSTATUS User_CheckStatus(BYTE lun) {
static DSTATUS driver_check_status(BYTE lun) {
UNUSED(lun);
Stat = STA_NOINIT;
if(sd_get_card_state() == SdSpiStatusOK) {
@ -54,32 +14,20 @@ static DSTATUS User_CheckStatus(BYTE lun) {
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 -----------------------------------------------*/
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 */
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) {
uint8_t* cached_data = sector_cache_get(address);
if(cached_data) {
@ -101,24 +49,73 @@ static inline void sd_cache_invalidate_all() {
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
* @param pdrv: Physical drive number (0..)
* @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_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_spi_release(&furi_hal_spi_bus_handle_sd_fast);
return status;
/* USER CODE END INIT */
}
/**
@ -126,11 +123,9 @@ DSTATUS USER_initialize(BYTE pdrv) {
* @param pdrv: Physical drive number (0..)
* @retval DSTATUS: Operation status
*/
DSTATUS USER_status(BYTE pdrv) {
/* USER CODE BEGIN STATUS */
static DSTATUS driver_status(BYTE pdrv) {
UNUSED(pdrv);
return Stat;
/* USER CODE END STATUS */
}
/**
@ -141,11 +136,10 @@ DSTATUS USER_status(BYTE pdrv) {
* @param count: Number of sectors to read (1..128)
* @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);
DRESULT res = RES_ERROR;
bool result;
bool single_sector = count == 1;
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);
}
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)
* @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);
DRESULT res = RES_ERROR;
bool result;
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
@ -233,9 +223,7 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
* @param *buff: Buffer to send/receive control data
* @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);
DRESULT res = RES_ERROR;
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);
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 */
/**
******************************************************************************
* @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
extern "C" {
#endif
/* USER CODE BEGIN 0 */
/* Includes ------------------------------------------------------------------*/
#include "sd_spi_io.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
}
#endif
#endif /* __USER_DISKIO_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
#endif

View File

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

View File

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