How to Upload Large .h Image Files to External SPI Flash (W25Q64) on ESP32?

Hi all, I have a Freenove ESP32 Board: dual-core 32-bit microprocessor, up to 240 MHz, 4 MB Flash, 520 KB SRAM.

I ran this display related sketch on it and it ran fine:

#include <TFT_eSPI.h>
#include <SPI.h>
#include "jpeg1.h"
#include "jpeg2.h"
#include "jpeg3.h"
#include "jpeg4.h"
#include "jpeg5.h"

TFT_eSPI tft = TFT_eSPI(); // Invoke custom library

void setup(){
    Serial.begin(115200);
    Serial.println("Start");
    tft.init();
    tft.setRotation(1);
    tft.setSwapBytes(true);
}

void loop(){
    tft.pushImage(0, 0,  320, 240, jpeg1);
    delay(150);  
    tft.pushImage(0, 0,  320, 240, jpeg2);
    delay(150);  
    tft.pushImage(0, 0,  320, 240, jpeg3);
    delay(150);  
    tft.pushImage(0, 0,  320, 240, jpeg4);
    delay(150);
    tft.pushImage(0, 0,  320, 240, jpeg5);
    delay(150);
}

As you can see, there are 5 JPEG files.

Later, I modified the sketch to handle 15 JPEGs.

The Arduino IDE then reported there wasn’t enough room on my board. Google suggested using an external SPI flash chip (W25Q64).

I later got an external flash chip and tested it with this demo sketch shared by a YouTube tutorial. That sketch is below:

/*
  ESP32 External SPI Flash Demo
  esp32-ext-flash-demo.ino
  Demonstrates use of W25Q64 Flash memory module
  Uses ESP32-S3 DevKit1
  Uses SPIMemory Library

  1 - Read Flash ID
  2 - Read Flash Capacity
  3 - Erase 4kB sector
  4 - Write and Read
  
  DroneBot Workshop 2025
  https://dronebotworkshop.com
*/

// Include Required Libraries
#include <SPI.h>
#include <SPIMemory.h>

// --- Your wiring on ESP32-S3 DevKitC-1 ---
static const int PIN_SCK = 12;   // CLK
static const int PIN_MISO = 13;  // DO  -> MISO
static const int PIN_MOSI = 11;  // DI  -> MOSI
static const int PIN_CS = 10;    // CS

SPIFlash flash(PIN_CS);

void setup() {
  Serial.begin(115200);
  delay(200);
  Serial.println("\n=== W25Q64 Quick Test ===");

  SPI.begin(PIN_SCK, PIN_MISO, PIN_MOSI, PIN_CS);

  if (!flash.begin()) {
    Serial.println("Flash NOT detected. Check 3V3, GND, CS, and wiring.");
    while (1) delay(10);
  }

  // NEW: getJEDECID() returns a 32-bit value like 0xEF4017 for W25Q64
  uint32_t jedec = flash.getJEDECID();
  uint8_t manufacturer = (jedec >> 16) & 0xFF;
  uint8_t memType = (jedec >> 8) & 0xFF;
  uint8_t capacityCode = jedec & 0xFF;

  Serial.printf("JEDEC ID: 0x%06lX  (MFG=0x%02X TYPE=0x%02X CAP=0x%02X)\n",
                (unsigned long)jedec, manufacturer, memType, capacityCode);
  Serial.printf("Reported capacity: %lu bytes\n", (unsigned long)flash.getCapacity());

  const uint32_t addr = 0x00000;  // sector 0
  Serial.println("Erasing 4KB sector @ 0x000000...");
  if (!flash.eraseSector(addr)) Serial.println("Erase FAILED");

  // NEW: make it non-const for writeCharArray (or use writeAnything)
  char msg[] = "Hello from ESP32-S3 + W25Q64!";
  bool okW = flash.writeCharArray(addr, msg, sizeof(msg));  // includes '\0'
  char buf[sizeof(msg)] = { 0 };
  bool okR = flash.readCharArray(addr, buf, sizeof(buf));

  Serial.printf("Write: %s  Read: %s\n", okW ? "OK" : "FAIL", okR ? "OK" : "FAIL");
  Serial.print("Data: ");
  Serial.println(buf);
}

void loop() {}

This demo works for basic write/read operations.

My goal now:
I want to download large .h files (images) onto the W25Q64 and access them from the ESP32, rather than embedding them in the main sketch.

Questions:

  1. Can someone guide me to a tutorial showing how to upload large files onto an external SPI flash like the W25Q64?

  2. Is there a Windows-based GUI tool where I can drag-and-drop files into a flash memory like the W25Q64?

Thanx for the replies!

A file of type .h is intended to be compiled and linked into part of a program image.

Put standard (.jpg, .bmp, .gif, ...) image files on the SPI flash chip instead, and display them using function calls in your program. There are plenty of examples on line showing how to do that.

Adafruit has libraries for SPI flash file systems.

I don't know what your final application is intended to do but a while ago I tried something very similar using a SD card and also SPI flash.

When using the spi flash I used bmp files for simplicity. I would extract the rgb888 image data convert to rgb565 and write the resulting binary data sequentially to the flash. For a 320 x 240 bmp file I would end up with a binary file of 153600 bytes, a reduction of over 70 KB. For 15 files that would be 2.3 MB of spi flash

So each image has an index of image number x 153600, I used the adafruit drivers and would write the data to a framebuffer/canvas before display which would give a small increase in speed.

You can find online resources to parse the image array from a bmp or use a c/c++ header file to extract the data, personally I used a python script that handles bmp or png files.

I probably would try to get a file system running on the flash. Something like LittleFS. To get the files into the flash I would add a webserver that accept either HTTP PUT or file uploads vis HTTP POST.

The jpeg.h is most likely uncompressed RGB565. Either you add an JPEG decoder or you need to prepare the file before upload.

This is the OP. Just to clarify, I want to put my huge .h image file on the flash and then I want it to be read/retrieved ( I dont have a preference how it happens here) so that the .h image file can be displayed on my TFT LCD screen. Thx

Your misguided idea was clear from the start. But if you insist on following through with it, simply write Arduino code that opens the .h file, interprets the data strings in it and sends the result to the display.

can you maybe switch the partition scheme to huge app??

this would allow for all of your 4 MB flash available for sketch..

good luck.. ~q