SD Cache: moved to diskio layer, invalidation in case of error (#2428)

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
Sergey Gavrilov 2023-02-26 14:28:51 +03:00 committed by GitHub
parent 12c1ec37a2
commit 9bda3e62ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 37 deletions

View File

@ -17,7 +17,6 @@
#define SD_DUMMY_BYTE 0xFF #define SD_DUMMY_BYTE 0xFF
#define SD_ANSWER_RETRY_COUNT 8 #define SD_ANSWER_RETRY_COUNT 8
#define SD_IDLE_RETRY_COUNT 100 #define SD_IDLE_RETRY_COUNT 100
#define SD_BLOCK_SIZE 512
#define FLAG_SET(x, y) (((x) & (y)) == (y)) #define FLAG_SET(x, y) (((x) & (y)) == (y))
@ -598,23 +597,6 @@ static SdSpiStatus sd_spi_get_cid(SD_CID* Cid) {
return ret; return ret;
} }
static inline bool sd_cache_get(uint32_t address, uint32_t* data) {
uint8_t* cached_data = sector_cache_get(address);
if(cached_data) {
memcpy(data, cached_data, SD_BLOCK_SIZE);
return true;
}
return false;
}
static inline void sd_cache_put(uint32_t address, uint32_t* data) {
sector_cache_put(address, (uint8_t*)data);
}
static inline void sd_cache_invalidate_range(uint32_t start_sector, uint32_t end_sector) {
sector_cache_invalidate_range(start_sector, end_sector);
}
static SdSpiStatus static SdSpiStatus
sd_spi_cmd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) { sd_spi_cmd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) {
uint32_t block_address = address; uint32_t block_address = address;
@ -833,30 +815,12 @@ SdSpiStatus sd_get_card_info(SD_CardInfo* card_info) {
SdSpiStatus SdSpiStatus
sd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) { sd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) {
SdSpiStatus status = SdSpiStatusError; SdSpiStatus status = sd_spi_cmd_read_blocks(data, address, blocks, timeout_ms);
bool single_sector_read = (blocks == 1);
if(single_sector_read) {
if(sd_cache_get(address, data)) {
return SdSpiStatusOK;
}
status = sd_spi_cmd_read_blocks(data, address, blocks, timeout_ms);
if(status == SdSpiStatusOK) {
sd_cache_put(address, data);
}
} else {
status = sd_spi_cmd_read_blocks(data, address, blocks, timeout_ms);
}
return status; return status;
} }
SdSpiStatus SdSpiStatus
sd_write_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) { sd_write_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) {
sd_cache_invalidate_range(address, address + blocks);
SdSpiStatus status = sd_spi_cmd_write_blocks(data, address, blocks, timeout_ms); SdSpiStatus status = sd_spi_cmd_write_blocks(data, address, blocks, timeout_ms);
return status; return status;
} }

View File

@ -5,6 +5,7 @@
#define __IO volatile #define __IO volatile
#define SD_TIMEOUT_MS (1000) #define SD_TIMEOUT_MS (1000)
#define SD_BLOCK_SIZE 512
typedef enum { typedef enum {
SdSpiStatusOK, SdSpiStatusOK,

View File

@ -36,6 +36,7 @@
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "user_diskio.h" #include "user_diskio.h"
#include <furi_hal.h> #include <furi_hal.h>
#include "sector_cache.h"
/* Private typedef -----------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/
@ -79,6 +80,26 @@ Diskio_drvTypeDef USER_Driver = {
}; };
/* Private functions ---------------------------------------------------------*/ /* 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) {
memcpy(data, cached_data, SD_BLOCK_SIZE);
return true;
}
return false;
}
static inline void sd_cache_put(uint32_t address, uint32_t* data) {
sector_cache_put(address, (uint8_t*)data);
}
static inline void sd_cache_invalidate_range(uint32_t start_sector, uint32_t end_sector) {
sector_cache_invalidate_range(start_sector, end_sector);
}
static inline void sd_cache_invalidate_all() {
sector_cache_init();
}
/** /**
* @brief Initializes a Drive * @brief Initializes a Drive
@ -125,6 +146,14 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
UNUSED(pdrv); UNUSED(pdrv);
DRESULT res = RES_ERROR; DRESULT res = RES_ERROR;
bool single_sector = count == 1;
if(single_sector) {
if(sd_cache_get(sector, (uint32_t*)buff)) {
return RES_OK;
}
}
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;
@ -145,6 +174,10 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
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);
if(single_sector && res == RES_OK) {
sd_cache_put(sector, (uint32_t*)buff);
}
return res; return res;
/* USER CODE END READ */ /* USER CODE END READ */
} }
@ -164,6 +197,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
UNUSED(pdrv); UNUSED(pdrv);
DRESULT res = RES_ERROR; DRESULT res = RES_ERROR;
sd_cache_invalidate_range(sector, sector + count);
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;
@ -175,6 +210,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
res = RES_OK; res = RES_OK;
while(sd_get_card_state() != SdSpiStatusOK) { while(sd_get_card_state() != SdSpiStatusOK) {
if(furi_hal_cortex_timer_is_expired(timer)) { if(furi_hal_cortex_timer_is_expired(timer)) {
sd_cache_invalidate_all();
res = RES_ERROR; res = RES_ERROR;
break; break;
} }