📄 sdi.c
字号:
sdi_dma_setup(SDI_READ,Rx_buf,1);//设置sdi的DMA通道 *sdi_control_obj.sdidcon=(1<<SDIDCON_RACMD_OFFSET)| (1<<SDIDCON_BLK_MODE_OFFSET)| (1<<SDIDCON_WIDE_BUS_OFFSET)| (1<<SDIDCON_DMA_ENABLE_OFFSET)| (2<<SDIDCON_DAT_MODE_OFFSET)| (1<<SDIDCON_BLK_NUM_OFFSET); /* * 向SD卡发送读单个块的命令(CMD17 READ_BLOCK) */ cmd_status=sdi_send_cmd(SD_CMD(17),sd_addr,SHORT_RESP,CRC_CHECK); if(cmd_status!=1) { return 0; } while(!sys_dma2_done);//等待DMA的完成 *sdi_control_obj.sdidcon&=~(1<<15);//关闭sdi的DMA if(!sdi_data_check())//数据检测 { return 0;//读取出错 } else { return 1;//读取成功 }}/* parm: pageIndex the start page numberPages number of pages will be wrote *ptrBuffer the date buffer return: the wrote data size(byte)---writed page*512*/int sdWrite(unsigned int pageIndex, unsigned int numberPages, unsigned char *ptrBuffer){ int page; int err; for(page=pageIndex,err=0;page<pageIndex+numberPages;) { if(sdi_dma_write_block(sdi_RCA,ptrBuffer+((page-pageIndex)*512),BLOCK(page))) { page++; } else { err++; if(err==10) return 0; } } return 1; }/* parm: pageIndex the start page numberPages number of pages will be wrote *ptrBuffer the date buffer return: the readed data size(byte)---readed page*512*/int sdRead(unsigned int pageIndex, unsigned int numberPages, unsigned char *ptrBuffer){ int page; int err; for(page=pageIndex,err=0;page<pageIndex+numberPages;) { if(sdi_dma_read_block(sdi_RCA,ptrBuffer+((page-pageIndex)*512),BLOCK(page))) { page++; } else { err++; if(err==10) { return 0; } } } return 1; }int sdi_erase_blocks(unsigned short rca,unsigned int start_blk_addr, unsigned int end_blk_addr){ unsigned int card_state; int cmd_status; int check_conter; /* * 循环检测SD卡,直到其处于tran状态 */ for(check_conter=0;check_conter<100;check_conter++) { cmd_status=sdi_send_status(rca,&card_state); if((CURRENT_STATE(card_state)==TRAN_STATE) && cmd_status) { break; } } if(check_conter==100) { #ifdef SDI_DEBUG printk("function \"sdi_erase_blocks\" card state fail %0x,%0x.\n", (card_state>>9)&0xf,cmd_status); #endif return 0; } sdi_send_cmd(SD_CMD(32),start_blk_addr,SHORT_RESP,CRC_CHECK); sdi_send_cmd(SD_CMD(33),end_blk_addr,SHORT_RESP,CRC_CHECK); sdi_send_cmd(SD_CMD(38),0x00000000,SHORT_RESP,CRC_CHECK); if(cmd_status) return (end_blk_addr-start_blk_addr)/512;}/* * Resets all cards to Idle State * 将所有卡设置为Idle状态 */void sdi_go_idle_state(){ sdi_send_cmd(SD_CMD(0),-1,NO_RESP,CRC_UNCHECK);}/* * check OCR,make sure the sd_card is power on * 检测OCR,确认SD卡已经上电 */int sdi_check_power_on(){ int check_count; for(check_count=0;check_count<100;check_count++) { sdi_send_cmd(SD_CMD(55),DEFAULT_RCA,SHORT_RESP,CRC_CHECK); sdi_send_cmd(SD_CMD(41),0xff8000,SHORT_RESP,CRC_UNCHECK); if(((*sdi_control_obj.sdirsp0)>>31)&0x01) { #ifdef SDI_DEBUG printk("SD Card is power on.\n"); sdi_dump_OCR(*sdi_control_obj.sdirsp0); #endif return 1; } delay(100);//必须加上延迟 } #ifdef SDI_DEBUG printk("SD Card is not insert.\n"); #endif return 0;}/* * Addressed card send its CSD number * 获得指定SD卡的CSD号 */int sdi_send_CSD(unsigned short rca, struct CSD_register_struct *CSD){ unsigned int rca_tmp=rca<<16; unsigned int resp0,resp1,resp2,resp3; int cmd_status; cmd_status=sdi_send_cmd(SD_CMD(9),rca_tmp,LONG_RESP,CRC_UNCHECK); resp0=*sdi_control_obj.sdirsp3; resp1=*sdi_control_obj.sdirsp2; resp2=*sdi_control_obj.sdirsp1; resp3=*sdi_control_obj.sdirsp0; CSD->CSD_STRUCTURE =(resp3>>30)&0x3; CSD->TAAC =(resp3>>16)&0xff; CSD->NSAC =(resp3>>8)&0xff; CSD->TRAN_SPEED = resp3&0xff; CSD->CCC =(resp2>>20)&0xfff; CSD->READ_BL_LEN =(resp2>>16)&0xf; CSD->READ_BL_PARTIAL =(resp2>>15)&0x1; CSD->WRITE_BLK_MISALIGN =(resp2>>14)&0x1; CSD->READ_BLK_MISALIGN =(resp2>>13)&0x1; CSD->DSR_IMP =(resp2>>12)&0x1; CSD->C_SIZE =((resp2&0x3FF)<<2)|((resp1>>30)&0x3); CSD->VDD_R_CURR_MIN =(resp1>>27)&0x7; CSD->VDD_R_CURR_MAX =(resp1>>24)&0x7; CSD->VDD_W_CURR_MIN =(resp1>>21)&0x7; CSD->VDD_W_CURR_MAX =(resp1>>18)&0x7; CSD->C_SIZE_MULT =(resp1>>15)&0x7; CSD->ERASE_BLK_EN =(resp1>>14)&0x1; CSD->SECTOR_SIZE =(resp1>>7)&0x7f; CSD->WP_GRP_SIZE =(resp1>>0)&0x7f; CSD->WP_GRP_ENABLE =(resp0>>31)&0x1; CSD->R2W_FACTOR =(resp0>>26)&0x7; CSD->WRITE_BL_LEN =(resp0>>22)&0xf; CSD->WRITE_BL_PARTIAL =(resp0>>21)&0x1; CSD->FILE_FORMAT_GRP =(resp0>>15)&0x1; CSD->COPY =(resp0>>14)&0x1; CSD->PERM_WRITE_PROTECT =(resp0>>13)&0x1; CSD->TMP_WRITE_PROTECT =(resp0>>12)&0x1; CSD->FILE_FORMAT =(resp0>>10)&0x3; CSD->CRC =(resp0>>1)&0xff; printk("%0x %0x %0x %0x\n",resp0,resp1,resp2,resp3); return cmd_status;}void dump_CSD(){ }unsigned int get_sd_card_capacity(struct CSD_register_struct CSD){ unsigned int blocknr; unsigned int block_len; unsigned int mult; int i; for(block_len=1,i=0;i<CSD.READ_BL_LEN;i++) { block_len=block_len*2; } for(mult=1,i=0;i<(CSD.C_SIZE_MULT+2);i++) { mult=mult*2; } blocknr=(CSD.C_SIZE+1)*mult; return blocknr*block_len;}/* * Asks any card to send their CID numbers * 获得SD卡的CID号 */int sdi_all_send_CID(struct CID_struct *CID){ unsigned int resp0,resp1,resp2,resp3; int cmd_status; cmd_status=sdi_send_cmd(SD_CMD(2),-1,LONG_RESP,CRC_UNCHECK); resp0=*sdi_control_obj.sdirsp3; resp1=*sdi_control_obj.sdirsp2; resp2=*sdi_control_obj.sdirsp1; resp3=*sdi_control_obj.sdirsp0; CID->CRC_1 =(resp0>>1)&0xff; //resp0 1~7 CID->MDT =(resp0>>8)&0xffff; //resp0 8~23 CID->PSN =((resp1&0xffffff)<<8)|((resp0>>24)&0xff); CID->PRV =(resp1>>24)&0xff; //resp1 24~31 CID->PNM[0] =(resp2)&0xff; //resp2 0~7 CID->PNM[1] =(resp2>>8)&0xff; //resp2 8~15 CID->PNM[2] =(resp2>>16)&0xff; //resp2 16~23 CID->PNM[3] =(resp2>>24)&0xff; //resp2 24~31 CID->PNM[4] =(resp3)&0xff; //resp3 0~7 CID->OID =(resp3>>8)&&0xffff; //resp3 8~23 CID->MID =(resp3>>24)&0xff; //resp3 24~31 return cmd_status;}/* * Addressed card send its CID numbers * 获得指定SD卡的CID号 */int sdi_send_CID(unsigned short rca, struct CID_struct *CID){ unsigned int rca_tmp=rca<<16; unsigned int resp0,resp1,resp2,resp3; int cmd_status; cmd_status=sdi_send_cmd(SD_CMD(10),rca_tmp,LONG_RESP,CRC_UNCHECK); resp0=*sdi_control_obj.sdirsp3; resp1=*sdi_control_obj.sdirsp2; resp2=*sdi_control_obj.sdirsp1; resp3=*sdi_control_obj.sdirsp0; CID->CRC_1 =(resp0>>1)&0xff; //resp0 1~7 CID->MDT =(resp0>>8)&0xffff; //resp0 8~23 CID->PSN =((resp1&0xffffff)<<8)|((resp0>>24)&0xff); CID->PRV =(resp1>>24)&0xff; //resp1 24~31 CID->PNM[0] =(resp2)&0xff; //resp2 0~7 CID->PNM[1] =(resp2>>8)&0xff; //resp2 8~15 CID->PNM[2] =(resp2>>16)&0xff; //resp2 16~23 CID->PNM[3] =(resp2>>24)&0xff; //resp2 24~31 CID->PNM[4] =(resp3)&0xff; //resp3 0~7 CID->OID =(resp3>>8)&&0xffff; //resp3 8~23 CID->MID =(resp3>>24)&0xff; //resp3 24~31 return cmd_status;}void sdi_dump_CID(struct CID_struct CID){ printk("CRC7 checksum: 0x%0x\n",CID.CRC_1); printk("Manufacture Data Code: 0x%0x\n",CID.MDT); printk("Serial Number: 0x%0x\n",CID.PSN); printk("Product Revision: %d.%d\n",(CID.PRV&0xf0)>>4,CID.PRV&0xf); printk("Product Name: %c%c%c%c%c\n", CID.PNM[4],CID.PNM[3],CID.PNM[2], CID.PNM[1],CID.PNM[0]); printk("OEM/Application ID: 0x%0x\n",CID.OID); printk("Manufacture ID: 0x%0x\n",CID.MID);}/* * Asks the card to publish a new relative address * SD卡发布RCA */int sdi_send_RCA(unsigned short *RCA){ unsigned short card_status; int cmd_status; //R6 cmd_status=sdi_send_cmd(SD_CMD(3),-1,SHORT_RESP,CRC_CHECK); //card_status card_status=(*sdi_control_obj.sdirsp0)&0xffff; //获得SD卡的RCA *RCA=(*sdi_control_obj.sdirsp0)>>16; #ifdef SDI_DEBUG printk("card_status: 0x%0x\n",card_status); #endif return cmd_status; }void sdi_dump_RCA(unsigned short RCA){ printk("sdi_RCA: 0x%0x\n",RCA);}/* * 选择指定的SD卡 */int select_card(unsigned short rca){ int cmd_status; unsigned int rca_tmp=rca<<16; cmd_status=sdi_send_cmd(SD_CMD(7),rca_tmp,SHORT_RESP,CRC_CHECK); #ifdef SDI_DEBUG sdi_dump_card_status(*sdi_control_obj.sdirsp0); #endif return cmd_status;}/* * 设置SD卡带宽 */int sdi_set_bus_width(unsigned short rca,unsigned char wide){ unsigned int rca_tmp=rca<<16; int cmd_status; cmd_status=sdi_send_cmd(SD_CMD(55),rca_tmp,SHORT_RESP,CRC_CHECK); cmd_status=sdi_send_cmd(SD_CMD(6),wide<<1,SHORT_RESP,CRC_CHECK); return cmd_status;}int sdi_send_status(unsigned short rca,unsigned int *status){ int cmd_status; cmd_status=sdi_send_cmd(SD_CMD(13),rca<<16,SHORT_RESP,CRC_CHECK); *status=*sdi_control_obj.sdirsp0; return cmd_status;}/* * 设置SD卡每个block的字节数 */int sdi_set_blocklen(unsigned int block_len){ int cmd_status; cmd_status=sdi_send_cmd(SD_CMD(16),block_len,SHORT_RESP,CRC_CHECK); return cmd_status;}void sdi_dump_card_status(unsigned int status){ unsigned char current_status; current_status=(status>>9)&0x0f; printk("card status:"); switch(current_status) { case 0: printk("idle\n"); break; case 1: printk("ready\n"); break; case 2: printk("ident\n"); break; case 3: printk("stby\n"); break; case 4: printk("tran\n"); break; case 5: printk("data\n"); break; case 6: printk("rcv\n"); break; case 7: printk("prg\n"); break; case 8: printk("dis\n"); break; }}void sdi_dump_OCR(unsigned int OCR){ printk("0-8 bits:0x%0x\n",OCR&0xff); printk("8-16 bits:0x%0x\n",(OCR>>8)&0xff); printk("16-24 bits:0x%0x\n",(OCR>>16)&0xff); printk("24-30 bits:0x%0x\n",(OCR>>24)&0x7f); printk("31 bits:0x%0x\n",(OCR>>31)&0x1);}void sdi_init(){ int i; //初始化命令数组 init_sd_cmd(); *sdi_control_obj.sdipre=(get_PCLK()/(2*400000))-1; *sdi_control_obj.sdicon=(1<<4)|(1<<3)|(1<<1)|1; *sdi_control_obj.sdibsize=0x200; *sdi_control_obj.sdidtimer=0xffff; delay(500); sdi_go_idle_state(); //CMD0 go Idle State if(sdi_check_power_on())//ACMD41 Ready State { sdi_all_send_CID(&sdi_CID);//CMD2 Identification State //sdi_dump_CID(sdi_CID); sdi_send_RCA(&sdi_RCA); //CMD3 Stand-by State *sdi_control_obj.sdipre=(get_PCLK()/(2*25000000))-1; // Normal clock=25MHz select_card(sdi_RCA); sdi_set_bus_width(sdi_RCA,WIDE_BUS); sdi_set_blocklen(512); //sdi_send_CSD(sdi_RCA,&sdi_CSD); //printk("\ncapacity: %d byte\n",get_sd_card_capacity(sdi_CSD)); //sdi_send_status(sdi_RCA,&sdi_status); /* * 下面的这部分代码仅用于测试sd卡的读写,不必理会 for(i=0;i<512*10;i++) { sd_Tx_buf[i]=i/512+1; } //sdWrite(3840,2,sd_Tx_buf); sdRead(3840,2,sd_Rx_buf); dump_sd_Rx_buf(0); printk("\n"); dump_sd_Rx_buf(1); printk("\nsd ok.\n");*/ } else { printk("SD Card not insert.\n"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -