标签:
二、MMC/SD卡的模型和工作原理 PIN脚、SD卡总线、SD卡结构、SD卡寄存器、上电过程 SD卡寄存器:
--------------------------------------------------------------------------- static void sd_init(void) { int retries; u8 *resp; unsigned int cardaddr; / resp = mmc_cmd(2, 0, MSC_CMDAT_RESPONSE_R2, MSC_CMDAT_RESPONSE_R2); //serial_puts(" SD carsd CID =R2= "); serial_dump_data(resp, 15); resp = mmc_cmd(3, 0, MSC_CMDAT_RESPONSE_R1, MSC_CMDAT_RESPONSE_R1); cardaddr = (resp[4] << 8) | resp[3]; //发生3命令 来或者rca rca = cardaddr << 16; //serial_puts("rca="); serial_puts_hex(rca); resp = mmc_cmd(9, rca, MSC_CMDAT_RESPONSE_R2, MSC_CMDAT_RESPONSE_R2); sd2_0 = (resp[14] & 0xc0) >> 6; //serial_puts("sd2_0====="); serial_puts_hex(sd2_0); //serial_puts(" SD carsd CSD Register =R2= "); serial_dump_data(resp, 16); OUTREG16(A_MSC_CLKRT(0), 0); resp = mmc_cmd(7, rca, MSC_CMDAT_BUSY | MSC_CMDAT_RESPONSE_R1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(55, rca, MSC_CMDAT_RESPONSE_R1, MSC_CMDAT_RESPONSE_R1); resp = mmc_cmd(6, 0x2, MSC_CMDAT_BUS_WIDTH_4BIT | MSC_CMDAT_RESPONSE_R1|MSC_CMDAT_BUSY, MSC_CMDAT_RESPONSE_R1);//应答类型R1b //while(!(INREG16(A_MSC_STAT(0))&(1<<13)));//等待编程完成 } ------------------------------------------------------------ //从这儿开始看 int mmc_init(void) // { int retries; u8 *resp; OUTREG32(A_CPM_MSCCDR,13); SETREG32(A_CPM_CPCCR, CPCCR_CHANGE_EN); MMC_INIT_GPIO(); __msc_reset(); MMC_IRQ_MASK(); OUTREG32(A_MSC_CLKRT(0), 7);//extclk/128 //OUTREG32(A_MSC_LPM(0),0x01); //sd2_0 = 0; //默认为标准SD卡 resp = mmc_cmd(0, 0, 80, 0); //先80个时钟 resp = mmc_cmd(8, 0x1aa, 0x1, MSC_CMDAT_RESPONSE_R1); //判断是sd2(返回0x1)以后的卡还是sd1(返回0x5)现在基本都是sd2以后 的所以都没有对返回值判断 resp = mmc_cmd(55, 0, MSC_CMDAT_RESPONSE_R1, MSC_CMDAT_RESPONSE_R1); //根据cmd55来判断是mmc卡还是sd卡,只有卡才有55命令 才能正确有返回值 返回值有command index =0x37=55 的话说明是sd //serial_puts(" Application Specific Commands =R1= "); serial_dump_data(resp, 6); if(resp[5] != 0x37) { //是mmc卡 //serial_puts("MMC card found!\n"); retries = 200; do{ resp = mmc_cmd(1, 0x40ff8000, MSC_CMDAT_RESPONSE_R3, MSC_CMDAT_RESPONSE_R3); //匹配电压 mmc卡是CMD1 SD卡是CMD41 因为上电是要一个时间的 所以就利用一个do{}while 来延时 sd_mdelay(10); } while (retries-- && !(resp[4] & 0x80)); //直到r3中的ocr回复值中的31位为1的时候表示上电完成了 if(resp[4]&0x40)//电压验证最后一次应答中带有数据访问模式位,如果为1,则类似SDHC卡基于块地址访问 { sd2_0 = 1; // 也可以利用r3 返回值中的ocr的30位来检查是高容量卡(>2G)还是标准卡 其实也可以利用cmd9命令读取cds来判断 在sd就是这么做的 } #if 0 serial_puts(" OCR =R3= "); serial_dump_data(resp, 6); if (resp[4]& 0x80) serial_puts("\n\nMMC init ok\n\n");// 表示上电完成 else serial_puts("\n\nMMC init fail\n\n"); #endif resp = mmc_cmd(2, 0, MSC_CMDAT_RESPONSE_R2, MSC_CMDAT_RESPONSE_R2); //获取CID //serial_puts(" CID CSD =R2= "); serial_dump_data(resp, 16); resp = mmc_cmd(3, 0x10, MSC_CMDAT_RESPONSE_R1, MSC_CMDAT_RESPONSE_R1); //这个东西就很恶心了 在sd卡和mmc卡的参数不一样 mmc卡的参数是自己设定一个rca值 ,但是sd卡是通过回复值中读取rca,上面sd卡的初始化中有描述 OUTREG16(A_MSC_CLKRT(0), 1); resp = mmc_cmd(7, 0x10, MSC_CMDAT_RESPONSE_R1, MSC_CMDAT_RESPONSE_R1);//设置新地址为有效地址 这样就进入了tarnsport mode .只有发送了7号命令 还有设置位宽CMD6 才能发生正在的进行读写发生16 17 18等 resp = mmc_cmd(6, 0x3b70101, MSC_CMDAT_BUS_WIDTH_4BIT|MSC_CMDAT_RESPONSE_R1|MSC_CMDAT_BUSY, MSC_CMDAT_RESPONSE_R1);//应答类型R1b,设置位宽 为4BIT模式 resp = mmc_cmd(13, rca, MSC_CMDAT_RESPONSE_R1, MSC_CMDAT_RESPONSE_R1); card_status = (resp[4] << 24) | (resp[3] << 16) | (resp[2] << 8) | resp[1]; serial_puts("mmc_cmd 13\n"); if((card_status & 0x900) != 0x900) //ready && tran { return OPEN_CARD_INIT_CHECK_STATUS_ERROR; } //对于mmc卡经常要加CMD13,不然经常会出现问题的,CMD13在发生玩cmd3后就可以随时发送 while(!(INREG16(A_MSC_STAT(0))&(1<<13)));//等待编程完成 } else//如果是sd卡 sd_init(); return 0;
当卡发生完CMD3后进入待机状态(stand-by state),cmd7可以让卡进入transport状态,
标签:
原文地址:http://www.cnblogs.com/heiyue/p/4415095.html