这是我在这里发的第一篇文章。
我遇到以下问题。我有一些代码可以将 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...)
这会永远重复。
测试了很多东西后,我意识到问题是我忘记在 Memoria::transferir 函数实现的末尾添加 return 语句。
我认为这个问题在某种程度上与 SD_MMC 库的具体实现有关,因为这就是日志引导我发现的。多么愚蠢啊。
我还实现了整个类SimpleStatus用于调试目的,但我没有使用它。如果我使用了它,那么我可能会使用日志发现该错误。