#include <stdlib.h>
#include "conf.h"
#include "sd.h"
#include "fat.h"
#include "delay.h"
#include "gui.h"
uint16 byts_per_sec; // 每扇区字节数
uint8 sec_per_clus; // 每簇扇区数
uint32 byts_per_clus; // 每簇字节数
uint32 fat_secs; // FAT所占扇区数
uint32 max_clus; // 最大簇号
uint32 first_fat_sec; // 第一个FAT扇区
uint32 first_dir_sec; // 第一个目录扇区
uint32 first_data_sec; // 数据区开始扇区号
uint32 root_dir_clus; // 根目录所在簇
uint32 root_dir_sec; // 根目录开始扇区号
uint32 root_dir_cnt; // 根目录目录数量
uint32 root_sec_cnt; // 根目录所占扇区数
#if USE_EEPROM == 0
uint32 folder_clus_buf[RECORD_ADDR_END] = {0};
#endif
// 函数指针指向sd卡的读写函数
uint8 (*fat_read_sec )(uint32 sec, uint8 *buf) = sd_read_block;
uint8 (*fat_write_sec)(uint32 sec, uint8 *buf) = sd_write_block;
// FAT初始化,不含SD的初始化,用之前应先调用sd的初始化
uint8 fat_init(void)
{
struct boot_struct *bs = 0;
struct bpb_struct *bpb = 0;
struct part_record *pr = 0;
uint32 hide_sec;
if(fat_read_sec(0, sd_cache)) return 1;
bs = (struct boot_struct *)sd_cache;
pr = (struct part_record *)((struct part_sector *)sd_cache)->psPart;
hide_sec = pr->prStartLBA;
if(bs->bsJump[0] == 0xE9 || bs->bsJump[0] == 0xEB)
{
hide_sec = 0;
}
else
{
if(fat_read_sec(pr->prStartLBA, sd_cache)) return 1; // 读取BPB数据
bs = (struct boot_struct *)sd_cache;
if(bs->bsJump[0] != 0xE9 && bs->bsJump[0] != 0xEB)
{
hide_sec = 0;
if(fat_read_sec(0, sd_cache)) return 1; // 读取BPB数据
bs = (struct boot_struct *)sd_cache;
}
}
if(bs->bsJump[0] != 0xE9 && bs->bsJump[0] != 0xEB) return 1; // 对付没有bootsect的sd卡
bpb = (struct bpb_struct *)bs->bsBPB;
byts_per_sec = bpb->BPB_BytsPerSec; // 每扇区字节数
sec_per_clus = bpb->BPB_SecPerClus; // 每簇扇区数
byts_per_clus = (uint32)sec_per_clus * (uint32)byts_per_sec; // 每簇字节数 // 每簇字节数
fat_secs = bpb->BPB_FATSz32; // FAT占用的扇区数
first_fat_sec = bpb->BPB_RsvdSecCnt + hide_sec; // 第一个FAT表扇区
root_dir_clus = bpb->BPB_RootClus; // 根目录所在簇
root_dir_cnt = bpb->BPB_RootEntCnt; // 根目录项数
root_sec_cnt = (root_dir_cnt * 32 + bpb->BPB_BytsPerSec - 1) / bpb->BPB_BytsPerSec;
first_dir_sec = first_fat_sec + bpb->BPB_NumFATs * fat_secs; // 第一个目录扇区
first_data_sec = first_dir_sec + root_sec_cnt; // 第一个数据扇区
root_dir_sec = first_data_sec + (uint32)(root_dir_clus - 2) * (uint32)sec_per_clus;
// 数据区最大簇号
max_clus = (bpb->BPB_TotSec32 - (bpb->BPB_RsvdSecCnt + bpb->BPB_NumFATs * fat_secs + root_sec_cnt)) / sec_per_clus + 1;
gui_char_to_hex(120, 30 , bs->bsJump[0] , 0xFFFF, 0x0000);
gui_char_to_hex(140, 30 , bs->bsJump[1] , 0xFFFF, 0x0000);
gui_char_to_hex(160, 30 , bs->bsJump[2] , 0xFFFF, 0x0000);
gui_char_to_hex(20 , 30 , byts_per_sec >> 8, 0xFFFF, 0x0000);
gui_char_to_hex(36 , 30 , byts_per_sec , 0xFFFF, 0x0000);
gui_char_to_hex(20 , 50 , sec_per_clus , 0xFFFF, 0x0000);
gui_long_to_hex(20 , 80 , root_dir_clus , 0xFFFF, 0x0000); // 根目录所在簇
gui_long_to_hex(20 , 100, root_dir_sec , 0xFFFF, 0x0000); // 根目录开始扇区号
gui_long_to_hex(20 , 130, fat_secs , 0xFFFF, 0x0000); // FAT占用的扇区数
gui_long_to_hex(120, 80 , bpb->BPB_TotSec32, 0xFFFF, 0x0000); // 总扇区数
gui_long_to_hex(120, 100, first_fat_sec , 0xFFFF, 0x0000); // 第一个FAT表扇区
gui_long_to_hex(120, 120, first_dir_sec , 0xFFFF, 0x0000); // 第一个目录扇区
gui_long_to_hex(120, 140, first_data_sec , 0xFFFF, 0x0000); // 第一个数据扇区
delay_nms(1000);
return 0;
}
// 读一个簇中的一个扇区
uint8 fat_read_part_clus(uint32 clus, uint16 part, uint8 *buf)
{
uint32 sec;
// 计算实际扇区号
sec = first_data_sec + (uint32)(clus - 2) * (uint32)sec_per_clus;
if(fat_read_sec(sec + part, buf))
{
return 1;
}
else
{
return 0;
}
}
// 写一个簇中的一个扇区
uint8 fat_write_part_clus(uint32 clus, uint16 part, uint8 *buf)
{
uint32 sec;
// 计算实际扇区号
sec = first_data_sec + (uint32)(clus - 2) * (uint32)sec_per_clus;
if(fat_write_sec(sec + part, buf))
{
return 1;
}
else
{
return 0;
}
}
// 读下一簇簇号
uint32 fat_next_clus(uint32 clus)
{
uint32 sec;
uint32 offset;
if(clus < 2) return BAD_CLUS;
offset = clus / (byts_per_sec >> 2);
sec = first_fat_sec + offset; // 计算实际扇区号
if(fat_read_sec(sec, sd_cache)) // 读FAT表,错误返回0x0FFFFFF8
{
return BAD_CLUS;
}
offset = clus % (byts_per_sec >> 2); // 查找原簇表中位置
clus = ((uint32 *)sd_cache)[offset];
return (uint32)clus; // 返回下一链接簇号
}
// 寻找空簇,返回空簇簇号
uint32 fat_find_blank_clus(void)
{
uint32 tmp_sec, sec, next_clus, clus;
uint32 offset;
sec = 0;
for(clus = root_dir_clus + 1; clus <= max_clus; clus++)
{
offset = clus / (byts_per_sec >> 2);
tmp_sec = first_fat_sec + offset; // 计算实际扇区号
if((sec != tmp_sec) || (sec == 0))
{
sec = tmp_sec;
if(fat_read_sec(sec, sd_cache)) // 读FAT表,错误返回0x0FFFFFF8
{
return BAD_CLUS;
}
}
offset = clus % (byts_per_sec >> 2); // 查找原簇表中位置
next_clus = ((uint32 *)sd_cache)[offset];
if(next_clus == EMPTY_CLUS) break;
}
return clus; // 返回下一链接簇号
}
// 在source_clus后链接指定next_clus簇
uint8 fat_link_clus(uint32 next_clus, uint32 source_clus)
{
uint32 sec;
uint32 offset;
offset = source_clus / (byts_per_sec >> 2);
if(source_clus < 2) return 1;
sec = first_fat_sec + offset; // 计算实际扇区号
if(fat_read_sec(sec, sd_cache)) // 读FAT表,错误返回0x0FFFFFF8
{
return 1;
}
offset = source_clus % (byts_per_sec >> 2); // 查找原簇表中位置
((uint32 *)sd_cache)[offset] = next_clus;
if(fat_write_sec(sec, sd_cache)) // 读FAT表,错误返回0x0FFFFFF8
{
return 1;
}
return 0; // 返回下一链接簇号
}
// 在指定簇后增加簇,并返回增加的簇号
uint32 fat_add_clus(uint32 clus)
{
uint32 tmp_clus_0, tmp_clus_1;
tmp_clus_0 = fat_next_clus(clus);
tmp_clus_1 = fat_find_blank_clus();
if(tmp_clus_1 > max_clus) return FAT_ADD_CLUS_FAIL; // 如果无后续簇则结束
fat_link_clus(tmp_clus_1, clus);
fat_link_clus(tmp_clus_0, tmp_clus_1);
return tmp_clus_1;
}
// 根据文件长度分配簇
uint8 fat_clus_assign(uint32 clus, uint32 len)
{
uint32 temp = byts_per_clus, tmp_clus;
while(temp < len)
{
tmp_clus = fat_next_clus(clus);
if(tmp_clus == EOF_CLUS)
{
tmp_clus = fat_add_clus(clus);
if(tmp_clus == FAT_ADD_CLUS_FAIL) return FAT_CLUS_ASSIGN_FAIL; // 如果添加不了簇则结束
}
clus = tmp_clus;
temp += byts_per_clus;
}
return FAT_CLUS_ASSIGN_OK;
}
// 删除指定簇链
void fat_del_clus_chain(uint32 clus)
{
uint32 next_clus;
if(clus <= 1)
{
return;
}
if(clus >= BAD_CLUS)
{
return;
}
while(1)
{
next_clus = fat_next_clus(clus);
fat_link_clus(0, clus);
if(next_clus >= BAD_CLUS)
{
break;
}
if(next_clus <= 1)
{
break;
}
clus = next_clus ;
}
}
// 清楚指定簇内容,用val值填满
uint8 fat_clus_fill_val(uint32 clus, uint8 val)
{
uint32 i;
for(i = 0; i < byts_per_sec; i++) sd_cache[i] = val;
for(i = 0; i < sec_per_clus; i++)
{
fat_write_part_clus(clus, i, sd_cache);
}
re