Une fat 32 ultra light pour dataloggeur embarqué. (Projet)
Répondre à la discussion
Affichage des résultats 1 à 11 sur 11

Une fat 32 ultra light pour dataloggeur embarqué. (Projet)



  1. #1
    mweber

    Une fat 32 ultra light pour dataloggeur embarqué. (Projet)


    ------

    Bonjour à tous,

    Je suis plus présent sur le forum élec, mais ici c'est une question plus "soft" (mais bas niveau):

    Dans le cadre d'un développement d'un projet sur microcontrôleur (PIC ou autre...) perso & open source, je cherche à développer un système de fichier basé sur la FAT32.

    Il s'agit de réaliser un datalogeur météo, qui écriera des données sur une carte SD en FAT32.

    On va ici s'intéresser qu'au software gérant le système de fichier TAF32, dans la mesure où je dispose déjà de 2 fonctions primitives essentielles d'accès aux secteurs de la carte SD :

    Code:
    char Buffer[512];            // L'image du contenu d'un secteur
    long Numero_secteur;    
    
    MMC_mmc_Read_Sector(Numero_secteur, Buffer);  // Lis le contenu d'un secteur
    MMC_mmc_Write_Sector(Numero_secteur, Buffer); // Écrit dans un secteur
    (Pour les curieux, j'utilise MikroC de MikroElectronika)


    Comme la mémoire RAM et ROM sont très limitées, je souhaite me contenter du minimum absolut pour la gestion FAT32 pour que mes données soient lisible sur PC.


    Formatage de la carte SD + création d'un fichier nommé : "DONNES.TXT" (exclusivement réalisée par le PIC):
    (Si cela était fait sur le PC cela serait +/- Équivalent à la commande format <Lecteur>: /A:2048 /V: DONNEES /FS:FAT32)

    Si la carte SD est vierge ou sans système connu, le programme sur le PIC formate la carte comme cela :
    - Pas de MBR => 1 seule partition
    - Pas de programme de BOOT
    - 1 cluster = 4 secteurs = 2048 octets (Pour info on ne peut pas faire moins avec des cartes de qq Go !)
    - Création d'une entrée fat pour 1 fichier "DONNES.TXT"

    Donc ici, pas de répertoires, pas de création de fichiers avec fopen etc...


    Pour l'écriture (exclusivement réalisée par le PIC) :
    - Accès à la FAT pour trouver le 1er cluster et secteur libre
    - On remplis les secteurs les un à la suite des autre pour remplir "DONNES.TXT" (pas de fragmentation possible car un seul fichier n'est autorisé)
    - On mets à jour la table d'allocation et la taille du fichier
    - On mets à jour le FSIO ?
    - Le PC ne devra pas écrire sur la carte SD il ne set qu'à lire les données

    Pour la lecture des données sur PC (La carte SD est insérée dans un lecteur sur le PC)
    - C'est l'OS qui le gère à son habitude => Transparent pour l'utilisateur (c'est tout le but de ce programme !)

    Pour la lecture des données (Sur le PIC)
    - Accès à la FAT
    - Accès aux clusters et récupération des données.


    Place au code : (que je complèterais au fur et à mesure :

    Code:
    // Variables globales :
    char Buffer[512];
    
    
    // format() : Formate rapide de la carte SD en fat 32
    // Pour le moment n'écrit que le secteur zéro : 1er secteur de l'unique partition
    
    void format(void)
    {
    int i = 0;
    
    // Informations sur la partition FAT32 qui va être créée :
    // 2048 octets par clusters
    const unsigned char Boot_code[] =
                     {0xEB, 0x58 ,0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E,
                      0x30, 0x00, 0x02, 0x04, 0x3E, 0x0D, 0x02, 0x00, 0x00, 0x00,
                      0x00, 0xF8, 0x00, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x00, 0x40, 0x73, 0x00, 0x61, 0x39, 0x00, 0x00,
                      0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00,
                      0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0xE6, 0x1C, 0x0A,
                      0x44, 0x4E, 0x4F, 0x20, 0x4E, 0x41, 0x4D, 0x45, 0x20, 0x20,
                      0x20, 0x20, 0x46, 0x41, 0x54, 0x33, 0x32, 0x20, 0x20, 0x20};
    
    for (i = 0; i < 512; i++)  Buffer[i] = 0;               // Créé une image de secteur vierge
    for (i = 2; i < 1024; i++) mmc_Write_Sector(i, Buffer); // Efface le début de la carte
    
    
    for (i = 0; i < 90; i++) Buffer[i] = Boot_code[i]; // Copie le bootcode identificateur de la partition
    
    mmc_Write_Sector(0, Buffer);                            // Ecriture du secteur 0
    
    }
    Voila, bientot la suite...

    en fait si vous avez un algo simple de gestion de fat 32 cela pourrait m'aider )

    Merci !

    Matthieu

    -----
    Dernière modification par mweber ; 12/05/2017 à 11h55.

  2. #2
    sandrecarpe

    Re : Une fat 32 ultra light pour dataloggeur embarqué. (Projet)

    Bonjour,
    Normalement, ceci :
    Code:
    for (i = 0; i < 512; i++)  Buffer[i] = 0;
    est équivalent à ça :
    Code:
    char Buffer[512] = {0};
    Sinon j'ai rien à dire sur ton problème

  3. #3
    mweber

    Re : Une fat 32 ultra light pour dataloggeur embarqué. (Projet)

    Salut à tous,

    Sandrecarpe, c'est exact, mais c’était un début de code ... j'ai créé une fonction Clear_SD_buffer qui efface mon buffer[] régulièrement avant tout écritures...

    Voila à présent la fonction format() qui créé la partition nommée LOGGEUR et créé un fichier vide "DONNEES.txt"

    chkdsk ne trouve rien à redire la dessus

    Reste donc a remplir mon fichier et à le relire.

    Au fait, est t'il possible d'éditer mon premier post pour mettre le code à jour au fur et à mesure des progrès ?

    Matt


    Code:
    char Buffer[512];
    
    
    
    void Clear_SD_buffer(void)
    {
    int i;
    for (i = 0; i < 512; i++)  Buffer[i] = 0;               // Créé une image de secteur vierge
    }
    
    
    void format(void)
    {
    unsigned int i = 0;
    
    // Informations sur la partition FAT32 qui va être créée :
    // 2048 octets par clusters
    const unsigned char FS_Information_Sector[] =
                     {0xEB, 0x58 ,0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E,
                      0x30, 0x00, 0x02, 0x04, 0x3E, 0x0D, 0x02, 0x00, 0x00, 0x00,
                      0x00, 0xF8, 0x00, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x00, 0x40, 0x73, 0x00, 0x61, 0x39, 0x00, 0x00,
                      0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00,
                      0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0xE6, 0x1C, 0x0A,
                      0x44, 0x4E, 0x4F, 0x20, 0x4E, 0x41, 0x4D, 0x45, 0x20, 0x20,
                      0x20, 0x20, 0x46, 0x41, 0x54, 0x33, 0x32, 0x20, 0x20, 0x20};
                      
    const unsigned char Directory_table[] =
                     {0x4C, 0x4F, 0x47, 0x47, 0x45, 0x55, 0x52, 0x20, 0x20, 0x20,
                      0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x8F, 0x56, 0xAC, 0x4A, 0x00, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x44, 0x4F, 0x4E, 0x4E, 0x45, 0x45, 0x53, 0x20,
                      0x54, 0x58, 0x54, 0x20, 0x10, 0xBD, 0xF5, 0x71, 0xAC, 0x4A,
                      0xAC, 0x4A, 0x00, 0x00, 0xF6, 0x71, 0xAC, 0x4A};
    
    
    const unsigned char FS_information_sector_signature1[] ={0x52, 0x52, 0x61, 0x41};   // = "RRaA")
    const unsigned char FS_information_sector_signature2[] ={0x72, 0x72, 0x41, 0x61};   // = "rrAa")
    
    const unsigned char File_allocation_table[] = {0xF8, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F};
    const unsigned char Boot_record_signature[] = {0x00, 0x00, 0x55, 0xAA};
    
    
    Clear_SD_buffer();
    
    UART1_Write_Text("\r\n\r\nEffacement carte en cours...");   // Affiche un message
    mmc_Write_Sector(0, Buffer); // Efface le début de la carte (Formatage bas nivau partiel...)
    mmc_Write_Sector(1, Buffer); // Efface le début de la carte (Formatage bas nivau partiel...)
    mmc_Write_Sector(3390, Buffer); // Efface un secteur de la carte (Formatage bas nivau partiel...)
    mmc_Write_Sector(32768, Buffer); // Efface un secteur de la carte (Formatage bas nivau partiel...)
    
    
    UART1_Write_Text("\r\n\r\nDebut formatage..."); // Affiche un message
    
    // Création du secteur 0 : (Appelé Boot sector ou VBR)
    for (i = 0; i < 90; i++) Buffer[i] = FS_Information_Sector[i]; // Copie le FS_Information_Sector: identificateur de la partition
    
    mmc_Write_Sector(0, Buffer);                            // Ecriture du secteur 0
    
    
    // Création du secteur 1 : (Appelé File System Information Sector)
    // (A VOIR => Some FAT32 implementations support a slight variation of Microsoft's specification by making the FS information 
    //  sector optional by specifying a value of 0xFFFF[24] (or 0x0000) in the entry at offset 0x030.)
    Clear_SD_buffer();
    for (i = 0; i < 4; i++)
      {
      Buffer[0x000+i] = FS_information_sector_signature1[i]; // Copie le FS information sector signature 1
      Buffer[0x1E4+i] = FS_information_sector_signature2[i]; // Copie le FS information sector signature 2
      Buffer[0x1E8+i] = 0xFF;                                // Last known number of free data clusters on the volume
      Buffer[0x1EC+i] = 0xFF;                                // Number of the most recently known to be allocated data cluster
      Buffer[0x1FC+i] = Boot_record_signature[i];            // FS information sector signature (Boot Record Signature (55hAAh))
      }
    mmc_Write_Sector(1, Buffer);                             // Ecriture du secteur 1
    
    // Création du secteur 32768 : (Appelé Directory table)
    // Et création du fichier DONNEES.TXT
    Clear_SD_buffer();
    for (i = 0; i < 58; i++) Buffer[i] = Directory_table[i];    // Copie la Directory_table: nom de volume et infos sur le fichier DONNEES.TXT
    mmc_Write_Sector(32768, Buffer);                            // Ecriture du secteur 32768
    
    // Création du secteur 3390 : (Appelé File Allocation Table)
    // Inclus les infos pour la création du fichier DONNEES.TXT
    Clear_SD_buffer();
    for (i = 0; i < 12; i++) Buffer[i] = File_allocation_table[i]; // Copie la File_allocation_table: chaine de clusters
    mmc_Write_Sector(3390, Buffer);                                // Ecriture du secteur 3390
    UART1_Write_Text("\r\n\r\nFini !\r\n"); // Affiche un message
    }
    Dernière modification par mweber ; 15/05/2017 à 13h59.

  4. #4
    mweber

    Re : Une fat 32 ultra light pour dataloggeur embarqué. (Projet)

    Salut à tous,

    J'ai avancé dans mon code, malheureusement cela ne marche pas.

    la fonction format créé la partition LOGGEUR sans MBR et un fichier DONNEES.TXT
    Scandisk sur le PC dit que tout est ok.

    Si en plus j'appelle ma fonction Write_append_SD qui écrit dans le fichier et met à jour la FAT et la FAT de secours:

    => Write_append_SD("Ceci est un test d'écriture dans un fichier texte", 49);

    Sur le PC: impossible de rentrer dans le fichier LOGGEUR.TXT => Illisible, et scandisk me dit:

    La taille de l'entrée \DONNEES.txt est incorrecte.

    En vérifiant avec l'éditeur hexadécimal:

    La structure de la FAT (secteur 3390) est, suite à mon essai sur le PC d'ouvrir le fichier DONNEES.TXT:
    F8 FF FF 0F FF FF FF 7F FF FF FF 0F FF FF FF 0F
    FF FF FF 0F ....

    Alors que ma fonction d'écriture sur le PIC lui programmait:
    F8 FF FF 0F FF FF FF FF FF FF FF 0F FF FF FF 0F
    00 00 00 00 ....

    Je lance un scandisk / f en refusant de convertir les liens perdus en fichiers, et là, la FAT donne:
    F8 FF FF 0F FF FF FF FF FF FF FF 0F 00 00 00 00
    00 00 00 00 ....

    Ensuite, toujours sur le PC, je remplis mon fichier avec la phrase test => Ceci est un test d'écriture dans un fichier texte
    La FAT donne maintenant:
    F8 FF FF 0F FF FF FF FF FF FF FF 0F FF FF FF 0F
    00 00 00 00 ....

    Idem pour la fat de secours (secteur 18079)

    Donc tel que je l'ai programmé.

    la taille du fichier est correcte (49 octets)

    Bizarre ??!!..

    Je vous met le code complet...


    Code:
    char Buffer[512];
    
    ////////////////////////////////////////////////////////////////////////////////
    
    void Clear_SD_buffer(void)
    {
    int i;
    for (i = 0; i < 512; i++)  Buffer[i] = 0;    // Créé une image de secteur vierge
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    void format(void)
    {
    unsigned int i = 0;
    
    // Informations sur la partition FAT32 qui va être créée :
    // 2048 octets par clusters
    const unsigned char FS_Information_Sector[] =
                     {0xEB, 0x58 ,0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E,
                      0x30, 0x00, 0x02, 0x04, 0x3E, 0x0D, 0x02, 0x00, 0x00, 0x00,
                      0x00, 0xF8, 0x00, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x00, 0x40, 0x73, 0x00, 0x61, 0x39, 0x00, 0x00,
                      0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00,
                      0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0xE6, 0x1C, 0x0A,
                      0x44, 0x4E, 0x4F, 0x20, 0x4E, 0x41, 0x4D, 0x45, 0x20, 0x20,
                      0x20, 0x20, 0x46, 0x41, 0x54, 0x33, 0x32, 0x20, 0x20, 0x20};
    
    const unsigned char Directory_table[] =
                     {0x4C, 0x4F, 0x47, 0x47, 0x45, 0x55, 0x52, 0x20, 0x20, 0x20,
                      0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x8F, 0x56, 0xAC, 0x4A, 0x00, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x44, 0x4F, 0x4E, 0x4E, 0x45, 0x45, 0x53, 0x20,
                      0x54, 0x58, 0x54, 0x20, 0x10, 0xBD, 0xF5, 0x71, 0xAC, 0x4A,
                      0xAC, 0x4A, 0x00, 0x00, 0xF6, 0x71, 0xAC, 0x4A};
    
    
    const unsigned char FS_information_sector_signature1[] ={0x52, 0x52, 0x61, 0x41};   // = "RRaA")
    const unsigned char FS_information_sector_signature2[] ={0x72, 0x72, 0x41, 0x61};   // = "rrAa")
    
    const unsigned char File_allocation_table[] = {0xF8, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F};
    // 0 cluster d'occupé  : F8 FF FF 0F FF FF FF FF FF FF FF 0F
    // 1 cluster d'occupé  : F8 FF FF 0F FF FF FF FF FF FF FF 0F   FF FF FF 0F
    // 2 clusters d'occupés: F8 FF FF 0F FF FF FF FF FF FF FF 0F   04 00 00 00 FF FF FF 0F
    // 3 clusters d'occupés: F8 FF FF 0F FF FF FF FF FF FF FF 0F   04 00 00 00 05 00 00 00 FF FF FF 0F
    // 4 clusters d'occupés: F8 FF FF 0F FF FF FF FF FF FF FF 0F   04 00 00 00 05 00 00 00 06 00 00 00 FF FF FF 0F
    // Etc .
    
    const unsigned char Boot_record_signature[] = {0x00, 0x00, 0x55, 0xAA};
    
    
    Clear_SD_buffer();
    
    UART1_Write_Text("\r\n\r\nEffacement carte en cours...");   // Affiche un message
    mmc_Write_Sector(0, Buffer);     // Efface le boot sector de la carte
    mmc_Write_Sector(1, Buffer);     // Efface le File System Information Sector de la carte
    
    for (i = 0; i < 50; i++)
      {
      UART1_Write('.');
      mmc_Write_Sector(32768 + i, Buffer);  // Efface la directory table de la carte
      mmc_Write_Sector(3390  + i, Buffer);  // Efface la FAT de la carte
      mmc_Write_Sector(18079 + i, Buffer);  // Efface la copie de secours de la FAT de la carte
      mmc_Write_Sector(32772 + i, Buffer);  // Efface les données
      }
    
    
    UART1_Write_Text("\r\n\r\nDebut formatage..."); // Affiche un message
    
    // Création du secteur 0 : (Appelé Boot sector ou VBR)
    for (i = 0; i < 90; i++) Buffer[i] = FS_Information_Sector[i]; // Copie le FS_Information_Sector: identificateur de la partition
    
    mmc_Write_Sector(0, Buffer);                            // Ecriture du secteur 0
    
    
    // Création du secteur 1 : (Appelé File System Information Sector)
    // (A VOIR => Some FAT32 implementations support a slight variation of Microsoft's specification by making the FS information
    //  sector optional by specifying a value of 0xFFFF[24] (or 0x0000) in the entry at offset 0x030.)
    Clear_SD_buffer();
    for (i = 0; i < 4; i++)
      {
      Buffer[0x000+i] = FS_information_sector_signature1[i]; // Copie le FS information sector signature 1
      Buffer[0x1E4+i] = FS_information_sector_signature2[i]; // Copie le FS information sector signature 2
      Buffer[0x1E8+i] = 0xFF;                                // Last known number of free data clusters on the volume
      Buffer[0x1EC+i] = 0xFF;                                // Number of the most recently known to be allocated data cluster
      Buffer[0x1FC+i] = Boot_record_signature[i];            // FS information sector signature (Boot Record Signature (55hAAh))
      }
    mmc_Write_Sector(1, Buffer);                             // Ecriture du secteur 1
    
    // Création du secteur 32768 : (Appelé Directory table)
    // Et création du fichier DONNEES.TXT
    Clear_SD_buffer();
    for (i = 0; i < 58; i++) Buffer[i] = Directory_table[i];    // Copie la Directory_table: nom de volume et infos sur le fichier DONNEES.TXT
    mmc_Write_Sector(32768, Buffer);                            // Ecriture du secteur 32768
    
    // Création du secteur 3390 et 18079: (Appelé File Allocation Table et sa copie de secours)
    // Inclus les infos pour la création du fichier DONNEES.TXT
    Clear_SD_buffer();
    
    // Copie la File_allocation_table: chaine de clusters
    for (i = 0; i < 16; i++) Buffer[i] = File_allocation_table[i];
    mmc_Write_Sector(3390,  Buffer); // Ecriture de la FAT au secteur 3390
    mmc_Write_Sector(18079, Buffer); // Ecriture de la copie de secours de la FAT au secteur 18079
    
    UART1_Write_Text("\r\n\r\nFini !\r\n"); // Affiche un message
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    // Modifie la taille du fichier _file_size est exprimé en octets
    void Set_file_size(unsigned long _file_size)
    {
    mmc_Read_Sector(32768, Buffer);  // Lecture de la Directory table pour avoir des infos sur le fichier DONNEES.TXT
    Buffer[0x3C] =  _file_size        & 0xFF;
    Buffer[0x3D] = (_file_size >> 8 ) & 0xFF;
    Buffer[0x3E] = (_file_size >> 16) & 0xFF;
    Buffer[0x3F] = (_file_size >> 24) & 0xFF;
    mmc_Write_Sector(32768, Buffer); // Met à jour la Directory table avec la nouvelle taille de fichier
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    // Retourne la taille du fichier si il existe, zéro sinon ou si il est vide
    // valeur exprimée en octets
    unsigned long Get_file_size(void)
    {
    mmc_Read_Sector(32768, Buffer); // Lecture de la Directory table pour avoir des infos sur le fichier DONNEES.TXT
    if ((Buffer[0x20] == 'D')  &&
        (Buffer[0x21] == 'O')  &&
        (Buffer[0x22] == 'N')  &&
        (Buffer[0x23] == 'N')  &&
        (Buffer[0x24] == 'E')  &&
        (Buffer[0x25] == 'E')  &&
        (Buffer[0x26] == 'S')  &&
        (Buffer[0x28] == 'T')  &&
        (Buffer[0x29] == 'X')  &&
        (Buffer[0x2A] == 'T'))
    return (Buffer[0x3C] + (Buffer[0x3D] << 8) + (Buffer[0x3E] << 16) + (Buffer[0x3F] << 24));
    
    else return 0;  // Fichier inexsistant ou vide !
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    // Créé et / ou ajoute à la fin du fichier DONNEES.TXT de nouvelles données
    void Write_append_SD(unsigned char* _txt, unsigned int _size)
    {
    unsigned long taille_fichier       = 0;
    unsigned long secteur_courant      = 0;
    unsigned long secteur_courant_fat  = 0;
    unsigned long cluster_courant      = 0;
    unsigned int  pos_dans_secteur     = 0;
    unsigned int  pos_dans_secteur_fat = 0;
    unsigned int i;
    
    taille_fichier = Get_file_size();   // Récupère la taille du fichier
    
    secteur_courant  = 32772 + (taille_fichier / 512); // recherche le secteur courant
    pos_dans_secteur = taille_fichier % 512;           // trouve la position exacte où écrire des nouvelles données
    
    mmc_Read_Sector(secteur_courant, Buffer); // Récupère les dernières données écrites dans le fichier (c.a.d. celles du secteur courant)
    
    for (i = 0; i <= _size; i++)  
      {
      taille_fichier++;         // Met à jour la taille du fichier
    
      if (pos_dans_secteur >= 512)  // On arrive en fin de secteur ?
        {
        mmc_Write_Sector(secteur_courant, Buffer);     // Ecrit les données dans le secteur
        pos_dans_secteur = 0;                          // On va passer au secteur suivant...
        secteur_courant++;                             // On va passer au secteur suivant...
        
        
        cluster_courant = 3 + (taille_fichier / 2048); // Quel est le numéro du dernier cluster occupé par le fichier ? (2048 octets / cluster)
        secteur_courant_fat = 3390 + (cluster_courant / 128); // Numéro du secteur de la FAT où est indiqué le dernier cluster utilisé par le fichier
        mmc_Read_Sector(secteur_courant_fat, Buffer);  // Récupère les données de la FAT (pour la mettre à jour)
        
        pos_dans_secteur_fat = (4 * (cluster_courant % 128)) - 4;
        Buffer[pos_dans_secteur_fat]   =  cluster_courant        & 0xFF; // Mise à jour des données de la FAT
        Buffer[pos_dans_secteur_fat++] = (cluster_courant >> 8 ) & 0xFF;
        Buffer[pos_dans_secteur_fat++] = (cluster_courant >> 16) & 0xFF;
        Buffer[pos_dans_secteur_fat++] = (cluster_courant >> 24) & 0xFF;
    
        if (pos_dans_secteur_fat > 508)   //   attention en cas d'écriture au dela du secteur de la fat
          {    
          mmc_Write_Sector(secteur_courant_fat, Buffer); // Ecriture dans la FAT
          mmc_Write_Sector(secteur_courant_fat - 3390 + 18079, Buffer); // Ecriture dans la FAT de secours
          mmc_Read_Sector(secteur_courant_fat, Buffer);  // Récupère les données de la FAT (pour la mettre à jour)
          secteur_courant_fat++;                         // On va passer au secteur suivant contenant la suite de la FAT...
          }
          
        Buffer[pos_dans_secteur_fat++] = 0xFF;
        Buffer[pos_dans_secteur_fat++] = 0xFF;
        Buffer[pos_dans_secteur_fat++] = 0xFF;
        Buffer[pos_dans_secteur_fat++] = 0x0F;
    
        mmc_Write_Sector(secteur_courant_fat, Buffer); // Ecriture dans la FAT
        mmc_Write_Sector(secteur_courant_fat - 3390 + 18079, Buffer); // Ecriture dans la FAT de secours
    
        mmc_Read_Sector(secteur_courant, Buffer);      // Récupère les données du secteur de données suivant
        }
    
      UART1_Write('[');
      UART1_Write_Text(itoa(pos_dans_secteur, 0));
      UART1_Write(']');
      Buffer[pos_dans_secteur] = _txt[i];  // Se prépare à écrire des données
      pos_dans_secteur++;
      }
    
    mmc_Write_Sector(secteur_courant, Buffer);  // Ecrit les dernières données avant de quitter la fonction
    
    Set_file_size(taille_fichier-1);  // Met à jour la taille du fichier
                                    
    // 0 cluster d'occupé  : F8 FF FF 0F FF FF FF FF FF FF FF 0F
    // 1 cluster d'occupé  : F8 FF FF 0F FF FF FF FF FF FF FF 0F   FF FF FF 0F
    // 2 clusters d'occupés: F8 FF FF 0F FF FF FF FF FF FF FF 0F   04 00 00 00 FF FF FF 0F
    // 3 clusters d'occupés: F8 FF FF 0F FF FF FF FF FF FF FF 0F   04 00 00 00 05 00 00 00 FF FF FF 0F
    // 4 clusters d'occupés: F8 FF FF 0F FF FF FF FF FF FF FF 0F   04 00 00 00 05 00 00 00 06 00 00 00 FF FF FF 0F
    // Etc .
    
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    void Read_SD(unsigned long relative_sector)
    {
    mmc_Read_Sector(32772 + relative_sector, Buffer);
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////
    
    
    void main (void)
    {
    short res = 1;
    int idx;
    
    
    PORTA = 0;
    PORTB = 0;
    PORTC = 0;
    
    
    PCFG3_bit = 0;
    PCFG2_bit = 1;
    PCFG1_bit = 1;      // Configure AN0 à AN8 en entrées analogiques
    PCFG0_bit = 0;
    
    
    UART1_Init(115200);                 // 19200: Compatible avec le module BlueTooth
    
    // affiche infos
    UART1_Write_Text("\r\nSoft, version : ");
    UART1_Write_Text(__DATE__);
    
    UART1_Write_Text("\r\nAttend carte SD");
    
    asm CLRWDT
    
    idx = 0;
    while (res != 0)
      {
      asm CLRWDT
      SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH); // SPI initialisé a vitesse réduite
      res = MMC_Init();  // Tente de réinitialiser la carte SD
      Delay_1sec();
      UART1_Write_Text(".");
      if (idx++ > 4) break;
      }
    
    SPI1_Init();  // SPI réinitialisé à vitesse MAX
    
    idx = 0;
    
    format();
    
    
    UART1_Write_Text("\r\nTaille du fichier: ");
    UART1_Write_Text(itoa(Get_file_size(), 0));
    UART1_Write_Text("\r\n");
    
    Clear_SD_buffer();
    
    Write_append_SD("Ceci est un test d'écriture dans un fichier texte", 49);
    
    Clear_SD_buffer();
    
    Read_SD(0);
    
    UART1_Write_Text(Buffer);
    
    UART1_Write_Text("\r\nNouvelle taille du fichier: ");
    UART1_Write_Text(itoa(Get_file_size(), 0));
    UART1_Write_Text("\r\n");
    
    
    }
    Dernière modification par mweber ; 30/05/2017 à 15h57.

  5. A voir en vidéo sur Futura
  6. #5
    mweber

    Re : Une fat 32 ultra light pour dataloggeur embarqué. (Projet)

    Bon bein ça marche maintenant !

    J'avais oublié de rentrer le numéro du 1er cluster dans la Directory_table...

    =>

    1) Il faut ajouter 0x03 dans le tableau

    Code:
    const unsigned char Directory_table[] =
                     {0x4C, 0x4F, 0x47, 0x47, 0x45, 0x55, 0x52, 0x20, 0x20, 0x20,
                      0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x8F, 0x56, 0xAC, 0x4A, 0x00, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x44, 0x4F, 0x4E, 0x4E, 0x45, 0x45, 0x53, 0x20,
                      0x54, 0x58, 0x54, 0x20, 0x10, 0xBD, 0xF5, 0x71, 0xAC, 0x4A,
                      0xAC, 0x4A, 0x00, 0x00, 0xF6, 0x71, 0xAC, 0x4A, 0x03};
    2) Remplacer le 58 par 59 dans la boucle for:

    Code:
    for (i = 0; i < 59; i++)  Buffer[i] = Directory_table[i];    // Copie la Directory_table: nom de volume et infos sur le fichier DONNEES.TXT
    Je n'ai pas encore testé la fonction d'écriture sur plusieurs clusters ni vu si la FAT s'écrit correctement sur plusieurs secteurs (cas de gros fichiers) mais c'est l'étape suivante !

    La fonction lecture ne gère pas la fin de fichier, à vous de voir cela en fonction de la taille du fichier donné par la fonction Get_file_size()

    Le code peut surement être amélioré et optimisé ! N’hésitez pas !

    Ce code certes basique prends au moins 2 à 3 fois moins de place que la routine fat 32 (plus élaborée) du compilateur MikroC à fonctions appelées équivalentes. Encore une fois le but c'est de faire une gestion de FAT minimaliste!

    Bonne soirée

    Matthieu
    Dernière modification par mweber ; 30/05/2017 à 16h11.

  7. #6
    Jack
    Modérateur

    Re : Une fat 32 ultra light pour dataloggeur embarqué. (Projet)

    Désolé de ne pas avoir pu t'aider. Merci pour ton retour d'informations en tout cas.

  8. #7
    sandrecarpe

    Re : Une fat 32 ultra light pour dataloggeur embarqué. (Projet)

    Le code peut surement être amélioré et optimisé ! N’hésitez pas !
    Bon bah je retente ma chance

    Code:
    void Clear_SD_buffer(void)
    {
    int i;
    for (i = 0; i < 512; i++)  Buffer[i] = 0;    // Créé une image de secteur vierge
    }
    Effacer ton buffer de cette manière met 1700ns sur ma machine

    Alors qu'un simple :
    Code:
    memset(&buffer, 0, 512);
    met 500ns

    Plus court, plus efficace (et bien sûr fait la même chose)

  9. #8
    mweber

    Re : Une fat 32 ultra light pour dataloggeur embarqué. (Projet)

    Hello,

    Plus court, plus efficace (et bien sûr fait la même chose)
    Bonne idée !

    Si je remplace, dans Clear_SD_buffer:

    int i;
    for (i = 0; i < 512; i++) Buffer[i] = 0;

    par memset(&buffer, 0, 512); Mon code prend 32 octets de plus. C'est tout à fait acceptable Merci !

    Bizarrement en remplaçant tout les appels de Clear_SD_buffer par memset(&buffer, 0, 512); je me prends au moins 150 octets de plus..

    va comprendre !! Mais bon Mikroc m'a déjà fait ce coup là: parfois un ajout de code diminue la taille du code final, sans doute dus aux optimisations du compilo...

    L’écriture du secteur 1 est optionnel tel l'indique le commentaire (trouvé sur le net: https://en.wikipedia.org/wiki/Design...002_INTER61-30)
    => Some FAT32 implementations support a slight variation of Microsoft's specification by making the FS information
    // sector optional by specifying a value of 0xFFFF[24] (or 0x0000) in the entry at offset 0x030.)

    Vous pouvez donc virer tout ce qui attrait au secteur 1... Et hop! 276 octets de moins !

    A+

    Matt
    Dernière modification par mweber ; 31/05/2017 à 10h52.

  10. #9
    mweber

    Re : Une fat 32 ultra light pour dataloggeur embarqué. (Projet)

    Attention pour le moment ce code bugge, je vais tacher de vous proposer une soluce qui marche d'ici peu !

    Matthieu

  11. #10
    mweber

    Re : Une fat 32 ultra light pour dataloggeur embarqué. (Projet)

    Hello,

    Voila la forme définitive du code que j'ai baptisé "Femto fat" permettant d'écrire dans un fichier DONNES.TXT, et de le relire soit sur votre montage à micro contrôleur, soit sur le PC / MAC / Tablette ou autre système capable de lire la FAT32.

    Vous pouvez utiliser des cartes SD de 4 à 32 Go (et plus, selon votre librairie d'accès aux primitives d'écriture de secteurs sur carte SD) mais seuls les 3,5 premiers Go seront utilisés. (C'est déjà pas mal !)

    Vous pouvez donc écrire jusqu'à 3,5 Go de données :

    3 850 629 120 octets d'espace disque total.
    2 048 octets dans chaque unité d'allocation.
    1 880 190 unités d'allocation au total sur le disque.


    Les fonctions :


    void format(void) : Efface la carte, créé la partition et créé le fichier (vide) DONNEES.TXT

    unsigned long Get_file_size(void) : Renvoie 0 si le fichier DONNEES.TXT n'existe pas ou est vide => Dans ce cas vous devriez appeler format(), car il est possible qu'une nouvelle carte SD aie été insérée dans l'appareil.
    Si le fichier existe, la fonction renvoie sa taille en octets.

    void Write_append_SD(unsigned char* _txt, unsigned int _size) : Une sorte de fopen("a"...) + fwrite(...) : Ajoute les données passées en argument en fin de fichier. Il faut indiquer la taille des données à écrire (de 1 à autant que la RAM vous le permette!) . On peut également écrire des caractères nul....

    void Read_SD(unsigned long relative_sector) : Lecture du fichier DONNEES.TXT (lis un secteur complet du fichier. Il faut éventuellement se référer à la taille du fichier (appeler Get_file_size()) pour savoir si on est arrivé à la fin de celui-ci !


    Clear_SD_buffer() : Fonction interne: Ne pas utiliser

    Set_file_size():
    Fonction interne: Ne pas utiliser



    Le code (testé avec des écritures variées de données):


    Code:
    // infos :
    // https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#BPB
    
    // Constantes
    //-------------
    #define AUTHOR  "\n\r(c) http://Matthieu.Weber.free.fr - "
    
    #define __DEBUG
    
    #define CLUSTER_SIZE 2048  // Taille d'un cluster en octets = Taille de l'unité d'allocation
    #define SECTOR_SIZE   512   // Taille d'un secteur en octets (512 en général)
    
    
    unsigned char Buffer[SECTOR_SIZE];
    
    ////////////////////////////////////////////////////////////////////////////////
    
    void Clear_SD_buffer(void)
    {
    memset(&buffer, 0, SECTOR_SIZE);
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    void format(void)
    {
    unsigned int i = 0;
    
    // Informations sur la partition FAT32 qui va être créé :
    // CLUSTER_SIZE octets par clusters
    const unsigned char FS_Information_Sector[] =
                     {0xEB, 0x58 ,0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E,
                      0x30, 0x00, 0x02, CLUSTER_SIZE/SECTOR_SIZE , 0x3E, 0x0D, 0x02, 0x00, 0x00, 0x00,
                      0x00, 0xF8, 0x00, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x00, 0x40, 0x73, 0x00, 0x61, 0x39, 0x00, 0x00,
                      0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00,
                      0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0xE6, 0x1C, 0x0A,
                      0x44, 0x4E, 0x4F, 0x20, 0x4E, 0x41, 0x4D, 0x45, 0x20, 0x20,
                      0x20, 0x20, 0x46, 0x41, 0x54, 0x33, 0x32, 0x20, 0x20, 0x20};
    
    const unsigned char Directory_table[] =
                     {0x4C, 0x4F, 0x47, 0x47, 0x45, 0x55, 0x52, 0x20, 0x20, 0x20,
                      0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x8F, 0x56, 0xAC, 0x4A, 0x00, 0x00, 0x00, 0x00,
                      0x00, 0x00, 0x44, 0x4F, 0x4E, 0x4E, 0x45, 0x45, 0x53, 0x20,
                      0x54, 0x58, 0x54, 0x20, 0x10, 0xBD, 0xF5, 0x71, 0xAC, 0x4A,
                      0xAC, 0x4A, 0x00, 0x00, 0xF6, 0x71, 0xAC, 0x4A, 0x03};
    
    const unsigned char File_allocation_table[] = {0xF8, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F};
    // 0 cluster d'occupé  : F8 FF FF 0F FF FF FF FF FF FF FF 0F
    // 1 cluster d'occupé  : F8 FF FF 0F FF FF FF FF FF FF FF 0F   FF FF FF 0F
    // 2 clusters d'occupés: F8 FF FF 0F FF FF FF FF FF FF FF 0F   04 00 00 00 FF FF FF 0F
    // 3 clusters d'occupés: F8 FF FF 0F FF FF FF FF FF FF FF 0F   04 00 00 00 05 00 00 00 FF FF FF 0F
    // 4 clusters d'occupés: F8 FF FF 0F FF FF FF FF FF FF FF 0F   04 00 00 00 05 00 00 00 06 00 00 00 FF FF FF 0F
    // Etc .
    
    
    Clear_SD_buffer();
    #ifdef __DEBUG
    UART1_Write_Text("\r\n\r\nEffacement carte en cours...");   // Affiche un message
    #endif
    
    for (i = 0; i < 64; i++)
      {
      #ifdef __DEBUG
      UART1_Write('.');
      #endif
      mmc_Write_Sector(0     + i, Buffer);  // Efface le boot sector de la carte, le File System Information Sector + divers reliquats...
      mmc_Write_Sector(32768 + i, Buffer);  // Efface la directory table
      mmc_Write_Sector(3390  + i, Buffer);  // Efface la FAT (en partie...)
      mmc_Write_Sector(18079 + i, Buffer);  // Efface la copie de secours de la FAT (en partie...)
      }
    
    #ifdef __DEBUG
    UART1_Write_Text("\r\n\r\nDebut formatage..."); // Affiche un message
    #endif
     
    // Création du secteur 0 : (Appelé Boot sector ou VBR)
    for (i = 0; i < 90; i++) Buffer[i] = FS_Information_Sector[i]; // Copie le FS_Information_Sector: identificateur de la partition
    Buffer[0x1FE] = 0x55; // Copie le Boot Record signature: identificateur du premier secteur de la partition
    Buffer[0x1FF] = 0xAA; // Copie le Boot Record signature: identificateur du premier secteur de la partition
    
    mmc_Write_Sector(0, Buffer);                            // Ecriture du secteur 0
    
    
    // Secteur 1 : (Appelé File System Information Sector) Inutile ici car il suffit de laisser la valeur 0x0000 à offset 0x030 du secteur 1
    // (=> Some FAT32 implementations support a slight variation of Microsoft's specification by making the FS information
    //  sector optional by specifying a value of 0xFFFF[24] (or 0x0000) in the entry at offset 0x030.)
    
    // Création du secteur 32768 : (Appelé Directory table)
    // Et création du fichier DONNEES.TXT
    Clear_SD_buffer();
    for (i = 0; i < 59; i++) Buffer[i] = Directory_table[i];    // Copie la Directory_table: nom de volume et infos sur le fichier DONNEES.TXT
    mmc_Write_Sector(32768, Buffer);                            // Ecriture du secteur 32768
    
    // Création du secteur 3390 et 18079: (Appelé File Allocation Table et sa copie de secours)
    // Inclus les infos pour la création du fichier DONNEES.TXT
    Clear_SD_buffer();
    
    // Copie la File_allocation_table: chaine de clusters
    for (i = 0; i < 16; i++) Buffer[i] = File_allocation_table[i];
    mmc_Write_Sector(3390,  Buffer); // Ecriture de la FAT au secteur 3390
    mmc_Write_Sector(18079, Buffer); // Ecriture de la copie de secours de la FAT au secteur 18079
    
    #ifdef __DEBUG
    UART1_Write_Text("\r\n\r\nFormatage fini !\r\n"); // Affiche un message
    #endif
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    // Modifie la taille du fichier, l'argument _file_size est exprimé en octets
    void Set_file_size(unsigned long _file_size)
    {
    mmc_Read_Sector(32768, Buffer);  // Lecture de la Directory table pour avoir des infos sur le fichier DONNEES.TXT
    Buffer[0x3C] =  _file_size        & 0xFF;
    Buffer[0x3D] = (_file_size >> 8 ) & 0xFF;
    Buffer[0x3E] = (_file_size >> 16) & 0xFF;
    Buffer[0x3F] = (_file_size >> 24) & 0xFF;
    mmc_Write_Sector(32768, Buffer); // Met à jour la Directory table avec la nouvelle taille de fichier
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    // Retourne la taille du fichier, si il existe, zéro sinon ou si il est vide
    // valeur exprimée en octets
    unsigned long Get_file_size(void)
    {
    mmc_Read_Sector(32768, Buffer); // Lecture de la Directory table pour avoir des infos sur le fichier DONNEES.TXT
    if ((Buffer[0x20] == 'D')  &&
        (Buffer[0x21] == 'O')  &&
        (Buffer[0x22] == 'N')  &&
        (Buffer[0x23] == 'N')  &&
        (Buffer[0x24] == 'E')  &&
        (Buffer[0x25] == 'E')  &&
        (Buffer[0x26] == 'S')  &&
        (Buffer[0x28] == 'T')  &&
        (Buffer[0x29] == 'X')  &&
        (Buffer[0x2A] == 'T'))
    return ((unsigned long)Buffer[0x3C] | ((unsigned long)Buffer[0x3D] << 8) | ((unsigned long)Buffer[0x3E] << 16) | ((unsigned long)Buffer[0x3F] << 24));
    
    else return 0;  // Fichier inexsistant ou vide !
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    // Créé et / ou ajoute à la fin du fichier DONNEES.TXT de nouvelles données
    void Write_append_SD(unsigned char* _txt, unsigned int _size)
    {
    unsigned long taille_fichier       = 0; // Taille du fichier en octets
    unsigned long secteur_courant      = 0; // Numéro du dernier secteur contenant les dernières données écrites dans le fichier DONNEES.TXT
    unsigned long secteur_courant_fat  = 0; // Numéro du dernier secteur de la FAT contenant les numéros des derniers secteurs liés au fichier DONNEES.TXT
    unsigned long cluster_courant      = 0; // Numéro du dernier cluster contenant des données du fichier DONNEES.TXT
    unsigned int  pos_dans_secteur     = 0; // position relative (0 ~ SECTOR_SIZE) dans le secteur courant où écrire de nouvelles données
             int  pos_dans_secteur_fat = 0; // position relative (0 ~ SECTOR_SIZE) dans le secteur FAT courant où écrire de nouveux numéros de clusters
    unsigned int  i;
    unsigned short j;
    
    taille_fichier = Get_file_size();       // Récupère la taille du fichier
    
    secteur_courant     = 32772 + (taille_fichier / SECTOR_SIZE);  // recherche le numéro du dernier secteur contenant les dernières données écrites dans le fichier DONNEES.TXT; appelé "secteur courant"
    cluster_courant     = 3     + (taille_fichier / CLUSTER_SIZE); // Quel est le numéro du dernier cluster occupé par le fichier ? (CLUSTER_SIZE octets = 1 cluster)
    secteur_courant_fat = 3390  + (cluster_courant / 128);         // Numéro du secteur de la FAT où est indiqué le dernier cluster utilisé par le fichier
    pos_dans_secteur    = taille_fichier % SECTOR_SIZE;            // trouve la position exacte dans secteur courant où écrire de nouvelles données
    
    mmc_Read_Sector(secteur_courant, Buffer); // Récupère les dernières données écrites dans le fichier (c.a.d. celles du secteur courant)
    
    for (i = 0; i <= _size; i++)
      {
      // Pour chaque octet à écrire...
      if (pos_dans_secteur >= SECTOR_SIZE)
        {
        // On arrive à la fin du secteur courant
        mmc_Write_Sector(secteur_courant, Buffer);     // Ecrit les données dans le secteur
        secteur_courant++;                             // On va passer au secteur suivant...
        pos_dans_secteur = 0;                          // Remet l'index de position reative dans le secteur courant, à zéro
    
        if ((taille_fichier % CLUSTER_SIZE) == 0)
          // On arrive à la fin du cluster courant
          {
          mmc_Read_Sector(secteur_courant_fat, Buffer);         // Récupère les données de la FAT (pour la mettre à jour)
    
          pos_dans_secteur_fat = (4 * (cluster_courant % 128));
    
          cluster_courant++;
    
          #ifdef __DEBUG
          UART1_Write_Text("\r\nTaille: ");
          UART1_Write_Text(itoa(taille_fichier, 0));
          UART1_Write_Text("\tSect: ");
          UART1_Write_Text(itoa(secteur_courant, 0));
          
          UART1_Write_Text("\tCl: ");
          UART1_Write_Text(itoa(cluster_courant, 0));
    
          UART1_Write_Text("\tS FAT: ");
          UART1_Write_Text(itoa(secteur_courant_fat, 0));
    
          UART1_Write_Text("\tP FAT: ");
          UART1_Write_Text(itoa(pos_dans_secteur_fat, 0));
          #endif
          
          Buffer[pos_dans_secteur_fat++] =  cluster_courant        & 0xFF; // Mise à jour des données de la FAT
          Buffer[pos_dans_secteur_fat++] = (cluster_courant >> 8 ) & 0xFF;
          Buffer[pos_dans_secteur_fat++] = (cluster_courant >> 16) & 0xFF;
          Buffer[pos_dans_secteur_fat++] = (cluster_courant >> 24) & 0xFF;
    
          if (pos_dans_secteur_fat >= SECTOR_SIZE)   //   Attention en cas d'arrrivée en fin du secteur courant de la fat (normalement on a 128 clusters / secteurs), il faut passer au suivant...
            {
            #ifdef __DEBUG
            UART1_Write_Text("\t>>> P FAT: ");
            UART1_Write_Text(itoa(pos_dans_secteur_fat, 0));
            UART1_Write_Text("\r\n<<< PASSAGE SECTEUR FAT SUIVANT >>>\r\n");
            #endif
            
            mmc_Write_Sector(secteur_courant_fat, Buffer); // Ecriture dans la FAT
            mmc_Write_Sector(secteur_courant_fat - 3390 + 18079, Buffer); // Ecriture dans la FAT de secours
            secteur_courant_fat++;                         // On va passer au secteur suivant contenant la suite de la FAT...
            pos_dans_secteur_fat = 0;
            mmc_Read_Sector(secteur_courant_fat, Buffer);  // Récupère les données de la FAT (pour la mettre à jour)
            }
    
          for (j = 0; j < 3; j++) Buffer[pos_dans_secteur_fat++] = 0xFF;   // Marqueur de dernier cluster du fichier
          Buffer[pos_dans_secteur_fat++] = 0x0F;                           // Marqueur de dernier cluster du fichier
    
          mmc_Write_Sector(secteur_courant_fat, Buffer); // Ecriture dans la FAT
          mmc_Write_Sector(secteur_courant_fat - 3390 + 18079, Buffer); // Ecriture dans la FAT de secours
          }
    
        mmc_Read_Sector(secteur_courant, Buffer);      // Récupère les données du secteur de données suivant
        }
    
      Buffer[pos_dans_secteur] = _txt[i];  // Se prépare à écrire des données
      pos_dans_secteur++;                  // On va écrire une donné plus loin...
      taille_fichier++;                    // Met à jour la taille du fichier
      }
    
    
    mmc_Write_Sector(secteur_courant, Buffer);  // Ecrit les dernières données avant de quitter la fonction
    
    Set_file_size(taille_fichier-1);       // Met à jour la taille du fichier
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    // Lecture du fichier DONNEES.TXT (lis un secteur complet du fichier
    // Il faut éventuellement se référer à la taille du fichier (Get_file_size())
    // pour savoir si on est arrivé à la fin de celui-ci !
    void Read_SD(unsigned long relative_sector)
    {
    mmc_Read_Sector(32772 + relative_sector, Buffer);
    }
    Dernière modification par mweber ; 14/06/2017 à 16h02.

  12. #11
    mweber

    Re : Une fat 32 ultra light pour dataloggeur embarqué. (Projet)

    Et un court exemple (simplifié!!) d'utilisation :

    Code:
    format();
    
    
    UART1_Write_Text("\r\nTaille du fichier: ");
    UART1_Write_Text(itoa(Get_file_size(), 0));
    UART1_Write_Text("\r\n");
    
    for (j = 0; j < 10000; j++)  Write_append_SD("On effectue le même raisonnement pour la capacité des supports statiques de stockage, en considérant que chaque position de la longueur (ou respectivement de la surface ou du volume) de ce support définit un certain nombre de signaux ayant chacun une qualité exprimée en bits, octets ou décibels, la nature de ces signaux détectables dépendant des capteurs employés (conversion de signaux électriques en signaux magnétiques, optique…), de leur qualité (c'est-à-dire leur précision intrinsèque), et du bruit...", 509);
    
    UART1_Write_Text("\r\nNouvelle taille du fichier: ");
    UART1_Write_Text(itoa(Get_file_size(), 0));
    UART1_Write_Text("\r\n");
    UART1_Write_Text("\r\n");
    
    Read_SD(0);  // Lis les 512 permiers octets du fichier DONNEES.TXT
    
    for (i = 0; i < SECTOR_SIZE; i++) UART1_Write(Buffer[i]);  // Affiche les donnée sur le port série
    
    UART1_Write_Text("\r\n");
    Note:

    Si vous changez la taille des clusters à 4096 octets par ex au lieu de 2048, ça marche, le fichier est lisible, mais chkdsk signale des erreurs (je en sais pas ou !)
    Et puis ca ne changera pas la face du monte quant à la taille des donnée inscriptibles.

    Amusez vous bien

    Matthieu

Discussions similaires

  1. projet en langage C / embarqué , telecoms .
    Par Linuxman99 dans le forum Programmation et langages, Algorithmique
    Réponses: 28
    Dernier message: 28/03/2017, 08h46
  2. Projet kart / capteur embarqué/ Bus CAN
    Par Phenax59 dans le forum Électronique
    Réponses: 0
    Dernier message: 31/03/2015, 10h29
  3. projet wattmetre+arduino en système embarqué
    Par choupiine dans le forum Électronique
    Réponses: 2
    Dernier message: 25/03/2015, 07h47
  4. [Blanc] help! café ultra light imbuvable MOULINEX DIRECT SERVE ! !
    Par inviteaa6d9321 dans le forum Dépannage
    Réponses: 3
    Dernier message: 13/10/2009, 15h34