¿Cómo usar el CRC de datos de las tarjetas SD en modo SPI?

0

Estoy conectando una tarjeta SD a través de SPI usando un microcontrolador AVR (más específicamente es la consola Uzebox).

Puedo inicializar con éxito la tarjeta activando CRC check ON con CMD59 (así que tengo un algoritmo CRC7 comprobado), y puedo leer sectores de él (descargar los datos leídos por CMD17 da los resultados correctos: veo lo que hay en el tarjeta propiamente dicha).

Lo que parece que no puedo trabajar es una verificación de CRC para los sectores de datos que usan los bytes de CRC recibidos de la tarjeta.

Actualmente tengo tres tarjetas SDSC que verifiqué para comportarme de la siguiente manera con mi algoritmo:

  • Dos de las tarjetas dan el mismo valor para ambos bytes CRC, y ninguno corresponde al resultado de CRC-CCITT con un valor de inicio 0x0000 o 0xFFFF (probado con múltiples sectores, los valores cambian según los datos del sector , pero los dos bytes son siempre los mismos).

  • La tercera tarjeta parece no tener CRC, proporcionando 0x0000 en estos bytes.

El código de transmisión de SPI para esos bytes finales parece correcto, hice algunos pasos para verificar que efectivamente leí lo que quiero incluir y que realmente hago dos transacciones de SPI para los dos bytes.

¿Alguien tiene alguna idea de lo que podría estar pasando allí? ¿O debería simplemente olvidarme de esos bytes CRC? (Tal vez las tarjetas simplemente no las implementen o lo hagan incorrectamente en modo SPI)

    
pregunta Jubatian

2 respuestas

1

Por lo tanto, con respecto a las dos "tarjetas de entrega de CRC": es un poco difícil depurar esto sin ningún tipo de datos de ejemplo y CRC, pero el problema más común que uno encuentra es que los polinomios del generador están "destinados" al revés, es decir. si \ $ x ^ 0 \ $ corresponde al primer o al último bit.

La verificación es fácil: solo tiene datos de prueba que tenga tanto en el orden de bits original como en el inverso, y vea lo que tiene sentido.

Ahora, ya has probado con 0xFFFF y 0x0000, que son simétricos. Al menos para 0x0000, el resultado de un polinomio definitivamente debería ser cero, ¿no es así? ¿Qué estás esperando, qué estás obteniendo?

Referencia:

enlace , p. 54f

    
respondido por el Marcus Müller
0

Aquí hay algoritmos que encontré calculando correctamente los CRC.

El CRC del Comando SD:

/* CRC7 table (for SD commands) */
static unsigned int sd_crc7_table[256];

(...)

/* Running CRC7 calculation for a byte. */
static unsigned int sd_crc7_byte(unsigned int crcval, unsigned int byte)
{
 return sd_crc7_table[(byte ^ (crcval << 1)) & 0xFFU];
}

(...)

/* Generate CRC7 table */
for (byt = 0U; byt < 256U; byt ++){
 crc = byt;
 if ((crc & 0x80U) != 0U){ crc ^= 0x89U; }
 for (bit = 1U; bit < 8U; bit ++){
  crc <<= 1;
  if ((crc & 0x80U) != 0U){ crc ^= 0x89U; }
 }
 sd_crc7_table[byt] = (crc & 0x7FU);
}

(...)

crcval = 0x00U;
crcval = sd_crc7_byte(crcval, first_byte);
(...)
crcval = sd_crc7_byte(crcval, last_byte);
crc_byte = (crcval << 1) | 0x01U;

El CRC de datos SD:

/* CRC16 table (for SD data) */
static unsigned int sd_crc16_table[256];

(...)

/* Running CRC16 calculation for a byte. */
static unsigned int sd_crc16_byte(unsigned int crcval, unsigned int byte)
{
 return (sd_crc16_table[(byte ^ (crcval >> 8)) & 0xFFU] ^ (crcval << 8)) & 0xFFFFU;
}

(...)

/* Generate CRC16 table */
for (byt = 0U; byt < 256U; byt ++){
 crc = byt << 8;
 for (bit = 0U; bit < 8U; bit ++){
  crc <<= 1;
  if ((crc & 0x10000U) != 0U){ crc ^= 0x1021U; }
 }
 sd_crc16_table[byt] = (crc & 0xFFFFU);
}

(...)

crcval = 0x0000U;
crcval = sd_crc16_byte(crcval, first_byte);
(...)
crcval = sd_crc16_byte(crcval, last_byte);
crc_byte_0 = crcval >> 8;
crc_byte_1 = crcval & 0xFFU;

Los valores de crc_byte y crc_byte_0 y crc_byte_1 se pueden usar para proporcionar los datos CRC necesarios hacia la tarjeta o para la comparación al leer (sectores de datos). Para los sectores de datos, crc_byte_0 viene primero (por lo tanto, CRC es Big Endian en la tarjeta).

    
respondido por el Jubatian

Lea otras preguntas en las etiquetas