电子工程师名片——FAT16文件系统(转)
从8月8号开始,连续一个月利用每天下班时间和周末的时间终于初步完成了一个电子工程师的电路板名片,就像U盘一样,不过这个FLASH只有64KB的大小,用的单片机是C8051F320,是一个USB型的单片机。这次获取的教训是一开始想好要做什么事,无论如何要坚持下来,也许困难有很大,但是和困难磨磨突然会发现原来眼前的困难也是有解决的办法的,突然的豁然开朗。
整体结构如下:
我打算把自己所做的按照我自己调试的过程写下来,会连续发几篇博客,欢迎关注我哦。FAT16文件系统是在最后才搞出来,趁热打铁,把它作为第一篇先记下来。
电子工程师电路板名片之FAT16文件系统
FAT16文件系统的介绍在这篇博客介绍比较详细:http://blog.csdn.net/menghnhhuan/article/details/4270168
FAT16文件系统在U盘、MMC卡、SD卡、以及一些小型系统上用的比较多,我在MX25L512这个64KB的FLASH安装的文件系统如下:
注:第一个8*512中包含DBR区共一个512 Bytes,其余7个512 Bytes内容为0,但这8个512 Bytes都是保留扇区
一、DBR区(DOS BOOT RECORD):即操作系统引导区,本身只占512Bytes,但是从0地址开始有8个保留扇区(包括DBR区),所以FAT1的起始地址为8×512Bytes
注:BPB区记录本分区的起始扇区,结束扇区,文件存储格式,磁盘介质描述符,根目录大小,FAT个数,分配单元大小等。
下面是我程序中具体去设置DBR的512个字节
code unsigned char DBR[] =
{
0xeb,0x3c,0x90, //跳转指令,跳转到0x3c+2的引导程序代码处
0x4d,0x53,0x44, 0x4f, 0x53, 0x35, 0x2e, 0x30, //厂商标志和OS版本号 //BPB(BIOS parameter block)
0x00,0x02, //扇区字节数512(合法的有512,1024,4096),C8051F单片机是大端模式
0x01, //每簇扇区数(合法的有1,2,4,8,16,32,64,128)
0x08,0x00, //保留扇区数,这样可以知道FAT1区起始地址,为8×512
0x02, //FAT数目
0x00,0x02, //根目录数,典型为512个目录,每个文件或文件夹名长度为32 bytes
0x80,0x00, //小扇区数,(对于大于65536个扇区的分区,本字段为0,采用大扇区表示,)
0xf8, //媒体描述符,0xf8表示硬盘,0xf0表示3.5寸软盘
0x08,0x00, //每个FAT占用的扇区数
0x3F,0x00, //每道扇区数
0xFF,0x00, //磁头数
0x00,0x00,0x00,0x00, //隐藏扇区数
0x00,0x00,0x00,0x00, //大扇区数,如果小扇区字段为0,本字段就包含了FAT16中的总扇区数
//如果小扇区字段不为0,那么本字段为0 //BPB扩展字段
0x80, //物理驱动器,硬盘被标志为0x80,软盘驱动器被标志为0x00
0x00, //保留字段
0x29, //扩展引导标签,要有能被windows 2000所识别的0x28或0x29
0xA8, 0x8B, 0x36, 0x52, //卷序号,在格式化磁盘时所产生的一个随机号,助于区分磁盘
0x4E, 0x4F, 0x20, 0x4E, 0x41, 0x4D, 0x45, 0x20, 0x20, 0x20, 0x20, //卷标
0x46, 0x41, 0x54, 0x31, 0x36, 0x20, 0x20, 0x20, //文件系统类型FAT16 //操作系统引导代码
0xf1, 0x7d,
0xfa, 0x33, 0xc9, 0x8e, 0xd1, 0xbc, 0xfc, 0x7b, 0x16, 0x07, 0xbd, 0x78, 0x00, 0xc5, 0x76, 0x00,
0x1e, 0x56, 0x16, 0x55, 0xbf, 0x22, 0x05, 0x89, 0x7e, 0x00, 0x89, 0x4e, 0x02, 0xb1, 0x0b, 0xfc,
0xf3, 0xa4, 0x06, 0x1f, 0xbd, 0x00, 0x7c, 0xc6, 0x45, 0xfe, 0x0f, 0x8b, 0x46, 0x18, 0x88, 0x45,
0xf9, 0xfb, 0x38, 0x66, 0x24, 0x7c, 0x04, 0xcd, 0x13, 0x72, 0x3c, 0x8a, 0x46, 0x10, 0x98, 0xf7,
0x66, 0x16, 0x03, 0x46, 0x1c, 0x13, 0x56, 0x1e, 0x03, 0x46, 0x0e, 0x13, 0xd1, 0x50, 0x52, 0x89,
0x46, 0xfc, 0x89, 0x56, 0xfe, 0xb8, 0x20, 0x00, 0x8b, 0x76, 0x11, 0xf7, 0xe6, 0x8b, 0x5e, 0x0b,
0x03, 0xc3, 0x48, 0xf7, 0xf3, 0x01, 0x46, 0xfc, 0x11, 0x4e, 0xfe, 0x5a, 0x58, 0xbb, 0x00, 0x07,
0x8b, 0xfb, 0xb1, 0x01, 0xe8, 0x94, 0x00, 0x72, 0x47, 0x38, 0x2d, 0x74, 0x19, 0xb1, 0x0b, 0x56,
0x8b, 0x76, 0x3e, 0xf3, 0xa6, 0x5e, 0x74, 0x4a, 0x4e, 0x74, 0x0b, 0x03, 0xf9, 0x83, 0xc7, 0x15,
0x3b, 0xfb, 0x72, 0xe5, 0xeb, 0xd7, 0x2b, 0xc9, 0xb8, 0xd8, 0x7d, 0x87, 0x46, 0x3e, 0x3c, 0xd8,
0x75, 0x99, 0xbe, 0x80, 0x7d, 0xac, 0x98, 0x03, 0xf0, 0xac, 0x84, 0xc0, 0x74, 0x17, 0x3c, 0xff,
0x74, 0x09, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0xeb, 0xee, 0xbe, 0x83, 0x7d, 0xeb, 0xe5, 0xbe, 0x81, 0x7d, 0xeb, 0xe0, 0x33, 0xc0, 0xcd, 0x16, 0x5e, 0x1f, 0x8f, 0x04, 0x8f, 0x44, 0x02,
0xcd, 0x19, 0xbe, 0x82, 0x7d, 0x8b, 0x7d, 0x0f, 0x83, 0xff, 0x02, 0x72, 0xc8, 0x8b, 0xc7, 0x48,
0x48, 0x8a, 0x4e, 0x0d, 0xf7, 0xe1, 0x03, 0x46, 0xfc, 0x13, 0x56, 0xfe, 0xbb, 0x00, 0x07, 0x53,
0xb1, 0x04, 0xe8, 0x16, 0x00, 0x5b, 0x72, 0xc8, 0x81, 0x3f, 0x4d, 0x5a, 0x75, 0xa7, 0x81, 0xbf,
0x00, 0x02, 0x42, 0x4a, 0x75, 0x9f, 0xea, 0x00, 0x02, 0x70, 0x00, 0x50, 0x52, 0x51, 0x91, 0x92,
0x33, 0xd2, 0xf7, 0x76, 0x18, 0x91, 0xf7, 0x76, 0x18, 0x42, 0x87, 0xca, 0xf7, 0x76, 0x1a, 0x8a,
0xf2, 0x8a, 0x56, 0x24, 0x8a, 0xe8, 0xd0, 0xcc, 0xd0, 0xcc, 0x0a, 0xcc, 0xb8, 0x01, 0x02, 0xcd,
0x13, 0x59, 0x5a, 0x58, 0x72, 0x09, 0x40, 0x75, 0x01, 0x42, 0x03, 0x5e, 0x0b, 0xe2, 0xcc, 0xc3,
0x03, 0x18, 0x01, 0x27, 0x0d, 0x0a, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x73, 0x79,
0x73, 0x74, 0x65, 0x6d, 0x20, 0x64, 0x69, 0x73, 0x6b, 0xff, 0x0d, 0x0a, 0x44, 0x69, 0x73, 0x6b,
0x20, 0x49, 0x2f, 0x4f, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0xff, 0x0d, 0x0a, 0x52, 0x65, 0x70,
0x6c, 0x61, 0x63, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x2c, 0x20, 0x61,
0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e,
0x79, 0x20, 0x6b, 0x65, 0x79, 0x0d, 0x0a, 0x00, 0x49, 0x4f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x53, 0x59, 0x53, 0x4d, 0x53, 0x44, 0x4f, 0x53, 0x20, 0x20, 0x20, 0x53, 0x59, 0x53, 0x80, 0x01,
0x00, 0x57, 0x49, 0x4e, 0x42, 0x4f, 0x4f, 0x54, 0x20, 0x53, 0x59, 0x53, 0x00, 0x00, //扇区结束标志
0x55, 0xaa
};
二、FAT16文件系统
FAT(File Allocation Table)文件分配表,是微软在FAT文件系统中用于磁盘数据文件索引和定位引进的一种链式结构,有两个,另一个是备份。FAT文件系统之所以有12、16、32不同的版本之分,其根本在于FAT表用来记录任意一簇链接的二进制位数。以FAT16为例,每一簇在FAT表中占据两个字节(二进制16位)。所以,FAT16最大可以表示的簇号为0xFFFF,以32K为一簇的大小,FAT16可以管理的最大磁盘空间为:32KB×65536=2048B,所以FAT16最大支持2GB的分区。
因此FAT表以2个字节为一个记录项,通常第1、2个记录项用作介质描述(0xF8、0xFF、0xFF、0xFF),从第3个记录项开始记录除根目录外的其他文件夹的簇链情况。具体FAT16表如何用很多个簇号链接表示见http://bbs.ednchina.com/BLOG_ARTICLE_226477.HTM,一个文件结尾的簇号为0xFFFF。
三、文件目录
跟目录的位置紧随FAT2表之后,系统以32个字节为单位进行目录文件所占簇的分配,文件目录必须占据32个扇区
0x1A~0x1B为文件开始簇号,例如簇号为02 00,因为是使用小端模式,转化后簇号为00 02,根据这个可以找到文件第一个簇号在FAT1中的位置,0x1000H+02H*02H=1004H,因此可以计算文件第一簇数据存放地址为56×512(用户数据起始地址)+(02H-02H)×512(1簇占1个扇区),而在FAT1表1004H的地址上的数据为03 00,转换后为00 03,那么可以计算第二簇的数据存放地址为56×512(用户数据起始地址)+(03H-02H)×512(1簇占1个扇区),一直到FAT1表的某两个字节为FF FF时代表文件结束。
四、处理PC端发来的读写文件系统的固件程序
U盘固件提供的功能:当主机要求读取某个扇区,定位到该扇区,从扇区里面读出内容,并输出给主机,他不需知道U盘是什么文件,只需把数据读出来,主机通过读取的扇区的内容来判断是什么文件系统。
FLASH知识:
64kB的flash本身的sector为4kB,Page为256Byte
Page为写入数据的最小单位,sector为数据擦除的最小单位。
而现在作为文件系统,我已经修改为:LBA(Logical BlockAddress)128个,每个Block的大小为512Byte,128*512B=65536B=64kB。
处理好LBA和Pagenum的关系
LBA指起始逻辑块地址,即flash中的第几个Block(512Byte)
Pagenum为有多少个逻辑块地址,最大为上面计算的128个Block。
因为现在文件系统Block的大小为512Bytes,而flash的page大小为256,所以每次写512字节要分两次来写。
SPI_Write_Page(buff,0,2*(LBA+Pagenum)-2);
SPI_Write_Page(buff,0,2*(LBA+Pagenum)-1);
case Read_10://回发MBR主引导扇区数据
//sector:擦除数据的最小单位
//page读写数据的最小单位
// LBA:logical block address
// PageNum:number of LBA
// 16 sectors 1 sector=16 page 1 page=256 byte
if(PageNum>)
{
for(i=;i<=PageNum;i++)
{
PageNumL=*(LBA+i-);
SPI_READ_Page(, PageNumL);
for(t=;t<;t++)
{
FIFO_Write(buff + t*MaxSize, FIFO1, MaxSize);
SFR_Write(EINCSRL,0x01);
while(SFR_Read(EINCSRL) & 0x01);
}
PageNumH=*(LBA+i-)+;
SPI_READ_Page(, PageNumH);
for(t=;t<;t++)
{
FIFO_Write(buff + t*MaxSize, FIFO1, MaxSize);
SFR_Write(EINCSRL,0x01);
while(SFR_Read(EINCSRL) & 0x01);
}
}
}
csw=;
sendDebug(Read_10);
sendDebug(LBA);
sendDebug(PageNum);
break;
case Write_10://host向slave发数据并写在U 盘里面
if(PageNum>)
{
SPI_SECTOR_ERASE(LBA/);
for(i=;i<=PageNum;i++)
{
for(j=;j<;j++)
{
for(t=;t<;t++)
buff[*j+t]=SFR_Read(FIFO1);
SFR_Write(EOUTCRSL,0x00);
}
PageNumL=*(LBA+i-);
SPI_WRITE_Page(buff, , PageNumL);
for(j=;j<;j++)
{
for(t=;t<;t++)
buff[*j+t]=SFR_Read(FIFO1);
SFR_Write(EOUTCRSL,0x00);
}
PageNumH=*(LBA+i-)+;
SPI_WRITE_Page(buff, , PageNumH);
}
}
flags.epin1=;
csw=;
sendDebug(Write_10);
sendDebug(LBA);
sendDebug(PageNum);
break;
电子工程师名片——FAT16文件系统(转)的更多相关文章
- 电子工程师名片——FAT16文件系统
从8月8号开始,连续一个月利用每天下班时间和周末的时间终于初步完成了一个电子工程师的电路板名片,就像U盘一样,不过这个FLASH只有64KB的大小,用的单片机是C8051F320,是一个USB型的单片 ...
- 电子工程师名片——UFI Command,USB盘符的显示
USB Mass Storage类规范概述 USB Mass storage Device协议即海量存储设备协议适用于硬盘,U盘等大容量存储设备.协议使用的接口端点有BulkIn.Bul ...
- 电子工程师名片——SPI NOR Flash
使用了MX25L512的SPI接口的Flash 电路连接图: 总的大小512kb,即64kB,sector的大小为256 Bytes,block的大小为4k Bytes 调试时出现的问题: 1.Fla ...
- FAT16文件系统简介
有必要说明一下,以下对FAT16系统的介绍,很多都是参考文献.由于FAT16系统一般在U盘.MMC卡.SD卡以及一些小型存储设备上使用比较多,以后把这些小型存储设备统称为存储卡,这里仅局限于对存储卡的 ...
- 基于stm32f103zet6的FAT16文件系统学习1(初识FAT16)
有了之前读写block的基础之后,准备弄个文件系统,之前没有接触过这东西,所以有很多都晕晕的,但是看到fat的源代码之后还是挺有信心的,因为之前一直过uboot,所以这个文件当然是小巫见大巫了.首先来 ...
- 【操作系统】C语言编写的FAT16文件系统
[操作系统]C语言编写的FAT16文件系统 这是操作系统的期末课程设计作业之一,主要功能是在物理内存中虚拟出一个1M大小的FAT16的文件系统,然后把它读入内存中,进行具体的文件操作,具体的实用性不大 ...
- 快速开发MQTT(一)电子工程师眼中的MQTT
转载:https://zhuanlan.zhihu.com/p/54669124 DigCore 主页http://www.digcore.cn 文章首发于同名微信公众号:DigCore 欢迎关注同名 ...
- 解析FAT16文件系统
引导扇区的信息如下: 1. 偏移地址00H,长度3,内容:EB 3C 90 跳转指令. 2. 偏移地址03H,长度8,内容:4D 53 44 4F 53 35 2E 30 为厂商标志和os 版本号 ...
- 基于stm32f103zet6的FAT16文件系统学习0(读SD卡扇区)
SD卡已经看了两天了,主要是因为测试出来的卡容量不对,所以一直找原因,最终还是发现了,总比不过是单位上面出现了问题,或许是之前没有接触到SD的缘故吧,所以对其中的一些寄存器很不了解,一切都是重新开始, ...
随机推荐
- to_date()与to_char()
1.以时间(Date类型)为查询条件时,可以用to_date函数实现: select t.* from D101 t where t.d101_40 = to_date('2013/9/12', 'y ...
- 编程实现Windows瞬间关机
我们先来看看Windows正常的关机流程:①关机指令通知Windows子系统csrss.exe,csrss.exe收到通知后会和Winlogon.exe做一个数据交换,再由Winlogon.exe通知 ...
- linux fork()函数
C语言编程创建函数fork() 执行解析 | 浏览:1842 | 更新:2013-04-22 15:12 | 标签:c语言 概述 最近在看进程间的通信,看到了fork()函数,虽然以前用过,这次经过思 ...
- 【多重背包】 poj 2392
转自:http://blog.csdn.net/wangjian8006 题目大意:有一头奶牛要上太空,他有很多种石头,每种石头的高度是hi,但是不能放到ai之上的高度,并且这种石头有ci个将这些石头 ...
- Springmvc默认首页的问题
之前自己写的springmvc 默认首页都是偷懒方式: web.xml 中定义的默认首页: <welcome-file-list> <welcome-file>index.ht ...
- jsp ${param.id}用法
它的取值范围Page,Request,Session,Application. ${param.id} 与输入有关,相对于 request.getParameter("id").意 ...
- centos6.5 安装git
1.安装编译git时需要的包 # yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel # yum ins ...
- 2016.10.08--Intel Code Challenge Final Round--D. Dense Subsequence
time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...
- lucene 中关于Store.YES 关于Store.NO的解释
总算搞明白 lucene 中关于Store.YES 关于Store.NO的解释了 一直对Lucene Store.YES不太理解,网上多数的说法是存储字段,NO为不存储. 这样的解释有点郁闷:字面意 ...
- unity LineRenderer
using UnityEngine; using System.Collections; public class Spider:MonoBehaviour { private LineRendere ...