尝试使用CubeMX做stm32开发之十五:FatFs的移植方法

news2024/11/19 3:17:40

一、数据类型

FatFs使用的数据类型在ff.h中定义,适用于绝大多数平台:

BYTE

8-bit无符号整形数据,范围0~28-1

WORD

16-bit无符号整形数据,范围0~216-1

DWORD

32-bit无符号整形数据,范围0~232-1

QWORD

64-bit无符号整型数据,范围0~264-1

UINT

无符号int

WCHAR

UTF-16代码单位的WORD

TCHAR

字符编码单位的CHAR、WCHAR、DCHAR

FSIZE_t

DWORD、QWORD别名,用于寻址文件偏移量和指定文件大小

LBA_t

DWORD、QWORD别名,用于寻址LBA的扇区并指定扇区数

二、ffconf.h

相关配置宏:

_FS_TINY

mini版本的FATFS

_FS_READONLY

设置只读,可以减少所占的空间

_FS_MINIMIZE

削减函数

_USE_STRFUNC

字符及字符串操作函数

_USE_MKFS

是否启用格式化

_USE_FASTSEEK

使能快速定位

_USE_LABEL

是否支持磁盘盘符的设置和读取

_CODE_PAGE

设置语言936-中文GBK编码

_USE_LFN

是否支持长文件名,值不同存储的位置不同

_MAX_LFN

文件名的最大长度

_VOLUMES

支持的逻辑设备数目

_MAX_SS

扇区缓冲最大值,一般为512

三、diskio.c

底层驱动涉及的6个接口函数:

  • Storage Device Controls
    • disk status - Get device status
    • disk initialize - Initialize device
    • disk read - Read data
    • disk write - Write data
    • disk ioct1 - Control device dependent functions
  • Real Time Clock
    • get fattime - Get current time

宏定义:

/* 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 */

FatFs支持多物理设备,必须为每个物理设备定义一个不同的编号。

实际中根据接入的物理设备(flash、SD卡等)进行修改。

设备状态读取函数 disk_status()

/*-----------------------------------------------------------------------*/
/* Get Drive Status                                                      */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
	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;
}

函数只有一个参数pdrv,表示宏定义中的物理设备的编号。

函数中使用switch函数实现判断。

各case中需要编写相应的硬件底层函数。

设备初始化函数 disk_initialize()

/*-----------------------------------------------------------------------*/
/* Inidialize a Drive                                                    */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
	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;
}

函数只有一个参数prdv,指定物理设备的编号。

各case中需要编写相应的硬件底层函数。

读取扇区函数 disk_read()

/*-----------------------------------------------------------------------*/
/* 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 */
)
{
	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;
}

函数包含4个参数:

pdrv:设备物理编号

buff:指向用于存放读取到的数据的存储位置首地址

sector:指定要读取数据的扇区首地址

count:指定扇区数量

各case中需要编写相应的硬件底层函数。

写扇区函数 disk_write()

/*-----------------------------------------------------------------------*/
/* 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 */
)
{
	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;
}

#endif

如果是只读模式,该函数无效。

函数包含4个参数:

pdrv:物理设备编号

buff:指向待写入扇区数据的首地址

sector:指定要写入数据的扇区首地址

count:指定扇区数量

各case中需要编写相应的硬件底层函数

其他功能控制函数 disk_ioct1():

/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

DRESULT disk_ioctl (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
	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;
}

时间函数 get_fattime():

