📄 mmc.c
字号:
/************************************************************** * ARMSYS-P, LiYuTai elec. * * MMC Card functions ************************************************************/#include "mmc.h"/************************************************************* * MMC Init function * * - flushes card receive buffer * - selects card * - sends the reset command * - sends the initialization command, waits for card ready * - queries card status *************************************************************/int mmc_init(void){ unsigned char c,d; unsigned int stat; mcu_io_init_formmc(); mmc_deselect(); /* start off with 80 bits of high data with card deselected */ for(d=0;d<10;d++) c = spi_byte(0xff); mmc_select(); /* select card */ /* now send CMD0 - go to idle state, try up to 16 times */ d = 100; while(c != 1 && d--) { mmc_command(0,0,0); /* software reset command */ c = mmc_get_r1(); Delay(10); } if(c != 1) { Uart_Printf("MMC is not detected\n"); return(-1); } else Uart_Printf("MMC is detected\n"); /* send CMD1 until we get a 0 back, indicating card is done initializing */ d = 255; /* but only do it up to 16 times */ c = 1; while(c && d--) { mmc_command(1,0,0); c = mmc_get_r1(); /* Uart_Printf(PSTR("c = ")); putchar(c); Uart_Printf(PSTR("\n")); */ //Uart_Printf("c=%x\n", c); Delay(10); } if(c) { Uart_Printf(" init failed\n"); return(-1); } else Uart_Printf(" card initialized.\n"); /* now we query the card status */ mmc_command(13,0,0); stat = mmc_get_r2(); Uart_Printf(" card status: "); if(stat) { Uart_Printf("ERROR\n"); return(-1); } else Uart_Printf("OK\n"); return 0;}/************************************************************ * MMC command * * - send one byte of 0xff, then issue command + params + (fake) crc * - eat up the one command of nothing after the CRC ************************************************************/int mmc_command(unsigned char command, unsigned int px, unsigned int py){ mmc_select(); spi_byte(0xff); spi_byte(command | 0x40); spi_byte((unsigned char)((px >> 8)&0x0ff)); /* high byte of param x */ spi_byte((unsigned char)(px & 0x00ff)); /* low byte of param x */ spi_byte((unsigned char)((py >> 8)&0x0ff)); /* high byte of param y */ spi_byte((unsigned char)(py & 0x00ff)); /* low byte of param y */ spi_byte(0x95); /* correct CRC for first command in SPI */ /* after that CRC is ignored, so no problem with */ /* always sending 0x95 */ spi_byte(0xff); return 0; }/************************************************************ * MMC get R1 * * - pings the card until it gets a non-0xff value * - returns one byte of read info ************************************************************/unsigned char mmc_get_r1(void){ unsigned char i,c; for(i=0;i<8;i++) { /* response will be after 1-8 0xffs.. */ c = spi_byte(0xff); if(c != 0xff) /* if it isn't 0xff, it is a response */ return(c); } return(c);}/************************************************************ * MMC get R2 * * - pings the card until it gets a non-0xff value * - returns one 16 bit word of read info ************************************************************/int mmc_get_r2(void){ unsigned int r; r = ((mmc_get_r1())<< 8) & 0xff00; r |= spi_byte(0xff); return(r);}/************************************************************ * MMC set_sector * * - write a sector to the card (512 bytes) * - takes sector # as param ************************************************************/int mmc_write_sector(unsigned long int sector_num, unsigned char * s){ // int addr; // char pattern, status=0; unsigned char c,d; unsigned int i; /* sectors are 512 bytes, which is 0x200 or 9 bits */ /* to format properly for mmc_command call, we get the high word */ /* of the address by shifting sector_num left 9 bits then right 16 bits */ /* which works out to be a total of 7 right shifts. */ /* low address word is reached by just left shifting sector num 9 bits */ mmc_command(24, (sector_num>>7)& 0xffff, (sector_num<<9)& 0xffff); c = mmc_get_r1(); // d = mmc_get_r1(); i = 0xffff; while((c !=0) && (i--)) { /* wait for data token */ c = mmc_get_r1(); } if(c != 0x0) { /* data token ? */ Uart_Printf("Can't write\n"); return(-1); } spi_byte(0xfe); for(i=0;i<512;i++) /* read the sector */ spi_byte(*s++); spi_byte(0xff); /* checksum -> don't care about it for now */ spi_byte(0xff); i = 0xffff; while(i--) { c=spi_byte(0xff); d=c; c&=0x11; if(c==0x1) break; } if(c==0x1) { while(c!=0xff) { c=spi_byte(0xff); } d&=0xe; if(d==4) Uart_Printf("Write O.K.\n"); mmc_deselect(); return(0); } mmc_deselect(); Uart_Printf("Write Failed.\n"); return(-1);}/************************************************************ * MMC get_sector * * - reads a sector from the card (512 bytes) * - takes sector # as param ************************************************************/int mmc_read_sector(unsigned long int sector_num, unsigned char * s){ unsigned char c,d; unsigned int i; unsigned char *buf; //int addr; //unsigned char buf[512]; /* sectors are 512 bytes, which is 0x200 or 9 bits */ /* to format properly for mmc_command call, we get the high word */ /* of the address by shifting sector_num left 9 bits then right 16 bits */ /* which works out to be a total of 7 right shifts. */ /* low address word is reached by just left shifting sector num 9 bits */ mmc_command(17, (sector_num>>7)& 0xffff, (sector_num<<9)& 0xffff); c = mmc_get_r1(); d = mmc_get_r1(); i = 0xffff; while(d == 0xff && i--) { /* wait for data token */ d = mmc_get_r1(); } if(c || d != 0xfe) { /* data token ? */ Uart_Printf("MMC: error during block read\n"); Uart_Printf(" c = %x d = %x sector = %x\n",c,d,sector_num); return(-1); } buf=s; for(i=0;i<512;i++) /* read the sector */ *s++ = spi_byte(0xff); spi_byte(0xff); /* checksum -> don't care about it for now */ spi_byte(0xff); mmc_deselect(); //-- Display Rx buffer s=buf; for(i=1;i<=512;i++) { Uart_Printf("%2x ",*s++); if(i==256) { Uart_Printf("\nPress ESC key to Exit, other key to continue..."); if(Uart_Getch()==ESC_KEY) { Uart_Printf("\n"); return 0; } } if((i%16)==0) Uart_Printf("\n"); } return(0);}/************************************************************ * MMC print card info * * - gets and prints formatted CID and CSD info from card ************************************************************/int mmc_print_card_info(void){ unsigned char c,d,c_mult; unsigned int i,bl_len,c_size; unsigned long int j; mmc_command(10,0,0); c = mmc_get_r1(); d = mmc_get_r1(); if(c || d != 0xfe) Uart_Printf("MMC: error during CID read\n"); /* get Manufacturer ID in 127:104 (3 bytes) */ //Uart_Printf("\n"); c = spi_byte(0xff); Uart_Printf(" Manufacturer ID: 0x%x",c); c = spi_byte(0xff); Uart_Printf("%x",c); c = spi_byte(0xff); Uart_Printf("%x\n",c); /* get Product name in 103:48 (7 byte string) */ Uart_Printf(" Product name: "); for(i=0;i<7;i++) putchar(spi_byte(0xff)); Uart_Printf("\n"); c = spi_byte(0xff); /* get HW and FW revs in 47:44 (1 byte) */ Uart_Printf(" HW Revision: %d\n",c>>4); Uart_Printf(" FW Revision: %d\n",c&0x0f); /* Serial number is in 39:16 (3 bytes) */ c = spi_byte(0xff); Uart_Printf(" Serial Number: 0x%x",spi_byte(0xff)); c = spi_byte(0xff); Uart_Printf("%x",c); c = spi_byte(0xff); Uart_Printf("%x\n",c); c = spi_byte(0xff); /* get Month/Year in 15:12 (1 byte) */ Uart_Printf(" Manufacture Date: %d/%d\n",c>>4,1997+(c&0x0f)); spi_byte(0xff); /* CRC */ spi_byte(0xff); spi_byte(0xff); spi_byte(0xff); mmc_command(9,0,0); c = mmc_get_r1(); d = mmc_get_r1(); if(c || d != 0xfe) Uart_Printf("MMC: error during CSD read\n"); c = spi_byte(0xff); /* Uart_Printf("CSD structure: %d\n",c>>6); */ Uart_Printf(" MMC spec version: %d\n",(c>>2)&0x0f); c = spi_byte(0xff); /* Uart_Printf("TAAC: %d\n",c); */ c = spi_byte(0xff); /* Uart_Printf("NSAC: %d\n",c); */ c = spi_byte(0xff); /* Uart_Printf("Speed: %d\n",c); */ c = spi_byte(0xff); /* throwing away CCC */ c = spi_byte(0xff); bl_len = c&0x0f; /* keep this for calculating device size */ Uart_Printf(" Read block length : %d bytes\n",(1<<bl_len)); /* get C_SIZE, used for calculating device size */ c = spi_byte(0xff); c_size = (c & 0x03)<<10; c_size |= (spi_byte(0xff))<<2; c = spi_byte(0xff); c_size |= c>>6; /* get current consumptions */ Uart_Printf(" Read current @Vdd_min: %dma\n",((c>>3)&0x07)*25); /* Uart_Printf(PSTR("Read current @Vdd_max: %dma\n",(c&0x07)*35); */ c = spi_byte(0xff); /* Uart_Printf(PSTR("Write current @Vdd_min: %dma\n",((c>>5)&0x07)*35);*/ Uart_Printf(" Write current @Vdd_max: %dma\n",((c>>2)&0x07)*45); /* get the multiplication factor for device size calculation */ c_mult = (c & 0x03)<<1; c = spi_byte(0xff); c_mult |= (c>>7)&0x01; /* device size calculation - from the MMC guide */ /* for some reasone it has to be done in several steps.. */ j = c_size + 1; j *= 1<<(c_mult+2); j *= 1<<bl_len; Uart_Printf(" Device Size : %ldk\n",j/1000); /* extra stuff we don't care about + CRC */ for(d=0;d<10;d++) spi_byte(0xff); mmc_deselect(); return(0);}void sdmmc_test(void){ int i,blknum; //unsigned char pattern; unsigned char buf[512]; Uart_Printf("[SD/MMC single block write & read test]\n"); Uart_Printf("Input number of the block to write\n"); blknum=Uart_GetIntNum(); //Uart_Printf("\nInput the char pattern to write..\n"); //pattern=(char)Uart_GetIntNum(); for(i=0;i<512;i++) { buf[i]=i;//pattern; } if(mmc_init()==0) { mmc_print_card_info(); mmc_write_sector(blknum,buf); Uart_Printf("Press ESC key to Exit, other key to continue...\n"); if(Uart_Getch()==ESC_KEY) return; mmc_read_sector(blknum,buf); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -