294|0

250

帖子

0

TA的资源

纯净的硅(初级)

楼主
 

[兆易GD32H759I-EVAL]5.熟悉SDIO接口通讯,基于FatFs文件系统实现对TF卡的读写操作 [复制链接]

 

1.SDIO

    GD32H759系列MCU带有2路SDIO接口,它定义了SD卡、 SD I/O卡和嵌入式多媒体卡(e•MMC)主机接口,提供AHB系统总线与SD存储卡、 SD I/O卡以及e•MMC设备之间的命令和数据传输。需要注意的是SDIO在同一时间仅支持一个SD、SD I/O卡或 e•MMC,但可支持多个e•MMC。

 

2.原理图

    在运行SDIO功能程序时,需要根据原理图上的标注,将硬件上必要的跳线帽跳到正确的位置。

 

3.基于SD卡底层的读写操作和验证

3.1.代码实现

  • /* initialize the card */
  • do
  • {
  • sd_error = sd_io_init();
  • }
  • while ((SD_OK != sd_error) && (--i));
  • if (i)
  • {
  • printf("\r\nCard init success!\r\n");
  • }
  • else
  • {
  • printf("\r\nCard init failed!\r\n");
  • /* turn on LED1, LED2 */
  • gd_eval_led_on(LED1);
  • gd_eval_led_on(LED2);
  • while (1)
  • {
  • }
  • }
  • /* get the information of the card and print it out by USART */
  • card_info_get();
  • /* init the write buffer */
  • for (i = 0; i < 512; i++)
  • {
  • buf_write[i] = i;
  • }
  • /* clean and invalidate buffer in D-Cache */
  • SCB_CleanInvalidateDCache_by_Addr(buf_write, 512 * 4);
  • printf("\r\n\r\nCard test:");
  • /* single block operation test */
  • sd_error = sd_block_write(buf_write, 100, 512);
  • if (SD_OK != sd_error)
  • {
  • printf("\r\nBlock write fail!");
  • /* turn on LED1, LED2 */
  • gd_eval_led_on(LED1);
  • gd_eval_led_on(LED2);
  • while (1)
  • {
  • }
  • }
  • else
  • {
  • printf("\r\nBlock write success!");
  • }
  • sd_error = sd_block_read(buf_read, 100, 512);
  • if (SD_OK != sd_error)
  • {
  • printf("\r\nBlock read fail!");
  • /* turn on LED1, LED2 */
  • gd_eval_led_on(LED1);
  • gd_eval_led_on(LED2);
  • while (1)
  • {
  • }
  • }
  • else
  • {
  • printf("\r\nBlock read success!");
  • #ifdef DATA_PRINT
  • SCB_CleanInvalidateDCache_by_Addr(buf_read, 512 * 4);
  • pdata = (uint8_t *)buf_read;
  • /* print data by USART */
  • printf("\r\n");
  • for (i = 0; i < 128; i++)
  • {
  • printf(" %3d %3d %3d %3d ", *pdata, *(pdata + 1), *(pdata + 2), *(pdata + 3));
  • pdata += 4;
  • if (0 == (i + 1) % 4)
  • {
  • printf("\r\n");
  • }
  • }
  • #endif /* DATA_PRINT */
  • }
  • /* compare the write date and the read data */
  • state = memory_compare(buf_write, buf_read, 128);
  • if (SUCCESS == state)
  • {
  • printf("\r\nSingle block read compare successfully!");
  • }
  • else
  • {
  • printf("\r\nSingle block read compare fail!");
  • /* turn on LED1, LED2 */
  • gd_eval_led_on(LED1);
  • gd_eval_led_on(LED2);
  • while (1)
  • {
  • }
  • }
  • /* lock and unlock operation test */
  • if (SD_CCC_LOCK_CARD & sd_cardinfo.card_csd.ccc)
  • {
  • /* lock the card */
  • sd_error = sd_lock_unlock(SD_LOCK);
  • if (SD_OK != sd_error)
  • {
  • printf("\r\nLock failed!");
  • /* turn on LED1, LED2 */
  • gd_eval_led_on(LED1);
  • gd_eval_led_on(LED2);
  • while (1)
  • {
  • }
  • }
  • else
  • {
  • printf("\r\nThe card is locked!");
  • }
  • sd_error = sd_erase(100, 101);
  • if (SD_OK != sd_error)
  • {
  • printf("\r\nErase failed!");
  • }
  • else
  • {
  • printf("\r\nErase success!");
  • }
  • /* unlock the card */
  • sd_error = sd_lock_unlock(SD_UNLOCK);
  • if (SD_OK != sd_error)
  • {
  • printf("\r\nUnlock failed!");
  • /* turn on LED1, LED2 */
  • gd_eval_led_on(LED1);
  • gd_eval_led_on(LED2);
  • while (1)
  • {
  • }
  • }
  • else
  • {
  • printf("\r\nThe card is unlocked!");
  • }
  • sd_error = sd_erase(100, 101);
  • if (SD_OK != sd_error)
  • {
  • printf("\r\nErase failed!");
  • }
  • else
  • {
  • printf("\r\nErase success!");
  • }
  • sd_error = sd_block_read(buf_read, 100, 512);
  • if (SD_OK != sd_error)
  • {
  • printf("\r\nBlock read fail!");
  • /* turn on LED1, LED2 */
  • gd_eval_led_on(LED1);
  • gd_eval_led_on(LED2);
  • while (1)
  • {
  • }
  • }
  • else
  • {
  • printf("\r\nBlock read success!");
  • #ifdef DATA_PRINT
  • SCB_CleanInvalidateDCache_by_Addr(buf_read, 512 * 4);
  • pdata = (uint8_t *)buf_read;
  • /* print data by USART */
  • printf("\r\n");
  • for (i = 0; i < 128; i++)
  • {
  • printf(" %3d %3d %3d %3d ", *pdata, *(pdata + 1), *(pdata + 2), *(pdata + 3));
  • pdata += 4;
  • if (0 == (i + 1) % 4)
  • {
  • printf("\r\n");
  • }
  • }
  • #endif /* DATA_PRINT */
  • }
  • }
  • /* multiple blocks operation test */
  • sd_error = sd_multiblocks_write(buf_write, 200, 512, 3);
  • if (SD_OK != sd_error)
  • {
  • printf("\r\nMultiple block write fail!");
  • /* turn on LED1, LED2 */
  • gd_eval_led_on(LED1);
  • gd_eval_led_on(LED2);
  • while (1)
  • {
  • }
  • }
  • else
  • {
  • printf("\r\nMultiple block write success!");
  • }
  • sd_error = sd_multiblocks_read(buf_read, 200, 512, 3);
  • if (SD_OK != sd_error)
  • {
  • printf("\r\nMultiple block read fail!");
  • /* turn on LED1, LED2 */
  • gd_eval_led_on(LED1);
  • gd_eval_led_on(LED2);
  • while (1)
  • {
  • }
  • }
  • else
  • {
  • printf("\r\nMultiple block read success!");
  • #ifdef DATA_PRINT
  • SCB_CleanInvalidateDCache_by_Addr(buf_read, 512 * 4);
  • pdata = (uint8_t *)buf_read;
  • /* print data by USART */
  • printf("\r\n");
  • for (i = 0; i < 512; i++)
  • {
  • printf(" %3d %3d %3d %3d ", *pdata, *(pdata + 1), *(pdata + 2), *(pdata + 3));
  • pdata += 4;
  • if (0 == (i + 1) % 4)
  • {
  • printf("\r\n");
  • }
  • }
  • #endif /* DATA_PRINT */
  • }
  • /* compare the write date and the read data */
  • state = memory_compare(buf_write, buf_read, 128 * 3);
  • if (SUCCESS == state)
  • {
  • printf("\r\nMultiple block read compare successfully!");
  • }
  • else
  • {
  • printf("\r\nMultiple block read compare fail!");
  • /* turn on LED1, LED2 */
  • gd_eval_led_on(LED1);
  • gd_eval_led_on(LED2);
  • while (1)
  • {
  • }
  • }
  • printf("\r\nSD card test successfully!");

 

