PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

627 lines
13KB

  1. //#define USB_SERIAL_PRIVATE_INCLUDE
  2. //#include "usb_mass_storage_debug.h"
  3. //#include "pauls_ugly_debug.h"
  4. #include "core_pins.h" // for delayMicroseconds
  5. inline uint32_t media_size(void);
  6. void media_init(void);
  7. uint8_t media_lock(void);
  8. void media_unlock(void);
  9. void media_poll(void);
  10. static void media_send_begin(uint32_t lba);
  11. static void media_send_chunk(uint32_t lba, uint8_t chunk);
  12. static void media_send_end(void);
  13. static void media_receive_begin(uint32_t lba);
  14. static void media_receive_chunk(uint32_t lba, uint8_t chunk);
  15. static void media_receive_end(void);
  16. /**************************************************************************
  17. *
  18. * Storage Media Access Functions
  19. *
  20. **************************************************************************/
  21. #define SPI_PORT PORTB
  22. #define SPI_DDR DDRB
  23. #define SPI_SS_PIN 0
  24. #define SPI_SCLK_PIN 1
  25. #define SPI_MOSI_PIN 2
  26. #define SPI_MISO_PIN 3
  27. #define SD_CMD_GO_IDLE_STATE 0x4095
  28. #define SD_CMD_SEND_OP_COND 0x41FF
  29. #define SD_CMD_SEND_IF_COND 0x4887
  30. #define SD_CMD_SEND_CSD 0x49FF
  31. #define SD_CMD_STOP_TRANSMISSION 0x4CFF
  32. #define SD_CMD_READ_SINGLE_BLOCK 0x51FF
  33. #define SD_CMD_READ_MULTIPLE_BLOCK 0x52FF
  34. #define SD_CMD_WRITE_SINGLE_BLOCK 0x58FF
  35. #define SD_CMD_WRITE_MULTIPLE_BLOCK 0x59FF
  36. #define SD_ACMD_SEND_OP_COND 0x69FF
  37. #define SD_CMD_APP_CMD 0x77FF
  38. #define SD_CMD_READ_OCR 0x7AFF
  39. inline void spi_write(uint8_t val) __attribute__((always_inline));
  40. inline void spi_write(uint8_t val)
  41. {
  42. SPDR = val;
  43. while ((SPSR & (1<<SPIF)) == 0) /*wait*/ ;
  44. }
  45. inline uint8_t spi_xfer(uint8_t val) __attribute__((always_inline));
  46. inline uint8_t spi_xfer(uint8_t val)
  47. {
  48. SPDR = val;
  49. while ((SPSR & (1<<SPIF)) == 0) /*wait*/ ;
  50. return SPDR;
  51. }
  52. void spi_ignore_bytes(uint8_t count)
  53. {
  54. do {
  55. spi_write(0xFF);
  56. } while (--count);
  57. }
  58. inline void spi_select(void)
  59. {
  60. SPI_PORT &= ~(1<<SPI_SS_PIN);
  61. }
  62. inline void sd_deselect(void)
  63. {
  64. SPI_PORT |= (1<<SPI_SS_PIN);
  65. spi_write(0xFF);
  66. }
  67. uint8_t sd_command(uint16_t cmd, uint32_t parm)
  68. {
  69. uint8_t n, r;
  70. union {
  71. struct {
  72. unsigned b1:8;
  73. unsigned b2:8;
  74. unsigned b3:8;
  75. unsigned b4:8;
  76. } byte;
  77. long i;
  78. } in;
  79. in.i = parm;
  80. phex(cmd >> 8);
  81. phex(in.byte.b4);
  82. phex(in.byte.b3);
  83. phex(in.byte.b2);
  84. phex(in.byte.b1);
  85. phex(cmd);
  86. print("\n");
  87. spi_select();
  88. spi_write(cmd >> 8);
  89. spi_write(in.byte.b4);
  90. spi_write(in.byte.b3);
  91. spi_write(in.byte.b2);
  92. spi_write(in.byte.b1);
  93. SPI_PORT |= (1<<SPI_MISO_PIN);
  94. r = spi_xfer(cmd);
  95. for (n=0; n < 9; n++) {
  96. if (r != 0xFF) break;
  97. r = spi_xfer(0xFF);
  98. }
  99. SPI_PORT &= ~(1<<SPI_MISO_PIN);
  100. return r;
  101. }
  102. uint8_t sd_wait_data(void)
  103. {
  104. uint16_t count=0;
  105. uint8_t r;
  106. do {
  107. r = spi_xfer(0xFF);
  108. //if (r != 0xFF) return r;
  109. if (r == 0xFE) return r;
  110. } while (count++ < 20000);
  111. return r;
  112. }
  113. #ifndef USBSTATE
  114. #define USBSTATE
  115. #endif
  116. #define READ_ONLY 0
  117. volatile uint8_t media_rdonly USBSTATE;
  118. #define MEDIA_PRESENT_MASK 0x10
  119. #define MEDIA_STATE_NOCARD 0x00
  120. #define MEDIA_STATE_INITIALIZING 0x01
  121. #define MEDIA_STATE_READY 0x12
  122. #define MEDIA_STATE_BUSY 0x14 // TODO: implement this!!!
  123. #define MEDIA_STATE_CLAIMED 0x80 // media is claimed
  124. #define MEDIA_STATE_CLAIMED_STATUS 0x40 // claimed status reported
  125. #define MEDIA_STATE_CLAIMED_SENSE 0x20 // claimed scsi sense sent
  126. volatile uint8_t media_state USBSTATE;
  127. #define MEDIA_TYPE_SDv1 0x00
  128. #define MEDIA_TYPE_SDv2 0x01
  129. #define MEDIA_TYPE_SDHC 0x02
  130. uint8_t media_type USBSTATE;
  131. void media_restart(void)
  132. {
  133. SPI_PORT |= (1<<SPI_SS_PIN);
  134. SPI_DDR |= ((1<<SPI_SS_PIN) | (1<<SPI_SCLK_PIN) | (1<<SPI_MOSI_PIN));
  135. SPCR = (1<<SPE) | (1<<MSTR); // 8 Mbit/sec
  136. SPSR = (1<<SPI2X);
  137. }
  138. void media_init(void)
  139. {
  140. media_restart();
  141. // TODO: initialize to unlocked condition
  142. media_state = MEDIA_STATE_NOCARD;
  143. media_type = MEDIA_TYPE_SDv1;
  144. media_rdonly = READ_ONLY;
  145. media_poll();
  146. }
  147. void media_claim(void)
  148. {
  149. if (media_state & MEDIA_STATE_CLAIMED) return;
  150. while (!media_lock()) /*wait*/ ;
  151. media_state = MEDIA_STATE_CLAIMED;
  152. print("Media claimed by user program\n");
  153. media_unlock();
  154. }
  155. void media_release(uint8_t read_only_mode)
  156. {
  157. uint8_t mstate;
  158. mstate = media_state;
  159. if (!(mstate & MEDIA_STATE_CLAIMED)) return;
  160. print("Media release begin\n");
  161. while (mstate != (MEDIA_STATE_CLAIMED|MEDIA_STATE_CLAIMED_STATUS|MEDIA_STATE_CLAIMED_SENSE)) {
  162. if (!usb_configuration) break;
  163. // TODO: a timeout??
  164. //_delay_ms(100);
  165. mstate = media_state;
  166. //print("mstate = ");
  167. //phex(mstate);
  168. //phex(MEDIA_STATE_CLAIMED|MEDIA_STATE_CLAIMED_STATUS|MEDIA_STATE_CLAIMED_SENSE);
  169. //print("\n");
  170. }
  171. // a brief delay is needed here... but why?
  172. delayMicroseconds(12500);
  173. print("Media released by user program\n");
  174. media_init();
  175. media_rdonly = read_only_mode;
  176. }
  177. void media_poll(void)
  178. {
  179. uint8_t i, r, mstate;
  180. mstate = media_state;
  181. //print("poll ");
  182. //phex(mstate);
  183. //print("\n");
  184. if (mstate & MEDIA_STATE_CLAIMED) {
  185. // never access the SD card while it's claimed by the user program!
  186. return;
  187. } else if (mstate == MEDIA_STATE_NOCARD) {
  188. media_type = MEDIA_TYPE_SDv1;
  189. spi_select();
  190. for (i=0; i<10; i++) {
  191. spi_write(0xFF);
  192. }
  193. r = sd_command(SD_CMD_GO_IDLE_STATE, 0); // CMD0
  194. sd_deselect();
  195. phex(r);
  196. print("\n");
  197. if ((r & 0xFE) == 0) {
  198. r = sd_command(SD_CMD_SEND_IF_COND, 0x1AA);
  199. phex(r);
  200. if ((r & 0xFE) == 0) {
  201. spi_write(0xFF);
  202. spi_write(0xFF);
  203. r = spi_xfer(0xFF);
  204. i = spi_xfer(0xFF);
  205. phex(r);
  206. phex(i);
  207. print("\n");
  208. if (r == 1 && i == 0xAA) {
  209. print("Card is version 2.0\n");
  210. media_type = MEDIA_TYPE_SDv2;
  211. }
  212. }
  213. sd_deselect();
  214. media_state = MEDIA_STATE_INITIALIZING;
  215. }
  216. } else {
  217. //r = sd_command(SD_CMD_SEND_OP_COND, 0); // CMD1
  218. r = sd_command(SD_CMD_SEND_OP_COND, media_type ? 0x40000000 : 0); // CMD1
  219. //sd_command(SD_CMD_APP_CMD, 0);
  220. //r = sd_command(SD_ACMD_SEND_OP_COND, media_type ? 0x40000000 : 0); // ACMD41
  221. if (r) {
  222. phex(r);
  223. phex(spi_xfer(0xFF));
  224. phex(spi_xfer(0xFF));
  225. phex(spi_xfer(0xFF));
  226. phex(spi_xfer(0xFF));
  227. phex(spi_xfer(0xFF));
  228. phex(spi_xfer(0xFF));
  229. phex(spi_xfer(0xFF));
  230. phex(spi_xfer(0xFF));
  231. phex(spi_xfer(0xFF));
  232. print("\n");
  233. }
  234. sd_deselect();
  235. phex(r);
  236. print("\n");
  237. if (r == 0) {
  238. if (mstate == MEDIA_STATE_INITIALIZING && media_type) {
  239. r = sd_command(SD_CMD_READ_OCR, 0);
  240. phex(r);
  241. if (r == 0) {
  242. r = spi_xfer(0xFF);
  243. if (r & 0x40) {
  244. print("Card is SDHC\n");
  245. media_type = MEDIA_TYPE_SDHC;
  246. }
  247. spi_write(0xFF);
  248. spi_write(0xFF);
  249. spi_write(0xFF);
  250. }
  251. sd_deselect();
  252. }
  253. media_state = MEDIA_STATE_READY;
  254. } else if (r & 0x80) {
  255. media_state = MEDIA_STATE_NOCARD;
  256. }
  257. }
  258. //return media_state;
  259. }
  260. inline uint32_t media_size(void)
  261. {
  262. uint8_t r;
  263. if (media_state != MEDIA_STATE_READY) return 1;
  264. r = sd_command(SD_CMD_SEND_CSD, 0);
  265. if (r) goto error;
  266. r = sd_wait_data();
  267. if (r != 0xFE) goto error;
  268. r = spi_xfer(0xFF) & 0xC0;
  269. if (r == 0) {
  270. uint8_t c1, c2, c3, mult;
  271. uint16_t c_size;
  272. // Version 1.0 (standard capacity, up to 2 gigbytes)
  273. spi_ignore_bytes(4);
  274. mult = spi_xfer(0xFF); // READ_BL_LEN
  275. //phex(mult);
  276. mult &= 0x0F;
  277. c1 = spi_xfer(0xFF); // C_SIZE[12:11]
  278. c2 = spi_xfer(0xFF); // C_SIZE[10:3]
  279. c3 = spi_xfer(0xFF); // C_SIZE[2:0]
  280. //phex(c1);
  281. //phex(c2);
  282. //phex(c3);
  283. c1 &= 0x03;
  284. c_size = ((c1 << 10) | (c2 << 2) | (c3 >> 6)) + 1;
  285. c1 = spi_xfer(0xFF); // C_SIZE_MULT[2:1]
  286. c2 = spi_xfer(0xFF); // C_SIZE_MULT[0]
  287. //phex(c1);
  288. //phex(c2);
  289. //print("\n");
  290. c1 &= 0x03;
  291. c2 &= 0x80;
  292. c1 = (c1 << 1) | (c2 >> 7);
  293. mult = mult + c1 - 7;
  294. spi_ignore_bytes(8);
  295. sd_deselect();
  296. return ((uint32_t)c_size << mult);
  297. } else if (r == 0x40) {
  298. // Version 2.0 (high capacity, more than 2 gigbytes)
  299. uint8_t c1, c2, c3;
  300. uint32_t size;
  301. spi_ignore_bytes(6);
  302. c1 = spi_xfer(0xFF); // C_SIZE
  303. c2 = spi_xfer(0xFF); // C_SIZE
  304. c3 = spi_xfer(0xFF); // C_SIZE
  305. spi_ignore_bytes(9);
  306. //phex(c1);
  307. //phex(c2);
  308. //phex(c3);
  309. //print("\n");
  310. c1 &= 0x3F;
  311. size = (((uint32_t)c1 << 16) | ((uint16_t)c2 << 8) | c3) + 1;
  312. size <<= 10;
  313. sd_deselect();
  314. return size;
  315. } else {
  316. goto error; // unknown CSD_STRUCTURE
  317. }
  318. error:
  319. sd_deselect();
  320. media_state = MEDIA_STATE_NOCARD;
  321. return 1;
  322. }
  323. uint8_t media_read_sector(uint32_t lba, uint8_t *buffer)
  324. {
  325. uint8_t r, i, ret=0;
  326. while (!media_lock()) /*wait*/ ;
  327. if (media_type != MEDIA_TYPE_SDHC) lba = (lba << 9);
  328. r = sd_command(SD_CMD_READ_SINGLE_BLOCK, lba);
  329. if (r) {
  330. // TODO: check for errors...
  331. print("User Read Error, r=");
  332. phex(r);
  333. print("\n");
  334. goto done;
  335. }
  336. print("User Read OK, lba=");
  337. phex32(lba >> 9);
  338. print("\n");
  339. if (sd_wait_data() != 0xFE) {
  340. print("User Read Error, bad token\n");
  341. goto done;
  342. }
  343. for (i=0; i<64; i++) {
  344. *buffer++ = spi_xfer(0xFF);
  345. *buffer++ = spi_xfer(0xFF);
  346. *buffer++ = spi_xfer(0xFF);
  347. *buffer++ = spi_xfer(0xFF);
  348. *buffer++ = spi_xfer(0xFF);
  349. *buffer++ = spi_xfer(0xFF);
  350. *buffer++ = spi_xfer(0xFF);
  351. *buffer++ = spi_xfer(0xFF);
  352. }
  353. ret = 1;
  354. spi_write(0xFF); // ignore CRC
  355. spi_write(0xFF);
  356. done:
  357. sd_deselect();
  358. media_unlock();
  359. return ret;
  360. }
  361. static void media_send_begin(uint32_t lba)
  362. {
  363. uint8_t r;
  364. if (media_type != MEDIA_TYPE_SDHC) lba = (lba << 9);
  365. r = sd_command(SD_CMD_READ_MULTIPLE_BLOCK, lba);
  366. if (r) {
  367. // TODO: check for errors...
  368. print("Read Error, r=");
  369. phex(r);
  370. print("\n");
  371. } else {
  372. print("Read OK\n");
  373. }
  374. }
  375. static void media_send_chunk(uint32_t lba, uint8_t chunk)
  376. {
  377. uint8_t i;
  378. if (chunk == 0) {
  379. i = sd_wait_data();
  380. //phex(i);
  381. if (i != 0xFE) {
  382. print("Read error, token=");
  383. phex(i);
  384. print("\n");
  385. }
  386. }
  387. for (i=0; i<8; i++) {
  388. // TODO: asm optimization
  389. UEDATX = spi_xfer(0xFF);
  390. UEDATX = spi_xfer(0xFF);
  391. UEDATX = spi_xfer(0xFF);
  392. UEDATX = spi_xfer(0xFF);
  393. UEDATX = spi_xfer(0xFF);
  394. UEDATX = spi_xfer(0xFF);
  395. UEDATX = spi_xfer(0xFF);
  396. UEDATX = spi_xfer(0xFF);
  397. }
  398. UEINTX = 0x3A;
  399. if (chunk == 7) {
  400. spi_write(0xFF);
  401. spi_write(0xFF);
  402. }
  403. //print(".");
  404. }
  405. static void media_send_end(void)
  406. {
  407. //uint8_t r;
  408. /* r = */ sd_command(SD_CMD_STOP_TRANSMISSION, 0);
  409. // TODO: proper handling of stop transaction.....
  410. // but what is the proper way? Older cards stop instantly,
  411. // but newer ones spew 1 or 2 bytes of garbage, then maybe
  412. // 0xFF's until the ok (0) response. What a mess!
  413. spi_write(0xFF);
  414. spi_write(0xFF);
  415. spi_write(0xFF);
  416. spi_write(0xFF);
  417. spi_write(0xFF);
  418. spi_write(0xFF);
  419. spi_write(0xFF);
  420. spi_write(0xFF);
  421. //print("\rr=");
  422. //phex(r);
  423. #if 0
  424. if (r) {
  425. print("Stop Transmission Error, r=");
  426. phex(r);
  427. phex(spi_xfer(0xFF));
  428. phex(spi_xfer(0xFF));
  429. phex(spi_xfer(0xFF));
  430. phex(spi_xfer(0xFF));
  431. phex(spi_xfer(0xFF));
  432. phex(spi_xfer(0xFF));
  433. phex(spi_xfer(0xFF));
  434. print("\n");
  435. // handle errors
  436. } else {
  437. print("Stop Transmission OK, r=");
  438. phex(r);
  439. phex(spi_xfer(0xFF));
  440. phex(spi_xfer(0xFF));
  441. phex(spi_xfer(0xFF));
  442. phex(spi_xfer(0xFF));
  443. phex(spi_xfer(0xFF));
  444. phex(spi_xfer(0xFF));
  445. phex(spi_xfer(0xFF));
  446. print("\n");
  447. }
  448. do {
  449. r = spi_xfer(0xFF);
  450. //phex(r);
  451. } while (r == 0);
  452. #endif
  453. sd_deselect();
  454. //print("\n");
  455. }
  456. uint8_t media_write_sector(uint32_t lba, const uint8_t *buffer)
  457. {
  458. uint8_t r, i, ret=0;
  459. while (!media_lock()) /*wait*/ ;
  460. if (media_type != MEDIA_TYPE_SDHC) lba = (lba << 9);
  461. r = sd_command(SD_CMD_WRITE_SINGLE_BLOCK, lba);
  462. if (r) {
  463. // TODO: check for errors...
  464. print("User Write Error, r=");
  465. phex(r);
  466. print("\n");
  467. goto done;
  468. }
  469. print("User Write OK, lba=");
  470. phex32(lba >> 9);
  471. print("\n");
  472. spi_write(0xFE); // start block token
  473. for (i=0; i<64; i++) {
  474. spi_write(*buffer++);
  475. spi_write(*buffer++);
  476. spi_write(*buffer++);
  477. spi_write(*buffer++);
  478. spi_write(*buffer++);
  479. spi_write(*buffer++);
  480. spi_write(*buffer++);
  481. spi_write(*buffer++);
  482. }
  483. spi_write(0xFF); // CRC
  484. spi_write(0xFF);
  485. do {
  486. r = spi_xfer(0xFF); // wait for busy
  487. //phex(r);
  488. } while (r != 0xFF);
  489. ret = 1;
  490. done:
  491. sd_deselect();
  492. media_unlock();
  493. return ret;
  494. }
  495. static void media_receive_begin(uint32_t lba)
  496. {
  497. uint8_t r;
  498. // TODO: check media_rdonly, return error is read only mode
  499. if (media_type != MEDIA_TYPE_SDHC) lba = (lba << 9);
  500. sd_command(SD_CMD_WRITE_MULTIPLE_BLOCK, lba);
  501. if (r) {
  502. // TODO: check for errors...
  503. }
  504. }
  505. static void media_receive_chunk(uint32_t lba, uint8_t chunk)
  506. {
  507. uint8_t i, r;
  508. if (chunk == 0) {
  509. spi_write(0xFC);
  510. }
  511. for (i=0; i<8; i++) {
  512. // TODO: asm optimization
  513. spi_write(UEDATX);
  514. spi_write(UEDATX);
  515. spi_write(UEDATX);
  516. spi_write(UEDATX);
  517. spi_write(UEDATX);
  518. spi_write(UEDATX);
  519. spi_write(UEDATX);
  520. spi_write(UEDATX);
  521. }
  522. UEINTX = 0x6B;
  523. print(".");
  524. if (chunk == 7) {
  525. spi_write(0xFF);
  526. spi_write(0xFF);
  527. do {
  528. r = spi_xfer(0xFF);
  529. phex(r);
  530. } while (r != 0xFF);
  531. }
  532. }
  533. static void media_receive_end(void)
  534. {
  535. uint8_t r;
  536. print("stop");
  537. spi_write(0xFD);
  538. spi_write(0xFF);
  539. do {
  540. // TODO: this can wait for a long time... would be
  541. // much better to create a busy media state and
  542. // return from the ISR, but then need to deal with
  543. // it everywhere else!
  544. r = spi_xfer(0xFF);
  545. phex(r);
  546. } while (r != 0xFF);
  547. sd_deselect();
  548. print("\n");
  549. }