Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

218 rindas
5.6KB

  1. /* SerialFlash Library - for filesystem-like access to SPI Serial Flash memory
  2. * https://github.com/PaulStoffregen/SerialFlash
  3. * Copyright (C) 2015, Paul Stoffregen, paul@pjrc.com
  4. *
  5. * Development of this library was funded by PJRC.COM, LLC by sales of Teensy.
  6. * Please support PJRC's efforts to develop open source software by purchasing
  7. * Teensy or other genuine PJRC products.
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice, development funding notice, and this permission
  17. * notice shall be included in all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. */
  27. #include "SerialFlash.h"
  28. #include "SPIFIFO.h"
  29. #define CSCONFIG() pinMode(6, OUTPUT)
  30. #define CSASSERT() digitalWriteFast(6, LOW)
  31. #define CSRELEASE() digitalWriteFast(6, HIGH)
  32. #define SPICONFIG SPISettings(50000000, MSBFIRST, SPI_MODE0)
  33. uint16_t SerialFlashChip::dirindex = 0;
  34. uint8_t SerialFlashChip::fourbytemode = 0;
  35. uint8_t SerialFlashChip::busy = 0;
  36. uint8_t SerialFlashChip::blocksize = 1;
  37. uint8_t SerialFlashChip::capacityId = 0;
  38. void SerialFlashChip::wait(void)
  39. {
  40. uint32_t status;
  41. do {
  42. SPI.beginTransaction(SPICONFIG);
  43. CSASSERT();
  44. status = SPI.transfer16(0x0500);
  45. CSRELEASE();
  46. SPI.endTransaction();
  47. } while ((status & 1));
  48. busy = 0;
  49. }
  50. void SerialFlashChip::read(void *buf, uint32_t addr, uint32_t len)
  51. {
  52. uint8_t *p = (uint8_t *)buf;
  53. uint8_t b;
  54. memset(p, 0, len);
  55. b = busy;
  56. if (b) {
  57. if (b == 1) {
  58. SPI.beginTransaction(SPICONFIG);
  59. CSASSERT();
  60. SPI.transfer(0x75); // Suspend program/erase
  61. CSRELEASE();
  62. SPI.endTransaction();
  63. delayMicroseconds(20); // Tsus = 20us
  64. } else {
  65. wait();
  66. }
  67. }
  68. SPI.beginTransaction(SPICONFIG);
  69. CSASSERT();
  70. // TODO: FIFO optimize....
  71. if (fourbytemode) {
  72. SPI.transfer(0x13);
  73. SPI.transfer16(addr >> 16);
  74. SPI.transfer16(addr);
  75. } else {
  76. SPI.transfer16(0x0300 | ((addr >> 16) & 255));
  77. SPI.transfer16(addr);
  78. }
  79. SPI.transfer(p, len);
  80. CSRELEASE();
  81. SPI.endTransaction();
  82. if (b == 1) {
  83. SPI.beginTransaction(SPICONFIG);
  84. CSASSERT();
  85. SPI.transfer(0x7A); // Resume program/erase
  86. CSRELEASE();
  87. SPI.endTransaction();
  88. }
  89. }
  90. void SerialFlashChip::write(const void *buf, uint32_t addr, uint32_t len)
  91. {
  92. const uint8_t *p = (const uint8_t *)buf;
  93. uint32_t max, pagelen;
  94. do {
  95. if (busy) wait();
  96. SPI.beginTransaction(SPICONFIG);
  97. CSASSERT();
  98. SPI.transfer(0x06);
  99. CSRELEASE();
  100. //delayMicroseconds(1);
  101. max = 256 - (addr & 0xFF);
  102. pagelen = (len <= max) ? len : max;
  103. len -= pagelen;
  104. CSASSERT();
  105. if (fourbytemode) {
  106. SPI.transfer(0x12);
  107. SPI.transfer16(addr >> 16);
  108. SPI.transfer16(addr);
  109. } else {
  110. SPI.transfer16(0x0200 | ((addr >> 16) & 255));
  111. SPI.transfer16(addr);
  112. }
  113. do {
  114. SPI.transfer(*p++);
  115. } while (--pagelen > 0);
  116. CSRELEASE();
  117. SPI.endTransaction();
  118. busy = 1;
  119. } while (len > 0);
  120. }
  121. void SerialFlashChip::eraseAll()
  122. {
  123. if (busy) wait();
  124. SPI.beginTransaction(SPICONFIG);
  125. CSASSERT();
  126. SPI.transfer(0x06);
  127. CSRELEASE();
  128. CSASSERT();
  129. SPI.transfer(0xC7);
  130. CSRELEASE();
  131. busy = 2;
  132. }
  133. bool SerialFlashChip::ready()
  134. {
  135. uint32_t status;
  136. if (!busy) return true;
  137. SPI.beginTransaction(SPICONFIG);
  138. CSASSERT();
  139. status = SPI.transfer16(0x0500);
  140. CSRELEASE();
  141. SPI.endTransaction();
  142. if ((status & 1)) return false;
  143. busy = 0;
  144. return true;
  145. }
  146. bool SerialFlashChip::begin()
  147. {
  148. SPI.begin();
  149. if (busy) wait();
  150. CSCONFIG();
  151. SPI.beginTransaction(SPICONFIG);
  152. CSASSERT();
  153. SPI.transfer(0x9F);
  154. SPI.transfer(0); // manufacturer ID
  155. SPI.transfer(0); // memory type
  156. capacityId = SPI.transfer(0); // capacity
  157. CSRELEASE();
  158. SPI.endTransaction();
  159. //Serial.print("capacity = ");
  160. //Serial.println(capacityId, HEX);
  161. if ((capacityId & 0xF0) == 0x20) {
  162. fourbytemode = 1; // chip larger than 16 MByte
  163. } else {
  164. fourbytemode = 0;
  165. }
  166. // TODO: how to detect the uniform sector erase size?
  167. blocksize = 1;
  168. return true;
  169. }
  170. uint32_t SerialFlashChip::capacity()
  171. {
  172. return 16777216; // TODO: compute this from capacityId...
  173. }
  174. uint32_t SerialFlashChip::blockSize()
  175. {
  176. return 4096; // TODO: how to discover this?
  177. }
  178. // size sector
  179. // Part Mbit kbyte ID bytes Digikey
  180. // ---- ---- ----- -------- -------
  181. // Winbond W25Q128FV 128 EF 40 18 W25Q128FVSIG-ND
  182. // Winbond W25Q256FV 256 64 EF 40 19
  183. // SST SST25VF016B 16 BF 25 41
  184. // Spansion S25FL127S 128 64? 01 20 18 1274-1045-ND
  185. // Spansion S25FL128P 128 01 20 18
  186. // Spansion S25FL064A 64 01 02 16
  187. // Macronix MX25L12805D 128 C2 20 18
  188. // Micron M25P80 8 20 20 14
  189. // Numonyx M25P128 128 20 20 18
  190. // SST SST25WF512 0.5 BF 25 01
  191. // SST SST25WF010 1 BF 25 02
  192. // SST SST25WF020 2 BF 25 03
  193. // SST SST25WF040 4 BF 25 04
  194. // Spansion FL127S 128 01 20 18 ?
  195. // Spansion S25FL512S 512 01 02 20 ?
  196. // Micron N25Q512A 512 4 20 BA 20 557-1569-ND
  197. // Micron N25Q00AA 1024 4/64 20 BA 21 557-1571-5-ND
  198. // Micron MT25QL02GC 2048 4/64 20 BB 22
  199. SerialFlashChip SerialFlash;