Advertisement
manitou

Sd2Card.cpp

May 27th, 2012
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.81 KB | None | 0 0
  1. #include "Sd2Card.h"
  2.  
  3. #define DO_DMA_WRITE
  4. bool dmaActive;
  5. uint8_t mysink[1];
  6.  
  7. inline void DMAEvent(){
  8. dma_irq_cause event = dma_get_irq_cause(DMA1, DMA_CH3);
  9. switch(event) {
  10. case DMA_TRANSFER_COMPLETE:
  11. dma_detach_interrupt(DMA1, DMA_CH2);
  12. dma_detach_interrupt(DMA1, DMA_CH3);
  13. dmaActive = false;
  14. break;
  15. case DMA_TRANSFER_ERROR:
  16. SerialUSB.println("DMA Error - read/write data might be corrupted");
  17. break;
  18. }
  19. }
  20.  
  21.  
  22. Sd2Card::Sd2Card() : errorCode_(0), inBlock_(0), partialBlockRead_(0), type_(0), HardwareSPI(1) {
  23. this->begin(SPI_18MHZ, MSBFIRST, 0);
  24. //init DMA
  25. dma_init(DMA1);
  26. //enable SPI over DMA
  27. spi_rx_dma_enable(SPI1);
  28. spi_tx_dma_enable(SPI1);
  29. //DMA activity control
  30. dmaActive = false;
  31. //Acknowledgment array
  32. for(int i=0; i<SPI_BUFF_SIZE; i++)
  33. ack[i] = 0xFF;
  34. }
  35.  
  36. void Sd2Card::spiSend(uint8_t b) {
  37. this->transfer(b); // thd write to transfer
  38. // this->write(b);
  39. }
  40.  
  41. uint8_t Sd2Card::spiRec(void) {
  42. return this->transfer(0XFF);
  43. }
  44.  
  45. uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
  46. readEnd();
  47. CS0;
  48. waitNotBusy(300);
  49.  
  50. spiSend(cmd );
  51.  
  52. spiSend(arg >> 24);
  53. spiSend(arg >> 16);
  54. spiSend(arg >> 8);
  55. spiSend(arg >> 0);
  56.  
  57. uint8_t crc = 0XFF;
  58. if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0
  59. if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA
  60. spiSend(crc);
  61.  
  62. for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++);
  63. return status_;
  64. }
  65.  
  66.  
  67. uint32_t Sd2Card::cardSize(void) {
  68. csd_t csd;
  69. if (!readCSD(&csd)) return 0;
  70. if (csd.v1.csd_ver == 0) {
  71. uint8_t read_bl_len = csd.v1.read_bl_len;
  72. uint16_t c_size = (csd.v1.c_size_high << 10) | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low;
  73. uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1) | csd.v1.c_size_mult_low;
  74. return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7);
  75. } else if (csd.v2.csd_ver == 1) {
  76. uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16) | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low;
  77. return (c_size + 1) << 10;
  78. } else {
  79. error(SD_CARD_ERROR_BAD_CSD);
  80. return 0;
  81. }
  82. }
  83.  
  84. uint8_t Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
  85. if (!eraseSingleBlockEnable()) {
  86. error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK);
  87. SerialUSB.println("Error: Erase Single Block");
  88. goto fail;
  89. }
  90. if (type_ != SD_CARD_TYPE_SDHC) {
  91. firstBlock <<= 9;
  92. lastBlock <<= 9;
  93. }
  94. if (cardCommand(CMD32, firstBlock) || cardCommand(CMD33, lastBlock) || cardCommand(CMD38, 0)) {
  95. error(SD_CARD_ERROR_ERASE);
  96. SerialUSB.println("Error: Erase");
  97. goto fail;
  98. }
  99. if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
  100. error(SD_CARD_ERROR_ERASE_TIMEOUT);
  101. SerialUSB.println("Error: Erase timeout");
  102. goto fail;
  103. }
  104. CS1;
  105. return true;
  106.  
  107. fail:
  108. CS1;
  109. SerialUSB.println("Error: Sd2Card::Erase()");
  110. return false;
  111. }
  112.  
  113.  
  114. uint8_t Sd2Card::eraseSingleBlockEnable(void) {
  115. csd_t csd;
  116. return readCSD(&csd) ? csd.v1.erase_blk_en : 0;
  117. }
  118.  
  119.  
  120. uint8_t Sd2Card::init() {
  121. errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0;
  122. uint16_t t0 = (uint16_t)millis();
  123. uint32_t arg;
  124.  
  125. gpio_set_mode(CSPORT, CS, GPIO_OUTPUT_PP);
  126.  
  127. CS1;
  128. for (uint8_t i = 0; i < 10; i++)
  129. spiSend(0XFF);
  130. CS0;
  131.  
  132. // command to go idle in SPI mode
  133. while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
  134. if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
  135. SerialUSB.println("Error: CMD0");
  136. error(SD_CARD_ERROR_CMD0);
  137. goto fail;
  138. }
  139. }
  140. // check SD version
  141. if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
  142. type(SD_CARD_TYPE_SD1);
  143. }
  144. else {
  145. // only need last byte of r7 response
  146. for (uint8_t i = 0; i < 4; i++)
  147. status_ = spiRec();
  148. if (status_ != 0XAA) {
  149. error(SD_CARD_ERROR_CMD8);
  150. SerialUSB.println("Error: CMD8");
  151. goto fail;
  152. }
  153. type(SD_CARD_TYPE_SD2);
  154. }
  155. // initialize card and send host supports SDHC if SD2
  156. arg = (type() == SD_CARD_TYPE_SD2) ? 0X40000000 : 0;
  157.  
  158. while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
  159. // check for timeout
  160. if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
  161. SerialUSB.println("Error: ACMD41");
  162. error(SD_CARD_ERROR_ACMD41);
  163. goto fail;
  164. }
  165. }
  166. // if SD2 read OCR register to check for SDHC card
  167. if (type() == SD_CARD_TYPE_SD2) {
  168. if (cardCommand(CMD58, 0)) {
  169. SerialUSB.println("Error: CMD58");
  170. error(SD_CARD_ERROR_CMD58);
  171. goto fail;
  172. }
  173. if ((spiRec() & 0XC0) == 0XC0)
  174. type(SD_CARD_TYPE_SDHC);
  175. // discard rest of ocr - contains allowed voltage range
  176. for (uint8_t i = 0; i < 3; i++)
  177. spiRec();
  178. }
  179. CS1;
  180.  
  181. return true;
  182.  
  183. fail:
  184. CS1;
  185. SerialUSB.println("Error: Sd2Card::init()");
  186. return false;
  187. }
  188.  
  189. void Sd2Card::partialBlockRead(uint8_t value) {
  190. readEnd();
  191. partialBlockRead_ = value;
  192. }
  193.  
  194. uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst) {
  195. return readData(block, 0, 512, dst);
  196. }
  197.  
  198. uint8_t Sd2Card::readData(uint32_t block, uint16_t offset, uint16_t count, uint8_t* dst) {
  199.  
  200. uint16_t n;
  201.  
  202. if (count == 0) return true;
  203. if ((count + offset) > 512) goto fail;
  204.  
  205. if (!inBlock_ || block != block_ || offset < offset_) {
  206. block_ = block;
  207. // use address if not SDHC card
  208. if (type() != SD_CARD_TYPE_SDHC)
  209. block <<= 9;
  210. if (cardCommand(CMD17, block)) {
  211. error(SD_CARD_ERROR_CMD17);
  212. SerialUSB.println("Error: CMD17");
  213. goto fail;
  214. }
  215. if (!waitStartBlock()) {
  216. goto fail;
  217. }
  218. offset_ = 0;
  219. inBlock_ = 1;
  220. }
  221. // skip data before offset
  222. if(offset_ < offset){
  223. dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS, ack, DMA_SIZE_8BITS,
  224. (/*DMA_MINC_MODE | DMA_CIRC_MODE |*/ DMA_FROM_MEM | DMA_TRNS_CMPLT | DMA_TRNS_ERR));
  225. dma_attach_interrupt(DMA1, DMA_CH3, DMAEvent);
  226. dma_set_priority(DMA1, DMA_CH3, DMA_PRIORITY_VERY_HIGH);
  227. dma_set_num_transfers(DMA1, DMA_CH3, offset - offset_);
  228.  
  229. dmaActive = true;
  230. dma_enable(DMA1, DMA_CH3);
  231.  
  232. while(dmaActive) delayMicroseconds(1);
  233. dma_disable(DMA1, DMA_CH3);
  234. }
  235. offset_ = offset;
  236.  
  237. // transfer data
  238. dma_setup_transfer(DMA1, DMA_CH2, &SPI1->regs->DR, DMA_SIZE_8BITS, dst, DMA_SIZE_8BITS,
  239. (DMA_MINC_MODE | DMA_TRNS_CMPLT | DMA_TRNS_ERR));
  240. dma_attach_interrupt(DMA1, DMA_CH2, DMAEvent);
  241. dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS, ack, DMA_SIZE_8BITS,
  242. (/*DMA_MINC_MODE | DMA_CIRC_MODE |*/ DMA_FROM_MEM));
  243. dma_set_priority(DMA1, DMA_CH2, DMA_PRIORITY_VERY_HIGH);
  244. dma_set_priority(DMA1, DMA_CH3, DMA_PRIORITY_VERY_HIGH);
  245. dma_set_num_transfers(DMA1, DMA_CH2, count);
  246. dma_set_num_transfers(DMA1, DMA_CH3, count);
  247.  
  248. dmaActive = true;
  249. dma_enable(DMA1, DMA_CH3);
  250. dma_enable(DMA1, DMA_CH2);
  251.  
  252. while(dmaActive) delayMicroseconds(1);
  253. dma_disable(DMA1, DMA_CH3);
  254. dma_disable(DMA1, DMA_CH2);
  255.  
  256. offset_ += count;
  257. if (!partialBlockRead_ || offset_ >= SPI_BUFF_SIZE) {
  258. readEnd();
  259. }
  260. return true;
  261.  
  262. fail:
  263. CS1;
  264. SerialUSB.println("Error: Sd2Card::readData()");
  265. return false;
  266. }
  267.  
  268. void Sd2Card::readEnd(void) {
  269. if (inBlock_) {
  270. dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS, ack, DMA_SIZE_8BITS,
  271. (/*DMA_MINC_MODE | DMA_CIRC_MODE |*/ DMA_FROM_MEM | DMA_TRNS_CMPLT | DMA_TRNS_ERR));
  272. dma_attach_interrupt(DMA1, DMA_CH3, DMAEvent);
  273. dma_set_priority(DMA1, DMA_CH3, DMA_PRIORITY_VERY_HIGH);
  274. dma_set_num_transfers(DMA1, DMA_CH3, SPI_BUFF_SIZE + 1 - offset_);
  275.  
  276. dmaActive = true;
  277. dma_enable(DMA1, DMA_CH3);
  278.  
  279. while(dmaActive)delayMicroseconds(1);
  280. dma_disable(DMA1, DMA_CH3);
  281.  
  282. CS1;
  283. inBlock_ = 0;
  284. }
  285. }
  286.  
  287. uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) {
  288. uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
  289. if (cardCommand(cmd, 0)) {
  290. error(SD_CARD_ERROR_READ_REG);
  291. SerialUSB.println("Error: Read reg");
  292. goto fail;
  293. }
  294. if (!waitStartBlock())
  295. goto fail;
  296. // transfer data
  297. for (uint16_t i = 0; i < 16; i++)
  298. dst[i] = spiRec();
  299. spiRec(); // get first crc byte
  300. spiRec(); // get second crc byte
  301. CS1;
  302. return true;
  303.  
  304. fail:
  305. SerialUSB.println("Error: Sd2Card::readRegister()");
  306. CS1;
  307. return false;
  308. }
  309.  
  310. uint8_t Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
  311. uint16_t t0 = millis();
  312. do {
  313. if (spiRec() == 0XFF)
  314. return true;
  315. }
  316. while (((uint16_t)millis() - t0) < timeoutMillis);
  317. return false;
  318. }
  319.  
  320. uint8_t Sd2Card::waitStartBlock(void) {
  321. uint16_t t0 = millis();
  322. while ((status_ = spiRec()) == 0XFF) {
  323. if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) {
  324. error(SD_CARD_ERROR_READ_TIMEOUT);
  325. SerialUSB.println("Error: Read timeout");
  326. goto fail;
  327. }
  328. }
  329. if (status_ != DATA_START_BLOCK) {
  330. SerialUSB.print(DATA_START_BLOCK);
  331. SerialUSB.print(" != ");
  332. SerialUSB.println(status_);
  333. error(SD_CARD_ERROR_READ);
  334. SerialUSB.println("Error: Read");
  335. goto fail;
  336. }
  337. return true;
  338.  
  339. fail:
  340. CS1;
  341. SerialUSB.println("Error: Sd2Card::waitStartBlock()");
  342. return false;
  343. }
  344.  
  345. uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
  346. #if SD_PROTECT_BLOCK_ZERO
  347. // don't allow write to first block
  348. if (blockNumber == 0) {
  349. error(SD_CARD_ERROR_WRITE_BLOCK_ZERO);
  350. SerialUSB.println("Error: Write block zero");
  351. goto fail;
  352. }
  353. #endif // SD_PROTECT_BLOCK_ZERO
  354.  
  355. // use address if not SDHC card
  356. if (type() != SD_CARD_TYPE_SDHC)
  357. blockNumber <<= 9;
  358. if (cardCommand(CMD24, blockNumber)) {
  359. SerialUSB.println("Error: CMD24");
  360. error(SD_CARD_ERROR_CMD24);
  361. goto fail;
  362. }
  363. if (!writeData(DATA_START_BLOCK, src))
  364. goto fail;
  365.  
  366. // wait for flash programming to complete
  367. if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
  368. error(SD_CARD_ERROR_WRITE_TIMEOUT);
  369. SerialUSB.println("Error: Write timeout");
  370. goto fail;
  371. }
  372. // response is r2 so get and check two bytes for nonzero
  373. if (cardCommand(CMD13, 0) || spiRec()) {
  374. error(SD_CARD_ERROR_WRITE_PROGRAMMING);
  375. SerialUSB.println("Error: Write programming");
  376. goto fail;
  377. }
  378. CS1;
  379. return true;
  380.  
  381. fail:
  382. CS1;
  383. SerialUSB.println("Error: Sd2Card::writeBlock");
  384. return false;
  385. }
  386.  
  387. uint8_t Sd2Card::writeData(const uint8_t* src) {
  388. // wait for previous write to finish
  389. if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
  390. error(SD_CARD_ERROR_WRITE_MULTIPLE);
  391. SerialUSB.println("Error: writeData");
  392. CS1;
  393. return false;
  394. }
  395. return writeData(WRITE_MULTIPLE_TOKEN, src);
  396. }
  397.  
  398. uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) {
  399. spiSend(token);
  400. #ifdef DO_DMA_WRITE
  401. dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS, (uint8_t *)src, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_FROM_MEM | DMA_TRNS_CMPLT | DMA_TRNS_ERR));
  402. dma_attach_interrupt(DMA1, DMA_CH3, DMAEvent);
  403. dma_set_priority(DMA1, DMA_CH3, DMA_PRIORITY_VERY_HIGH);
  404. dma_set_num_transfers(DMA1, DMA_CH3, 512);
  405.  
  406. dmaActive = true;
  407. dma_enable(DMA1, DMA_CH3);
  408.  
  409. while(dmaActive) delayMicroseconds(1);
  410. dma_disable(DMA1, DMA_CH3);
  411. #else
  412. for (uint16_t i = 0; i < 512; i++) {
  413. spiSend(src[i]);
  414. }
  415. #endif
  416. spiSend(0xff); // dummy crc
  417. spiSend(0xff); // dummy crc
  418.  
  419. while((status_ = spiRec()) == 0xff); // thd catch up hack
  420. if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
  421. error(SD_CARD_ERROR_WRITE);
  422. CS1;
  423. SerialUSB.print(status_,HEX);
  424. SerialUSB.println(" Error: Write");
  425. SerialUSB.println("Error: Sd2Card::writeData()");
  426. return false;
  427. }
  428. return true;
  429. }
  430.  
  431. uint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
  432. #if SD_PROTECT_BLOCK_ZERO
  433. // don't allow write to first block
  434. if (blockNumber == 0) {
  435. error(SD_CARD_ERROR_WRITE_BLOCK_ZERO);
  436. SerialUSB.println("Error: Write block zero");
  437. goto fail;
  438. }
  439. #endif // SD_PROTECT_BLOCK_ZERO
  440. // send pre-erase count
  441. if (cardAcmd(ACMD23, eraseCount)) {
  442. SerialUSB.println("Error: ACMD23");
  443. error(SD_CARD_ERROR_ACMD23);
  444. goto fail;
  445. }
  446. // use address if not SDHC card
  447. if (type() != SD_CARD_TYPE_SDHC)
  448. blockNumber <<= 9;
  449. if (cardCommand(CMD25, blockNumber)) {
  450. error(SD_CARD_ERROR_CMD25);
  451. SerialUSB.println("Error: CMD25");
  452. goto fail;
  453. }
  454. return true;
  455.  
  456. fail:
  457. CS1;
  458. SerialUSB.println("Error: Sd2Card::writeStart()");
  459. return false;
  460. }
  461.  
  462. uint8_t Sd2Card::writeStop(void) {
  463. if (!waitNotBusy(SD_WRITE_TIMEOUT))
  464. goto fail;
  465. spiSend(STOP_TRAN_TOKEN);
  466. if (!waitNotBusy(SD_WRITE_TIMEOUT))
  467. goto fail;
  468. CS1;
  469. return true;
  470.  
  471. fail:
  472. error(SD_CARD_ERROR_STOP_TRAN);
  473. CS1;
  474. SerialUSB.println("Error: Sd2Card::writeStop()");
  475. return false;
  476. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement