AnsweredAssumed Answered

STM32F4Discovery - SDCard sector reading

Question asked by piechota.maksymilian on Dec 29, 2015

long time I try to implement FatFs module, but its gets crazy after every sd card formatting. (different errors each time). I've decided to go lower and check my SDCard drivers and I've noticed that when I read some (but ALWAYS THE SAME) of sector's field I receive garbage and I can't interpret it.

My driver's test looks like below:

#if 1 //SD Card Test
uint16_t i;
uint8_t CSD; //card capacity
uint8_t CID; //card id
uint8_t Buffer[512]; //this buffer is written to card
for(i=0; i<512;i++)
{
    Buffer[i]=i;
}
SD_CardInit();          //card initialization
CSD = SD_Read_CSD();    //read capacity
CID = SD_Read_CID();    //read ID
SD_WriteBlock(0x200, Buffer, 512);  //write Buffer under 0x200 (512) address
SD_Read_Block(0x200);               //read buffer from 0x200
CSD = 0;
#endif

I put breakpoint at CSD = 0; line. Here is what I get after writing and reading the same address:

N0nhq.jpg

Buffer is filled with numbers from 0 to 255 (two times, because of overflow). To reduce noise I've minimized SPI frequency to minimum. Nothing changed. But in fact that wrong numbers appears ALWAYS under the same table index and with the same values suggest that is no problem with noise, but some error. It looks like drivers works properly, because they write and read most of the fields, but always in the same it answer with garbage. I can't find any trace what could I do wrong. Do I write under some permitted address? When I read any random address I receive the same result.

I include functions: read and write (SD_Sector is a global buffer)

READ



// return:
// 0x00 -- read OK
// 0x01..0xfe -- error response from CMD17
// 0xff -- timeout
uint8_t SD_Read_Block(uint32_t addr)
{
    uint32_t wait;
    uint16_t i;
    uint8_t response;


    SDCard_privChipSelect();


#if 0 //TODO: reconsider PiechotM, do not work with that line
    if (SD_CardType != SD_HIGH_CAPACITY_SD_CARD) addr <<= 9; // Convert block number to byte offset
#endif
    response = SD_SendCmd(SD_CMD_READ_SINGLE_BLOCK,addr); // CMD17
    if (response != 0x00)
    {
        // Something wrong happened, fill buffer with zeroes
        for (i = 0; i < 512; i++) SD_sector[i] = 0;
        return response; // SD_CMD_READ_SINGLE_BLOCK command returns bad response
    }
    else
    {
        wait = 0; response = 0;
        while (++wait <= 0x1ff && response != 0xfe) response = SD_Recv();
        if (wait >= 0x1ff) return 0xff;
        // Read 512 bytes of sector
        for (i = 0; i < 512; i++) SD_sector[i] = SD_Recv();
    }


    // Receive 16-bit CRC (some cards demand this)
    SD_CRC16_rcv  = SD_Recv() << 8;
    SD_CRC16_rcv |= SD_Recv();


    // Calculate CRC16 of received buffer
    SD_CRC16_cmp = CRC16_buf(&SD_sector[0],512);


    SDCard_privChipDeSelect();


    // Must send at least 74 clock ticks to SD Card
    for (wait = 0; wait < 8; wait++) SD_Send(0xff);


    return 0;
}


/* -------------------- WRITE SECTION ------------------------------*/
/*               Lonely Wolf library imported                       */
/*------------------------PiechotM----------------------------------*/


// Send buffer to the SD card
// input:
//   pBuf - pointer to the buffer
//   len - length of the buffer
// return: last response from SD card
void SD_WriteBuf(uint8_t *pBuf, uint16_t len)
{
    while (len--) SD_Send(*pBuf++);
}

WRITE



// Write block of data to the SD card
// input:
//   addr - start address of the block (must be power of two)
//   pBuf - pointer to the buffer with data
//   len - buffer length
// return: SDR_xxx
SDResult_TypeDef SD_WriteBlock(uint32_t addr, uint8_t *pBuf, uint32_t len)
{
    uint32_t wait;
    uint16_t CRC_loc; // Calculated CRC16 of the block
    uint16_t i;
    uint8_t cmdres, response, temp;


    SDCard_privChipSelect();


    // Calculate 16-bit CRC
    CRC_loc = CRC16_buf(pBuf,len);


    // SDSC card uses byte unit address and
    // SDHC/SDXC cards use block unit address (1 unit = 512 bytes)
    // For SDHC/SDXC card addr must be converted to block address
#if 0 //TODO: reconsider PiechotM, do not work with that line
    if (SD_CardType == SD_HIGH_CAPACITY_SD_CARD) addr >>= 9;
#endif
    response = SD_SendCmd(SD_CMD_WRITE_SINGLE_BLOCK,addr); // CMD24


    if (response != 0x00)
    {
        // Something wrong happened, do nothing
        return response; // SD_CMD_READ_SINGLE_BLOCK command returns bad response
    }
    else
    {
        wait = 0; response = 0;
        while (++wait <= 512/*0x1ff*/ && response == 0xff)
        {
            temp = 0xFF;
            SD_Send( temp );
            response = SD_Recv();
        }
        if (wait >= 0x1ff) return 0xff;


        // Send start block token
        SD_Send(SD_TOKEN_START_BLOCK);


        // Send data block
        for (i = 0; i < len; i++)
        {
            uint8_t temp;


            SD_Send( *pBuf++ );
        }


        // Send CRC
        SD_Send(CRC_loc >> 8);
        SD_Send((uint8_t)CRC_loc);
    }


    // Get response from the SD card
    cmdres = SD_Recv();
    cmdres &= 0x1f;
    if (cmdres != SD_TOKEN_DATA_ACCEPTED)
    {
        // Data block rejected by SD card for some reason
        // Release SD card
        SD_Send(0xff);


        SDCard_privChipDeSelect();


        if (cmdres & SD_TOKEN_WRITE_CRC_ERROR) return SDR_WriteCRCError;
        if (cmdres & SD_TOKEN_WRITE_ERROR) return SDR_WriteErrorInternal;
        return SDR_WriteError;
    }


    // Wait while the SD card is busy by data programming
    wait = 0x7fff; // Recommended timeout is 250ms (500ms for SDXC) 
    do
    {
        cmdres = SD_Recv();
    } while (cmdres == 0 && --wait);


    // Provide extra 8 clocks for the card (from SanDisk specification)
    SD_Send(0xff);


    // Release SD card
    SDCard_privChipDeSelect();


    // Must send at least 74 clock ticks to SD Card
    for (wait = 0; wait < 10; wait++) SD_Send(0xff);


    return SDR_Success;
}

I will be very thankful for your help!

Best regards,

Maks Piechota

PS. How Can I highlight the code to make it more readable?

Outcomes