Problemas al leer la Delkin Micro SD 16 GB usando SPI

He estado trabajando con tarjetas SD y tarjetas micro SD por un tiempo.

Estoy usando Part1_Physical_Layer_Simplified_Specification_Ver6.00 como referencia.

Puedo realizar correctamente la inicialización de la tarjeta, leer y escribir para otras micro SD como ATP 8GB SLC, Panasonic 8GB SLC, etc. Sin embargo, cuando estoy usando Delkin 16 GB SLC (y también Swissbit 8GB SLC), aunque tengo éxito en la inicialización de la tarjeta y escribo, cuando intento leer, no obtengo el token de bloque de inicio 0xFE y hay alrededor de 512 bytes de datos basura antes de que vuelva a ser normal.

El patrón es el siguiente (utilizando el analizador Beagle SPI):

Después de escribir lo siguiente (solo se muestran los primeros 24 bytes, pero el patrón es el mismo):

ingrese la descripción de la imagen aquí

Si estoy escribiendo 0xA0. Por favor, consulte la siguiente imagen:

ingrese la descripción de la imagen aquí

Si cambio los bytes escritos, también se cambian los bytes leídos y también hay una correspondencia uno a uno entre los bytes escritos y los bytes leídos. Pero los bytes no son los mismos.

Estoy verificando que los datos se escribieron correctamente usando el lector de tarjetas SD con el visor hexadecimal HxD.

Para el primer caso:

ingrese la descripción de la imagen aquí

Para el segundo caso:

ingrese la descripción de la imagen aquí

No parece que el voltaje de la tarjeta SD varíe, ya que lo verifiqué en el osciloscopio y permanece en 3,3 voltios durante la lectura.

Estoy usando el Launchpad F28377s de TI como microcontrolador.

Me gustaría obtener las entradas de usted. ¿Qué puedo hacer exactamente para solucionar este problema?

Edit1: se observa exactamente el mismo comportamiento para Swissbit 8GB SLC. Las mismas imágenes de arriba se pueden aplicar a Swissbit. Los datos leídos para Swissbit son los mismos que para Delkin. El reloj SPI antes de la inicialización es de 200 kHz y después de la inicialización se cambia a 1 MHz.

Edit2: mire las imágenes del osciloscopio a continuación (he cambiado la frecuencia del reloj a 225 KHz):

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Edit3: La segunda imagen del osciloscopio sigue inmediatamente a la primera imagen del osciloscopio. La primera imagen es el comando de lectura y la respuesta, mientras que la segunda imagen envía 0xFF y espera el token del bloque de datos de inicio, que es 0xA8 en la segunda imagen, ya que 0xFE se desplaza 2 bits. Puede ver los datos hexadecimales decodificados del osciloscopio en la parte inferior de las imágenes del osciloscopio. Son los mismos que los datos de depuración de mi analizador Beagle SPI para el ejemplo 2 (donde estoy escribiendo 0xA0 y leyendo 0x28).

Edit4: según la sugerencia de Anonymous, actualicé mi código de modo que antes de cada comando y después de CS LOW, envío 8 relojes antes de cualquier transmisión SPI real prevista. Después de completar la respuesta del comando, envío 8 ciclos de reloj justo antes de CS HIGH y 8 ciclos de reloj justo después de CS HIGH. La finalización de la respuesta del comando en el caso de lectura SD significa que hemos recibido el último byte CRC. La finalización de la respuesta del comando en SD Write significa que la tarjeta deja de enviar la señal de ocupado después de escribir. Del mismo modo, también lo he aplicado a otros comandos. Además, no hago CS HIGH hasta que se completan el comando y su respuesta. Por ejemplo, en SD Read Case, hago CS LOW y envío el comando, obtengo la respuesta del comando, obtengo el token de bloque de inicio (0xFE), obtengo el CRC y luego hago CS HIGH.

Gracias.

Respuestas (1)

Creo que deberías haber notado el patrón:

fe 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 00 01 02 03 ...

cambiando esta secuencia dos bits a la derecha se obtiene

ff 80 00 40 80 c1 01 41 81 ...

Así que exactamente la secuencia que tienes. Ha agregado dos bits de repuesto en la transmisión y los bytes se desalinearon. ¿Por qué? Sin diagramas exactos que muestren el reloj, no es posible decirlo. Lo más probable es que tenga problemas con el reloj o la sincronización de datos.

Esta desalineación puede ocurrir en escritura o lectura, por lo que puede parecer que escribe una secuencia incorrecta porque su comando de escritura tiene bytes desalineados y luego vuelve a leer esa secuencia incorrecta (por supuesto), o podría ser un problema de comando de lectura pura. La conclusión de que debe verificar qué tarjeta SD ha escrito realmente en ella, utilizando otro dispositivo que funcione (por ejemplo, PC volcando su tarjeta en el archivo y verificando la imagen), antes de depurar la ejecución del comando de lectura o escritura.

Editar: mirando los diagramas de alcance, veo/recomiendo lo siguiente:

  1. cambie la polaridad del reloj cuando esté inactivo a bajo. Actualmente es alto. Consulte aquí . En otras palabras, use el modo SPI 0;
  2. antes de que comience el comando (antes de poner el primer 0 en la línea MOSI) realice 8 ciclos de reloj de repuesto con CS bajo. Idealmente, haga lo mismo al final del comando: coloque 8 relojes de repuesto con CS bajo cuando se complete el comando, y otros 8 relojes de repuesto con CS alto;
  3. No estoy seguro de entender la segunda imagen: ¿envía FF como comando a la tarjeta? Y parece que la tarjeta informa continuamente 0x05 (comando no válido).

Edición 2:

La segunda imagen del osciloscopio sigue inmediatamente a la primera imagen del osciloscopio.

Tenga mucho cuidado al anular la selección de la tarjeta: sus imágenes muestran que emite un comando a la tarjeta, anula la selección elevando CS alto y luego vuelve a seleccionarla enviando continuamente 0xFF a la tarjeta. Parece que la tarjeta no entiende eso, y devuelve 0x28s, que en realidad son 0x05: la respuesta R1 de "comando no válido" cambió. Solo hay circunstancias específicas en las que puede anular la selección de la tarjeta, se explica en la especificación SD simplificada y sigue un protocolo muy específico:

Cuando la tarjeta indica que está ocupada, el anfitrión puede anular su selección (elevando el CS) en cualquier momento. La tarjeta liberará la línea DataOut un reloj después de que el CS pase a nivel alto. Para verificar si la tarjeta todavía está ocupada, debe volver a seleccionarse afirmando (establecer en baja) la señal CS. La tarjeta reanudará la señal de ocupado (tirando de DataOut bajo) un reloj después del flanco descendente de CS.

Con respecto a mi segundo comentario.

Además, su comentario 2, ¿es necesario para todos los comandos? Actualmente, solo he aplicado su sugerencia a Read Command.

Los ciclos de repuesto, aunque tomarán algún tiempo, asegurarán que la tarjeta haya completado/cancelado correctamente la operación anterior y esté lista para la siguiente. Así que te recomiendo que lo implementes para todos los comandos si es posible.

Hola Anónimo, gracias por tu respuesta. Por favor, mire la penúltima imagen. Allí mostré que leí los datos de la tarjeta SD manualmente desde un lector de tarjetas SD en la PC usando el visor hexadecimal HxD. Y confirma que mi escritura fue exitosa. Lo que pasa con el cambio de bit en la lectura, también lo noté y tiene sentido. Tomaré imágenes de osciloscopio el lunes y las adjuntaré aquí también. Pero cuando vi las señales del osciloscopio la última vez, también muestran el cambio de bits del que estás hablando. Sin embargo, todavía no obtengo el token de bloque de inicio 0xFE de la tarjeta, lo que me preocupa.
Obtiene el token, pero se desplaza dos bits a la derecha, y por lo tanto, en lugar de ff feobtenerff ff 80
Gracias Anónimo ... Entiendo cómo ambos casos se desplazan dos bits a la derecha. ¿Alguna razón en particular por la que pueda pensar que la escritura no tiene problemas pero la lectura se desplaza dos bits?
Como dije anteriormente, se requieren diagramas de alcance con datos y señales de reloj para ver. Debe haber un problema con la sincronización de reloj/datos.
Hola Anónimo... He agregado las imágenes del osciloscopio en Edit2. Por favor échale un vistazo.
Actualicé la respuesta.
Hola Anónimo, "antes de que comience el comando (antes de poner el primer 0 en la línea MOSI) realice 8 ciclos de reloj de repuesto con CS bajo" resolvió el problema. No estoy seguro de si lo pasé por alto, pero ¿se menciona en Part1_Physical_Layer_Simplified_Specification_Ver6.00? Además, su comentario 2, ¿es necesario para todos los comandos? Actualmente, solo he aplicado su sugerencia a Read Command. Para todos los demás comandos, antes de CS Low (antes de enviar cmd) envío 8 relojes y después de CS High (después de la respuesta) envío 8 relojes. Con respecto a su comentario 3, mire la edición.
actualizo la respuesta
Consulte edit4, he incluido su sugerencia, funciona bien para todas las diferentes tarjetas SD que tengo.