A C++ toolbox repo until the pair uTL/dTL arives
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

721 lines
26 KiB

  1. /*!
  2. * \file drv/sd_spi.h
  3. * \brief
  4. * SD card driver using SPI interface
  5. *
  6. * \copyright Copyright (C) 2021 Christos Choutouridis <christos@choutouridis.net>
  7. *
  8. * <dl class=\"section copyright\"><dt>License</dt><dd>
  9. * The MIT License (MIT)
  10. *
  11. * Permission is hereby granted, free of charge, to any person obtaining a copy
  12. * of this software and associated documentation files (the "Software"), to deal
  13. * in the Software without restriction, including without limitation the rights
  14. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15. * copies of the Software, and to permit persons to whom the Software is
  16. * furnished to do so, subject to the following conditions:
  17. *
  18. * The above copyright notice and this permission notice shall be included in all
  19. * copies or substantial portions of the Software.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  24. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  27. * SOFTWARE.
  28. * </dd></dl>
  29. */
  30. #ifndef TBX_DRV_SD_SPI_H_
  31. #define TBX_DRV_SD_SPI_H_
  32. #include <core/core.h>
  33. #include <core/crtp.h>
  34. //#include <drv/diskio.h>
  35. #include <ctime>
  36. #include <utility>
  37. namespace tbx {
  38. /*!
  39. *
  40. * http://elm-chan.org/docs/mmc/mmc_e.html
  41. *
  42. * CRTP requirements
  43. * bool WP_impl (); // write protect, true => write protect
  44. * bool CD_impl (); // check disk present, true => present
  45. * void CS_impl (bool select); // Chip select, true => select
  46. * void PWR_impl(bool state); // SD power, true => power the card
  47. * data_type SPI_rw_impl (data_type); // SPI read-write functionality
  48. * bool SPI_set_clk_impl(uint32_t clk); // SPI set clock functionality
  49. * clock_t clock_impl(); // get system's CPU time
  50. */
  51. template <typename Impl_t>
  52. class sd_card {
  53. _CRTP_IMPL(Impl_t);
  54. using data_type = uint8_t;
  55. // Driver settings
  56. constexpr static clock_t SD_WaitTimeout = 500; // 500 [CPU time]
  57. constexpr static clock_t SD_PowerTimeout= 250; // 250 [CPU time]
  58. constexpr static clock_t SD_RxTimeout = 100; // 100 [CPU time]
  59. constexpr static clock_t SD_InitTimeout = 2000; // 2000 [CPU time]
  60. constexpr static uint32_t MaxInitClock = 400000; // 400000 [Hz]
  61. // MMC/SDC definitions
  62. constexpr static data_type CMD_MSB = 0x40;
  63. constexpr static data_type CMD_CRC_LSB = 0x01;
  64. constexpr static data_type CMD0 = (CMD_MSB | 0); //!< GO_IDLE_STATE
  65. constexpr static data_type CMD1 = (CMD_MSB | 1); //!< SEND_OP_COND (MMC)
  66. constexpr static data_type CMD8 = (CMD_MSB | 8); //!< SEND_IF_COND
  67. constexpr static data_type CMD9 = (CMD_MSB | 9); //!< SEND_CSD
  68. constexpr static data_type CMD10 = (CMD_MSB | 10); //!< SEND_CID
  69. constexpr static data_type CMD12 = (CMD_MSB | 12); //!< STOP_TRANSMISSION
  70. constexpr static data_type CMD16 = (CMD_MSB | 16); //!< SET_BLOCKLEN
  71. constexpr static data_type CMD17 = (CMD_MSB | 17); //!< READ_SINGLE_BLOCK
  72. constexpr static data_type CMD18 = (CMD_MSB | 18); //!< READ_MULTIPLE_BLOCK
  73. constexpr static data_type CMD23 = (CMD_MSB | 23); //!< SET_BLOCK_COUNT (MMC)
  74. constexpr static data_type CMD24 = (CMD_MSB | 24); //!< WRITE_BLOCK
  75. constexpr static data_type CMD25 = (CMD_MSB | 25); //!< WRITE_MULTIPLE_BLOCK
  76. constexpr static data_type CMD55 = (CMD_MSB | 55); //!< APP_CMD
  77. constexpr static data_type CMD58 = (CMD_MSB | 58); //!< READ_OCR
  78. constexpr static data_type ACMD13 = (0xC0 + 13); //!< SD_STATUS (SDC)
  79. constexpr static data_type ACMD23 = (0xC0 + 23); //!< SET_WR_BLK_ERASE_COUNT (SDC)
  80. constexpr static data_type ACMD41 = (0xC0 + 41); //!< SEND_OP_COND (SDC)
  81. constexpr static data_type R1_READY_STATE = 0x00; //!< status for card in the ready state
  82. constexpr static data_type R1_IDLE_STATE = 0x01; //!< status for card in the idle state
  83. constexpr static data_type R1_ILLEGAL_COMMAND = 0x04; //!< status bit for illegal command
  84. constexpr static data_type DATA_START_BLOCK = 0xFE; //!< start data token for read or write single block
  85. constexpr static data_type STOP_TRAN_TOKEN = 0xFD; //!< stop token for write multiple blocks
  86. constexpr static data_type WRITE_MULTIPLE_TOKEN= 0xFC; //!< start data token for write multiple blocks
  87. constexpr static data_type DATA_RES_MASK = 0x1F; //!< mask for data response tokens after a write block operation
  88. constexpr static data_type DATA_RES_ACCEPTED = 0x05; //!< write data accepted token
  89. // MMC card type flags (MMC_GET_TYPE)
  90. //! \note
  91. //! These types are compatible with FatFS types
  92. constexpr static data_type CT_NONE = 0x00;
  93. constexpr static data_type CT_MMC = 0x01; //!< MMC ver 3
  94. constexpr static data_type CT_SD1 = 0x02; //!< SD ver 1
  95. constexpr static data_type CT_SD2 = 0x04; //!< SD ver 2
  96. constexpr static data_type CT_SDC = (CT_SD1|CT_SD2); //!< SD
  97. constexpr static data_type CT_BLOCK = 0x08; //!< Block addressing
  98. public:
  99. enum status_t : uint8_t {
  100. ST_OK =0,
  101. ST_NOINIT = 1,
  102. ST_NODISK = 2,
  103. ST_WRPROTECT = 3,
  104. ST_ERROR = 4
  105. };
  106. enum ioctl_cmd {
  107. // Fatfs compatibility
  108. IOCTL_SYNC =0, //!< Flush disk cache (for write functions)
  109. IOCTL_GET_SECTOR_COUNT =1, //!< Get media size (for only f_mkfs())
  110. IOCTL_GET_SECTOR_SIZE =2, //!< Get sector size (for multiple sector size (_MAX_SS >= 1024))
  111. IOCTL_GET_BLOCK_SIZE =3, //!< Get erase block size (for only f_mkfs())
  112. IOCTL_ERASE_SECTOR =4, //!< Force erased a block of sectors (for only _USE_ERASE)
  113. // Generics
  114. IOCTL_POWER =5, //!< Get/Set power status
  115. IOCTL_LOCK =6, //!< Lock/Unlock media removal
  116. IOCTL_EJECT =7, //!< Eject media
  117. IOCTL_FORMAT =8, //!< Create physical format on the media
  118. // SD/MMC specific
  119. IOCTL_MMC_GET_TYPE =10, //!< Get card type
  120. IOCTL_MMC_GET_CSD =11, //!< Get CSD
  121. IOCTL_MMC_GET_CID =12, //!< Get CID
  122. IOCTL_MMC_GET_OCR =13, //!< Get OCR
  123. IOCTL_MMC_GET_SDSTAT =14, //!< Get SD status
  124. };
  125. public:
  126. sd_card() :
  127. status{ST_NOINIT} { }
  128. sd_card(const sd_card&) = delete;
  129. sd_card& operator=(const sd_card&) = delete;
  130. private:
  131. /*!
  132. * \brief
  133. * Calculate the maximum data transfer rate per one data line
  134. * from the CSD.
  135. * TRAN_SPEED is the CSD[103..96]
  136. *
  137. * TRAN_SPEED bit code
  138. * ---------------------------------------------------
  139. * 2:0 | transfer rate unit
  140. * | 0=100kbit/s, 1=1Mbit/s, 2=10Mbit/s,
  141. * | 3=100Mbit/s, 4... 7=reserved
  142. * ---------------------------------------------------
  143. * 6:3 | time value
  144. * --------------------------------------------------
  145. * 7 | Reserved
  146. *
  147. * \param csd Pointer to CSD array 128bit.
  148. * \return The maximum spi baud rate.
  149. */
  150. uint32_t csd2bautrate (data_type *csd) {
  151. data_type brmul = 0;
  152. uint32_t br = 100000; // 100Kbit
  153. // Mask [2..0] bits of TRAN_SPEED
  154. brmul = csd[3] & 0x07;
  155. while (brmul--)
  156. br *= 10;
  157. return br;
  158. }
  159. void delay (clock_t t) {
  160. clock_t mark = impl().clock_impl();
  161. while (impl().clock_impl() - mark < t)
  162. ;
  163. }
  164. /*!
  165. * \brief Check if SD Card is present.
  166. * \return The sd card present status
  167. * \arg false Is NOT present
  168. * \arg true Is present.
  169. */
  170. bool is_present () {
  171. return impl().CD_impl();
  172. }
  173. /*!
  174. * \brief Check if SD Card is write protected.
  175. * \return The write protect status
  176. * \arg false Is NOT write protected
  177. * \arg true Is write protected.
  178. */
  179. bool is_write_protected () {
  180. return impl().WP_impl();
  181. }
  182. /*!
  183. * \brief Powers up or down the SD Card.
  184. * \param on On/Off flag.
  185. * \return The new power state state
  186. */
  187. bool power (bool on) {
  188. impl().PWR_impl(on);
  189. return pwr_flag = on;
  190. }
  191. /*!
  192. * \brief Check if SD Card is powered.
  193. * \return The power status
  194. * \arg false The drive is not powered
  195. * \arg true The drive is powered
  196. */
  197. bool power () { return pwr_flag; }
  198. /*!
  199. * \brief Chip-select control
  200. * \param state True to Select, false to de-select.
  201. */
  202. void select() {
  203. spi_tx(0xFF);
  204. impl().CS_impl(false);
  205. spi_tx(0xFF);
  206. }
  207. /*!
  208. * \brief De-select SD Card and release SPI bus
  209. * \return None.
  210. */
  211. void release () {
  212. spi_tx(0xFF);
  213. impl().CS_impl(true);
  214. spi_tx(0xFF);
  215. }
  216. /*!
  217. * \brief Transmit a byte to SD/MMC via SPI
  218. * \param data The data to send to the SPI bus.
  219. */
  220. void spi_tx (data_type data) {
  221. impl().SPI_rw_impl (data);
  222. }
  223. /*!
  224. * \brief Receive a byte to SD/MMC via SPI.
  225. * \return The data received from SPI bus.
  226. */
  227. data_type spi_rx () {
  228. return impl().SPI_rw_impl (0xFF);
  229. }
  230. /*!
  231. * \brief Keep calling spi_rx until response \c resp.
  232. *
  233. * \param resp the response we wait for
  234. * \param timeout timeout for the operation
  235. * \return
  236. * \arg true Ready
  237. * \arg false NOT ready.
  238. */
  239. bool spi_wait_for (data_type resp, clock_t timeout) {
  240. data_type res;
  241. clock_t mark = impl().clock_impl();
  242. do
  243. res = spi_rx ();
  244. while ((res != resp) && ((impl().clock_impl() - mark) < timeout));
  245. return (res == resp);
  246. }
  247. bool activate (bool state) {
  248. if (state) {
  249. power(true); // power on with delay
  250. delay (SD_PowerTimeout);
  251. impl().CS_impl(1); // make sure CS is high
  252. for (size_t i=0 ; i<10 ; ++i) // 80 dummy clocks with DI high
  253. spi_tx(0xFF);
  254. status = ST_NOINIT; // mark the status
  255. }
  256. else {
  257. power(false); // power off
  258. impl().CS_impl(0); // keep CS pin voltage low
  259. status = ST_NOINIT; // mark the status
  260. }
  261. return state;
  262. }
  263. /*!
  264. * \brief
  265. * Receive a data packet from MMC/SD
  266. *
  267. * \param buffer Pointer to data buffer to store received data
  268. * \param n Byte count (must be multiple of 4)
  269. * \return The operation status
  270. * \arg false Fail
  271. * \arg true Success.
  272. */
  273. bool rx_datablock (data_type* buffer, size_t n) {
  274. if (! spi_wait_for(DATA_START_BLOCK, SD_RxTimeout))
  275. return false;
  276. /*!
  277. * Receive the data block into buffer and make sure
  278. * we receive multiples of 4
  279. */
  280. n += (n%4) ? 4-(n%4):0;
  281. for ( ; n>0 ; --n)
  282. *buffer++ = spi_rx ();
  283. spi_rx (); // Discard CRC
  284. spi_rx ();
  285. return true;
  286. }
  287. /*!
  288. * \brief
  289. * Transmit a data block (512bytes) to MMC/SD
  290. *
  291. * \param buffer Pointer to 512 byte data block to be transmitted
  292. * \param token Data/Stop token
  293. * \return The operation status
  294. * \arg false Fail
  295. * \arg true Success.
  296. */
  297. bool tx_datablock (const data_type* buffer, data_type token) {
  298. if (!spi_wait_for(0xFF, SD_WaitTimeout))
  299. return false;
  300. spi_tx(token); // transmit data token
  301. if (token != STOP_TRAN_TOKEN) {
  302. // if its data token, transmit the 512 byte block
  303. size_t cnt = 512;
  304. do
  305. spi_tx(*buffer++);
  306. while (--cnt);
  307. spi_tx(0xFF); // CRC (Dummy)
  308. spi_tx(0xFF);
  309. data_type r = spi_rx(); // Receive data response
  310. if ((r & DATA_RES_MASK) != DATA_RES_ACCEPTED) // If not accepted, return with error
  311. return false;
  312. }
  313. return true;
  314. }
  315. /*!
  316. * \brief
  317. * Send a command packet to SD/MMC and return the response
  318. *
  319. * \param cmd Command byte
  320. * \param arg Argument
  321. * \return The response as operation status
  322. */
  323. data_type command (data_type cmd, uint32_t arg) {
  324. data_type n, r;
  325. if (cmd & 0x80) {
  326. /*!
  327. * SD_ACMD<n> is the command sequence of CMD55-SD_CMD<n>
  328. */
  329. cmd &= 0x7F;
  330. r = command (CMD55, 0);
  331. if (r > 1)
  332. return r;
  333. }
  334. // Send command packet
  335. spi_tx (cmd); // Start + Command index
  336. spi_tx ((data_type)(arg>>24)); // Argument [31..24]
  337. spi_tx ((data_type)(arg>>16)); // Argument [23..16]
  338. spi_tx ((data_type)(arg>>8)); // Argument [15..8]
  339. spi_tx ((data_type)arg); // Argument [7..0]
  340. if (cmd == CMD0) n = 0x94; // Valid CRC for CMD0(0)
  341. else if (cmd == CMD8) n = 0x86; // Valid CRC for CMD8(0x1AA)
  342. else n = 0x00;
  343. spi_tx (n | CMD_CRC_LSB);
  344. // Receive command response
  345. if (cmd == CMD12)
  346. spi_rx (); // Skip a stuff byte when stop reading
  347. // Wait for a valid response in timeout of 0xFF attempts
  348. size_t nn = 0xFF;
  349. do
  350. r = spi_rx ();
  351. while ((r & 0x80) && --nn);
  352. return r; // Return with the response value
  353. }
  354. bool do_command_until (data_type done, data_type cmd, uint32_t arg, clock_t timeout) {
  355. clock_t mark = impl().clock_impl();
  356. data_type ret;
  357. do
  358. ret = command (cmd, arg);
  359. while (ret != done && impl().clock_impl() - mark < timeout);
  360. return ret == done;
  361. }
  362. public:
  363. bool get_CSD (data_type* csd) {
  364. bool ret = false;
  365. select(); // select card's CS
  366. if (command (CMD9, 0) == R1_READY_STATE && rx_datablock (csd, 16)) // READ_CSD
  367. ret = true;
  368. release(); // release card's CS
  369. return ret;
  370. }
  371. bool get_CID (data_type* cid) {
  372. bool ret = false;
  373. select(); // select card's CS
  374. if (command (CMD10, 0) == R1_READY_STATE && rx_datablock (cid, 16)) // READ_CID
  375. ret = true;
  376. release(); // release card's CS
  377. return ret;
  378. }
  379. bool get_OCR (data_type* ocr) {
  380. bool ret = false;
  381. select(); // select card's CS
  382. // Receive OCR as an R3 response (4 bytes)
  383. if (command (CMD58, 0) == 0) { // READ_OCR
  384. for (size_t n = 0; n < 4; ++n)
  385. *ocr++ = spi_rx ();
  386. ret = true;
  387. }
  388. release(); // release card's CS
  389. return ret;
  390. }
  391. // bool get_SDSTAT (data_type* sdstat) {
  392. // bool ret = false;
  393. // select(); // select card's CS
  394. // if (command (ACMD13, 0) == 0) { // SD_STATUS
  395. // spi_rx ();
  396. // if (rx_datablock (sdstat, 64))
  397. // ret = true;
  398. // }
  399. // release(); // release card's CS
  400. // return ret;
  401. // }
  402. bool sync () {
  403. select(); // select card's CS
  404. bool st = spi_wait_for(0xFF, SD_WaitTimeout); // flush
  405. release(); // release card's CS
  406. return st;
  407. }
  408. size_t sector_count() {
  409. size_t ret =0;
  410. data_type csd[16];
  411. select(); // select card's CS
  412. if (get_CSD(csd)) {
  413. if ((csd[0] >> 6) == 1) {
  414. // SDC version 2.00
  415. size_t csize = csd[9] + ((uint16_t)csd[8] << 8) + 1;
  416. ret = csize << 10;
  417. }
  418. else {
  419. // SDC version 1.XX or MMC
  420. uint8_t n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
  421. size_t csize = (csd[8] >> 6) + ((uint16_t)csd[7] << 2) + ((uint16_t)(csd[6] & 3) << 10) + 1;
  422. ret = csize << (n - 9);
  423. }
  424. }
  425. release(); // release card's CS
  426. return ret;
  427. }
  428. size_t sector_size() const { return 512; }
  429. size_t block_size() {
  430. size_t ret =0;
  431. data_type csd[16];
  432. select(); // select card's CS
  433. if (card_type & CT_SD2) {
  434. // SDC version 2.00
  435. if (command (ACMD13, 0) == R1_READY_STATE) {
  436. spi_rx (); // Read SD status
  437. if (rx_datablock (csd, 16)) { // Read partial block
  438. for (size_t n = 64 - 16; n; n--) // Purge trailing data
  439. spi_rx ();
  440. ret = 16UL << (csd[10] >> 4);
  441. }
  442. }
  443. }
  444. else {
  445. // SDC version 1.XX or MMC
  446. if (get_CSD(csd)) { // Read CSD
  447. if (card_type & CT_SD1) // SDC version 1.XX
  448. ret = (((csd[10] & 63) << 1) + ((uint16_t)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
  449. else // MMC
  450. ret = ((uint16_t)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
  451. }
  452. }
  453. release(); // release card's CS
  454. return ret;
  455. }
  456. /*!
  457. * \brief
  458. * De-Initialize SD Drive.
  459. * \return None
  460. */
  461. void deinit () {
  462. card_type = data_type{};
  463. status = status_t{};
  464. activate (0); // finally power off the card
  465. }
  466. /*!
  467. * \brief
  468. * Initialize SD Drive.
  469. *
  470. * \return The status of the operation
  471. * \arg false On error.
  472. * \arg true On success.
  473. */
  474. bool init () {
  475. uint32_t clk;
  476. data_type ocr[4], csd[16];
  477. clk = 400000; // Start at lower clk
  478. impl().SPI_set_clk_impl(clk);
  479. activate (0); // Initially power off the card
  480. if (!is_present()) { // check for presence
  481. status = ST_NODISK;
  482. return false;
  483. }
  484. activate (1); // activate and wait for PowerTimeout delay
  485. select(); // select card
  486. data_type type = CT_NONE;
  487. if (command (CMD0, 0) == R1_IDLE_STATE) { // Command to enter Idle state
  488. if (command (CMD8, 0x1AA) == 1) { // check SD version
  489. // SDHC
  490. for (size_t n=0 ; n<4 ; ++n) // Get trailing return value of R7 response
  491. ocr[n] = spi_rx ();
  492. if (ocr[2] == 0x01 && ocr[3] == 0xAA) {
  493. // Wait for leaving idle state (ACMD41 with HCS bit)
  494. bool st = do_command_until(R1_READY_STATE, ACMD41, 1UL << 30, SD_InitTimeout);
  495. if (st && get_OCR(ocr))
  496. type = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;
  497. }
  498. } else {
  499. data_type cmd;
  500. // SDSC or MMC
  501. if (command (ACMD41, 0) <= 1) { // SDSC
  502. type = CT_SD1; cmd = ACMD41;
  503. } else { // MMC
  504. type = CT_MMC; cmd = CMD1;
  505. }
  506. // Wait for leaving idle state (ACMD41 || CMD1)
  507. bool st = do_command_until(R1_READY_STATE, cmd, 0, SD_InitTimeout);
  508. // On failure, set R/W block length to 512 (For FAT compatibility)
  509. if (!st || command (CMD16, 512) != R1_READY_STATE)
  510. type = CT_NONE;
  511. }
  512. }
  513. card_type = type;
  514. release (); // Initialization ended
  515. if (type != CT_NONE) {
  516. // Success
  517. get_CSD(csd);
  518. clk = csd2bautrate(csd);
  519. impl().SPI_set_clk_impl(clk);
  520. status = ST_OK;
  521. return true;
  522. }
  523. else {
  524. activate(0);
  525. return false;
  526. }
  527. }
  528. status_t get_status () const { return status; }
  529. /*!
  530. * \brief
  531. * Read Sector(s)
  532. *
  533. * \param sector Start sector number (LBA)
  534. * \param buf Pointer to the data buffer to store read data
  535. * \param count Sector (512 bytes) count (1..255)
  536. * \return The status of the operation
  537. * \arg false On error.
  538. * \arg true On success.
  539. */
  540. bool read (size_t sector, data_type *buf, size_t count) {
  541. if (status != ST_OK) return false;
  542. if (!(card_type & CT_BLOCK)) // Convert to byte address if needed
  543. sector *= 512;
  544. select();
  545. if (count == 1) { //Single block read
  546. if (command (CMD17, sector) == 0)
  547. if (rx_datablock (buf, 512))
  548. count = 0;
  549. }
  550. else { // Multiple block read
  551. if (command (CMD18, sector) == 0) {
  552. do {
  553. if (!rx_datablock (buf, 512))
  554. break;
  555. buf += 512;
  556. } while (--count);
  557. command (CMD12, 0); // STOP_TRANSMISSION
  558. }
  559. }
  560. release ();
  561. return (count == 0);
  562. }
  563. /*!
  564. * \brief
  565. * Write Sector(s)
  566. *
  567. * \param sector Start sector number (LBA)
  568. * \param buf Pointer to the data to be written
  569. * \param count Sector(512 bytes) count (1..255)
  570. * \return The status of the operation
  571. * \arg false On error.
  572. * \arg true On success.
  573. */
  574. bool write (size_t sector, const data_type *buf, size_t count) {
  575. if (!count) return false;
  576. if (status != ST_OK) return false;
  577. if (!(card_type & CT_BLOCK)) // Convert to byte address if needed
  578. sector *= 512;
  579. select();
  580. if (count == 1) { // Single block write
  581. if ((command (CMD24, sector) == 0) && tx_datablock (buf, 0xFE))
  582. count = 0;
  583. } else { // Multiple block write
  584. if (card_type & CT_SDC)
  585. command (ACMD23, count);
  586. if (command (CMD25, sector) == 0) {
  587. do {
  588. if (!tx_datablock (buf, WRITE_MULTIPLE_TOKEN))
  589. break;
  590. buf += 512;
  591. } while (--count);
  592. if (!tx_datablock (0, STOP_TRAN_TOKEN)) // STOP token
  593. count = 1;
  594. }
  595. }
  596. release ();
  597. return (count == 0);
  598. }
  599. bool ioctl (ioctl_cmd cmd, void* buffer) {
  600. switch (cmd) {
  601. // SD/MMC specific
  602. case IOCTL_MMC_GET_TYPE: *(data_type*)buffer = card_type; return true;
  603. case IOCTL_MMC_GET_CSD: return get_CSD ((data_type*)buffer);
  604. case IOCTL_MMC_GET_CID: return get_CID ((data_type*)buffer);
  605. case IOCTL_MMC_GET_OCR: return get_OCR ((data_type*)buffer);
  606. case IOCTL_MMC_GET_SDSTAT: return false;
  607. // Generic
  608. case IOCTL_POWER:
  609. switch (*(data_type*)buffer) {
  610. case 0: *((data_type*)buffer+1) = (data_type)activate(0); return true;
  611. case 1: *((data_type*)buffer+1) = (data_type)activate(0); return true;
  612. case 2: *((data_type*)buffer+1) = (data_type)power(); return true;
  613. default: return false;
  614. }
  615. break;
  616. case IOCTL_LOCK:
  617. case IOCTL_EJECT:
  618. case IOCTL_FORMAT:
  619. return false;
  620. // FatFS compatibility
  621. case IOCTL_SYNC: return sync();
  622. case IOCTL_GET_SECTOR_COUNT:return (*(size_t*) buffer = sector_count() != 0);
  623. case IOCTL_GET_SECTOR_SIZE: return (*(size_t*) buffer = sector_size() != 0);
  624. case IOCTL_GET_BLOCK_SIZE: return (*(size_t*) buffer = block_size() != 0);
  625. case IOCTL_ERASE_SECTOR: return false;
  626. default:
  627. return false;
  628. }
  629. }
  630. private:
  631. data_type card_type{};
  632. status_t status{};
  633. bool pwr_flag{};
  634. };
  635. } // namespace tbx
  636. #endif /* TBX_DRV_SD_SPI_H_ */