如何使用CubeMx制作一个基于SD卡的文件系统工程(2)

本文是原文http://blog.csdn.net/flydream0/article/details/52777923的补充。

原文并没有考虑SD卡拔插问题,且SDIO没有使用DMA,本文作为补充,将示例如何改善这两方面的问题。

1 SD卡拔插检测

FATFS文件系统初始化得修改下:

void MX_FATFS_Init(void)
{
  /*## FatFS: Link the SD driver ###########################*/
  retSD = FATFS_LinkDriver(&SD_Driver, SD_Path);

  /* USER CODE BEGIN Init */
  /* additional user code for init */

  /* USER CODE END Init */
}

即保持CubeMx自动生成的原样即可,并不需要增加任何其他内容。

关键实在main中的while循环中检测SD卡的拔插:

 while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
        curSdCardStatus =BSP_SD_IsDetected();
        if(curSdCardStatus !=preSdCardStatus)
        {
            switch(curSdCardStatus)
            {
            case SD_PRESENT:
                BSP_SD_Init();
                MountFat32FileSystemImmeditely();
                break;
            case SD_NOT_PRESENT:
                UnmountFilesystem();
                //FATFS_UnLinkDriver("0:/");
                break;
            }
            preSdCardStatus =curSdCardStatus;
        }
//      HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
//      HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);
//      HAL_GPIO_TogglePin(LED3_GPIO_Port,LED3_Pin);
//      HAL_GPIO_TogglePin(LED4_GPIO_Port,LED4_Pin);
//      HAL_Delay(200);
  }

如上代码,循环检测SD卡的插入状态,一旦发现状态有变化,则进行相应操作,比如挂载文件系统,或者卸载文件系统。

挂载文件系统

static int  MountFat32FileSystem(void)
{
        FRESULT ret ;

        ret =f_mount(&SDFatFs, "0:/", 0);
        if(ret!= FR_OK)
    {
      if(ret ==FR_DISK_ERR)
            {
//              if(f_mkfs((TCHAR const*)SD_Path, 0, 0) != FR_OK)        //format the SDCard with FAT32 filesystem
//              {
//                  /* FatFs Format Error */
//                  Error_Handler();
//              }
            }
            else
            {
        Error_Handler();
            }
    }

        return 0;
}

函数f_mount为实际操作挂载文件系统的函数,有3个输入参数,最后那个参数为0,表示先不挂载,等到fopen时再挂载,为1时,则表示立即挂载,在这个函数内部会使用check_fs函数去检查是否为FAT32文件系统,如果是,在挂载成功,否则失败。

当然这里可以立即挂载,但是你若不断拔插SD卡,还是有一定的概率会出意外,比如后续fopen失败。因此,这里第3个参数使用0,不马上挂载,而是等到真正读取文件时才执行挂载文件系统。

文件系统卸载

static int UnmountFilesystem(void)
{
    FRESULT ret;
    ret =f_mount(NULL, "0:/", 0);

    return ret;
}

f_mout的第3个参数在这里没有意义,在这个f_mount函数内部会忽略它。

文件测试

相比之前的代码,文件测试我们将其改在按键回调函数中进行:

