w25x20cl.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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_ini(void)
  38. {
  39. PIN_OUT(W25X20CL_PIN_CS);
  40. _CS_HIGH();
  41. if (!w25x20cl_mfrid_devid()) return 0;
  42. return 1;
  43. }
  44. void w25x20cl_enable_wr(void)
  45. {
  46. _CS_LOW();
  47. _SPI_TX(_CMD_ENABLE_WR); // send command 0x06
  48. _CS_HIGH();
  49. }
  50. void w25x20cl_disable_wr(void)
  51. {
  52. _CS_LOW();
  53. _SPI_TX(_CMD_DISABLE_WR); // send command 0x04
  54. _CS_HIGH();
  55. }
  56. uint8_t w25x20cl_rd_status_reg(void)
  57. {
  58. _CS_LOW();
  59. _SPI_TX(_CMD_RD_STATUS_REG); // send command 0x90
  60. uint8_t val = _SPI_RX(); // receive value
  61. _CS_HIGH();
  62. return val;
  63. }
  64. void w25x20cl_wr_status_reg(uint8_t val)
  65. {
  66. _CS_LOW();
  67. _SPI_TX(_CMD_WR_STATUS_REG); // send command 0x90
  68. _SPI_TX(val); // send value
  69. _CS_HIGH();
  70. }
  71. void w25x20cl_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt)
  72. {
  73. _CS_LOW();
  74. _SPI_TX(_CMD_RD_DATA); // send command 0x03
  75. _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
  76. _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
  77. _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
  78. while (cnt--) // receive data
  79. *(data++) = _SPI_RX();
  80. _CS_HIGH();
  81. }
  82. void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt)
  83. {
  84. _CS_LOW();
  85. _SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02
  86. _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
  87. _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
  88. _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
  89. while (cnt--) // send data
  90. _SPI_TX(*(data++));
  91. _CS_HIGH();
  92. }
  93. void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt)
  94. {
  95. _CS_LOW();
  96. _SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02
  97. _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
  98. _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
  99. _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
  100. while (cnt--) // send data
  101. _SPI_TX(pgm_read_byte(data++));
  102. _CS_HIGH();
  103. }
  104. void w25x20cl_erase(uint8_t cmd, uint32_t addr)
  105. {
  106. _CS_LOW();
  107. _SPI_TX(_CMD_SECTOR_ERASE); // send command 0x20
  108. _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
  109. _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
  110. _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
  111. _CS_HIGH();
  112. }
  113. void w25x20cl_sector_erase(uint32_t addr)
  114. {
  115. return w25x20cl_erase(_CMD_SECTOR_ERASE, addr);
  116. }
  117. void w25x20cl_block32_erase(uint32_t addr)
  118. {
  119. return w25x20cl_erase(_CMD_BLOCK32_ERASE, addr);
  120. }
  121. void w25x20cl_block64_erase(uint32_t addr)
  122. {
  123. return w25x20cl_erase(_CMD_BLOCK64_ERASE, addr);
  124. }
  125. void w25x20cl_chip_erase(void)
  126. {
  127. _CS_LOW();
  128. _SPI_TX(_CMD_CHIP_ERASE); // send command 0xc7
  129. _CS_HIGH();
  130. }
  131. void w25x20cl_rd_uid(uint8_t* uid)
  132. {
  133. _CS_LOW();
  134. _SPI_TX(_CMD_RD_UID); // send command 0x4b
  135. uint8_t cnt = 4; // 4 dummy bytes
  136. while (cnt--) // receive dummy bytes
  137. _SPI_RX();
  138. cnt = 8; // 8 bytes UID
  139. while (cnt--) // receive UID
  140. uid[7 - cnt] = _SPI_RX();
  141. _CS_HIGH();
  142. }
  143. int w25x20cl_mfrid_devid(void)
  144. {
  145. _CS_LOW();
  146. _SPI_TX(_CMD_MFRID_DEVID); // send command 0x90
  147. uint8_t cnt = 3; // 3 address bytes
  148. while (cnt--) // send address bytes
  149. _SPI_TX(0x00);
  150. uint8_t w25x20cl_mfrid = _SPI_RX(); // receive mfrid
  151. uint8_t w25x20cl_devid = _SPI_RX(); // receive devid
  152. _CS_HIGH();
  153. return ((w25x20cl_mfrid == _MFRID) && (w25x20cl_devid == _DEVID));
  154. }