SD Cache: moved to diskio layer, invalidation in case of error (#2428)
Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									12c1ec37a2
								
							
						
					
					
						commit
						9bda3e62ee
					
				| @ -17,7 +17,6 @@ | ||||
| #define SD_DUMMY_BYTE 0xFF | ||||
| #define SD_ANSWER_RETRY_COUNT 8 | ||||
| #define SD_IDLE_RETRY_COUNT 100 | ||||
| #define SD_BLOCK_SIZE 512 | ||||
| 
 | ||||
| #define FLAG_SET(x, y) (((x) & (y)) == (y)) | ||||
| 
 | ||||
| @ -598,23 +597,6 @@ static SdSpiStatus sd_spi_get_cid(SD_CID* Cid) { | ||||
|     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 | ||||
|     sd_spi_cmd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) { | ||||
|     uint32_t block_address = address; | ||||
| @ -833,30 +815,12 @@ SdSpiStatus sd_get_card_info(SD_CardInfo* card_info) { | ||||
| 
 | ||||
| SdSpiStatus | ||||
|     sd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) { | ||||
|     SdSpiStatus status = SdSpiStatusError; | ||||
| 
 | ||||
|     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); | ||||
|     } | ||||
| 
 | ||||
|     SdSpiStatus status = sd_spi_cmd_read_blocks(data, address, blocks, timeout_ms); | ||||
|     return status; | ||||
| } | ||||
| 
 | ||||
| SdSpiStatus | ||||
|     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); | ||||
|     return status; | ||||
| } | ||||
|  | ||||
| @ -5,6 +5,7 @@ | ||||
| #define __IO volatile | ||||
| 
 | ||||
| #define SD_TIMEOUT_MS (1000) | ||||
| #define SD_BLOCK_SIZE 512 | ||||
| 
 | ||||
| typedef enum { | ||||
|     SdSpiStatusOK, | ||||
|  | ||||
| @ -36,6 +36,7 @@ | ||||
| /* Includes ------------------------------------------------------------------*/ | ||||
| #include "user_diskio.h" | ||||
| #include <furi_hal.h> | ||||
| #include "sector_cache.h" | ||||
| /* Private typedef -----------------------------------------------------------*/ | ||||
| /* Private define ------------------------------------------------------------*/ | ||||
| 
 | ||||
| @ -79,6 +80,26 @@ Diskio_drvTypeDef USER_Driver = { | ||||
| }; | ||||
| 
 | ||||
| /* 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 | ||||
| @ -125,6 +146,14 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) { | ||||
|     UNUSED(pdrv); | ||||
|     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_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_spi_release(&furi_hal_spi_bus_handle_sd_fast); | ||||
| 
 | ||||
|     if(single_sector && res == RES_OK) { | ||||
|         sd_cache_put(sector, (uint32_t*)buff); | ||||
|     } | ||||
| 
 | ||||
|     return res; | ||||
|     /* USER CODE END READ */ | ||||
| } | ||||
| @ -164,6 +197,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) { | ||||
|     UNUSED(pdrv); | ||||
|     DRESULT res = RES_ERROR; | ||||
| 
 | ||||
|     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; | ||||
| 
 | ||||
| @ -175,6 +210,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) { | ||||
|         res = RES_OK; | ||||
|         while(sd_get_card_state() != SdSpiStatusOK) { | ||||
|             if(furi_hal_cortex_timer_is_expired(timer)) { | ||||
|                 sd_cache_invalidate_all(); | ||||
| 
 | ||||
|                 res = RES_ERROR; | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Sergey Gavrilov
						Sergey Gavrilov