//FAT初始化,不含SD的初始化,用之前应先调用sd的初始化 //返回值:0,初始化成功 // 其他,初始化失败 unsigned char FAT_Init(void)//Initialize of FAT need initialize SD first { bootsector710 *bs = 0; bpb710 *bpb = 0; partrecord *pr = 0; DWORD hidsec=0; u32 Capacity; Capacity = SD_GetCapacity(); if(Capacity<0xff)return 1; if(SD_ReadSingleBlock(0,fat_buffer))return 2; bs = (bootsector710 *)fat_buffer; pr = (partrecord *)((partsector *)fat_buffer)->psPart;//first partition hidsec = pr->prStartLBA;//the hidden sectors if(hidsec >= Capacity/512)hidsec = 0; else { if(SD_ReadSingleBlock(pr->prStartLBA,fat_buffer))return 3;//read the bpb sector bs = (bootsector710 *)fat_buffer; if(bs->bsJump[0]!=0xE9 && bs->bsJump[0]!=0xEB) { hidsec = 0; if(SD_ReadSingleBlock(0,fat_buffer))return 4;//read the bpb sector bs = (bootsector710 *)fat_buffer; } } if(bs->bsJump[0]!=0xE9 && bs->bsJump[0]!=0xEB)return 5;//对付没有bootsect的sd卡 //dead with the card which has no bootsect bpb = (bpb710 *)bs->bsBPB; if(bpb->bpbFATsecs)//detemine thd FAT type //do not support FAT12 { FAT32_Enable=0; //FAT16 FATsectors = bpb->bpbFATsecs;//FAT表占用的扇区数 FirstDirClust = 2; } else { FAT32_Enable=1; //FAT32 FATsectors = bpb->bpbBigFATsecs;//FAT占用的扇区数 FirstDirClust = bpb->bpbRootClust; } BytesPerSector = bpb->bpbBytesPerSec; //每扇区字节数 SectorsPerClust = (BYTE)bpb->bpbSecPerClust;//每簇扇区数 FirstFATSector = bpb->bpbResSectors+hidsec;//第一个FAT表扇区 RootDirCount = bpb->bpbRootDirEnts; //根目录项数 RootDirSectors = (RootDirCount*32)>>9; //根目录占用的扇区数 FirstDirSector = FirstFATSector+bpb->bpbFATs*FATsectors;//第一个目录扇区 FirstDataSector = FirstDirSector+RootDirSectors;//第一个数据扇区 return 0; }
int main(void) { uint32_t i; DelayInit(); GPIO_QuickInit(HW_GPIOE, 6, kGPIO_Mode_OPP); UART_QuickInit(UART0_RX_PD06_TX_PD07, 115200); printf("SD test\r\n"); printf("please insert SD card...\r\n"); //SD卡模块快速初始化,设置速度为20000000 SD_QuickInit(20000000); //获取SD卡的容量 printf("SD size:%dMB\r\n", SD_GetSizeInMB()); /* 读取0扇区数据,每一个扇区512字节 */ SD_ReadSingleBlock(0, sd_buffer); /* 打印0扇区数据 */ printf("sectoer 0 data:\r\n"); for(i = 0; i < 512; i++) { printf("0x%02X ", sd_buffer[i]); } while(1) { //小灯闪烁 GPIO_ToggleBit(HW_GPIOE, 6); DelayMs(500); } }
//读取512个字节 //FileInfo:要读取的文件 //buf :数据缓存区 //返回值 :0,操作失败,1,操作成功 unsigned char F_Read(FileInfoStruct *FileInfo,u8 *buf) { DWORD sector; sector=fatClustToSect(FileInfo->F_CurClust);//得到当前簇号对应的扇区号 if(SD_ReadSingleBlock(sector+FileInfo->F_Offset,buf))return 0;//读数错误 FileInfo->F_Offset++; if(FileInfo->F_Offset==SectorsPerClust) //簇的尽头,换簇 { FileInfo->F_Offset=0; FileInfo->F_CurClust=FAT_NextCluster(FileInfo->F_CurClust);//读取下一个簇号 if((FAT32_Enable==0&&FileInfo->F_CurClust==0xffff) \ ||FileInfo->F_CurClust==0x0ffffff8||FileInfo->F_CurClust == 0x0fffffff)return 0;//error } return 1;//读取成功 }
DRESULT disk_read ( BYTE drv, /* Physical drive nmuber (0..) */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address (LBA) */ BYTE count /* Number of sectors to read (1..255) */ ) { u8 res=0; if (drv || !count) { return RES_PARERR; //仅支持单磁盘操作,count不能等于0,否则返回参数错误 } if(!SD_DET()) { return RES_NOTRDY; //没有检测到SD卡,报NOT READY错误 } if(count==1) //1个sector的读操作 { res = SD_ReadSingleBlock(sector, buff); } else //多个sector的读操作 { res = SD_ReadMultiBlock(sector, buff, count); } /* do { if(SD_ReadSingleBlock(sector, buff)!=0) { res = 1; break; } buff+=512; }while(--count); */ //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值 if(res == 0x00) { return RES_OK; } else { return RES_ERROR; } }
DRESULT disk_read ( BYTE drv, /* Physical drive nmuber (0..) */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address (LBA) */ BYTE count /* Number of sectors to read (1..255) */ ) { u8 res=0; if (drv || !count) { return RES_PARERR; // only supports single disk operation, count is not equal to 0, otherwise parameter error } // if(!SD_DET()) // { // return RES_NOTRDY; // does not detect SD card, NOT READY error reported // } if(count==1) // sector reads 1 { res = SD_ReadSingleBlock(sector, buff); } else // multiple sector read operations { res = SD_ReadMultiBlock(sector, buff, count); } /* do { if(SD_ReadSingleBlock(sector, buff)!=0) { res = 1; break; } buff+=512; }while(--count); */ // Process the return value, the return value of the SPI_SD_driver.c the return value turned into ff.c if(res == 0x00) { return RES_OK; } else { return RES_ERROR; } }
/*****************************SD卡读取********************************/ void Sd_D(void) { uint8_t i; while(SD_ReadSingleBlock(SD_D,Send_Data) != ESDHC_OK); for(i=0;i<=127;i++) { Sent_Data->Pixels[i] = Send_Data[i]; } Sent_Data->Lcr[0].Left = Send_Data[197]; Sent_Data->Lcr[0].Right = Send_Data[198]; Sent_Data->Lcr[0].Center = Send_Data[199]; Sent_Data->Lcr[1].Left = Send_Data[197]; Sent_Data->Lcr[1].Right = Send_Data[198]; Sent_Data->Lcr[1].Center = Send_Data[199]; SD_D++; }
DRESULT disk_read (BYTE drv,BYTE* buff,DWORD sector,BYTE count)//哪个卡(一般为0),读出的数据存储的地方,块地址,块个数 { u8 res=0; if (drv || !count) { return RES_PARERR; //仅支持单磁盘操作,count不能等于0,否则返回参数错误 } if(SD_Insert_Status()) { return RES_NOTRDY; //没有检测到SD卡,报NOT READY错误 } if(count==1) //1个sector的读操作 { res = SD_ReadSingleBlock(sector, buff); } else //多个sector的读操作 { res = SD_ReadMultiBlock(sector, buff, count); } /* do { if(SD_ReadSingleBlock(sector, buff)!=0) { res = 1; break; } buff+=512; }while(--count); */ //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值 if(res == 0x00) { return RES_OK; } else { return RES_ERROR; } }
//在SD卡上的FAT表中查找下一簇号 //cluster:当前簇号 //返回值:0x0ffffff8,表示没有后续簇了 // 其他值,下一簇号 unsigned long FAT_NextCluster(unsigned long cluster) { DWORD sector; DWORD offset; if(FAT32_Enable)offset = cluster/128;//FAT32的FAT表中,用四个字节表示一个簇地址.512/4=128 else offset = cluster/256; //FAT16的FAT表中,用两个字节表示一个簇地址.512/2=256 if(cluster<2)return 0x0ffffff8; //簇0,1不能用于存放 sector=FirstFATSector+offset;//计算该簇实际所在扇区 if(SD_ReadSingleBlock(sector,fat_buffer))return 0x0ffffff8;//读取FAT表,发生错误是返回0x0ffffff8 if(FAT32_Enable) { offset=cluster%128;//计算在扇区内的偏移 sector=((unsigned long *)fat_buffer)[offset];//u32 } else { offset=cluster%256;//计算在扇区内的偏移 sector=((unsigned short *)fat_buffer)[offset];//u16 } return (unsigned long)sector;//return the cluste number }
//查找系统文件 //在指定目录下,找寻一个指定类型的指定名字的文件 //cluster:文件夹的簇号!!! //Name :文件的名字 //type :文件类型 //返回值 :该文件的详细信息/如果 FileInfo.F_StartCluster=0 则说明此次寻找失败 FileInfoStruct F_Search(u32 cluster,unsigned char *Name,u32 type) { DWORD sector; DWORD tempclust; unsigned char cnt; unsigned int offset; direntry *item = 0; FileInfoStruct FileInfo; if(cluster==0 && FAT32_Enable==0)//FAT16根目录读取 { for(cnt=0;cnt<RootDirSectors;cnt++) { if(SD_ReadSingleBlock(FirstDirSector+cnt,fat_buffer)) { FileInfo.F_StartCluster=0;//读数错误 return FileInfo; } for(offset=0;offset<512;offset+=32) { item=(direntry *)(&fat_buffer[offset]);//指针转换 //找到一个可用的文件 if((item->deName[0] != 0x00) && (item->deName[0] != 0xe5))//找到一个合法文件 { if(item->deAttributes != AM_LFN)//忽略长文件名 { CopyDirentruyItem(&FileInfo,item);//复制目录项,提取详细信息 if(FileInfo.F_Type&type)//找到一个合适的类型了 { // //printf("File Name:%s\n",FileInfo.F_Name); //找到了文件,返回这个文件的首簇 if(mystrcmp(Name,FileInfo.F_Name)) { return FileInfo; } } LongNameFlag=0;//清空长文件名 } } } } }else//其他文件夹/FAT32系统 { tempclust=cluster; while(1) { sector=fatClustToSect(tempclust); for(cnt=0;cnt<SectorsPerClust;cnt++) { if(SD_ReadSingleBlock(sector+cnt,fat_buffer)) { FileInfo.F_StartCluster=0;//读数错误 return FileInfo; } for(offset=0;offset<512;offset+=32) { item=(direntry *)(&fat_buffer[offset]); if((item->deName[0] != 0x00) && (item->deName[0] != 0xe5)) { if(item->deAttributes != AM_LFN) //忽略长文件名 { CopyDirentruyItem(&FileInfo,item);//复制目录项,提取详细信息 if(FileInfo.F_Type&type)//找到一个合适的类型了 { /* //printf("F_Info->F_Name:%s\n",FileInfo.F_Name); //printf("F_Info->F_Type:%d\n",FileInfo.F_Type); //printf("F_Info->F_Size:%d\n",FileInfo.F_Size); //printf("F_Info->F_StartClusterH:%x\n",FileInfo.F_StartCluster>>8); //printf("F_Info->F_StartClusterL:%x\n\n",FileInfo.F_StartCluster&0xff); */ //找到了文件,返回这个文件的首簇 if(mystrcmp(Name,FileInfo.F_Name)) { return FileInfo; } } LongNameFlag=0;//清空长文件名 } } } } tempclust=FAT_NextCluster(tempclust);//查找下一个簇号 if(tempclust==0x0fffffff||tempclust==0x0ffffff8 ||(FAT32_Enable==0&&tempclust==0xffff))break; } } FileInfo.F_StartCluster=0;//读数错误 return FileInfo; }
//浏览目标文件夹下面的一个文件类 //dir_clust:当前目录所在簇号 //FileInfo :目标文件的实体对象(FileInfoStruct体) //type :要查找的文件类型:1<<0,mp1;1<<1,mp2;1<<2,mp3;1<<3,mp4;1<<4,m4a;1<<5,3gp; // 1<<6,3g2;1<<7,ogg;1<<8,acc;1<<9,wma;1<<10,wav;1<<11,mid; // 1<<12,flac;1<<13,lrc;1<<14,txt;1<<15,c;1<<16,h;1<<17,file; // 1<<18,fon;1<<19,sys;1<<20,bmp;1<<21,jpg;1<<22,jpeg; //count :0,返回当前目录下,该类型文件的个数;不为零时,返回第count个文件的详细信息 //返回值 :1,操作成功.0,操作失败 u8 Get_File_Info(u32 dir_clust,FileInfoStruct *FileInfo,u32 type,u16 *count) { DWORD sector; DWORD cluster=dir_clust; DWORD tempclust; unsigned char cnt; unsigned int offset; unsigned short cont=0;//文件索引标志 <65536 unsigned char j; //long name fat_buffer offset; unsigned char *p;//long name fat_buffer pointer direntry *item = 0; winentry *we =0; cont=0; LongNameFlag = 0;//清空长文件名标志 //SD_Init();//初始化SD卡,在意外拔出之后可以正常使用 //goto SD; if(cluster==0 && FAT32_Enable==0)//FAT16根目录读取 { for(cnt=0;cnt<RootDirSectors;cnt++) { if(SD_ReadSingleBlock(FirstDirSector+cnt,fat_buffer))return 0;//读数错误 for(offset=0;offset<512;offset+=32) { item=(direntry *)(&fat_buffer[offset]);//指针转换 //找到一个可用的文件 if((item->deName[0]!=0x2E)&&(item->deName[0]!=0x00)&&(item->deName[0]!=0xe5) ||((item->deName[0]==0x2E)&&(item->deName[1]==0x2E)))//找到一个合法文件.忽略".",使用".." { if(item->deAttributes == 0x0f)//找到一个长文件名 { we = (winentry *)(&fat_buffer[offset]); j = 26 *( (we->weCnt-1) & WIN_CNT);//长文件名的长度 if(j<MAX_LONG_NAME_SIZE-25) { p = &LongNameBuffer[j];//偏移到目标地址 for (j=0;j<10;j++) *p++ = we->wePart1[j]; for (j=0;j<12;j++) *p++ = we->wePart2[j]; for (j=0;j<4;j++) *p++ = we->wePart3[j]; if (we->weCnt & 0x40) (*(unsigned int *)p) = 0; if ((we->weCnt & WIN_CNT) == 1) LongNameFlag = 1;//最后一个长文件项找到了 } }else { if(type&FileType_Tell(item->deExtension))//找到一个目标文件 { cont++;//文件索引增加 } //查找该目录下,type类型的文件个数 if(*count&&cont==*count) { ////printf("\ncount:%d",*count); CopyDirentruyItem(FileInfo,item);//复制目录项,提取详细信息 return 1;//找到目标文件成功 } LongNameFlag=0;//清空长文件名 } } } } } else//其他文件夹/FAT32系统 { tempclust=cluster; while(1) { sector=fatClustToSect(tempclust); for(cnt=0;cnt<SectorsPerClust;cnt++) { if(SD_ReadSingleBlock(sector+cnt,fat_buffer))return 0; for(offset=0;offset<512;offset+=32) { item=(direntry *)(&fat_buffer[offset]); if((item->deName[0]!=0x2E)&&(item->deName[0]!=0x00)&&(item->deName[0]!=0xe5) ||((item->deName[0]==0x2E)&&(item->deName[1]==0x2E)))//找到一个合法文件.忽略".",使用".." { if(item->deAttributes == 0x0f) //得到一个长文件名 { we = (winentry *)(&fat_buffer[offset]); j = 26 *( (we->weCnt-1) & WIN_CNT); if(j<MAX_LONG_NAME_SIZE-25) { p = &LongNameBuffer[j];//p指向长文件名的存放地址 for (j=0;j<10;j++) *p++ = we->wePart1[j]; for (j=0;j<12;j++) *p++ = we->wePart2[j]; for (j=0;j<4;j++) *p++ = we->wePart3[j]; if (we->weCnt & 0x40) (*(unsigned int *)p) = 0; if ((we->weCnt & WIN_CNT) == 1) LongNameFlag = 1; } } else { if(type&FileType_Tell(item->deExtension))//找到一个目标文件 { cont++;//文件索引增加 } //查找该目录下,type类型的文件个数 if(*count&&cont==*count) { CopyDirentruyItem(FileInfo,item);//复制目录项,提取详细信息 return 1;//找到目标文件成功 } LongNameFlag=0;//清空长文件名 } } } } tempclust=FAT_NextCluster(tempclust);//查找下一个簇号 if(tempclust==0x0fffffff||tempclust==0x0ffffff8 ||(FAT32_Enable==0&&tempclust==0xffff))break; } } if(*count==0) { *count=cont;//得到总共文件数目 return 1; //操作成功,找到cont个符合条件的文件了 }else return 0; //操作失败,没找到文件,或者出错 }
void SDCardReadWriteTextTask(void* parameters) { uint8_t outbuf[512]; uint8_t inbuf[512]; int i; //LED_LowLevel_Init(); //UART_LowLevel_Init(); SD_LowLevel_Init(); //Initialize PINS, vector table and SDIO interface //UART_SendLine("Ready...Steady\n"); printf("SSD\n\r"); LEDOn(LED2); //Initialize the SD SD_Init(); //After return from this function sd is in transfer mode. //UART_SendLine("GO\n"); printf("SDI\n\r"); LEDOff(LED2); //Write a single block to the SD for (i=0;i<512;i++) { outbuf[i]='a'; } //Single Block Test SD_WriteSingleBlock(outbuf, 3000); SD_ReadSingleBlock(inbuf, 3000); //UART_SendLine("First Block\n"); //UART_Send(inbuf,512); printf("\n\r%s", "First Block"); printf("\n\r%i,%i,%i,%i", (int)inbuf[0], (int)inbuf[1], (int)inbuf[2], (int)inbuf[3]); SD_WriteSingleBlock(outbuf, 3001); SD_ReadSingleBlock(inbuf, 3001); //UART_SendLine("Second Block\n"); //UART_Send(inbuf,512); printf("\n\r%s", "Second Block"); printf("\n\r%i,%i,%i,%i", (int)inbuf[0], (int)inbuf[1], (int)inbuf[2], (int)inbuf[3]); //Multiple block SD_StartMultipleBlockWrite(1000); SD_WriteData(outbuf,500); SD_WriteData(outbuf+50,50); SD_WriteData(outbuf,500); SD_StopMultipleBlockWrite(); SD_ReadSingleBlock(inbuf, 1000); //UART_SendLine("Mult. Block 1\n"); //UART_Send(inbuf,512); printf("\n\r%s", "Mult. Block 1"); printf("\n\r%i,%i,%i,%i", (int)inbuf[0], (int)inbuf[1], (int)inbuf[2], (int)inbuf[3]); SD_WaitTransmissionEnd(); SD_ReadSingleBlock(inbuf, 1001); //UART_SendLine("Mult. Block 2\n"); //UART_Send(inbuf,512); printf("\n\r%s", "Mult. Block 2"); printf("\n\r%i,%i,%i,%i", (int)inbuf[0], (int)inbuf[1], (int)inbuf[2], (int)inbuf[3]); // LEDOn(LED6); portTickType lastExecutionTime = xTaskGetTickCount(); for (;;) { DelayUntilTime( &lastExecutionTime, SDCardReadWriteTextTaskT); } }
/*-----------------------------------*/ static int ReadSectors(void * DriveData, DWORD Sector, UINT Sectors, void * Buffer) { SDC_CMD_STATUS status; kal_uint8 retry = 0; kal_uint32 adrs; #if defined(__SIM_PLUS__) sd_select_enum sel; if((MSDC_HANDLE *)DriveData == &MSDC_Blk[0]) sel = SD_EXT; else sel = SD_SIM; MSDC_Switch_Card(sel); #endif #if defined(SD_MMC_HIGH_DENSITY_SUPPORT) if(gSD->flags & SD_FLAG_HCS_SUPPORT) adrs = Sector; else #endif adrs = Sector * SECTOR_SIZE; gMSDC_Handle->timeout_count = 0; start: if(!gMSDC_Handle->mIsInitialized) { //dbg_print("Read but not Initialized \r\n"); MSDC_PDNControl(KAL_TRUE); return FS_MSDC_READ_SECTOR_ERROR; } retry ++; MSDC_PDNControl(KAL_FALSE); #ifndef LSD_SINGLE_READ if(Sectors > 1) status = SD_ReadMultiBlock((kal_uint32)adrs,(kal_uint32*)Buffer,(kal_uint32)Sectors); else status = SD_ReadSingleBlock((kal_uint32)adrs,(kal_uint32*)Buffer); #else while(Sectors) { status = SD_ReadSingleBlock((kal_uint32)adrs,(kal_uint32*)Buffer); if(status != NO_ERROR ) break; (kal_uint8 *)Buffer += SECTOR_SIZE; Sector ++; #if defined(SD_MMC_HIGH_DENSITY_SUPPORT) if(gSD->flags & SD_FLAG_HCS_SUPPORT) adrs = Sector; else #endif adrs = Sector * SECTOR_SIZE; Sectors--; } #endif if(status != NO_ERROR ) { sd_r++; if(kal_query_systemInit()== KAL_TRUE) { MSDC_PDNControl(KAL_TRUE); return FS_MSDC_READ_SECTOR_ERROR; } //dbg_print("read retry:%d,status:%d,total %d\r\n",retry,status,sd_r); if(status == ERR_CMD_TIMEOUT || status == MSDC_GPT_TIMEOUT_ERR) gMSDC_Handle->timeout_count++; if(gMSDC_Handle->timeout_count++ == 3 && gMSDC_Handle->mIsPresent == KAL_TRUE) { kal_print("[MSDC]:re-mount(read fail)"); gMSDC_Handle->mIsInitialized = KAL_FALSE; retry = 0; if(SD_Initialize() != NO_ERROR) { MSDC_PDNControl(KAL_TRUE); return FS_MSDC_READ_SECTOR_ERROR; } } if(retry >= SD_MAX_RETRY) { MSDC_PDNControl(KAL_TRUE); return FS_MSDC_READ_SECTOR_ERROR; } else { // kal_prompt_trace(MOD_AUD,"CRC etry:%d,status:%d",retry,status); goto start; } } MSDC_PDNControl(KAL_TRUE); return FS_NO_ERROR; }