ESP32-S3。 Arduino框架:使用类实现时的SD卡读取问题

问题描述 投票:0回答:1

这是我在这里发的第一篇文章。

我遇到以下问题。我有一些代码可以将 gif 文件从 SD 卡传输到闪存,然后使用 TFT 显示屏显示它。

以下代码按预期工作:

#include <Memoria.h>
#include <Pantalla.h>

#include <FS.h>
#include <LittleFS.h>

#include <SD_MMC.h>

//  ************************* PINES SD  *************************
#define ONE_BIT_MODE false               // Indica si la SD trabajará con MMC de 1 bit (si no, trabaja con 4 bits)

int d2  = 4;
int d3  = 5;          // GPIO 34 is not broken-out on ESP32-S3-DevKitC-1 v1.1
int cmd = 6;
int clk = 7;
int d0  = 15;
int d1  = 16;

Pantalla *Pantalla::inst_ = NULL;                 // Se instancia el punturo al singleton
Pantalla* pantalla = Pantalla::getInstance();     // Se obtiene una copia del singleton

Memoria memoria = Memoria(clk, cmd, d0, d1, d2, d3);    //  Se instancia la memoria

const char *filename = "/sparkle_simple.gif";   // Change to load other gif files in images/GIF

void inicializarSD(void);
void inicializarLittleFS(void);
void cargarArchivo(const char *filename);

void setup()
{
  Serial.begin(115200);
/*
  memoria.begin();

  memoria.transferir(filename);
  */

  inicializarSD();
  inicializarLittleFS();
  cargarArchivo(filename);

  pantalla->begin();          // Se inicializa la pantalla

  // Initialize the GIF
  pantalla->mostrar(filename);
}

void loop()
{
  
}

void inicializarSD(void) {
  //  Configuracion de resistencias pull-up
  //  Se siguio la indicacion del README de la librería SD_MMC

  pinMode(clk, INPUT_PULLUP);
  pinMode(cmd, INPUT_PULLUP);
  pinMode(d0,  INPUT_PULLUP);
  pinMode(d1,  INPUT_PULLUP);
  pinMode(d2,  INPUT_PULLUP);
  pinMode(d3,  INPUT_PULLUP);

  //  Seteo de pines de la SD
  if(! SD_MMC.setPins(clk, cmd, d0, d1, d2, d3)) {
      Serial.println("Pin change failed!");                            
      return;
  }
                                                                                   
  Serial.println("SD card initialization...");                                                                                      
  if (!SD_MMC.begin("/sdcard", ONE_BIT_MODE)) {
    Serial.println("SD card initialization failed!");                  
    return;
  }
}

void inicializarLittleFS(void) {
  // Inicialización LittleFS                                                                     
  Serial.println("Initialize LittleFS...");                                                               
  if (!LittleFS.begin(true))
  {
    Serial.println("LittleFS initialization failed!");
  }

  // Reformmating the LittleFS to have space if a large GIF is loaded
  // You could run out of LittleFS storage space if you load more than one image or a large GIF
  // You can also increase the LittleFS storage space by changing the partition of the ESP32
  //                                                                 
  Serial.println("Formatting LittleFS...");                                                                  
  LittleFS.format(); // This will erase all the files, change as needed, LittleFS is non-volatile memory
  Serial.println("LittleFS formatted successfully.");
}

void cargarArchivo(const char *filename) {
  // Open GIF file from SD card                                                                                                                                                        
  Serial.println("Openning GIF file from SD card...");                                                           
  File sdFile = SD_MMC.open(filename);
  if (!sdFile) {
    Serial.println("Failed to open GIF file from SD card!");
    return;
  }

  // Create a file in LittleFS to store the GIF                          )
  File LittleFSFile = LittleFS.open(filename, FILE_WRITE, true);
  if (!LittleFSFile) {
    Serial.println("Failed to copy GIF in LittleFS!");
    return;
  }

  // Read the GIF from SD card and write to LittleFS
  Serial.println("Copy GIF in LittleFS...");
  byte buffer[512];
  while (sdFile.available())
  {
    int bytesRead = sdFile.read(buffer, sizeof(buffer));
    LittleFSFile.write(buffer, bytesRead);
  }  

  LittleFSFile.close();
  sdFile.close();  
}

我想创建一个 Memory 类来处理 SD 卡和闪存。这是我写的:

记忆.h

#pragma once
#include "Arduino.h"

#include <FS.h>
#include <LittleFS.h>

#include <SD_MMC.h>

#include "StatusTools.h"

class Memoria {
  using Status = SimpleStatus;

  public: // These are the "functions" exposed to the consumer of this library

    Memoria(int clk, int cmd, int d0, int d1, int d2, int d3);    //  Constructor

    Status begin(void);                         //  Inicializar la SD
    Status transferir(const char *filename);    //  Transferir el archivo "filename" desde la SD a la flash

  private: // Only visible from within this class

    //  Registro de los pines
    int clk_;
    int cmd_;
    int d0_;
    int d1_;
    int d2_;
    int d3_;

  protected:  // Not exposed publicly. Can be used within this class AND used in inherited classes
              // Hmm Nothing springs to mind that should go here instead of one of the above sections
};

记忆.cpp

#include "Memoria.h"
#include "Arduino.h"

#include <FS.h>
#include <LittleFS.h>

#include <SD_MMC.h>

#include "StatusTools.h"

using Status = SimpleStatus;

Memoria::Memoria(int clk, int cmd, int d0, int d1, int d2, int d3) {

  //  Registro pines SD
  clk_ = clk;
  cmd_ = cmd;
  d0_ =  d0;
  d1_ =  d1;
  d2_ =  d2;
  d3_ =  d3;

  //  Configuracion de resistencias pull-up
  //  Se siguio la indicacion del README de la librería SD_MMC
  pinMode(clk_, INPUT_PULLUP);
  pinMode(cmd_, INPUT_PULLUP);
  pinMode(d0_,  INPUT_PULLUP);
  pinMode(d1_,  INPUT_PULLUP);
  pinMode(d2_,  INPUT_PULLUP);
  pinMode(d3_,  INPUT_PULLUP);
}

Status Memoria::begin(void) {
  //  Seteo de pines de la SD
  if(!SD_MMC.setPins(clk_, cmd_, d0_, d1_, d2_, d3_)) {
      Serial.println("Pin change failed!");
      return Status::Error;
  }

  //  Inicialización SD
  Serial.println("SD card initialization..."); 
  if (!SD_MMC.begin()) {          //  MMC 4-bit
    Serial.println("SD card initialization failed!");
    return Status::Error;
  }

  //  Inicialización LittleFS
  Serial.println("Initialize LittleFS...");                                                       
  if (!LittleFS.begin(true)) {
    Serial.println("LittleFS initialization failed!");
  }

  //  Formateo de LittleFS                                                                   
  Serial.println("Formatting LittleFS...");                                                            
  LittleFS.format(); // This will erase all the files, change as needed, LittleFS is non-volatile memory
  Serial.println("LittleFS formatted successfully.");

  return Status::Success;
}

Status Memoria::transferir(const char *filename) {

  // Open GIF file from SD card
  Serial.println("Openning GIF file from SD card...");                                     
  File sdFile = SD_MMC.open(filename);
  if (!sdFile) {
    Serial.println("Failed to open GIF file from SD card!");
    return Status::Error;
  }

  // Create a file in LittleFS to store the GIF
  File LittleFSFile = LittleFS.open(filename, FILE_WRITE, true);
  if (!LittleFSFile) {
    Serial.println("Failed to copy GIF in LittleFS!");
    return Status::Error;
  }

  // Read the GIF from SD card and write to LittleFS
  Serial.println("Copy GIF in LittleFS...");
  byte buffer[512];
  while (sdFile.available()) {
    int bytesRead = sdFile.read(buffer, sizeof(buffer));
    LittleFSFile.write(buffer, bytesRead);
  } 

  LittleFSFile.close();
  sdFile.close();

}

我通过注释以下几行在我的主程序文件中实现了这一点...

  inicializarSD();
  inicializarLittleFS();
  cargarArchivo(filename);

...并取消注释上面的两行代码。

运行程序时得到以下日志:

load:0x3fce3808,len:0x4bc
load:0x403c9700,len:0xbd8
load:0x403cc700,len:0x2a0c
entry 0x403c98d0
[   348][I][esp32-hal-psram.c:96] psramInit(): PSRAM enabled
[   358][V][esp32-hal-uart.c:330] uartBegin(): UART0 baud(115200) Mode(800001c) rxPin(44) txPin(43)
[   367][V][esp32-hal-uart.c:416] uartBegin(): UART0 not installed. Starting installation
[   376][V][esp32-hal-uart.c:463] uartBegin(): UART0 initialization done.
SD card initialization...
Initialize LittleFS...
Formatting LittleFS...
LittleFS formatted successfully.
Openning GIF file from SD card...
Copy GIF in LittleFS...
Guru Meditation Error: Core  0 panic'ed (LoadProhibited). Exception was unhandled.

Core  0 register dump:
PC      : 0x42002960  PS      : 0x00060a30  A0      : 0x8200269b  A1      : 0x3fceba00  
A2      : 0x00000000  A3      : 0x3c050120  A4      : 0x0000e100  A5      : 0x00000000  
A6      : 0x0000002b  A7      : 0x0001c200  A8      : 0x82002930  A9      : 0x00000004  
A10     : 0x42002db0  A11     : 0x3fced200  A12     : 0x000000b6  A13     : 0x3c050264  
A14     : 0x00000001  A15     : 0x00000000  SAR     : 0x0000001e  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000004  LBEG    : 0x400570a4  LEND    : 0x400570a9  LCOUNT  : 0x00000000  


Backtrace: 0x4200295d:0x3fceba00 0x42002698:0x3fcebc60 0x4200d7f3:0x3fcebc90




ELF file SHA256: 690274674a15b2f5

Rebooting...

这会永远重复,直到我打开设备电源。

我尝试使用以下行将 SD 频率更改为 20 MHz

SD_MMC.begin("\sdcard", false, false, 20000, 5)

我也遇到同样的问题

我还在这里放了一个打印声明...

  // Read the GIF from SD card and write to LittleFS
  Serial.println("Copy GIF in LittleFS...");
  byte buffer[512];
  while (sdFile.available()) {
    int bytesRead = sdFile.read(buffer, sizeof(buffer));
    Serial.println(bytesRead);          // TEST
    LittleFSFile.write(buffer, bytesRead);
  } 

...这会导致以下日志...

(Same as before...)
Copy GIF in LittleFS...
512
512
512
512
512
512
512
512
512
512
512
182
Guru Meditation Error: Core  0 panic'ed (LoadProhibited). Exception was unhandled.
(Same as before...)

这会永远重复。

class sd-card arduino-esp32
1个回答
0
投票

测试了很多东西后,我意识到问题是我忘记在 Memoria::transferir 函数实现的末尾添加 return 语句。

我认为这个问题在某种程度上与 SD_MMC 库的具体实现有关,因为这就是日志引导我发现的。多么愚蠢啊。

我还实现了整个类SimpleStatus用于调试目的,但我没有使用它。如果我使用了它,那么我可能会使用日志发现该错误。

© www.soinside.com 2019 - 2024. All rights reserved.