void FileTest(void)
{
    FRESULT res;
    uint32_t byteswritten, bytesread;                     /* File write/read counts */
    uint8_t wtext[] = "This is STM32 working with FatFs"; /* File write buffer */
    uint8_t rtext[100];

    if(f_open(&MyFile, "0:/STM32.TXT", FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
    {
        /* ‘STM32.TXT‘ file Open for write Error */
        Error_Handler();
    }
  else
  {
            res = f_write(&MyFile, wtext, sizeof(wtext), (void *)&byteswritten);
            if((byteswritten == 0) || (res != FR_OK))
            {
                /* ‘STM32.TXT‘ file Write or EOF Error */
                Error_Handler();
            }
            else
            {
                f_close(&MyFile);

                /*##-7- Open the text file object with read access ###############*/
                if(f_open(&MyFile, "0:/STM32.TXT", FA_READ) != FR_OK)
                {
                    /* ‘STM32.TXT‘ file Open for read Error */
                    Error_Handler();
                }
                else
                {
                    res = f_read(&MyFile, rtext, sizeof(rtext), (UINT*)&bytesread);

                    if((bytesread == 0) || (res != FR_OK))
                    {
                        /* ‘STM32.TXT‘ file Read or EOF Error */
                        Error_Handler();
                    }
                    else
                    {
                        f_close(&MyFile);

                        /*##-10- Compare read data with the expected data ############*/
                        if((bytesread != byteswritten))
                        {
                            /* Read data is different from the expected data */
                            Error_Handler();
                        }
                        else
                        {
                            /* Success of the demo: no error occurrence */
                            HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
                        }
                    }
                }
            }
  }
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if(GPIO_Pin ==GPIO_PIN_15)
    {
        if(BSP_SD_IsDetected() ==SD_PRESENT)
        {
            FileTest();
        }
    }
}

2 SDIO使用DMA来操作

要增加DMA,首先得在CubeMx中为SDIO分别为Tx和RX增加DMA:

图1 SDIO的DMA设置

其次需要注意地是,SDIO的几个中断优先级设置:

图2 SDIO的DMA设置

这里SDIO global inerrupt的中断优先级不能比DMA的优先级高,否则会出现DMA回调死等的情况。

最后就是对接了:

在sd_diskio.c文件中,找到SD_read函数,将BSP_SD_ReadBlocks函数改为BSP_SD_ReadBlocks_DMA函数:

DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
{
  DRESULT res = RES_OK;

  if(BSP_SD_ReadBlocks_DMA((uint32_t*)buff,
                       (uint64_t) (sector * BLOCK_SIZE),
                       BLOCK_SIZE,
                       count) != MSD_OK)
  {
    res = RES_ERROR;
  }

  return res;
}

同样,写函数也相应地修改,使用带DMA函数:

DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
{
  DRESULT res = RES_OK;

  if(BSP_SD_WriteBlocks_DMA((uint32_t*)buff,
                        (uint64_t)(sector * BLOCK_SIZE),
                        BLOCK_SIZE, count) != MSD_OK)
  {
    res = RES_ERROR;
  }

  return res;
}

需要注意地是,sd_diskio.c这个文件每次cubeMx生成代码时都会重新覆盖它,默认是使用非DMA方式的。

3 结论:

这里的关键是那个中断优先级,SDIO global中断(4)必须比DMA中断优先级高(5),否则程序会卡在DMA中断里。

另附上附件: http://download.csdn.net/detail/flydream0/9728000

时间: 2024-12-14 18:05:53

如何使用CubeMx制作一个基于SD卡的文件系统工程(2)的相关文章

S3C6410基于SD卡的裸机开发

手里只有一块OK6410开发板,一张8G的SD卡,没有相关的JTAG调试器,也没有集成开发环境可用,那如何进行裸机开发呢?查询开发的手册可知,6410芯片支持从SD卡启动,因此裸机开发就从SD卡开始. 1.开发环境的搭建 首先搭建虚拟机平台,安装Linux开发环境centos6.5,安装过程这里不再赘述. 2.交叉编译环境的安装 进入centos6.5,在/home目录下新建gnutools目录,将arm-linux-gcc-4.3.2.tgz(开发板的所带的资料)文件拷贝到 centos的/h

制作SD卡img文件,并扩容

/**************************************************************************************** * 制作SD卡img文件,并扩容 * 说明: * 主要是为了简便以后的系统烧录操作,通过制作SD卡烧录img文件,可以完成将系统dd到任何 * SD卡上,加上resize2fs这个命令对SD最后一个分区进行扩容,该功能是从树莓派上借鉴过来的. * * 2017-2-26 深圳 南山平山村 曾剑锋 ***********

SD卡添加文件,添加不进去,报 Read-only file system错误

android 模拟器手机如何添加文件到sd卡? 在DDMS中直接添加文件到模拟器sd卡如果出现错误类似:Failed to push XXXXX.txt on emulator- : Read-only file system的错误,原因是你的sdcard权限不够,需要直接创建一个SDCARD . 一.首先创建SDCARD  我创建的sdcard名为:sdcard.img(名字随便取,以img后缀名结束) 进入DOS  指向  目录 E:\android-sdk_r10-windows\and

安卓 SD卡写入文件后不能立即显示被写入的文件解决方法

每次通过输出流往SD卡写入文件,连接上电脑,用MTP的方式模拟一个移动磁盘,打开磁盘却没有这样一个文件,而通过adb的方式查看就有,造成这个现象的原因是,每次写入之后,MTP的数据库并没有更新,因为更新一次MTP数据库需要的带价比较大,所以只有在重启,挂载和用户手动发送Intent出发,故存入文件后需要手动发送Intent广播,出发一下MTP数据库的更新. /** * 出发扫描 mtp下的文件,在保存文件到 sd卡下后,不能显示,故这里触发一下扫描机制,让手机连上电脑后,就可以读出文件了 * @

使用File Explorer向SD卡Push文件抛出:Failed to push selection: Read-only file sys

使用File Explorer向SD卡(/mnt/sdcard/)写入数据时发生异常,Failed to push selection: Read-only file sys. 原因有2点 1:没有申请权限. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission

手机sd卡删除文件恢复呢

手机sd卡删除文件恢复呢?我们现在有些时候会使用我们的SD卡去存储我们的数据,但是有些时候呢,我们会因为自己的不小心或者是其他方面的原因,将我们的手机SD卡上的文件给误删了. 那么我们若是误删了我们的SD卡文件,我们是不是可以恢复呢?我们又该怎么去进行我们SD卡的恢复呢?相信很多的人都会有这个疑问,下面我们就一起看看具体的SD卡删除文件如何恢复吧. 第一步:在过程刚刚开始的时候,打开我们丢失数据的电脑,然后在电脑浏览器上下载并安装"互盾数据恢复软件",之后对软件进行安装等待安装结束:

sd卡删除文件了能恢复吗?恢复的具体方法

sd卡删除文件了能恢复吗?恢复的具体方法.我们现在很多的时候或许并不是使用我们的SD卡去进行数据的存储,但是有的时候,我们会因为自己的一些细小的原因,将我们的文件存储到我们的SD卡上. 那么当我们删除了我们SD卡上的数据的时候,我们该怎么办呢?我们是不是可以恢复呢?我们又该怎么去进行恢复呢?若是你也不清楚的话,不用担心,我们或许可以用下面的方法找回. 1.在过程刚刚开始的时候,打开我们丢失数据的电脑,然后在电脑浏览器上下载并安装"互盾数据恢复软件",之后对软件进行安装等待安装结束: 2

一个不用SD卡,不用livesuit的刷nand的想法

最近看到很多人说livesuit(phoenixsuit)不好用,又不好拿SD卡去刷系统.有了一种新的想法,类似berryboot,但是不一样.先是用ttl线或者安卓的虚拟终端程序去运行一个shell.shell会自动检测网络,然后下载一个很小的启动文件(当然用的是busybox来做rootfs),接着自动dd进nand里面,可能会抹掉u-boot,这个算比较危险的,不过估计会去校验md5.接着启动完这个小系统后,会自动用HDMI和VGA方式来显示图形界面,然后就是类似berryboot但是不一

android如何获取一个SD卡指定文件夹的图片Uri uri问题

============问题描述============ String a="file://"+Environment.getExternalStorageDirectory().getPath()+"/dcim/Camera/"; //  File baseFile = new File(a+"/dcim/Camera/15.jpg"); //  Uri uri =  Uri.fromFile(baseFile) ; //  Uri uri =