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

📄 hdd driver.c

📁 使用单片机 读写SD卡 带FAT16功能 PIC18f452
💻 C
📖 第 1 页 / 共 3 页
字号:
		lnf_tiles=buff[0] & 0b00111111;
		bytes_read=bytes_read+lnf_tiles*32;
		if(bytes_read>cluster_size_bytes){
			// compute next cluster address next_cluster_ptr must be valid
			// assigns this_cluster_ptr

			dir_addr_ptr=cluster_addr(fnbr,NEXT_CLUSTER);
			if (dir_addr_ptr==0xFFFFFF) return (22);
			bytes_read=bytes_read-cluster_size_bytes;
			dir_addr_ptr=dir_addr_ptr+bytes_read;
		}
		else{
			dir_addr_ptr=dir_addr_ptr+lnf_tiles*32;
		}

		//advance over the lnf tiles
		/// test to see if we need next cluster in chain
		if (read_BLOCK(dir_addr_ptr,buff)==false) return(31);
		/// !!! may read into next sector
	}


	/// check out the standard DOS tile
	#IF MMC_OPEN_TRACE
		printf("\n\r fname[%s] level=%u \n\r",file_name,level);
		for (j=0;j<11;j++)printf("%c",buff[j]);
	#ENDIF
	if(strncmp(buff,file_name, 11)==0){ ///8.3 file name ex "FILE EXT" "FOLDER "
		// we have a file type or a sub directory(folder)
		// so we get the starting cluster number
		attribute=buff[11];

		file[fnbr].root_cluster_ptr=make16(buff[27],buff[26]);/// assign initial cluster ptr
		/// if it is not a directory
		/// it points to the begining of the file
		/// cluster chain



		if ((attribute & 0b00010000)>0)directory=true;
		else directory=false;
		if ((attribute & 0b00100000)>0 || attribute==0){
			archive=true; //// we have our file

			file[fnbr].size=make32(buff[31],buff[30],buff[29],buff[28]);
			file[fnbr].dir_addr_ptr=dir_addr_ptr; ///save address of this files tile
			/// assign global value
		}
		else archive=false;



		goto match_found;
		// goto fill_table; // we have a match
	}
	next_tile:
	bytes_read=bytes_read+32;
	if(bytes_read > cluster_size_bytes){
		/// requires a valid next=next_cluster_ptr
		// compute next cluster address and assign this cluster
		dir_addr_ptr=cluster_addr(fnbr,NEXT_CLUSTER);
		if (dir_addr_ptr==0xFFFFFF) return (23);
		bytes_read=bytes_read-cluster_size_bytes;
		dir_addr_ptr=dir_addr_ptr+bytes_read;
	}
	else{
		dir_addr_ptr=dir_addr_ptr+32;
	}


	dir_addr_ptr=dir_addr_ptr+32;

	if (read_BLOCK(dir_addr_ptr,buff)==false) return(32);
	goto tile_decode;

	match_found:
	///// if we have a sub directory we need to cycle down a level
	if (directory==true) {
		// compute the sub directory address
		// compute this cluster address this_cluster_ptr must be valid
		dir_addr_ptr=cluster_addr(fnbr,ROOT_CLUSTER); /// set physical addr of starting cluster
		#IF MMC_OPEN_TRACE
			printf("\n\r next_cluster_ptr=%lu \n\r ",file[fnbr].next_cluster_ptr);
		#ENDIF
		//printf("\n\r dir_addr_ptr=%lu",dir_addr_ptr);
		// dir_addr_ptr=((int32)cluster_table[0]-(int32)2)*(int32)cluster_size_bytes+
		// data_area_address;
		level++;
		goto read_directory;
	}


	// note record length must divide into 512 to align properly
	if (rec_length<2) return(12);



	/// get the initial file_addr_ptr

	file[fnbr].addr_ptr=cluster_addr(fnbr,ROOT_CLUSTER);
	file[fnbr].offset=0; //init bytes read from beginning of open file
	file[fnbr].cluster_offset=0; //init bytes read to beginning of the current cluster
	file[fnbr].rec_size=(int32)rec_length; /// assign file record size
	#IF MMC_OPEN_TRACE
		printf("root_cluster=%lu \n\r",file[fnbr].root_cluster_ptr);
	#ENDIF

	//printf("\n\r fopen %u rec size=%lu",fnbr,file[fnbr].rec_size);

	if(set_BLOCKLEN(file[fnbr].rec_size)==false) return(13);

	return(0);
}

//////////////////////////////////////////////////////////////////////////////////
////////////////////////////// FILE READ ///////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
#separate
int file_read(int8 fnbr,char *buff){
	int32 address;
	int32 nxt_cluster;
	//// MMC allows a read to start and stop at any address but this file system
	//// imposes a record size restriction the record size must divide into the
	/// 512 block to allow writing of the records
	/// rec_size must align with cluster boundary 2048 ...must be a divisor of 2048
	/// find the cluster containing the offset
	/// buff must be at least the size of the recordsize requested in the File open

	//printf("foffset=%lu coffset=%lu ",file[fnbr].offset,file[fnbr].cluster_offset);////$$$$

	if ( file[fnbr].offset>=file[fnbr].size) return(10); /// already beyond eof

	if ( file[fnbr].offset + (int32) file[fnbr].rec_size > file[fnbr].cluster_offset + (int32) cluster_size_bytes){
		#IF MMC_READ_TRACE
			printf("adv to next cluster");
		#ENDIF
		/// need to advance to the next cluster
		nxt_cluster=cluster_addr(fnbr,NEXT_CLUSTER);
		if ( nxt_cluster!=0XFFFFFFFF) file[fnbr].addr_ptr=nxt_cluster;
		else return(11); /// last cluster in file reached

		file[fnbr].cluster_offset=file[fnbr].cluster_offset+(int32)cluster_size_bytes; //foffset is the byte offset within the file
		//that file_addr_ptr points to
	}
	address=file[fnbr].addr_ptr+file[fnbr].offset-file[fnbr].cluster_offset;
	#IF MMC_READ_TRACE
		//printf("\n\r offset=%lu",cluster_offset);
		printf("\n\r data_area_address=%lu",address);
		printf("\n\r cluster_size_bytes=%lu",cluster_size_bytes);

		//printf("\n\r file_addr_ptr=%lu",file_addr_ptr);
	#ENDIF

	if (read_BLOCK(address,buff)==false)return(12); /// read block into buff

	if ( file[fnbr].offset+file[fnbr].rec_size< file[fnbr].size ) file[fnbr].offset=file[fnbr].offset+file[fnbr].rec_size;
	else{ /// end of file
		#IF MMC_READ_TRACE
			printf("eof size=%lu",file[fnbr].size);
		#ENDIF
		buff[ file[fnbr].size-file[fnbr].offset]=0; /// short record
		file[fnbr].offset=file[fnbr].size;
		return(255); //eof
	}
	return(0);
}


//////////////////////////////////////////////////////////////////////////////////
////////////////////////////// WRITE FILE /////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
#separate
int file_write(int8 fnbr,int *buff){
	//// buff size must be at least the recordsize requested in File open
	//// the record is updated only chars beyond rec_size are ignored
	/// set up for write
	/// A MMC write is restricted it must be for a block and allign on block boundaries
	/// blocklen must be exactly 512 and start address must be the begining of a
	/// sector
	/// the buff could potentially span a sector and or span a block(512) boundary
	/// ex there could be 1byte left in a block and 1 byte lect in a sector
	// if the block is the last block in the sector
	/// worst case we could write to two blocks and need a new sector
	int32 address,nxt_cluster;

	int16 in_cluster_size,out_cluster_size;
	int8 appending_flag;
	appending_flag=0;
	if (file[fnbr].offset + file[fnbr].rec_size>=file[fnbr].size) appending_flag=1;


	/// find the cluster containing the offset
	if ( file[fnbr].offset+file[fnbr].rec_size>=file[fnbr].cluster_offset + cluster_size_bytes){
		#IF MMC_WRITE_TRACE
			printf("spanning cluster \n\r");
		#ENDIF
		/// spans the current cluster so we split the write
		in_cluster_size=file[fnbr].cluster_offset+cluster_size_bytes-file[fnbr].offset;
		/// bytes from start of file to end of this cluste- bytes into the file
		out_cluster_size=file[fnbr].rec_size - in_cluster_size;
		#IF MMC_WRITE_TRACE
			printf("write>> spanning cluster inside=%lu outside=%lu \n\r",in_cluster_size,out_cluster_size);
		#ENDIF
		address=file[fnbr].addr_ptr+file[fnbr].offset - file[fnbr].cluster_offset;
		// physical address=
		// physical address of the cluster +offset from begining of file
		// - offset from the begining of file for the byte at the begining of the cluster
		#IF MMC_WRITE_TRACE
			printf("write file>>cluster=%lu in clstr addr=%lu",file[fnbr].this_cluster_ptr,address);
		#ENDIF
		//// address=physical offset of this cluster +bytes into this cluster
		if(write_BLOCK(address,buff,in_cluster_size)==false)return(81); //// write first chunk



		/// allocate the next cluster
		nxt_cluster=cluster_addr(fnbr,NEXT_CLUSTER); ///physical address of file data that the
		/// specific cluster indexes
		#IF MMC_WRITE_TRACE
			printf("nxt_cluster=%lu",nxt_cluster);
		#ENDIF

		if ( nxt_cluster==0xFFFFFFFF){
			#IF MMC_WRITE_TRACE
				printf("updating FAT");
			#ENDIF
			//// FAT2 is an identical copy of FAT1
			file_new_cluster(fnbr,1); /// a new cluster is allocated in FAT1
			file_new_cluster(fnbr,2); /// a new cluster is allocated in FAT2
			nxt_cluster=cluster_addr(fnbr,NEXT_CLUSTER); ///physical address of file data that the
			#IF MMC_WRITE_TRACE
				printf("\n\r write>>nxt_cluster addr=%lu this clstr=%lu next=%lu",nxt_cluster,file[fnbr].this_cluster_ptr,file[fnbr].next_cluster_ptr); /// specific cluster indexes
			#ENDIF
		}

		file[fnbr].addr_ptr =nxt_cluster;
		file[fnbr].cluster_offset=file[fnbr].cluster_offset + cluster_size_bytes; //foffset is the byte offset within the file
		//that file_addr_ptr points to
		address=file[fnbr].addr_ptr + file[fnbr].offset - file[fnbr].cluster_offset + in_cluster_size;
		#IF MMC_WRITE_TRACE
			printf("out addr=%lu,out size=%lu",address,out_cluster_size);
		#ENDIF
		if(write_BLOCK(address,&buff[in_cluster_size],out_cluster_size)==false)return(82); /// write block pads with 0x00 to end of sector
	}// end of spanned cluster
	else{
		/// within the current cluster
		address=file[fnbr].addr_ptr+file[fnbr].offset - file[fnbr].cluster_offset;



		if(write_BLOCK(address,buff,file[fnbr].rec_size)==false)return(84); /// write block pads with 0x00 to end of sector

	}
	if(appending_flag==1) {
		/// if appended we need to up date the file size
		file[fnbr].size=file[fnbr].size + file[fnbr].rec_size; /// add one record
		address=file[fnbr].dir_addr_ptr+28; /// file size is offset 28 in tiles
		#IF MMC_WRITE_TRACE
			printf("new file size=%lu",file[fnbr].size);
		#ENDIF
		buff[0]=make8(file[fnbr].size,0);
		buff[1]=make8(file[fnbr].size,1);
		buff[2]=make8(file[fnbr].size,2);
		buff[3]=make8(file[fnbr].size,3);
		MMC_dir_protected=false;
		if(write_BLOCK(address,buff,4)==false)return(85);
	}
	if(set_BLOCKLEN(file[fnbr].rec_size)==false) return(86); /// reset to original rec_size
	return(0);
}


#separate
int file_set(int fnbr,int32 offset){
	/// file open sets the offset to the begining offset=0
	/// this sets the offset within the file ...offset of 0 is a reset

	if(offset>=file[fnbr].size) return(71);

	file[fnbr].offset=offset; //// overwrite the existing offset
	file[fnbr].next_cluster_ptr=file[fnbr].root_cluster_ptr; /// set current ptr to beginning
	file[fnbr].cluster_offset=0;
	// move the cluster to the one containing the offset

	while ( offset>cluster_size_bytes ){

		file[fnbr].addr_ptr=cluster_addr(fnbr,NEXT_CLUSTER);
		file[fnbr].cluster_offset+=cluster_size_bytes; //foffset is the byte offset within the file
		if (offset-cluster_size_bytes >0) offset= offset - cluster_size_bytes;

	}
	return(0);
}


#separate
int file_new_cluster(int8 fnbr,int8 mode){ ///////////// this does identical writes to either the FAT1 and FAT2 sectors
	int16 eof_cluster;

	char buff[2],tmp_buff[2];
	int32 address;
	int32 fat_address;
	int16 slot;
	/// an unused cluster has the value 0x0000 as its next cluster ptr
	/// a used cluster has either 0xFFFF meaning last in chain
	/// or a valid cluster displacement in the FAT1 amd FAT2 area
	/// to append a cluster the 0XFFFF needs to be replaced by the appended
	/// cluster location and the appended locations data (next ptr) needs to be set to 0XFFFF



	eof_cluster=file[fnbr].this_cluster_ptr;
	#IF MMC_NEW_CLUSTER
		printf("the cluster with eof (FFFF)=%lu \n\r",eof_cluster);
	#ENDIF

	slot=0;
	if(set_BLOCKLEN((int32)2)==false)return(false); // force blocklen to 2
	/// use global address of FAT1 assigned by INIT
	if (mode==2)fat_address=fat2_address;
	else fat_address=fat1_address;
	address=fat_address;

	#IF MMC_NEW_CLUSTER
		printf("mode=%u FAT addr=%lu \n\r",mode,address);
	#ENDIF

	do{
		if(read_block(address,buff)==false) return(false) ;
		slot=slot+1;
		address=address+2;
		//printf(" slot %lu =%2x %2x",slot,buff[0],buff[1]);
	}
	while (buff[0]!=0 || buff[1]!=0);

	address=address-2; // correct for over step
	slot=slot-1;


	#IF MMC_NEW_CLUSTER
		printf("slot=%lu address=%lu",slot,address);
	#ENDIF

	/// found an unused cluster
	tmp_buff[0]=0xFF;tmp_buff[1]=0xFF; /// stamp it as last
	MMC_dir_protected=false; /// allow writes to the protected areas
	if(write_block(address,tmp_buff,2)==false ) return(false);

	/////////////////////////////////////////////
	/// update prev cluster with 0xFFFF in it
	tmp_buff[1]=make8(slot,1);
	tmp_buff[0]=make8(slot,0);
	if (mode==1){
		//// update the file info
		file[fnbr].next_cluster_ptr=slot;
		#IF MMC_NEW_CLUSTER
			printf("cluster %lu was updated to point to %lu",file[fnbr].this_cluster_ptr,file[fnbr].next_cluster_ptr);
		#ENDIF
	}
	/// compute physical address of the current cluster
	MMC_dir_protected=false; /// allow writes to the protected areas
	if(write_BLOCK(fat_address+(file[fnbr].this_cluster_ptr)*2,tmp_buff,2)==false) return(33);
	if(set_BLOCKLEN((int32)file[fnbr].rec_size)==false)return(false); // reset blocklen

	return(true);
}


signed int strncmp(char *s1, char *s2, int n){
	for (; n > 0; s1++, s2++, n--){
		if (*s1 != *s2) return((*s1 <*s2) ? -1: 1);
		else if (*s1 == '\0') return(0);
	}
	return(0);
}

⌨️ 快捷键说明

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