CS创世SD NAND的存储芯片应用方案

描述

前言:

 很感谢深圳雷龙发展有限公司为博主提供的两片SD NAND的存储芯片,在这里博主记录一下自己的使用过程以及部分设计。

 深入了解该产品:

 拿到这个产品之后,我大致了解了下两款芯片的性能。CSNP4GCR01-AMW是一种基于NAND闪存和SD控制器的4Gb密度嵌入式存储;而CSNP32GCR01-AOW是一种基于NAND闪存和SD控制器的32Gb密度嵌入式存储。与原始NAND相比其具有嵌入式坏块管理和更强的嵌入式ECC。即使在异常断电,它仍然可以安全地保存数据。作为一个存储芯片,它确实做到了小巧,LGA-8的封装对比我之前用到过的TF卡,只占到了其面积的三分之一,这样对于一些嵌入式的设计就方便了很多。

内存卡

 

 

 雷龙官方还很贴心的提供了样品的测试板,在这款测试板上,我焊接了4GB的CSNP4GCR01-AMW上去,并且跑了一下分,对于一款小的存储芯片而言,实在难得。

内存卡

 

 (上图为测试板焊接图)

 博主日前在设计基于H616与NB-IOT的嵌入式智能储物柜的时候考虑过存储方面的问题,当时在SD NAND和EMMC与TF卡中徘徊,以下是几个存储类型的对比。

内存卡

 

 

内存卡

 

 

 经过多方对比,本着不需要频繁更换的原则,同时也为了更好的防水和成本考虑,最终决定使用雷龙公司的SD NAND 作为设计样品的存储部分。

 此外,SD NAND还具有不用写驱动程序自带坏块管理的NAND FLASH(贴片式TF卡),不标准的SDIO接口,也同时兼容SPI/SD接口,10万次的SLC晶圆擦写寿命,通过一万次的随机掉电测试耐高低温,经过跑分测得,速度级别Class10。标准的SD2.0协议,普通的SD卡可以直接驱动,支持TF卡启动的SOC都可以用SD NAND,而且雷龙官方还贴心的提供了STM32参考例程和原厂技术支持,这对于刚上手的小白而言,十分友好。

 设计理念:

 使用H616作为主控CPU并搭配NB-IOT来向申请下来的云端传输数据,当WIFI正常时,储物数据每搁两小时向云端传输一次,当有人取出物品时再次向云端发送一次数据(不保留在SD NAND中);一旦系统检测到WIFI出现问题,储物数据转而存储到SD NAND中,取物时输入的物品ID和取出时间一并放入SD NAND中(我也是看中了SD NAND与原始NAND相比其具有嵌入式坏块管理和更强的嵌入式ECC。即使在异常断电,它仍然可以安全地保存数据这一点)。

 部分SD NAND的参考设计

 根据官方数据手册提供的SD NAND参考设计,只占用8个GPIO,对于H616来说,确实很友好

内存卡

 

 

 这里为了不泄露他人的劳动成果,我也就不粘PCB设计了。

内存卡

 

 

 采用H616驱动SD NAND的示例代码

 下面是关于H616驱动SD NAND的示例代码,这里记录一下自己当初的学习过程(注:这个代码不能直接拿过来就用,而是要根据自己的需求修改)

  1. #include
  2. #include
  3. #include
  4. #include
  5. #include "h616_sdio.h"
  6.  
  7. // 定义SDIO引脚
  8. #define SDIO_CMD_PIN 0
  9. #define SDIO_CLK_PIN 1
  10. #define SDIO_D0_PIN 2
  11. #define SDIO_D1_PIN 3
  12. #define SDIO_D2_PIN 4
  13. #define SDIO_D3_PIN 5
  14.  
  15. // 定义NAND芯片命令
  16. #define CMD_READ 0x00
  17. #define CMD_WRITE 0x80
  18. #define CMD_ERASE 0x60
  19. #define CMD_STATUS 0x70
  20. #define CMD_RESET 0xff
  21.  
  22. // 定义NAND芯片状态
  23. #define STATUS_READY 0x40
  24. #define STATUS_ERROR 0x01
  25.  
  26. // 初始化SDIO控制器
  27. void sdio_init()
  28. {
  29. // 设置SDIO引脚模式和速率
  30. h616_sdio_set_pin_mode(SDIO_CMD_PIN, H616_SDIO_PIN_MODE_SDIO);
  31. h616_sdio_set_pin_mode(SDIO_CLK_PIN, H616_SDIO_PIN_MODE_SDIO);
  32. h616_sdio_set_pin_mode(SDIO_D0_PIN, H616_SDIO_PIN_MODE_SDIO);
  33. h616_sdio_set_pin_mode(SDIO_D1_PIN, H616_SDIO_PIN_MODE_SDIO);
  34. h616_sdio_set_pin_mode(SDIO_D2_PIN, H616_SDIO_PIN_MODE_SDIO);
  35. h616_sdio_set_pin_mode(SDIO_D3_PIN, H616_SDIO_PIN_MODE_SDIO);
  36. h616_sdio_set_clock(H616_SDIO_CLOCK_FREQ_25MHZ);
  37.  
  38. // 初始化SDIO控制器
  39. h616_sdio_init();
  40. }
  41.  
  42. // 发送NAND芯片命令
  43. void nand_send_cmd(uint8_t cmd)
  44. {
  45. // 设置SDIO控制器传输模式和命令码
  46. h616_sdio_set_transfer_mode(H616_SDIO_TRANSFER_MODE_WRITE);
  47. h616_sdio_set_command_code(cmd);
  48.  
  49. // 发送命令
  50. h616_sdio_send_command();
  51. }
  52.  
  53. // 发送NAND芯片地址
  54. void nand_send_addr(uint32_t addr)
  55. {
  56. // 设置SDIO控制器传输模式和地址
  57. h616_sdio_set_transfer_mode(H616_SDIO_TRANSFER_MODE_WRITE);
  58. h616_sdio_set_address(addr);
  59.  
  60. // 发送地址
  61. h616_sdio_send_address();
  62. }
  63.  
  64. // 读取NAND芯片数据
  65. void nand_read_data(uint8_t *data, uint32_t size)
  66. {
  67. // 设置SDIO控制器传输模式
  68. h616_sdio_set_transfer_mode(H616_SDIO_TRANSFER_MODE_READ);
  69.  
  70. // 读取数据
  71. h616_sdio_read_data(data, size);
  72. }
  73.  
  74. // 写入NAND芯片数据
  75. void nand_write_data(const uint8_t *data, uint32_t size)
  76. {
  77. // 设置SDIO控制器传输模式
  78. h616_sdio_set_transfer_mode(H616_SDIO_TRANSFER_MODE_WRITE);
  79.  
  80. // 写入数据
  81. h616_sdio_write_data(data, size);
  82. }
  83.  
  84. // 读取NAND芯片状态
  85. uint8_t nand_read_status()
  86. {
  87. uint8_t status;
  88.  
  89. // 发送读取状态命令
  90. nand_send_cmd(CMD_STATUS);
  91.  
  92. // 读取状态
  93. nand_read_data(&status, 1);
  94.  
  95. return status;
  96. }
  97.  
  98. // 等待NAND芯片准备就绪
  99. void nand_wait_ready()
  100. {
  101. uint8_t status;
  102.  
  103. // 循环读取状态,直到NAND芯片准备就绪
  104. do {
  105. status = nand_read_status();
  106. } while ((status & STATUS_READY) == 0);
  107. }
  108.  
  109. // 读取NAND芯片数据
  110. void nand_read(uint32_t page, uint32_t column, uint8_t *data, uint32_t size)
  111. {
  112. // 发送读取命令和地址
  113. nand_send_cmd(CMD_READ);
  114. nand_send_addr(column | (page << 8));
  115.  
  116. // 等待NAND芯片准备就绪
  117. nand_wait_ready();
  118.  
  119. // 读取数据
  120. nand_read_data(data, size);
  121. }
  122.  
  123. // 写入NAND芯片数据
  124. void nand_write(uint32_t page, uint32_t column, const uint8_t *data, uint32_t size)
  125. {
  126. // 发送写入命令和地址
  127. nand_send_cmd(CMD_WRITE);
  128. nand_send_addr(column | (page << 8));
  129.  
  130. // 写入数据
  131. nand_write_data(data, size);
  132.  
  133. // 等待NAND芯片准备就绪
  134. nand_wait_ready();
  135. }
  136.  
  137. // 擦除NAND芯片块
  138. void nand_erase(uint32_t block)
  139. {
  140. // 发送擦除命令和地址
  141. nand_send_cmd(CMD_ERASE);
  142. nand_send_addr(block << 8);
  143.  
  144. // 等待NAND芯片准备就绪
  145. nand_wait_ready();
  146. }
  147.  
  148. // 复位NAND芯片
  149. void nand_reset()
  150. {
  151. // 发送复位命令
  152. nand_send_cmd(CMD_RESET);
  153.  
  154. // 等待NAND芯片准备就绪
  155. nand_wait_ready();
  156. }
  157.  
  158. // 示例程序入口
  159. int main()
  160. {
  161. uint8_t data[2048];
  162. memset(data, 0x5a, sizeof(data));
  163.  
  164. // 初始化SDIO控制器
  165. sdio_init();
  166.  
  167. // 复位NAND芯片
  168. nand_reset();
  169.  
  170. // 擦除第0块
  171. nand_erase(0);
  172.  
  173. // 写入第0页
  174. nand_write(0, 0, data, sizeof(data));
  175.  
  176. // 读取第0页
  177. nand_read(0, 0, data, sizeof(data));
  178.  
  179. return 0;
  180. }
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分