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

📄 mmc_spi_fat16.c

📁 fat16 biblioteca spi mmc
💻 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 + -