[FL-2435] SD over SPI improvements (#2204)

* get rid of BSP layer
* sector_cache: init in any case
* new sd-spi driver: init
* Delete stm32_adafruit_sd.c.old
* Delete spi_sd_hal.c.old
* Storage: faster api lock primitive
* Threads: priority control
* Flags: correct error code
* Spi: dma mode
* SD-card: use DMA for big blocks of SPI data
* Fix wrong SD_TOKEN_START_DATA_MULTIPLE_BLOCK_WRITE value
* do not memset cache if it is NULL
* remove top-level timeouts
* sd hal: disable debug
* Furi HAL: DMA
* Furi HAL RFID: use furi_hal_dma
* Furi HAL DMA: tests
* Furi HAL DMA: docs
* rollback "Furi HAL RFID: use furi_hal_dma"
* 4 channels taken from DMA manager for core HAL.
* Furi HAL DMA: live fast, die young
* RPC tests: increase message buffer
* SPI HAL: use second DMA instance
* sd hal: new CID getter
* SPI hal: use non-DMA version if kernel is not running
* IR hal: generalize DMA definition
* storage: add CID data to sd info
* RFID hal: generalize DMA definition
* SUBGHZ hal: generalize DMA definition. Core hal moved to DMA2.
* Storage: small optimizations, removal of extra mutex
* Storage: redundant macro
* SD hal: more timeouts
* SPI hal: DMA init
* Target: make furi_hal_spi_dma_init symbol private
* Update F18 api symbols

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
Sergey Gavrilov
2023-02-08 07:41:22 +03:00
committed by GitHub
parent 224d0aefe4
commit e3d473bf42
31 changed files with 1539 additions and 1661 deletions

View File

@@ -1,6 +1,5 @@
#include <furi.h>
#include <furi_hal.h>
#include <stm32_adafruit_sd.h>
#include <cli/cli.h>
#include <lib/toolbox/args.h>
@@ -61,28 +60,26 @@ static void storage_cli_info(Cli* cli, FuriString* path) {
}
} else if(furi_string_cmp_str(path, STORAGE_EXT_PATH_PREFIX) == 0) {
SDInfo sd_info;
SD_CID sd_cid;
FS_Error error = storage_sd_info(api, &sd_info);
BSP_SD_GetCIDRegister(&sd_cid);
if(error != FSE_OK) {
storage_cli_print_error(error);
} else {
printf(
"Label: %s\r\nType: %s\r\n%luKiB total\r\n%luKiB free\r\n"
"%02x%2.2s %5.5s %i.%i\r\nSN:%04lx %02i/%i\r\n",
"%02x%s %s v%i.%i\r\nSN:%04lx %02i/%i\r\n",
sd_info.label,
sd_api_get_fs_type_text(sd_info.fs_type),
sd_info.kb_total,
sd_info.kb_free,
sd_cid.ManufacturerID,
sd_cid.OEM_AppliID,
sd_cid.ProdName,
sd_cid.ProdRev >> 4,
sd_cid.ProdRev & 0xf,
sd_cid.ProdSN,
sd_cid.ManufactMonth,
sd_cid.ManufactYear + 2000);
sd_info.manufacturer_id,
sd_info.oem_id,
sd_info.product_name,
sd_info.product_revision_major,
sd_info.product_revision_minor,
sd_info.product_serial_number,
sd_info.manufacturing_month,
sd_info.manufacturing_year);
}
} else {
storage_cli_print_usage();

View File

@@ -12,9 +12,7 @@
#define TAG "StorageAPI"
#define S_API_PROLOGUE \
FuriSemaphore* semaphore = furi_semaphore_alloc(1, 0); \
furi_check(semaphore != NULL);
#define S_API_PROLOGUE FuriApiLock lock = api_lock_alloc_locked();
#define S_FILE_API_PROLOGUE \
Storage* storage = file->storage; \
@@ -24,13 +22,12 @@
furi_check( \
furi_message_queue_put(storage->message_queue, &message, FuriWaitForever) == \
FuriStatusOk); \
furi_semaphore_acquire(semaphore, FuriWaitForever); \
furi_semaphore_free(semaphore);
api_lock_wait_unlock_and_free(lock)
#define S_API_MESSAGE(_command) \
SAReturn return_data; \
StorageMessage message = { \
.semaphore = semaphore, \
.lock = lock, \
.command = _command, \
.data = &data, \
.return_data = &return_data, \

View File

@@ -31,29 +31,13 @@ void storage_file_clear(StorageFile* obj) {
/****************** storage data ******************/
void storage_data_init(StorageData* storage) {
storage->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
furi_check(storage->mutex != NULL);
storage->data = NULL;
storage->status = StorageStatusNotReady;
StorageFileList_init(storage->files);
}
bool storage_data_lock(StorageData* storage) {
return (furi_mutex_acquire(storage->mutex, FuriWaitForever) == FuriStatusOk);
}
bool storage_data_unlock(StorageData* storage) {
return (furi_mutex_release(storage->mutex) == FuriStatusOk);
}
StorageStatus storage_data_status(StorageData* storage) {
StorageStatus status;
storage_data_lock(storage);
status = storage->status;
storage_data_unlock(storage);
return status;
return storage->status;
}
const char* storage_data_status_text(StorageData* storage) {

View File

@@ -38,8 +38,6 @@ void storage_file_set(StorageFile* obj, const StorageFile* src);
void storage_file_clear(StorageFile* obj);
void storage_data_init(StorageData* storage);
bool storage_data_lock(StorageData* storage);
bool storage_data_unlock(StorageData* storage);
StorageStatus storage_data_status(StorageData* storage);
const char* storage_data_status_text(StorageData* storage);
void storage_data_timestamp(StorageData* storage);
@@ -57,7 +55,6 @@ struct StorageData {
const FS_Api* fs_api;
StorageApi api;
void* data;
FuriMutex* mutex;
StorageStatus status;
StorageFileList_t files;
uint32_t timestamp;

View File

@@ -1,5 +1,6 @@
#pragma once
#include <furi.h>
#include <toolbox/api_lock.h>
#ifdef __cplusplus
extern "C" {
@@ -130,7 +131,7 @@ typedef enum {
} StorageCommand;
typedef struct {
FuriSemaphore* semaphore;
FuriApiLock lock;
StorageCommand command;
SAData* data;
SAReturn* return_data;

View File

@@ -2,15 +2,7 @@
#include <m-list.h>
#include <m-dict.h>
#define FS_CALL(_storage, _fn) \
storage_data_lock(_storage); \
ret = _storage->fs_api->_fn; \
storage_data_unlock(_storage);
#define ST_CALL(_storage, _fn) \
storage_data_lock(_storage); \
ret = _storage->api._fn; \
storage_data_unlock(_storage);
#define FS_CALL(_storage, _fn) ret = _storage->fs_api->_fn;
static StorageData* storage_get_storage_by_type(Storage* app, StorageType type) {
furi_check(type == ST_EXT || type == ST_INT);
@@ -44,16 +36,11 @@ static const char* remove_vfs(const char* path) {
static StorageType storage_get_type_by_path(Storage* app, const char* path) {
StorageType type = ST_ERROR;
if(strlen(path) >= strlen(STORAGE_EXT_PATH_PREFIX) &&
memcmp(path, STORAGE_EXT_PATH_PREFIX, strlen(STORAGE_EXT_PATH_PREFIX)) == 0) {
if(memcmp(path, STORAGE_EXT_PATH_PREFIX, strlen(STORAGE_EXT_PATH_PREFIX)) == 0) {
type = ST_EXT;
} else if(
strlen(path) >= strlen(STORAGE_INT_PATH_PREFIX) &&
memcmp(path, STORAGE_INT_PATH_PREFIX, strlen(STORAGE_INT_PATH_PREFIX)) == 0) {
} else if(memcmp(path, STORAGE_INT_PATH_PREFIX, strlen(STORAGE_INT_PATH_PREFIX)) == 0) {
type = ST_INT;
} else if(
strlen(path) >= strlen(STORAGE_ANY_PATH_PREFIX) &&
memcmp(path, STORAGE_ANY_PATH_PREFIX, strlen(STORAGE_ANY_PATH_PREFIX)) == 0) {
} else if(memcmp(path, STORAGE_ANY_PATH_PREFIX, strlen(STORAGE_ANY_PATH_PREFIX)) == 0) {
type = ST_ANY;
}
@@ -68,21 +55,15 @@ static StorageType storage_get_type_by_path(Storage* app, const char* path) {
}
static void storage_path_change_to_real_storage(FuriString* path, StorageType real_storage) {
if(memcmp(
furi_string_get_cstr(path), STORAGE_ANY_PATH_PREFIX, strlen(STORAGE_ANY_PATH_PREFIX)) ==
0) {
if(furi_string_search(path, STORAGE_ANY_PATH_PREFIX) == 0) {
switch(real_storage) {
case ST_EXT:
furi_string_set_char(path, 0, STORAGE_EXT_PATH_PREFIX[0]);
furi_string_set_char(path, 1, STORAGE_EXT_PATH_PREFIX[1]);
furi_string_set_char(path, 2, STORAGE_EXT_PATH_PREFIX[2]);
furi_string_set_char(path, 3, STORAGE_EXT_PATH_PREFIX[3]);
furi_string_replace_at(
path, 0, strlen(STORAGE_EXT_PATH_PREFIX), STORAGE_EXT_PATH_PREFIX);
break;
case ST_INT:
furi_string_set_char(path, 0, STORAGE_INT_PATH_PREFIX[0]);
furi_string_set_char(path, 1, STORAGE_INT_PATH_PREFIX[1]);
furi_string_set_char(path, 2, STORAGE_INT_PATH_PREFIX[2]);
furi_string_set_char(path, 3, STORAGE_INT_PATH_PREFIX[3]);
furi_string_replace_at(
path, 0, strlen(STORAGE_INT_PATH_PREFIX), STORAGE_INT_PATH_PREFIX);
break;
default:
break;
@@ -604,7 +585,7 @@ void storage_process_message_internal(Storage* app, StorageMessage* message) {
break;
}
furi_semaphore_release(message->semaphore);
api_lock_unlock(message->lock);
}
void storage_process_message(Storage* app, StorageMessage* message) {

View File

@@ -23,6 +23,16 @@ typedef struct {
uint16_t cluster_size;
uint16_t sector_size;
char label[SD_LABEL_LENGTH];
uint8_t manufacturer_id;
char oem_id[3];
char product_name[6];
uint8_t product_revision_major;
uint8_t product_revision_minor;
uint32_t product_serial_number;
uint8_t manufacturing_month;
uint16_t manufacturing_year;
FS_Error error;
} SDInfo;

View File

@@ -26,12 +26,10 @@ static FS_Error storage_ext_parse_error(SDError error);
static bool sd_mount_card(StorageData* storage, bool notify) {
bool result = false;
uint8_t counter = BSP_SD_MaxMountRetryCount();
uint8_t counter = sd_max_mount_retry_count();
uint8_t bsp_result;
SDData* sd_data = storage->data;
storage_data_lock(storage);
while(result == false && counter > 0 && hal_sd_detect()) {
if(notify) {
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
@@ -41,9 +39,9 @@ static bool sd_mount_card(StorageData* storage, bool notify) {
if((counter % 2) == 0) {
// power reset sd card
bsp_result = BSP_SD_Init(true);
bsp_result = sd_init(true);
} else {
bsp_result = BSP_SD_Init(false);
bsp_result = sd_init(false);
}
if(bsp_result) {
@@ -91,7 +89,6 @@ static bool sd_mount_card(StorageData* storage, bool notify) {
}
storage_data_timestamp(storage);
storage_data_unlock(storage);
return result;
}
@@ -100,14 +97,12 @@ FS_Error sd_unmount_card(StorageData* storage) {
SDData* sd_data = storage->data;
SDError error;
storage_data_lock(storage);
storage->status = StorageStatusNotReady;
error = FR_DISK_ERR;
// TODO do i need to close the files?
f_mount(0, sd_data->path, 0);
storage_data_unlock(storage);
return storage_ext_parse_error(error);
}
@@ -120,8 +115,6 @@ FS_Error sd_format_card(StorageData* storage) {
SDData* sd_data = storage->data;
SDError error;
storage_data_lock(storage);
work_area = malloc(_MAX_SS);
error = f_mkfs(sd_data->path, FM_ANY, 0, work_area, _MAX_SS);
free(work_area);
@@ -138,8 +131,6 @@ FS_Error sd_format_card(StorageData* storage) {
storage->status = StorageStatusOK;
} while(false);
storage_data_unlock(storage);
return storage_ext_parse_error(error);
#endif
}
@@ -156,14 +147,12 @@ FS_Error sd_card_info(StorageData* storage, SDInfo* sd_info) {
memset(sd_info, 0, sizeof(SDInfo));
// get fs info
storage_data_lock(storage);
error = f_getlabel(sd_data->path, sd_info->label, NULL);
if(error == FR_OK) {
#ifndef FURI_RAM_EXEC
error = f_getfree(sd_data->path, &free_clusters, &fs);
#endif
}
storage_data_unlock(storage);
if(error == FR_OK) {
// calculate size
@@ -210,6 +199,20 @@ FS_Error sd_card_info(StorageData* storage, SDInfo* sd_info) {
#endif
}
SD_CID cid;
SdSpiStatus status = sd_get_cid(&cid);
if(status == SdSpiStatusOK) {
sd_info->manufacturer_id = cid.ManufacturerID;
memcpy(sd_info->oem_id, cid.OEM_AppliID, sizeof(cid.OEM_AppliID));
memcpy(sd_info->product_name, cid.ProdName, sizeof(cid.ProdName));
sd_info->product_revision_major = cid.ProdRev >> 4;
sd_info->product_revision_minor = cid.ProdRev & 0x0F;
sd_info->product_serial_number = cid.ProdSN;
sd_info->manufacturing_year = 2000 + cid.ManufactYear;
sd_info->manufacturing_month = cid.ManufactMonth;
}
return storage_ext_parse_error(error);
}