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

📄 fs.c

📁 使用ISP1362芯片的USB_OTG参考设计源代码比较新的版本
💻 C
📖 第 1 页 / 共 5 页
字号:
		{
			num_of_large_read_clusters	= 0;
			size_of_post_read			= length;
		}
		else
		{
			num_of_large_read_clusters	= length / vpp->bytes_per_cluster;
			size_of_post_read			= length % vpp->bytes_per_cluster;
		}
	}

	if ( size_of_pre_read )
	{
		size	= fs_read_small( fp, buffer_ptr, size_of_pre_read );
		
		buffer_ptr			+= size_of_pre_read;
		size_of_total_read	+= size;
	}
	
	if ( num_of_large_read_clusters )
	{
		size	= fs_read_large( fp, buffer_ptr, num_of_large_read_clusters );
		
		buffer_ptr			+= (num_of_large_read_clusters * vpp->bytes_per_cluster);
		size_of_total_read	+= size;
	}
		
	if ( size_of_post_read )
	{
		size	= fs_read_small( fp, buffer_ptr, size_of_post_read );

		size_of_total_read	+= size;
	}

	return ( size_of_total_read );
}


static unsigned short fs_read_large( fs_FILE *fp, unsigned char *buffer_ptr, unsigned long clusters )
{
	unsigned short	target_cluster_N;
	unsigned short	base_cluster;
	unsigned short	next_cluster;
	unsigned short	read_bytes;
	unsigned short	read_sectors;
	unsigned short	total_read_bytes	= 0;
	unsigned short	continuous_length;
	unsigned short	i;
	volume_param	*vpp;

	vpp				= fp->volume_param_ptr;	

	target_cluster_N		= fp->current_file_data_position / vpp->bytes_per_cluster;
	
	//	cluster buffer control
	//	if the target cluster number does not match to read cluster number,
	//	update the current cluster index.
	
	continuous_length	= 0;
	
	do
	{
		if ( !continuous_length )
		{
			if ( fp->number_of_cluster_processed != (target_cluster_N + 1) )
			{
				if ( fp->current_cluster )
					fp->current_cluster		= read_FAT( fp->current_cluster );
				else
					fp->current_cluster		= fp->start_cluster;
			}
					
			base_cluster		= fp->current_cluster;
		}
		
		continuous_length++;
		clusters--;
		(fp->number_of_cluster_processed)++;
		
		next_cluster		= read_FAT( fp->current_cluster );

		if ( (fp->current_cluster == (next_cluster - 1)) && clusters )
		{
			fp->current_cluster		= next_cluster;
			continue;
		}
		
		read_bytes		= vpp->bytes_per_cluster  * continuous_length;
		read_sectors	= vpp->sector_per_cluster * continuous_length;

		if ( read_sectors != storage_read_sector( buffer_ptr, cluster_to_sector( base_cluster ), read_sectors ) )
		{
			//storage_unmount();
			return ( 0 );
		}

		buffer_ptr			+= read_bytes;
		total_read_bytes	+= read_bytes;
		
		fp->current_file_data_position	+= read_bytes;
		
		continuous_length	= 0;
	}
	while ( clusters );

	return ( total_read_bytes );
}


static unsigned short fs_read_small( fs_FILE *fp, unsigned char *buffer_ptr, unsigned short length )
{
	unsigned long			data_offset_in_cluster;
	unsigned short			target_cluster_N;
	unsigned long			remaining_file_size;
	unsigned short			remaining_size;
	unsigned short			reading_size;
	volume_param			*vpp;

	if ( !length )
		return ( 0 );

	//	get volume parameter pointer to refer volume information.
	//	this function needs information like sector size etc.
	vpp				= fp->volume_param_ptr;	
	
#ifdef ALWAYS_SMALL_READ

	//	calcurate file data size left
	
	if ( (fp->file_info).attributes & 0x10 )
		remaining_file_size		= vpp->bytes_per_cluster;	//	Possible problem : No bigger directory handling
	else
		remaining_file_size		= (fp->file_info).size - fp->current_file_data_position;

	//	limit file reading size to file size.
	//	to prevent over reading.
	length					= ((unsigned long)length < remaining_file_size) ? length : (unsigned short)remaining_file_size;

	//	set "remaining_size". 
	//	the "length" will kept to hold the expected data reading size untill this function end.
	//	it will be used to report read size as return value.
	
#endif // ALWAYS_SMALL_READ

	remaining_size			= length;

	while ( remaining_size )
	{
		//	find target cluster and ofset from data position in the file
	
		data_offset_in_cluster	= fp->current_file_data_position % vpp->bytes_per_cluster;
		target_cluster_N		= fp->current_file_data_position / vpp->bytes_per_cluster;
		
		//	cluster buffer control
		//	if the target cluster number does not match to read cluster number,
		//	update the current cluster index.
		
		if ( fp->number_of_cluster_processed != (target_cluster_N + 1) )
		{

			if ( fp->current_cluster )
			
				//	if it is not first time to load,
				//	get the cluster index from FAT information.

				fp->current_cluster		= read_FAT( fp->current_cluster );
			else
			
				//	if it is first time, set the index which was got in fs_open
				//	"fp->current_cluster" holds the index to the reading source cluster 
			
				fp->current_cluster		= fp->start_cluster;
		}

		//	check the index of reading source and buffered cluster.

		if (fp->current_cluster != fp->buffered_cluster)
		{
			//	if those are different, read from sectors to file buffer
		
			if ( vpp->sector_per_cluster != storage_read_sector( fp->cluster_buffer_pointer, cluster_to_sector( fp->current_cluster ), vpp->sector_per_cluster ) )
			{
				//storage_unmount();
				return ( 0 );
			}
			//	update to show the current buffered cluster information

			fp->buffered_cluster	= fp->current_cluster;
			
			//	count up, the counter to count the cluster has been read.
			
			(fp->number_of_cluster_processed)++;
		}


		//	calculate the readout size. 
		//	The data can be readout from the file data position to cluster end.
	
		reading_size	= (vpp->bytes_per_cluster < (remaining_size + data_offset_in_cluster)) ? (vpp->bytes_per_cluster - data_offset_in_cluster) : remaining_size;
		
		//	read out : 
		//	copy data from file buffer to user buffer for size of reading_size.
		
		//mprintf( LIGHTGRAY, CONTINUE, "remaining_size %d   reading %d   n_cluster %u   offset %ld   c 0x%04X\r\n", remaining_size, reading_size, target_cluster_N, data_offset_in_cluster, fp->current_cluster );
		fs_data_copy( buffer_ptr, (fp->cluster_buffer_pointer) + data_offset_in_cluster, reading_size );
		
		//	update pointers
		//	when the remaining size is not zero, the loop will kepp execution.
		
		fp->current_file_data_position	+= reading_size;
		buffer_ptr						+= reading_size;
		remaining_size					-= reading_size;
	}

	return ( length - remaining_size );
}


//////////
//////////	"write" file write
//////////
//#define ALWAYS_SMALL_WRITE
#ifdef ALWAYS_SMALL_WRITE
#else
unsigned short fs_write( fs_FILE *fp, unsigned char *buffer_ptr, unsigned short length )
{
	unsigned short	size_of_pre_write;
	unsigned short	num_of_large_write_clusters;
	unsigned short	size_of_post_write;
	unsigned short	data_offset_in_cluster;
	unsigned short	write_clusters;
	unsigned short	size;
	unsigned short	size_of_total_write	= 0;
	unsigned long	remaining_file_size;

	volume_param	*vpp;

	vpp						= fp->volume_param_ptr;	

	if ( length < vpp->bytes_per_cluster )
	{
		size_of_pre_write			= length;
		num_of_large_write_clusters	= 0;
		size_of_post_write			= 0;
	}
	else
	{
		data_offset_in_cluster		= fp->current_file_data_position % vpp->bytes_per_cluster;
		size_of_pre_write			= data_offset_in_cluster ? (vpp->bytes_per_cluster - data_offset_in_cluster) : 0;
		length					   -= size_of_pre_write;
		
		if ( length < vpp->bytes_per_cluster )
		{
			num_of_large_write_clusters	= 0;
			size_of_post_write			= length;
		}
		else
		{
			num_of_large_write_clusters	= length / vpp->bytes_per_cluster;
			size_of_post_write			= length % vpp->bytes_per_cluster;
		}
	}

	if ( size_of_pre_write )
	{
		size	= fs_write_small( fp, buffer_ptr, size_of_pre_write );
		
		buffer_ptr			+= size_of_pre_write;
		size_of_total_write	+= size;
	}
	
	if ( num_of_large_write_clusters )
	{
		size	= fs_write_large( fp, buffer_ptr, num_of_large_write_clusters );
		
		buffer_ptr			+= (num_of_large_write_clusters * vpp->bytes_per_cluster);
		size_of_total_write	+= size;
	}
		
	if ( size_of_post_write )
	{
		size	= fs_write_small( fp, buffer_ptr, size_of_post_write );

		size_of_total_write	+= size;
	}

	return ( size_of_total_write );
}


static unsigned short fs_write_large( fs_FILE *fp, unsigned char *buffer_ptr, unsigned long clusters )
{
	unsigned short	target_cluster_N;
	unsigned short	base_cluster;
	unsigned short	next_cluster;
	unsigned short	write_bytes;
	unsigned short	write_sectors;
	unsigned short	total_write_bytes	= 0;
	unsigned short	continuous_length;
	unsigned short	i;
	volume_param	*vpp;

	vpp						= fp->volume_param_ptr;	
	fp->buffered_cluster	= NULL;

	target_cluster_N		= fp->current_file_data_position / vpp->bytes_per_cluster;
	
	//	cluster buffer control
	//	if the target cluster number does not match to write cluster number,
	//	update the current cluster index.
	
	continuous_length	= 0;
	
	do
	{
		if ( !continuous_length )
		{
			if ( fp->number_of_cluster_processed != (target_cluster_N + 1) )
			{
				if ( fp->current_cluster )
				{
					if ( !(next_cluster		= find_free_cluster( fp->current_cluster )) )
						return ( total_write_bytes );
					
					write_FAT( fp->current_cluster, next_cluster );
					write_FAT( next_cluster,        0xFFFF       );		
					fp->current_cluster		= next_cluster;
				}
				else
				{
					fp->current_cluster			= fp->start_cluster;
					(fp->file_info).cluster		= fp->start_cluster;
					
					write_FAT( fp->current_cluster, 0xFFFF       );		
				}
			}
					
			base_cluster		= fp->current_cluster;
		}
		
		continuous_length++;
		clusters--;
		(fp->number_of_cluster_processed)++;
		
		if ( !(next_cluster		= find_free_cluster( fp->current_cluster )) )
			return ( total_write_bytes );

		if ( (fp->current_cluster == (next_cluster - 1)) && clusters )
		{
			write_FAT( fp->current_cluster, next_cluster );
			write_FAT( next_cluster,        0xFFFF       );		
			fp->current_cluster		= next_cluster;
			
			continue;
		}
		
		write_bytes		= vpp->bytes_per_cluster  * continuous_length;
		write_sectors	= vpp->sector_per_cluster * continuous_length;

		if ( write_sectors != storage_write_sector( buffer_ptr, cluster_to_sector( base_cluster ), write_sectors ) )
		{
			//storage_unmount();
			return ( 0 );
		}
		
		write_FAT( fp->current_cluster, 0xFFFF );		

		buffer_ptr			+= write_bytes;
		total_write_bytes	+= write_bytes;
		
		fp->current_file_data_position	+= write_bytes;
		(fp->file_info).size			+= write_bytes;

		continuous_length	= 0;
	}
	while ( clusters );

	return ( total_write_bytes );
}
#endif 	//ALWAYS_SMALL_WRITE



#ifdef ALWAYS_SMALL_WRITE
unsigned short fs_write( fs_FILE *fp, unsigned char *buffer_ptr, unsigned short length )
#else
static unsigned short fs_write_small( fs_FILE *fp, unsigned char *buffer_ptr, unsigned short length )
#endif
{
	unsigned long			data_offset_in_cluster;
	unsigned short			target_cluster_N;
	unsigned short			next_cluster;
	unsigned short			remaining_size;
	unsigned short			writing_size;
	volume_param			*vpp;

	if ( !length )
		return ( 0 );
		
	vpp				= fp->volume_param_ptr;

	remaining_size	= length;

	while ( remaining_size )
	{
		data_offset_in_cluster	= fp->current_file_data_position % vpp->bytes_per_cluster;
		target_cluster_N		= fp->current_file_data_position / vpp->bytes_per_cluster;
				
//		mprintf( LIGHTCYAN, CONTINUE, "remaining_size=%u  data_offset_in_cluster=%lu  target_cluster_N=%u\r\n", remaining_size, data_offset_in_cluster, target_cluster_N );
//		mprintf( LIGHTCYAN, CONTINUE, "fp->start_cluster=%u  fp->number_of_cluster_processed=%u  fp->current_cluster=%u  fp->buffered_cluster=%u\r\n", fp->start_cluster, fp->number_of_cluster_processed, fp->current_cluster, fp->buffered_cluster );

		if ( fp->number_of_cluster_processed != (target_cluster_N + 1) )
		{
			//	if the data on the boundary, new cluster will be allocated

			if ( fp->current_cluster )
			{
				//	if the new cluster required, search the open cluster from current 
				//	cluster.
#if 0			
				if ( !(fp->current_cluster		= find_free_cluster( fp->current_cluster )) )
					return ( length - remaining_size );

#else

				if ( !(next_cluster		= find_free_cluster( fp->current_cluster )) )
					return ( length - remaining_size );
				
				write_FAT( fp->current_cluster, next_cluster );
				write_FAT( next_cluster,        0xFFFF       );		
				fp->current_cluster		= next_cluster;

#endif
			}
			else
			{
				//	the first cluster allocation is done by file open function.
				//	this action just doing the copying the cluster number to current.
				
				fp->current_cluster			= fp->start_cluster;
				(fp->file_info).cluster		= fp->start_cluster;
			}
		}
		

		//	if the curent cluster index and buffered cluster index are different 
		if (fp->current_cluster != fp->buffered_cluster)
		{
			//	if the buffered data already exist
			if ( fp->buffered_cluster )
			{
#define FAST_WRITE
#ifdef FAST_WRITE
				if ( vpp->sector_per_cluster != storage_write_sector( fp->cluster_buffer_pointer, cluster_to_sector( fp->buffered_cluster ), vpp->sector_per_cluster ) )
					return ( 0 );
#else
				flush_FILE_write_buffer( fp );
#endif
				//	set next cluster value to current cluster entry. links the clusters (FATs).
				write_FAT( fp->buffered_cluster, fp->current_cluster );
			}

			write_FAT( fp->current_cluster, 0xFFFF );

			fp->buffered_cluster	= fp->current_cluster;
			(fp->number_of_cluster_processed)++;

⌨️ 快捷键说明

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