存储设备驱动开发:移植Flash的FatFs文件系统以及常见知识点扫盲

目录

1. 移植与设备驱动开发

2. FatFs文件系统移植

3. 易错点总结


        在讲具体的文件系统移植之前,我们先来重新梳理一下“移植”与“设备驱动开发”这两个概念。

1. 移植设备驱动开发

        “设备驱动开发”即,为设备编写驱动,可以理解成,为某个设备编写便于使用的API接口,供开发人员调用,这一工作一般是由BSP开发工程师(或称之为驱动开发工程师)完成,所提供的API接口将交给软开人员进行高层应用开发。
        例如现在我们需要通过主控MCU-stm32f103zet6片内集成了SPI控制器去控制某个Flash外设(W25Q64),则应当遵循下列步骤。

1.确定主控MCU上的通信控制器,例如SPI,并对其进行初始化,这一步包括相关GPIO口、总线时钟的初始化,以及SPI外设的寄存器配置;

2.根据Flash的相关指令分别编写相关的函数,比如我们需要首先通过SPI协议发送读ID指令获得Flash外设的相关设备号,然后编写读函数、写函数等,这些函数内部实际上就是根据Flash器件手册给的命令去控制Flash,并保存Flash返回的数据(如有);

注:常见外设器件的指令非常多,所以可以维护一个指令编码表;

以W25Q64为例,FLASH常用命令如下:
2 #define W25X_WriteEnable 0x06
3 #define W25X_WriteDisable 0x04
4 #define W25X_ReadStatusReg 0x05
5 #define W25X_WriteStatusReg 0x01
6 #define W25X_ReadData 0x03
7 #define W25X_FastReadData 0x0B
8 #define W25X_FastReadDual 0x3B
9 #define W25X_PageProgram 0x02
10 #define W25X_BlockErase 0xD8
11 #define W25X_SectorErase 0x20
12 #define W25X_ChipErase 0xC7
13 #define W25X_PowerDown 0xB9
14 #define W25X_ReleasePowerDown 0xAB
15 #define W25X_DeviceID 0xAB
16 #define W25X_ManufactDeviceID 0x90
17 #define W25X_JedecDeviceID 0x9F

        接下来我们再来讲讲“移植”这个概念:

        简单来说,移植(Porting)是指将一段代码、模块、库或操作系统,从原本适配的硬件/平台/环境,修改适配到另一个新的平台上仍能正常运行的过程。

        相对于一个初级开发工程师来说,“移植”这一项工作是有一定难度的,因为不同平台之间的差异往往是多方面的,例如可能差异在硬件、架构或者编译器上,此外,接口层也需要重写,包括IO、中断、内存控制等。

        移植的本质就是让已有的“通用代码”在新的“平台/硬件/操作系统/编译器”下正确运行。

        例如,你有一张电源插头是美式标准的插座板(原平台),现在你要在欧式插座(新平台)使用,那你需要“转接头+适配电压” —— 这就是移植。在软件中,"转接头"就是适配层、"适配电压"是指修改对接的新系统能力。

一些常见的需要做移植工作的场景:

(1)把FreeRTOS从STM32F1移植到STM32H7(CPU、外设不同)——硬件平台移植

(2)把Linux程序移植到RTOS环境下运行——操作系统平台移植

(3)把x86程序移植到ARM平台(如从PC移植到树莓派)——架构平台移植

(4)把Keil工程移植到GCC编译环境——编译器/工具链移植

2. FatFs文件系统移植

        讲完设备驱动开发移植这两个概念后,接下来我们开始进入正题,来讲讲FatFs文件系统移植。

        首先需要明白,原FatFs是平台无关的,我们需要把FatFs文件系统移植到STM32平台上,用来控制Flash存储器,就需要实现disk_read(), disk_write()等接口函数、调用我们自己的SPI驱动去读TF卡、定义宏BYTE, DWORD等以适配32位平台以及写初始化代码挂载文件系统(f_mount)。这就是从“裸平台”到“嵌入式平台”的移植过程。我们对移植、编译以及集成这几个概念做进一步区分:

(1)把Linux上的OpenCV代码放到STM32上运行 → 是移植

(2)把main.c变成main.hex → 是编译

(3)把FreeRTOS + FatFs + UART调试组装到一个工程 → 是集成

        FatFs文件系统,是嵌入式系统中最常用的文件系统之一,特别适合使用TF卡、SD卡、SPI-Flash、U盘等外部存储设备的场景。它由日本嵌入式开发者ChaN开发,是一个高可靠、可裁剪、纯C实现、平台无关的轻量级FAT文件系统模块。

        一个典型的FAT文件系统核心组成如下图所示:

        FAT = File Allocation Table,本质是一个“簇链表”,每个文件的数据由多个簇组成,FAT记录这些簇之间的链式连接。

        FatFs核心模块与架构如下图所示:

        文件系统本质上就是为了让开发人员能够更高效的控制底层存储器读写数据,最底层的设备就是用来存储数据的物理设备,如STM32中常用的Flash芯片,在物理芯片和应用层调用代码之间,还存在两层,分别是底层磁盘接口以及FatFs文件系统。前面我们说过,FatFs文件系统是已经写好的一套用来抽象存储设备做文件管理的接口程序,所以这一部分在移植过程中是不需要修改的,移植的主要工作在修改底层磁盘接口上,即修改diskio.c文件,在此文件中,我们需要实现SPI协议,以此来通过SPI通信控制具体的物理存储设备,访问实际的存储扇区,并根据FatFs文件系统的框架,完成底层接口函数的编写,比如disk_read()等,说白了,我们只需要在diskio.c文件中实现以下底层硬件访问函数即可完成系统移植。

3. 易错点总结

        最后,还有一些小白容易混淆的点,比如我们说设备驱动开发是指“从零开始编写代码来控制硬件外设工作”,从而让上层应用或系统能通过标准接口调用硬件功能,这似乎与设备驱动移植很像,但需要明确的是,设备驱动开发强调的是,用代码去控制硬件,并将这些繁琐的控制代码(驱动程序)封装成开发友好的函数,提供给应用开发人员使用,而设备驱动移植则强调将已有平台上的驱动代码(驱动程序),适配到新的平台/芯片/操作系统上,使其能继续工作。

        总结一下就是,设备驱动开发是写驱动程序,而设备驱动移植是改已有的驱动程序,例如,编写SPI驱动、I2C驱动、LCD驱动、USB Host驱动,这些都是设备驱动开发,而把原本为STM32F1写的CAN驱动,移植到STM32H7平台,这叫设备驱动移植。“移植”是在“已有驱动基础上”做“适配工作”,而“开发”是在“无驱动基础”上做“全新实现”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NJUST_ZHChen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值