#include "partition.h"
#include "fat16.h"
#include <stdlib.h>
#include <string.h>
#include "sd_file_time.h"
/* 簇未使用 */
#define FAT16_CLUSTER_FREE 0x0000
/* 预留簇标记最小值 */
#define FAT16_CLUSTER_RESERVED_MIN 0xfff0
/* 预留簇标记最大值 */
#define FAT16_CLUSTER_RESERVED_MAX 0xfff6
/*坏簇*/
#define FAT16_CLUSTER_BAD 0xfff7
/*结束簇最小值*/
#define FAT16_CLUSTER_LAST_MIN 0xfff8
/*结束簇最大值,通常使用这个值*/
#define FAT16_CLUSTER_LAST_MAX 0xffff
/*文件已经被标记删除*/
#define FAT16_DIRENTRY_DELETED 0xe5
/*??标记含义不清*/
#define FAT16_DIRENTRY_LFNLAST (1 << 6)
/*??标记含义不清*/
#define FAT16_DIRENTRY_LFNSEQMASK ((1 << 6) - 1)
/*用来传参数的的临时结构*/
struct fat16_read_callback_arg
{
uint16_t entry_cur;
uint16_t entry_num;
uint32_t entry_offset;
uint8_t byte_count;
};
/*读分区引导扇区*/
static uint8_t fat16_read_header(fat16_filesystem* fs);
/*从根目录读一个目录项*/
static uint8_t fat16_read_root_dir_entry(const fat16_filesystem* fs, uint16_t entry_num, fat16_dir_entry* dir_entry);
/*从一个子目录中读取一个目录项*/
static uint8_t fat16_read_sub_dir_entry(const fat16_filesystem* fs, uint16_t entry_num, const fat16_dir_entry* parent, struct fat16_dir_entry_struct* dir_entry);
static uint8_t fat16_dir_entry_seek_callback(uint8_t* buffer, uint32_t offset, void* p);
static uint8_t fat16_dir_entry_read_callback(uint8_t* buffer, uint32_t offset, void* p);
static uint8_t fat16_interpret_dir_entry(fat16_dir_entry* dir_entry, const uint8_t* raw_entry);
/*取出下一簇号*/
static uint16_t fat16_get_next_cluster(const fat16_filesystem* fs, uint16_t cluster_num);
/*在簇链尾部增加一个新的簇*/
static uint16_t fat16_append_cluster(const fat16_filesystem* fs, uint16_t cluster_num);
/*将簇释放以供后面使用*/
static uint8_t fat16_free_cluster(fat16_filesystem* fs, uint16_t cluster_num);
/*写一个目录项到磁盘*/
uint8_t fat16_write_dir_entry(fat16_filesystem* fs, const fat16_dir_entry* dir_entry);
/**
打开FAT16文件系统
输入参数 partition 分区句柄
返回: 0失败,1 成功
*/
uint8_t fat16_open(fat16_filesystem * fat16_to_open, partition_base_info* partition)
{
if(!partition ||!partition->device_write )
return 0;
if(!fat16_to_open)
return 0;
memset(fat16_to_open, 0, sizeof(*fat16_to_open));
fat16_to_open->ptr_partition = partition;
if(!fat16_read_header(fat16_to_open))
{
return 0;
}
return 1;
}
/**
特定分区文件系统
输入参数 fs 特定分区文件系统
*/
void fat16_close(fat16_filesystem * fs)
{
if(!fs)
return;
memset(fs,0x00,sizeof(fs));
}
/*读分区引导扇区*/
uint8_t fat16_read_header(fat16_filesystem* fs)
{
uint8_t buffer[25];
partition_base_info* partition;
fat16_header* header;
uint32_t partition_offset;
uint16_t bytes_per_sector;
uint8_t sectors_per_cluster ;
uint16_t reserved_sectors ;
uint8_t fat_copies ;
uint16_t max_root_entries;
uint16_t sectors_per_fat ;
uint32_t sector_count ;
if(!fs || !fs->ptr_partition)
return 0;
partition = fs->ptr_partition;
header = &fs->header;
if(partition->type != PARTITION_TYPE_FAT16 &&
partition->type != PARTITION_TYPE_FAT16_LBA)
return 0;
partition_offset = partition->offset * 512;
if(!partition->device_read(partition_offset + 0x0b, buffer, sizeof(buffer)))
return 0;
memset(header, 0, sizeof(*header));
bytes_per_sector = ((uint16_t) buffer[0x00]) |
((uint16_t) buffer[0x01] << 8);
sectors_per_cluster = buffer[0x02];
reserved_sectors = ((uint16_t) buffer[0x03]) |
((uint16_t) buffer[0x04] << 8);
fat_copies = buffer[0x05];
max_root_entries = ((uint16_t) buffer[0x06]) |
((uint16_t) buffer[0x07] << 8);
sectors_per_fat = ((uint16_t) buffer[0x0b]) |
((uint16_t) buffer[0x0c] << 8);
sector_count = ((uint32_t) buffer[0x15]) |
((uint32_t) buffer[0x16] << 8) |
((uint32_t) buffer[0x17] << 16) |
((uint32_t) buffer[0x18] << 24);
/*分区的大小字节数*/
header->size = sector_count * bytes_per_sector;
/*fat表的相对于物理扇区的偏移地址*/
header->fat_offset = partition_offset + (uint32_t) reserved_sectors * bytes_per_sector;
/*fat表占用的字节数 = fat表所占扇区数* 每扇区字节数 */
header->fat_size = (uint32_t) sectors_per_fat * bytes_per_sector;
/*每扇区字节数*/
header->sector_size = bytes_per_sector;
/*每簇字节数*/
header->cluster_size = (uint16_t) bytes_per_sector * sectors_per_cluster;
/*根目录的偏移地址*/
header->root_dir_offset = header->fat_offset + (uint32_t) fat_copies * sectors_per_fat * bytes_per_sector;
/*数据区第1个簇的偏移地址*/
header->cluster_zero_offset = /* jump to root directory entries */
header->root_dir_offset +
/* skip root directory entries */
(uint32_t) max_root_entries * 32;
return 1;
}
/*从根目录读一个目录项
输入参数 fs 特定分区文件系统句柄
输入参数 entry_num 目录项的索引号
输出参数 dir_entry 用来填写目录项的缓冲区
返回值 0 : 失败 , 1 成功
*/
uint8_t fat16_read_root_dir_entry(const fat16_filesystem* fs, uint16_t entry_num, fat16_dir_entry* dir_entry)
{
/*我们读根目录的入口 */
const fat16_header* header = &fs->header;
device_read_interval_t device_read_interval ;
uint8_t buffer[32];
/* 跳到第n个项 */
struct fat16_read_callback_arg arg;
if(!fs || !dir_entry)
return 0;
device_read_interval = fs->ptr_partition->device_read_interval;
memset(&arg, 0, sizeof(arg));
arg.entry_num = entry_num;
if(!device_read_interval(header->root_dir_offset,
buffer,
sizeof(buffer),
header->cluster_zero_offset - header->root_dir_offset,
fat16_dir_entry_seek_callback,
&arg) ||
arg.entry_offset == 0
)
return 0;
/* read entry */
memset(dir_entry, 0, sizeof(*dir_entry));
if(!device_read_interval(arg.entry_offset,
buffer,
sizeof(buffer),
arg.byte_count,
fat16_dir_entry_read_callback,
dir_entry))
return 0;
return dir_entry->long_name[0] != '\0' ? 1 : 0;
}
/**
从一个给定的父目录中读目录项(这个父目录不是根目录)
从根目录中读子目录用的是另外一个函数fat16_read_root_dir_entry
输入参数 fs 特定分区文件系统
输入参数 entry_num 目录的索引值
输入参数 parent 父目录的句柄
输出参数 dir_entry 填写目录项的缓冲区
返回值 0 失败, 1 成功
*/
uint8_t fat16_read_sub_dir_entry(const fat16_filesystem * fs, uint16_t entry_num, const fat16_dir_entry* parent, struct fat16_dir_entry_struct* dir_entry)
{
/* 循环 这个目录所有的簇 */
uint8_t buffer[32];
uint32_t cluster_offset;
uint16_t cluster_size = fs->header.cluster_size;
uint16_t cluster_num = parent->cluster;
struct fat16_read_callback_arg arg;
if(!fs || !parent || !dir_entry)
return 0;
/* 我们是在一个父目录,并且准备在他的目录表中搜索
*/
if(!(parent->attributes & FAT16_ATTRIB_DIR))
return 0;
while(1)
{
/* 计算新簇的偏移量 */
cluster_offset = fs->header.cluster_zero_offset + (uint32_t) (cluster_num - 2) * cluster_size;
/* 跳到第n个目录项 */
memset(&arg, 0, sizeof(arg));
arg.entry_num = entry_num;
if(!fs->ptr_partition->device_read_interval(cluster_offset,
buffer,
sizeof(buffer),
c
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
spi_sd_fat20080909.zip (65个子文件)
spi_sd_fat20080909
Disk1_0x8A.bin 512B
Disk1_0x2C0.bin 512B
spi_sd_fat20080909
main.c 11KB
sd_basic_test.c 6KB
spi_sd_fat.ncb 73KB
partition.c 2KB
spi_sd_fat.dsw 526B
partition.h 4KB
fat16.c 41KB
sd_fat16_globals.c 14KB
TESTMEM.c 231B
sd_raw.c 1KB
sd_file_time.c 2KB
spi_sd_fat.opt 52KB
spi_sd_fat.vcproj.M-0R7948.Administrator.user 1KB
sd_raw.h 2KB
sd_dir.h 2KB
Debug
fat16.sbr 0B
spi_sd_fat.pch 275KB
vc60.pdb 52KB
spi_sd_fat.bsc 177KB
sd_raw.obj 5KB
partition.sbr 0B
sd_raw.sbr 0B
spi_sd_fat.exe 224KB
vc60.idb 41KB
spi_sd_fat.ilk 342KB
sd_file_time.sbr 0B
sd_basic_test.sbr 0B
sd_error.obj 3KB
sd_basic_test.obj 9KB
fat16.obj 34KB
main.obj 28KB
sd_file_time.obj 4KB
TESTMEM.obj 3KB
spi_sd_fat.pdb 513KB
sd_error.sbr 0B
TESTMEM.sbr 0B
main.sbr 0B
sd_fat16_globals.sbr 0B
sd_fat16_globals.obj 26KB
partition.obj 3KB
sd_basic.h 873B
fat16.h 4KB
sd_fat16_globals.h 1KB
sd_file_time.h 614B
spi_sd_fat.vcproj 9KB
sd_error.c 339B
sd_fileop.h 794B
sd_init.h 116B
sd_file.h 4KB
spi_sd_fat.plg 2KB
stdint.h 7KB
sd_error.h 2KB
ClassDiagram1.cd 1B
sd_disk.h 782B
spi_sd_fat.suo 5KB
spi_sd_fat.dsp 6KB
TESTMEM.H 213B
Disk1_0x89.bin 512B
Disk1_0x280.bin 512B
Disk1_0x0.bin 512B
sd.bin 1024KB
Disk1_0x260.bin 512B
Disk1_0x175.bin 512B
共 65 条
- 1
资源评论
robin19
- 粉丝: 0
- 资源: 4
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- Integrated-Energy-Systems-with-CAES-(注释完全,可直接运行)
- PDF为英语文本绘制热区(DEMO)
- 4.22.cpp
- 基于Transformer和Bert的close domain抽取式问答系统构建的智能聊天机器人项目源代码
- 基于扩展(EKF)和无迹卡尔曼滤波(UKF)的电力系统动态状态估计(注释完全,可直接运行)(文档加Matlab源码)
- 2023各大软件技术峰会演进资料汇总(PPT),资料难得
- 基于混沌集成决策树的电能质量复合扰动识别(注释完全,可直接运行)(文档加Matlab源码)
- 航空公司如何成功实现数字化转型英文版.rar
- RTL8309N-8口交换机评估板Cadence设计硬件(原理图+PCB)及PDF原理图+RTL8309N技术规格书
- 基于JAVA的打飞机游戏设计(程序).zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功