Détérioration de contrôleur de carte µSD

C'est le lieu des discussions diverses et variées, mais toujours en rapport avec le thème général du forum et dans l'esprit de celui-ci. Contient des rubriques électroniques.

Modérateurs : Papy.G, fneck, Carl

Avatar de l’utilisateur
Papy.G
Modérateur
Messages : 3054
Inscription : 10 juin 2014 13:40
Localisation : Haute-Garonne/Gers

Détérioration de contrôleur de carte µSD

Message par Papy.G »

Bonjour à tous, voilà, je viens de cramer une carte µSD malgré qu'elle soit récente et n'ait pas été utilisée intensivement, et comme c'est la deuxième en six mois, j'avais plusieurs questions à vous poser:

Pensez-vous qu'il soit possible par des erreurs de communications (envoi de mauvaises commandes, utilisation de programmes "expérimentaux", retrait de carte à la sauvage…) de rendre hors-service une carte SD? (Je sais qu'on peut foutre en l'air ainsi un système de fichiers, mais carrément de ne plus pouvoir formater.)

Avez-vous des utilitaires qui pourraient intervenir sur le fonctionnement bas-niveau d'une carte SD? Tout ce que je trouve en cherchant son des utilitaires de restauration de fichiers après formatage rapide. :|
Soyez exigeants, ne vous contentez pas de ce que l'on vous vend.
Demandez-en plus, ou faites-le vous-même.
__sam__
Messages : 7983
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: Détérioration de contrôleur de carte µSD

Message par __sam__ »

Je pige pas le titre : tu parles du contrôleur ou de la µSD elle-même ?
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Avatar de l’utilisateur
jojo
Messages : 668
Inscription : 13 mai 2007 13:27
Localisation : Entre la France, la Suisse et l'Italie ... dans la vallée du bien décolleté.

Re: Détérioration de contrôleur de carte µSD

Message par jojo »

Je ne sais pas si ça peux t'aider mais Sandisk renvoie systématiquement une carte sd en cas de défaillance dans les 10 ans après l'achat et ce même sans la preuve d'achat (une photo recto-verso avec le n° de série suffit en expliquant que le ticket a été perdu par exemple). Certes, ça ne permet pas de récupérer le contenu de la carte défectueuse mais ça évite surtout d'avoir à en racheter une ! J'ai déjà eu recours 2 fois à ce service suite à une mauvaise manipulation de la carte sd dans un téléphone.

Le lien pour le retour si tu es concerné: Demande d’Autorisation de Retour de Matériel
Avatar de l’utilisateur
Papy.G
Modérateur
Messages : 3054
Inscription : 10 juin 2014 13:40
Localisation : Haute-Garonne/Gers

Re: Détérioration de contrôleur de carte µSD

Message par Papy.G »

Sam> Le contrôleur de/dans la carte, si je ne m'abuse, en gros, une carte SD, c'est un bloc mémoire, et un bloc contôleur/interface, non?
L'idée, c'est qu'un hdd par exemple, tu peux foirer son système de fichiers, mais tu peux toujours re-formater et après, ça roule. La question est: le micro-programme de contrôle interne d'une carte SD est-il inscriptible, ou est-ce le système de protection (Secure Digital) pourrait être activé par erreur?
Dans ma GC, où elle est adressée en SPI, je vois les bonnes valeurs de mémoire totale et occupée, sur le Mac ou machine virtuelle Windows, le disque est inexploitable, et apparaît verrouillé en écriture.

Jojo> Oui, j'avais fait une procédure pour un proche avec une carte SanDisk ou Kingston, je ne sais plus, et ils ne sont pas trop regardants.
Il y a des marques qui tiennent à leur image, j'ai obtenu un échange sur une manette de Game Cube BigBen longtemps après l'achat, j'avais l'emballage d'origine, le ticket, mais surtout, j'ai relevé une arnaque manifeste sur l'emballage (double moteur de vibration annoncé, et à l'intérieur de ladite manette, ô surprise, un seul vibreur! :evil: )
Mais c'est une marque de redistribution polonaise (Platinet), je vais essayer de les contacter, ou voir aussi avec l'organisme de cashback par lequel je l'avais obtenu (Maximiles).
Pour les données, c'étaient des dumps/backups de mes disques GameCube, rien d'unique ou rare n'a été perdu. Mais bon, c'était une carte de 64Go, quand-même…

Je me demande s'il n'y a pas un soucis avec mon lecteur de cartes ou l'utilisation de la capture de port USB de VirtualBox, car c'est lors d'une telle utilisation que les deux défaillances sont apparues. :?
Soyez exigeants, ne vous contentez pas de ce que l'on vous vend.
Demandez-en plus, ou faites-le vous-même.
__sam__
Messages : 7983
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: Détérioration de contrôleur de carte µSD

Message par __sam__ »

Est-ce que tu as essayé cet oui de l'association SD ?
https://www.sdcard.org/downloads/formatter/
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Daniel
Messages : 17418
Inscription : 01 mai 2007 18:30
Localisation : Vaucluse
Contact :

Re: Détérioration de contrôleur de carte µSD

Message par Daniel »

Première question à se poser : Quel fabricant et quel modèle ? Carte authentique ou contrefaçon ?
Si c'est une carte sans marque ou une contrefaçon de Sandisk, c'est normal que le contrôleur tombe en panne.

Deuxième question : Sur quoi a-t-elle été connectée ? Si elle a été exposée à des tensions trop élevées, ou inverses, les diodes de protection ne suffisent pas toujours à la protéger efficacement.

J'ai déjà utilisé plus d'une centaine de cartes microSD. Aucune carte de marque (Sandisk, Kingston, Toshiba, etc.) n'est tombée en panne. Les cartes chinoises ont presque toutes eu un problème : lenteurs inexplicables, initialisation impossible, erreurs d'écriture ou de lecture.

Pour vérifier l'authenticité des cartes microSD j'ai écrit un programme Arduino qui liste sur un petit écran TFT toutes les informations des principaux registres : OCR, CID et CSD. Le voici :

Code : Tout sélectionner

/**************************************************\
*           S D C A R D I N F O _ T F T            * 
*           (c) 2020 - Daniel Coulom               *  
*           http://dcmoto.free.fr/                 *
*           http://forum.system-cfg.com/           *
*--------------------------------------------------*
* Ce code est distribue gratuitement dans l'espoir *
* qu'il sera utile, mais sans aucune  garantie  et *
* sans  engager  la  responsabilité  de  l'auteur. *
* Vous  pouvez  l' utiliser,  le  modifier  et  le *
* diffuser librement, en conservant cette  licence *
* et les références de l'auteur dans   toutes  les *
* copies. L'exploitation commerciale est interdite.*
\**************************************************/
/*
Affichage de contenu des registres de la carte SD,
en particulier le CID et le CSD
*/

/***************************************************
*                Version 2020.02.03                *
****************************************************
Historique
2020.02.03 affichage sur ecran TFT
2020.02.02 premiere version operationnelle

Connexion module Catalex pour carte micro SD
 GND --> Arduino GND
 SCK --> Arduino D13
MISO --> Arduino D12
MOSI --> Arduino D11
 VCC --> Arduino VCC (5V)
  CS --> Arduino D10
 
*****************************************************************
SD card management is adapted from SimpleSDAudio library.
Visit SimpleSDAudio website for more information:
http://www.hackerspace-ffm.de/wiki/index.php?title=SimpleSDAudio
*****************************************************************
*/
//#define DEBUG
#define SDCARDINFO_VERSION "  v1.0"

#include <MCUFRIEND_kbv.h>            
MCUFRIEND_kbv tft;

// Assign human-readable names to some common 16-bit color values:

#define BLACK                         0x0000
#define WHITE                         0xFFFF
#define GRAY                          0x8410
#define BLUE                          0x001F
#define RED                           0xF800
#define GREEN                         0x07E0
#define PINK                          0xF8FF
#define ORANGE                        0xFA60
#define CYAN                          0x07FF
#define AQUA                          0x04FF
#define MAGENTA                       0xF81F
#define YELLOW                        0xFFE0

// SD card constants
#define SD_CARD_TYPE_SD1        1 /** Standard capacity V1 SD card */
#define SD_CARD_TYPE_SD2        2 /** Standard capacity V2 SD card */
#define SD_CARD_TYPE_SDHC       3 /** High Capacity SD card */
#define SD_PARTTYPE_UNKNOWN     0
#define SD_PARTTYPE_SUPERFLOPPY 1
#define SD_PARTTYPE_FAT16       2
#define SD_PARTTYPE_FAT32       3
#define SD_INIT_TIMEOUT      2000 /** temps maxi pour l'initialisation */
#define SD_READ_TIMEOUT       300 /** temps maxi pour le debut de la lecture d'un bloc */
#define SD_COMMAND_TIMEOUT    300 /** temps maxi pour repondre a une commande */
#define SD_READY_STATE       0x00 /** status for card in the ready state */
#define SD_IDLE_STATE        0x01 /** status for card in the idle state */
#define SD_ILLEGAL_COMMAND   0x04 /** status bit for illegal command */
#define SD_DATA_START_BLOCK  0xFE /** start data token for read or write single block*/

// SD card commands
#define SD_CMD0   0x00  /** GO_IDLE_STATE - init card in spi mode if CS low */
#define SD_CMD8   0x08  /** SEND_IF_COND - verify SD Memory Card interface operating condition.*/
#define SD_CMD9   0x09  /** SEND_CSD - read the Card Specific Data (CSD register), response R1 */
#define SD_CMD10  0x0A  /** SEND_CID - read the card identification information (CID register), response R1 */
#define SD_CMD12  0x0C  /** STOP_TRANSMISSION - end multiple block read sequence, response R1b */
#define SD_CMD13  0x0D  /** SEND_STATUS - read the card status register, response R2 */
#define SD_CMD16  0x10  /** SET_BLOCKLEN arg0[31:0]: block length, response R1 */
#define SD_CMD17  0x11  /** READ_SINGLE_BLOCK - read a single data block from the card, response R1 */
#define SD_CMD18  0x12  /** READ_MULTIPLE_BLOCK - read a multiple data blocks from the card, response R1 */
#define SD_CMD55  0x37  /** APP_CMD - escape for application specific command */
#define SD_CMD58  0x3A  /** READ_OCR - read the OCR register of a card */
#define SD_CMD59  0x3B  /** CRC_ON_OFF - Turns CRC option on or off, response R1 */
#define SD_ACMD41 0x29  /** SD_SEND_OP_COMD - Sends host capacity support information and activates the card's initialization process */

// SD card error codes
#define SD_ERROR_CMD0           0x01 /** timeout error for command CMD0 (initialize card in SPI mode), signal problem */
#define SD_ERROR_CMD8           0x02 /** CMD8 was not accepted - not a valid SD card */
#define SD_ERROR_ACMD41         0x03 /** ACMD41 initialization process timeout */
#define SD_ERROR_CMD58          0x04 /** card returned an error response for CMD58 (read OCR) */
#define SD_ERROR_CMD16          0x05 /** card returned an error response for CMD16 (set block len) */
#define SD_ERROR_VOLTMATCH      0x06 /** card operation voltage range doesn't match (2.7V - 3.6V) */
#define SD_ERROR_READ_TIMEOUT   0x07 /** timeout while waiting for start of read data */
#define SD_ERROR_READ           0x08 /** card returned error token when tried to read data */
#define SD_ERROR_CMD17          0x09 /** card returned an error response for CMD17 (read single block) */
#define SD_ERROR_CMD9           0x0e /** card returned an error response for CMD9  (read CSD) */
#define SD_ERROR_CMD10          0x0f /** card returned an error response for CMD10 (read CID) */
#define SD_ERROR_CMD18          0x10 /** card returned an error response for CMD18 (read multi block) */
#define SD_ERROR_INVAL_SECT0    0x30 /** No valid MBR/FAT-BS signature found in sector 0 */
#define SD_ERROR_INVAL_BS       0x31 /** Malformed FAT boot sector */
#define SD_ERROR_FAT12          0x32 /** FAT12 is not supported */
#define SD_ERROR_FAT_NOT_INIT   0x33 /** FAT not initialized properly */
#define SD_ERROR_DIR_EOC        0x34 /** End of cluster reached (not a real error, just information) */
#define SD_ERROR_FILE_NOT_FOUND 0x35 /** File not found after reaching end of directory */
#define SD_ERROR_EOF            0x38 /** End of file reached */

// SD card structures
typedef struct {
  uint8_t     Attributes;
  uint32_t    Size;           // in bytes
  uint32_t    FirstCluster;   // First cluster
  uint32_t    ActSector;      // 0 to (SD_FAT.SecPerClus - 1)
  uint32_t    ActBytePos;     // 0 to Size
} SD_File_t;

typedef struct  {
  uint8_t     PartType;           // Use this to test whether it is FAT16 or FAT32 or not initialized
  // Stuff from FAT boot sector
  uint8_t     SecPerClus;
  uint16_t    RsvdSecCnt;
  uint8_t     NumFATs;
  uint16_t    RootEntryCount;
  uint32_t    TotalSec;
  uint32_t    SecPerFAT;
  uint32_t    RootClus;
  // For cluster calculations
  uint8_t     ClusterSizeShift;
  uint32_t    ClusterCount;
  // Start addresses (all in blocks / sector addresses)
  uint32_t    BootSectorStart;    // Address of boot sector from FAT
  uint32_t    FatStart;           // First file allocation table starts here
  uint32_t    RootDirStart;       // Root directory starts here
  uint32_t    DataStart;          // Cluster 0 starts here
  uint32_t    ClusterEndMarker;   // if Cluster >= this then end of file reached.
} SD_FAT_t;

// SD card variables
SD_File_t FileInfo;      // information fichier
SD_FAT_t SD_FAT;         // FAT 
uint8_t  SD_type;        // type de la carte SD
uint8_t  SD_CSPin;       // numero de la broche CS de la carte SD
uint8_t  SD_buffer[513]; // SD buffer must hold 512 bytes + 1

// chaine de caracteres pour affichage
char name[20];


/////////////////////////////////////////////////////////////////////////////
// Programme principal
/////////////////////////////////////////////////////////////////////////////
void setup()
{
 uint32_t i;
 uint32_t an, mois;
 uint32_t blocklength;
 uint32_t cardsize;
 uint64_t mult;
 uint8_t SDHC;
 uint8_t reg[18];
 char string[256];
 uint16_t  identifier;               // TFT identifier

#ifdef DEBUG
 char barre[256];
 strcpy(barre, "================================================================");
 Serial.begin(9600);      //open the serial port at 9600 bps:
#endif

 //Initialisations
 SD_CSPin = 10;           //numero de la broche CS de la carte SD
 SD_Init();               //initialiser la carte SD
  
//========================================================================
// Affichage de l'ecran de presentation
//========================================================================
 
  tft.reset();
  identifier = tft.readID(); // lecture de l'identifiant
  tft.begin(identifier);     // initialisation de l'ecran
  tft.setRotation(1);        // mode paysage

  tft.fillScreen(BLACK);      
  tft.fillRect(0,0,320,16,YELLOW);
  tft.setCursor(24,1);
  tft.setTextSize(2);
  tft.setTextColor(BLACK); tft.print(F("SDCARD INFO "));
  tft.setTextColor(RED); tft.print(F("T"));
  tft.setTextColor(GREEN);tft.print(F("F"));
  tft.setTextColor(BLUE);tft.print(F("T"));
  tft.setTextColor(BLACK); tft.println(F(SDCARDINFO_VERSION));
  tft.setTextColor(GREEN);
  tft.setTextSize(1);
  tft.println();
  
//========================================================================
// OCR
//========================================================================
 //CMD58 command (read 0CR)
 SD_CardCommand(58, 0);            //envoi CMD58 
 for(i = 0; i < 4; i++)            //boucle sur 4 octets
 {
  reg[i] = SD_SpiReadByte();
  sprintf(string + 3 * i, "%02x ", reg[i]);
 } 

 //OCR en hexadecimal
#ifdef DEBUG
 Serial.println(barre);
 Serial.print("OCR = ");
 Serial.println(string);     
 Serial.println(barre);
#else
 tft.println("OCR =================================================");
 tft.println(string);     
#endif
  
 //Voltage
#ifdef DEBUG
 Serial.print("Voltage................: ");
 if(reg[2] & 128) Serial.print("2.7 ");
 if(reg[1] &   1) Serial.print("2.8 ");
 if(reg[1] &   2) Serial.print("2.9 ");
 if(reg[1] &   4) Serial.print("3.0 ");
 if(reg[1] &   8) Serial.print("3.1 ");
 if(reg[1] &  16) Serial.print("3.2 ");
 if(reg[1] &  32) Serial.print("3.3 ");
 if(reg[1] &  64) Serial.print("3.4 ");
 if(reg[1] & 128) Serial.print("3.5 3.6");
 Serial.println();
#else
 tft.print("Voltage: ");
 if(reg[2] & 128) tft.print("2.7 ");
 if(reg[1] &   1) tft.print("2.8 ");
 if(reg[1] &   2) tft.print("2.9 ");
 if(reg[1] &   4) tft.print("3.0 ");
 if(reg[1] &   8) tft.print("3.1 ");
 if(reg[1] &  16) tft.print("3.2 ");
 if(reg[1] &  32) tft.print("3.3 ");
 if(reg[1] &  64) tft.print("3.4 ");
 if(reg[1] & 128) tft.print("3.5 3.6");
 tft.println();
#endif

 //Switching to 1.8V
#ifdef DEBUG
 Serial.print("Switching to 1.8V......: ");
 if(reg[0] & 1) Serial.println("YES");
           else Serial.println("NO");
#else
 tft.print("Switching to 1.8V.....: ");
 if(reg[0] & 1) tft.println("YES");
           else tft.println("NO");
#endif

 //Card capacity status
#ifdef DEBUG
 Serial.print("Card capacity status...: ");
 Serial.println((reg[0] >> 6) & 1);
#else
 tft.print("Card capacity status..: ");
 tft.println((reg[0] >> 6) & 1);
#endif

 //Card power up status
#ifdef DEBUG
 Serial.print("Card power up status...: ");
 Serial.println((reg[0] >> 7) & 1);
 Serial.println();
#else
 tft.print("Card power up status..: ");
 tft.println((reg[0] >> 7) & 1);
 tft.println();
#endif

  
//========================================================================
// CID
//========================================================================
 //CMD10 command (read CID)
 SD_CardCommand(10, 0);            //envoi CMD10 
 while(SD_SpiReadByte() != 0xfe);  //attente octet $FE de debut de bloc
 for(i = 0; i < 18; i++)           //boucle sur 18 octets (CID=16 + CRC=2)
 {
  reg[i] = SD_SpiReadByte();
  sprintf(string + 3 * i, "%02x ", reg[i]);
 } 
 string[3 * i - 1] = 0;
 
 //CID en hexadecimal
#ifdef DEBUG
 Serial.println(barre);
 Serial.print("CID = ");
 Serial.println(string);     
 Serial.println(barre);
#else
 tft.println("CID =================================================");
 tft.print(string);     
#endif

 //Manufacturer
 string[2] = 0;
#ifdef DEBUG
 Serial.print("Manufacturer ID........: ");
 Serial.print(string);
#else
 tft.print("Manufacturer.ID.......: ");
 tft.print(string);
#endif
 Manufacturer(reg[0]);
#ifdef DEBUG
 Serial.print("              (");
 Serial.print(name);
 Serial.println(")");
#else
 tft.print(" (");
 tft.print(name);
 tft.println(")");
#endif

 //Application ID
 string[8] = 0;
 for(i = 0; i < 2; i++) name[i] = reg[i + 1];
 name[2] = 0; 
#ifdef DEBUG
 Serial.print("Application ID.........: ");
 Serial.print(string + 3);
 Serial.print("           (");
 Serial.print(name);
 Serial.println(")");
#else
 tft.print("Application.ID........: ");
 tft.print(string + 3);
 tft.print(" (");
 tft.print(name);
 tft.println(")");
#endif

 //Product name
 string[23] = 0;
 for(i = 0; i < 5; i++) name[i] = reg[i + 3];
 name[5] = 0; 
#ifdef DEBUG
 Serial.print("Product name...........: ");
 Serial.print(string + 9);
 Serial.print("  (");
 Serial.print(name);
 Serial.println(")");
#else
 tft.print("Product name..........: ");
 tft.print(string + 9);
 tft.print(" (");
 tft.print(name);
 tft.println(")");
#endif

 //Product revision
 string[26] = 0;
#ifdef DEBUG
 Serial.print("Product revision.......: ");
 Serial.println(string + 24);
#else
 tft.print("Product revision......: ");
 tft.println(string + 24);
#endif

 //Product serial number
 string[38] = 0;
#ifdef DEBUG
 Serial.print("Product serial number..: ");
 Serial.println(string + 27);
#else
 tft.print("Product serial number.: ");
 tft.println(string + 27);
#endif

 //Manufacturing date
 string[44] = 0;
 i = 256 * reg[13] + reg[14]; mois = i & 15; an = 2000 + (i >> 4);
#ifdef DEBUG
 Serial.print("Manufacturing date.....: ");
 Serial.print(string + 39);
 Serial.print("           (");
 Serial.print(an);
 Serial.print("/");
 Serial.print(mois);
 Serial.println(")");
#else
 tft.print("Manufacturing date....: ");
 tft.print(string + 39);
 tft.print(" (");
 tft.print(an);
 tft.print("/");
 tft.print(mois);
 tft.println(")");
#endif

 //checksum
 string[47] = 0;
#ifdef DEBUG
 Serial.print("Checksum...............: ");
 Serial.println(string + 45);
#else
 tft.print("Checksum..............: ");
 tft.println(string + 45);
#endif

 //CRC
 string[53] = 0;
#ifdef DEBUG
 Serial.print("CRC for R2 response....: ");
 Serial.println(string + 48);
 Serial.println();
#else
 tft.print("CRC for R2 response...: ");
 tft.println(string + 48);
 tft.println();
#endif
  
//========================================================================
// CSD
//========================================================================
 //CMD9 command (read CSD)
 SD_CardCommand(9, 0);             //envoi CMD9 
 while(SD_SpiReadByte() != 0xfe);  //attente octet $FE de debut de bloc
 for(i = 0; i < 18; i++)           //boucle sur 18 octets (CSD=16 + CRC=2)
 {
  reg[i] = SD_SpiReadByte();
  sprintf(string + 3 * i, "%02x ", reg[i]);
 } 
 string[3 * i - 1] = 0;

 //CSD en hexadecimal
#ifdef DEBUG
 Serial.println(barre);
 Serial.print("CSD = ");
 Serial.println(string);
 Serial.println(barre);
#else
 tft.println("CSD =================================================");
 tft.print(string);     
#endif

 //CSD Structure version
 SDHC = reg[0] & 64;
#ifdef DEBUG
 Serial.print("CSD structure version..: ");
 if(SDHC) Serial.println("2.0 - High Capacity (SDHC) & Extended Capacity (SDXC)");
     else Serial.println("1.0 - Standard Capacity (SDSC)");
#else
 tft.print("CSD structure version.: ");
 if(SDHC) tft.println("2.0 - SDHC & SDXC");
     else tft.println("1.0 - SD ou SDSC");
#endif

 //READ_BL_LEN
 i = (reg[5] & 15) - 1;
 blocklength = 2 << i;
#ifdef DEBUG
 Serial.print("Read data block length.: ");
 Serial.println(blocklength);
#else
 tft.print("Read data block length: ");
 tft.println(blocklength);
#endif

 //C_SIZE
 if(SDHC)
 {
  cardsize = reg[7] << 16;
  cardsize += reg[8] << 8;
  cardsize += reg[9];
 }
 else
 {
  cardsize = (reg[6] & 3) << 10;
  cardsize += reg[7] << 2;
  cardsize += reg[8] >> 6;
 }
#ifdef DEBUG
 Serial.print("Device size.................: ");
 Serial.println(cardsize);
#else
 tft.print("Device size...........: ");
 tft.println(cardsize);
#endif

 //C_SIZE_MULT
 if(SDHC == 0)
 {
  i = (reg[9] & 3) << 1;
  i += reg[10] >> 7;
#ifdef DEBUG
  Serial.print("Device size multiplier.: ");
  Serial.println(i);
#else
  tft.print("Device size multiplier: ");
  tft.println(i);
#endif
 }
 
 //Card size
 if(SDHC) mult = 1024; else mult = 2 << (i + 1);
 mult *= cardsize + 1; //resultat sur 64 bits
 mult *= blocklength;  //resultat sur 64 bits
 cardsize = mult / 10000; //partie gauche
#ifdef DEBUG
 Serial.print("Card memory capacity...: ");
 Serial.print(cardsize);
#else
 tft.print("Card memory capacity..: ");
 tft.print(cardsize);
#endif
 cardsize = mult % 10000; //partie droite
#ifdef DEBUG
 sprintf(string, "%04u", cardsize);
 Serial.println(string);
#else
 sprintf(string, "%04u", cardsize);
 tft.println(string);
#endif
 
 //checksum
 string[47] = 0;
#ifdef DEBUG
 Serial.print("Checksum...............: ");
 Serial.println(string + 45);
#else
 tft.print("Checksum..............: ");
 tft.println(string + 45);
#endif

 //CRC
 string[53] = 0;
#ifdef DEBUG
 Serial.print("CRC for R2 response....: ");
 Serial.println(string + 48);
 Serial.println();
#else
 tft.print("CRC for R2 response...: ");
 tft.println(string + 48);
 tft.println();
#endif
}

/////////////////////////////////////////////////////////////////////////////
// Decodage du code fabricant
/////////////////////////////////////////////////////////////////////////////
void Manufacturer(uint8_t code)
{
 switch(code)
 {
  case 0x00: strcpy(name, "Unbranded"); break;
  case 0x01: strcpy(name, "Panasonic"); break;
  case 0x02: strcpy(name, "Toshiba"); break;
  case 0x03: strcpy(name, "Sandisk"); break;
  case 0x1b: strcpy(name, "Samsung"); break;
  case 0x1d: strcpy(name, "AData"); break;
  case 0x27: strcpy(name, "Phison"); break;
  case 0x28: strcpy(name, "Lexar"); break;
  case 0x31: strcpy(name, "Silicon Power"); break;
  case 0x41: strcpy(name, "Kingston"); break;
  case 0x74: strcpy(name, "Transcend"); break;
  case 0x76: strcpy(name, "Patriot?"); break;
  case 0x82: strcpy(name, "Sony?"); break;
  default:   strcpy(name, "Unknown"); break;
 }
 return; 
}

/////////////////////////////////////////////////////////////////////////////
// Fonction d'acces a la carte SD
/////////////////////////////////////////////////////////////////////////////

/**************************************************************************\
* Set CS High 
* Sends also one dummy byte to ensure MISO goes high impedance
\**************************************************************************/
void SD_SetCSHigh()
{
 digitalWrite(SD_CSPin, HIGH);
 SD_SpiSendByte(0xff);
}

/**************************************************************************\
* Sends a raw byte to the SPI - \param[in] b The byte to sent.
\**************************************************************************/
void SD_SpiSendByte(uint8_t b)
{
 SPDR = b;
 while(!(SPSR & (1 << SPIF))); /* wait for byte to be shifted out */
 SPSR &= ~(1 << SPIF);
}

/**************************************************************************\
* Send a command to the memory card which responses with a R1 response 
* (and possibly others).
* \param[in] command The command to send.
* \param[in] arg The argument for command.
* \returns The command answer.
\**************************************************************************/
uint8_t SD_CardCommand(uint8_t cmd, uint32_t arg) 
{
 uint8_t response;
 uint8_t crc;
 uint16_t t0;
      
 // select card
 digitalWrite(SD_CSPin, LOW);

 // wait up to timeout if busy
 t0 = ((uint16_t)millis());
 while (SD_SpiReadByte() != 0xFF)
  if ((((uint16_t)millis()) - t0) >= SD_COMMAND_TIMEOUT) break;

 // send command
 SD_SpiSendByte(cmd | 0x40);

 // send argument
 SD_SpiSendByte((arg >> 24) & 0xff);
 SD_SpiSendByte((arg >> 16) & 0xff);
 SD_SpiSendByte((arg >>  8) & 0xff);
 SD_SpiSendByte((arg >>  0) & 0xff);
  
 // send CRC, only required for commands 0 and 8
 crc = 0xFF;
 if (cmd == SD_CMD0) crc = 0x95;  // correct crc for CMD0 with arg 0
 if (cmd == SD_CMD8) crc = 0x87;  // correct crc for CMD8 with arg 0X1AA
 SD_SpiSendByte(crc);

 // skip stuff byte for stop read
 if (cmd == SD_CMD12) SD_SpiReadByte();

 // wait for response
 for(uint8_t i = 0; i < 100; ++i)
 {
  response = SD_SpiReadByte();
  if(response != 0xff) break;
 }
 return response;
}

/**************************************************************************\
* Send an application specific command which responses with a R1 response 
* (and possibly others).
* \param[in] command The command to send.
* \param[in] arg The argument for command.
* \returns The command answer.
\**************************************************************************/
uint8_t SD_CardACommand(uint8_t cmd, uint32_t arg)
{
 SD_CardCommand(SD_CMD55, 0);
 return SD_CardCommand(cmd, arg);
}

/**************************************************************************\
 * Initialize the SD memory card.
 * Power up the card, set SPI mode.
 * Detects the card version (V1, V2, SDHC), sets sector length to 512.
 * \return Zero if successfull, errorcode otherwise
\**************************************************************************/
uint8_t SD_Init()
{
 uint8_t status;
 uint16_t t0 = ((uint16_t)millis());
 uint32_t arg;

 /* Setup ports */
 pinMode(SD_CSPin, OUTPUT);
 digitalWrite(SD_CSPin, HIGH);
 pinMode(MISO, INPUT);
 pinMode(SCK, OUTPUT);
 pinMode(MOSI, OUTPUT);
 pinMode(SS, OUTPUT);
  
 digitalWrite(SCK, LOW);
 digitalWrite(MOSI, LOW);
 digitalWrite(SS, HIGH);

 /*
 * SPI configuration: 
 * - enable uC for SPI master
 * - typical no interrupts are used for SPI
 * - data order: MSB is transmitted first
 * - clock polarity: CLK is low when idle
 * - clock phase: 1-0 > Sample, 0-1 > Setup
 * - clock frequency: less than 400kHz 
 *   (will be switched to higher value after initialization)
 */
 /* 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 */
  
 // must supply min of 74 clock cycles with CS high.
 SD_SetCSHigh();
 for (uint8_t i = 0; i < 10; i++) SD_SpiSendByte(0xFF);

 // command to go idle in SPI mode
 while ((SD_CardCommand(SD_CMD0, 0)) != SD_IDLE_STATE)
  if ((((uint16_t)millis()) - t0) > SD_INIT_TIMEOUT) {SD_SetCSHigh(); return(SD_ERROR_CMD0);}
  
 // check SD version ( 2.7V - 3.6V + test pattern )
 SD_type = 0;
 if ((SD_CardCommand(SD_CMD8, 0x1AA) & SD_ILLEGAL_COMMAND)) SD_type = SD_CARD_TYPE_SD1;
    // Not done here: Test if SD or MMC card here using CMD55 + CMD1
 else
 {
  // only need last byte of r7 response
  SD_SpiReadByte();
  SD_SpiReadByte();
  status = SD_SpiReadByte();
  if ((status & 0x01) == 0) // card operation voltage range doesn't match
  {SD_SetCSHigh(); return(SD_ERROR_VOLTMATCH);}
  if (SD_SpiReadByte() != 0xAA) {SD_SetCSHigh(); return(SD_ERROR_CMD8);}
  SD_type = SD_CARD_TYPE_SD2;
 }
  
 // Turn CRC option off
 SD_CardCommand(SD_CMD59, 0);
  
 // initialize card and send host supports SDHC if SD2
 arg = (SD_type == SD_CARD_TYPE_SD2) ? 0X40000000 : 0;
 while ((SD_CardACommand(SD_ACMD41, arg)) != SD_READY_STATE) // check for timeout
  if ((((uint16_t)millis()) - t0) > SD_INIT_TIMEOUT) {SD_SetCSHigh(); return(SD_ERROR_ACMD41);}
  
 // if SD2 read OCR register to check for SDHC card
 if (SD_type == SD_CARD_TYPE_SD2)
 {
  if (SD_CardCommand(SD_CMD58, 0)) {SD_SetCSHigh(); return(SD_ERROR_CMD58);}
  // other implementation test only against 0x40 for SDHC detection...
  if ((SD_SpiReadByte() & 0xC0) == 0xC0) SD_type = SD_CARD_TYPE_SDHC;
  // discard rest of ocr - contains allowed voltage range
  SD_SpiReadByte();
  SD_SpiReadByte();
  SD_SpiReadByte();
 }

 // set block size to 512 bytes
 if(SD_CardCommand(SD_CMD16, 512)) {SD_SetCSHigh(); return(SD_ERROR_CMD16);}
 SD_SetCSHigh();
 SD_SpiSetHighSpeed();
 return 0;
}

/**************************************************************************\
* Set SPI for full operation speed (up to 25 MHz).
* Will be called after first part of card 
* initialization was successful.
\**************************************************************************/
void SD_SpiSetHighSpeed(void)
{
 SPCR &= ~((1 << SPR1) | (1 << SPR0)); /* Clock Frequency: f_OSC / 4 */
 SPSR |= (1 << SPI2X);         /* Doubled Clock Frequency: f_OSC / 2 */
}

/**************************************************************************\
* Receives a raw byte from the SPI.
* \returns The byte which should be read.
\**************************************************************************/
uint8_t SD_SpiReadByte()
{
 SPDR = 0xff; /* send dummy data for receiving some */
 while(!(SPSR & (1 << SPIF)));
 SPSR &= ~(1 << SPIF);
 return SPDR;
}

/**************************************************************************\
* Read a 512 byte block from an SD card.
* \param[in] blockNumber Logical block to be read.
* \param[out] dst Pointer to the location that will receive the data.
* \return 0 is returned for success, error code otherwise
\**************************************************************************/
uint8_t SD_ReadBlock(uint32_t blockNumber) 
{
  uint8_t status;
  uint16_t t0;

 // use address if not SDHC card
 if (SD_type != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
 if (SD_CardCommand(SD_CMD17, blockNumber)) {SD_SetCSHigh(); return(SD_ERROR_CMD17);}

 // wait for start block token
 t0 = ((uint16_t)millis());
 while ((status = SD_SpiReadByte()) == 0xFF)
  if ((((uint16_t)millis()) - t0) > SD_READ_TIMEOUT) {SD_SetCSHigh(); return(SD_ERROR_READ_TIMEOUT);}
 if (status != SD_DATA_START_BLOCK) {SD_SetCSHigh(); return(SD_ERROR_READ);}
  
 // transfer data
 SPDR = 0xFF;
 for (uint16_t i = 0; i < 512; i++)
 {
  while (!(SPSR & (1 << SPIF)));
  SD_buffer[i] = SPDR;
  SPDR = 0xFF;
 }
 while (!(SPSR & (1 << SPIF)));
 SD_buffer[512] = SPDR;

 // discard CRC
 SD_SpiReadByte();
 SD_SpiReadByte();
 SD_SetCSHigh();

 return 0;
}

void loop(void){}

Ou celui-ci, qui fonctionne sur tous les ordinateurs Thomson :

Code : Tout sélectionner

/**************************************************\
*           S D D R I V E _ I N I T                * 
*           (c) 2018 - Daniel Coulom               *  
*           http://dcmoto.free.fr/                 *
*           http://forum.system-cfg.com/           *
*--------------------------------------------------*
* Ce code est distribue gratuitement dans l'espoir *
* qu'il sera utile, mais sans aucune  garantie  et *
* sans  engager  la  responsabilité  de  l'auteur. *
* Vous  pouvez  l' utiliser,  le  modifier  et  le *
* diffuser librement, en conservant cette  licence *
* et les références de l'auteur dans   toutes  les *
* copies. L'exploitation commerciale est interdite.*
\**************************************************/

* Ce programme initialise une carte SD.
* En cas d'echec il affiche un message
* permettant d'identifier l'erreur.
* Sinon il affiche le contenu des registres
* CID et CSD de la carte.
* Cette version est compatible avec les cartes SD
* et SDHC sur MO et sur TO
    
/**************************************************\
*                Version 2018.07.16                *
\**************************************************/
* Historique
* 2018.07.16 premiere version issue de cs91280_init

*------------------------------------------------------
* DETECTION DU TYPE D'ORDINATEUR TO OU MO
*------------------------------------------------------
  ORG   $9000 
INIT
  PSHS  U,Y,X,DP,B,A,CC                  
  ORCC  #$50           desactive les interruptions 
  LDA   #$E7           valeur initialisation DP pour TO
  LDB   >$FFF2         $FFF2: $F0(MO) et $70(TO)
  BPL   INIT1          TO detecte

*-------------------------------------------------------
* MODIFICATIONS POUR LES ORDINATEURS MO
*-------------------------------------------------------
  LDD   #$3F82         affichage caractere MO = SWI #$82
  STD   WCHAR          modification routine affichage
  LDA   #$A7           valeur initialisation DP pour MO

*-------------------------------------------------------
* Initialisation DP pour SDDRIVE
*-------------------------------------------------------
INIT1
  TFR   A,DP           DP = $A7(MO) ou $E7(TO)
  
*------------------------------------------------------
* CMD0 = SOFTWARE RESET
* Commande precedee de tops d'horloge (minimum 74)
* Test successivement retour 1 et retour 3
*------------------------------------------------------
RESET0
  LDY   #$0008         compteur pour 8 boucles
RESET1
  LDA   #$0A           pour 10 fois 8 tops
  LBSR  CLOCK          envoi de A*8 tops horloge 
  LDU   #CMD0          commande CMD0
  LBSR  EXCMD0         execution commande
  BCC   RESET2         code retour = 1 (OK)
  LEAY  -1,Y           decrementation compteur
  BNE   RESET1         nouvel essai
  BRA   ERROR1         erreur apres 8 essais

*------------------------------------------------------
* CMD8 = SEND INTERFACE CONDITION
* Non reconnue par les cartes SD de version < 2.00
* c'est pourquoi le code retour n'est pas teste.
* Lire les 4 derniers octets de la reponse R7
*------------------------------------------------------
RESET2
  CLR   SD_TYP,PCR     carte SD par defaut 
  LBSR  EXCMD          execution commande
  LDA   #$04           nbre d'octets
  LBSR  CLOCK          envoi 4 fois 8 tops horloge 

*------------------------------------------------------
* CMD55 + ACMD41 = INITIALISATION
* Si la commande ne renvoie pas le code retour
* attendu elle boucle eternellement 
*------------------------------------------------------
RESET3     
  LDY   #$0100         compteur pour 255 essais
RESET4
  LEAY  -1,Y           decrementation compteur
  BEQ   ERROR2         erreur apres 255 essais
  LEAU  CMD55,PCR      adresse commande CMD55
  LBSR  EXCMD          execution commande CMD55
  LBSR  EXCMD          execution commande ACMD41
  BCS   RESET4         carte non prete, nouvel essai

*------------------------------------------------------
* CMD58 = LECTURE OCR
* Permet de determiner le type de carte SD ou SDHC
* Premier octet bit 6 : SD=0 SDHC=1
*------------------------------------------------------
RESET5
  LBSR  EXCMD          execution commande
  BCS   ERROR3         erreur commande
  LBSR  RBYTE          lecture OCR poids fort
  ASLA                 isole le type de carte 
  BPL   RESET6         carte SD   : SD_TYP=0
  INC   SD_TYP,PCR     carte SDHC : SD_TYP=1
RESET6
  LDA   #$03           pour 3 octets        
  LBSR  CLOCK          lecture OCR (octets 2, 3, 4)
  
*------------------------------------------------------
* PAS D'ERREUR DETECTEE
*------------------------------------------------------
ERROR0
  LDY   #MESS0         message "initialisation OK"
  LBSR  DISPL          affichage message
  BRA   GETOCR         lecture OCR
  
*------------------------------------------------------
* ERREUR CMD0
*------------------------------------------------------
ERROR1
  LDY   #MESS1         message "erreur CMD0"
  LBSR  DISPL          affichage message
  BRA   RETOUR         retour au Basic
  
*------------------------------------------------------
* ERREUR ACMD41
*------------------------------------------------------
ERROR2
  LDY   #MESS2         message "erreur ACMD41"
  LBSR  DISPL          affichage message
  BRA   RETOUR         retour au Basic
  
*------------------------------------------------------
* ERREUR CMD58
*------------------------------------------------------
ERROR3
  LDY   #MESS3         message "erreur CMD58"
  LBSR  DISPL          affichage message
  BRA   RETOUR         retour au Basic

*------------------------------------------------------
* CMD58 LECTURE OCR
*------------------------------------------------------
GETOCR
  LDU   #CMD58         commande CMD58
  LBSR  EXCMD          EXCMD = execution commande
  LDY   #MESS6         adresse du message a afficher
  LBSR  DISPL          affichage message
  BSR   DUMP           affichage registre 
  LDB   #$0A           line feed
  LBSR  WCHAR          envoi 

*-------------------------------------------------------
* CMD10 LECTURE CID
*-------------------------------------------------------
GETCID
  LBSR  EXCMD          EXCMD = execution commande
WAIT1
  LBSR  RBYTE          lecture d'un octet
  CMPA  #$FE           test debut de bloc $FE
  BNE   WAIT1          attente debut de bloc
  LDY   #MESS4         adresse du message a afficher
  LBSR  DISPL          affichage message
  BSR   DUMP           affichage registre
  LDB   #$0A           line feed
  LBSR  WCHAR          envoi 

*-------------------------------------------------------
* CMD9 LECTURE CSD
*-------------------------------------------------------
GETCSD
  LBSR  EXCMD          EXCMD = execution commande
WAIT2
  LBSR  RBYTE          lecture d'un octet
  CMPA  #$FE           test debut de bloc $FE
  BNE   WAIT2          attente debut de bloc
  LDY   #MESS5         adresse du message a afficher
  LBSR  DISPL          affichage message
  BSR   DUMP           affichage registre

*------------------------------------------------------
* RETOUR AU BASIC
*------------------------------------------------------
RETOUR
  PULS  CC,A,B,DP,X,Y,U,PC

*-------------------------------------------------------
* Dump d'un registre
*-------------------------------------------------------
DUMP
  LDB   #$03           nombre de lignes
  PSHS  B              empilage compteur lignes
DUMP1
  LDY   #$9F00         adresse buffer ligne
  LDB   #$08           nombre d'octets par ligne
  PSHS  B              empilage compteur octets
HEX  
  LBSR  RBYTE          lecture d'un octet
  STA   ,Y             stockage dans le buffer
  LBSR  HEXA           affichage en hexadecimal
  DEC   ,S             decrementation compteur
  BNE   HEX            octet suivant
  PULS  B              depilage compteur octet
  LDY   #$9F00         adresse buffer ligne
  LDB   #$08           nombre d'octets par ligne
  PSHS  B              empilage compteur octet
ASCII  
  LBSR  CHAR           affichage du caractere
  DEC   ,S             decrementation compteur
  BNE   ASCII          caractere suivant
  PULS  B              depilage compteur octet
  LDB   #$0D           carriage return
  LBSR  WCHAR          envoi 
  LDB   #$0A           line feed
  LBSR  WCHAR          envoi 
  DEC   ,S             decrementation compteur ligne
  BNE   DUMP1          nouvelle ligne
  PULS  B              depilage compteur ligne
  RTS                  retour

*------------------------------------------------------
* AFFICHAGE D'UN CARACTERE POINTE PAR Y
* Y EST INCREMENTE POUR LA LECTURE DU CARACTERE SUIVANT
*------------------------------------------------------
CHAR
  LDB   ,Y+            lecture du caractere du buffer
  CMPB  #$20           test par rapport a $20
  BLO   CHAR1          plus petit = non affichable
  CMPB  #$80           test par rapport a $80
  LBLO  WCHAR          plus petit = affichable
CHAR1
  LDB   #$2E           caractere remplace par un point
  LBRA  WCHAR          affichage

*------------------------------------------------------
* AFFICHAGE CARACTERE POINTE PAR Y EN HEXADECIMAL
* Y EST INCREMENTE POUR LA LECTURE DU CARACTERE SUIVANT
*------------------------------------------------------
HEXA
  LDA   ,Y+            lecture du caractere 
  TFR   A,B            transfert du  caractere dans B 
  LSRB                 decalage 
  LSRB                 a droite 
  LSRB                 de quatre
  LSRB                 bits
  BSR   HEXB           affichage chiffre hexadecimal
  TFR   A,B            transfert du caractere dans B
  ANDB  #$0F           garde les 4 bits de droite
  BSR   HEXB           affichage chiffre hexadecimal
  LDB   #$20           espace
  LBSR  WCHAR          affichage espace
  RTS                  retour

*------------------------------------------------------
* AFFICHAGE CHIFFRE B EN HEXADECIMAL
*------------------------------------------------------
HEXB
  CMPB  #$0A           comparaison avec $0A
  BLO   HEXB1          branchement si plus petit
  ADDB  #$07           sinon ajout de 7
HEXB1
  ADDB  #$30           conversion binaire vers ASCII
  LBSR  WCHAR          affichage du caractere
  RTS                  retour

*------------------------------------------------------
* AFFICHAGE MESSAGE TERMINE PAR ZERO BINAIRE
* ADRESSE DANS LE REGISTRE Y
*------------------------------------------------------
DISPL
  LDB   ,Y+
  BEQ   DISPL9         fin de la chaine
  LBSR  WCHAR          envoi caractere
  BRA   DISPL          caractere suivant
DISPL9
  RTS                  retour
  
*------------------------------------------------------
* LECTURE DE 4 OCTETS NON SIGNIFICATIFS (32 BITS)
*------------------------------------------------------
RBIT32
  BSR   RBYTE          lecture d'un octet
  BSR   RBYTE          lecture d'un octet
  BSR   RBYTE          lecture d'un octet
  BRA   RBYTE          lecture d'un octet

*------------------------------------------------------
* ATTENTE CARTE PRETE PUIS EXECUTION D'UNE COMMANDE
* Le registre U pointe sur les 6 octets de la commande
* Le registre B n'est pas preserve.
* le code retour est dans le registre A
*------------------------------------------------------
EXCMD
  BSR   RBYTE          lecture d'un octet dans A
  INCA                 ajout de 1 ($FF --> $00) 
  BNE   EXCMD          attente carte prete
EXCMD0
  LDB   #$06           nombre d'octets de la commande
EXCMD2
  LDA   ,U+            chargement octet de commande
  BSR   WBYTE          ecriture de l'octet
  DECB                 decrementation compteur
  BNE   EXCMD2         il reste des octets a envoyer
  LDX   #$0100         compteur pour 255 essais
  LDB   #$7F           valeur A et B pour signal SCK
EXCMD3
  LEAX  -1,X           decrementation compteur
  BEQ   EXCMD4         pas de reponse
  LBSR  RB0            lecture d'un bit dans A
  ANDA  #$01           isole le bit lu
  BNE   EXCMD3         attendre bit a zero
  BSR   RB6            lecture des 7 autres bits
  CMPA  ,U+            test code de retour
  BEQ   EXCMD5         code bon, carry clear 
  COMB                 carry set en erreur
EXCMD4
  COMB                 carry set en erreur
EXCMD5
  RTS                  retour

*------------------------------------------------------
* LECTURE D'UN OCTET
* Valeur de l'octet dans le registre A en sortie
*------------------------------------------------------
RBYTE
  LDB   #$7F           initialisation de B        (2) 
  CMPB  <$BF           lecture bit 7              (4)
  ROLA                 pousser dans A             (2)
RB6
  CMPB  <$BF           lecture bit 6              (4)
  ROLA                 pousser dans A             (2)
RB5
  CMPB  <$BF           lecture bit 5              (4)
  ROLA                 pousser dans A             (2)
RB4
  CMPB  <$BF           lecture bit 4              (4)
  ROLA                 pousser dans A             (2)
RB3
  CMPB  <$BF           lecture bit 3              (4)
  ROLA                 pousser dans A             (2)
RB2
  CMPB  <$BF           lecture bit 2              (4)
  ROLA                 pousser dans A             (2)
RB1
  CMPB  <$BF           lecture bit 1              (4)
  ROLA                 pousser dans A             (2)
RB0
  CMPB  <$BF           lecture bit 0              (4)
  ROLA                 pousser dans A             (2)
  RTS                  retour octet dans A        (5)

*------------------------------------------------------
* ECRITURE D'UN OCTET
* Valeur de l'octet dans le registre A en entree
*------------------------------------------------------
WBYTE
  ROLA                 b7 dans carry   (2)
  ROLA                 b7 dans b0      (2)
  STA   <$BF           ecriture bit 7  (4)
  ROLA                 b6 dans b0      (2)
  STA   <$BF           ecriture bit 6  (4)
  ROLA                 b5 dans b0      (2)
  STA   <$BF           ecriture bit 5  (4)
  ROLA                 b4 dans b0      (2)
  STA   <$BF           ecriture bit 4  (4)
  ROLA                 b3 dans b0      (2)
  STA   <$BF           ecriture bit 3  (4)
  ROLA                 b2 dans b0      (2)
  STA   <$BF           ecriture bit 2  (4)
  ROLA                 b1 dans b0      (2)
  STA   <$BF           ecriture bit 1  (4)
  ROLA                 b0 dans b0      (2)
  STA   <$BF           ecriture bit 0  (4)
  RTS                  retour          (5) 

*------------------------------------------------------
* ENVOI DE 8*A TOPS D'HORLOGE
* Le registre B est preserve. Au retour A=0
*------------------------------------------------------
CLOCK
  CMPB  <$BF           envoi d'un top d'horloge
  CMPB  <$BF           envoi d'un top d'horloge
  CMPB  <$BF           envoi d'un top d'horloge
  CMPB  <$BF           envoi d'un top d'horloge
  CMPB  <$BF           envoi d'un top d'horloge
  CMPB  <$BF           envoi d'un top d'horloge
  CMPB  <$BF           envoi d'un top d'horloge
  CMPB  <$BF           envoi d'un top d'horloge
  DECA
  BNE   CLOCK                            
  RTS                                      

*------------------------------------------------------
* AFFICHAGE CARACTERE (CARACTERE DANS REGISTRE B)
* Version TO remplacee par SWI #$82 pour MO
*------------------------------------------------------
WCHAR
  JMP   $E803          envoi caractere

*------------------------------------------------------
* Zones de travail
*------------------------------------------------------
SD_TYP
  FCB 0
  
*------------------------------------------------------
* Messages a afficher
*------------------------------------------------------
MESS0
  FCB $0D,$0A
  FCC "Initialisation OK"
  FCB $0D,$0A,$0D,$0A,$00
MESS1
  FCC "Erreur CMD0"
  FCB $0D,$0A,$0D,$0A,$00
MESS2
  FCC "Erreur ACMD41"
  FCB $0D,$0A,$0D,$0A,$00
MESS3
  FCC "Erreur CMD58"
  FCB $0D,$0A,$0D,$0A,$00
MESS4
  FCC "CID Card IDentification"
  FCB $0D,$0A,$00
MESS5
  FCC "CSD Card Specific Data"
  FCB $0D,$0A,$00
MESS6
  FCC "OCR Operation Conditions"
  FCB $0D,$0A,$00

*------------------------------------------------------
* COMMANDES
*------------------------------------------------------
CMD0
  FCB   $40            go iddle state
  FDB   $0000
  FDB   $0000
  FCB   $95            checksum obligatoire           
  FCB   $01            code retour attendu 1  
*------------------------------------------------------
CMD8
  FCB   $48            send interface condition
  FDB   $0000
  FDB   $01AA
  FCB   $87            checksum obligatoire  
  FCB   $00            code retour attendu  
*------------------------------------------------------
CMD55
  FCB   $77            application command
  FDB   $0000
  FDB   $0000
  FCB   $FF            checksum non testee  
  FCB   $00            code retour attendu  
*------------------------------------------------------
AC41
  FCB   $69            activate card initialization 
  FDB   $4000
  FDB   $0000 
  FCB   $FF            checksum non testee  
  FCB   $00            code retour attendu  
*------------------------------------------------------
CMD58
  FCB   $7A            read OCR
  FDB   $0000
  FDB   $0000
  FCB   $FF            checksum non testee
  FCB   $00            code retour attendu  
*------------------------------------------------------
CMD10
  FCB   $4A            send CID
  FDB   $0000          dummy
  FDB   $0000          dummy
  FCB   $FF            checksum non testee 
  FCB   $00            code retour attendu  
*------------------------------------------------------
CMD9
  FCB   $49            send CSD
  FDB   $0000          dummy
  FDB   $0000          dummy
  FCB   $FF            checksum non testee 
  FCB   $00            code retour attendu  
*------------------------------------------------------

  END
Daniel
L'obstacle augmente mon ardeur.
Avatar de l’utilisateur
Falkor
Messages : 1701
Inscription : 28 juin 2010 12:09
Localisation : Cluny, Saône et Loire

Re: Détérioration de contrôleur de carte µSD

Message par Falkor »

Papy.G a écrit : 09 août 2020 22:26retrait de carte à la sauvage…
J'ai déjà vu des clés usb tuées en abusant du retrait sans déconnexion.
Avatar de l’utilisateur
Papy.G
Modérateur
Messages : 3054
Inscription : 10 juin 2014 13:40
Localisation : Haute-Garonne/Gers

Re: Détérioration de contrôleur de carte µSD

Message par Papy.G »

Merci Sam, bon, ça marche pas, mais je le garde de côté. :wink:

Daniel>Mauvaise pioche, Corée et Taiwan, l'une accompagnait un téléphone Nokia, et l'autre, c'est celle que je viens de cramer, je ne l'ai pas importée moi-même (genre achetée sur Alix, BG, MiniITB ou autre…).
L'appareil en commun est un hub avec lecteur multi-cartes de qualité médiocre (XOOPAR Podium), mais je n'ai pas cramé de cartes avec celui-ci jusque récemment, car j'utilise plus souvent Virtual Box quand j'ai besoin de Windows (avant j'avais une config PC headless et mon bootcamp).
Ton utilitaire m'intéresse, Daniel, mais je n'ai ni Thomson, ni Arduino. :cry:
Personne n'a fait cet outil pour Windows, ou sur GameCube, à la rigueur… :mrgreen:

Falkor> C'est pas que je sois un sauvage, mais quand un appareil plante en lecture ou écriture, c'est un peu comme si la carte était retirée sans déconnection… :|
Soyez exigeants, ne vous contentez pas de ce que l'on vous vend.
Demandez-en plus, ou faites-le vous-même.
Répondre