w25x20cl.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. //w25x20cl.c
  2. #include "w25x20cl.h"
  3. #include <avr/io.h>
  4. #include <avr/pgmspace.h>
  5. #include "io_atmega2560.h"
  6. #include "spi.h"
  7. #define _MFRID 0xEF
  8. #define _DEVID 0x11
  9. #define _CMD_ENABLE_WR 0x06
  10. #define _CMD_ENABLE_WR_VSR 0x50
  11. #define _CMD_DISABLE_WR 0x04
  12. #define _CMD_RD_STATUS_REG 0x05
  13. #define _CMD_WR_STATUS_REG 0x01
  14. #define _CMD_RD_DATA 0x03
  15. #define _CMD_RD_FAST 0x0b
  16. #define _CMD_RD_FAST_D_O 0x3b
  17. #define _CMD_RD_FAST_D_IO 0xbb
  18. #define _CMD_PAGE_PROGRAM 0x02
  19. #define _CMD_SECTOR_ERASE 0x20
  20. #define _CMD_BLOCK32_ERASE 0x52
  21. #define _CMD_BLOCK64_ERASE 0xd8
  22. #define _CMD_CHIP_ERASE 0xc7
  23. #define _CMD_CHIP_ERASE2 0x60
  24. #define _CMD_PWR_DOWN 0xb9
  25. #define _CMD_PWR_DOWN_REL 0xab
  26. #define _CMD_MFRID_DEVID 0x90
  27. #define _CMD_MFRID_DEVID_D 0x92
  28. #define _CMD_JEDEC_ID 0x9f
  29. #define _CMD_RD_UID 0x4b
  30. #define _CS_LOW() PORT(W25X20CL_PIN_CS) &= ~__MSK(W25X20CL_PIN_CS)
  31. #define _CS_HIGH() PORT(W25X20CL_PIN_CS) |= __MSK(W25X20CL_PIN_CS)
  32. //#define _SPI_TX swspi_tx
  33. //#define _SPI_RX swspi_rx
  34. #define _SPI_TX(b) spi_txrx(b)
  35. #define _SPI_RX() spi_txrx(0xff)
  36. int w25x20cl_mfrid_devid(void);
  37. int8_t w25x20cl_init(void)
  38. {
  39. PIN_OUT(W25X20CL_PIN_CS);
  40. _CS_HIGH();
  41. W25X20CL_SPI_ENTER();
  42. if (!w25x20cl_mfrid_devid()) return 0;
  43. return 1;
  44. }
  45. void w25x20cl_enable_wr(void)
  46. {
  47. _CS_LOW();
  48. _SPI_TX(_CMD_ENABLE_WR); // send command 0x06
  49. _CS_HIGH();
  50. }
  51. void w25x20cl_disable_wr(void)
  52. {
  53. _CS_LOW();
  54. _SPI_TX(_CMD_DISABLE_WR); // send command 0x04
  55. _CS_HIGH();
  56. }
  57. uint8_t w25x20cl_rd_status_reg(void)
  58. {
  59. _CS_LOW();
  60. _SPI_TX(_CMD_RD_STATUS_REG); // send command 0x90
  61. uint8_t val = _SPI_RX(); // receive value
  62. _CS_HIGH();
  63. return val;
  64. }
  65. void w25x20cl_wr_status_reg(uint8_t val)
  66. {
  67. _CS_LOW();
  68. _SPI_TX(_CMD_WR_STATUS_REG); // send command 0x90
  69. _SPI_TX(val); // send value
  70. _CS_HIGH();
  71. }
  72. void w25x20cl_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt)
  73. {
  74. _CS_LOW();
  75. _SPI_TX(_CMD_RD_DATA); // send command 0x03
  76. _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
  77. _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
  78. _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
  79. while (cnt--) // receive data
  80. *(data++) = _SPI_RX();
  81. _CS_HIGH();
  82. }
  83. void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt)
  84. {
  85. _CS_LOW();
  86. _SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02
  87. _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
  88. _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
  89. _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
  90. while (cnt--) // send data
  91. _SPI_TX(*(data++));
  92. _CS_HIGH();
  93. }
  94. void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt)
  95. {
  96. _CS_LOW();
  97. _SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02
  98. _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
  99. _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
  100. _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
  101. while (cnt--) // send data
  102. _SPI_TX(pgm_read_byte(data++));
  103. _CS_HIGH();
  104. }
  105. void w25x20cl_erase(uint8_t cmd, uint32_t addr)
  106. {
  107. _CS_LOW();
  108. _SPI_TX(cmd); // send command 0x20
  109. _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
  110. _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
  111. _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
  112. _CS_HIGH();
  113. }
  114. void w25x20cl_sector_erase(uint32_t addr)
  115. {
  116. return w25x20cl_erase(_CMD_SECTOR_ERASE, addr);
  117. }
  118. void w25x20cl_block32_erase(uint32_t addr)
  119. {
  120. return w25x20cl_erase(_CMD_BLOCK32_ERASE, addr);
  121. }
  122. void w25x20cl_block64_erase(uint32_t addr)
  123. {
  124. return w25x20cl_erase(_CMD_BLOCK64_ERASE, addr);
  125. }
  126. void w25x20cl_chip_erase(void)
  127. {
  128. _CS_LOW();
  129. _SPI_TX(_CMD_CHIP_ERASE); // send command 0xc7
  130. _CS_HIGH();
  131. }
  132. void w25x20cl_rd_uid(uint8_t* uid)
  133. {
  134. _CS_LOW();
  135. _SPI_TX(_CMD_RD_UID); // send command 0x4b
  136. uint8_t cnt = 4; // 4 dummy bytes
  137. while (cnt--) // receive dummy bytes
  138. _SPI_RX();
  139. cnt = 8; // 8 bytes UID
  140. while (cnt--) // receive UID
  141. uid[7 - cnt] = _SPI_RX();
  142. _CS_HIGH();
  143. }
  144. int w25x20cl_mfrid_devid(void)
  145. {
  146. _CS_LOW();
  147. _SPI_TX(_CMD_MFRID_DEVID); // send command 0x90
  148. uint8_t cnt = 3; // 3 address bytes
  149. while (cnt--) // send address bytes
  150. _SPI_TX(0x00);
  151. uint8_t w25x20cl_mfrid = _SPI_RX(); // receive mfrid
  152. uint8_t w25x20cl_devid = _SPI_RX(); // receive devid
  153. _CS_HIGH();
  154. return ((w25x20cl_mfrid == _MFRID) && (w25x20cl_devid == _DEVID));
  155. }
  156. void w25x20cl_wait_busy(void)
  157. {
  158. while (w25x20cl_rd_status_reg() & W25X20CL_STATUS_BUSY) ;
  159. }