選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

461 行
12KB

  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. #define CSCONFIG() pinMode(6, OUTPUT)
  29. #define CSASSERT() digitalWriteFast(6, LOW)
  30. #define CSRELEASE() digitalWriteFast(6, HIGH)
  31. #define SPICONFIG SPISettings(50000000, MSBFIRST, SPI_MODE0)
  32. #if !defined(__arm__) || !defined(CORE_TEENSY)
  33. #define digitalWriteFast(pin, state) digitalWrite((pin), (state))
  34. #endif
  35. uint16_t SerialFlashChip::dirindex = 0;
  36. uint8_t SerialFlashChip::flags = 0;
  37. uint8_t SerialFlashChip::busy = 0;
  38. #define FLAG_32BIT_ADDR 0x01 // larger than 16 MByte address
  39. #define FLAG_STATUS_CMD70 0x02 // requires special busy flag check
  40. #define FLAG_DIFF_SUSPEND 0x04 // uses 2 different suspend commands
  41. #define FLAG_MULTI_DIE 0x08 // multiple die, don't read cross 32M barrier
  42. #define FLAG_256K_BLOCKS 0x10 // has 256K erase blocks
  43. #define FLAG_DIE_MASK 0xC0 // top 2 bits count during multi-die erase
  44. void SerialFlashChip::wait(void)
  45. {
  46. uint32_t status;
  47. //Serial.print("wait-");
  48. while (1) {
  49. SPI.beginTransaction(SPICONFIG);
  50. CSASSERT();
  51. if (flags & FLAG_STATUS_CMD70) {
  52. // some Micron chips require this different
  53. // command to detect program and erase completion
  54. SPI.transfer(0x70);
  55. status = SPI.transfer(0);
  56. CSRELEASE();
  57. SPI.endTransaction();
  58. //Serial.printf("b=%02x.", status & 0xFF);
  59. if ((status & 0x80)) break;
  60. } else {
  61. // all others work by simply reading the status reg
  62. SPI.transfer(0x05);
  63. status = SPI.transfer(0);
  64. CSRELEASE();
  65. SPI.endTransaction();
  66. //Serial.printf("b=%02x.", status & 0xFF);
  67. if (!(status & 1)) break;
  68. }
  69. }
  70. busy = 0;
  71. //Serial.println();
  72. }
  73. void SerialFlashChip::read(uint32_t addr, void *buf, uint32_t len)
  74. {
  75. uint8_t *p = (uint8_t *)buf;
  76. uint8_t b, f, status;
  77. memset(p, 0, len);
  78. f = flags;
  79. SPI.beginTransaction(SPICONFIG);
  80. b = busy;
  81. if (b) {
  82. // read status register ... chip may no longer be busy
  83. CSASSERT();
  84. if (flags & FLAG_STATUS_CMD70) {
  85. SPI.transfer(0x70);
  86. status = SPI.transfer(0);
  87. if ((status & 0x80)) b = 0;
  88. } else {
  89. SPI.transfer(0x05);
  90. status = SPI.transfer(0);
  91. if (!(status & 1)) b = 0;
  92. }
  93. CSRELEASE();
  94. if (b == 0) {
  95. // chip is no longer busy :-)
  96. busy = 0;
  97. } else if (b < 3) {
  98. // TODO: this may not work on Spansion chips
  99. // which apparently have 2 different suspend
  100. // commands, for program vs erase
  101. CSASSERT();
  102. SPI.transfer(0x06); // write enable (Micron req'd)
  103. CSRELEASE();
  104. delayMicroseconds(1);
  105. CSASSERT();
  106. SPI.transfer(0x75); // Suspend program/erase
  107. CSRELEASE();
  108. if (f & FLAG_STATUS_CMD70) {
  109. // Micron chips don't actually suspend until flags read
  110. CSASSERT();
  111. SPI.transfer(0x70);
  112. do {
  113. status = SPI.transfer(0);
  114. } while (!(status & 0x80));
  115. CSRELEASE();
  116. } else {
  117. delayMicroseconds(20); // Tsus = 20us (Winbond)
  118. }
  119. } else {
  120. // chip is busy with an operation that can not suspend
  121. SPI.endTransaction(); // is this a good idea?
  122. wait(); // should we wait without ending
  123. b = 0; // the transaction??
  124. SPI.beginTransaction(SPICONFIG);
  125. }
  126. }
  127. do {
  128. uint32_t rdlen = len;
  129. if (f & FLAG_MULTI_DIE) {
  130. if ((addr & 0xFE000000) != ((addr + len - 1) & 0xFE000000)) {
  131. rdlen = 0x2000000 - (addr & 0x1FFFFFF);
  132. }
  133. }
  134. CSASSERT();
  135. // TODO: FIFO optimize....
  136. if (f & FLAG_32BIT_ADDR) {
  137. SPI.transfer(0x03);
  138. SPI.transfer16(addr >> 16);
  139. SPI.transfer16(addr);
  140. } else {
  141. SPI.transfer16(0x0300 | ((addr >> 16) & 255));
  142. SPI.transfer16(addr);
  143. }
  144. SPI.transfer(p, rdlen);
  145. CSRELEASE();
  146. p += rdlen;
  147. addr += rdlen;
  148. len -= rdlen;
  149. } while (len > 0);
  150. if (b) {
  151. CSASSERT();
  152. SPI.transfer(0x06); // write enable (Micro req'd)
  153. CSRELEASE();
  154. delayMicroseconds(1);
  155. CSASSERT();
  156. SPI.transfer(0x7A); // Resume program/erase
  157. CSRELEASE();
  158. }
  159. SPI.endTransaction();
  160. }
  161. void SerialFlashChip::write(uint32_t addr, const void *buf, uint32_t len)
  162. {
  163. const uint8_t *p = (const uint8_t *)buf;
  164. uint32_t max, pagelen;
  165. //Serial.println("write");
  166. do {
  167. if (busy) wait();
  168. //Serial.printf("pagelen=%d\n", pagelen);
  169. SPI.beginTransaction(SPICONFIG);
  170. CSASSERT();
  171. // write enable command
  172. SPI.transfer(0x06);
  173. CSRELEASE();
  174. max = 256 - (addr & 0xFF);
  175. pagelen = (len <= max) ? len : max;
  176. len -= pagelen;
  177. CSASSERT();
  178. if (flags & FLAG_32BIT_ADDR) {
  179. //Serial.printf("write 32 bit addr %08X %02X\n", addr, addr >> 24);
  180. SPI.transfer(0x02);
  181. SPI.transfer16(addr >> 16);
  182. SPI.transfer16(addr);
  183. } else {
  184. SPI.transfer16(0x0200 | ((addr >> 16) & 255));
  185. SPI.transfer16(addr);
  186. }
  187. // program page command
  188. do {
  189. SPI.transfer(*p++);
  190. } while (--pagelen > 0);
  191. CSRELEASE();
  192. SPI.endTransaction();
  193. busy = 1;
  194. //Serial.printf("busy=%d\n", busy);
  195. } while (len > 0);
  196. }
  197. void SerialFlashChip::eraseAll()
  198. {
  199. if (busy) wait();
  200. uint8_t id[3];
  201. readID(id);
  202. //Serial.printf("ID: %02X %02X %02X\n", id[0], id[1], id[2]);
  203. if (id[0] == 0x20 && id[2] >= 0x20 && id[2] <= 0x22) {
  204. // Micron's multi-die chips require special die erase commands
  205. // N25Q512A 20 BA 20 2 dies 32 Mbyte/die 65 nm transitors
  206. // N25Q00AA 20 BA 21 4 dies 32 Mbyte/die 65 nm transitors
  207. // MT25QL02GC 20 BA 22 2 dies 128 Mbyte/die 45 nm transitors
  208. uint8_t die_count = 2;
  209. if (id[2] == 0x21) die_count = 4;
  210. uint8_t die_index = flags >> 6;
  211. //Serial.printf("Micron die erase %d\n", die_index);
  212. flags &= 0x3F;
  213. if (die_index >= die_count) return; // all dies erased :-)
  214. uint8_t die_size = 2; // in 16 Mbyte units
  215. if (id[2] == 0x22) die_size = 8;
  216. SPI.beginTransaction(SPICONFIG);
  217. CSASSERT();
  218. SPI.transfer(0x06); // write enable command
  219. CSRELEASE();
  220. delayMicroseconds(1);
  221. CSASSERT();
  222. // die erase command
  223. SPI.transfer(0xC4);
  224. SPI.transfer16((die_index * die_size) << 8);
  225. SPI.transfer16(0x0000);
  226. CSRELEASE();
  227. //Serial.printf("Micron erase begin\n");
  228. flags |= (die_index + 1) << 6;
  229. } else {
  230. // All other chips support the bulk erase command
  231. SPI.beginTransaction(SPICONFIG);
  232. CSASSERT();
  233. // write enable command
  234. SPI.transfer(0x06);
  235. CSRELEASE();
  236. delayMicroseconds(1);
  237. CSASSERT();
  238. // bulk erase command
  239. SPI.transfer(0xC7);
  240. CSRELEASE();
  241. SPI.endTransaction();
  242. }
  243. busy = 3;
  244. }
  245. void SerialFlashChip::eraseBlock(uint32_t addr)
  246. {
  247. uint8_t f = flags;
  248. if (busy) wait();
  249. SPI.beginTransaction(SPICONFIG);
  250. CSASSERT();
  251. SPI.transfer(0x06); // write enable command
  252. CSRELEASE();
  253. delayMicroseconds(1);
  254. CSASSERT();
  255. if (f & FLAG_32BIT_ADDR) {
  256. SPI.transfer(0xD8);
  257. SPI.transfer16(addr >> 16);
  258. SPI.transfer16(addr);
  259. } else {
  260. SPI.transfer16(0xD800 | ((addr >> 16) & 255));
  261. SPI.transfer16(addr);
  262. }
  263. CSRELEASE();
  264. SPI.endTransaction();
  265. busy = 2;
  266. }
  267. bool SerialFlashChip::ready()
  268. {
  269. uint32_t status;
  270. if (!busy) return true;
  271. SPI.beginTransaction(SPICONFIG);
  272. CSASSERT();
  273. if (flags & FLAG_STATUS_CMD70) {
  274. // some Micron chips require this different
  275. // command to detect program and erase completion
  276. SPI.transfer(0x70);
  277. status = SPI.transfer(0);
  278. CSRELEASE();
  279. SPI.endTransaction();
  280. //Serial.printf("ready=%02x\n", status & 0xFF);
  281. if ((status & 0x80) == 0) return false;
  282. } else {
  283. // all others work by simply reading the status reg
  284. SPI.transfer(0x05);
  285. status = SPI.transfer(0);
  286. CSRELEASE();
  287. SPI.endTransaction();
  288. //Serial.printf("ready=%02x\n", status & 0xFF);
  289. if ((status & 1)) return false;
  290. }
  291. busy = 0;
  292. if (flags & 0xC0) {
  293. // continue a multi-die erase
  294. eraseAll();
  295. return false;
  296. }
  297. return true;
  298. }
  299. #define ID0_WINBOND 0xEF
  300. #define ID0_SPANSION 0x01
  301. #define ID0_MICRON 0x20
  302. #define ID0_MACRONIX 0xC2
  303. #define ID0_SST 0xBF
  304. //#define FLAG_32BIT_ADDR 0x01 // larger than 16 MByte address
  305. //#define FLAG_STATUS_CMD70 0x02 // requires special busy flag check
  306. //#define FLAG_DIFF_SUSPEND 0x04 // uses 2 different suspend commands
  307. //#define FLAG_256K_BLOCKS 0x10 // has 256K erase blocks
  308. bool SerialFlashChip::begin()
  309. {
  310. uint8_t id[3];
  311. uint8_t f;
  312. uint32_t size;
  313. SPI.begin();
  314. CSCONFIG();
  315. CSRELEASE();
  316. readID(id);
  317. f = 0;
  318. size = capacity(id);
  319. if (size > 16777216) {
  320. // more than 16 Mbyte requires 32 bit addresses
  321. f |= FLAG_32BIT_ADDR;
  322. SPI.beginTransaction(SPICONFIG);
  323. if (id[0] == ID0_SPANSION) {
  324. // spansion uses MSB of bank register
  325. CSASSERT();
  326. SPI.transfer16(0x1780); // bank register write
  327. CSRELEASE();
  328. } else {
  329. // micron & winbond & macronix use command
  330. CSASSERT();
  331. SPI.transfer(0x06); // write enable
  332. CSRELEASE();
  333. delayMicroseconds(1);
  334. CSASSERT();
  335. SPI.transfer(0xB7); // enter 4 byte addr mode
  336. CSRELEASE();
  337. }
  338. SPI.endTransaction();
  339. if (id[0] == ID0_MICRON) f |= FLAG_MULTI_DIE;
  340. }
  341. if (id[0] == ID0_SPANSION) {
  342. // Spansion has separate suspend commands
  343. f |= FLAG_DIFF_SUSPEND;
  344. if (size >= 67108864) {
  345. // Spansion chips >= 512 mbit use 256K sectors
  346. f |= FLAG_256K_BLOCKS;
  347. }
  348. }
  349. if (id[0] == ID0_MICRON) {
  350. // Micron requires busy checks with a different command
  351. f |= FLAG_STATUS_CMD70; // TODO: all or just multi-die chips?
  352. }
  353. flags = f;
  354. readID(id);
  355. return true;
  356. }
  357. void SerialFlashChip::readID(uint8_t *buf)
  358. {
  359. if (busy) wait();
  360. SPI.beginTransaction(SPICONFIG);
  361. CSASSERT();
  362. SPI.transfer(0x9F);
  363. buf[0] = SPI.transfer(0); // manufacturer ID
  364. buf[1] = SPI.transfer(0); // memory type
  365. buf[2] = SPI.transfer(0); // capacity
  366. CSRELEASE();
  367. SPI.endTransaction();
  368. //Serial.printf("ID: %02X %02X %02X\n", buf[0], buf[1], buf[2]);
  369. }
  370. uint32_t SerialFlashChip::capacity(const uint8_t *id)
  371. {
  372. uint32_t n = 1048576; // unknown chips, default to 1 MByte
  373. if (id[2] >= 16 && id[2] <= 31) {
  374. n = 1ul << id[2];
  375. } else
  376. if (id[2] >= 32 && id[2] <= 37) {
  377. n = 1ul << (id[2] - 6);
  378. }
  379. //Serial.printf("capacity %lu\n", n);
  380. return n;
  381. }
  382. uint32_t SerialFlashChip::blockSize()
  383. {
  384. // Spansion chips >= 512 mbit use 256K sectors
  385. if (flags & FLAG_256K_BLOCKS) return 262144;
  386. // everything else seems to have 64K sectors
  387. return 65536;
  388. }
  389. /*
  390. Chip Uniform Sector Erase
  391. 20/21 52 D8/DC
  392. ----- -- -----
  393. W25Q64CV 4 32 64
  394. W25Q128FV 4 32 64
  395. S25FL127S 64
  396. N25Q512A 4 64
  397. N25Q00AA 4 64
  398. S25FL512S 256
  399. SST26VF032 4
  400. */
  401. // size sector busy pgm/erase chip
  402. // Part Mbyte kbyte ID bytes cmd suspend erase
  403. // ---- ---- ----- -------- --- ------- -----
  404. // Winbond W25Q64CV 8 64 EF 40 17
  405. // Winbond W25Q128FV 16 64 EF 40 18 05 single 60 & C7
  406. // Winbond W25Q256FV 32 64 EF 40 19
  407. // Spansion S25FL064A 8 ? 01 02 16
  408. // Spansion S25FL127S 16 64 01 20 18 05
  409. // Spansion S25FL128P 16 64 01 20 18
  410. // Spansion S25FL256S 32 64 01 02 19 05 60 & C7
  411. // Spansion S25FL512S 64 256 01 02 20
  412. // Macronix MX25L12805D 16 ? C2 20 18
  413. // Macronix MX66L51235F 64 C2 20 1A
  414. // Numonyx M25P128 16 ? 20 20 18
  415. // Micron M25P80 1 ? 20 20 14
  416. // Micron N25Q128A 16 64 20 BA 18
  417. // Micron N25Q512A 64 ? 20 BA 20 70 single C4 x2
  418. // Micron N25Q00AA 128 64 20 BA 21 single C4 x4
  419. // Micron MT25QL02GC 256 64 20 BA 22 70 C4 x2
  420. // SST SST25WF010 1/8 ? BF 25 02
  421. // SST SST25WF020 1/4 ? BF 25 03
  422. // SST SST25WF040 1/2 ? BF 25 04
  423. // SST SST25VF016B 1 ? BF 25 41
  424. // SST26VF016 ? BF 26 01
  425. // SST26VF032 ? BF 26 02
  426. // SST25VF032 4 64 BF 25 4A
  427. // SST26VF064 8 ? BF 26 43
  428. // LE25U40CMC 1/2 64 62 06 13
  429. SerialFlashChip SerialFlash;