La lectura de bloque de SDHC devuelve 0x00

0

Tengo una tarjeta sd de 4 GB conectada a través de SPI a mi XMega MCU y quiero leer esta tarjeta con la interfaz USART-SPI en el modo SPI de la MCU. Así que tengo este código

SD.c

SD_Error_t SD_Init(SPI_Config_t* Config)
{
    SD_Error_t Status = SD_InitInterface(Config);
    SD_ReadSingleBlock(0x00);   
    return Status;
}

SD.h

#ifndef SD_H_
#define SD_H_

 /*
     SD card settings
 */
 #define SD_INTERFACE_TYPE                  INTERFACE_USART_SPI
 #define SD_SS_PORT                         &PORTE
 #define SD_SS_PIN                          0

 #define SD_BLOCK_SIZE                      512

 typedef enum
 {
     SD_SUCCESSFULL = 0,
     SD_NO_RESPONSE = -1,
     SD_TIMEOUT = -2,
     SD_UNSUPPORTED_CARD = -3,
 } SD_Error_t;

 #include "Peripheral/SD/Interface/SD_Interface.h"

 SD_Error_t SD_Init(SPI_Config_t* Config);

#endif /* SD_H_ */

Y mi controlador de tarjeta SD de bajo nivel

SD_Interface.h

#ifndef SD_INTERFACE_H_
#define SD_INTERFACE_H_

 /*
     Driver include
 */
 #include "Board.h"
 #include "Common/types.h"
 #include "Peripheral/SD/SD.h"

 #if MCU_ARCH == MCU_ARCH_XMEGA
    #include "XMega/GPIO/GPIO.h"
    #include "XMega/ClockManagment/SysClock.h"
    #if SD_INTERFACE_TYPE == INTERFACE_USART_SPI
        #include "XMega/USART/USART.h"

        #define SD_SPI_INIT(Config)                             USART_SPI_Init(Config)
        #define SD_SPI_TRANSMIT(Command)                        USART_SPI_Transmit(SPI_INTERFACE, Command)
        #define SD_SPI_CHIP_SELECT(Port, Pin)                   USART_SPI_SelectDevice(Port, Pin)
        #define SD_SPI_CHIP_UNSELECT(Port, Pin)                 USART_SPI_DeselectDevice(Port, Pin)
    #elif SD_INTERFACE_TYPE == INTERFACE_SPI
        #include "XMega/SPI/SPI.h"

        #define SD_SPI_INIT(Config)                             SPI_Init(Config)
        #define SD_SPI_TRANSMIT(Command)                        SPI_Transmit(SPI_INTERFACE, Command)
        #define SD_SPI_CHIP_SELECT(Port, Pin)                   SPI_SelectDevice(Port, Pin)
        #define SD_SPI_CHIP_UNSELECT(Port, Pin)                 SPI_DeselectDevice(Port, Pin)
    #else
        #error "No SPI interface specified"
    #endif
 #elif MCU_ARCH == MCU_ARCH_AVR8
    #include "AVR8/GPIO/GPIO.h"
    #include "AVR8/SPI/SPI.h"

    #define SD_SPI_INIT(Config)                                 SPI_Init(Config)
    #define SD_SPI_TRANSMIT(Command)                            SPI_Transmit(Command)
    #define SD_SPI_CHIP_SELECT(Port, Pin)                       SPI_SelectDevice(Port, Pin)
    #define SD_SPI_CHIP_UNSELECT(Port, Pin)                     SPI_DeselectDevice(Port, Pin)
 #else
     #error "MCU architecture not supported"
 #endif

 typedef enum
 {
     SD_VER_UNKNOWN  = 0x00,
     SD_VER_1_STD = 0x01,
     SD_VER_2_STD = 0x02,
     SD_VER_2_HI = 0x03,
     SD_MMC = 0x04,
 } SD_CardType_t;

 typedef struct  
 {
     uint8_t MID;
     uint16_t OID;
     uint8_t PNM[5];
     uint8_t PRV;
     uint32_t PSN;
     uint8_t Reserved0:3;
     uint16_t MDT0:11;
     uint8_t CRC0:6;
     uint8_t Reserved1:1;
 } __attribute__((packed)) SD_CID_t;

 #define SD_ID_TO_CMD(ID)                           (0x40 + ID)

 #define SD_STATE_SUCCESSFULL                       0x00
 #define SD_STATE_IDLE                              0x01
 #define SD_STATE_ERASE_RESEIT                      0x02
 #define SD_STATE_ILLEGAL_COMMAND                   0x04
 #define SD_STATE_CRC_ERROR                         0x08
 #define SD_STATE_ERASE_ERROR                       0x10
 #define SD_STATE_ADDRESS_ERROR                     0x20
 #define SD_STATE_PARAMETER_ERROR                   0x40
 #define SD_STATE_BEGIN_TRANSMISSION                0xFE

 SD_Error_t SD_InitInterface(SPI_Config_t* Config);
 void SD_ReadCSD(void);
 void SD_ReadCID(void);
 uint8_t SD_Command(uint8_t Command, uint32_t Arg, uint8_t Checksum, uint32_t Count, uint8_t* Buffer);
 SD_Error_t SD_SoftwareReset(void);
 SD_Error_t SD_InitializeCard(void);
 SD_CardType_t SD_GetCardType(void);
 uint8_t SD_SetBlockLength(uint32_t BlockLength);
 uint8_t SD_ReadSingleBlock(uint32_t Address);

#endif /* SD_INTERFACE_H_ */

SD_Interface.c

#include "Peripheral/SD/SD.h"
#include "Peripheral/SD/Interface/SD_Interface.h"

static SD_CardType_t CardType = SD_VER_UNKNOWN;

SD_Error_t SD_InitInterface(SPI_Config_t* Config)
{   
    SD_Error_t ErrorCode = SD_SUCCESSFULL;

    // Set SD card CS as output in high state
    GPIO_SetDirection(SD_SS_PORT, SD_SS_PIN, GPIO_DIRECTION_OUT);
    GPIO_Set(SD_SS_PORT, SD_SS_PIN);

    if(Config != NULL)
    {
        SD_SPI_INIT(Config);
    }

    // Reset the SD card
    ErrorCode = SD_SoftwareReset();
    if(ErrorCode != SD_SUCCESSFULL)
    {
        return ErrorCode;
    }

    // Initialize the SD card
    ErrorCode = SD_InitializeCard();
    if(ErrorCode != SD_SUCCESSFULL)
    {
        return ErrorCode;
    }

    // Set the block length to 512 (only necessary if the card is not a SDXC or SDHX card) 
    if((CardType != SD_VER_2_HI) & (CardType != SD_VER_2_STD))
    {
        ErrorCode = SD_SetBlockLength(SD_BLOCK_SIZE);
        if(ErrorCode != SD_SUCCESSFULL)
        {
            return ErrorCode;
        }
    }

    return ErrorCode;
}
/*
void SD_ReadCSD(void)
{
    uint8_t Buffer[16];
    uint8_t R1 = SD_Command(SD_ID_TO_CMD(9), 0x00000000, 0x00000000, 16, Buffer);
}

void SD_ReadCID(void)
{
    uint8_t Buffer[16];
    uint8_t R1 = SD_Command(SD_ID_TO_CMD(10), 0x00000000, 0x00000000, 16, Buffer);
    SD_CID_t* T = (SD_CID_t*)Buffer;
}*/

uint8_t SD_Command(uint8_t Command, uint32_t Arg, uint8_t Checksum, uint32_t Count, uint8_t* Buffer)
{
    // Create 8 clock pulse before activating the card
    SD_SPI_TRANSMIT(0xFF);
    SD_SPI_CHIP_SELECT(SD_SS_PORT, SD_SS_PIN);
    SD_SPI_TRANSMIT(Command);
    SD_SPI_TRANSMIT(Arg >> 0x18);
    SD_SPI_TRANSMIT(Arg >> 0x10);
    SD_SPI_TRANSMIT(Arg >> 0x08);
    SD_SPI_TRANSMIT(Arg);
    SD_SPI_TRANSMIT(Checksum);

    /*  
    Wait for the response (0 - 8 bytes for SD cards and 1 - 8 bytes for MMC)
    The spec also say that you have to wait 8 clock cycles after the last bus
    transaction.
    */          
    for(uint8_t i = 0; i < 0x08; i++)
    {
        uint8_t DataIn = SD_SPI_TRANSMIT(0xFF);
        if(DataIn != 0xFF)
        {
            // Read all additional data
            if(Count > 0)
            {
                for(uint32_t j = 0x01; j < Count; j++)
                {
                    *Buffer++ = SD_SPI_TRANSMIT(0xFF);
                }
            }

            // Send a dummy byte and deselect the card after it
            SD_SPI_TRANSMIT(0xFF);
            SD_SPI_CHIP_UNSELECT(SD_SS_PORT, SD_SS_PIN);

            return DataIn;
        }
    }

    SD_SPI_CHIP_UNSELECT(SD_SS_PORT, SD_SS_PIN);

    return SD_NO_RESPONSE;
}

SD_Error_t SD_SoftwareReset(void)
{
    uint8_t Repeat = 0x00;

    //SD_SPI_CHIP_SELECT(SD_SS_PORT, SD_SS_PIN);

    for(uint8_t i = 0x00; i < 0x0A; i++)
    {
        SD_SPI_TRANSMIT(0xFF);
    }

    SD_SPI_CHIP_UNSELECT(SD_SS_PORT, SD_SS_PIN);

    while(SD_Command(SD_ID_TO_CMD(0), 0x00000000, 0x95, 0, 0) != SD_STATE_IDLE)
    {
        // Initialization failed
        if(Repeat++ == 10)
        {
            return SD_NO_RESPONSE;
        }
    }

    return SD_SUCCESSFULL;
}

SD_Error_t SD_InitializeCard(void)
{
    uint16_t Wait = 0x00;
    uint32_t R3 = 0x00;
    uint8_t R1 = 0xFF;
    uint8_t Buffer[4];

    R1 = SD_Command(SD_ID_TO_CMD(8), 0x000001AA, 0x87, 4, Buffer);
    if(R1 == SD_STATE_IDLE)
    {
        /*
            Version 2 SD card
        */

        R3 = ((uint32_t)Buffer[3]) << 0x18;
        R3 |= ((uint32_t)Buffer[2]) << 0x10;
        R3 |= ((uint32_t)Buffer[1]) << 0x08;
        R3 |= ((uint32_t)Buffer[0]);
        /*
        if(R3 != 0x000001AA)
        {
            return SD_UNSUPPORTED_CARD;
        }*/

        // Send ACMD41 and check for ready
        R1 = 0xFF;
        while((++Wait < 0x2710) & (R1 != SD_STATE_SUCCESSFULL))
        {
            SD_Command(SD_ID_TO_CMD(55), 0x00000000, 0x00, 0, 0);
            R1 = SD_Command(SD_ID_TO_CMD(41), 0x40000000, 0x00, 0, 0);
        }

        if((Wait >= 0x2710) | (R1 != SD_STATE_SUCCESSFULL))
        {
            return SD_TIMEOUT;
        }

        // Send CMD58 to read OCR
        R1 = SD_Command(SD_ID_TO_CMD(58), 0x00000000, 0x00, 4, Buffer);
        if(R1 == SD_STATE_SUCCESSFULL)
        {
            R3 = ((uint32_t)Buffer[3]) << 0x18;
            R3 |= ((uint32_t)Buffer[2]) << 0x10;
            R3 |= ((uint32_t)Buffer[1]) << 0x08;
            R3 |= ((uint32_t)Buffer[0]);
        }
        else
        {
            CardType = SD_VER_UNKNOWN;
        }

        // Check if the CCS bit is set
        if(R3 & 0x40000000)
        {
            CardType = SD_VER_2_HI;
        }
        else
        {
            CardType = SD_VER_2_STD;
        }
    }
    else
    {
        /*
            Version 1 SD card or MMC
        */

        // Check for version 1 SD card
        Wait = 0x00;
        while(++Wait < 0xFF) 
        {
            SD_Command(SD_ID_TO_CMD(55), 0x00000000, 0, 0, 0);
            R1 = SD_Command(SD_ID_TO_CMD(41), 0x00000000, 0, 0, 0);
            if(R1 == SD_STATE_SUCCESSFULL)
            {
                CardType = SD_VER_1_STD;
                break;
            }
        }

        // Check for multimedia card
        Wait = 0x00;
        if(R1 & SD_STATE_ILLEGAL_COMMAND)
        {
            while(++Wait < 0xFF)
            {
                R1 = SD_Command(SD_ID_TO_CMD(1), 0x00000000, 0, 0, 0);
                if(R1 == SD_STATE_SUCCESSFULL) 
                {
                    CardType = SD_MMC;
                    break;
                }
            }
        }
    }

    return SD_SUCCESSFULL;
}

SD_CardType_t SD_GetCardType(void)
{
    return CardType;
}

uint8_t SD_SetBlockLength(uint32_t BlockLength)
{
    return SD_Command(SD_ID_TO_CMD(16), 0x00000200, 0xFF, 0, 0);
}

uint8_t SD_ReadSingleBlock(uint32_t Address)
{
    uint8_t R1 = 0x00;
    uint16_t Wait = 0x00;
    uint32_t Offset = 0x00;
    uint32_t Len = 10;
    uint8_t Buffer[512];
    uint32_t Sector = 0x00;

    SD_SPI_TRANSMIT(0xFF);
    SD_SPI_CHIP_SELECT(SD_SS_PORT, SD_SS_PIN);
    SD_SPI_TRANSMIT(SD_ID_TO_CMD(17));
    SD_SPI_TRANSMIT(0);
    SD_SPI_TRANSMIT(0);
    SD_SPI_TRANSMIT(0);
    SD_SPI_TRANSMIT(0x00);
    SD_SPI_TRANSMIT(0xFF);

    // Wait for 0x00
    R1 = 0xFF;
    while((++Wait < 0x2710) & (R1 != SD_STATE_SUCCESSFULL))
    {
        R1 = SD_SPI_TRANSMIT(0xFF);
    }

    if((Wait >= 0x2710) | (R1 != SD_STATE_SUCCESSFULL))
    {
        return SD_TIMEOUT;
    }

    // Wait for 0xFE
    Wait = 0x00;
    R1 = 0xFF;
    while((++Wait < 0x2710) & (R1 != SD_STATE_BEGIN_TRANSMISSION))
    {
        R1 = SD_SPI_TRANSMIT(0xFF);
    }

    if((Wait >= 0x2710) | (R1 != SD_STATE_BEGIN_TRANSMISSION))
    {
        return SD_TIMEOUT;
    }

    for(uint32_t i = 0x00; i < Offset; i++)
    {
        SD_SPI_TRANSMIT(0xFF);
    }

    for(uint32_t i = 0x00; i < Len; i++)
    {
        Buffer[i] = SD_SPI_TRANSMIT(0xFF);
    }

     for(uint32_t i = 0x00; i < 512 - Offset; i++)
    {
        SD_SPI_TRANSMIT(0xFF);
    }

    // skip checksum
    SD_SPI_TRANSMIT(0xFF);
    SD_SPI_TRANSMIT(0xFF);    

    SD_SPI_CHIP_UNSELECT(SD_SS_PORT, SD_SS_PIN);

    return;
}

Puedo inicializar la tarjeta sd. La llamada

SD_Error_t Status = SD_InitInterface(Config);

devuelve SD_SUCCESSFULL y la tarjeta se detecta como SD_VER_2_STD (4 GB micro sdhc). Pero si trato de leer 512 bytes del primer sector de la tarjeta, me convierto en un búfer que se llena con 0x00 (verificado por el depurador). Pero la tarjeta no está vacía. He comprobado el contenido con HxD (ver captura de pantalla).

Entonces, ¿cuál es el problema? No tengo idea de lo que está pasando aquí.
Gracias.

    
pregunta Kampi

0 respuestas

Lea otras preguntas en las etiquetas