DWORD get_fattime (void)
{
    time_t t;
    struct tm *stm;


    t = time(0);
    stm = localtime(&t);

    return (DWORD)(stm->tm_year - 80) << 25 |
           (DWORD)(stm->tm_mon + 1) << 21 |
           (DWORD)stm->tm_mday << 16 |
           (DWORD)stm->tm_hour << 11 |
           (DWORD)stm->tm_min << 5 |
           (DWORD)stm->tm_sec >> 1;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/81021.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C#基础学习】第十八章、接口

目录 接口 1.接口 1.1 声明接口 1.2 实现接口&调用接口 1.2.1 显式接口实现方式 1.2.2 显式接口实现&隐式接口实现的使用场景 1.3 as运算符 2.接口继承接口 接口 1.接口 接口的意义&#xff1a;C#的继承不支持一个子类拥有多个父类。而接口的存在就是为了弥补这…

C# 数组的声明与分配空间

一 数组的概述 数组是多个相同类型数据的组合&#xff1b;数组属引用类型&#xff1b; 1 一维数组声明 一维数组的声明方式&#xff1a; int[] a1;注意方括号写到变量名的签名&#xff1b; double [] b mydate[] c; C# 语言中声明的数组时不能指定其长度(数组中元素的个数)…

【RPA进阶】 一文了解使用Visual Studio扩展UiPath Activity Creator创建自定义Activity

&#x1f40b;作者简介&#xff1a;博主是一位.Net开发者&#xff0c;同时也是RPA和低代码平台的践行者。 &#x1f42c;个人主页&#xff1a;会敲键盘的肘子 &#x1f430;系列专栏&#xff1a;UiPath &#x1f980;专栏简介&#xff1a;UiPath在传统的RPA&#xff08;Robotic…

Dockerfile构建Springboot镜像

Dockerfile构建Springboot镜像 文章目录Dockerfile构建Springboot镜像简介实例演示前期准备Docker环境Springboot项目Dockerfile文件Windows要求构建镜像启动测试Linux要求构建镜像启动测试简介 容器技术大流行的时代&#xff0c;也是docker大流行的时代。 此文章以一个简单的实…

无线网卡收包流程

环境 x86_64 Linux&#xff0c; AR9462 无线网卡&#xff0c;PCIe 接口 ath9k 驱动 收包过程 ① 无线网卡从空气中捕获到无线数据包 【物理层】 ② 无线网卡把帧 DMA 到内存的 Ring Buffer ③ 无线网卡向 CPU 发起中断请求 ④ CPU 响应中断&#xff0c;执行 ISR&#xff0c;…

fatfs相关宏定义说明

fat16文件系统DBR 宏定义如下&#xff1a; #define BS_JmpBoot 0 //跳转指令。3字节。/* x86 jump instruction (3-byte) */ #define BS_OEMName 3 //OEM名称。8字节。/* OEM name (8-byte) */ #define BPB_BytsPerSec 11 //扇区字节数。2字节。/* Sector size [byte…

Python学习基础笔记四十五——包

C:\Program Files\Python310\Lib 1、 包的概念&#xff1a;把解决同一类问题的模块放在同一个文件夹里&#xff0c;我们就称为包。 2、在PyCharm中创建一个包&#xff1a; 文件夹中会有一个init.py文件。 在Python3中没有这个__init__.py文件也没有问题。 3、在包A和包B下有同…

Go设计与实现 -- map哈希表

Go语言中的哈希表有它自己的一套实现方式。和Java的哈希表还是有些不同的&#xff0c;但是为了保证知识体系的完整性&#xff0c;我还是准备从头开始说起。 哈希表设计原理 哈希表的读写时间复杂度是O(1)&#xff0c;因为它提供了键值之间的映射。要实现一个性能优异的哈希表…

spring——AOP面向切面编程——基于XML的AspectJ AOP开发(转载)

我们可以在 Spring 项目中通过 XML 配置&#xff0c;对切面(Aspect 或 Advisor)、切点(PointCut)以及通知(Advice)进行定义和管理&#xff0c;以实现基于 AspectJ 的 AOP 开发。Spring 提供了基于 XML 的 AOP 支持&#xff0c;并提供了一个名为“aop”的命名空间&#xff0c;该…

Docker笔记--使用Docker部署MySQL

1--Docker部署MySQL ① 搜索MySQL镜像 docker search mysql ② 拉取MySQL镜像 docker pull mysql:latest ③ 创建MySQL容器 首先在宿主机创建MySQL的映射目录&#xff0c;即数据卷&#xff1a; cd /home mkdir mysql cd mysql 之后在当前目录创建MySQL容器&#xff08;$PW…

【事故复盘】吐血整理一场线上事故——CPU飙升200%

&#x1f50d; 经验使你在第二次犯相同错误时及时发现。 —— 琼斯 &#x1f516; 事故时间&#xff1a;12.7日 17:43 ~ 21:03 &#x1f516; 事故影响&#xff1a;服务接口查询慢&#xff0c;用户查看数据转圈 &#x1f516; 事故过程&#xff1a; 那是一个宛如平静的下午&…

128-150-mysql-高级篇-索引及调优篇

115-mysql-高级篇-索引及调优篇&#xff1a; 索引及调优篇 1、索引的创建与设计原则 1. 索引的声明与使用 1.1 索引的分类 从功能逻辑上说&#xff0c;索引主要有 4 种&#xff0c;分别是普通索引、唯一索引、主键索引、全文索引。按照物理实现方式&#xff0c;索引可以分…

BUUCTF Web1

[极客大挑战 2019]EasySQL 试了个万能密码就能上去了 flag: flag{8e685472-02e4-440a-b04e-b0d9b6d9c27f} [HCTF 2018]WarmUp 看源码有个source.php <?phphighlight_file(__FILE__);class emmm{public static function checkFile(&$page){$whitelist ["source&qu…

Mysql 创建存储过程和函数及各种例子

Mysql 创建存储过程和函数及各种例子1. Mysql 创建存储过程1.1 前言知识1.1.1 语法结构1.1.2 简单解释1.2 创建存储过程入门例子1.2.1 无参存储过程1.2.1.1 不带变量1.2.1.2 带变量1.2.2 有入参的存储过程1.2.3 有出参的存储过程1.2.4 有入参和存储的存储过程1.2.5 inout的存储…

如何将镜像上传至阿里云?如何从阿里云中拉取自己的镜像?

目录 如何将制作好的镜像上传至阿里云&#xff1f; 一、前期准备 1、注册阿里云账户 2、登录账号 3、配置Docker加速器 4、创建镜像仓库的命名空间&#xff08;私有的&#xff09; 5.创建镜像仓库(创建镜像仓库时要绑定一个代码托管网站&#xff0c;例如&#xff1a;githu…

Zookeeper集群搭建

文章目录前言Zookeeper集群搭建&#xff08;一&#xff09;LeaderFollower模式&#xff08;二&#xff09;下载zookeeeper的压缩包&#xff08;三&#xff09;解压&#xff08;四&#xff09;修改配置文件&#xff08;五&#xff09;添加myid配置&#xff08;六&#xff09;安装…

痞子衡嵌入式:存储器大厂Micron的NOR Flash芯片特殊丝印设计(FBGA代码)

大家好&#xff0c;我是痞子衡&#xff0c;是正经搞技术的痞子。今天痞子衡给大家讲的是存储器大厂Micron的NOR Flash芯片特殊丝印设计(FBGA代码)。 痞子衡之前写过一篇文章 《J-Flash在Micron Flash固定区域下载校验失败的故事》&#xff0c;这篇文章里提及了 Micron 家的串行…

明峰医疗IPO终止:亏损超过14亿元,王瑶法、潘华素夫妇为实控人

近日&#xff0c;上海证券交易所科创板披露的信息显示&#xff0c;明峰医疗系统股份有限公司&#xff08;下称“明峰医疗”&#xff09;向上海证券交易所提交了撤回上市申请文件的申请&#xff0c;保荐人海通证券提交了撤回保荐的申请。 因此&#xff0c;上海证券交易所决定终…

设计模式之创建型模式---单例模式

文章目录1.介绍2.应用场景3.实现3.1 结构3.2 类图3.3 代码示例3.3.1 饿汉式3.3.2 懒汉式3.3.3 双重检验锁3.3.3 静态内部类实现单例3.3.4 枚举类实现单例总结1.介绍 单例模式(singleton) 是指某个类中能生成一个实例&#xff0c;该类提供了一个全局访问点&#xff0c;提供一个唯…

JUC并发编程与源码分析笔记07-volatile与JMM

被volatile修饰的变量有两大特点 可见性、有序性&#xff0c;但是不保证原子性。 当写一个volatile变量时&#xff0c;JMM会把该线程对应的本地内存中的共享变量值立即刷新回主内存中。当读一个volatile变量时&#xff0c;JMM会把该线程对应的本地内存设置为无效&#xff0c;重…