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_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; | ||||||
| } | } | ||||||
|  | |||||||
| @ -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, | ||||||
|  | |||||||
| @ -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; | ||||||
|             } |             } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Sergey Gavrilov
						Sergey Gavrilov