📄 mmcfmt.c
字号:
spi_cmd[0] = 9;
printf_P(PSTR("\n\rResponse to CMD9: 0 / %d"), spi_command());
while(spi_byte(0xFF) != 0xFE); // wait for data start token; add time-out?
for(i=0; i<16; i++)
reg_csd[15-i] = spi_byte(0xFF); // fill in from MSB
printf_P(PSTR("\n\r Contents of CSD Register:")); // defaults from SanDisk 32MB card / read values
printf_P(PSTR("\n\r CSD_STRUCTURE: 1 / %x"), get_slice(reg_csd,127,126) );
printf_P(PSTR("\n\r MMC_PROT: 1 / %x"), get_slice(reg_csd,125,122) );
printf_P(PSTR("\n\r Reserved: 0 / %x"), get_slice(reg_csd,121,120) );
printf_P(PSTR("\n\r TAAC: 26 / %x"), get_slice(reg_csd,119,112) );
printf_P(PSTR("\n\r NSAC: 0 / %x"), get_slice(reg_csd,111,104) );
printf_P(PSTR("\n\r TRAN_SPEED: 2a / %x"), get_slice(reg_csd,103,96) );
printf_P(PSTR("\n\r CCC: 1ff / %x"), get_slice(reg_csd,95,84) );
read_bl_len=get_slice(reg_csd,83,80);
printf_P(PSTR("\n\r READ_BL_LEN: 9 / %x"), read_bl_len );
printf_P(PSTR("\n\r READ_BL_PARTIAL: 1 / %x"), get_slice(reg_csd,79,79) );
printf_P(PSTR("\n\r WRITE_BLK_MISALIGN: 0 / %x"), get_slice(reg_csd,78,78) );
printf_P(PSTR("\n\r READ_BLK_MISALIGN: 0 / %x"), get_slice(reg_csd,77,77) );
printf_P(PSTR("\n\r DSR_IMP: 0 / %x"), get_slice(reg_csd,76,76) );
printf_P(PSTR("\n\r Reserved: 0 / %x"), get_slice(reg_csd,75,74) );
block_cnt=get_slice(reg_csd,73,62); // this var is c_size, not block count; just using the block cnt to save space (instead of creating new var)
printf_P(PSTR("\n\r C_SIZE: - / %x"), block_cnt );
printf_P(PSTR("\n\r VDD_R_CURR_MIN: 4 / %x"), get_slice(reg_csd,61,59) );
printf_P(PSTR("\n\r VDD_R_CURR_MAX: 4 / %x"), get_slice(reg_csd,58,56) );
printf_P(PSTR("\n\r VDD_W_CURR_MIN: 5 / %x"), get_slice(reg_csd,55,53) );
printf_P(PSTR("\n\r VDD_W_CURR_MAX: 5 / %x"), get_slice(reg_csd,52,50) );
c_size_mult=get_slice(reg_csd,49,47);
printf_P(PSTR("\n\r C_SIZE_MULT: - / %x"), c_size_mult );
printf_P(PSTR("\n\r SECTOR_SIZE: 0 / %x"), get_slice(reg_csd,46,42) );
printf_P(PSTR("\n\r ERASE_GRP_SIZE: - / %x"), get_slice(reg_csd,41,37) );
printf_P(PSTR("\n\r WP_GRP_SIZE: 1f / %x"), get_slice(reg_csd,36,32) );
printf_P(PSTR("\n\r WP_GRP_ENABLE: 1 / %x"), get_slice(reg_csd,31,31) );
printf_P(PSTR("\n\r DEFAULT_ECC: 0 / %x"), get_slice(reg_csd,30,29) );
printf_P(PSTR("\n\r R2W_FACTOR: 4 / %x"), get_slice(reg_csd,28,26) );
printf_P(PSTR("\n\r WRITE_BL_LEN: 9 / %x"), get_slice(reg_csd,25,22) );
printf_P(PSTR("\n\r WRITE_BL_PARTIAL: 0 / %x"), get_slice(reg_csd,21,21) );
printf_P(PSTR("\n\r Reserved: 0 / %x"), get_slice(reg_csd,20,16) );
printf_P(PSTR("\n\r Reserved: 0 / %x"), get_slice(reg_csd,15,15) );
printf_P(PSTR("\n\r COPY: 1 / %x"), get_slice(reg_csd,14,14) );
printf_P(PSTR("\n\r PERM_WRITE_PROTECT: 0 / %x"), get_slice(reg_csd,13,13) );
printf_P(PSTR("\n\r TEMP_WRITE_PROTECT: 0 / %x"), get_slice(reg_csd,12,12) );
printf_P(PSTR("\n\r Reserved: 0 / %x"), get_slice(reg_csd,11,10) );
printf_P(PSTR("\n\r ECC: 0 / %x"), get_slice(reg_csd,9,8) );
printf_P(PSTR("\n\r CRC: - / %x"), get_slice(reg_csd,7,1) );
printf_P(PSTR("\n\r Not Used (Always 1): 1 / %x"), get_slice(reg_csd,0,0) );
block_cnt++;
block_cnt *= (1<<(c_size_mult+2));
block_len = (1<<read_bl_len);
printf_P(PSTR("\n\r Card Size: %ld blocks @ %db = %ldmb\n\r"),
block_cnt, block_len, block_cnt*block_len/1000000 );
spi_cmd[0] = 10;
printf_P(PSTR("\n\rResponse to CMD10: 0 / %d"), spi_command());
while(spi_byte(0xFF) != 0xFE); // wait for data start token; add time-out?
for(i=0; i<16; i++)
reg_cid[15-i] = spi_byte(0xFF); // fill in from MSB
printf_P(PSTR("\n\r Contents of CID Register:"));
printf_P(PSTR("\n\r Product Name: "));
for(i=0; i<7; i++)
uart_tx(reg_cid[12-i]);
printf_P(PSTR("\n\r Mfg Month: %d"), get_slice(reg_cid,15,12)); // ??? card returns 12/2005
printf_P(PSTR("\n\r Mfg Year: %d"), 1996+get_slice(reg_cid,11,8)); // ??? .. unless it's 12/2004?
}
// void get_regs(void)
/*** init_spi *****************************************************************
* init card
*****************************************************************************/
void init_spi(void) {
uint8_t tries, retval;
MMC_PORT |= _BV(MMC_CS); // cs high (deselect)
spi_byte(0xFF); // spec says to clock at least 74 high bits into the
spi_byte(0xFF); // MMC; we'll do 80 here, it's easier ;)
spi_byte(0xFF);
spi_byte(0xFF);
spi_byte(0xFF);
spi_byte(0xFF);
spi_byte(0xFF);
spi_byte(0xFF);
spi_byte(0xFF);
spi_byte(0xFF);
MMC_PORT &= ~_BV(MMC_CS); // cs low (select, spi mode)
// send CMD0 (reset/idle)
// send CMD0 (reset) continuously until out of idle
// loop until return == 00 0001 (idle); ?after timeout there's an error
tries = 0xFF;
while(( (retval=spi_command())==0) && tries!=0) // (less space than checking !=1) all vals in array already 0, no need to mod spi_command
tries--; // all vals in array already 0, no need to mod
printf_P(PSTR("\n\rResponse to CMD0: 1 / %d"), retval); // get rid of retval assignment in while when done debugging
if(tries == 0)
return;
// send CMD1 (init) continuously until ready
// loop until return == 00 0000 (ready); ?after timeout there's an error
spi_cmd[0] = 1;
tries = 0xFF;
while(( (retval=spi_command())!=0) && tries!=0) //
tries--;
printf_P(PSTR("\n\rResponse to CMD1: 0 / %d"), retval);
if(tries == 0)
return;
spi_cmd[0] = 13;
retval = spi_command();
printf_P(PSTR("\n\rResponse to CMD13: 0,0 / %d,%d"), retval,spi_byte(0xff));
// show 1st and 2nd bytes of R1b response
get_regs();
}
// void init_spi(void)
/*** init_io ******************************************************************
* init io ports
*****************************************************************************/
void init_io(void) {
// init ports
/* PORT C pins connected to MMC
0 / CS - out, high (inactive)
1 / DO - out from MMC (MISO, only read on clock)
2 / DI - in to MMC (MOSI)
4 / GND - 2nd ground; make output and ground pin
6 / CLK - in to MMC
*/
// C G MMC
// K IOS
MMC_DDR = 0b01010011; // 1011 1111: all outputs except Din (PA6); PA7 unused
MMC_PORT = 0b10101101; // 1100 1011: gnd, clk, MOSI low, others high (pull-up on Din)
LED_DDR = 0xFF; // all leds are outputs
LED_PORT = 0xFF; // all leds off
SW_DDR = 0x00; // all switches are inputs
SW_PORT = 0xFF; // pull-ups active
// init USART
// UCSRC &= ~_BV(UMSEL); // make sure we're in async mode
// UCSRA |= _BV(U2X); // set double speed, change 16 to 8 below
// set baud rate: UBRR = (F_CPU/(16*BAUDRATE)) - 1
UBRRH = BAUD_H;
UBRRL = BAUD_L;
UCSRB = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE); // enable tx, rx //and rx int
sei();
}
// void init_io(void)
/*** init_vars ****************************************************************
* init vars
*****************************************************************************/
void init_vars(void) {
spi_cmd[0] = 0; // command
spi_cmd[4] = 0; // 31-24 (MSB)
spi_cmd[3] = 0; // 23-16
spi_cmd[2] = 0; // 15-08
spi_cmd[1] = 0; // 07-00 (LSB)
}
// void init_vars(void)
int main(void) {
// uint8_t retval;
init_vars();
init_io();
FILE * stdio_dev;
stdio_dev = fdevopen(uart_tx, uart_rx, 0);
printf_P(PSTR("\n\r\n\r\n\rLocked Card Fixer (build 050831017), by Muhammad J. A. Galadima.\n\r\n\r"));
init_spi();
printf_P(PSTR("\n\r\n\r\n\rPlease remove your card now, or press a key to wipe."));
show_resp(128);
printf_P(PSTR("\n\rPerforming card WIPE..."));
// now do something (ie. erase card!)
// set block length to 1
spi_cmd[0] = 16; // set block length / R1
spi_cmd[4] = 0; // set size to 1
spi_cmd[3] = 0; // "
spi_cmd[2] = 0; // "
spi_cmd[1] = 1; // "
spi_command();
// send the send forced erase command
spi_cmd[0] = 42; // LOCK_UNLOCK / R1b
spi_cmd[4] = 0; //
spi_cmd[3] = 0; // "
spi_cmd[2] = 0; // "
spi_cmd[1] = 0; // "
spi_command();
spi_busywait(); // wait for busy
// send the data byte (1 byte, as defined in block length)
spi_byte(0b11111110); // data start token
spi_byte(0b00001000); // forced erase
spi_byte(0xFF); //
spi_byte(0xFF); // CRC
printf_P(PSTR("\n\r\n\rData Response: 0x%x"), 0b00011111 & spi_byte(0xFF)); // read data response
spi_busywait();
printf_P(PSTR("\n\rCard Erased!"));
/*
uint32_t i;
uint8_t block[512];
for(i=0; i<512; i++)
block[i] = 0;
*/
// loop forever
for (;;);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -