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

📄 mmc_spi_fat16.c

📁 fat16 biblioteca spi mmc
💻 C
📖 第 1 页 / 共 3 页
字号:
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//   Name:            HDD Driver.c                                        //
//   Date:            02/01/2004                                          //
//   Version:         1.1                                               //
//   Type:            PIC C Driver for MMC                                //
//   Author:        Mike Luck & Douglas Kennedy                       //
//   Company:         MPIC3.COM                                         //
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

//   Note:
//       This code is a work in progress & not a finished fully working
//         project. Please check www.mpic3.com reguarly for updates.

/// PIN Assignments //////////////////////////////
#DEFINE _CS PIN_C2 // chip select for MMC
//#DEFINE SDO PIN_C5
//#DEFINE CLK PIN_C3
//#DEFINE SDI PIN_C4
// SPI hardware pins are
// SDO C5
// SDI C4
// SCK C3
///////////////////////////////////////////////////////////////

///// Note old values needed before all SPI modes could be set up using SPI_setup
/// for 16 parts ///////////
//#DEFINE SSPCON 0x14
//#DEFINE SSPSTAT 0x94
//#BIT SMP=SSPSTAT.7
//#BIT CKE=SSPSTAT.6
//#BIT CKP=SSPCON.4
//#BIT SSPEN=SSPCON.5
//////////////////////////////

// For 18F452
#DEFINE SSPSTAT 0x0FC7
#DEFINE SSPCON1 0x0FC6
#BIT SMP=SSPSTAT.7
#BIT CKE=SSPSTAT.6
#BIT CKP=SSPCON1.4

#DEFINE MAX_FILES 2 /// max number of open files
#DEFINE MMC_BUFF_SIZE 32 /// 32 for PCM
#DEFINE MMC_FILE_NAME_SIZE 32

#DEFINE ROOT_CLUSTER 0
#DEFINE NEXT_CLUSTER 1

#define MMC_INIT_TRACE FALSE
#define MMC_CMD_TRACE FALSE
#define MMC_CLUSTER_TRACE FALSE // if true prints to serial port
#define MMC_OPEN_TRACE FALSE // if true prints to serial port
#define MMC_READ_TRACE FALSE // if true prints file_addr,cluster index etc
#define MMC_WRITE_TRACE FALSE
#define MMC_READ_BLOCK_TRACE FALSE
#define MMC_SET_BLOCK_LEN_TRACE FALSE
#define MMC_WRITE_BLOCK_TRACE FALSE
#define MMC_NEW_CLUSTER FALSE
////// MMC prototypes
#separate
int init_MMC(int max_tries);
#separate
int open_file(int fnbr,char *fname,int16 rec_length);
#separate
int file_read(int8 fnbr,char *buff);
#separate
int file_write(int8 fnbr,int *buff);
#separate
int file_set(int fnbr,int32 offset);
#separate
int file_new_cluster(int8 fnbr,int8 mode); /// mode 1=fat1 2=fat2

int32 atoint32 (char *s );
signed int strncmp(char *s1, char *s2, int n);
///////////////////// MMC GLOBALS /////////////////////////////
int16 cluster_size_bytes; // bytes in a cluster
//int16 dir_cluster_chain_ptr; // link to the first cluster in the dir

int32 fat1_address; // physical address of fat1 cluster table assigned by INIT_MMC
int32 fat2_address; // physical address of fat1 cluster table assigned by INIT_MMC
int32 root_dir_address; // physical address of volume,file,folder tiles assigned by INIT_MMC
int32 data_area_address; // physical address of data area assigned by INIT_MMC
int32 winhex_adj; // Win hex hides the bytes in the reserved sectors
// this means Fat1 is address 512
// so adj is fat1-512

int32 block_size; // current MMC block size

int MMC_init=FALSE;

int MMC_dir_protected=TRUE;

////////// open file specific globals ///////////////////////
struct{
   char name[MMC_FILE_NAME_SIZE+1]; // fopen file name
   int32 dir_addr_ptr; // physical address of this files tile info
   int16 root_cluster_ptr; // location of first cluster in FAT
   int16 this_cluster_ptr; // location of current cluster in FAT
   int16 next_cluster_ptr; // location of the next cluster for a file or sub dir in FAT
   int32 addr_ptr; // physical address in the file the current
   // cluster points to
   // address=(this_chain_ptr-2)*cluster_size_bytes+data_area_address
   //
   // cluster_addr(THIS_CLUSTER) assigns it
   // cluster_addr(NEXT_CLUSTER) moves to the data the next
   // cluster points to
   int32 size; // size of open file in bytes
   int32 cluster_offset; // offset within the file representing the start of the current cluster
   // (0 is start and ends with the cluster contianing eof )
   // auto increased by cluster_size_bytes each time a new cluster is entered

   int32 offset; // current offset into the open file ( 0 is start size(file size) is end)
   // auto increased by rec size each time a rec is read
   // addr_prt+offset-cluster_offset is physical address of
   // the current position within the file
   // the physical positions are not always contiguous since the
   // clusters of the file are not always adjacent to each other
   int16 rec_size; // fopen record_size
   // char buff[MMC_BUFF_SIZE+1]; // used for open and for read write
   // init MMC uses file 0 buff to fetch the globals

} file[MAX_FILES];


#separate
int mmc_cmd(int8 cmd,int32 address,int8 tries,int8 valid,int8 invalid){
   int i,r1;
   for( i=0;i<16;i++) SPI_READ(0xFF);// digest prior operation
   // commands
   // 7 6 5 4 3 2 1 0
   // 0 1 b b b b b b bbbbbb=cmd
   // 16=0x50 set blocklength
   // 17=0x51 read block
   // 24=0x58 write block
   #if MMC_CMD_TRACE
   printf("\n\r cmd=%2X \n\r",cmd);
   #endif
   SPI_READ(cmd);
   SPI_READ(MAKE8(address,3));
   SPI_READ(MAKE8(address,2));
   SPI_READ(MAKE8(address,1));
   SPI_READ(MAKE8(address,0));
   SPI_READ(0x95); // valid crc for 0x40 only invalid for others but spi mode doesn't care
   for(i=0;i< tries;i++) {
      r1=SPI_READ(0xFF);
      #if MMC_CMD_TRACE
         printf(" %2X",r1);
      #endif
      if (r1==valid) break;
      if (r1==invalid) break;
   }
   return(r1);
}


#separate
int set_BLOCKLEN( int32 size){
   int r1;

   r1=mmc_cmd(0x50,size,16,0x00,0x40); /// cmd.data,tries,valid code,invlaid code
   if (r1==0x00) goto done ;
   if (r1==0x40) goto invalid;


   return(false);
   invalid:
   #IF MMC_SET_BLOCK_LEN_TRACE
      printf("\n\r para err\n\r");
   #ENDIF
done:
   block_size=size; //// assign global block size
   //printf("\n\r blk size=%lu",block_size);
   return(true);
}


#separate
int read_BLOCK( int32 address, char *buff){
   //// low level read ..requires block len to be called first to set global blocksize
   int r1;
   long i,iw; /// allows large gt 255 buff size addressing
   //int data[128];
   r1=mmc_cmd(0x51,address,16,0x00,0x40);

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

   #IF MMC_READ_BLOCK_TRACE
      printf("\n\r read block err 1 address=%lu \n\r",address);
   #ENDIF
   return(false);
   invalid:
   #IF MMC_READ_BLOCK_TRACE
      printf("\n\r read block err 2 adress=%lu \n\r",address);
   #ENDIF
   return(false);
   get_token:
   for(iw=0;iw<1024;iw++){
   r1=SPI_READ(0xFF);
   //data[iw]=r1;
   if (r1==0xFE) goto read_data; // read token $FE
   }
   #IF MMC_READ_BLOCK_TRACE
      printf("\n\r read block err 3 address=%lu \n\r",address);
   #ENDIF
   return(false);
   read_data:
   #IF MMC_READ_BLOCK_TRACE
      printf("\n\r read block tries for FE =%lu \n\r",iw);
   #ENDIF

   for (i=0;i<block_size;i++) buff[i]=SPI_READ(0xFF);
   SPI_READ(0xFF); // read crc
   SPI_READ(0xFF);

   return(true);
}

//////////////////////////////////////////////////////////////////
///////////////////////////////// INIT MMC ///////////////////////
//////////////////////////////////////////////////////////////////
#separate

