⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat32.c

📁 Hardware and firmware for a DSP based digital audio MP3 player with USB pen drive funtionality, usin
💻 C
字号:
/*
 * DSPdap-bootloader - DSP based Digital Audio Player, Bootloader
 * Copyright (C) 2004-2007 Roger Quadros <rogerquads @ yahoo . com>
 * http://dspdap.sourceforge.net
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: FAT32.c,v 1.2 2007/06/03 08:54:03 Roger Exp $
 */

#include "FAT32.h"
#include "CF.h"

//----------------FAT fields--------------
//these fields are updated by GetFatFieldsFromVolumeID()


//----------------------------------------
UI32 partition_begin_lba = 0;

FAT FAT32;	
//returns an 8-bit word from a byte offset in a given buffer
UI8 Get8BitWord(UI* buffer, int byteOffset)
{
	UI8 byte;
	UI *wordPtr;
	
	wordPtr = (UI *)&buffer[byteOffset>>1];	//(buffer + byteOffset/2)
	if(byteOffset & 1)
	{
		//odd boundary so byte is in MSB
		byte = (*wordPtr)>>8 & 0xFF;
	}
	else
	{
		//even boundary so byte is in LSB
		byte = (*wordPtr)&0xFF;
	}
	return byte;
}

//returns a 16-bit word from a byte offset in a given buffer
UI16 Get16BitWord(UI* buffer, int byteOffset)
{
	UI16 word;
	UI *wordPtr;
	
	wordPtr = (UI *)&buffer[byteOffset>>1];	//(buffer + byteOffset/2)
	if(byteOffset & 1)
	{
		//odd boundary so LSB of word is in given locations MSB
		//and MSB of word is in next locations LSB
		word = (*wordPtr)>>8 & 0xFF;
		word |= (*(wordPtr + 1))<<8 & 0xFF00;
	}
	else
	{
		//even boundary so complete word is in given location
		word = *wordPtr;
	}
	return word;
}

//returns a 32-bit word from a byte offset in a given buffer
UI32 Get32BitWord(UI* buffer, int byteOffset)
{
	UI32 lword;
	UI32 lword2;
	UI *wordPtr;
	
	wordPtr = (UI *)&buffer[byteOffset>>1];	//(buffer + byteOffset/2)

	if(byteOffset & 1)
	{
		//odd boundary so LSB of word is in given locations MSB
		//2nd LSB of word is in +1 locations LSB
		//3rd LSB of word is in +1 locations MSB..and so on
		lword = (*wordPtr)>>8 & 0xFF;
		lword2 = (*(wordPtr + 1));
		lword |= lword2<<8;
		lword2 = (*(wordPtr + 2))<<8 & 0xFF00;
		lword |= lword2 <<16;
	}
	else
	{
		//even boundary
		lword = *wordPtr;	//LS word
		lword2 = (*(wordPtr+1));
		lword |= lword2 << 16;
	}
	return lword;
}

UI32 FAT32_GetStartLBAofCluster(UI32 cluster_num)
{
 return (FAT32.cluster_begin_lba + ((cluster_num)-2)*FAT32.sectors_per_cluster);
}

//populates the FAT32 structure fields from Volume ID sector of drive.
int FAT32_GetFAT32Details()
{
	UI FAT_buffer[256];
	partition_begin_lba = 0;	//our partition starts at LBA 0..we have only 1 partition.
	if(CF_ReadSector(partition_begin_lba, FAT_buffer))
	{
		return 1;	//FAILED
	}
	
	FAT32.bytes_per_sector = Get16BitWord(FAT_buffer, 0xB);
	FAT32.sectors_per_cluster = Get8BitWord(FAT_buffer, 0xD);
	FAT32.num_reserved_sectors = Get16BitWord(FAT_buffer, 0xE);
	FAT32.num_FATs = Get8BitWord(FAT_buffer, 0x10);
	FAT32.FAT_size32 = Get32BitWord(FAT_buffer, 0x24);
	FAT32.root_begin_cluster = Get32BitWord(FAT_buffer, 0x2C);
	FAT32.signature = Get16BitWord(FAT_buffer, 0x1FE);
	
	FAT32.fat_begin_lba = partition_begin_lba + FAT32.num_reserved_sectors;
	FAT32.cluster_begin_lba = FAT32.fat_begin_lba + (FAT32.num_FATs * FAT32.FAT_size32);
	FAT32.root_dir_lba = FAT32_GetStartLBAofCluster(FAT32.root_begin_cluster);
	
	return 0;	//success
}

//Finds the next cluster in the FAT cluster chain from the current cluster and FAT.
//Either returns the next cluster number or -1 (i.e. 0xFFFFFFFF) if
//end of cluster chain. i.e. currentCluster was the last cluster.
//not yet tested
UI32 FAT32_FindNextCluster(UI32 currentCluster)
{
	UI FAT_buffer[256];
	UI32 FAT_sectorToRead, recordIdx;
	UI32 FAT_sector_offset;
	UI32 nextCluster;
	
	// Why is '..' labelled with cluster 0 when it should be 2 ??
	if(currentCluster==0) 
		currentCluster=2;
		
	// Find which sector of FAT table to read
		//FAT_sectorNumber  = ClusterNumber/Cluster Numbers per Sector
		//					= ClusterNumber/128		
		//as 1 cluster number = 32-bits = 4 bytes..so there are 128 cluster numbers in 1 sector
		
	FAT_sector_offset = currentCluster / 128;
	FAT_sectorToRead = FAT32.fat_begin_lba + FAT_sector_offset;
	
	// Read required FAT sector into buffer
	CF_ReadSector(FAT_sectorToRead, FAT_buffer);
	 
	// Find 32-bit FAT entry (record) index in current sector relating to cluster number 
	recordIdx = currentCluster - (FAT_sector_offset * 128);

	// Read Next Clusters value from Sector Buffer
	nextCluster = Get32BitWord(FAT_buffer, recordIdx*4);

	// Mask out MS 4 bits (its 28bit addressing)
	nextCluster &= 0x0FFFFFFF;		
				 
	// If 0x0FFFFFFF then end of cluster chain found
	if (nextCluster==0x0FFFFFFF) 
	   	return (0xFFFFFFFF); 
	else 
		 // Else return next cluster
		return (nextCluster);		
}

//Interprets the short name FAT32 record in buffer and fills the DIR_ENTRY structure
//NOTE: one FAT32 record is of 32 bytes.
void GetDirEntryFromBuffer(UI16* recordBuf, DIR_ENTRY *pDirEntry)
{
	//form name
	pDirEntry->Name[0] = Get8BitWord(recordBuf, 0);
	pDirEntry->Name[1] = Get8BitWord(recordBuf, 1);
	pDirEntry->Name[2] = Get8BitWord(recordBuf, 2);
	pDirEntry->Name[3] = Get8BitWord(recordBuf, 3);
	pDirEntry->Name[4] = Get8BitWord(recordBuf, 4);
	pDirEntry->Name[5] = Get8BitWord(recordBuf, 5);
	pDirEntry->Name[6] = Get8BitWord(recordBuf, 6);
	pDirEntry->Name[7] = Get8BitWord(recordBuf, 7);
	pDirEntry->Name[8] = Get8BitWord(recordBuf, 8);
	pDirEntry->Name[9] = Get8BitWord(recordBuf, 9);
	pDirEntry->Name[10] = Get8BitWord(recordBuf, 10);
	pDirEntry->Name[11] = 0;
	
	pDirEntry->Attr = Get8BitWord(recordBuf, 11);
	pDirEntry->NTRes = Get8BitWord(recordBuf, 12);
	pDirEntry->CreTimeTenth = Get8BitWord(recordBuf, 13);
	pDirEntry->CreTime = Get16BitWord(recordBuf, 14);
	pDirEntry->CreDate = Get16BitWord(recordBuf, 16);
	
	pDirEntry->LastAccessDate = Get16BitWord(recordBuf, 18);
	
	//form first cluster
	pDirEntry->FirstCluster = Get16BitWord(recordBuf, 20);
	pDirEntry->FirstCluster  = (pDirEntry->FirstCluster<<16) | (Get16BitWord(recordBuf, 26) & 0xFFFF);	

	pDirEntry->WriteTime = Get16BitWord(recordBuf, 22);
	pDirEntry->WriteDate = Get16BitWord(recordBuf, 24);
			
	pDirEntry->FileSize = Get32BitWord(recordBuf, 28);
}

//Interprets the long name FAT32 record in buffer and fills the 
//LFN_ENTRY structure
//NOTE: one FAT32 record is of 32 bytes.
void GetLfnEntryFromBuffer(UI16* recordBuf, LFN_ENTRY *pLfn)
{
	int i,j;

	pLfn->Ordinal = recordBuf[0] & 0xFF;
	
	//copy Name1 into name
	for(i=0; i<5; i++)
	{
		//copy unicode characters.
		pLfn->Name[i] = (recordBuf[i] >> 8) | (recordBuf[i+1] & 0xFF);
	}

	//copy Name2 into name
	for(j=7; j<(7+6) ; j++)
	{
		pLfn->Name[i++] = recordBuf[j];
	}
	
	//copy Name3 into name
	pLfn->Name[i++] = recordBuf[14];
	pLfn->Name[i++] = recordBuf[15];
	pLfn->Name[i] = 0;	//NULL terminator;
	
	pLfn->Attr = Get8BitWord(recordBuf, 11);
	pLfn->Checksum = Get8BitWord(recordBuf, 13);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -