电子工程师名片——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的缘故吧,所以对其中的一些寄存器很不了解,一切都是重新开始, ...
随机推荐
- NDK编译应用程序
Android源码目录下的build/envsetup.sh文件,描述编译的命令 - m: Makes from the top of the tree. - mm: Build ...
- MySQL 异常错误码使用 及 对照表
DECLARE CONTINUE HANDLER FOR SQLWARNING, SQLEXCEPTION, NOT FOUND BEGIN GET DIAGNOSTICS CONDITION cod ...
- selection与range笔记
selection对象代表当前激活选中区,通常是高亮的文本块 创建选中区: 1.拖拽文本 2.脚本创建 cerateRange() 获取selection对象 IE document.sele ...
- Viewpager实现图片轮播
//-------------主布局文件------------------------------------- <LinearLayout xmlns:android="http: ...
- lucene索引合并与增量索引
利用 Lucene,在创建索引的工程中你可以充分利用机器的硬件资源来提高索引的效率.当你需要索引大量的文件时,你会注意到索引过程的瓶颈是在往磁盘上写索引文件的过程中.为了解决这个问题, Lucene ...
- 【转】HBase技术介绍 转载自 http://www.searchtb.com/2011/01/understanding-hbase.html
HBase简介 HBase – Hadoop Database,是一个高可靠性.高性能.面向列.可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群. HB ...
- C++:new 和 delete
在 C++ 中 , 使用 new 操作符动态申请内存的时候,如果申请失败,则会抛出 bad_alloc异常 当使用 delete 释放一块内存的时候 , 有些编译器上delete 不能判断一块内存 ...
- 2015十大顶级开源ERP系统点评
如今,企业资源规划(ERP)和客户关系管理(CRM)系统的必要性已经被各种组织和企业所认可:ERP和CRM能够直接为企业的业务效率和利润做出贡献. 但是随着今天企业商业形态的日趋多样化,互联网新经济的 ...
- 为什么做Web开发要选择PHP
大部分互联网公司做WEb开发都选择PHP,PHP的优势在哪?你应该知道的 以前偶尔被人问到,为什么你(和大部分互联网公司)做Web开发要选择PHP, PHP有什么好处.简单的回答便是“PHP简单,开发 ...
- Nginx代理外网映射
外网映射内网端口8080, 外网访问使用端口8379: nginx监听8080和80端口 #user nobody; worker_processes ; #error_log logs/error. ...