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.

SerialFlashChip.cpp 4.1KB

пре 9 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #include "SerialFlash.h"
  2. #include "SPIFIFO.h"
  3. #define CSCONFIG() pinMode(6, OUTPUT)
  4. #define CSASSERT() digitalWriteFast(6, LOW)
  5. #define CSRELEASE() digitalWriteFast(6, HIGH)
  6. #define SPICONFIG SPISettings(50000000, MSBFIRST, SPI_MODE0)
  7. uint16_t SerialFlashChip::dirindex = 0;
  8. uint8_t SerialFlashChip::fourbytemode = 0;
  9. uint8_t SerialFlashChip::busy = 0;
  10. uint8_t SerialFlashChip::blocksize = 1;
  11. uint8_t SerialFlashChip::capacityId = 0;
  12. void SerialFlashChip::wait(void)
  13. {
  14. uint32_t status;
  15. do {
  16. SPI.beginTransaction(SPICONFIG);
  17. CSASSERT();
  18. status = SPI.transfer16(0x0500);
  19. CSRELEASE();
  20. SPI.endTransaction();
  21. } while ((status & 1));
  22. busy = 0;
  23. }
  24. void SerialFlashChip::read(void *buf, uint32_t addr, uint32_t len)
  25. {
  26. uint8_t *p = (uint8_t *)buf;
  27. uint8_t b;
  28. memset(p, 0, len);
  29. b = busy;
  30. if (b) {
  31. if (b == 1) {
  32. SPI.beginTransaction(SPICONFIG);
  33. CSASSERT();
  34. SPI.transfer(0x75); // Suspend program/erase
  35. CSRELEASE();
  36. SPI.endTransaction();
  37. delayMicroseconds(20); // Tsus = 20us
  38. } else {
  39. wait();
  40. }
  41. }
  42. SPI.beginTransaction(SPICONFIG);
  43. CSASSERT();
  44. // TODO: FIFO optimize....
  45. if (fourbytemode) {
  46. SPI.transfer(0x13);
  47. SPI.transfer16(addr >> 16);
  48. SPI.transfer16(addr);
  49. } else {
  50. SPI.transfer16(0x0300 | ((addr >> 16) & 255));
  51. SPI.transfer16(addr);
  52. }
  53. SPI.transfer(p, len);
  54. CSRELEASE();
  55. SPI.endTransaction();
  56. if (b == 1) {
  57. SPI.beginTransaction(SPICONFIG);
  58. CSASSERT();
  59. SPI.transfer(0x7A); // Resume program/erase
  60. CSRELEASE();
  61. SPI.endTransaction();
  62. }
  63. }
  64. void SerialFlashChip::write(const void *buf, uint32_t addr, uint32_t len)
  65. {
  66. const uint8_t *p = (const uint8_t *)buf;
  67. uint32_t max, pagelen;
  68. do {
  69. if (busy) wait();
  70. SPI.beginTransaction(SPICONFIG);
  71. CSASSERT();
  72. SPI.transfer(0x06);
  73. CSRELEASE();
  74. //delayMicroseconds(1);
  75. max = 256 - (addr & 0xFF);
  76. pagelen = (len <= max) ? len : max;
  77. len -= pagelen;
  78. CSASSERT();
  79. if (fourbytemode) {
  80. SPI.transfer(0x12);
  81. SPI.transfer16(addr >> 16);
  82. SPI.transfer16(addr);
  83. } else {
  84. SPI.transfer16(0x0200 | ((addr >> 16) & 255));
  85. SPI.transfer16(addr);
  86. }
  87. do {
  88. SPI.transfer(*p++);
  89. } while (--pagelen > 0);
  90. CSRELEASE();
  91. SPI.endTransaction();
  92. busy = 1;
  93. } while (len > 0);
  94. }
  95. void SerialFlashChip::eraseAll()
  96. {
  97. if (busy) wait();
  98. SPI.beginTransaction(SPICONFIG);
  99. CSASSERT();
  100. SPI.transfer(0x06);
  101. CSRELEASE();
  102. CSASSERT();
  103. SPI.transfer(0xC7);
  104. CSRELEASE();
  105. busy = 2;
  106. }
  107. bool SerialFlashChip::ready()
  108. {
  109. uint32_t status;
  110. if (!busy) return true;
  111. SPI.beginTransaction(SPICONFIG);
  112. CSASSERT();
  113. status = SPI.transfer16(0x0500);
  114. CSRELEASE();
  115. SPI.endTransaction();
  116. if ((status & 1)) return false;
  117. busy = 0;
  118. return true;
  119. }
  120. bool SerialFlashChip::begin()
  121. {
  122. SPI.begin();
  123. if (busy) wait();
  124. CSCONFIG();
  125. SPI.beginTransaction(SPICONFIG);
  126. CSASSERT();
  127. SPI.transfer(0x9F);
  128. SPI.transfer(0); // manufacturer ID
  129. SPI.transfer(0); // memory type
  130. capacityId = SPI.transfer(0); // capacity
  131. CSRELEASE();
  132. SPI.endTransaction();
  133. //Serial.print("capacity = ");
  134. //Serial.println(capacityId, HEX);
  135. if ((capacityId & 0xF0) == 0x20) {
  136. fourbytemode = 1; // chip larger than 16 MByte
  137. } else {
  138. fourbytemode = 0;
  139. }
  140. // TODO: how to detect the uniform sector erase size?
  141. blocksize = 1;
  142. return true;
  143. }
  144. uint32_t SerialFlashChip::capacity()
  145. {
  146. return 16777216; // TODO: compute this from capacityId...
  147. }
  148. uint32_t SerialFlashChip::blockSize()
  149. {
  150. return 4096; // TODO: how to discover this?
  151. }
  152. // size sector
  153. // Part Mbit kbyte ID bytes Digikey
  154. // ---- ---- ----- -------- -------
  155. // Winbond W25Q128FV 128 EF 40 18 W25Q128FVSIG-ND
  156. // Winbond W25Q256FV 256 64 EF 40 19
  157. // SST SST25VF016B 16 BF 25 41
  158. // Spansion S25FL127S 128 64? 01 20 18 1274-1045-ND
  159. // Spansion S25FL128P 128 01 20 18
  160. // Spansion S25FL064A 64 01 02 16
  161. // Macronix MX25L12805D 128 C2 20 18
  162. // Micron M25P80 8 20 20 14
  163. // Numonyx M25P128 128 20 20 18
  164. // SST SST25WF512 0.5 BF 25 01
  165. // SST SST25WF010 1 BF 25 02
  166. // SST SST25WF020 2 BF 25 03
  167. // SST SST25WF040 4 BF 25 04
  168. // Spansion FL127S 128 01 20 18 ?
  169. // Spansion S25FL512S 512 01 02 20 ?
  170. // Micron N25Q512A 512 4 20 BA 20 557-1569-ND
  171. // Micron N25Q00AA 1024 4/64 20 BA 21 557-1571-5-ND
  172. // Micron MT25QL02GC 2048 4/64 20 BB 22
  173. SerialFlashChip SerialFlash;