SD Card, CMD8, STK500

Gast #3343789
Lesenswert?

Hallo,

Ich verwende den Code von Roland Riegel, hab den aber ein wenig an meine 
HW (ordentliche PegelWandler von RIBU Elektronik) anpassen müssen. Im 
Prinzip funktioniert die ganze Sache ausser
ich hab meinen STK500 über den 6-pin ISP angeschlossen,
schalte alles das erste Mal ein. Dann gehts nicht. Wenn ich den STK500 
kurz ausschalte gehts ab dann immer.

Das relevante Code Fragment (inc Debug Code) ist unten zu sehen.
Die Ausgabe bei "uart_putc_hex (r1)" etc ergibt:

r1 = 0x00
r2 = 0x00
r3 = 0x01
r4 = 0x0f <============0

Es scheitert nur(!) beim aller aller ersten Einschalten.

PS: Woher weiß der STK500 eigentlich, dass nicht er als Slave adressiert 
ist, der hat ja keine SS Leitung ?!



===================0
uint8_t sd_raw_init()
{

    uint8_t  r1, r2, r3, r4  ;

    configure_pin_Status  ;

    if ( ! (PINB & SdCard_Present) )
       return (1) ;

    configure_pin_Von   ;
    SdCard_TurnVon      ;

    /* enable inputs for reading card status */
    configure_pin_available();
    configure_pin_locked();

    /* enable outputs for MOSI, SCK, SS, input for MISO */
    configure_pin_ss()      ;
  PORTB |= 0x01           ;
    configure_pin_mosi()    ;
    configure_pin_sck()     ;
    configure_pin_miso()    ;
  configure_pin_SelCrd()  ;
    configure_pin_xferled() ;


    unselect_card();

    /* initialize SPI with lowest frequency; max. 400kHz during 
identification mode of card */
    SPCR = (0 << SPIE) | /* SPI Interrupt Enable */
           (1 << SPE)  | /* SPI Enable */
           (0 << DORD) | /* Data Order: MSB first */
           (1 << MSTR) | /* Master mode */
           (0 << CPOL) | /* Clock Polarity: SCK low when idle */
           (0 << CPHA) | /* Clock Phase: sample on rising SCK edge */
           (1 << SPR1) | /* Clock Frequency: f_OSC / 128 */
           (1 << SPR0);
    SPSR &= ~(1 << SPI2X); /* No doubled clock frequency */

    /* initialization procedure */
    sd_raw_card_type = 0;

    if(!sd_raw_available())
        return 2;

    /* card needs 74 cycles minimum to start up */
    for(uint8_t i = 0; i < 20; ++i)
    {
        /* wait 8 clock cycles */
        sd_raw_rec_byte();
    }

    /* address card */
    select_card();

    /* card needs 74 cycles minimum to start up */
    for(uint8_t i = 0; i < 20; ++i)
    {
      /* wait 8 clock cycles */
      sd_raw_rec_byte();
    }

    uint8_t  i = 0 ;

    /* reset card */
    uint8_t response;
    for(uint16_t i = 0; ; ++i)
    {
        response = sd_raw_send_command(CMD_GO_IDLE_STATE, 0);
        if(response == (1 << R1_IDLE_STATE))
            break;

        if(i == 0x1ff)
        {
            unselect_card();
            return 3;
        }
    }

#if SD_RAW_SDHC

    /* check for version of SD card specification */
    response = sd_raw_send_command(CMD_SEND_IF_COND, 0x100 /* 2.7V - 
3.6V */ | 0xaa /* test pattern */);

  uart_putc_hex (0x41) ;
  uart_putc_hex (response) ;

    if((response & (1 << R1_ILL_COMMAND)) == 0)
    {
        r1 = sd_raw_rec_byte();
        r2 = sd_raw_rec_byte();
        r3 = sd_raw_rec_byte();

        if ((r3 & 0x01) == 0)
       {
          uart_putc_hex (0x42) ;
            return 9; /* card operation voltage range doesn't match */
           }

        r4 = sd_raw_rec_byte();

        uart_putc_hex (0) ;
        uart_putc_hex (r1) ;
        uart_putc_hex (r2) ;
        uart_putc_hex (r3) ;
        uart_putc_hex (r4) ;
        uart_putc_hex (0) ;

        if (r4 != 0xaa)
          {
            return 4; /* wrong test pattern */
      }

        /* card conforms to SD 2 card specification */
        sd_raw_card_type |= (1 << SD_RAW_SPEC_2);
    }

    else
#endif
    {
      uart_putc_hex (0x43) ;

        /* determine SD/MMC card type */
        sd_raw_send_command(CMD_APP, 0);
        response = sd_raw_send_command(CMD_SD_SEND_OP_COND, 0);
        if((response & (1 << R1_ILL_COMMAND)) == 0)
        {
            /* card conforms to SD 1 card specification */
            sd_raw_card_type |= (1 << SD_RAW_SPEC_1);
          uart_putc_hex (0x44) ;
        }
        else
        {
            /* MMC card */
        }
    }

    /* wait for card to get ready */
    for(uint16_t i = 0; ; ++i)
    {
        if(sd_raw_card_type & ((1 << SD_RAW_SPEC_1) | (1 << 
SD_RAW_SPEC_2)))
        {
            uint32_t arg = 0;
#if SD_RAW_SDHC
            if(sd_raw_card_type & (1 << SD_RAW_SPEC_2))
                arg = 0x40000000;
#endif
            sd_raw_send_command(CMD_APP, 0);
            response = sd_raw_send_command(CMD_SD_SEND_OP_COND, arg);
        }
        else
        {
            response = sd_raw_send_command(CMD_SEND_OP_COND, 0);
        }

        if((response & (1 << R1_IDLE_STATE)) == 0)
            break;

        if(i == 0x7fff)
        {
            unselect_card();
            return 5;
        }
    }

#if SD_RAW_SDHC
    if(sd_raw_card_type & (1 << SD_RAW_SPEC_2))
    {
        if(sd_raw_send_command(CMD_READ_OCR, 0))
        {
            unselect_card();
            return 6;
        }

        if(sd_raw_rec_byte() & 0x40)
            sd_raw_card_type |= (1 << SD_RAW_SPEC_SDHC);

        sd_raw_rec_byte();
        sd_raw_rec_byte();
        sd_raw_rec_byte();
    }
#endif

    /* set block size to 512 bytes */
    if(sd_raw_send_command(CMD_SET_BLOCKLEN, 512))
    {
        unselect_card();
        return 7;
    }

    /* deaddress card */
    unselect_card();

    /* switch to highest SPI frequency possible */
    SPCR &= ~((1 << SPR1) | (1 << SPR0)); /* Clock Frequency: f_OSC / 4 
*/
//     SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */

#if !SD_RAW_SAVE_RAM
    /* the first block is likely to be accessed first, so precache it 
here */
    raw_block_address = (offset_t) -1;
#if SD_RAW_WRITE_BUFFERING
    raw_block_written = 1;
#endif
    if(!sd_raw_read(0, raw_block, sizeof(raw_block)))
        return 8;
#endif

    return 0;
}
=======================

Danke, Mario
Gast #3344171
Lesenswert?

Habs selbst gefunden:

Bei der genannten Library sollte man zuvor z.B. beim 1284er
generell das PORTB auf Eingang stellen und die PullUp aufdrehen,
es wird dann in der SD_RAW_INIT() ohnehin die passende Richtung 
eingestellt, aber eben nicht die PullUp's.

Mario

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren