Advertisement
Guest User

Untitled

a guest
Jan 20th, 2014
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 15.91 KB | None | 0 0
  1. /*** MMC Unlocker *************************************************************
  2.  *
  3.  *  File Name  : mmcfmt.c
  4.  *  Title      : Multi-Media Card Unlocker
  5.  *  Description: Reset locked MMC cards (and wipes all data) allowing them
  6.  *                to be used again
  7.  *  Author     : Muhammad J. A. Galadima
  8.  *  Created    : 2004 / 01 / 27
  9.  *  Modified   : 2005 / 08 / 31
  10.  *               2008 / 03 / 05
  11.  *          Dropped serial port speed to 9600 because it didn't
  12.  *                      work at 115200 with the internal osc any more (thought
  13.  *                      I broke my STK (haven't used it in a while). It still
  14.  *                      works at 57600 but I'll leave it at 9600 to be safe
  15.  *  Version    : 0.2
  16.  *  Target MCU : STK500 (can be used w/any AVRs with enough pins for
  17.                  the MMC card (4) plus any switches/LEDs you want)
  18.  * 
  19.  * 
  20.  *  This program is free software; you can redistribute it and/or
  21.  *  modify it under the terms of the GNU General Public License
  22.  *  as published by the Free Software Foundation; either version 2
  23.  *  of the License, or (at your option) any later version.
  24.  * 
  25.  *  This program is distributed in the hope that it will be useful,
  26.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  27.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  28.  *  GNU General Public License for more details.
  29.  *
  30.  *****************************************************************************/
  31.  
  32. #include <stdio.h>
  33. #include <avr/io.h>
  34. #include <avr/interrupt.h>
  35. //#include <avr/signal.h>
  36. #include <avr/pgmspace.h>
  37.  
  38. #include <ctype.h>
  39. #include <inttypes.h>
  40. #include <string.h>
  41.  
  42.  
  43. #define MMC_PORT    PORTC
  44. #define MMC_PIN     PINC
  45. #define MMC_DDR     DDRC
  46. #define MMC_CS      PC0
  47. #define MMC_MISO    PC2
  48. #define MMC_MOSI    PC1
  49. #define MMC_CLK     PC6
  50.  
  51. #define LED_PORT    PORTB
  52. #define LED_PIN     PINB
  53. #define LED_DDR     DDRB
  54. #define SW_PORT     PORTA
  55. #define SW_PIN      PINA
  56. #define SW_DDR      DDRA
  57. #define BAUDRATE 9600
  58. #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
  59. #define BAUD_H      ((uint8_t)(0xFF&(BAUD_REG>>8)))
  60. #define BAUD_L      ((uint8_t)(0xFF&BAUD_REG))
  61.  
  62. #define spi_response()  spi_byte(0xFF)                  // read response
  63. #define spi_busywait()  while(spi_byte(0xFF) == 0)      // wait for non-zero response to continue
  64.  
  65.  
  66.  
  67. uint8_t spi_cmd[5]; // 6 is CRC, which we won't be using here (or should be generated indide spi_command())
  68. uint8_t reg_csd[16];
  69. uint8_t reg_cid[16];
  70. uint16_t block_len;
  71. uint32_t block_cnt;
  72.  
  73.  
  74. /*** SIG_UART_RECV ************************************************************
  75.  *  interrupt on receive byte; for now just echo if any char received
  76.  *****************************************************************************/
  77. SIGNAL (SIG_UART_RECV) {
  78.     uint8_t temp;
  79.     temp = UDR;         // read
  80.     LED_PORT = ~temp;   // show the current command on the LEDs
  81.     if(temp=='\r' || temp == '\n') {
  82.         printf_P(PSTR("\n\r"));
  83.     }
  84.     else
  85.         UDR = temp;         // write    (just echo what the user types)
  86. }
  87.  
  88. uint8_t uart_tx(uint8_t uart_tx) {
  89.     while(!(UCSRA & _BV(UDRE)));        // wait for empty tx buffer
  90.     UDR = uart_tx;                      // put data in buffer, init send
  91.    
  92.     return 0;
  93. }
  94. // uint8_t uart_tx(uint8_t uart_tx)
  95.  
  96.  
  97. uint8_t uart_rx(void) {
  98.     while(!(UCSRA & _BV(RXC)));     // wait for full rx buffer
  99.     return UDR;                   /* return the new c */
  100. }
  101. // uint8_t uart_rx(void)
  102.  
  103.  
  104. /*** delay ********************************************************************
  105.  *  rough delay; 65k loops, 4 instr each, +over head: 65536*4 = 262144,
  106.  *  round up tp 300000 clks (time: 300000/F_CPU seconds)
  107.  *****************************************************************************/
  108. void delay(void) {
  109.     uint8_t i, j;
  110.     for(i=0; i<255; i++) {
  111.         for(j=0; j<255; j++) {
  112.             asm volatile("nop"::);
  113.             asm volatile("nop"::);
  114.             asm volatile("nop"::);
  115.             asm volatile("nop"::);
  116.         }
  117.     }
  118. }
  119. // void delay(void)
  120.  
  121. /*** show_resp ****************************************************************
  122.  *  show value in response on LEDs and wait for keypress; for debugging only
  123.  *****************************************************************************/
  124. void show_resp(uint8_t retval) {
  125.     LED_PORT = ~(retval);               // light leds 0-7 according to error,
  126.                                         //  and show that system is waiting (led7)
  127.     loop_until_bit_is_clear(SW_PIN, 0); // wait for sw0 to be pressed
  128.     delay();                            // debounce delay
  129.     loop_until_bit_is_set(SW_PIN, 0);   // wait for sw0 to be released
  130.     delay();                            // debounce delay
  131.     LED_PORT = 0xFF;                    // clear all leds
  132. }
  133. // void show_resp(uint8_t retval)
  134.  
  135. /*** spi_byte *****************************************************************
  136.  *  Send one, receive one (happens simultaneously)
  137.  *****************************************************************************/
  138. uint8_t spi_byte(uint8_t spi_tx) {
  139.     uint8_t i, spi_rx = 0;
  140.    
  141.     for(i=8; i>0; i--) {
  142.         i--;
  143.        
  144.         if( bit_is_set(spi_tx,i) )
  145.             MMC_PORT |= _BV(MMC_MOSI);  // set mosi pin
  146.         else
  147.             MMC_PORT &= ~_BV(MMC_MOSI);  // clr mosi pin
  148.  
  149.         // read MISO
  150.         spi_rx <<= 1;       // x2, shift left to create space for next
  151.         if( bit_is_set(MMC_PIN,MMC_MISO) )
  152.             spi_rx++;
  153.  
  154.         MMC_PORT |= _BV(MMC_CLK);   // clk high
  155.         MMC_PORT &= ~_BV(MMC_CLK);  // clk low
  156.        
  157.         i++;
  158.     }
  159.    
  160.     return spi_rx;
  161. }
  162. // uint8_t spi_byte(uint8_t spi_tx)
  163.  
  164.  
  165. /*** spi_command **************************************************************
  166.  *  Send contents of command structure, get (first) response byte
  167.  *****************************************************************************/
  168. uint8_t spi_command(void) {
  169.     uint8_t retval, i;
  170.    
  171.     MMC_PORT &= ~_BV(MMC_CS);   // cs low (select, spi mode)
  172.    
  173.     spi_byte(0xFF);
  174.     // send command struct
  175.     spi_byte(spi_cmd[0] | 0x40);    // make 2 MSBs '01' (01xxxxxx, where x represents command bit)
  176.     spi_byte(spi_cmd[4]);           // address
  177.     spi_byte(spi_cmd[3]);           //    "
  178.     spi_byte(spi_cmd[2]);           //    "
  179.     spi_byte(spi_cmd[1]);           //    "
  180.     spi_byte(0x95);                 // CRC (from spec; calculate?)
  181. //  spi_byte(0xFF);
  182.    
  183.     i=0;
  184.     do {                            // Flush Ncr (1-8 bytes) before response
  185.         retval = spi_byte(0xff);
  186.         i++;
  187.     } while(i<8 && retval == 0xFF);
  188.    
  189.     return retval;  // return R1 response (or first byte of any other command)
  190. }
  191. // uint8_t spi_command(void)
  192.  
  193.  
  194. /*** get_slice ****************************************************************
  195.  *  get the requested portion of the given register
  196.  *****************************************************************************/
  197. uint16_t get_slice(uint8_t *ptr_reg, uint8_t start, uint8_t stop) {
  198.     uint8_t upper, lower, lower_s, count, i;
  199.     uint32_t rval=0;
  200.    
  201.     lower = stop / 8.0;
  202.     upper = start / 8.0;
  203.    
  204.     // merge all used bytes into on large var
  205.     count = upper - lower;
  206.     for(i=0; i<=count; i++) {
  207.         rval <<= 8;
  208.         rval |= ptr_reg[upper-i];
  209.     }
  210.    
  211.     // shift data down so it starts at zero
  212.     lower_s = stop - (lower * 8);
  213.     rval >>= lower_s;
  214.    
  215.     // clear upper bits (all bits before start)
  216.     start -= stop;
  217.     start++;
  218.     //for(i=start; i<32; i++)
  219.     for(i=start; i<16; i++) // clear bits 15-start
  220.         rval &= ~(1<<i);
  221.     rval &= 0x0000FFFF;         // clear bits 31-16
  222.    
  223.     return (uint16_t)rval;
  224. }
  225. // uint16_t get_slice(uint8_t ptr_reg[], uint8_t start, uint8_t stop)
  226.  
  227. /*** get_regs *****************************************************************
  228.  *  read the contents of the CSD + CID registers from the card
  229.  *****************************************************************************/
  230. void get_regs(void) {
  231.     uint8_t i, c_size_mult, read_bl_len;
  232.    
  233.     spi_cmd[0] = 9;
  234.     printf_P(PSTR("\n\rResponse to CMD9: 0 / %d"), spi_command());
  235.     while(spi_byte(0xFF) != 0xFE);      // wait for data start token; add time-out?
  236.     for(i=0; i<16; i++)
  237.         reg_csd[15-i] = spi_byte(0xFF); // fill in from MSB
  238.        
  239.     printf_P(PSTR("\n\r Contents of CSD Register:"));   // defaults from SanDisk 32MB card / read values
  240.     printf_P(PSTR("\n\r  CSD_STRUCTURE: 1 / %x"), get_slice(reg_csd,127,126) );
  241.     printf_P(PSTR("\n\r  MMC_PROT:      1 / %x"), get_slice(reg_csd,125,122) );
  242.     printf_P(PSTR("\n\r  Reserved:      0 / %x"), get_slice(reg_csd,121,120) );
  243.     printf_P(PSTR("\n\r  TAAC:          26 / %x"), get_slice(reg_csd,119,112) );
  244.     printf_P(PSTR("\n\r  NSAC:          0 / %x"), get_slice(reg_csd,111,104) );
  245.     printf_P(PSTR("\n\r  TRAN_SPEED:        2a / %x"), get_slice(reg_csd,103,96) );
  246.     printf_P(PSTR("\n\r  CCC:           1ff / %x"), get_slice(reg_csd,95,84) );
  247.     read_bl_len=get_slice(reg_csd,83,80);
  248.     printf_P(PSTR("\n\r  READ_BL_LEN:       9 / %x"), read_bl_len );
  249.     printf_P(PSTR("\n\r  READ_BL_PARTIAL:   1 / %x"), get_slice(reg_csd,79,79) );
  250.     printf_P(PSTR("\n\r  WRITE_BLK_MISALIGN:    0 / %x"), get_slice(reg_csd,78,78) );
  251.     printf_P(PSTR("\n\r  READ_BLK_MISALIGN: 0 / %x"), get_slice(reg_csd,77,77) );
  252.     printf_P(PSTR("\n\r  DSR_IMP:       0 / %x"), get_slice(reg_csd,76,76) );
  253.     printf_P(PSTR("\n\r  Reserved:      0 / %x"), get_slice(reg_csd,75,74) );
  254.     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)
  255.     printf_P(PSTR("\n\r  C_SIZE:        - / %x"), block_cnt );
  256.     printf_P(PSTR("\n\r  VDD_R_CURR_MIN:    4 / %x"), get_slice(reg_csd,61,59) );
  257.     printf_P(PSTR("\n\r  VDD_R_CURR_MAX:    4 / %x"), get_slice(reg_csd,58,56) );
  258.     printf_P(PSTR("\n\r  VDD_W_CURR_MIN:    5 / %x"), get_slice(reg_csd,55,53) );
  259.     printf_P(PSTR("\n\r  VDD_W_CURR_MAX:    5 / %x"), get_slice(reg_csd,52,50) );
  260.     c_size_mult=get_slice(reg_csd,49,47);
  261.     printf_P(PSTR("\n\r  C_SIZE_MULT:       - / %x"), c_size_mult );
  262.     printf_P(PSTR("\n\r  SECTOR_SIZE:       0 / %x"), get_slice(reg_csd,46,42) );
  263.     printf_P(PSTR("\n\r  ERASE_GRP_SIZE:    - / %x"), get_slice(reg_csd,41,37) );
  264.     printf_P(PSTR("\n\r  WP_GRP_SIZE:       1f / %x"), get_slice(reg_csd,36,32) );
  265.     printf_P(PSTR("\n\r  WP_GRP_ENABLE: 1 / %x"), get_slice(reg_csd,31,31) );
  266.     printf_P(PSTR("\n\r  DEFAULT_ECC:       0 / %x"), get_slice(reg_csd,30,29) );
  267.     printf_P(PSTR("\n\r  R2W_FACTOR:        4 / %x"), get_slice(reg_csd,28,26) );
  268.     printf_P(PSTR("\n\r  WRITE_BL_LEN:      9 / %x"), get_slice(reg_csd,25,22) );
  269.     printf_P(PSTR("\n\r  WRITE_BL_PARTIAL:  0 / %x"), get_slice(reg_csd,21,21) );
  270.     printf_P(PSTR("\n\r  Reserved:      0 / %x"), get_slice(reg_csd,20,16) );
  271.     printf_P(PSTR("\n\r  Reserved:      0 / %x"), get_slice(reg_csd,15,15) );
  272.     printf_P(PSTR("\n\r  COPY:          1 / %x"), get_slice(reg_csd,14,14) );
  273.     printf_P(PSTR("\n\r  PERM_WRITE_PROTECT:    0 / %x"), get_slice(reg_csd,13,13) );
  274.     printf_P(PSTR("\n\r  TEMP_WRITE_PROTECT:    0 / %x"), get_slice(reg_csd,12,12) );
  275.     printf_P(PSTR("\n\r  Reserved:      0 / %x"), get_slice(reg_csd,11,10) );
  276.     printf_P(PSTR("\n\r  ECC:           0 / %x"), get_slice(reg_csd,9,8) );
  277.     printf_P(PSTR("\n\r  CRC:           - / %x"), get_slice(reg_csd,7,1) );
  278.     printf_P(PSTR("\n\r  Not Used (Always 1):   1 / %x"), get_slice(reg_csd,0,0) );
  279.    
  280.     block_cnt++;
  281.     block_cnt *= (1<<(c_size_mult+2));
  282.     block_len = (1<<read_bl_len);
  283.     printf_P(PSTR("\n\r Card Size:  %ld blocks @ %db = %ldmb\n\r"),
  284.         block_cnt, block_len, block_cnt*block_len/1000000 );
  285.    
  286.    
  287.     spi_cmd[0] = 10;
  288.     printf_P(PSTR("\n\rResponse to CMD10: 0 / %d"), spi_command());
  289.     while(spi_byte(0xFF) != 0xFE);      // wait for data start token; add time-out?
  290.     for(i=0; i<16; i++)
  291.         reg_cid[15-i] = spi_byte(0xFF); // fill in from MSB
  292.     printf_P(PSTR("\n\r Contents of CID Register:"));
  293.     printf_P(PSTR("\n\r  Product Name:  "));
  294.     for(i=0; i<7; i++)
  295.         uart_tx(reg_cid[12-i]);
  296.     printf_P(PSTR("\n\r  Mfg Month:     %d"), get_slice(reg_cid,15,12));        // ??? card returns 12/2005
  297.     printf_P(PSTR("\n\r  Mfg Year:      %d"), 1996+get_slice(reg_cid,11,8));    // ??? .. unless it's 12/2004?
  298. }
  299. // void get_regs(void)
  300.  
  301. /*** init_spi *****************************************************************
  302.  *  init card
  303.  *****************************************************************************/
  304. void init_spi(void) {
  305.     uint8_t tries, retval;
  306.  
  307.     MMC_PORT |= _BV(MMC_CS);    // cs high (deselect)
  308.     spi_byte(0xFF);             // spec says to clock at least 74 high bits into the
  309.     spi_byte(0xFF);             //  MMC; we'll do 80 here, it's easier ;)
  310.     spi_byte(0xFF);
  311.     spi_byte(0xFF);
  312.     spi_byte(0xFF);
  313.     spi_byte(0xFF);
  314.     spi_byte(0xFF);
  315.     spi_byte(0xFF);
  316.     spi_byte(0xFF);
  317.     spi_byte(0xFF);
  318.     MMC_PORT &= ~_BV(MMC_CS);           // cs low (select, spi mode)
  319.    
  320.     // send CMD0 (reset/idle)
  321.    
  322.     // send CMD0 (reset) continuously until out of idle
  323.     // loop until return == 00 0001 (idle); ?after timeout there's an error
  324.     tries = 0xFF;
  325.     while(( (retval=spi_command())==0) && tries!=0) // (less space than checking !=1) all vals in array already 0, no need to mod spi_command
  326.         tries--;                                // all vals in array already 0, no need to mod
  327.     printf_P(PSTR("\n\rResponse to CMD0: 1 / %d"), retval); // get rid of retval assignment in while when done debugging
  328.     if(tries == 0)
  329.         return;
  330.    
  331.     // send CMD1 (init) continuously until ready
  332.     // loop until return == 00 0000 (ready); ?after timeout there's an error
  333.     spi_cmd[0] = 1;
  334.     tries = 0xFF;
  335.     while(( (retval=spi_command())!=0) && tries!=0)         //
  336.         tries--;
  337.     printf_P(PSTR("\n\rResponse to CMD1: 0 / %d"), retval);
  338.     if(tries == 0)
  339.         return;
  340.    
  341.     spi_cmd[0] = 13;
  342.     retval = spi_command();
  343.     printf_P(PSTR("\n\rResponse to CMD13: 0,0 / %d,%d"), retval,spi_byte(0xff));
  344.         // show 1st and 2nd bytes of R1b response
  345.  
  346.     get_regs();
  347. }
  348. // void init_spi(void)
  349.  
  350.  
  351. /*** init_io ******************************************************************
  352.  *  init io ports
  353.  *****************************************************************************/
  354. void init_io(void) {
  355.     // init ports
  356.    
  357.     /* PORT C pins connected to MMC
  358.         0 / CS  - out, high (inactive)
  359.         1 / DO  - out from MMC (MISO, only read on clock)
  360.         2 / DI  - in to MMC (MOSI)
  361.         4 / GND - 2nd ground; make output and ground pin
  362.         6 / CLK - in to MMC
  363.     */
  364.  
  365.     //               C G MMC
  366.     //               K   IOS
  367.     MMC_DDR     = 0b01010011;   // 1011 1111: all outputs except Din (PA6); PA7 unused
  368.     MMC_PORT    = 0b10101101;   // 1100 1011: gnd, clk, MOSI low, others high (pull-up on Din)
  369.    
  370.     LED_DDR     = 0xFF;         // all leds are outputs
  371.     LED_PORT    = 0xFF;         // all leds off
  372.    
  373.     SW_DDR = 0x00;              // all switches are inputs
  374.     SW_PORT = 0xFF;             // pull-ups active
  375.    
  376.     // init USART
  377. //  UCSRC &= ~_BV(UMSEL);       // make sure we're in async mode
  378. //  UCSRA |= _BV(U2X);          // set double speed, change 16 to 8 below
  379.    
  380.     // set baud rate: UBRR = (F_CPU/(16*BAUDRATE)) - 1
  381.     UBRRH = BAUD_H;
  382.     UBRRL = BAUD_L;
  383.     UCSRB = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE); // enable tx, rx //and rx int
  384.    
  385.     sei();
  386. }
  387. // void init_io(void)
  388.  
  389. /*** init_vars ****************************************************************
  390.  *  init vars
  391.  *****************************************************************************/
  392. void init_vars(void) {
  393.     spi_cmd[0] = 0;     // command
  394.     spi_cmd[4] = 0;     // 31-24    (MSB)
  395.     spi_cmd[3] = 0;     // 23-16
  396.     spi_cmd[2] = 0;     // 15-08
  397.     spi_cmd[1] = 0;     // 07-00    (LSB)
  398. }
  399. // void init_vars(void)
  400.  
  401. int main(void) {
  402. //  uint8_t retval;
  403.    
  404.     init_vars();
  405.     init_io();
  406.    
  407.     FILE * stdio_dev;
  408.     stdio_dev = fdevopen(uart_tx, uart_rx);
  409.    
  410.     printf_P(PSTR("\n\r\n\r\n\rLocked Card Fixer (build 080305003), by Muhammad J. A. Galadima.\n\r\n\r"));
  411.    
  412.     init_spi();
  413.    
  414.     printf_P(PSTR("\n\r\n\r\n\rPlease remove your card now, or press a key to wipe."));
  415.     show_resp(128);
  416.     printf_P(PSTR("\n\rPerforming card WIPE..."));
  417.    
  418.    
  419.     // now do something (ie. erase card!)
  420.    
  421.     // set block length to 1
  422.     spi_cmd[0] = 16;    // set block length / R1
  423.     spi_cmd[4] = 0;     // set size to 1
  424.     spi_cmd[3] = 0;     //      "
  425.     spi_cmd[2] = 0;     //      "
  426.     spi_cmd[1] = 1;     //      "
  427.     spi_command();
  428.    
  429.     // send the send forced erase command
  430.     spi_cmd[0] = 42;    // LOCK_UNLOCK / R1b
  431.     spi_cmd[4] = 0;     //
  432.     spi_cmd[3] = 0;     //      "
  433.     spi_cmd[2] = 0;     //      "
  434.     spi_cmd[1] = 0;     //      "
  435.     spi_command();
  436.     spi_busywait();     // wait for busy
  437.    
  438.     // send the data byte (1 byte, as defined in block length)
  439.     spi_byte(0b11111110);   // data start token
  440.     spi_byte(0b00001000);   // forced erase
  441.     spi_byte(0xFF);         //
  442.     spi_byte(0xFF);         // CRC
  443.    
  444.     printf_P(PSTR("\n\r\n\rData Response: 0x%x"), 0b00011111 & spi_byte(0xFF)); // read data response
  445.     spi_busywait();
  446.     printf_P(PSTR("\n\rCard Erased!"));
  447.    
  448.     /*
  449.     uint32_t i;
  450.     uint8_t block[512];
  451.     for(i=0; i<512; i++)
  452.         block[i] = 0;
  453.     */
  454.    
  455.     // loop forever
  456.     for (;;);
  457. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement