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

📄 hdd driver.c

📁 使用单片机 读写SD卡 带FAT16功能 PIC18f452
💻 C
📖 第 1 页 / 共 3 页
字号:


	if (r1==0x00) goto get_token ; // we can read data payload

	return(false);
	get_token:
	for(i=0;i<16;i++)if (SPI_READ(0xFF)==0xFE) goto read_CSD; // read token $FE
	return(false);
	read_CSD:
	//for(i=0;i<18;i++) s[i]=SPI_READ(0xFF);

	return(true);
}


#separate
int write_BLOCK( int32 address,char *buff,int16 size)
{
	/// low level write ....MMC restriction is that exactly 512 bytes must be written
	/// so a 512 byte section is read in starting at address the first (size) bytes
	/// are over written with the new data and the updated 512 bytes written back
	/// the starting address of the block that contains the requeseted address
	///
	/// the data may span a block if so it is split and two writes are done
	/// so as to maitain MMC 512 write boundary restrictions

	int r1,a,b,c,d;
	int16 i,blk_offset,bytes_posted;
	char tmp_buff[512];
	int32 block_address;

	#if MMC_WRITE_BLOCK_TRACE
		printf("addr=%lu",address);
	#endif

	a=make8(address,3);
	b=make8(address,2);
	c=make8(address,1);
	c=c & 0b11111110;
	d=0;
	block_address=make32(a,b,c,d); //// address int divided by 512
	#if MMC_WRITE_BLOCK_TRACE
		printf("wb>> size=%lu payload=",size);
		for(i=0;i<size;i++)printf("%c",buff[i]);
	#endif

	/// first set up the block size to 512
	if(set_BLOCKLEN((int32)512)==false) return(false); // sets global block_size

	if(block_size!=512) return(false);
	bytes_posted=0; /// no data updated yet

	////////////////////////////////////////////////
	next_block: /// loop back here for second block
	////////////////////////////////////////////////
	#if MMC_WRITE_BLOCK_TRACE
		printf("\n\r blk addr=%lu \n\r",block_address);
	#endif

	if((block_address < data_area_address) && MMC_dir_protected) return(false);

	MMC_dir_protected=true;
	#if MMC_WRITE_BLOCK_TRACE
		printf("read blk");
	#endif
	/// first read in the existing block
	if(read_block(block_address,tmp_buff)==false) return(false) ;



	/// now update the block with new data
	blk_offset=(address - block_address); /// offset within the block
	#if MMC_WRITE_BLOCK_TRACE
		printf("blk_offset=%lu size=%lu",blk_offset,size);
	#endif

	if( blk_offset + size > 512 ){
		// data spans the block so write to end of block first

		#if MMC_WRITE_BLOCK_TRACE
			//// original data
			printf("\n\r spans wb=");
			for(i=blk_offset;i<512;i++)printf("%c",tmp_buff[i]);
		#endif

		for (i=blk_offset;i < 512;i++)tmp_buff[i]=buff[i-blk_offset];

		#if MMC_WRITE_BLOCK_TRACE
			/// updated data
			printf("\n\r spans wb*=");
			for(i=blk_offset;i<512;i++)printf("%c",tmp_buff[i]);
		#endif

		bytes_posted=512-blk_offset; /// wrote from offset to end of block

		#if MMC_WRITE_BLOCK_TRACE
			printf("\n\r posted=%lu",bytes_posted);
		#endif

	}
	else{
		//original or remaining spanned block data fits in next block or original block

		#if MMC_WRITE_BLOCK_TRACE
			printf(" blk offset=%lu",blk_offset);
			/// original data
			printf("\n\r wb=");
			for(i=blk_offset;i<blk_offset+size;i++)printf("%c",tmp_buff[i]);
		#endif

		for (i=blk_offset;i<blk_offset+ size;i++)tmp_buff[i]=buff[bytes_posted+i-blk_offset];

		#if MMC_WRITE_BLOCK_TRACE
			/// updated data
			printf("\n\r wb*=");
			for(i=blk_offset;i<blk_offset+size;i++)printf("%c",tmp_buff[i]);
		#endif

		bytes_posted=size;

		#if MMC_WRITE_BLOCK_TRACE
			printf("\n\r posted=%lu",bytes_posted);
		#endif

	}

	///////////////////////////////////
	/////////// write out the block
	//////////////////////////////////
	#if MMC_WRITE_BLOCK_TRACE
		printf("wb>> writing block %lu",block_address);
	#endif
	r1=mmc_cmd(0x58,block_address,16,0x00,0x40);


	if (r1==0x00) goto send_token ; // we can send data payload
	if (r1==0x40) goto invalid;


	return(false);
invalid:
	printf("\n\r write block err %2X\n\r",r1);
	return(false);
	send_token:
	SPI_READ(0xFE);

	for (i=0;i < 512;i++) {

		SPI_READ(tmp_buff[i]); /// send payload
	}


	SPI_READ(0xFF); // send dummy chcksum
	SPI_READ(0xFF);
	r1=SPI_READ(0xFF);
	for( i=0;i<0x0fff;i++) {
		r1=SPI_READ(0xFF);// digest prior operation
		if (r1!=0x00) break;
	}

	if(size > bytes_posted){
		/// data spanned block so we need to upadte next block as well
		size=size-bytes_posted;
		block_address=block_address+512;/// advance a block

		address=address+bytes_posted; /// move address ptr forward

		goto next_block;
	}


	return(true);
}


