📄 sddriver.c
字号:
/****************************************Copyright (c)**************************************************** Guangzhou ZHIYUAN electronics Co.,LTD.** ** http://www.zyinside.com****--------------File Info-------------------------------------------------------------------------------** File Name: sddriver.c** Last modified Date: 2006.01.09** Last Version: V1.0 ** Description: API funciton of initializ,read,write SD/MMC卡 ** 初始化、读、写 SD/MMC卡的 API 函数**------------------------------------------------------------------------------------------------------** Created By: MingYuan Zheng 郑明远** Created date: 2006.01.09** Version: V1.0** Descriptions: The original version 初始版本****------------------------------------------------------------------------------------------------------** Modified by:** Modified date:** Version:** Description:**********************************************************************************************************/#include "drv_extr.h"#include "sd_extr.h"/* SD/MMC卡信息结构体变量 the information structure variable of SD/MMC Card */sd_struct sds = {0}; /* 超时时间单位表(单位:0.000000001ns) timeout unit table */const INT32U time_unit[8] = {1000000000,100000000,10000000, 1000000,100000,10000,1000,100};/* 超时时间表 timeout value table */ const INT8U time_value[16] = {0,10,12,13,15,20,25,30, 35,40,45,50,55,60,70,80}; /* 超时时间因数表 timeout factor table */ const INT8U r2w_fator[6] = {1,2,4,8,16,32}; /* 与中断相关的全局变量 global variable releated with interrupt */#if SD_INTERRUPT_ENstatic DECLARE_WAIT_QUEUE_HEAD(wq);volatile int reading; /* 读卡(1)或写卡(1)状态 read card(1) or write card(1) status */INT8U *buffer; /* 读卡或写卡缓冲区 the buffer of read or write card */INT32 bufcnt; /* 缓冲区计数器 buffer counter */INT32 datalen; /* 读卡或写卡数据长度 the data length of read or write card */volatile int error;#endif volatile int card_insert = 1;int card_change = 0; /* 卡改变,卡插入开拔出 */ volatile INT16U card_id = 0; /* card slot identify, added 20060330 */ /* *************************************************************************************************** 用户API函数: 初始化,读,写,擦 SD卡 User API Function: Initialize,read,write,erase SD Card *************************************************************************************************** */char *m[12] = {"Jan", "Feb", "Mar", "Api", "May", "Jun", "Jul","Aug","Sep", "Oct","Nov","Dec" };char *tm_unit[] = { "1ns", "10ns", "100ns", "1us", "10us","100us","1ms","10ms"};char *tm_val[] = { "Reserved","1.0", "1.2", "1.3","1.5", "2.0", "2.5", "3.0","3.5","4.0","4.5", "5.0", "5.5", "6.0","7.0","8.0" };char *rate_unit[]={ "100kbit/s", "1Mbit/s", "10Mbit/s", "100Mbit/s"};char *curr_min[] ={ "0.5mA", "1mA", "5mA", "10mA", "25mA", "35mA", "60mA", "100mA"};char *curr_max[] ={ "1mA", "5mA", "10mA", "25mA", "35mA", "45mA", "80mA", "200mA" };char *file_format[] = { "Hard disk-like file system with partition table", "DOS FAT (floppy-like) with boot sector only (no partition table)", "Universal File Format", "Others / Unknown"};char *vtg[]={0,0,0,0,"1.6-1.7", "1.7-1.8", "1.8-1.9", "1.9-2.0", "2.0-2.1", "2.1-2.2", "2.2-2.3", "2.3-2.4", "2.4-2.5", "2.5-2.6", "2.6-2.7", "2.7-2.8", "2.8-2.9", "2.9-3.0", "3.0-3.1" , "3.1-3.2", "3.2-3.3", "3.3-3.4", "3.4-3.5", "3.5-3.6"};volatile int RCA; void SD_print_info(sd_struct *sds){ int i; Uart_Printf("\r\n\r\n SD|MMC Card Information \r\n\r\n" ); Uart_Printf("Manufacturer ID :%d\r\n", sds->MID); Uart_Printf("OEM/Application ID :%d\r\n", sds->OID); Uart_Printf("Product name :%s\r\n", sds->PNM); Uart_Printf("Product revision :%d.%d\r\n", (sds->PRV>>4), sds->PRV & 0xf); Uart_Printf("Product Serial NUmber :0x%x\r\n", sds->PSN); Uart_Printf("Manufacturing date :%s %d\r\n" ,m[sds->MDT&0xf], ((sds->MDT>>4) & 0xff) + 2000); Uart_Printf("CSD structure version :%s\r\n", (sds->CSD_stuc ? "NULL" : "Version 1.0")); Uart_Printf("data read access time -1 :%s.%s\r\n", tm_unit[sds->TAAC & 0x3], tm_val[(sds->TAAC & 0x7f) >> 3]); Uart_Printf("data read access time -2 :%d k clock cycles\r\n", sds->NSAC * 100); Uart_Printf("max data transfer rate :%s.%s\r\n", rate_unit[sds->NSAC & 0x3], tm_val[(sds->NSAC & 0x7f) >> 3]); Uart_Printf("card command classes supported :"); for(i=0;i<12;i++) { if((sds->CCC >> i) & 0x1) Uart_Printf("Class%d ",i); } Uart_Printf("\r\n"); Uart_Printf("VDD voltage Window :"); for(i=4; i<25; i++) { if( (sds->vtg_win >> i) & 0x1 ) Uart_Printf("%s ",vtg[i]); } Uart_Printf("\r\n"); Uart_Printf("Relative Card Address :%d\r\n", sds->RCA); Uart_Printf("Max read data block length :%d\r\n", 0x1 << sds->read_bl_len ); Uart_Printf("partial block for read allowed(allways = 1 in SD Memory Card) :%d\r\n", sds->read_bl_partial); Uart_Printf("Write block misalignment :%s\r\n", sds->write_blk_mis ? "crossing physical boundaries is allowed":"crossing physical boundaries is invalid"); Uart_Printf("Read block misalignment :%s\r\n", sds->read_blk_mis ? "crossing physical boundaries is allowed":"crossing physical boundaries is invalid"); Uart_Printf("DSR implemented :%s\r\n", sds->dsr_imp ? "DSR Implemented":"No DSR"); Uart_Printf("Device_size(C_size) :%d\r\n", sds->C_size); Uart_Printf("R/W min current :%s\r\n", curr_min[sds->vdd_r_curr_min]); Uart_Printf("R/W max current :%s\r\n", curr_max[sds->vdd_r_curr_max]); Uart_Printf("MULT :%d\r\n", (1 << (sds->C_Size_mult+2)) ); Uart_Printf("Erase Block Enable :%d\r\n", sds->erase_blk_en); Uart_Printf("Sector Size :%d\r\n", sds->sector_size); Uart_Printf("Size of Write Group :%d\r\n", sds->wp_grp_size); Uart_Printf("Write Group Enable :%d\r\n", sds->wp_grp_enable); Uart_Printf("R2W Factor :%d\r\n", sds->r2w_factor); Uart_Printf("Write Block Size :%d\r\n", (1<<sds->write_bl_len) ); Uart_Printf("WRITE_BL_PARTIAL :%d\r\n", sds->write_bl_partial); Uart_Printf("File Format Group :%d\r\n", sds->file_format_grp); Uart_Printf("Copy :%s\r\n", sds->copy ? "Copied":"Original"); Uart_Printf("Permanently Write Protect :%d\r\n", sds->perm_write_pro); Uart_Printf("Temperal Write Protect :%d\r\n", sds->tmp_write_pro); Uart_Printf("File Format :%s\r\n", file_format[sds->file_format]); Uart_Printf("---------Capacity of SD is :%d\r\n", (sds->C_size+1)*(1 << (sds->C_Size_mult+2)) * (1<<sds->read_bl_len));} /*********************************************************************************************************** Function name: SD_Initialize** Descriptions: initialize SD/MMC card** 初始化SD/MMC卡 ** Input: sd_struct *sds: SD卡信息结构体 sd_struct *sds: the information structure of SD Card** Output: 0: 正确 >0: 错误码 0: right >0: error code ** Created by: MingYuan Zheng 郑明远 ** Created Date: 2006-01-09 **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/INT8U SD_Initialize(sd_struct *sds){ INT8U response[16], ret; SD_HardWareInit(); /* 1. 初始化SD/MMC接口硬件 Initialize the hardware of SD/MMC interface */ ret = SD_ResetSD(); if (ret!= SD_NO_ERR) /* 2. 发出CMD0命令复位SD卡 send CMD0 command to reset SD/MMC card */ return ret; sds->card_type = Card_Indentify(); /* 3. 判别卡的型号:SD或MMC卡 identify card type: SD or MMC card */ ret = SD_ActiveCard(sds); /* 4. 激活SD/MMC卡 active SD/MMC card */ if (ret != SD_NO_ERR) return ret; ret = SD_ReadAllCID(16, response); /* 5. 请所有卡发送CID寄存器 ask all card send their CID number */ if (ret != SD_NO_ERR) return ret; /* cid information */ { sds->MDT = ((response[2] & 0xf)<<8) | response[1]; sds->PSN = (response[6] << 24) + (response[5] << 16) + (response[4] << 8) + response[3]; sds->PRV = response[7]; sds->PNM[0] = response[8]; sds->PNM[1] = response[9]; sds->PNM[2] = response[10]; sds->PNM[3] = response[11]; sds->PNM[4] = response[12]; sds->PNM[5] = 0; sds->OID = response[14] << 8 + response[13]; sds->MID = response[15]; } if (sds->RCA == 0) { card_id++; sds->RCA = card_id; /* 给卡分配一个地址 assign a address */ } ret = SD_GetRCA(sds->card_type, &sds->RCA); /* 6. 得到卡的RCA get the RCA of the card */ if (ret != SD_NO_ERR) return ret; ret = SD_GetCardInfo(sds); /* 7. 读CSD寄存器,获取SD卡信息 read CSD register, get the information of SD card */ if (ret != SD_NO_ERR) return ret; SD_ClkToMax(); /* 8. 设置读/写SD/MMC时钟到最大值 set clock of reading or writing SD/MMC to maximum */ ret = SD_SetBlockLen(sds->RCA, SD_BLOCKSIZE); return ret; /* 9. 设置块的长度: 512Bytes Set the block length: 512Bytes */}/*********************************************************************************************************** Function name: SD_ReadBlock** Descriptions: read a block from SD/MMC card** 从SD/MMC卡中读出一个块,先选中卡,然后设置数据控制寄存器,接着发送读块命令, 最后从数据缓冲区读取数据** Input: sd_struct *sds : SD/MMC卡信息结构体 sd_struct *sds : the information structure of SD/MMC Card INT32U blockaddr: 块地址 INT32U blockaddr: the address of the block INT8U *recbuf : 接收缓冲区,长度512Bytes INT8U *recbuf : the buffer of receive,length is 512Bytes** Output: 1: 成功 > 0: 错误码 1: sucessfully > 0: error code ** Created by: MingYuan Zheng 郑明远 ** Created Date: 2006-01-09 **-------------------------------------------------------------------------------------------------------** Modified by: ** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/INT8U SD_ReadBlock_1(sd_struct *sds, int blockaddr, int blocknum, INT8U *buf){ int rd_cnt = 0; INT8U ret,status[4]; INT32U stat = 0; //Uart_Printf("\r\n[MultiBlock read test]\n\r"); ret = SD_ReadCard_Status(sds->RCA, 4, status); /* 读取卡的状态 read the status of the card */ if (ret != SD_NO_ERR) return ret; ret = SD_SelectCard(sds->RCA); /* CMD7,进入传输状态 CMD7, enter tranfer status */ if (ret != SD_NO_ERR) return ret; if (sds->card_type == CARDTYPE_SD) { /* 卡为SD卡 card is SD card */ ret = SD_SetBusWidth(sds->RCA, 1); /* 设置卡为数据总线方式 set card to wide data bus */ if (ret != SD_NO_ERR) return ret; } SDIBSIZE = SD_BLOCKSIZE; /* 复位 FIFO reset FIFO */ SDIFSTA= SDIFSTA|(1<<16); //为什么多块读取总是从第一块读取呢 SDIDCON=(00<<22)|(1<<19)|(1<<17)|(1<<16)|(1<<14)|(2<<12)|(blocknum<<0); //YH 040220 ret = SD_ReadMultipleBlock(blockaddr); /* 读单块命令 read single blocks command */ if (ret != SD_NO_ERR) return ret; SDICSTA=0xa00; // Clear cmd_end(with rsp) //Uart_Printf("\r\n"); //Uart_Printf("%d Block\r\n", blockaddr++); while(rd_cnt<512*blocknum) // 512*block bytes { if((SDIDSTA&0x20)==0x20) // Check timeout { SDIDSTA=(0x1<<0x5); // Clear timeout flag break; } stat=SDIFSTA; if((stat&0x1000)==0x1000) // Is Rx data? { //int temp; //temp = SDIDAT; //Uart_Printf("0x%02x ", (temp>>24)&0xff); //Uart_Printf("0x%02x ", (temp>>16)&0xff); //Uart_Printf("0x%02x ", (temp>>8)&0xff); //Uart_Printf("0x%02x ", temp&0xff); //Uart_Printf("0x%02x ", SDIDAT8); //*(buf+rd_cnt) = SDIDAT8; buf[rd_cnt] = SDIDAT8; rd_cnt++; /* if( (rd_cnt & 0xf) == 0 ) { Uart_Printf("\r\n"); } if((rd_cnt & 0x1ff) == 0 ) { Uart_Printf("\r\n%d Block\r\n", blockaddr++); } */ } } SD_StopTransmission(); ret = SD_DeSelectCard(); /* CMD7, 退出传输状态 */ return ret; }INT8U SD_ReadBlock(sd_struct *sds, INT32U blockaddr, INT8U *recbuf){ INT8U ret,status[4]; ret = SD_ReadCard_Status(sds->RCA, 4, status); /* 读取卡的状态 read the status of the card */ if (ret != SD_NO_ERR) return ret; ret = SD_SelectCard(sds->RCA); /* CMD7,进入传输状态 CMD7, enter tranfer status */ if (ret != SD_NO_ERR) return ret; if (sds->card_type == CARDTYPE_SD) { /* 卡为SD卡 card is SD card */ ret = SD_SetBusWidth(sds->RCA, 1); /* 设置卡为数据总线方式 set card to wide data bus */ if (ret != SD_NO_ERR) return ret; } SDIBSIZE = SD_BLOCKSIZE; /* 复位 FIFO reset FIFO */ SDIFSTA= SDIFSTA|(1<<16); SDIDCON=(00<<22)|(1<<19)|(1<<17)|(1<<16)|(1<<14)|(2<<12)|(1<<0); //YH 040220 ret = SD_ReadSingleBlock(blockaddr); /* 读单块命令 read single blocks command */ if (ret != SD_NO_ERR) return ret; SDICSTA=0xa00; // Clear cmd_end(with rsp) /// read data ret = SD_ReadBlockData(SD_BLOCKSIZE, recbuf, sds->timeout_read); if (ret != SD_NO_ERR) return ret; ret = SD_DeSelectCard(); /* CMD7, 退出传输状态 */ return SD_NO_ERR; }/*********************************************************************************************************** Function name: SD_WriteBlock** Descriptions: write a block to SD/MMC card** 向SD/MMC卡中写入一个块 ** Input: sd_struct *sds : SD/MMC卡信息结构体 sd_struct *sds : the information structure of SD/MMC Card INT32U blockaddr: 块地址 INT32U blockaddr: the address of the block INT8U *sendbuf : 发送缓冲区,长度512Bytes INT8U *sendbuf : the buffer of send,length is 512Bytes** Output: 1: 成功 > 0: 错误码 1: sucessfully > 0: error code ** Created by: MingYuan Zheng 郑明远 ** Created Date: 2006-01-09 **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/INT8U SD_WriteBlock(sd_struct *sds, INT32U blockaddr, const INT8U *sendbuf){ INT8U ret,tmp[4]; ret = SD_ReadCard_Status(sds->RCA, 4, tmp); /* 读取卡的状态 read the status of the card */ if (ret != SD_NO_ERR) return ret; ret = SD_SelectCard(sds->RCA); /* CMD7,进入传输状态 CMD7, enter tranfer status */ if (ret != SD_NO_ERR) return ret; if (sds->card_type == CARDTYPE_SD) { /* 卡为SD卡 card is SD card */ ret = SD_SetBusWidth(sds->RCA, 1); /* 设置卡为数据总线方式 set card to wide data bus */ if (ret != SD_NO_ERR) return ret;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -