📄 mmcfmt.c
字号:
/*** MMC Unlocker *************************************************************
*
* File Name : mmcfmt.c
* Title : Multi-Media Card Unlocker
* Description: Reset locked MMC cards (and wipes all data) allowing them
* to be used again
* Author : Muhammad J. A. Galadima
* Created : 2004 / 01 / 27
* Version : 0.1
* Target MCU : STK500 (can be used w/any AVRs with enough pins for
the MMC card (4) plus any switches/LEDs you want)
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*****************************************************************************/
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/pgmspace.h>
#include <ctype.h>
#include <inttypes.h>
#include <string.h>
#define MMC_PORT PORTC
#define MMC_PIN PINC
#define MMC_DDR DDRC
#define MMC_CS PC0
#define MMC_MISO PC2
#define MMC_MOSI PC1
#define MMC_CLK PC6
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED_DDR DDRB
#define SW_PORT PORTA
#define SW_PIN PINA
#define SW_DDR DDRA
#define BAUDRATE 115200
#define BAUD_REG ((uint16_t)((F_CPU / (16.0 * (BAUDRATE))) + 0.5) - 1) // if above .5 mark, round up; replace 16 with 8 for double
#define BAUD_H ((uint8_t)(0xFF&(BAUD_REG>>8)))
#define BAUD_L ((uint8_t)(0xFF&BAUD_REG))
#define spi_response() spi_byte(0xFF) // read response
#define spi_busywait() while(spi_byte(0xFF) == 0) // wait for non-zero response to continue
uint8_t spi_cmd[5]; // 6 is CRC, which we won't be using here (or should be generated indide spi_command())
uint8_t reg_csd[16];
uint8_t reg_cid[16];
uint16_t block_len;
uint32_t block_cnt;
/*** SIG_UART_RECV ************************************************************
* interrupt on receive byte; for now just echo if any char received
*****************************************************************************/
SIGNAL (SIG_UART_RECV) {
uint8_t temp;
temp = UDR; // read
LED_PORT = ~temp; // show the current command on the LEDs
if(temp=='\r' || temp == '\n') {
printf_P(PSTR("\n\r"));
}
else
UDR = temp; // write (just echo what the user types)
}
uint8_t uart_tx(uint8_t uart_tx) {
while(!(UCSRA & _BV(UDRE))); // wait for empty tx buffer
UDR = uart_tx; // put data in buffer, init send
return 0;
}
// uint8_t uart_tx(uint8_t uart_tx)
uint8_t uart_rx(void) {
while(!(UCSRA & _BV(RXC))); // wait for full rx buffer
return UDR; /* return the new c */
}
// uint8_t uart_rx(void)
/*** delay ********************************************************************
* rough delay; 65k loops, 4 instr each, +over head: 65536*4 = 262144,
* round up tp 300000 clks (time: 300000/F_CPU seconds)
*****************************************************************************/
void delay(void) {
uint8_t i, j;
for(i=0; i<255; i++) {
for(j=0; j<255; j++) {
asm volatile("nop"::);
asm volatile("nop"::);
asm volatile("nop"::);
asm volatile("nop"::);
}
}
}
// void delay(void)
/*** show_resp ****************************************************************
* show value in response on LEDs and wait for keypress; for debugging only
*****************************************************************************/
void show_resp(uint8_t retval) {
LED_PORT = ~(retval); // light leds 0-7 according to error,
// and show that system is waiting (led7)
loop_until_bit_is_clear(SW_PIN, 0); // wait for sw0 to be pressed
delay(); // debounce delay
loop_until_bit_is_set(SW_PIN, 0); // wait for sw0 to be released
delay(); // debounce delay
LED_PORT = 0xFF; // clear all leds
}
// void show_resp(uint8_t retval)
/*** spi_byte *****************************************************************
* Send one, receive one (happens simultaneously)
*****************************************************************************/
uint8_t spi_byte(uint8_t spi_tx) {
uint8_t i, spi_rx = 0;
for(i=8; i>0; i--) {
i--;
if( bit_is_set(spi_tx,i) )
MMC_PORT |= _BV(MMC_MOSI); // set mosi pin
else
MMC_PORT &= ~_BV(MMC_MOSI); // clr mosi pin
// read MISO
spi_rx <<= 1; // x2, shift left to create space for next
if( bit_is_set(MMC_PIN,MMC_MISO) )
spi_rx++;
MMC_PORT |= _BV(MMC_CLK); // clk high
MMC_PORT &= ~_BV(MMC_CLK); // clk low
i++;
}
return spi_rx;
}
// uint8_t spi_byte(uint8_t spi_tx)
/*** spi_command **************************************************************
* Send contents of command structure, get (first) response byte
*****************************************************************************/
uint8_t spi_command(void) {
uint8_t retval, i;
MMC_PORT &= ~_BV(MMC_CS); // cs low (select, spi mode)
spi_byte(0xFF);
// send command struct
spi_byte(spi_cmd[0] | 0x40); // make 2 MSBs '01' (01xxxxxx, where x represents command bit)
spi_byte(spi_cmd[4]); // address
spi_byte(spi_cmd[3]); // "
spi_byte(spi_cmd[2]); // "
spi_byte(spi_cmd[1]); // "
spi_byte(0x95); // CRC (from spec; calculate?)
// spi_byte(0xFF);
i=0;
do { // Flush Ncr (1-8 bytes) before response
retval = spi_byte(0xff);
i++;
} while(i<8 && retval == 0xFF);
return retval; // return R1 response (or first byte of any other command)
}
// uint8_t spi_command(void)
/*** get_slice ****************************************************************
* get the requested portion of the given register
*****************************************************************************/
uint16_t get_slice(uint8_t *ptr_reg, uint8_t start, uint8_t stop) {
uint8_t upper, lower, lower_s, count, i;
uint32_t rval=0;
lower = stop / 8.0;
upper = start / 8.0;
// merge all used bytes into on large var
count = upper - lower;
for(i=0; i<=count; i++) {
rval <<= 8;
rval |= ptr_reg[upper-i];
}
// shift data down so it starts at zero
lower_s = stop - (lower * 8);
rval >>= lower_s;
// clear upper bits (all bits before start)
start -= stop;
start++;
//for(i=start; i<32; i++)
for(i=start; i<16; i++) // clear bits 15-start
rval &= ~(1<<i);
rval &= 0x0000FFFF; // clear bits 31-16
return (uint16_t)rval;
}
// uint16_t get_slice(uint8_t ptr_reg[], uint8_t start, uint8_t stop)
/*** get_regs *****************************************************************
* read the contents of the CSD + CID registers from the card
*****************************************************************************/
void get_regs(void) {
uint8_t i, c_size_mult, read_bl_len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -