Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

SerialFlashChip.cpp 6.9KB

před 9 roky
před 9 roky
před 9 roky
před 9 roky
před 9 roky
před 9 roky
před 9 roky
před 9 roky
před 9 roky
před 9 roky
před 9 roky
před 9 roky
před 9 roky
před 9 roky
před 9 roky
před 9 roky
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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. void SerialFlashChip::wait(void)
  37. {
  38. uint32_t status;
  39. do {
  40. SPI.beginTransaction(SPICONFIG);
  41. CSASSERT();
  42. status = SPI.transfer16(0x0500);
  43. CSRELEASE();
  44. SPI.endTransaction();
  45. } while ((status & 1));
  46. busy = 0;
  47. }
  48. void SerialFlashChip::read(void *buf, uint32_t addr, uint32_t len)
  49. {
  50. uint8_t *p = (uint8_t *)buf;
  51. uint8_t b;
  52. memset(p, 0, len);
  53. b = busy;
  54. if (b) {
  55. if (b == 1) {
  56. // TODO: this may not work on Spansion chips
  57. // which apparently have 2 different suspend
  58. // commands, for program vs erase
  59. SPI.beginTransaction(SPICONFIG);
  60. CSASSERT();
  61. SPI.transfer(0x75); // Suspend program/erase
  62. CSRELEASE();
  63. SPI.endTransaction();
  64. delayMicroseconds(20); // Tsus = 20us
  65. } else {
  66. wait();
  67. }
  68. }
  69. SPI.beginTransaction(SPICONFIG);
  70. CSASSERT();
  71. // TODO: FIFO optimize....
  72. if (fourbytemode) {
  73. SPI.transfer(0x13);
  74. SPI.transfer16(addr >> 16);
  75. SPI.transfer16(addr);
  76. } else {
  77. SPI.transfer16(0x0300 | ((addr >> 16) & 255));
  78. SPI.transfer16(addr);
  79. }
  80. SPI.transfer(p, len);
  81. CSRELEASE();
  82. SPI.endTransaction();
  83. if (b == 1) {
  84. SPI.beginTransaction(SPICONFIG);
  85. CSASSERT();
  86. SPI.transfer(0x7A); // Resume program/erase
  87. CSRELEASE();
  88. SPI.endTransaction();
  89. }
  90. }
  91. void SerialFlashChip::write(const void *buf, uint32_t addr, uint32_t len)
  92. {
  93. const uint8_t *p = (const uint8_t *)buf;
  94. uint32_t max, pagelen;
  95. do {
  96. if (busy) wait();
  97. SPI.beginTransaction(SPICONFIG);
  98. CSASSERT();
  99. SPI.transfer(0x06);
  100. CSRELEASE();
  101. //delayMicroseconds(1);
  102. max = 256 - (addr & 0xFF);
  103. pagelen = (len <= max) ? len : max;
  104. len -= pagelen;
  105. CSASSERT();
  106. if (fourbytemode) {
  107. // TODO: Winbond doesn't implement 0x12 on W25Q256FV
  108. SPI.transfer(0x12);
  109. SPI.transfer16(addr >> 16);
  110. SPI.transfer16(addr);
  111. } else {
  112. SPI.transfer16(0x0200 | ((addr >> 16) & 255));
  113. SPI.transfer16(addr);
  114. }
  115. do {
  116. SPI.transfer(*p++);
  117. } while (--pagelen > 0);
  118. CSRELEASE();
  119. SPI.endTransaction();
  120. busy = 1;
  121. } while (len > 0);
  122. }
  123. void SerialFlashChip::eraseAll()
  124. {
  125. if (busy) wait();
  126. SPI.beginTransaction(SPICONFIG);
  127. CSASSERT();
  128. SPI.transfer(0x06);
  129. CSRELEASE();
  130. CSASSERT();
  131. SPI.transfer(0xC7);
  132. CSRELEASE();
  133. SPI.endTransaction();
  134. busy = 2;
  135. }
  136. void SerialFlashChip::eraseBlock(uint32_t addr)
  137. {
  138. if (busy) wait();
  139. SPI.beginTransaction(SPICONFIG);
  140. CSASSERT();
  141. if (fourbytemode) {
  142. // TODO: Winbond doesn't implement 0xDC on W25Q256FV
  143. SPI.transfer(0xDC);
  144. SPI.transfer16(addr >> 16);
  145. SPI.transfer16(addr);
  146. } else {
  147. SPI.transfer16(0xD800 | ((addr >> 16) & 255));
  148. SPI.transfer16(addr);
  149. }
  150. CSRELEASE();
  151. SPI.endTransaction();
  152. busy = 1;
  153. }
  154. bool SerialFlashChip::ready()
  155. {
  156. uint32_t status;
  157. if (!busy) return true;
  158. SPI.beginTransaction(SPICONFIG);
  159. CSASSERT();
  160. status = SPI.transfer16(0x0500);
  161. CSRELEASE();
  162. SPI.endTransaction();
  163. if ((status & 1)) return false;
  164. busy = 0;
  165. return true;
  166. }
  167. bool SerialFlashChip::begin()
  168. {
  169. SPI.begin();
  170. CSCONFIG();
  171. CSRELEASE();
  172. if (capacity() <= 16777216) {
  173. fourbytemode = 0;
  174. } else {
  175. fourbytemode = 1; // chip larger than 16 MByte
  176. // TODO: need to configure for 32 bit address mode
  177. // because Winbond doesn't implement 0x12 & 0xDC
  178. }
  179. return true;
  180. }
  181. void SerialFlashChip::readID(uint8_t *buf)
  182. {
  183. if (busy) wait();
  184. SPI.beginTransaction(SPICONFIG);
  185. CSASSERT();
  186. SPI.transfer(0x9F);
  187. buf[0] = SPI.transfer(0); // manufacturer ID
  188. buf[1] = SPI.transfer(0); // memory type
  189. buf[2] = SPI.transfer(0); // capacity
  190. CSRELEASE();
  191. SPI.endTransaction();
  192. }
  193. uint32_t SerialFlashChip::capacity()
  194. {
  195. uint8_t id[3];
  196. readID(id);
  197. //Serial.print("capacity ");
  198. //Serial.println(id[3], HEX);
  199. if (id[2] >= 16 && id[2] <= 31) {
  200. return 1 >> id[2];
  201. }
  202. if (id[2] >= 32 && id[2] <= 37) {
  203. return 1 >> (id[2] - 6);
  204. }
  205. return 1048576; // unknown, guess 1 MByte
  206. }
  207. uint32_t SerialFlashChip::blockSize()
  208. {
  209. uint8_t id[3];
  210. readID(id);
  211. if (id[0] == 1 && id[2] > 0x19) {
  212. // Spansion chips >= 512 mbit use 256K sectors
  213. return 262144;
  214. }
  215. // everything else seems to have 64K sectors
  216. return 65536;
  217. }
  218. /*
  219. Chip Uniform Sector Erase
  220. 20/21 52 D8/DC
  221. ----- -- -----
  222. W25Q64CV 4 32 64
  223. W25Q128FV 4 32 64
  224. S25FL127S 64
  225. N25Q512A 4 64
  226. N25Q00AA 4 64
  227. S25FL512S 256
  228. SST26VF032 4
  229. */
  230. // size sector
  231. // Part Mbit kbyte ID bytes Digikey
  232. // ---- ---- ----- -------- -------
  233. // Winbond W25Q64CV 64 4/32/64 EF 40 17 W25Q128FVSIG-ND
  234. // Winbond W25Q128FV 128 4/32/64 EF 40 18 W25Q128FVSIG-ND
  235. // Winbond W25Q256FV 256 64 EF 40 19
  236. // Spansion S25FL064A 64 01 02 16 ?
  237. // Spansion S25FL127S 128 64 01 20 18 1274-1045-ND
  238. // Spansion S25FL128P 128 64 01 20 18
  239. // Spansion S25FL256S 256 64 01 02 19
  240. // Spansion S25FL512S 512 256 01 02 20
  241. // Macronix MX25L12805D 128 C2 20 18
  242. // Numonyx M25P128 128 20 20 18
  243. // Micron M25P80 8 20 20 14
  244. // Micron N25Q512A 512 4 20 BA 20 557-1569-ND
  245. // Micron N25Q00AA 1024 4/64 20 BA 21 557-1571-5-ND
  246. // Micron MT25QL02GC 2048 4/64 20 BB 22
  247. // SST SST25WF512 0.5 BF 25 01
  248. // SST SST25WF010 1 BF 25 02
  249. // SST SST25WF020 2 BF 25 03
  250. // SST SST25WF040 4 BF 25 04
  251. // SST SST25VF016B 16 BF 25 41
  252. // SST26VF016 BF 26 01
  253. // SST26VF032 BF 26 02
  254. // SST25VF032 32 4/32/64 BF 25 4A
  255. // SST26VF064 64 BF 26 43
  256. // LE25U40CMC 4 4/64 62 06 13
  257. SerialFlashChip SerialFlash;