3.2.运行结果

 

4.移植FatFs文件系统及接口函数

  • /*-----------------------------------------------------------------------*/
  • /* Low level disk I/O module SKELETON for FatFs (C)ChaN, 2019 */
  • /*-----------------------------------------------------------------------*/
  • /* If a working storage control module is available, it should be */
  • /* attached to the FatFs via a glue function rather than modifying it. */
  • /* This is an example of glue functions to attach various exsisting */
  • /* storage control modules to the FatFs module with a defined API. */
  • /*-----------------------------------------------------------------------*/
  • #include "ff.h" /* Obtains integer types */
  • #include "diskio.h" /* Declarations of disk functions */
  • #include "sdcard.h"
  • #include <stdio.h>
  • /* Definitions of physical drive number for each drive */
  • #define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */
  • #define DEV_MMC 1 /* Example: Map MMC/SD card to physical drive 1 */
  • #define DEV_USB 2 /* Example: Map USB MSD to physical drive 2 */
  • extern sd_error_enum sd_io_init(void);
  • extern void card_info_get(void);
  • /*-----------------------------------------------------------------------*/
  • /* Get Drive Status */
  • /*-----------------------------------------------------------------------*/
  • DSTATUS disk_status (
  • BYTE pdrv /* Physical drive nmuber to identify the drive */
  • )
  • {
  • #if 0
  • DSTATUS stat;
  • int result;
  • switch (pdrv) {
  • case DEV_RAM :
  • result = RAM_disk_status();
  • // translate the reslut code here
  • return stat;
  • case DEV_MMC :
  • result = MMC_disk_status();
  • // translate the reslut code here
  • return stat;
  • case DEV_USB :
  • result = USB_disk_status();
  • // translate the reslut code here
  • return stat;
  • }
  • return STA_NOINIT;
  • #else
  • return RES_OK;
  • #endif
  • }
  • /*-----------------------------------------------------------------------*/
  • /* Inidialize a Drive */
  • /*-----------------------------------------------------------------------*/
  • DSTATUS disk_initialize (
  • BYTE pdrv /* Physical drive nmuber to identify the drive */
  • )
  • {
  • #if 0
  • DSTATUS stat;
  • int result;
  • switch (pdrv) {
  • case DEV_RAM :
  • result = RAM_disk_initialize();
  • // translate the reslut code here
  • return stat;
  • case DEV_MMC :
  • result = MMC_disk_initialize();
  • // translate the reslut code here
  • return stat;
  • case DEV_USB :
  • result = USB_disk_initialize();
  • // translate the reslut code here
  • return stat;
  • }
  • return STA_NOINIT;
  • #else
  • int result, count = 5;
  • do
  • {
  • result = sd_io_init();
  • count -= 1;
  • }
  • while (SD_OK != result);
  • if ((SD_OK == result) && (count != 0))
  • {
  • printf("\r\nCard init success!");
  • card_info_get(); printf("\r\n");
  • return RES_OK;
  • }
  • else
  • {
  • printf("\r\nCard init failed!");
  • while (1)
  • {
  • }
  • }
  • #endif
  • }
  • /*-----------------------------------------------------------------------*/
  • /* Read Sector(s) */
  • /*-----------------------------------------------------------------------*/
  • DRESULT disk_read (
  • BYTE pdrv, /* Physical drive nmuber to identify the drive */
  • BYTE *buff, /* Data buffer to store read data */
  • LBA_t sector, /* Start sector in LBA */
  • UINT count /* Number of sectors to read */
  • )
  • {
  • #if 0
  • DRESULT res;
  • int result;
  • switch (pdrv) {
  • case DEV_RAM :
  • // translate the arguments here
  • result = RAM_disk_read(buff, sector, count);
  • // translate the reslut code here
  • return res;
  • case DEV_MMC :
  • // translate the arguments here
  • result = MMC_disk_read(buff, sector, count);
  • // translate the reslut code here
  • return res;
  • case DEV_USB :
  • // translate the arguments here
  • result = USB_disk_read(buff, sector, count);
  • // translate the reslut code here
  • return res;
  • }
  • return RES_PARERR;
  • #else
  • int result;
  • if (count == 1)
  • {
  • result = sd_block_read((uint32_t *)buff, sector, 512);
  • }
  • else
  • {
  • result = sd_multiblocks_read((uint32_t *)buff, sector, 512, count);
  • }
  • if (result == SD_OK)
  • {
  • return RES_OK;
  • }
  • else
  • {
  • return RES_PARERR;
  • }
  • #endif
  • }
  • /*-----------------------------------------------------------------------*/
  • /* Write Sector(s) */
  • /*-----------------------------------------------------------------------*/
  • #if FF_FS_READONLY == 0
  • DRESULT disk_write (
  • BYTE pdrv, /* Physical drive nmuber to identify the drive */
  • const BYTE *buff, /* Data to be written */
  • LBA_t sector, /* Start sector in LBA */
  • UINT count /* Number of sectors to write */
  • )
  • {
  • #if 0
  • DRESULT res;
  • int result;
  • switch (pdrv) {
  • case DEV_RAM :
  • // translate the arguments here
  • result = RAM_disk_write(buff, sector, count);
  • // translate the reslut code here
  • return res;
  • case DEV_MMC :
  • // translate the arguments here
  • result = MMC_disk_write(buff, sector, count);
  • // translate the reslut code here
  • return res;
  • case DEV_USB :
  • // translate the arguments here
  • result = USB_disk_write(buff, sector, count);
  • // translate the reslut code here
  • return res;
  • }
  • return RES_PARERR;
  • #else
  • int result = sd_multiblocks_write((uint32_t *)buff, sector, 512, count);
  • if (result == SD_OK)
  • {
  • return RES_OK;
  • }
  • else
  • {
  • return RES_PARERR;
  • }
  • #endif
  • }
  • #endif
  • /*-----------------------------------------------------------------------*/
  • /* Miscellaneous Functions */
  • /*-----------------------------------------------------------------------*/
  • DRESULT disk_ioctl (
  • BYTE pdrv, /* Physical drive nmuber (0..) */
  • BYTE cmd, /* Control code */
  • void *buff /* Buffer to send/receive control data */
  • )
  • {
  • #if 0
  • DRESULT res;
  • int result;
  • switch (pdrv) {
  • case DEV_RAM :
  • // Process of the command for the RAM drive
  • return res;
  • case DEV_MMC :
  • // Process of the command for the MMC/SD card
  • return res;
  • case DEV_USB :
  • // Process of the command the USB drive
  • return res;
  • }
  • return RES_PARERR;
  • #else
  • switch (cmd)
  • {
  • case GET_SECTOR_COUNT:
  • *(DWORD *)buff = sd_card_capacity_get() / 512;
  • break;
  • case GET_SECTOR_SIZE:
  • *(WORD *)buff = 512;
  • break;
  • case GET_BLOCK_SIZE:
  • *(DWORD *)buff = 512;
  • break;
  • default:
  • break;
  • }
  • return RES_OK;
  • #endif
  • }
  • DWORD get_fattime(void)
  • {
  • return 0;
  • }

 

