user_diskio.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #include "user_diskio.h"
  2. #include <furi_hal.h>
  3. #include "sector_cache.h"
  4. static volatile DSTATUS Stat = STA_NOINIT;
  5. static DSTATUS driver_check_status(BYTE lun) {
  6. UNUSED(lun);
  7. Stat = STA_NOINIT;
  8. if(sd_get_card_state() == SdSpiStatusOK) {
  9. Stat &= ~STA_NOINIT;
  10. }
  11. return Stat;
  12. }
  13. static DSTATUS driver_initialize(BYTE pdrv);
  14. static DSTATUS driver_status(BYTE pdrv);
  15. static DRESULT driver_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
  16. static DRESULT driver_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
  17. static DRESULT driver_ioctl(BYTE pdrv, BYTE cmd, void* buff);
  18. Diskio_drvTypeDef sd_fatfs_driver = {
  19. driver_initialize,
  20. driver_status,
  21. driver_read,
  22. driver_write,
  23. driver_ioctl,
  24. };
  25. static inline bool sd_cache_get(uint32_t address, uint32_t* data) {
  26. uint8_t* cached_data = sector_cache_get(address);
  27. if(cached_data) {
  28. memcpy(data, cached_data, SD_BLOCK_SIZE);
  29. return true;
  30. }
  31. return false;
  32. }
  33. static inline void sd_cache_put(uint32_t address, uint32_t* data) {
  34. sector_cache_put(address, (uint8_t*)data);
  35. }
  36. static inline void sd_cache_invalidate_range(uint32_t start_sector, uint32_t end_sector) {
  37. sector_cache_invalidate_range(start_sector, end_sector);
  38. }
  39. static inline void sd_cache_invalidate_all() {
  40. sector_cache_init();
  41. }
  42. static bool sd_device_read(uint32_t* buff, uint32_t sector, uint32_t count) {
  43. bool result = false;
  44. furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
  45. furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
  46. if(sd_read_blocks(buff, sector, count, SD_TIMEOUT_MS) == SdSpiStatusOK) {
  47. FuriHalCortexTimer timer = furi_hal_cortex_timer_get(SD_TIMEOUT_MS * 1000);
  48. /* wait until the read operation is finished */
  49. result = true;
  50. while(sd_get_card_state() != SdSpiStatusOK) {
  51. if(furi_hal_cortex_timer_is_expired(timer)) {
  52. result = false;
  53. break;
  54. }
  55. }
  56. }
  57. furi_hal_sd_spi_handle = NULL;
  58. furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
  59. return result;
  60. }
  61. static bool sd_device_write(uint32_t* buff, uint32_t sector, uint32_t count) {
  62. bool result = false;
  63. furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
  64. furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
  65. if(sd_write_blocks(buff, sector, count, SD_TIMEOUT_MS) == SdSpiStatusOK) {
  66. FuriHalCortexTimer timer = furi_hal_cortex_timer_get(SD_TIMEOUT_MS * 1000);
  67. /* wait until the Write operation is finished */
  68. result = true;
  69. while(sd_get_card_state() != SdSpiStatusOK) {
  70. if(furi_hal_cortex_timer_is_expired(timer)) {
  71. sd_cache_invalidate_all();
  72. result = false;
  73. break;
  74. }
  75. }
  76. }
  77. furi_hal_sd_spi_handle = NULL;
  78. furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
  79. return result;
  80. }
  81. /**
  82. * @brief Initializes a Drive
  83. * @param pdrv: Physical drive number (0..)
  84. * @retval DSTATUS: Operation status
  85. */
  86. static DSTATUS driver_initialize(BYTE pdrv) {
  87. furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
  88. furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
  89. DSTATUS status = driver_check_status(pdrv);
  90. furi_hal_sd_spi_handle = NULL;
  91. furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
  92. return status;
  93. }
  94. /**
  95. * @brief Gets Disk Status
  96. * @param pdrv: Physical drive number (0..)
  97. * @retval DSTATUS: Operation status
  98. */
  99. static DSTATUS driver_status(BYTE pdrv) {
  100. UNUSED(pdrv);
  101. return Stat;
  102. }
  103. /**
  104. * @brief Reads Sector(s)
  105. * @param pdrv: Physical drive number (0..)
  106. * @param *buff: Data buffer to store read data
  107. * @param sector: Sector address (LBA)
  108. * @param count: Number of sectors to read (1..128)
  109. * @retval DRESULT: Operation result
  110. */
  111. static DRESULT driver_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
  112. UNUSED(pdrv);
  113. bool result;
  114. bool single_sector = count == 1;
  115. if(single_sector) {
  116. if(sd_cache_get(sector, (uint32_t*)buff)) {
  117. return RES_OK;
  118. }
  119. }
  120. result = sd_device_read((uint32_t*)buff, (uint32_t)(sector), count);
  121. if(!result) {
  122. uint8_t counter = sd_max_mount_retry_count();
  123. while(result == false && counter > 0 && hal_sd_detect()) {
  124. SdSpiStatus status;
  125. if((counter % 2) == 0) {
  126. // power reset sd card
  127. status = sd_init(true);
  128. } else {
  129. status = sd_init(false);
  130. }
  131. if(status == SdSpiStatusOK) {
  132. result = sd_device_read((uint32_t*)buff, (uint32_t)(sector), count);
  133. }
  134. counter--;
  135. }
  136. }
  137. if(single_sector && result == true) {
  138. sd_cache_put(sector, (uint32_t*)buff);
  139. }
  140. return result ? RES_OK : RES_ERROR;
  141. }
  142. /**
  143. * @brief Writes Sector(s)
  144. * @param pdrv: Physical drive number (0..)
  145. * @param *buff: Data to be written
  146. * @param sector: Sector address (LBA)
  147. * @param count: Number of sectors to write (1..128)
  148. * @retval DRESULT: Operation result
  149. */
  150. static DRESULT driver_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
  151. UNUSED(pdrv);
  152. bool result;
  153. sd_cache_invalidate_range(sector, sector + count);
  154. result = sd_device_write((uint32_t*)buff, (uint32_t)(sector), count);
  155. if(!result) {
  156. uint8_t counter = sd_max_mount_retry_count();
  157. while(result == false && counter > 0 && hal_sd_detect()) {
  158. SdSpiStatus status;
  159. if((counter % 2) == 0) {
  160. // power reset sd card
  161. status = sd_init(true);
  162. } else {
  163. status = sd_init(false);
  164. }
  165. if(status == SdSpiStatusOK) {
  166. result = sd_device_write((uint32_t*)buff, (uint32_t)(sector), count);
  167. }
  168. counter--;
  169. }
  170. }
  171. return result ? RES_OK : RES_ERROR;
  172. }
  173. /**
  174. * @brief I/O control operation
  175. * @param pdrv: Physical drive number (0..)
  176. * @param cmd: Control code
  177. * @param *buff: Buffer to send/receive control data
  178. * @retval DRESULT: Operation result
  179. */
  180. static DRESULT driver_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
  181. UNUSED(pdrv);
  182. DRESULT res = RES_ERROR;
  183. SD_CardInfo CardInfo;
  184. if(Stat & STA_NOINIT) return RES_NOTRDY;
  185. furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
  186. furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
  187. switch(cmd) {
  188. /* Make sure that no pending write process */
  189. case CTRL_SYNC:
  190. res = RES_OK;
  191. break;
  192. /* Get number of sectors on the disk (DWORD) */
  193. case GET_SECTOR_COUNT:
  194. sd_get_card_info(&CardInfo);
  195. *(DWORD*)buff = CardInfo.LogBlockNbr;
  196. res = RES_OK;
  197. break;
  198. /* Get R/W sector size (WORD) */
  199. case GET_SECTOR_SIZE:
  200. sd_get_card_info(&CardInfo);
  201. *(WORD*)buff = CardInfo.LogBlockSize;
  202. res = RES_OK;
  203. break;
  204. /* Get erase block size in unit of sector (DWORD) */
  205. case GET_BLOCK_SIZE:
  206. sd_get_card_info(&CardInfo);
  207. *(DWORD*)buff = CardInfo.LogBlockSize;
  208. res = RES_OK;
  209. break;
  210. default:
  211. res = RES_PARERR;
  212. }
  213. furi_hal_sd_spi_handle = NULL;
  214. furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
  215. return res;
  216. }