📄 f34x_msd_file_system.c
字号:
//-----------------------------------------------------------------------------
// F34x_MSD_File_System.c
//-----------------------------------------------------------------------------
// Copyright 2006 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// File contains the basic functions for file system commands.
//
//
//
// How To Test: See Readme.txt
//
//
// FID: 34X000035
// Target: C8051F34x
// Tool chain: Keil
// Command Line: See Readme.txt
// Project Name: F34x_USB_MSD
//
// Release 1.1
// -All changes by PKC
// -09 JUN 2006
// -No changes; incremented revision number to match project revision
//
// Release 1.0
// -Initial Release
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "F34x_MSD_Definitions.h"
#include "F34x_MSD_File_System.h"
#include "F34x_MSD_Sect_Serv.h"
#include "F34x_MSD_Util.h"
#include <string.h>
#include <stdio.h>
#include <ctype.h>
extern bootrecord_small xdata MBR;
void Print_File(FILE *file);
//-----------------------------------------------------------------------------
// file_name_match
//-----------------------------------------------------------------------------
//
// Return Value : 1 if they match
// Parameters : filename - pointer to file name
// direntryname - pointer to enterd directory name
//
// Compares the file name and directory name
//-----------------------------------------------------------------------------
static BYTE file_name_match(char* filename,char* direntryname)
{
xdata BYTE i,j = filename[0];
for(i=0;i<8;i++) {
if(direntryname[i] == ' ' && (filename[i] == '\0' || filename[i] == '.'))
{
if(!(j == '.' && filename[i] == '.'))
break;
}
if(tolower(direntryname[i])!=filename[i])
return 0;
}
j = i+1;
for(i = 8; i < 11; i++) {
if( filename[j] == '\0' && direntryname[i] != ' ')
return 0;
if( direntryname[i] == ' ' && (filename[j] == '\0' || filename[j] == '.'
|| filename[j-1] == '\0'))
break;
if(tolower(direntryname[i]) != filename[j])
return 0;
j++;
}
return 1;
}
//-------------------------------------------------------------------------------
// Functions only for F340 device
//-------------------------------------------------------------------------------
#ifdef __F340_VER__
xdata unsigned char Path_Name[200];
xdata unsigned long Current_Dir_Block;
//xdata char current_dir_name[40];
static find_info xdata findinfo; // Shared find_info for fopen() and fdelete()
static unsigned fat_chain_alloc(unsigned from,unsigned nr) ;
static unsigned long fat_chain(unsigned long from,unsigned nr) ;
static void fat_chain_free(unsigned from);
//-----------------------------------------------------------------------------
// write_current_dir
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This function printout current directory name
//-----------------------------------------------------------------------------
void write_current_dir()
{
printf("%s",Path_Name);
}
//-----------------------------------------------------------------------------
// GetClusterOfParentDirectory
//-----------------------------------------------------------------------------
//
// Return Value : cluster number
// Parameters : None
//
// Function returns cluster number which begins current directory
//-----------------------------------------------------------------------------
static unsigned GetClusterOfParentDirectory()
{
if(Current_Dir_Block == Sect_Root_Dir()) return 0;
return (Current_Dir_Block - Sect_File_Data()) / MBR.sectors_per_cluster;
}
//-----------------------------------------------------------------------------
// Get_Cluster_From_Sector
//-----------------------------------------------------------------------------
//
// Return Value : cluster number
// Parameters : sector - sector which belongs to returned cluster
//
// Function returns cluster number which contains sector
//-----------------------------------------------------------------------------
static unsigned Get_Cluster_From_Sector(unsigned long sector)
{
if(sector < (Sect_File_Data() + 2*MBR.sectors_per_cluster)) return 0;
return ((sector - Sect_File_Data()) / MBR.sectors_per_cluster);
}
//-----------------------------------------------------------------------------
// Get_First_Sector
//-----------------------------------------------------------------------------
//
// Return Value : sector address
// Parameters : cluster - cluster number
//
// Function returns first sector which belongs to the cluster
//-----------------------------------------------------------------------------
static unsigned long Get_First_Sector(unsigned cluster)
{
if(cluster >= 2) return Sect_File_Data() + cluster*MBR.sectors_per_cluster;
else return Sect_Root_Dir();
}
//-----------------------------------------------------------------------------
// Get_First_Block_Of_Next_Cluster
//-----------------------------------------------------------------------------
//
// Return Value : first block of next cluster in chain or 0xFFFFFFFF if cluster
// is last in chain
//
// Parameters : cluster - searching cluster
//
// Function returns number of first sector in next cluster in cluster chain
//-----------------------------------------------------------------------------
static unsigned long Get_First_Block_Of_Next_Cluster(unsigned cluster)
{
xdata unsigned long ret = fat_chain(cluster,MBR.sectors_per_cluster);
if(ret != 0xFFFFFFFF)
return ret + Sect_File_Data();
return ret;
}
//-----------------------------------------------------------------------------
// Get_Next_Cluster
//-----------------------------------------------------------------------------
//
// Return Value : cluster number
// Parameters : next cluster in chain
//
// Function returns number of next cluster in chain
//-----------------------------------------------------------------------------
static unsigned Get_Next_Cluster(unsigned cluster)
{
unsigned* xdata fat_table=Scratch;
Sect_Read(Sect_Fat1() + cluster/(Sect_Block_Size()/2));
return ntohs(fat_table[cluster%(Sect_Block_Size()/2)]);
}
//-----------------------------------------------------------------------------
// Get_File_Name
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : file_name - name of file [out] (must be allocated outside
// this function)
// direntry_name - name used in direntry [in]
//
// Function gets file name from direntry
//-----------------------------------------------------------------------------
static void Get_File_Name(char* direntry_name,char* file_name)
{
unsigned i,j = 0,k = 0;
for(i=0;i<11;i++)
{
if(direntry_name[i] == ' ')
{
j = 1;
continue;
}
if(j)
{
file_name[k++] = '.';
j = 0;
}
file_name[k++] = tolower(direntry_name[i]);
}
file_name[k] = 0;
}
//-----------------------------------------------------------------------------
// Get_First_Block_Directory_Cluster
//-----------------------------------------------------------------------------
//
// Return Value : first sector of cluster which belongs to current directory
// fat chain
// Parameters : sector - sector to check
//
// Function returns first sector of cluster which contains sector if this
// cluster belongs to FAT chain of current directory
//-----------------------------------------------------------------------------
static unsigned long Get_First_Block_Directory_Cluster(unsigned long sector)
{
xdata unsigned cluster = Get_Cluster_From_Sector(sector);
xdata unsigned next_dir_cluster = GetClusterOfParentDirectory();
while(next_dir_cluster != cluster)
{
next_dir_cluster = Get_Next_Cluster(next_dir_cluster);
if(next_dir_cluster >= 0xfff8) return next_dir_cluster;
}
return Get_First_Sector(cluster);
}
//-----------------------------------------------------------------------------
// Clear_Cluster
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : cluster - cluster number
//
// Function is used to clear all sectors of cluster
//-----------------------------------------------------------------------------
static void Clear_Cluster(unsigned cluster)
{
xdata unsigned long sector = Get_First_Sector(cluster);
xdata unsigned i;
memset(Scratch,0,512);
for(i=0;i<MBR.sectors_per_cluster;i++)
{
Sect_Write(sector+i);
}
}
//-----------------------------------------------------------------------------
// FillDirEntry
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : direntry - dir entry
// dir_name - file/directory name
//
// Function fills dir entry with file name
//-----------------------------------------------------------------------------
static void FillDirEntry(dir_entry* direntry,char* dir_name)
{
xdata BYTE i;
for( i = 0; i < 10; i++)
direntry->sfn.reserved[i] = 0;
direntry->sfn.time.i = findinfo.direntry->sfn.date.i = 0;
direntry->sfn.filesize = 0;
// Fill in the filename
for( i = 0; i < 11; i++ )
direntry->sfn.name[i] = ' ';
for( i = 0; i < 11; i++ ) {
if(!dir_name[i])
break;
direntry->sfn.name[i] = toupper(dir_name[i]);
}
}
//-----------------------------------------------------------------------------
// FileSys_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Function initializes some data used to navigate over directories
//-----------------------------------------------------------------------------
void FileSys_Init()
{
Current_Dir_Block = Sect_Root_Dir();
strcpy(Path_Name,"\\");
}
//-----------------------------------------------------------------------------
// chngdir
//-----------------------------------------------------------------------------
//
// Return Value : 0 - if such directory not exists in current directory 1
// otherwise
// Parameters : dirname - directory name to create
//
// Function tries to find and opens directory in current directory
//-----------------------------------------------------------------------------
BYTE chngdir(char* dirname)
{
findfirst(&findinfo, 0);
while(!file_name_match(dirname,findinfo.direntry->sfn.name)) {
if(!findnext(&findinfo)) {
return 0;
}
}
if(findinfo.direntry->sfn.attrib & ATTRIB_SUBDIR)
{
if(findinfo.direntry->sfn.starting_cluster == 0x00)
Current_Dir_Block = Sect_Root_Dir();
else
Current_Dir_Block = Sect_File_Data() +
(htons(findinfo.direntry->sfn.starting_cluster) * MBR.sectors_per_cluster);
if(!strcmp(dirname,".")) return 1;
if(!strcmp(dirname,".."))
{
xdata unsigned char* next,*pos = strstr(Path_Name,"\\");
while((next = strstr(pos,"\\")) != (NULL))
pos = next+1;
if(pos!=(Path_Name+1))
pos--;
*pos = '\0';
}
else
{
xdata unsigned len = strlen(Path_Name);
if(Path_Name[len-1] != '\\')
{
strcpy(&Path_Name[len],"\\");
len++;
}
strcpy(&Path_Name[len],dirname);
}
return 1;
}
return 0;
}
//-----------------------------------------------------------------------------
// mkdir
//-----------------------------------------------------------------------------
//
// Return Value : 0 if function succeeds other value if error occurs
// Parameters : dir_name - directory name
//
// Function creates directory
//-----------------------------------------------------------------------------
BYTE mkdir(char* dir_name)
{
xdata unsigned long dir_sectors;
xdata dir_entry* entry;
xdata unsigned start_cluster;
unsigned max_len = strlen(dir_name);
if((dir_name == NULL) || (max_len == 0) || (max_len > 8))
{
return DIRNAME_LENGTH_ERROR;
}
start_cluster = fat_chain_alloc(0,1);
// try to find directory with such name
findfirst(&findinfo, 0);
while(findnext(&findinfo)) {
if(file_name_match(dir_name,findinfo.direntry->sfn.name)) {
return DIRECTORY_EXISTS;
}
}
if(!findfirst(&findinfo,1)) return NO_PLACE_FOR_DIRECTORY;;
// Fill in the direntry
FillDirEntry(findinfo.direntry,dir_name);
findinfo.direntry->sfn.starting_cluster = htons(start_cluster);
// Don't forget to set the attrib:
findinfo.direntry->sfn.attrib = ATTRIB_SUBDIR;
// Write the new data to MMC
Sect_Write(findinfo.block);
// Clear dir_entry of directory and create dot and dotdot directory inside
Clear_Cluster(start_cluster);
dir_sectors = Sect_File_Data() + (start_cluster * MBR.sectors_per_cluster);
entry = (dir_entry*)Scratch;
FillDirEntry(entry,".");
entry->sfn.starting_cluster = htons(start_cluster);
entry->sfn.attrib = ATTRIB_SUBDIR;
entry = (dir_entry*)&Scratch[32];
FillDirEntry(entry,"..");
entry->sfn.starting_cluster = htons(GetClusterOfParentDirectory());
entry->sfn.attrib = ATTRIB_SUBDIR;
Sect_Write(dir_sectors);
return 0;
}
//-----------------------------------------------------------------------------
// rmdir
//-----------------------------------------------------------------------------
//
// Return Value : 1 if function suceeds other value if error occurs
// Parameters : dir_name - directory name
//
// Function removes directory
//-----------------------------------------------------------------------------
BYTE rmdir(char* dir_name)
{
unsigned dir_deep = 0;
PREV_SEARCH prev_dir_block[40];
char first_part_of_dir[20];
char dir_tmp_name[20];
char* tmp;
// error if someone tries to removw root directory
if(!strcmp(dir_name,"\\")) return 0;
if((tmp = strstr(dir_name,"\\")) == NULL)
{
strcpy(first_part_of_dir,dir_name);
}
else
{
if(tmp == dir_name)
{
tmp = strstr(&dir_name[1],"\\");
if(tmp != NULL)
*tmp = 0;
strcpy(first_part_of_dir,&dir_name[1]);
if(tmp != NULL)
*tmp = '\\';
}
else
{
*tmp = 0;
strcpy(first_part_of_dir,dir_name);
*tmp = '\\';
}
}
if(!chngdir(dir_name)) return 0;
if(!findfirst(&findinfo,0)) return 0;
while(1)
{
if(findinfo.direntry->sfn.name[0]!=(char)0xE5)
{
if(!(findinfo.direntry->sfn.attrib & ATTRIB_LABEL))
{
if(findinfo.direntry->sfn.attrib & (ATTRIB_SUBDIR))
{
if(!file_name_match(".",findinfo.direntry->sfn.name) &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -