sd_spi.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. #include "sd_spi.h"
  2. // #include "sector_cache.h"
  3. #include <furi.h>
  4. #include <furi_hal.h>
  5. #include <furi/core/core_defines.h>
  6. #define SD_SPI_DEBUG 1
  7. #define TAG "SdSpi"
  8. #ifdef SD_SPI_DEBUG
  9. #define sd_spi_debug(...) FURI_LOG_I(TAG, __VA_ARGS__)
  10. #else
  11. #define sd_spi_debug(...)
  12. #endif
  13. #define SD_CMD_LENGTH 6
  14. #define SD_DUMMY_BYTE 0xFF
  15. #define SD_ANSWER_RETRY_COUNT 8
  16. #define SD_IDLE_RETRY_COUNT 100
  17. #define FLAG_SET(x, y) (((x) & (y)) == (y))
  18. static bool sd_high_capacity = false;
  19. SdSpiCmdAnswer cmd_answer = {
  20. .r1 = SD_DUMMY_BYTE,
  21. .r2 = SD_DUMMY_BYTE,
  22. .r3 = SD_DUMMY_BYTE,
  23. .r4 = SD_DUMMY_BYTE,
  24. .r5 = SD_DUMMY_BYTE,
  25. };
  26. typedef enum {
  27. SdSpiDataResponceOK = 0x05,
  28. SdSpiDataResponceCRCError = 0x0B,
  29. SdSpiDataResponceWriteError = 0x0D,
  30. SdSpiDataResponceOtherError = 0xFF,
  31. } SdSpiDataResponce;
  32. typedef enum {
  33. SdSpiCmdAnswerTypeR1,
  34. SdSpiCmdAnswerTypeR1B,
  35. SdSpiCmdAnswerTypeR2,
  36. SdSpiCmdAnswerTypeR3,
  37. SdSpiCmdAnswerTypeR4R5,
  38. SdSpiCmdAnswerTypeR7,
  39. } SdSpiCmdAnswerType;
  40. typedef enum {
  41. SD_CMD0_GO_IDLE_STATE = 0,
  42. SD_CMD1_SEND_OP_COND = 1,
  43. SD_CMD8_SEND_IF_COND = 8,
  44. SD_CMD9_SEND_CSD = 9,
  45. SD_CMD10_SEND_CID = 10,
  46. SD_CMD12_STOP_TRANSMISSION = 12,
  47. SD_CMD13_SEND_STATUS = 13,
  48. SD_CMD16_SET_BLOCKLEN = 16,
  49. SD_CMD17_READ_SINGLE_BLOCK = 17,
  50. SD_CMD18_READ_MULT_BLOCK = 18,
  51. SD_CMD23_SET_BLOCK_COUNT = 23,
  52. SD_CMD24_WRITE_SINGLE_BLOCK = 24,
  53. SD_CMD25_WRITE_MULT_BLOCK = 25,
  54. SD_CMD27_PROG_CSD = 27,
  55. SD_CMD28_SET_WRITE_PROT = 28,
  56. SD_CMD29_CLR_WRITE_PROT = 29,
  57. SD_CMD30_SEND_WRITE_PROT = 30,
  58. SD_CMD32_SD_ERASE_GRP_START = 32,
  59. SD_CMD33_SD_ERASE_GRP_END = 33,
  60. SD_CMD34_UNTAG_SECTOR = 34,
  61. SD_CMD35_ERASE_GRP_START = 35,
  62. SD_CMD36_ERASE_GRP_END = 36,
  63. SD_CMD37_UNTAG_ERASE_GROUP = 37,
  64. SD_CMD38_ERASE = 38,
  65. SD_CMD41_SD_APP_OP_COND = 41,
  66. SD_CMD42_LOCK_UNLOCK = 42,
  67. SD_CMD55_APP_CMD = 55,
  68. SD_CMD58_READ_OCR = 58,
  69. } SdSpiCmd;
  70. /** Data tokens */
  71. typedef enum {
  72. SD_TOKEN_START_DATA_SINGLE_BLOCK_READ = 0xFE,
  73. SD_TOKEN_START_DATA_MULTIPLE_BLOCK_READ = 0xFE,
  74. SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE = 0xFE,
  75. SD_TOKEN_START_DATA_MULTIPLE_BLOCK_WRITE = 0xFC,
  76. SD_TOKEN_STOP_DATA_MULTIPLE_BLOCK_WRITE = 0xFD,
  77. } SdSpiToken;
  78. static inline void sd_spi_select_card() {
  79. furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, false);
  80. furi_delay_us(10); // Entry guard time for some SD cards
  81. }
  82. static inline void sd_spi_deselect_card() {
  83. furi_delay_us(10); // Exit guard time for some SD cards
  84. furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, true);
  85. }
  86. // void sd_bytes_debug(uint8_t* bytes, size_t size){
  87. // char out[size];
  88. // for(size_t i = 0; i < size; i++)
  89. // snprintf(out+i*3, 255, "%02x ", bytes[i]);
  90. // FURI_LOG_T(TAG, out);
  91. // }
  92. // void sd_byte_debug(uint8_t byte){
  93. // char out[3];
  94. // snprintf(out, 255, "%02x ", byte);
  95. // FURI_LOG_T(TAG, out);
  96. // }
  97. static void sd_spi_bus_to_ground() {
  98. furi_hal_gpio_init_ex(
  99. furi_hal_sd_spi_handle->miso,
  100. GpioModeOutputPushPull,
  101. GpioPullNo,
  102. GpioSpeedVeryHigh,
  103. GpioAltFnUnused);
  104. furi_hal_gpio_init_ex(
  105. furi_hal_sd_spi_handle->mosi,
  106. GpioModeOutputPushPull,
  107. GpioPullNo,
  108. GpioSpeedVeryHigh,
  109. GpioAltFnUnused);
  110. furi_hal_gpio_init_ex(
  111. furi_hal_sd_spi_handle->sck,
  112. GpioModeOutputPushPull,
  113. GpioPullNo,
  114. GpioSpeedVeryHigh,
  115. GpioAltFnUnused);
  116. sd_spi_select_card();
  117. furi_hal_gpio_write(furi_hal_sd_spi_handle->miso, false);
  118. furi_hal_gpio_write(furi_hal_sd_spi_handle->mosi, false);
  119. furi_hal_gpio_write(furi_hal_sd_spi_handle->sck, false);
  120. }
  121. static void sd_spi_bus_rise_up() {
  122. sd_spi_deselect_card();
  123. furi_hal_gpio_init_ex(
  124. furi_hal_sd_spi_handle->miso,
  125. GpioModeAltFunctionPushPull,
  126. GpioPullUp,
  127. GpioSpeedVeryHigh,
  128. GpioAltFn5SPI2);
  129. furi_hal_gpio_init_ex(
  130. furi_hal_sd_spi_handle->mosi,
  131. GpioModeAltFunctionPushPull,
  132. GpioPullUp,
  133. GpioSpeedVeryHigh,
  134. GpioAltFn5SPI2);
  135. furi_hal_gpio_init_ex(
  136. furi_hal_sd_spi_handle->sck,
  137. GpioModeAltFunctionPushPull,
  138. GpioPullUp,
  139. GpioSpeedVeryHigh,
  140. GpioAltFn5SPI2);
  141. }
  142. static inline uint8_t sd_spi_read_byte(void) {
  143. uint8_t responce;
  144. furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, NULL, &responce, 1, SD_TIMEOUT_MS));
  145. return responce;
  146. }
  147. static inline void sd_spi_write_byte(uint8_t data) {
  148. furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, &data, NULL, 1, SD_TIMEOUT_MS));
  149. }
  150. static inline uint8_t sd_spi_write_and_read_byte(uint8_t data) {
  151. uint8_t responce;
  152. furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, &data, &responce, 1, SD_TIMEOUT_MS));
  153. return responce;
  154. }
  155. static inline void sd_spi_write_bytes(uint8_t* data, uint32_t size) {
  156. furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, data, NULL, size, SD_TIMEOUT_MS));
  157. }
  158. static inline void sd_spi_read_bytes(uint8_t* data, uint32_t size) {
  159. furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, NULL, data, size, SD_TIMEOUT_MS));
  160. }
  161. static inline void sd_spi_write_bytes_dma(uint8_t* data, uint32_t size) {
  162. uint32_t timeout_mul = (size / 512) + 1;
  163. furi_check(furi_hal_spi_bus_trx_dma(
  164. furi_hal_sd_spi_handle, data, NULL, size, SD_TIMEOUT_MS * timeout_mul));
  165. }
  166. static inline void sd_spi_read_bytes_dma(uint8_t* data, uint32_t size) {
  167. uint32_t timeout_mul = (size / 512) + 1;
  168. furi_check(furi_hal_spi_bus_trx_dma(
  169. furi_hal_sd_spi_handle, NULL, data, size, SD_TIMEOUT_MS * timeout_mul));
  170. }
  171. static uint8_t sd_spi_wait_for_data_and_read(void) {
  172. uint8_t retry_count = SD_ANSWER_RETRY_COUNT;
  173. uint8_t responce;
  174. // Wait until we get a valid data
  175. do {
  176. responce = sd_spi_read_byte();
  177. retry_count--;
  178. } while((responce == SD_DUMMY_BYTE) && retry_count);
  179. return responce;
  180. }
  181. static SdSpiStatus sd_spi_wait_for_data(uint8_t data, uint32_t timeout_ms) {
  182. FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout_ms * 1000);
  183. uint8_t byte;
  184. do {
  185. byte = sd_spi_read_byte();
  186. if(furi_hal_cortex_timer_is_expired(timer)) {
  187. return SdSpiStatusTimeout;
  188. }
  189. } while((byte != data));
  190. return SdSpiStatusOK;
  191. }
  192. static inline void sd_spi_deselect_card_and_purge() {
  193. sd_spi_deselect_card();
  194. sd_spi_read_byte();
  195. }
  196. static inline void sd_spi_purge_crc() {
  197. sd_spi_read_byte();
  198. sd_spi_read_byte();
  199. }
  200. static SdSpiCmdAnswer
  201. sd_spi_send_cmd(SdSpiCmd cmd, uint32_t arg, uint8_t crc, SdSpiCmdAnswerType answer_type) {
  202. uint8_t frame[SD_CMD_LENGTH];
  203. cmd_answer.r1 = SD_DUMMY_BYTE;
  204. cmd_answer.r2 = SD_DUMMY_BYTE;
  205. cmd_answer.r3 = SD_DUMMY_BYTE;
  206. cmd_answer.r4 = SD_DUMMY_BYTE;
  207. cmd_answer.r5 = SD_DUMMY_BYTE;
  208. frame[0] = ((uint8_t)cmd | 0x40);
  209. frame[1] = (uint8_t)(arg >> 24);
  210. frame[2] = (uint8_t)(arg >> 16);
  211. frame[3] = (uint8_t)(arg >> 8);
  212. frame[4] = (uint8_t)(arg);
  213. frame[5] = (crc | 0x01);
  214. sd_spi_select_card();
  215. sd_spi_write_bytes(frame, sizeof(frame));
  216. switch(answer_type) {
  217. case SdSpiCmdAnswerTypeR1:
  218. cmd_answer.r1 = sd_spi_wait_for_data_and_read();
  219. break;
  220. case SdSpiCmdAnswerTypeR1B:
  221. cmd_answer.r1 = sd_spi_wait_for_data_and_read();
  222. // reassert card
  223. sd_spi_deselect_card();
  224. furi_delay_us(1000);
  225. sd_spi_deselect_card();
  226. // and wait for it to be ready
  227. while(sd_spi_read_byte() != 0xFF) {
  228. };
  229. break;
  230. case SdSpiCmdAnswerTypeR2:
  231. cmd_answer.r1 = sd_spi_wait_for_data_and_read();
  232. cmd_answer.r2 = sd_spi_read_byte();
  233. break;
  234. case SdSpiCmdAnswerTypeR3:
  235. case SdSpiCmdAnswerTypeR7:
  236. cmd_answer.r1 = sd_spi_wait_for_data_and_read();
  237. cmd_answer.r2 = sd_spi_read_byte();
  238. cmd_answer.r3 = sd_spi_read_byte();
  239. cmd_answer.r4 = sd_spi_read_byte();
  240. cmd_answer.r5 = sd_spi_read_byte();
  241. break;
  242. default:
  243. break;
  244. }
  245. return cmd_answer;
  246. }
  247. static SdSpiDataResponce sd_spi_get_data_response(uint32_t timeout_ms) {
  248. SdSpiDataResponce responce = sd_spi_read_byte();
  249. // read busy response byte
  250. sd_spi_read_byte();
  251. switch(responce & 0x1F) {
  252. case SdSpiDataResponceOK:
  253. // TODO: check timings
  254. sd_spi_deselect_card();
  255. sd_spi_select_card();
  256. // wait for 0xFF
  257. if(sd_spi_wait_for_data(0xFF, timeout_ms) == SdSpiStatusOK) {
  258. return SdSpiDataResponceOK;
  259. } else {
  260. return SdSpiDataResponceOtherError;
  261. }
  262. case SdSpiDataResponceCRCError:
  263. return SdSpiDataResponceCRCError;
  264. case SdSpiDataResponceWriteError:
  265. return SdSpiDataResponceWriteError;
  266. default:
  267. return SdSpiDataResponceOtherError;
  268. }
  269. }
  270. static SdSpiStatus sd_spi_init_spi_mode_v1(void) {
  271. SdSpiCmdAnswer response;
  272. uint8_t retry_count = 0;
  273. sd_spi_debug("Init SD card in SPI mode v1");
  274. do {
  275. retry_count++;
  276. // CMD55 (APP_CMD) before any ACMD command: R1 response (0x00: no errors)
  277. sd_spi_send_cmd(SD_CMD55_APP_CMD, 0, 0xFF, SdSpiCmdAnswerTypeR1);
  278. sd_spi_deselect_card_and_purge();
  279. // ACMD41 (SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors)
  280. response = sd_spi_send_cmd(SD_CMD41_SD_APP_OP_COND, 0, 0xFF, SdSpiCmdAnswerTypeR1);
  281. sd_spi_deselect_card_and_purge();
  282. if(retry_count >= SD_IDLE_RETRY_COUNT) {
  283. return SdSpiStatusError;
  284. }
  285. } while(response.r1 == SdSpi_R1_IN_IDLE_STATE);
  286. sd_spi_debug("Init SD card in SPI mode v1 done");
  287. return SdSpiStatusOK;
  288. }
  289. static SdSpiStatus sd_spi_init_spi_mode_v2(void) {
  290. SdSpiCmdAnswer response;
  291. uint8_t retry_count = 0;
  292. sd_spi_debug("Init SD card in SPI mode v2");
  293. do {
  294. retry_count++;
  295. // CMD55 (APP_CMD) before any ACMD command: R1 response (0x00: no errors)
  296. sd_spi_send_cmd(SD_CMD55_APP_CMD, 0, 0xFF, SdSpiCmdAnswerTypeR1);
  297. sd_spi_deselect_card_and_purge();
  298. // ACMD41 (APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors)
  299. response =
  300. sd_spi_send_cmd(SD_CMD41_SD_APP_OP_COND, 0x40000000, 0xFF, SdSpiCmdAnswerTypeR1);
  301. sd_spi_deselect_card_and_purge();
  302. if(retry_count >= SD_IDLE_RETRY_COUNT) {
  303. sd_spi_debug("ACMD41 failed");
  304. return SdSpiStatusError;
  305. }
  306. } while(response.r1 == SdSpi_R1_IN_IDLE_STATE);
  307. if(FLAG_SET(response.r1, SdSpi_R1_ILLEGAL_COMMAND)) {
  308. sd_spi_debug("ACMD41 is illegal command");
  309. retry_count = 0;
  310. do {
  311. retry_count++;
  312. // CMD55 (APP_CMD) before any ACMD command: R1 response (0x00: no errors)
  313. response = sd_spi_send_cmd(SD_CMD55_APP_CMD, 0, 0xFF, SdSpiCmdAnswerTypeR1);
  314. sd_spi_deselect_card_and_purge();
  315. if(response.r1 != SdSpi_R1_IN_IDLE_STATE) {
  316. sd_spi_debug("CMD55 failed");
  317. return SdSpiStatusError;
  318. }
  319. // ACMD41 (SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors)
  320. response = sd_spi_send_cmd(SD_CMD41_SD_APP_OP_COND, 0, 0xFF, SdSpiCmdAnswerTypeR1);
  321. sd_spi_deselect_card_and_purge();
  322. if(retry_count >= SD_IDLE_RETRY_COUNT) {
  323. sd_spi_debug("ACMD41 failed");
  324. return SdSpiStatusError;
  325. }
  326. } while(response.r1 == SdSpi_R1_IN_IDLE_STATE);
  327. }
  328. sd_spi_debug("Init SD card in SPI mode v2 done");
  329. return SdSpiStatusOK;
  330. }
  331. static SdSpiStatus sd_spi_init_spi_mode(void) {
  332. SdSpiCmdAnswer response;
  333. uint8_t retry_count;
  334. // CMD0 (GO_IDLE_STATE) to put SD in SPI mode and
  335. // wait for In Idle State Response (R1 Format) equal to 0x01
  336. retry_count = 0;
  337. do {
  338. retry_count++;
  339. response = sd_spi_send_cmd(SD_CMD0_GO_IDLE_STATE, 0, 0x95, SdSpiCmdAnswerTypeR1);
  340. sd_spi_deselect_card_and_purge();
  341. if(retry_count >= SD_IDLE_RETRY_COUNT) {
  342. sd_spi_debug("CMD0 failed");
  343. return SdSpiStatusError;
  344. }
  345. } while(response.r1 != SdSpi_R1_IN_IDLE_STATE);
  346. // CMD8 (SEND_IF_COND) to check the power supply status
  347. // and wait until response (R7 Format) equal to 0xAA and
  348. response = sd_spi_send_cmd(SD_CMD8_SEND_IF_COND, 0x1AA, 0x87, SdSpiCmdAnswerTypeR7);
  349. sd_spi_deselect_card_and_purge();
  350. if(FLAG_SET(response.r1, SdSpi_R1_ILLEGAL_COMMAND)) {
  351. if(sd_spi_init_spi_mode_v1() != SdSpiStatusOK) {
  352. sd_spi_debug("Init mode v1 failed");
  353. return SdSpiStatusError;
  354. }
  355. sd_high_capacity = 0;
  356. } else if(response.r1 == SdSpi_R1_IN_IDLE_STATE) {
  357. if(sd_spi_init_spi_mode_v2() != SdSpiStatusOK) {
  358. sd_spi_debug("Init mode v2 failed");
  359. return SdSpiStatusError;
  360. }
  361. // CMD58 (READ_OCR) to initialize SDHC or SDXC cards: R3 response
  362. response = sd_spi_send_cmd(SD_CMD58_READ_OCR, 0, 0xFF, SdSpiCmdAnswerTypeR3);
  363. sd_spi_deselect_card_and_purge();
  364. if(response.r1 != SdSpi_R1_NO_ERROR) {
  365. sd_spi_debug("CMD58 failed");
  366. return SdSpiStatusError;
  367. }
  368. sd_high_capacity = (response.r2 & 0x40) >> 6;
  369. } else {
  370. return SdSpiStatusError;
  371. }
  372. sd_spi_debug("SD card is %s", sd_high_capacity ? "SDHC or SDXC" : "SDSC");
  373. return SdSpiStatusOK;
  374. }
  375. static SdSpiStatus sd_spi_get_csd(SD_CSD* csd) {
  376. uint16_t counter = 0;
  377. uint8_t csd_data[16];
  378. SdSpiStatus ret = SdSpiStatusError;
  379. SdSpiCmdAnswer response;
  380. // CMD9 (SEND_CSD): R1 format (0x00 is no errors)
  381. response = sd_spi_send_cmd(SD_CMD9_SEND_CSD, 0, 0xFF, SdSpiCmdAnswerTypeR1);
  382. if(response.r1 == SdSpi_R1_NO_ERROR) {
  383. if(sd_spi_wait_for_data(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ, SD_TIMEOUT_MS) ==
  384. SdSpiStatusOK) {
  385. // read CSD data
  386. for(counter = 0; counter < 16; counter++) {
  387. csd_data[counter] = sd_spi_read_byte();
  388. }
  389. sd_spi_purge_crc();
  390. /*************************************************************************
  391. CSD header decoding
  392. *************************************************************************/
  393. csd->CSDStruct = (csd_data[0] & 0xC0) >> 6;
  394. csd->Reserved1 = csd_data[0] & 0x3F;
  395. csd->TAAC = csd_data[1];
  396. csd->NSAC = csd_data[2];
  397. csd->MaxBusClkFrec = csd_data[3];
  398. csd->CardComdClasses = (csd_data[4] << 4) | ((csd_data[5] & 0xF0) >> 4);
  399. csd->RdBlockLen = csd_data[5] & 0x0F;
  400. csd->PartBlockRead = (csd_data[6] & 0x80) >> 7;
  401. csd->WrBlockMisalign = (csd_data[6] & 0x40) >> 6;
  402. csd->RdBlockMisalign = (csd_data[6] & 0x20) >> 5;
  403. csd->DSRImpl = (csd_data[6] & 0x10) >> 4;
  404. /*************************************************************************
  405. CSD v1/v2 decoding
  406. *************************************************************************/
  407. if(sd_high_capacity == 0) {
  408. csd->version.v1.Reserved1 = ((csd_data[6] & 0x0C) >> 2);
  409. csd->version.v1.DeviceSize = ((csd_data[6] & 0x03) << 10) | (csd_data[7] << 2) |
  410. ((csd_data[8] & 0xC0) >> 6);
  411. csd->version.v1.MaxRdCurrentVDDMin = (csd_data[8] & 0x38) >> 3;
  412. csd->version.v1.MaxRdCurrentVDDMax = (csd_data[8] & 0x07);
  413. csd->version.v1.MaxWrCurrentVDDMin = (csd_data[9] & 0xE0) >> 5;
  414. csd->version.v1.MaxWrCurrentVDDMax = (csd_data[9] & 0x1C) >> 2;
  415. csd->version.v1.DeviceSizeMul = ((csd_data[9] & 0x03) << 1) |
  416. ((csd_data[10] & 0x80) >> 7);
  417. } else {
  418. csd->version.v2.Reserved1 = ((csd_data[6] & 0x0F) << 2) |
  419. ((csd_data[7] & 0xC0) >> 6);
  420. csd->version.v2.DeviceSize = ((csd_data[7] & 0x3F) << 16) | (csd_data[8] << 8) |
  421. csd_data[9];
  422. csd->version.v2.Reserved2 = ((csd_data[10] & 0x80) >> 8);
  423. }
  424. csd->EraseSingleBlockEnable = (csd_data[10] & 0x40) >> 6;
  425. csd->EraseSectorSize = ((csd_data[10] & 0x3F) << 1) | ((csd_data[11] & 0x80) >> 7);
  426. csd->WrProtectGrSize = (csd_data[11] & 0x7F);
  427. csd->WrProtectGrEnable = (csd_data[12] & 0x80) >> 7;
  428. csd->Reserved2 = (csd_data[12] & 0x60) >> 5;
  429. csd->WrSpeedFact = (csd_data[12] & 0x1C) >> 2;
  430. csd->MaxWrBlockLen = ((csd_data[12] & 0x03) << 2) | ((csd_data[13] & 0xC0) >> 6);
  431. csd->WriteBlockPartial = (csd_data[13] & 0x20) >> 5;
  432. csd->Reserved3 = (csd_data[13] & 0x1F);
  433. csd->FileFormatGrouop = (csd_data[14] & 0x80) >> 7;
  434. csd->CopyFlag = (csd_data[14] & 0x40) >> 6;
  435. csd->PermWrProtect = (csd_data[14] & 0x20) >> 5;
  436. csd->TempWrProtect = (csd_data[14] & 0x10) >> 4;
  437. csd->FileFormat = (csd_data[14] & 0x0C) >> 2;
  438. csd->Reserved4 = (csd_data[14] & 0x03);
  439. csd->crc = (csd_data[15] & 0xFE) >> 1;
  440. csd->Reserved5 = (csd_data[15] & 0x01);
  441. ret = SdSpiStatusOK;
  442. }
  443. }
  444. sd_spi_deselect_card_and_purge();
  445. return ret;
  446. }
  447. static SdSpiStatus sd_spi_get_cid(SD_CID* Cid) {
  448. uint16_t counter = 0;
  449. uint8_t cid_data[16];
  450. SdSpiStatus ret = SdSpiStatusError;
  451. SdSpiCmdAnswer response;
  452. // CMD10 (SEND_CID): R1 format (0x00 is no errors)
  453. response = sd_spi_send_cmd(SD_CMD10_SEND_CID, 0, 0xFF, SdSpiCmdAnswerTypeR1);
  454. if(response.r1 == SdSpi_R1_NO_ERROR) {
  455. if(sd_spi_wait_for_data(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ, SD_TIMEOUT_MS) ==
  456. SdSpiStatusOK) {
  457. // read CID data
  458. for(counter = 0; counter < 16; counter++) {
  459. cid_data[counter] = sd_spi_read_byte();
  460. }
  461. sd_spi_purge_crc();
  462. Cid->ManufacturerID = cid_data[0];
  463. memcpy(Cid->OEM_AppliID, cid_data + 1, 2);
  464. memcpy(Cid->ProdName, cid_data + 3, 5);
  465. Cid->ProdRev = cid_data[8];
  466. Cid->ProdSN = cid_data[9] << 24;
  467. Cid->ProdSN |= cid_data[10] << 16;
  468. Cid->ProdSN |= cid_data[11] << 8;
  469. Cid->ProdSN |= cid_data[12];
  470. Cid->Reserved1 = (cid_data[13] & 0xF0) >> 4;
  471. Cid->ManufactYear = (cid_data[13] & 0x0F) << 4;
  472. Cid->ManufactYear |= (cid_data[14] & 0xF0) >> 4;
  473. Cid->ManufactMonth = (cid_data[14] & 0x0F);
  474. Cid->CID_CRC = (cid_data[15] & 0xFE) >> 1;
  475. Cid->Reserved2 = 1;
  476. ret = SdSpiStatusOK;
  477. }
  478. }
  479. sd_spi_deselect_card_and_purge();
  480. return ret;
  481. }
  482. static SdSpiStatus
  483. sd_spi_cmd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) {
  484. uint32_t block_address = address;
  485. uint32_t offset = 0;
  486. // CMD16 (SET_BLOCKLEN): R1 response (0x00: no errors)
  487. SdSpiCmdAnswer response =
  488. sd_spi_send_cmd(SD_CMD16_SET_BLOCKLEN, SD_BLOCK_SIZE, 0xFF, SdSpiCmdAnswerTypeR1);
  489. sd_spi_deselect_card_and_purge();
  490. if(response.r1 != SdSpi_R1_NO_ERROR) {
  491. return SdSpiStatusError;
  492. }
  493. if(!sd_high_capacity) {
  494. block_address = address * SD_BLOCK_SIZE;
  495. }
  496. while(blocks--) {
  497. // CMD17 (READ_SINGLE_BLOCK): R1 response (0x00: no errors)
  498. response =
  499. sd_spi_send_cmd(SD_CMD17_READ_SINGLE_BLOCK, block_address, 0xFF, SdSpiCmdAnswerTypeR1);
  500. if(response.r1 != SdSpi_R1_NO_ERROR) {
  501. sd_spi_deselect_card_and_purge();
  502. return SdSpiStatusError;
  503. }
  504. // Wait for the data start token
  505. if(sd_spi_wait_for_data(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ, timeout_ms) ==
  506. SdSpiStatusOK) {
  507. // Read the data block
  508. sd_spi_read_bytes_dma((uint8_t*)data + offset, SD_BLOCK_SIZE);
  509. sd_spi_purge_crc();
  510. // increase offset
  511. offset += SD_BLOCK_SIZE;
  512. // increase block address
  513. if(sd_high_capacity) {
  514. block_address += 1;
  515. } else {
  516. block_address += SD_BLOCK_SIZE;
  517. }
  518. } else {
  519. sd_spi_deselect_card_and_purge();
  520. return SdSpiStatusError;
  521. }
  522. sd_spi_deselect_card_and_purge();
  523. }
  524. return SdSpiStatusOK;
  525. }
  526. static SdSpiStatus sd_spi_cmd_write_blocks(
  527. uint32_t* data,
  528. uint32_t address,
  529. uint32_t blocks,
  530. uint32_t timeout_ms) {
  531. uint32_t block_address = address;
  532. uint32_t offset = 0;
  533. // CMD16 (SET_BLOCKLEN): R1 response (0x00: no errors)
  534. SdSpiCmdAnswer response =
  535. sd_spi_send_cmd(SD_CMD16_SET_BLOCKLEN, SD_BLOCK_SIZE, 0xFF, SdSpiCmdAnswerTypeR1);
  536. sd_spi_deselect_card_and_purge();
  537. if(response.r1 != SdSpi_R1_NO_ERROR) {
  538. return SdSpiStatusError;
  539. }
  540. if(!sd_high_capacity) {
  541. block_address = address * SD_BLOCK_SIZE;
  542. }
  543. while(blocks--) {
  544. // CMD24 (WRITE_SINGLE_BLOCK): R1 response (0x00: no errors)
  545. response = sd_spi_send_cmd(
  546. SD_CMD24_WRITE_SINGLE_BLOCK, block_address, 0xFF, SdSpiCmdAnswerTypeR1);
  547. if(response.r1 != SdSpi_R1_NO_ERROR) {
  548. sd_spi_deselect_card_and_purge();
  549. return SdSpiStatusError;
  550. }
  551. // Send dummy byte for NWR timing : one byte between CMD_WRITE and TOKEN
  552. // TODO: check bytes count
  553. sd_spi_write_byte(SD_DUMMY_BYTE);
  554. sd_spi_write_byte(SD_DUMMY_BYTE);
  555. // Send the data start token
  556. sd_spi_write_byte(SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE);
  557. sd_spi_write_bytes_dma((uint8_t*)data + offset, SD_BLOCK_SIZE);
  558. sd_spi_purge_crc();
  559. // Read data response
  560. SdSpiDataResponce data_responce = sd_spi_get_data_response(timeout_ms);
  561. sd_spi_deselect_card_and_purge();
  562. if(data_responce != SdSpiDataResponceOK) {
  563. return SdSpiStatusError;
  564. }
  565. // increase offset
  566. offset += SD_BLOCK_SIZE;
  567. // increase block address
  568. if(sd_high_capacity) {
  569. block_address += 1;
  570. } else {
  571. block_address += SD_BLOCK_SIZE;
  572. }
  573. }
  574. return SdSpiStatusOK;
  575. }
  576. uint8_t sd_max_mount_retry_count() {
  577. return 10;
  578. }
  579. SdSpiStatus sd_init(bool power_reset) {
  580. sd_spi_debug("sd_init");
  581. furi_hal_spi_acquire(&furi_hal_spi_bus_handle_external);
  582. furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_external;
  583. furi_hal_gpio_init(&gpio_ext_pa4,GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh);
  584. if(power_reset) {
  585. sd_spi_debug("Power reset");
  586. // disable power and set low on all bus pins
  587. furi_hal_power_disable_external_3_3v();
  588. sd_spi_bus_to_ground();
  589. hal_sd_detect_set_low();
  590. furi_delay_ms(250);
  591. // reinit bus and enable power
  592. sd_spi_bus_rise_up();
  593. hal_sd_detect_init();
  594. furi_hal_power_enable_external_3_3v();
  595. furi_delay_ms(100);
  596. }
  597. SdSpiStatus status = SdSpiStatusError;
  598. // Send 80 dummy clocks with CS high
  599. sd_spi_deselect_card();
  600. for(uint8_t i = 0; i < 80; i++) {
  601. sd_spi_write_byte(SD_DUMMY_BYTE);
  602. }
  603. for(uint8_t i = 0; i < 128; i++) {
  604. // for(uint8_t i = 0; i < 4; i++) {
  605. status = sd_spi_init_spi_mode();
  606. if(status == SdSpiStatusOK) {
  607. // SD initialized and init to SPI mode properly
  608. sd_spi_debug("SD init OK after %d retries", i);
  609. break;
  610. }
  611. }
  612. status = sd_get_card_state();
  613. furi_hal_sd_spi_handle = NULL;
  614. // furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_slow);
  615. furi_hal_spi_release(&furi_hal_spi_bus_handle_external);
  616. // Init sector cache
  617. // sector_cache_init();
  618. return status;
  619. }
  620. SdSpiStatus sd_get_card_state(void) {
  621. SdSpiCmdAnswer response;
  622. // Send CMD13 (SEND_STATUS) to get SD status
  623. response = sd_spi_send_cmd(SD_CMD13_SEND_STATUS, 0, 0xFF, SdSpiCmdAnswerTypeR2);
  624. sd_spi_deselect_card_and_purge();
  625. // Return status OK if response is valid
  626. if((response.r1 == SdSpi_R1_NO_ERROR) && (response.r2 == SdSpi_R2_NO_ERROR || response.r2 == SdSpi_R2_CARD_LOCKED)) {
  627. return SdSpiStatusOK;
  628. }
  629. return SdSpiStatusError;
  630. }
  631. SdSpiStatus sd_get_card_info(SD_CardInfo* card_info) {
  632. SdSpiStatus status;
  633. status = sd_spi_get_csd(&(card_info->Csd));
  634. if(status != SdSpiStatusOK) {
  635. return status;
  636. }
  637. status = sd_spi_get_cid(&(card_info->Cid));
  638. if(status != SdSpiStatusOK) {
  639. return status;
  640. }
  641. if(sd_high_capacity == 1) {
  642. card_info->LogBlockSize = 512;
  643. card_info->CardBlockSize = 512;
  644. card_info->CardCapacity = ((uint64_t)card_info->Csd.version.v2.DeviceSize + 1UL) * 1024UL *
  645. (uint64_t)card_info->LogBlockSize;
  646. card_info->LogBlockNbr = (card_info->CardCapacity) / (card_info->LogBlockSize);
  647. } else {
  648. card_info->CardCapacity = (card_info->Csd.version.v1.DeviceSize + 1);
  649. card_info->CardCapacity *= (1UL << (card_info->Csd.version.v1.DeviceSizeMul + 2));
  650. card_info->LogBlockSize = 512;
  651. card_info->CardBlockSize = 1UL << (card_info->Csd.RdBlockLen);
  652. card_info->CardCapacity *= card_info->CardBlockSize;
  653. card_info->LogBlockNbr = (card_info->CardCapacity) / (card_info->LogBlockSize);
  654. }
  655. return status;
  656. }
  657. SdSpiStatus sd_set_pwd(char* pwd) {
  658. sd_spi_debug("sd_set_pwd");
  659. sd_spi_debug(pwd);
  660. SdSpiStatus status = SdSpiStatusError;
  661. SdSpiCmdAnswer response;
  662. furi_hal_spi_acquire(&furi_hal_spi_bus_handle_external);
  663. furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_external;
  664. response = sd_spi_send_cmd(SD_CMD42_LOCK_UNLOCK, 0, 0xFF, SdSpiCmdAnswerTypeR1);
  665. if(response.r1 == SdSpi_R1_NO_ERROR) {
  666. sd_spi_debug("SD_CMD42_LOCK_UNLOCK R1_NO_ERROR");
  667. uint8_t data[512] = {0xFF};
  668. data[0] = 0x05;
  669. data[1] = strlen(pwd);
  670. for(int i = 0; i < (int)strlen(pwd); i++){
  671. data[i+2] = pwd[i];
  672. }
  673. sd_spi_write_byte(SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE);
  674. sd_spi_write_bytes_dma(data, SD_BLOCK_SIZE);
  675. sd_spi_purge_crc();
  676. SdSpiDataResponce data_responce = sd_spi_get_data_response(SD_TIMEOUT_MS);
  677. sd_spi_deselect_card_and_purge();
  678. if(data_responce == SdSpiDataResponceOK) {
  679. sd_spi_debug("SD_CMD42_LOCK_UNLOCK SdSpiDataResponceOK");
  680. if(sd_get_card_state()==SdSpiStatusOK) {
  681. if(cmd_answer.r2==SdSpi_R2_CARD_LOCKED) { status = SdSpiStatusOK; }
  682. }
  683. }
  684. else { sd_spi_debug("SD_CMD42_LOCK_UNLOCK SdSpiDataResponceError"); }
  685. }
  686. else { sd_spi_debug("SD_CMD42_LOCK_UNLOCK R1_ERROR"); }
  687. furi_hal_sd_spi_handle = NULL;
  688. furi_hal_spi_release(&furi_hal_spi_bus_handle_external);
  689. return status;
  690. }
  691. SdSpiStatus sd_clr_pwd(char* pwd) {
  692. sd_spi_debug("sd_clr_pwd");
  693. sd_spi_debug(pwd);
  694. SdSpiStatus status = SdSpiStatusError;
  695. SdSpiCmdAnswer response;
  696. furi_hal_spi_acquire(&furi_hal_spi_bus_handle_external);
  697. furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_external;
  698. response = sd_spi_send_cmd(SD_CMD42_LOCK_UNLOCK, 0, 0xFF, SdSpiCmdAnswerTypeR1);
  699. if(response.r1 == SdSpi_R1_NO_ERROR) {
  700. sd_spi_debug("SD_CMD42_LOCK_UNLOCK R1_NO_ERROR");
  701. uint8_t data[512] = {0xFF};
  702. data[0] = 0x02;
  703. data[1] = strlen(pwd);
  704. for(int i = 0; i < (int)strlen(pwd); i++){
  705. data[i+2] = pwd[i];
  706. }
  707. sd_spi_write_byte(SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE);
  708. sd_spi_write_bytes_dma(data, SD_BLOCK_SIZE);
  709. sd_spi_purge_crc();
  710. SdSpiDataResponce data_responce = sd_spi_get_data_response(SD_TIMEOUT_MS);
  711. sd_spi_deselect_card_and_purge();
  712. if(data_responce == SdSpiDataResponceOK) {
  713. sd_spi_debug("SD_CMD42_LOCK_UNLOCK SdSpiDataResponceOK");
  714. if(sd_get_card_state()==SdSpiStatusOK) {
  715. if(cmd_answer.r2==SdSpi_R2_NO_ERROR) { status = SdSpiStatusOK; }
  716. }
  717. }
  718. else { sd_spi_debug("SD_CMD42_LOCK_UNLOCK SdSpiDataResponceError"); }
  719. }
  720. else { sd_spi_debug("SD_CMD42_LOCK_UNLOCK R1_ERROR"); }
  721. furi_hal_sd_spi_handle = NULL;
  722. furi_hal_spi_release(&furi_hal_spi_bus_handle_external);
  723. return status;
  724. }
  725. SdSpiStatus sd_force_erase(void) {
  726. SdSpiStatus status = SdSpiStatusError;
  727. SdSpiCmdAnswer response;
  728. furi_hal_spi_acquire(&furi_hal_spi_bus_handle_external);
  729. furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_external;
  730. sd_spi_debug("SD_CMD16_SET_BLOCKLEN 1");
  731. sd_spi_send_cmd(SD_CMD16_SET_BLOCKLEN, 1, 0xFF, SdSpiCmdAnswerTypeR1);
  732. sd_spi_deselect_card_and_purge();
  733. sd_spi_debug("SD_CMD42_LOCK_UNLOCK");
  734. response = sd_spi_send_cmd(SD_CMD42_LOCK_UNLOCK, 0, 0xFF, SdSpiCmdAnswerTypeR1);
  735. if(response.r1 == SdSpi_R1_NO_ERROR) {
  736. sd_spi_debug("SD_CMD42_LOCK_UNLOCK R1_NO_ERROR");
  737. uint8_t data[2] = {0xfe,0x08};
  738. sd_spi_write_bytes_dma(data, sizeof(data));
  739. sd_spi_purge_crc();
  740. SdSpiDataResponce data_responce = sd_spi_get_data_response(SD_TIMEOUT_MS);
  741. sd_spi_deselect_card_and_purge();
  742. status = SdSpiStatusOK;
  743. if(data_responce == SdSpiDataResponceOK) {
  744. sd_spi_debug("SD_CMD42_LOCK_UNLOCK SdSpiDataResponceOK");
  745. if(sd_get_card_state()==SdSpiStatusOK) {
  746. if(cmd_answer.r2==SdSpi_R2_NO_ERROR) { status = SdSpiStatusOK; }
  747. }
  748. }
  749. else { sd_spi_debug("SD_CMD42_LOCK_UNLOCK SdSpiDataResponceError"); }
  750. }
  751. else { sd_spi_debug("SD_CMD42_LOCK_UNLOCK R1_ERROR"); }
  752. furi_hal_sd_spi_handle = NULL;
  753. furi_hal_spi_release(&furi_hal_spi_bus_handle_external);
  754. return status;
  755. }
  756. SdSpiStatus
  757. sd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) {
  758. SdSpiStatus status = sd_spi_cmd_read_blocks(data, address, blocks, timeout_ms);
  759. return status;
  760. }
  761. SdSpiStatus
  762. sd_write_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) {
  763. SdSpiStatus status = sd_spi_cmd_write_blocks(data, address, blocks, timeout_ms);
  764. return status;
  765. }
  766. SdSpiStatus sd_get_cid(SD_CID* cid) {
  767. SdSpiStatus status;
  768. furi_hal_spi_acquire(&furi_hal_spi_bus_handle_external);
  769. furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_external;
  770. memset(cid, 0, sizeof(SD_CID));
  771. status = sd_spi_get_cid(cid);
  772. furi_hal_sd_spi_handle = NULL;
  773. furi_hal_spi_release(&furi_hal_spi_bus_handle_external);
  774. return status;
  775. }