注意:diskio.c是实现FatFs文件系统与底层SDIO操作SD卡的接口文件,其中disk_read和disk_write这两个函数中的sector参数在调用sd卡底层函数时,传递的函数实参直接传递sector就可以了,不需要将sector再乘以blocksize;因为在sd卡底层操作函数中,对sd卡操作地址已经做了处理;如果这边再乘以blocksize,就会出现我在调试时遇到的挂载文件系统提示FR_NO_FILESYSTEM错误的情况。

 

5.FatFs功能演示

5.1.代码实现

  • #include "ff.h"
  • #include "diskio.h"
  • #include "ffconf.h"
  • #include <string.h>
  • FATFS FatFs;
  • FIL File;
  • UINT br = 0, bw = 0;
  • FRESULT Result;
  • char wBuffer[] = "\r\nGD32H7xx_SDIO_TFCard_FatFs";
  • char rBuffer[200];
  • memset(rBuffer, 0, sizeof(rBuffer));
  • Result = f_mount(&FatFs, "0:", 1);
  • if(Result)
  • {
  • printf("\r\nf_mount Fail! Result = %d\r\n", Result);
  • }
  • else
  • {
  • Result = f_open(&File, "0:/HELLO.txt", FA_READ);
  • if(Result != RES_OK)
  • {
  • printf("\r\nf_open HELLO.txt Fail! Result = %d\r\n", Result);
  • }
  • else
  • {
  • do
  • {
  • Result = f_read(&File, rBuffer, 200, &br);
  • if(br != 0) printf("\r\nf_read : %s\r\n", rBuffer);
  • } while(br != 0);
  • f_close(&File);
  • }
  • Result = f_open(&File, "0:/HELLO.txt", FA_CREATE_ALWAYS | FA_WRITE);
  • if (Result != RES_OK)
  • {
  • printf("\r\nf_open HELLO.txt Fail! Result = %d\r\n", Result);
  • }
  • else
  • {
  • Result = f_write(&File, wBuffer, strlen(wBuffer), &bw);
  • if (Result != RES_OK)
  • {
  • printf("\r\nf_write HELLO.txt Fail! Result = %d\r\n", Result);
  • }
  • else
  • {
  • printf("\r\nf_write HELLO.txt Result = %d, bw = %d\r\n", Result, bw);
  • f_sync(&File);
  • }
  • f_close(&File);
  • }
  • }

 

5.2.运行结果

 

6.软件工程

GD32H7xx_SDIO_SD_FatFs.zip (3.88 MB, 下载次数: 4)
查看本帖全部内容,请登录或者注册

赞赏

1

查看全部赞赏

点赞 关注
个人签名We are a team and we work as a team !
 
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
【干货上新】电源解决方案和技术第二趴 | DigiKey 应用探索站
当月好物、电源技术资源、特色活动、DigiKey在线实用工具,干货多多~

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 4

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表