📄 hdd driver.c
字号:
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 + -