int init_MMC(int max_tries){
   int32 start_lsec;
   int16 sec_resv,sec_for_FAT,bytes_per_sector,root_dir_entries,
   sec_for_data,count_of_clusters,root_dir_sectors,total_sectors;
   int i,tries,sec_per_cluster,c;
   char buff[32];
   tries=0;
   cmd0:
   ///////////////////// place null treminators in globals fname and buff
   for(i=0;i<MAX_FILES;i++){
      file[i].name[0]=0;
      file[i].rec_size=32; //// default rec_size = 32 byte tile size of FAT16
   }
   //buff[MMC_BUFF_SIZE]=0;
   //frec_size=32; //// default rec_size = 32 byte tile size of FAT16
   output_high(_CS); /// reset chip hardware !!! required
   delay_ms(20);
   for(i=0;i<20;i++) SPI_READ(0xFF); // min 80 clocks to get MMC ready
   output_low(_CS); /// !!! required
   delay_ms(20);
   #if MMC_INIT_TRACE
      printf("cmd0");
   #ENDIF
   c=mmc_cmd(0x40,0x00000000,128,0x01,0x99);

   if (c==0x01) goto exit_cmd1;

   // note: i must cycle at least 8 times (16 is safe )

   if (tries++<max_tries) goto cmd0; /// restart
   else return (10);
   exit_cmd1:
   // CPDMOD - This SOMETIMES seems to be necessary
   // output_high(_CS);
   // SPI_READ(0xFF); // min 8 clocks to get MMC ready
   // output_low(_CS);
   //CPDMOD End


   tries=0;
   cmd1:

   /// now try to switch to idle mode
   /// Note: cmd1(idle) is the only command allowed after a cmd0(reset)
   //

   c=mmc_cmd(0x41,0x00000000,128,0x00,0x99);
   if (c==0x00) { goto ready;}


   if( tries++<max_tries) { printf("cmd1"); goto cmd1;}
   else return(11);
   ready:
   //for( i=0;i<32;i++) SPI_READ(0xFF);// digest operation
   /// MMC is inialized and in idle state ready for commands
   ////
   //// we need to first access the master boot sector physical address=0
   ///
   if(set_BLOCKLEN((int32)32)==false) return(12); /// sets global block_size to 32

   if (read_block(0x00000000,buff)==false) return (99); /// read the first few bytes
   #if MMC_INIT_TRACE
      printf("\n\r sector0=");
      for(i=0;i<32;i++)printf("%2X ",buff[i]);
   #ENDIF
   if (buff[0]==0xEB || buff[0]==0xE9){
      /// sector 0 is the boot sector
      #if MMC_INIT_TRACE
         printf("\n\r boot sector= 0");
      #ENDIF
   }
   else{
      //// partition

      /// access the master boot sector physical address 0 at offset 1BE
      if (read_BLOCK(0x000001BE,buff)==false) return(13);
      #if MMC_INIT_TRACE
         for(i=0;i<32;i++)printf("%2X ",buff[i]);
      #ENDIF
      // start_lsec is address of the partion boot sector
      start_lsec=make32(buff[11],buff[10],buff[9],buff[8]);
      #if MMC_INIT_TRACE
         printf("\n\r boot sector= %lu",start_lsec);
      #ENDIF
      if (read_BLOCK(start_lsec*512,buff)==false) return(14);
   }

   bytes_per_sector=make16(buff[12],buff[11]);
   if(bytes_per_sector!=512) return(15);
   sec_per_cluster=buff[13];
   cluster_size_bytes=(int16)sec_per_cluster*bytes_per_sector;


   sec_resv=make16(buff[15],buff[14]);

   root_dir_entries=make16(buff[18],buff[17]);// number of 32 byte tiles

   total_sectors=make16(buff[20],buff[19]);

   sec_for_FAT=make16(buff[23],buff[22]);
   //branch to file directory
   fat1_address=(start_lsec+sec_resv)*bytes_per_sector;
   fat2_address=fat1_address+bytes_per_sector*sec_for_FAT;
   root_dir_address=(sec_for_FAT*2+start_lsec+sec_resv)*bytes_per_sector;
   data_area_address=root_dir_address+root_dir_entries*32;
   ///// check for FAT16
   root_dir_sectors=root_dir_entries>>4;

   sec_for_data=total_sectors - sec_resv -sec_for_fat*2 -root_dir_sectors;

   count_of_clusters=sec_for_data/sec_per_cluster;

   if (count_of_clusters <4085 || count_of_clusters>65525) return(17);

   winhex_adj=fat1_address-bytes_per_sector;

   #if MMC_INIT_TRACE

      printf("Files:/n/r");
      for(i=0;i<MAX_FILES;i++){
         printf("/n/r",file[i].name[i]);
      }

   #ENDIF

   return(0);
}


#separate
int get_CID(char s){
   int i,r1;
   r1=mmc_cmd(0x4A,0x00000000,16,0x00,0x99);


   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_CID; // read token $FE
   return(false);
   read_CID:
   //for (i=0;i<18;i++) s[i]=SPI_READ(0xFF);

   return(true);
}


#separate
int get_CSD(char s){
   int i,r1;
   r1=mmc_cmd(0x4A,0x00000000,16,0x00,0x99);

⌨️ 快捷键说明

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