xflash.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. //xflash.c
  2. #include "xflash.h"
  3. #include <avr/io.h>
  4. #include <avr/pgmspace.h>
  5. #include "spi.h"
  6. #include "fastio.h"
  7. #ifdef XFLASH
  8. #define _MFRID_W25X20CL 0xEF
  9. #define _DEVID_W25X20CL 0x11
  10. #define _MFRID_GD25Q20C 0xC8
  11. #define _DEVID_GD25Q20C 0x11
  12. #define _CMD_ENABLE_WR 0x06
  13. #define _CMD_ENABLE_WR_VSR 0x50
  14. #define _CMD_DISABLE_WR 0x04
  15. #define _CMD_RD_STATUS_REG 0x05
  16. #define _CMD_WR_STATUS_REG 0x01
  17. #define _CMD_RD_DATA 0x03
  18. #define _CMD_RD_FAST 0x0b
  19. #define _CMD_RD_FAST_D_O 0x3b
  20. #define _CMD_RD_FAST_D_IO 0xbb
  21. #define _CMD_PAGE_PROGRAM 0x02
  22. #define _CMD_SECTOR_ERASE 0x20
  23. #define _CMD_BLOCK32_ERASE 0x52
  24. #define _CMD_BLOCK64_ERASE 0xd8
  25. #define _CMD_CHIP_ERASE 0xc7
  26. #define _CMD_CHIP_ERASE2 0x60
  27. #define _CMD_PWR_DOWN 0xb9
  28. #define _CMD_PWR_DOWN_REL 0xab
  29. #define _CMD_MFRID_DEVID 0x90
  30. #define _CMD_MFRID_DEVID_D 0x92
  31. #define _CMD_JEDEC_ID 0x9f
  32. #define _CMD_RD_UID 0x4b
  33. #define _CS_LOW() WRITE(XFLASH_PIN_CS, 0)
  34. #define _CS_HIGH() WRITE(XFLASH_PIN_CS, 1)
  35. //#define _SPI_TX swspi_tx
  36. //#define _SPI_RX swspi_rx
  37. #define _SPI_TX(b) spi_txrx(b)
  38. #define _SPI_RX() spi_txrx(0xff)
  39. int xflash_mfrid_devid(void);
  40. int8_t xflash_init(void)
  41. {
  42. _CS_HIGH();
  43. SET_OUTPUT(XFLASH_PIN_CS);
  44. XFLASH_SPI_ENTER();
  45. if (!xflash_mfrid_devid()) return 0;
  46. return 1;
  47. }
  48. void xflash_enable_wr(void)
  49. {
  50. _CS_LOW();
  51. _SPI_TX(_CMD_ENABLE_WR); // send command 0x06
  52. _CS_HIGH();
  53. }
  54. void xflash_disable_wr(void)
  55. {
  56. _CS_LOW();
  57. _SPI_TX(_CMD_DISABLE_WR); // send command 0x04
  58. _CS_HIGH();
  59. }
  60. uint8_t xflash_rd_status_reg(void)
  61. {
  62. _CS_LOW();
  63. _SPI_TX(_CMD_RD_STATUS_REG); // send command 0x90
  64. uint8_t val = _SPI_RX(); // receive value
  65. _CS_HIGH();
  66. return val;
  67. }
  68. #if 0
  69. void w25x20cl_wr_status_reg(uint8_t val)
  70. {
  71. _CS_LOW();
  72. _SPI_TX(_CMD_WR_STATUS_REG); // send command 0x90
  73. _SPI_TX(val); // send value
  74. _CS_HIGH();
  75. }
  76. #endif
  77. static void xflash_send_cmdaddr(uint8_t cmd, uint32_t addr)
  78. {
  79. _SPI_TX(cmd); // send command 0x03
  80. _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
  81. _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
  82. _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
  83. }
  84. void xflash_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt)
  85. {
  86. _CS_LOW();
  87. xflash_send_cmdaddr(_CMD_RD_DATA, addr);
  88. while (cnt--) // receive data
  89. *(data++) = _SPI_RX();
  90. _CS_HIGH();
  91. }
  92. void xflash_page_program(uint32_t addr, uint8_t* data, uint16_t cnt)
  93. {
  94. _CS_LOW();
  95. xflash_send_cmdaddr(_CMD_PAGE_PROGRAM, addr);
  96. while (cnt--) // send data
  97. _SPI_TX(*(data++));
  98. _CS_HIGH();
  99. }
  100. void xflash_multipage_program(uint32_t addr, uint8_t* data, uint16_t cnt)
  101. {
  102. while(cnt)
  103. {
  104. xflash_enable_wr();
  105. _CS_LOW();
  106. xflash_send_cmdaddr(_CMD_PAGE_PROGRAM, addr);
  107. while(1)
  108. {
  109. // send data
  110. _SPI_TX(*(data++));
  111. if(!--cnt || !(++addr & 0xFF))
  112. {
  113. // on a page boundary or end of write
  114. _CS_HIGH();
  115. xflash_wait_busy();
  116. break;
  117. }
  118. }
  119. }
  120. }
  121. void xflash_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt)
  122. {
  123. _CS_LOW();
  124. xflash_send_cmdaddr(_CMD_PAGE_PROGRAM, addr);
  125. while (cnt--) // send data
  126. _SPI_TX(pgm_read_byte(data++));
  127. _CS_HIGH();
  128. }
  129. void xflash_erase(uint8_t cmd, uint32_t addr)
  130. {
  131. _CS_LOW();
  132. xflash_send_cmdaddr(cmd, addr);
  133. _CS_HIGH();
  134. }
  135. void xflash_sector_erase(uint32_t addr)
  136. {
  137. return xflash_erase(_CMD_SECTOR_ERASE, addr);
  138. }
  139. void xflash_block32_erase(uint32_t addr)
  140. {
  141. return xflash_erase(_CMD_BLOCK32_ERASE, addr);
  142. }
  143. void xflash_block64_erase(uint32_t addr)
  144. {
  145. return xflash_erase(_CMD_BLOCK64_ERASE, addr);
  146. }
  147. void xflash_chip_erase(void)
  148. {
  149. _CS_LOW();
  150. _SPI_TX(_CMD_CHIP_ERASE); // send command 0xc7
  151. _CS_HIGH();
  152. }
  153. void xflash_rd_uid(uint8_t* uid)
  154. {
  155. _CS_LOW();
  156. _SPI_TX(_CMD_RD_UID); // send command 0x4b
  157. uint8_t cnt = 4; // 4 dummy bytes
  158. while (cnt--) // transmit dummy bytes
  159. _SPI_TX(0x00);
  160. cnt = 8; // 8 bytes UID
  161. while (cnt--) // receive UID
  162. uid[7 - cnt] = _SPI_RX();
  163. _CS_HIGH();
  164. }
  165. int xflash_mfrid_devid(void)
  166. {
  167. _CS_LOW();
  168. _SPI_TX(_CMD_MFRID_DEVID); // send command 0x90
  169. uint8_t cnt = 3; // 3 address bytes
  170. while (cnt--) // send address bytes
  171. _SPI_TX(0x00);
  172. uint8_t xflash_mfrid = _SPI_RX(); // receive mfrid
  173. uint8_t xflash_devid = _SPI_RX(); // receive devid
  174. _CS_HIGH();
  175. return
  176. ((xflash_mfrid == _MFRID_W25X20CL) && (xflash_devid == _DEVID_W25X20CL)) ||
  177. ((xflash_mfrid == _MFRID_GD25Q20C) && (xflash_devid == _DEVID_GD25Q20C));
  178. }
  179. void xflash_wait_busy(void)
  180. {
  181. while (xflash_rd_status_reg() & XFLASH_STATUS_BUSY) ;
  182. }
  183. #endif //XFLASH