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

📄 f34x_msd_file_system.c

📁 C8051F340读写SD卡的程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    return (n0==(char)0xE5) || (n0=='\0');
  }
  return (n0!=(char)0xE5) && (n0>' ') && (findinfo->direntry->sfn.attrib!=0x0F);
}


BYTE findfirst(find_info* findinfo,BYTE empty) 
{
  Sect_Read(findinfo->block = Current_Dir_Block);

  findinfo->findempty=empty;

  findinfo->direntry=(dir_entry*)(Scratch+(findinfo->offset=0));
  if(findvalid(findinfo))
    return 1;
  return findnext(findinfo);
}


BYTE findnext(find_info* findinfo) 
{
  xdata BYTE bRoot = (Current_Dir_Block == Sect_Root_Dir());
  

  do {
    if((findinfo->offset+=sizeof(dir_entry))>=Sect_Block_Size()) {
      xdata unsigned long dir_next_cluster_block = 
                     Get_First_Block_Directory_Cluster(findinfo->block);
      if(bRoot &&  (findinfo->block>=Sect_Root_Dir_Last()))
      {
      //	printf("NOT FOUND\r\n");
        return 0;
      }
	  else if((!bRoot) && (dir_next_cluster_block != 0xffffffff) && 
	  		(findinfo->block>=(dir_next_cluster_block + MBR.sectors_per_cluster-1)))
	  {
	  	// read next cluster occupied by directory	
	  	xdata unsigned long next_next_block = Get_First_Block_Of_Next_Cluster(
										Get_Cluster_From_Sector(dir_next_cluster_block));
			
		if(next_next_block == (0xFFFFFFFF))
		{
			if(!findinfo->findempty)
				return 0;
			else
			{
				xdata new_cluster = 
                  fat_chain_alloc(Get_Cluster_From_Sector(dir_next_cluster_block),1);
				if(new_cluster == 0xFFFF)
					return 0;
				next_next_block = Get_First_Sector(new_cluster);
				Clear_Cluster(new_cluster);
			}	
		}

		dir_next_cluster_block = next_next_block;
		findinfo->offset=0;
		Sect_Read(findinfo->block = dir_next_cluster_block);
	  }
      else {
        findinfo->offset=0;
        Sect_Read(++findinfo->block);

      }
    }
		
		
    findinfo->direntry=(dir_entry*)(Scratch+findinfo->offset);
  } while(!findvalid(findinfo));

  return 1;
}

#else

//---------------------------------------------------------
/* Copy of functions for devices different then F340*/
//---------------------------------------------------------

static BYTE fcreate(find_info* findinfo,char* filename) 
{
  BYTE i,j;
  // Find the first empty directory entry
  if(!findfirst(findinfo,1)) return 0;

  // Fill in the direntry
  for( i = 0; i < 10; i++) 
    findinfo->direntry->sfn.reserved[i] = 0;
  findinfo->direntry->sfn.time.i = findinfo->direntry->sfn.date.i = 0;
  findinfo->direntry->sfn.starting_cluster = findinfo->direntry->sfn.filesize = 0;

  // Fill in the filename
  for( i = 0; i < 11; i++ ) 
    findinfo->direntry->sfn.name[i] = ' ';
  for( j = 0; j < 20; j++ ) {
    if(!filename[j] || filename[j] == '.') 
      break;
    if( j < 8 ) 
      findinfo->direntry->sfn.name[j] = toupper(filename[j]);
  }
  if( filename[j] == '.' ) {
    for( i = 0; i < 3; i++ ) {
      if(!filename[j+i+1] || filename[j+i+1]=='.') 
        break;
      findinfo->direntry->sfn.name[8+i] = toupper(filename[j+i+1]);
    }
  }
  //for(i=0;i<11;i++) findinfo->direntry->sfn.name[i]=
  //toupper(findinfo->direntry->sfn.name[i]);

  // Don't forget to set the attrib:
  findinfo->direntry->sfn.attrib = ATTRIB_ARCHIVE;

	// Write the new data to MMC
  Sect_Write(findinfo->block);

	return 1;
}


static find_info xdata findinfo; // Shared find_info for fopen() and fdelete()

int fopen(FILE* f,char* filename,char* mode) 
{
	f->isopen = 0;

	if( mode[0] == 'w' ) { 
    fdelete(filename); 
  } // This is the most memory-efficient solution, not the most time-efficient solution.

  findfirst(&findinfo, 0);
  while(!file_name_match(filename,findinfo.direntry->sfn.name)) {
    if(!findnext(&findinfo)) {
      if(mode[0] == 'r') {
        return 0; // File not found.
      }
      if( mode[0] == 'w' || mode[0] == 'a' ) {
        if(!fcreate(&findinfo, filename)) {
          return 0; // File cannot be created.
        } else {
          break;
        }
      }
    }
  }

  f->sector_direntry=findinfo.block;
  f->offset_direntry=findinfo.offset;
  f->cluster_start=f->sector_current=
  ntohs(findinfo.direntry->sfn.starting_cluster);//*MBR.sectors_per_cluster;
  f->attrib=findinfo.direntry->sfn.attrib;
  f->size=ntohl(findinfo.direntry->sfn.filesize);

  if(mode[0]=='a') f->pos=f->size; else f->pos=0;
//	Print_File(f);
  return 	f->isopen=1;
}

/*
int fexists(char* filename) {
	FILE xdata f;
	if(fopen(&f,filename,"r")) {
		fclose(&f);
		return 1;
	}
	return 0;
}
*/

/*
int fseek(FILE* f,long offset,int origin) {
	if(!f->isopen) return 0;
	switch(origin) {
		case SEEK_SET:default:
			if(offset>=0)
				f->pos=offset;
			else
				return 0;
			break;
		case SEEK_END:
			f->pos=f->size+offset;
			break;
		case SEEK_CUR:
			f->pos+=offset;
			break;
	}

	return 1;
}
*/

/*
DWORD ftell(FILE* f) {
	if(!f->isopen) return 0;
	return f->pos;
}
*/

int feof(FILE* f) 
{
  if(!f->isopen) return 1;
  return f->pos >= f->size;
}

// Find the 'nr'-th sector in the fat chain starting at 'from'
static unsigned long fat_chain(unsigned long from,unsigned nr) 
{
  unsigned* xdata fat_table=Scratch;
  unsigned xdata sect,sect_prev=0;
  unsigned xdata cluster = nr/MBR.sectors_per_cluster;

  while(cluster) {
    sect = Sect_Fat1() + from/(Sect_Block_Size()/2);
    if(sect!=sect_prev) {
      Sect_Read(sect_prev=sect);
    }

    from=ntohs(fat_table[from%(Sect_Block_Size()/2)]);

    if(!(from>=2 && from<=0xFFEF)) {
      return 0xFFFFu;
    }

    cluster--;
  }
  from *= MBR.sectors_per_cluster;
  from += nr%MBR.sectors_per_cluster;
  return from;
}

// Free an entire fat chain, starting at 'from' until the end of the chain
static void fat_chain_free(unsigned from) 
{
  unsigned* xdata fat_table=Scratch;
  unsigned xdata sect,sect_prev=0;
  unsigned xdata index;

  if(from<2) return;

  sect = Sect_Fat1() + from/(Sect_Block_Size()/2);

  while(1) {
    if(sect!=sect_prev) {
      Sect_Read(sect_prev=sect);
    }

    index = from%(Sect_Block_Size()/2);
	
    from=ntohs(fat_table[index]);
		
    fat_table[index]=0x0000; // Free it

    if(!(from>=2 && from<=0xFFEF)) {
      Sect_Write_Multi_Fat(sect_prev);
      break;
    }

    sect = Sect_Fat1() + from/(Sect_Block_Size()/2);
    if(sect!=sect_prev) {
      Sect_Write_Multi_Fat(sect_prev);
    }
  }
}


// Allocate 'nr' extra FAT blocks at the end of the chain that starts at 'from':
static unsigned fat_chain_alloc(unsigned from,unsigned nr) 
{
  unsigned* xdata fat_table=Scratch;
  unsigned xdata sect,sect_prev=0;
  unsigned xdata index;
  unsigned xdata alloced=0xFFFF;

	// Find free FAT entries, allocate them, and link them together.
  for(sect=Sect_Fat1();nr && sect<Sect_Fat2();sect++) {
    Sect_Read(sect);
		// (Skip first two FAT entries when looking for free blocks)
    for(index=((sect==Sect_Fat1())?2:0);index<Sect_Block_Size()/2;index++) {
      if(fat_table[index]==0x0000) { 		// It's free
        fat_table[index]=ntohs(alloced);// Allocate it (refer to previously alloc'ed FAT entry).
        alloced = 						// Remember which FAT entry was alloc'ed
          (sect-Sect_Fat1()) * (Sect_Block_Size()/2) + index;
        if(!--nr) break;
      }
    }
    if(alloced!=0xFFFF) Sect_Write_Multi_Fat(sect);	// Write all FAT copies
  }

  // When we get here, 'alloced' contains the first FAT block in the alloc'ed chain
  // Find the end of the current FAT chain.
  // Make the end of the current FAT chain refer to the newly allocated FAT chain
  while(from>=2 && from<=0xFFEF && alloced!=0xFFFF) {
    sect = Sect_Fat1() + from/(Sect_Block_Size()/2);
    if(sect!=sect_prev) {
      Sect_Read(sect_prev=sect);
    }
    index = from%(Sect_Block_Size()/2);
    from=ntohs(fat_table[index]);

    if(from>=0xFFF8) {
      fat_table[index]=ntohs(alloced);
      Sect_Write_Multi_Fat(sect);
    }
  }

  return alloced;
}

unsigned fread(FILE* f,BYTE* buffer,unsigned count) 
{
  unsigned xdata cnt,total_cnt=0;
  if(!f->isopen || !count) return 0;

  // If you use the Scratch buffer as fread buffer, then
  // we cannot possibly support transfers consisting of
  // multiple Sect_Read() operations. The second Sect_Read
  // would overwrite the stored bytes from the first one.
  if(buffer>=Scratch && buffer<Scratch+Sect_Block_Size())
    count=min(count,Sect_Block_Size()-f->pos%Sect_Block_Size());

  while(count && !feof(f)) {
    f->sector_current = fat_chain(f->cluster_start,f->pos/Sect_Block_Size());

    Sect_Read(Sect_File_Data() + f->sector_current);

    cnt=min(Sect_Block_Size()-f->pos%Sect_Block_Size(),count);
    cnt=min(cnt,f->size-f->pos);

    memmove(buffer,Scratch+f->pos%Sect_Block_Size(),cnt); // MUST be overlap-safe copy operation!
    total_cnt+=cnt;
    f->pos+=cnt;
    count-=cnt;
    buffer+=cnt;
  }

  return total_cnt;
}

unsigned fwrite(FILE* f,BYTE* buffer,unsigned count) 
{
  unsigned cnt,total_cnt=0,xtra,alloced;
  dir_entry* entry;
  if(!f->isopen || !count) return 0;


  // First, extend the file so it can hold all the data:
  if(f->pos+count>f->size) {
    // If the new EOF ends up in the next FAT block, an extra block must be 
    // allocated.
    // The number of blocks needed to store X bytes = 1+(X-1)/512 if X!=0, 
    // or =0 if X==0.
    // We will need to store 'pos+count' bytes after the write operation
    // This means we need 1+(pos+count-1)/512 blocks after the write operation
    // We currently have 'size' bytes in the file, or 1+(size-1)/512 blocks 
    // (or 0 if size==0).
    // So, we need to allocate (1+(pos+count-1)/512) - (1+(size-1)/512) 
    // extra blocks
    xtra=(1+((f->pos+count-1)/Sect_Block_Size())/MBR.sectors_per_cluster); 
    if ( f->size )
      xtra -= 
      ( 1 +(( f->size - 1 ) / Sect_Block_Size() ) / MBR.sectors_per_cluster );
		

    if(xtra) {
      if(0xFFFF==
      (alloced=fat_chain_alloc(f->sector_current/MBR.sectors_per_cluster,xtra)))
        return 0;
    }

		// Modify the direntry for this file:
    Sect_Read(f->sector_direntry);
    entry = (dir_entry*)(Scratch+f->offset_direntry);
    if((entry->sfn.filesize==0) && (entry->sfn.starting_cluster<2 || 
    entry->sfn.starting_cluster>=0xFFF0)) {
      entry->sfn.starting_cluster=ntohs(f->cluster_start=alloced);
    } 
    entry->sfn.filesize=ntohl(f->size=f->pos+count);
    f->attrib=(entry->sfn.attrib|=ATTRIB_ARCHIVE);
    Sect_Write(f->sector_direntry);
  }

  // Now we are sure the fwrite() operation can be performed
  // in the existing file data blocks. Either because the file 
  // was big enough to start with, or because we have just
  // allocated extra blocks for the new data.
  while(count && !feof(f)) {
    f->sector_current = fat_chain(f->cluster_start,f->pos/Sect_Block_Size());
		

    Sect_Read(Sect_File_Data() + f->sector_current);
  //	Print_File(f);
  //	print_scratch();

    cnt=min(Sect_Block_Size()-f->pos%Sect_Block_Size(),count);
    cnt=min(cnt,f->size-f->pos);

    memmove(Scratch+f->pos%Sect_Block_Size(),buffer,cnt);

  //	print_scratch();
    Sect_Write(Sect_File_Data() + f->sector_current);

    total_cnt+=cnt;
    f->pos+=cnt;
    count-=cnt;
    buffer+=cnt;
  }

  return total_cnt;
}

void fclose(FILE* f) 
{
  f->isopen=0;
}

int fdelete(char* name) 
{
  findfirst(&findinfo,0);
  while(!file_name_match(name,findinfo.direntry->sfn.name)) {
    if(!findnext(&findinfo)) {
      return 0;
    }
  }

  // Do not delete subdirectories or labels:
  if(findinfo.direntry->sfn.attrib & (ATTRIB_SUBDIR|ATTRIB_LABEL)) return 0;

  // Mark the direntry as "deleted" before freeing the fat chain.
  // At this point, the findinfo is still valid in the 'Scratch' buffer.
  // fat_chain_free() would overwrite the Scratch buffer.
  findinfo.direntry->sfn.name[0]=0xE5; // Mark as "deleted"
  Sect_Write(findinfo.block);
  fat_chain_free(ntohs(findinfo.direntry->sfn.starting_cluster));

  return 1;
}

//--------- findfirst, findnext directory functions ---------

static BYTE findvalid(find_info* findinfo) 
{
  char n0 = findinfo->direntry->sfn.name[0];
  if(findinfo->findempty) {
    return (n0==(char)0xE5) || (n0=='\0');
  }
  return (n0!=(char)0xE5) && (n0>' ') && (findinfo->direntry->sfn.attrib!=0x0F);
}

BYTE findfirst(find_info* findinfo,BYTE empty) 
{
  Sect_Read(findinfo->block = Sect_Root_Dir());

  findinfo->findempty=empty;

  findinfo->direntry=(dir_entry*)(Scratch+(findinfo->offset=0));
  if(findvalid(findinfo))
    return 1;
  return findnext(findinfo);
}
void print_info(find_info* info);

BYTE findnext(find_info* findinfo) 
{
  do {
    if((findinfo->offset+=sizeof(dir_entry))>=Sect_Block_Size()) {
      if(findinfo->block>=Sect_Root_Dir_Last())
      {
      //	printf("NOT FOUND\r\n");
        return 0;
      }
      else {
        findinfo->offset=0;
        Sect_Read(++findinfo->block);

      }
    }
		
		
    findinfo->direntry=(dir_entry*)(Scratch+findinfo->offset);
  } while(!findvalid(findinfo));

  return 1;
}

#endif

⌨️ 快捷键说明

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