Board logo

标题: STM32F4通过SDIO使用FatFs读取文件,使用STM32CubeMX配置-2 [打印本页]

作者: look_w    时间: 2018-1-24 21:08     标题: STM32F4通过SDIO使用FatFs读取文件,使用STM32CubeMX配置-2

二、在Keil中做初始化
1、调用BSP_SD_Init()函数
在main函数开头的部分调用了各种初始化函数,这些函数完成了硬件的初始化工作。在我的前一篇帖子 The specified item was not found. 中,SDIO的初始化也是要添加一点代码才可以正常的工作。这里也是一样,不过更加的简单。我们只需在MX_FATFS_Init();之前调用BSP_SD_Init();函数就可以了,我在下面贴出了这段初始化的代码。
这里介绍一下BSP_SD_Init()函数。BSP的意思是板级支持包的意思,也就是这个函数是专门针对某一类芯片支持的。这个函数在文件bsp_driver_sd.c文件中,在这个文件里面还有很多的函数,这些函数完成了对读写SD卡、查询SD卡状态、初始化SD卡等一系列操作。这些函数原先都是要用户来编写,提供给FatFs调用作为驱动支持的。但是这里帮我们都定义好了只需要调用即可,如果你要用FatFs来连接自己的设备的话,那你就需要自己定义这些底层的IO驱动函数了。
关于FatFs底层驱动支持和驱动架构的关系请查看附件UM1721_DM00105259_CN.pdf,这里面有ST官方对这个的详细说明。
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */  HAL_Init();  /* Configure the system clock */  SystemClock_Config();  /* Initialize all configured peripherals */  MX_GPIO_Init();  MX_SDIO_SD_Init();  MX_USART1_UART_Init();  BSP_SD_Init();  MX_FATFS_Init();
2、修改MX_FATFS_Init(void)函数
除了上面对初始化函数的调用以外,我们还需要一些别的修改。在这里,我希望调用BSP_SD_Init()初始化好了SD卡之后,在调用MX_FATFS_Init()初始化的时候就挂载SD卡。所以我们就在FatFs的初始化函数里面用户代码的部分加入了我们的f_mount函数。下面贴出MX_FATFS_Init()函数的代码,这个函数位于文件Application/User->fatfs.c中。
我还设置了一个简单的条件语句,如果挂载SD卡成功的话就发送一个成功的消息。
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 */ if(f_mount(&SDCard, SD_Path,0) == 0)  {  HAL_UART_Transmit(&huart1, (uint8_t *)"Success!\n", 9, 500);  }  /* USER CODE END Init */}
OK,到了这里我们对文件的修改就基本上完成了,但是仅仅如此只能让SD卡正常驱动和挂载,并不能够打开文件和读写操作。接下来的内容就是来解决这个问题的。
三、修改启动文件
1、malloc函数的介绍
原型
extern void *malloc(unsigned int num_bytes);
头文件
#include <stdlib.h>
函数声明
void *malloc(size_t size);
备注:void* 表示未确定类型的指针,void *可以指向任何类型的数据,更明确的说是指申请内存空间时还不知道用户是用这段空间来存储什么类型的数据(比如是char还是int或者其他数据类型)。
功能
分配长度为num_bytes字节的内存块
返回值
如果分配成功则返回指向被分配内存的指针(此存储区中的初始值不确定),否则返回空指针NULL。当内存不再使用时,应使用free()函数将内存块释放。函数返回的指针一定要适当对齐,使其可以用于任何数据对象。
以上是百度百科对malloc函数的一些简介,在Keil中要使用这个函数需要包含stdlib.h头文件。同时在Keil的编译器设置中要选中microlib选项,不过使用STM32CubeMX生成的工程默认都选中了这一选项。这个函数是放在标准库里面的,所以不能找到这个的定义代码在哪里,编译的时候链接所属的库就可以了。
2、FatFs对malloc函数的调用
为了讨论FatFs和malloc函数的关系,我们要先打开MiddleWares/FatFs->syscall.c文件。在这个文件里面,我们可以看到有一些函数是分配内存的函数。滚动页面到最下面,可以看到最后两个函数都和分配内存有关。这些函数都调用了malloc函数来动态分配内存,在ST的手册中没有提到这个malloc。但是如果没有这个系统提供的malloc函数我们就需要自己来定义一个动态内存分配函数,同时把原来的malloc调用替换为我们提供的函数接口。
这样我们就知道了FatFs对malloc函数有调用。但是仅仅如此吗?不是这么简单。FatFs默认是开启了对长文件名支持的,这样就需要很多的内存来存储文件名这些信息。如果malloc内存初始化的时候内存设置的比较小的话,就不能成功分配内存了不是吗?这样一来调用FatFs的f_open函数的时候就会返回17,查询这个枚举值的定义就知道是内存分配不足的错误。感兴趣的话可以不进行下一步修改heap的大小来调用f_open同时把返回值发送到串口来看一看。
3、改变heap的内存大小
malloc函数的内存是从堆(heap)里面分配的,如果使用了对长文件名的支持我们就需要malloc为FatFs提供内存分配的支持。在使用malloc之前会对malloc的内存池进行初始化,而这个初始化的操作是由我们的库提供的启动代码完成的。
下面贴出汇编语言的启动代码的一部分。
Stack_Size      EQU     0x00000400                AREA    STACK, NOINIT, READWRITE, ALIGN=3Stack_Mem       SPACE   Stack_Size__initial_sp; <h> Heap Configuration;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>; </h>Heap_Size       EQU     0x00000800                AREA    HEAP, NOINIT, READWRITE, ALIGN=3__heap_baseHeap_Mem        SPACE   Heap_Size__heap_limit
这一段代码是初始化内存池的汇编语言代码,在这里我把Heap_Size设置为0x00000800,也就是2KB。默认的数值是512Bytes,这样的话分配给我们的FatFs使用会不足,分配内存会失败。只有这样子修改了之后,后面的f_open这些函数才可以正常使用。
进行了以上的步骤之后,我们就可以轻松愉快地使用FatFs提供的各种函数了。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0