sd_sample.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-09-25 misonyo first edition.
  9. */
  10. /*
  11. * 程序清单:这是一个SD卡设备的使用例程
  12. * 例程导出了 sd_sample 命令到控制终端
  13. * 命令调用格式:sd_sample sd0
  14. * 命令解释:命令第二个参数是要使用的SD设备的名称,为空则使用例程默认的SD设备。
  15. * 程序功能:程序会产生一个块大小的随机数,然后写入SD卡中,然后在读取这部分写入的数据。
  16. * 对比写入和读出的数据是否一致,一致则表示程序运行正确。
  17. */
  18. #include <rtthread.h>
  19. #include <rtdevice.h>
  20. #include <stdlib.h>
  21. #define SD_DEVICE_NAME "sd0"
  22. void fill_buffer(rt_uint8_t *buff, rt_uint32_t buff_length)
  23. {
  24. rt_uint32_t index;
  25. /* 往缓冲区填充随机数 */
  26. for (index = 0; index < buff_length; index++)
  27. {
  28. buff[index] = ((rt_uint8_t)rand()) & 0xff;
  29. }
  30. }
  31. static int sd_sample(int argc, char *argv[])
  32. {
  33. rt_err_t ret;
  34. rt_device_t sd_device;
  35. char sd_name[RT_NAME_MAX];
  36. rt_uint8_t *write_buff, *read_buff;
  37. struct rt_device_blk_geometry geo;
  38. rt_uint8_t block_num;
  39. /* 判断命令行参数是否给定了设备名称 */
  40. if (argc == 2)
  41. {
  42. rt_strncpy(sd_name, argv[1], RT_NAME_MAX);
  43. }
  44. else
  45. {
  46. rt_strncpy(sd_name, SD_DEVICE_NAME, RT_NAME_MAX);
  47. }
  48. /* 查找设备获取设备句柄 */
  49. sd_device = rt_device_find(sd_name);
  50. if (sd_device == RT_NULL)
  51. {
  52. rt_kprintf("find device %s failed!\n", sd_name);
  53. return RT_ERROR;
  54. }
  55. /* 打开设备 */
  56. ret = rt_device_open(sd_device, RT_DEVICE_OFLAG_RDWR);
  57. if (ret != RT_EOK)
  58. {
  59. rt_kprintf("open device %s failed!\n", sd_name);
  60. return ret;
  61. }
  62. rt_memset(&geo, 0, sizeof(geo));
  63. /* 获取块设备信息 */
  64. ret = rt_device_control(sd_device, RT_DEVICE_CTRL_BLK_GETGEOME, &geo);
  65. if (ret != RT_EOK)
  66. {
  67. rt_kprintf("control device %s failed!\n", sd_name);
  68. return ret;
  69. }
  70. rt_kprintf("device information:\n");
  71. rt_kprintf("sector size : %d byte\n", geo.bytes_per_sector);
  72. rt_kprintf("sector count : %d \n", geo.sector_count);
  73. rt_kprintf("block size : %d byte\n", geo.block_size);
  74. /* 准备读写缓冲区空间,大小为一个块 */
  75. read_buff = rt_malloc(geo.block_size);
  76. if (read_buff == RT_NULL)
  77. {
  78. rt_kprintf("no memory for read buffer!\n");
  79. return RT_ERROR;
  80. }
  81. write_buff = rt_malloc(geo.block_size);
  82. if (write_buff == RT_NULL)
  83. {
  84. rt_kprintf("no memory for write buffer!\n");
  85. rt_free(read_buff);
  86. return RT_ERROR;
  87. }
  88. /* 填充写数据缓冲区,为写操作做准备 */
  89. fill_buffer(write_buff, geo.block_size);
  90. /* 把写数据缓冲的数据写入SD卡中,大小为一个块,size参数以块为单位 */
  91. block_num = rt_device_write(sd_device, 0, write_buff, 1);
  92. if (1 != block_num)
  93. {
  94. rt_kprintf("write device %s failed!\n", sd_name);
  95. }
  96. /* 从SD卡中读出数据,并保存在读数据缓冲区中 */
  97. block_num = rt_device_read(sd_device, 0, read_buff, 1);
  98. if (1 != block_num)
  99. {
  100. rt_kprintf("read %s device failed!\n", sd_name);
  101. }
  102. /* 比较写数据缓冲区和读数据缓冲区的内容是否完全一致 */
  103. if (rt_memcmp(write_buff, read_buff, geo.block_size) == 0)
  104. {
  105. rt_kprintf("Block test OK!\n");
  106. }
  107. else
  108. {
  109. rt_kprintf("Block test Fail!\n");
  110. }
  111. /* 释放缓冲区空间 */
  112. rt_free(read_buff);
  113. rt_free(write_buff);
  114. ret = rt_device_close(sd_device);
  115. if(ret != RT_EOK)
  116. {
  117. rt_kprintf("close device %s failed!\n", sd_name);
  118. return ret;
  119. }
  120. else
  121. {
  122. rt_kprintf("close device %s ok!\n", sd_name);
  123. }
  124. return RT_EOK;
  125. }
  126. /* 导出到 msh 命令列表中 */
  127. MSH_CMD_EXPORT(sd_sample, sd device sample);