Dans la continuité de mon post sur le parcours récursif de la carte SD , je souhaite maintenant stocker l'arbre dans la mémoire flash.
je stocke la variable rootItem, elle a une taille de 68, j'arrive a lire la mémoire flash et stocker ça dans une variable rootItem2, qui a également une taille de 68 .... et ça plante.
void setup() {
pinMode(pushButton_pin, INPUT);
setCpuFrequencyMhz(160);
tft.init();
tft.setRotation(3);
tft.fillScreen(TFT_BLACK);
tft.setTextWrap(false);
// Set microSD Card CS as OUTPUT and set HIGH
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);
// Initialize SPI bus for microSD Card
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
// Start Serial Port
Serial.begin(115200);
delay(500);
// Start microSD Card
if(!SD.begin(SD_CS))
{
Serial.println("Error accessing microSD card!");
while(true);
}
Serial.println("initialization done.");
Serial.println("Creating structure of files");
File root = SD.open("/");
FileItem rootItem;
if (strlen(root.name()) != 0) strncpy(rootItem.name, root.name(), maxFileNameSize);
else strncpy(rootItem.name, "/", maxFileNameSize);
rootItem.name[maxFileNameSize] = '\0';
rootItem.isDir = true;
Serial.println("--start of Listing--");
readSdCard(root, rootItem);
//Fin du listing
if (!EEPROM.begin(EEPROM_SIZE))
{
Serial.println("failed to initialise EEPROM"); delay(1000000);
}
Serial.print("Size of rootItem : ");
Serial.println(sizeof(rootItem));
EEPROM.put(0,rootItem);
EEPROM.commit();
FileItem rootItem2;
EEPROM.get(0,rootItem2);
Serial.print("Size of rootItem2 : ");
Serial.println(sizeof(rootItem2));
}
voici ce que j'ai dans le moniteur série :
----end of listing ----
Size of rootItem : 68
Size of rootItem2 : 68
CORRUPT HEAP: Bad tail at 0x3ffb3e64. Expected 0xbaad5678 got 0x3ffb2c14
voici le code complet, mais pour moi l'erreur vient bien de la ligne avec le EEPROM.get, car quand je la passe en commentaire, tout va bien.
En continuant mes recherches, le CORRUPT HEAP: vient d'une mauvaise allocation de la mémoire.
Je suis en train de voir sur la doc espressif mais pour le moment, je ne comprends pas tout
#define pushButton_pin 32
// Include required libraries
#include "Audio.h"
#include "SD.h"
#include "FS.h"
#include <Wire.h>
#include <TFT_eSPI.h>
#include <SPI.h>
#include "EEPROM.h"
#define EEPROM_SIZE 128
// microSD Card Reader connections
#define SD_CS 5
#define SPI_MOSI 21
#define SPI_MISO 19
#define SPI_SCK 18
// I2S Connections
#define I2S_DOUT 22
#define I2S_BCLK 26
#define I2S_LRC 25
// Create Audio object
Audio audio;
TFT_eSPI tft = TFT_eSPI();
//digitalWrite(TFT_BL, 1);
int maxIndex;
uint32_t Freq = 0;
int Val;
String Btn,SongName;
String Status="Idle";
bool state=true;
bool Current_State=state;
int Current_Millis;
int Previous_Millis;
int Debounce=175;
int Xindex=0;
int Yindex=0;
const uint8_t maxFileNameSize = 50;
struct FileItem {
bool isDir;
char name[maxFileNameSize+1];
FileItem* upDir;
std::vector<FileItem> elements;
};
File dir;
String CurrDir;
String NextDir;
String Song;
String Liste[50];
void setup() {
pinMode(pushButton_pin, INPUT);
setCpuFrequencyMhz(160);
tft.init();
tft.setRotation(3);
tft.fillScreen(TFT_BLACK);
tft.setTextWrap(false);
// Set microSD Card CS as OUTPUT and set HIGH
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);
// Initialize SPI bus for microSD Card
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
// Start Serial Port
Serial.begin(115200);
delay(500);
// Start microSD Card
if(!SD.begin(SD_CS))
{
Serial.println("Error accessing microSD card!");
while(true);
}
Serial.println("initialization done.");
Serial.println("Creating structure of files");
File root = SD.open("/");
FileItem rootItem;
if (strlen(root.name()) != 0) strncpy(rootItem.name, root.name(), maxFileNameSize);
else strncpy(rootItem.name, "/", maxFileNameSize);
rootItem.name[maxFileNameSize] = '\0';
rootItem.isDir = true;
Serial.println("--start of Listing--");
readSdCard(root, rootItem);
//Fin du listing
Serial.println ("----end of listing ----");
if (!EEPROM.begin(EEPROM_SIZE))
{
Serial.println("failed to initialise EEPROM"); delay(1000000);
}
Serial.print("Size of rootItem : ");
Serial.println(sizeof(rootItem));
EEPROM.put(0,rootItem);
EEPROM.commit();
FileItem rootItem2;
EEPROM.get(0,rootItem2);
Serial.print("Size of rootItem2 : ");
Serial.println(sizeof(rootItem2));
Serial.println(rootItem2.elements[0].elements.at(1).elements[1].name);
}
void readSdCard(File dir, FileItem& parentItem) {
while (true) {
File entry = dir.openNextFile();
if (!entry) {
break; // no more files
}
FileItem item;
item.isDir = entry.isDirectory();
strncpy(item.name, entry.name(), maxFileNameSize); // https://cplusplus.com/reference/cstring/strncpy/
item.name[maxFileNameSize] = '\0';
//parentItem.elements.push_back(item);
Serial.printf("Add %s to %s\n", item.name, parentItem.name);
if (entry.isDirectory()) {
readSdCard(entry, item);
}
parentItem.elements.push_back(item);
}
}
void displaySdCardContent(FileItem& item, int numTabs) {
for (int i = 0; i < numTabs; i++) {Serial.print("...");}
if (item.isDir) {
Serial.print ("name : ");
Serial.println(item.name);
Serial.print ("IsDir : ");
Serial.println(item.isDir);
Serial.print("size :");
Serial.println(item.elements.size());
for (FileItem& fileElement : item.elements) {
displaySdCardContent(fileElement, numTabs + 1);
}
} else {
Serial.println(item.name);
}
}
void loop()
{
Current_Millis=millis();
audio.loop();
if (Current_Millis - Previous_Millis>Debounce )
{
Get_Button(analogRead(pushButton_pin));
Previous_Millis=millis();
if (Current_State!=state )
{
Serial.println(Btn);
Current_State= state;
}
}
}
void audio_id3data(const char *info){ //id3 metadata
//Serial.print("id3data ");Serial.println(info);
String word3 = getValue(info,': ',0);
//Serial.println(word3);
if(word3=="Title:")
{
String bla =String(info);
String titre = bla.substring(6,maxIndex+1);
Serial.println(titre);
tft.setCursor(-10, 0, 2);
tft.setTextSize(1.9);
//tft.println(titre);
}
}
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = {0, -1};
maxIndex = data.length()-1;
for(int i=0; i<=maxIndex && found<=index; i++){
if(data.charAt(i)==separator || i==maxIndex){
found++;
strIndex[0] = strIndex[1]+1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
Toutes les navigations dans l'arbre que j'ai testé pour le moment, n'ont pas posées de problème (quand l'élement existe) quand je viens de faire le listing en début de code.
Mais quand j'essaye de récupérer ça depuis la mémoire flash, sans meme chercher a naviguer dans l'abre ... l'ESP de met en Corrupt heap
votre type FileItem n'est pas sérialisable par EEPROM.put. D'une part vous avez un pointeur (upDir) qui est une adresse absolue et donc ne voudra rien dire à la relecture et d'autre part votre type n'est pas trivial et put ne saura pas gérer cette récursivité.
si vous voulez mettre cela en flash, il faut pouvoir sérialiser et deserialiser les données
ok, mais il faut que ce contenu soit "lisible". Si j'ai bien compris ce que j'ai lu pour le moment de la sérialisation/déserialisation, il faut que je découpe ma variable rootItem en élément qui plus simple (typiquement qui peuvent s'ecrire dans le moniteur série) et que je fasse le processus inverse quand je veux récupérer les données.
ça ce n'est pas obligé, ça peut être du binaire, mais ça doit être "flat" et indépendant de la mémoire ➜ donc vous ne pouvez pas stocker un pointeur et vous ne pouvez pas stocker un objet complexe comme un vecteur d'instances d'un truc compliqué...
➜ vous pourriez ranger les données dans un tableau et garder des index relatifs au lieu de pointeurs
le parcours initial ferait l'insertion dans ce tableau elements (avec comme convention qu'un ID est mis à idInconnu pour dire qu'on ne pointe sur rien)
l'insertion dans le tableau se fait sur prochainIndexElementDispo et vous mettez à jour les Index (ID) des membres de l'Element
ensuite la tableau étant "à plat", vous pourriez l'écrire avec put() ou le relire avec get()
Je ne comprends pas trop ce que vous entendez par "index relatifs".
Ce que j'arrive a faire en modifiant un peu la fonction readSdcard, c'est avoir un index de chaque chanson qui commence a 0 a chaque changement d'album, un incrément pour chaque dossier, ainsi que le chemin complet de chaque item. Chose indispensable pour lancer mes mp3.
Est ce que je peux faire quelque chose avec ça ?
Je n'ai jamais testé mais d'après ce que j'ai lu je dois pouvoir recréer l'aborescence dans le SPIFFS, mais je ne sais pas si ça sera vraiment utile car initialement je pourcourais la carte SD à la volée et ça coupait le son le temps du listing du dossier a afficher. J'imagine que ça sera là meme chose avec la mémoire SPIFFS, a moins que ce soit vraiment plus rapide que la lecture de la carte SD
Parce pour avoir suivantID, precedentID et enfantID, il faut que je change un peu plus en profondeur la fonction, et dans un précédent post sur ce forum je n'avais pas réussi a établir tous ces liens.
Je veux dire par la qu’on n’a pas un pointeur sur une position absolue en mémoire vers l’autre structure mais l’index par rapport au début du tableau de structure (le N° de case du tableau).
Ainsi si vous dupliquez tout le tableau ou le déplacez de RAM en FLASH les valeurs d’index restent valables
Quel est l’objectif réel de cette duplication de la table des fichiers en mémoire ?
c'est dans le cadre d'un lecteur MP3.
La musique est sur une carte SD.
l'objectif est d'afficher la liste des MP3 à l'écran pour selectionner la chanson a lancer.
Actuellement je parcours la carte SD à la volée, c'est a dire, je sais dans quel dossier je suis, si je selectionne un dossier, j'ai une fonctione qui va faire OpenNextFile tant qu'il y a quelque chose a parcourir dans le dossier.
Ca fonctionne bien, mais le souci, c'est que si j'ai une lecture en cours, le fait de lister les fichier d'un dossier va bloquer la musique le temps de le faire.
L'idée est donc d'avoir déja fait le boulot en amont pour avoir quelque chose de plus rapide et ne plus avoir ce petit "blanc" durant la lecture, le stocker pour ne pas avoir a le refaire a chaque extinction de l'appareil.