#separate
void dump_block(){
	int in_buff[12],c,i,j;
	int32 read_address;
	char buff[MMC_BUFF_SIZE+1];
	for(i=0;i<12;i++)in_buff[i]=0;
	printf("\n\r Input Start address:");
	j=0;
	do {
		c=getc();
		in_buff[j++]=c;
		putc(c);
	}
	while(c!=13);
	in_buff[j-1]=0;

	read_address=atoint32(in_buff);
	if (read_BLOCK(read_address,buff)==true){
		printf(" BLOCK\n\r");
		for(j=0;j<MMC_BUFF_SIZE;j=j+8){
			printf("%4LX ",read_address+j);
			for(i=0;i<8;i++)printf(" %2X",buff[i+j]);
			printf("\n\r");

		}
	}
	else printf("\n\r read_BLOCK failed");

}


#separate
int32 cluster_addr(int fnbr,int mode){
	int32 address;
	char buff[2]; //// buffer for 2 byte ptrs
	///// returns the physical address in the data area of the data pointed to by either the
	///// root cluster or the next cluster in the chain
	/////
	///// if ROOT_CLUSTER is called then this routine returns the address of the first cluster
	///// and assigns this_cluster_ptr and next_cluster_ptr
	/////
	///// if NEXT_CLUSTER is called then this routine returns the address of the next cluster
	///// using the existing next_cluster ptr number
	///// and moves the existing next_cluster ptr number into this_cluster
	///// and assigns the new next cluster ptr number (FFFF) if at the end of chain
	///// if NEXT_CLUSTER is called and the next_cluster_ptr number is FFFF
	///// an address of FFFFFFFF is returned

	///// uses the globals cluster_size_bytes,data_area_address
	//// file struct has the base=root cluster ptr, current=this cluster ptr ,next =cluster chain ptr

	//// !!!! a call with NEXT_cluster must have a valid next_cluster_ptr value
	//// !!!! a call to THIS CLUSTER must have a valid this_cluster_ptr

	//// !!!! Fopen logic considers the cluster prt in the directory tile
	//// to be a next=next_cluster_ptr so NEXT_CLUSTER is used to calc the physical address
	//// of the first root cluster this also assigns the current=this_cluster_ptr
	/// and fetches the next cluster prt
	////
	#IF MMC_CLUSTER_TRACE // if true prints to serial port
		printf("\n\r cluster addr>> next_cluster_ptr= %lu this_cluster=%lu \r\n",file[fnbr].next_cluster_ptr,file[fnbr].this_cluster_ptr);
	#ENDIF
	if (mode==NEXT_CLUSTER){
		///access the next cluster in the chain
		/// requires a valid this_cluster_ptr number and a valid next_cluster_ptr number

		if(file[fnbr].next_cluster_ptr==0xFFFF){
			#IF MMC_CLUSTER_TRACE // if true prints to serial port
				printf("last cluster");
			#ENDIF
			address=0XFFFFFFFF;
		}
		else{
			if(set_BLOCKLEN((int32)2)==false) return(35); /// set up to read 2 bytes
			if(read_BLOCK(fat1_address+(file[fnbr].next_cluster_ptr)*2,buff)==false) return(33);
			file[fnbr].this_cluster_ptr=file[fnbr].next_cluster_ptr; // update current with prev next in chain
			file[fnbr].next_cluster_ptr=make16(buff[1],buff[0]); /// update next in chain

			address=((int32)file[fnbr].this_cluster_ptr-(int32)2)*(int32)cluster_size_bytes+
			data_area_address;

		}
	}
	if (mode==ROOT_CLUSTER){
		//// root_cluster_ptr was assigned from the file tile in fopen
		file[fnbr].this_cluster_ptr=file[fnbr].root_cluster_ptr;
		if(set_BLOCKLEN((int32)2)==false) return(35); /// set up to read 2 bytes
		if(read_BLOCK(fat1_address+(file[fnbr].this_cluster_ptr)*2,buff)==false) return(33);
		file[fnbr].next_cluster_ptr=make16(buff[1],buff[0]); /// update next in chain
		address=((int32)file[fnbr].this_cluster_ptr-(int32)2)*(int32)cluster_size_bytes+
		data_area_address;

	}

	// printf("clust addr call fnbr=%u blk_size=%lu",fnbr,file[fnbr].rec_size);

	if(set_BLOCKLEN(file[fnbr].rec_size)==false) return(37); /// reset to original rec_size

	#IF MMC_CLUSTER_TRACE // if true prints to serial port
		printf("\n\r cluster addr>> next_cluster_ptr*= %lu this_cluster*=%lu \r\n",file[fnbr].next_cluster_ptr,file[fnbr].this_cluster_ptr);
	#ENDIF return(address);
}


///////////////////////////////////////////////////////////////////////////////////
///////////////////////// OPEN FILE ///////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
#separate
int open_file(int fnbr,char *fname,int16 rec_length){
	int32 dir_addr_ptr;
	int16 bytes_read;
	int i,ptr1,ptr2,lnf_tiles,j;
	char file_name[12];
	int attribute,directory,archive;
	char tmp;
	char buff[32]; //// buffer for 32 byte tiles

	int level; /// level in the directory structure 0 is top
	/////// directory is searched and if file is found

	//////
	////// init_MMC(tries) must be called first
	////// uses globals root_dir_address

	//start by searching the root directory for folder or file

	/// assign an inital next_cluster_ptr in the root directory
	file[fnbr].next_cluster_ptr=0;
	file[fnbr].this_cluster_ptr=0;

	dir_addr_ptr=root_dir_address;
	file_name[11]=0;
	level=0;
	ptr1=0;
	ptr2=0;
	bytes_read=0; //// byte read so far in this cluster

	read_directory:
	/// extract the directory levels(folders)
	while ((fname[ptr2]!='/') && (fname[ptr2]!='\\') && (fname[ptr2]!='\0') && (fname[ptr2]!='.') ){
		// a dos directory (folder) name can not exceed 8 chars
		if ((ptr2-ptr1)>7) return (20);
		ptr2++;
	}
	#IF MMC_OPEN_TRACE
		printf("\n\r fopen ptr1=%u ptr2=%u ",ptr1,ptr2);
	#ENDIF

	if (ptr2==0){ ptr2=1;ptr1=1;goto read_directory;} /// skip a leading '/' or '\'
	if ((ptr2-ptr1)==0) return (21);

	// ptr1 is the chars processed so far
	// ptr2 is the position of '/' or '\' or '.' or '\0'
	// prepare the file or directory name fomat is cccccccceee
	// c is a valid letter or blank eee is extension or blank
	// a directory name is 'cccccccc ' a file 'cccccccceee' always 11 chars
	for(i=0;i<11;i++)file_name[i]=32;//blank
	file_name[11]=0;
	i=0;
	while(ptr1<ptr2){
		// extract the name

		tmp=fname[ptr1];
		tmp=TOUPPER(tmp);
		file_name[i]=tmp;
		ptr1++;i++;
	}
	if(fname[ptr2]=='.'){
		// extract the extension
		i=8;
		while((fname[ptr1]!='\0') && (i<12)){
			ptr1++;
			tmp=fname[ptr1];
			file_name[i]=TOUPPER(tmp);
			i++;
		}
	}
	ptr1++;
	ptr2=ptr1; // advance over the '\' or '/' so next pass starts correctly
	if (block_size!=(int32)32){
		if(set_BLOCKLEN((int32)32)==false) return(17); /// tiles are 32 bytes
	}
	if (read_BLOCK(dir_addr_ptr,buff)==false) return(10);

	// decode the FAT16 entries
	// a tile is 32 bytes
	// std dos files take one tile
	// a long file name has multiple tiles
	// starting with the last down to the first and
	// then a std dos tile is found
	// byte 11 is 0x0f for LNF tiles and 0x00 for std
	// we skip the LNF and goto STD tile

	tile_decode:
	lnf_tiles=0;
	if (buff[0]==0xE5) goto next_tile; ///0xE5 is the deleted file flag
	if (buff[0]==0x00){
		printf("\n\r file err [%s] not found \n\r",file_name);
		return(11); /// file not found
	}
	if (buff[11]==0x0F){
		/// get number of LNF tiles

⌨️ 快捷键说明

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