SPIFLASH.C 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. Test program for SPI flash memory
  3. */
  4. #define word char
  5. #include "LIB/MATH.C"
  6. #include "LIB/STDLIB.C"
  7. #include "LIB/SYS.C"
  8. // Sets SPI0_CS low
  9. void SpiBeginTransfer()
  10. {
  11. asm(
  12. "; Backup regs\n"
  13. "push r1\n"
  14. "push r2\n"
  15. "load32 0xC02729 r2 ; r2 = 0xC02729\n"
  16. "load 0 r1 ; r1 = 0 (enable)\n"
  17. "write 0 r2 r1 ; write to SPI0_CS\n"
  18. "; Restore regs\n"
  19. "pop r2\n"
  20. "pop r1\n"
  21. );
  22. }
  23. // Sets SPI0_CS high
  24. void SpiEndTransfer()
  25. {
  26. asm(
  27. "; Backup regs\n"
  28. "push r1\n"
  29. "push r2\n"
  30. "load32 0xC02729 r2 ; r2 = 0xC02729\n"
  31. "load 1 r1 ; r1 = 1 (disable)\n"
  32. "write 0 r2 r1 ; write to SPI0_CS\n"
  33. "; Restore regs\n"
  34. "pop r2\n"
  35. "pop r1\n"
  36. );
  37. }
  38. // Write dataByte and return read value
  39. // Write 0x00 for a read
  40. // Writes byte over SPI0
  41. word SpiTransfer(word dataByte)
  42. {
  43. word retval = 0;
  44. asm(
  45. "load32 0xC02728 r2 ; r2 = 0xC02728\n"
  46. "write 0 r2 r4 ; write r4 over SPI0\n"
  47. "read 0 r2 r2 ; read return value\n"
  48. "write -4 r14 r2 ; write to stack to return\n"
  49. );
  50. return retval;
  51. }
  52. // Inits SPI by enabling SPI0 and resetting the chip
  53. void initSPI()
  54. {
  55. // Already set CS high before enabling SPI0
  56. SpiEndTransfer();
  57. // Enable SPI0
  58. word *p = (word *) 0xC0272A; // Set address (SPI0 enable)
  59. *p = 1; // Write value
  60. delay(10);
  61. // Reset to get out of continuous read mode
  62. SpiBeginTransfer();
  63. SpiTransfer(0x66);
  64. SpiEndTransfer();
  65. delay(1);
  66. SpiBeginTransfer();
  67. SpiTransfer(0x99);
  68. SpiEndTransfer();
  69. delay(1);
  70. SpiBeginTransfer();
  71. SpiTransfer(0x66);
  72. SpiEndTransfer();
  73. delay(1);
  74. SpiBeginTransfer();
  75. SpiTransfer(0x99);
  76. SpiEndTransfer();
  77. delay(1);
  78. }
  79. // Should print 239 as Winbond manufacturer, and 23 for W25Q128 device ID
  80. void readDeviceID()
  81. {
  82. SpiBeginTransfer();
  83. SpiTransfer(0x90);
  84. SpiTransfer(0);
  85. SpiTransfer(0);
  86. SpiTransfer(0);
  87. word manufacturer = SpiTransfer(0);
  88. word deviceID = SpiTransfer(0);
  89. SpiEndTransfer();
  90. BDOS_PrintConsole("Manufacturer ID: ");
  91. BDOS_PrintDecConsole(manufacturer);
  92. BDOS_PrintConsole("\n");
  93. BDOS_PrintConsole("Device ID: ");
  94. BDOS_PrintDecConsole(deviceID);
  95. BDOS_PrintConsole("\n");
  96. }
  97. void enableWrite()
  98. {
  99. SpiBeginTransfer();
  100. SpiTransfer(0x06);
  101. SpiEndTransfer();
  102. }
  103. void read_from_address(word addr, word len)
  104. {
  105. SpiBeginTransfer();
  106. SpiTransfer(0x03);
  107. SpiTransfer(addr >> 16);
  108. SpiTransfer(addr >> 8);
  109. SpiTransfer(addr);
  110. word i;
  111. for (i = 0; i < len; i++)
  112. {
  113. word x = SpiTransfer(0x00);
  114. // delay a bit here
  115. uprintDec(x);
  116. uprint(" ");
  117. }
  118. uprint("\n");
  119. SpiEndTransfer();
  120. }
  121. word readStatusRegister(word reg)
  122. {
  123. SpiBeginTransfer();
  124. if (reg == 2)
  125. SpiTransfer(0x35);
  126. else if (reg == 3)
  127. SpiTransfer(0x15);
  128. else
  129. SpiTransfer(0x05);
  130. word status = SpiTransfer(0);
  131. SpiEndTransfer();
  132. return status;
  133. }
  134. // Executes chip erase operation
  135. // TAKES AT LEAST 20 SECONDS!
  136. // Returns 1 on success
  137. word chipErase()
  138. {
  139. enableWrite();
  140. word status = readStatusRegister(1);
  141. // Check if write is enabled
  142. if ((status & 0x2) == 0)
  143. {
  144. BDOS_PrintlnConsole("WE disabled!");
  145. return 0;
  146. }
  147. // Send command
  148. SpiBeginTransfer();
  149. SpiTransfer(0xC7);
  150. SpiEndTransfer();
  151. // Wait for busy bit to be 0
  152. status = 1;
  153. while((status & 0x1) == 1)
  154. {
  155. delay(100);
  156. status = readStatusRegister(1);
  157. }
  158. BDOS_PrintlnConsole("Chip erase complete!");
  159. return 1;
  160. }
  161. void dump_memory()
  162. {
  163. word page_max = 9000;//65536;
  164. word page;
  165. for (page = 0; page < page_max; page++)
  166. {
  167. uprintDec(page);
  168. uprint(": ");
  169. word addr = page * 256;
  170. SpiBeginTransfer();
  171. SpiTransfer(0x03);
  172. SpiTransfer(addr >> 16);
  173. SpiTransfer(addr >> 8);
  174. SpiTransfer(addr);
  175. word i;
  176. for (i = 0; i < 16; i++)
  177. {
  178. word x = SpiTransfer(0x00);
  179. uprintDec(x);
  180. uprint(" ");
  181. }
  182. uprint("\n");
  183. SpiEndTransfer();
  184. }
  185. }
  186. int main()
  187. {
  188. // Clear UART screen:
  189. uprintc(0x1B);
  190. uprintc(0x5B);
  191. uprintc(0x32);
  192. uprintc(0x4A);
  193. BDOS_PrintConsole("SPI Flash test\n");
  194. initSPI();
  195. readDeviceID();
  196. //chipErase();
  197. word addr = 2000000;
  198. read_from_address(addr, 512);
  199. //dump_memory();
  200. return 'q';
  201. }
  202. void interrupt()
  203. {
  204. // Handle all interrupts
  205. word i = getIntID();
  206. switch(i)
  207. {
  208. case INTID_TIMER1:
  209. timer1Value = 1; // Notify ending of timer1
  210. break;
  211. default:
  212. break;
  213. }
  214. }