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.

503 lines
14KB

  1. // RawHardwareTest - Check if a SPI Flash chip is compatible
  2. // with SerialFlash by performing many read and write tests
  3. // to its memory.
  4. //
  5. // The chip should be fully erased before running this test.
  6. // Use the EraseEverything to do a (slow) full chip erase.
  7. //
  8. // Normally you should NOT access the flash memory directly,
  9. // as this test program does. You should create files and
  10. // read and write the files. File creation allocates space
  11. // with program & erase boundaries within the chip, to allow
  12. // reading from any other files while a file is busy writing
  13. // or erasing (if created as erasable).
  14. //
  15. // If you discover an incompatible chip, please report it here:
  16. // https://github.com/PaulStoffregen/SerialFlash/issues
  17. // You MUST post the complete output of this program, and
  18. // the exact part number and manufacturer of the chip.
  19. #include <SerialFlash.h>
  20. #include <SPI.h>
  21. const int FlashChipSelect = 6; // digital pin for flash chip CS pin
  22. // Uncomment this line if using the built-in SPI Flash device
  23. // on an Arduino 101 board
  24. //const int FlashChipSelect = 21;
  25. SerialFlashFile file;
  26. const unsigned long testIncrement = 4096;
  27. void setup() {
  28. //uncomment these if using Teensy audio shield
  29. //SPI.setSCK(14); // Audio shield has SCK on pin 14
  30. //SPI.setMOSI(7); // Audio shield has MOSI on pin 7
  31. //uncomment these if you have other SPI chips connected
  32. //to keep them disabled while using only SerialFlash
  33. //pinMode(4, INPUT_PULLUP);
  34. //pinMode(10, INPUT_PULLUP);
  35. Serial.begin(9600);
  36. while (!Serial) ;
  37. delay(100);
  38. Serial.println("Raw SerialFlash Hardware Test");
  39. SerialFlash.begin(FlashChipSelect);
  40. if (test()) {
  41. Serial.println();
  42. Serial.println("All Tests Passed :-)");
  43. Serial.println();
  44. Serial.println("Test data was written to your chip. You must run");
  45. Serial.println("EraseEverything before using this chip for files.");
  46. } else {
  47. Serial.println();
  48. Serial.println("Tests Failed :{");
  49. Serial.println();
  50. Serial.println("The flash chip may be left in an improper state.");
  51. Serial.println("You might need to power cycle to return to normal.");
  52. }
  53. }
  54. bool test() {
  55. unsigned char buf[256], sig[256], buf2[8];
  56. unsigned long address, count, chipsize, blocksize;
  57. unsigned long usec;
  58. bool first;
  59. // Read the chip identification
  60. Serial.println();
  61. Serial.println("Read Chip Identification:");
  62. SerialFlash.readID(buf);
  63. Serial.print(" JEDEC ID: ");
  64. Serial.print(buf[0], HEX);
  65. Serial.print(" ");
  66. Serial.print(buf[1], HEX);
  67. Serial.print(" ");
  68. Serial.println(buf[2], HEX);
  69. Serial.print(" Part Nummber: ");
  70. Serial.println(id2chip(buf));
  71. Serial.print(" Memory Size: ");
  72. chipsize = SerialFlash.capacity(buf);
  73. Serial.print(chipsize);
  74. Serial.println(" bytes");
  75. if (chipsize == 0) return false;
  76. Serial.print(" Block Size: ");
  77. blocksize = SerialFlash.blockSize();
  78. Serial.print(blocksize);
  79. Serial.println(" bytes");
  80. // Read the entire chip. Every test location must be
  81. // erased, or have a previously tested signature
  82. Serial.println();
  83. Serial.println("Reading Chip...");
  84. memset(buf, 0, sizeof(buf));
  85. memset(sig, 0, sizeof(sig));
  86. memset(buf2, 0, sizeof(buf2));
  87. address = 0;
  88. count = 0;
  89. first = true;
  90. while (address < chipsize) {
  91. SerialFlash.read(address, buf, 8);
  92. //Serial.print(" addr = ");
  93. //Serial.print(address, HEX);
  94. //Serial.print(", data = ");
  95. //printbuf(buf, 8);
  96. create_signature(address, sig);
  97. if (is_erased(buf, 8) == false) {
  98. if (equal_signatures(buf, sig) == false) {
  99. Serial.print(" Previous data found at address ");
  100. Serial.println(address);
  101. Serial.println(" You must fully erase the chip before this test");
  102. Serial.print(" found this: ");
  103. printbuf(buf, 8);
  104. Serial.print(" correct: ");
  105. printbuf(sig, 8);
  106. return false;
  107. }
  108. } else {
  109. count = count + 1; // number of blank signatures
  110. }
  111. if (first) {
  112. address = address + (testIncrement - 8);
  113. first = false;
  114. } else {
  115. address = address + 8;
  116. first = true;
  117. }
  118. }
  119. // Write any signatures that were blank on the original check
  120. if (count > 0) {
  121. Serial.println();
  122. Serial.print("Writing ");
  123. Serial.print(count);
  124. Serial.println(" signatures");
  125. memset(buf, 0, sizeof(buf));
  126. memset(sig, 0, sizeof(sig));
  127. memset(buf2, 0, sizeof(buf2));
  128. address = 0;
  129. first = true;
  130. while (address < chipsize) {
  131. SerialFlash.read(address, buf, 8);
  132. if (is_erased(buf, 8)) {
  133. create_signature(address, sig);
  134. //Serial.printf("write %08X: data: ", address);
  135. //printbuf(sig, 8);
  136. SerialFlash.write(address, sig, 8);
  137. while (!SerialFlash.ready()) ; // wait
  138. SerialFlash.read(address, buf, 8);
  139. if (equal_signatures(buf, sig) == false) {
  140. Serial.print(" error writing signature at ");
  141. Serial.println(address);
  142. Serial.print(" Read this: ");
  143. printbuf(buf, 8);
  144. Serial.print(" Expected: ");
  145. printbuf(sig, 8);
  146. return false;
  147. }
  148. }
  149. if (first) {
  150. address = address + (testIncrement - 8);
  151. first = false;
  152. } else {
  153. address = address + 8;
  154. first = true;
  155. }
  156. }
  157. } else {
  158. Serial.println(" all signatures present from prior tests");
  159. }
  160. // Read all the signatures again, just to be sure
  161. // checks prior writing didn't corrupt any other data
  162. Serial.println();
  163. Serial.println("Double Checking All Signatures:");
  164. memset(buf, 0, sizeof(buf));
  165. memset(sig, 0, sizeof(sig));
  166. memset(buf2, 0, sizeof(buf2));
  167. count = 0;
  168. address = 0;
  169. first = true;
  170. while (address < chipsize) {
  171. SerialFlash.read(address, buf, 8);
  172. create_signature(address, sig);
  173. if (equal_signatures(buf, sig) == false) {
  174. Serial.print(" error in signature at ");
  175. Serial.println(address);
  176. Serial.print(" Read this: ");
  177. printbuf(buf, 8);
  178. Serial.print(" Expected: ");
  179. printbuf(sig, 8);
  180. return false;
  181. }
  182. count = count + 1;
  183. if (first) {
  184. address = address + (testIncrement - 8);
  185. first = false;
  186. } else {
  187. address = address + 8;
  188. first = true;
  189. }
  190. }
  191. Serial.print(" all ");
  192. Serial.print(count);
  193. Serial.println(" signatures read ok");
  194. // Read pairs of adjacent signatures
  195. // check read works across boundaries
  196. Serial.println();
  197. Serial.println("Checking Signature Pairs");
  198. memset(buf, 0, sizeof(buf));
  199. memset(sig, 0, sizeof(sig));
  200. memset(buf2, 0, sizeof(buf2));
  201. count = 0;
  202. address = testIncrement - 8;
  203. first = true;
  204. while (address < chipsize - 8) {
  205. SerialFlash.read(address, buf, 16);
  206. create_signature(address, sig);
  207. create_signature(address + 8, sig + 8);
  208. if (memcmp(buf, sig, 16) != 0) {
  209. Serial.print(" error in signature pair at ");
  210. Serial.println(address);
  211. Serial.print(" Read this: ");
  212. printbuf(buf, 16);
  213. Serial.print(" Expected: ");
  214. printbuf(sig, 16);
  215. return false;
  216. }
  217. count = count + 1;
  218. address = address + testIncrement;
  219. }
  220. Serial.print(" all ");
  221. Serial.print(count);
  222. Serial.println(" signature pairs read ok");
  223. // Write data and read while write in progress
  224. Serial.println();
  225. Serial.println("Checking Read-While-Write (Program Suspend)");
  226. address = 256;
  227. while (address < chipsize) { // find a blank space
  228. SerialFlash.read(address, buf, 256);
  229. if (is_erased(buf, 256)) break;
  230. address = address + 256;
  231. }
  232. if (address >= chipsize) {
  233. Serial.println(" error, unable to find any blank space!");
  234. return false;
  235. }
  236. for (int i=0; i < 256; i += 8) {
  237. create_signature(address + i, sig + i);
  238. }
  239. Serial.print(" write 256 bytes at ");
  240. Serial.println(address);
  241. Serial.flush();
  242. SerialFlash.write(address, sig, 256);
  243. usec = micros();
  244. if (SerialFlash.ready()) {
  245. Serial.println(" error, chip did not become busy after write");
  246. return false;
  247. }
  248. SerialFlash.read(0, buf2, 8); // read while busy writing
  249. while (!SerialFlash.ready()) ; // wait
  250. usec = micros() - usec;
  251. Serial.print(" write time was ");
  252. Serial.print(usec);
  253. Serial.println(" microseconds.");
  254. SerialFlash.read(address, buf, 256);
  255. if (memcmp(buf, sig, 256) != 0) {
  256. Serial.println(" error writing to flash");
  257. Serial.print(" Read this: ");
  258. printbuf(buf, 256);
  259. Serial.print(" Expected: ");
  260. printbuf(sig, 256);
  261. return false;
  262. }
  263. create_signature(0, sig);
  264. if (memcmp(buf2, sig, 8) != 0) {
  265. Serial.println(" error, incorrect read while writing");
  266. Serial.print(" Read this: ");
  267. printbuf(buf2, 256);
  268. Serial.print(" Expected: ");
  269. printbuf(sig, 256);
  270. return false;
  271. }
  272. Serial.print(" read-while-writing: ");
  273. printbuf(buf2, 8);
  274. Serial.println(" test passed, good read while writing");
  275. // Erase a block and read while erase in progress
  276. if (chipsize >= 262144 + blocksize + testIncrement) {
  277. Serial.println();
  278. Serial.println("Checking Read-While-Erase (Erase Suspend)");
  279. memset(buf, 0, sizeof(buf));
  280. memset(sig, 0, sizeof(sig));
  281. memset(buf2, 0, sizeof(buf2));
  282. SerialFlash.eraseBlock(262144);
  283. usec = micros();
  284. delayMicroseconds(50);
  285. if (SerialFlash.ready()) {
  286. Serial.println(" error, chip did not become busy after erase");
  287. return false;
  288. }
  289. SerialFlash.read(0, buf2, 8); // read while busy writing
  290. while (!SerialFlash.ready()) ; // wait
  291. usec = micros() - usec;
  292. Serial.print(" erase time was ");
  293. Serial.print(usec);
  294. Serial.println(" microseconds.");
  295. // read all signatures, check ones in this block got
  296. // erased, and all the others are still intact
  297. address = 0;
  298. first = true;
  299. while (address < chipsize) {
  300. SerialFlash.read(address, buf, 8);
  301. if (address >= 262144 && address < 262144 + blocksize) {
  302. if (is_erased(buf, 8) == false) {
  303. Serial.print(" error in erasing at ");
  304. Serial.println(address);
  305. Serial.print(" Read this: ");
  306. printbuf(buf, 8);
  307. return false;
  308. }
  309. } else {
  310. create_signature(address, sig);
  311. if (equal_signatures(buf, sig) == false) {
  312. Serial.print(" error in signature at ");
  313. Serial.println(address);
  314. Serial.print(" Read this: ");
  315. printbuf(buf, 8);
  316. Serial.print(" Expected: ");
  317. printbuf(sig, 8);
  318. return false;
  319. }
  320. }
  321. if (first) {
  322. address = address + (testIncrement - 8);
  323. first = false;
  324. } else {
  325. address = address + 8;
  326. first = true;
  327. }
  328. }
  329. Serial.print(" erase correctly erased ");
  330. Serial.print(blocksize);
  331. Serial.println(" bytes");
  332. // now check if the data we read during erase is good
  333. create_signature(0, sig);
  334. if (memcmp(buf2, sig, 8) != 0) {
  335. Serial.println(" error, incorrect read while erasing");
  336. Serial.print(" Read this: ");
  337. printbuf(buf2, 256);
  338. Serial.print(" Expected: ");
  339. printbuf(sig, 256);
  340. return false;
  341. }
  342. Serial.print(" read-while-erasing: ");
  343. printbuf(buf2, 8);
  344. Serial.println(" test passed, good read while erasing");
  345. } else {
  346. Serial.println("Skip Read-While-Erase, this chip is too small");
  347. }
  348. return true;
  349. }
  350. void loop() {
  351. // do nothing after the test
  352. }
  353. const char * id2chip(const unsigned char *id)
  354. {
  355. if (id[0] == 0xEF) {
  356. // Winbond
  357. if (id[1] == 0x40) {
  358. if (id[2] == 0x14) return "W25Q80BV";
  359. if (id[2] == 0x17) return "W25Q64FV";
  360. if (id[2] == 0x18) return "W25Q128FV";
  361. if (id[2] == 0x19) return "W25Q256FV";
  362. }
  363. }
  364. if (id[0] == 0x01) {
  365. // Spansion
  366. if (id[1] == 0x02) {
  367. if (id[2] == 0x16) return "S25FL064A";
  368. if (id[2] == 0x19) return "S25FL256S";
  369. if (id[2] == 0x20) return "S25FL512S";
  370. }
  371. if (id[1] == 0x20) {
  372. if (id[2] == 0x18) return "S25FL127S";
  373. }
  374. }
  375. if (id[0] == 0xC2) {
  376. // Macronix
  377. if (id[1] == 0x20) {
  378. if (id[2] == 0x18) return "MX25L12805D";
  379. }
  380. }
  381. if (id[0] == 0x20) {
  382. // Micron
  383. if (id[1] == 0xBA) {
  384. if (id[2] == 0x20) return "N25Q512A";
  385. if (id[2] == 0x21) return "N25Q00AA";
  386. }
  387. if (id[1] == 0xBB) {
  388. if (id[2] == 0x22) return "MT25QL02GC";
  389. }
  390. }
  391. if (id[0] == 0xBF) {
  392. // SST
  393. if (id[1] == 0x25) {
  394. if (id[2] == 0x02) return "SST25WF010";
  395. if (id[2] == 0x03) return "SST25WF020";
  396. if (id[2] == 0x04) return "SST25WF040";
  397. if (id[2] == 0x41) return "SST25VF016B";
  398. if (id[2] == 0x4A) return "SST25VF032";
  399. }
  400. if (id[1] == 0x25) {
  401. if (id[2] == 0x01) return "SST26VF016";
  402. if (id[2] == 0x02) return "SST26VF032";
  403. if (id[2] == 0x43) return "SST26VF064";
  404. }
  405. }
  406. return "(unknown chip)";
  407. }
  408. void print_signature(const unsigned char *data)
  409. {
  410. Serial.print("data=");
  411. for (unsigned char i=0; i < 8; i++) {
  412. Serial.print(data[i]);
  413. Serial.print(" ");
  414. }
  415. Serial.println();
  416. }
  417. void create_signature(unsigned long address, unsigned char *data)
  418. {
  419. data[0] = address >> 24;
  420. data[1] = address >> 16;
  421. data[2] = address >> 8;
  422. data[3] = address;
  423. unsigned long hash = 2166136261ul;
  424. for (unsigned char i=0; i < 4; i++) {
  425. hash ^= data[i];
  426. hash *= 16777619ul;
  427. }
  428. data[4] = hash;
  429. data[5] = hash >> 8;
  430. data[6] = hash >> 16;
  431. data[7] = hash >> 24;
  432. }
  433. bool equal_signatures(const unsigned char *data1, const unsigned char *data2)
  434. {
  435. for (unsigned char i=0; i < 8; i++) {
  436. if (data1[i] != data2[i]) return false;
  437. }
  438. return true;
  439. }
  440. bool is_erased(const unsigned char *data, unsigned int len)
  441. {
  442. while (len > 0) {
  443. if (*data++ != 255) return false;
  444. len = len - 1;
  445. }
  446. return true;
  447. }
  448. void printbuf(const void *buf, uint32_t len)
  449. {
  450. const uint8_t *p = (const uint8_t *)buf;
  451. do {
  452. unsigned char b = *p++;
  453. Serial.print(b >> 4, HEX);
  454. Serial.print(b & 15, HEX);
  455. //Serial.printf("%02X", *p++);
  456. Serial.print(" ");
  457. } while (--len > 0);
  458. Serial.println();
  459. }