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.

481 lines
13KB

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