sd_spi.c 30 KB

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