luat_sfd_w25q.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #include "luat_base.h"
  2. #include "luat_spi.h"
  3. #include "luat_gpio.h"
  4. #include "luat_sfd.h"
  5. #define LUAT_LOG_TAG "sfd"
  6. #include "luat_log.h"
  7. #define CS_H(pin) luat_gpio_set(pin, 1)
  8. #define CS_L(pin) luat_gpio_set(pin, 0)
  9. // 针对drv的实现
  10. static int sfd_w25q_init (void* userdata);
  11. static int sfd_w25q_status (void* userdata);
  12. static int sfd_w25q_read (void* userdata, char* buff, size_t offset, size_t len);
  13. static int sfd_w25q_write (void* userdata, const char* buff, size_t offset, size_t len);
  14. static int sfd_w25q_erase (void* userdata, size_t offset, size_t len);
  15. static int sfd_w25q_ioctl (void* userdata, size_t cmd, void* buff);
  16. const sdf_opts_t sfd_w25q_opts = {
  17. .initialize = sfd_w25q_init,
  18. .status = sfd_w25q_status,
  19. .read = sfd_w25q_read,
  20. .write = sfd_w25q_write,
  21. .erase = sfd_w25q_erase,
  22. .ioctl = sfd_w25q_ioctl,
  23. };
  24. static int sfd_w25q_init (void* userdata) {
  25. sfd_drv_t *drv = (sfd_drv_t *)userdata;
  26. uint8_t cmd = 0x9F;
  27. // 发送CMD 9F, 读取容量信息
  28. luat_gpio_set(drv->cfg.spi.cs, 0);
  29. luat_spi_send(drv->cfg.spi.id, (const char*)&cmd, 1);
  30. char buff[3] = {0};
  31. luat_spi_recv(drv->cfg.spi.id, buff, 3);
  32. luat_gpio_set(drv->cfg.spi.cs, 1);
  33. if (buff[0] != 0xEF) {
  34. LLOGW("can't read spi flash: cmd 9F");
  35. return -1;
  36. }
  37. LLOGD("spi flash %02X %02X %02X", buff[0], buff[1], buff[2]);
  38. if (buff[1] == 0x40) {
  39. switch(buff[2]) {
  40. case 0x13:
  41. drv->sector_count = 8*256;// drv80, 8M
  42. break;
  43. case 0x14:
  44. drv->sector_count = 16*256;// drv16, 16M
  45. break;
  46. case 0x15:
  47. drv->sector_count = 32*256;// drv32, 32M
  48. break;
  49. case 0x16:
  50. drv->sector_count = 64*256;// drv64, 64M
  51. break;
  52. case 0x17:
  53. drv->sector_count = 128*256;// drv128, 128M
  54. break;
  55. case 0x18:
  56. drv->sector_count = 256*256;// drv256, 256M
  57. break;
  58. case 0x19:
  59. drv->sector_count = 512*256;// drv512, 512M
  60. break;
  61. default :
  62. drv->sector_count = 16*256;// 默认当16M吧
  63. break;
  64. }
  65. }
  66. else {
  67. drv->sector_count = 16*256;// 默认当16M吧
  68. }
  69. //drv->flash_id[0] = buff[1];
  70. //drv->flash_id[1] = buff[2];
  71. // 读设备唯一id
  72. luat_gpio_set(drv->cfg.spi.cs, 0);
  73. char chip_id_cmd[] = {0x4B, 0x00, 0x00, 0x00, 0x00};
  74. luat_spi_send(drv->cfg.spi.id, chip_id_cmd, sizeof(chip_id_cmd));
  75. luat_spi_recv(drv->cfg.spi.id, drv->chip_id, 8);
  76. luat_gpio_set(drv->cfg.spi.cs, 1);
  77. return 0;
  78. }
  79. static int sfd_w25q_status (void* userdata) {
  80. sfd_drv_t *drv = (sfd_drv_t *)userdata;
  81. return drv->sector_count == 0 ? 0 : 1; // TODO 根据BUSY 状态返回
  82. }
  83. static int sfd_w25q_read (void* userdata, char* buff, size_t offset, size_t len) {
  84. sfd_drv_t *drv = (sfd_drv_t *)userdata;
  85. char cmd[4] = {0x03, offset >> 16, (offset >> 8) & 0xFF, offset & 0xFF};
  86. luat_gpio_set(drv->cfg.spi.cs, 0);
  87. luat_spi_send(drv->cfg.spi.id, (const char*)&cmd, sizeof(cmd));
  88. luat_spi_recv(drv->cfg.spi.id, buff, len);
  89. luat_gpio_set(drv->cfg.spi.cs, 1);
  90. return 0;
  91. }
  92. void sfd_w25q_write_enable(sfd_drv_t *drv) {
  93. luat_gpio_set(drv->cfg.spi.cs, 0);
  94. uint8_t cmd = 0x06;
  95. luat_spi_send(drv->cfg.spi.id, (const char*)&cmd, sizeof(cmd));
  96. luat_gpio_set(drv->cfg.spi.cs, 1);
  97. }
  98. static int sfd_w25q_write (void* userdata, const char* buff, size_t offset, size_t len) {
  99. sfd_drv_t *drv = (sfd_drv_t *)userdata;
  100. sfd_w25q_write_enable(drv);
  101. char cmd[4] = {0x02, offset >> 16, (offset >> 8) & 0xFF, offset & 0xFF};
  102. luat_gpio_set(drv->cfg.spi.cs, 0);
  103. luat_spi_send(drv->cfg.spi.id, (const char*)&cmd, sizeof(cmd));
  104. luat_spi_send(drv->cfg.spi.id, buff, len);
  105. luat_gpio_set(drv->cfg.spi.cs, 1);
  106. return 0;
  107. }
  108. static int sfd_w25q_erase (void* userdata, size_t offset, size_t len) {
  109. sfd_drv_t *drv = (sfd_drv_t *)userdata;
  110. sfd_w25q_write_enable(drv);
  111. char cmd[4] = {0x20, offset >> 16, (offset >> 8) & 0xFF, offset & 0xFF};
  112. luat_gpio_set(drv->cfg.spi.cs, 0);
  113. luat_spi_send(drv->cfg.spi.id, (const char*)&cmd, sizeof(cmd));
  114. luat_gpio_set(drv->cfg.spi.cs, 1);
  115. return 0;
  116. }
  117. static int sfd_w25q_ioctl (void* userdata, size_t cmd, void* buff) {
  118. return -1;
  119. }