I am using ESP32 wroom with W25q32 . i want to use the SPI flash memory as storage space to store images ,gif and mp3 audio files .Is there a way to get Filesystem like littleFs or SPIFFS for External SPI flash Memory .
After some research i found out we can use FATFS for external FLash filesystem i am trying to make it using the Example code . I modified the code little to work on Arduino Environment . I am using Arduino 2.3.4 .
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* Example of FAT filesystem on external Flash.
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
This sample shows how to store files inside a FAT filesystem.
FAT filesystem is stored in a partition inside SPI flash, using the
flash wear levelling library.
*/
// SPI pin definitions for external Flash
#define PIN_MOSI 23 // Master Out Slave In (MOSI)
#define PIN_MISO 19 // Master In Slave Out (MISO)
#define PIN_CLK 18 // Serial Clock (SCK)
#define PIN_CS 5 // Chip Select (CS)
#define HOST_ID SPI3_HOST // Use SPI3_HOST (VSPI) or SPI2_HOST (HSPI)
#define EXAMPLE_FLASH_FREQ_MHZ 133 // Replace with your chip's maximum frequency
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "esp_flash.h"
#include "esp_flash_spi_init.h"
#include "esp_partition.h"
#include "esp_vfs.h"
#include "esp_vfs_fat.h"
#include "esp_system.h"
#include "soc/spi_pins.h"
// h2 and c2 will not support external flash
#define EXAMPLE_FLASH_FREQ_MHZ 40
static const char* TAG = "example";
// Pin mapping
// ESP32 (VSPI)
#ifdef CONFIG_IDF_TARGET_ESP32
#define HOST_ID SPI3_HOST
#define PIN_MOSI SPI3_IOMUX_PIN_NUM_MOSI
#define PIN_MISO SPI3_IOMUX_PIN_NUM_MISO
#define PIN_CLK SPI3_IOMUX_PIN_NUM_CLK
#define PIN_CS SPI3_IOMUX_PIN_NUM_CS
#define PIN_WP SPI3_IOMUX_PIN_NUM_WP
#define PIN_HD SPI3_IOMUX_PIN_NUM_HD
#define SPI_DMA_CHAN SPI_DMA_CH_AUTO
#else // Other chips (SPI2/HSPI)
#define HOST_ID SPI2_HOST
#define PIN_MOSI SPI2_IOMUX_PIN_NUM_MOSI
#define PIN_MISO SPI2_IOMUX_PIN_NUM_MISO
#define PIN_CLK SPI2_IOMUX_PIN_NUM_CLK
#define PIN_CS SPI2_IOMUX_PIN_NUM_CS
#define PIN_WP SPI2_IOMUX_PIN_NUM_WP
#define PIN_HD SPI2_IOMUX_PIN_NUM_HD
#define SPI_DMA_CHAN SPI_DMA_CH_AUTO
#endif
// Handle of the wear levelling library instance
static wl_handle_t s_wl_handle = WL_INVALID_HANDLE;
// Mount path for the partition
const char* base_path = "/extflash";
static esp_flash_t* example_init_ext_flash(void);
static const esp_partition_t* example_add_partition(esp_flash_t* ext_flash, const char* partition_label);
static void example_list_data_partitions(void);
static bool example_mount_fatfs(const char* partition_label);
void setup(void) {
Serial.begin(115200);
// Set up SPI bus and initialize the external SPI Flash chip
esp_flash_t* flash = example_init_ext_flash();
if (flash == NULL) {
return;
}
// Add the entire external flash chip as a partition
const char* partition_label = "storage";
example_add_partition(flash, partition_label);
// List the available partitions
example_list_data_partitions();
// Initialize FAT FS in the partition
if (!example_mount_fatfs(partition_label)) {
return;
}
// Print FAT FS size information
uint64_t bytes_total, bytes_free;
esp_vfs_fat_info(base_path, &bytes_total, &bytes_free);
ESP_LOGI(TAG, "FAT FS: %" PRIu64 " kB total, %" PRIu64 " kB free", bytes_total / 1024, bytes_free / 1024);
// Create a file in FAT FS
ESP_LOGI(TAG, "Opening file");
FILE* f = fopen("/extflash/hello.txt", "wb");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for writing");
return;
}
fprintf(f, "Written using ESP-IDF %s\n", esp_get_idf_version());
fclose(f);
ESP_LOGI(TAG, "File written");
// Open file for reading
ESP_LOGI(TAG, "Reading file");
f = fopen("/extflash/hello.txt", "rb");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for reading");
return;
}
char line[128];
fgets(line, sizeof(line), f);
fclose(f);
// strip newline
char* pos = strchr(line, '\n');
if (pos) {
*pos = '\0';
}
ESP_LOGI(TAG, "Read from file: '%s'", line);
}
static esp_flash_t* example_init_ext_flash(void) {
// Define the SPI bus configuration
spi_bus_config_t bus_config;
bus_config.mosi_io_num = PIN_MOSI; // Assign GPIO for MOSI
bus_config.miso_io_num = PIN_MISO; // Assign GPIO for MISO
bus_config.sclk_io_num = PIN_CLK; // Assign GPIO for CLK
bus_config.quadwp_io_num = -1; // Set to -1 if not used
bus_config.quadhd_io_num = -1; // Set to -1 if not used
bus_config.max_transfer_sz = 4096; // Default transfer size
ESP_LOGI(TAG, "SPI Bus Pins: MOSI=%d, MISO=%d, CLK=%d, CS=%d",
PIN_MOSI, PIN_MISO, PIN_CLK, PIN_CS);
// Define the SPI flash device configuration
esp_flash_spi_device_config_t device_config;
device_config.host_id = HOST_ID;
device_config.cs_io_num = PIN_CS;
device_config.io_mode = SPI_FLASH_DIO;
device_config.freq_mhz = EXAMPLE_FLASH_FREQ_MHZ;
device_config.cs_id = 0;
ESP_LOGI(TAG, "Initializing SPI bus");
esp_err_t ret = spi_bus_initialize(HOST_ID, &bus_config, 0); // Replace SPI_DMA_CH_AUTO with 0
if (ret != ESP_OK) {
ESP_LOGE(TAG, "SPI bus initialization failed: %s", esp_err_to_name(ret));
return NULL;
}
// Add flash device to the SPI bus
esp_flash_t* ext_flash;
ret = spi_bus_add_flash_device(&ext_flash, &device_config);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to add flash device: %s", esp_err_to_name(ret));
return NULL;
}
ESP_LOGI(TAG, "Flash device added successfully");
// Probe the flash device to ensure it works
ESP_LOGI(TAG, "Probing the flash device");
ret = esp_flash_init(ext_flash);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize flash: %s", esp_err_to_name(ret));
return NULL;
}
// Log successful initialization
uint32_t id;
ESP_ERROR_CHECK(esp_flash_read_id(ext_flash, &id));
ESP_LOGI(TAG, "Flash ID: 0x%x, size: %u KB", id, ext_flash->size / 1024);
return ext_flash;
}
static const esp_partition_t* example_add_partition(esp_flash_t* ext_flash, const char* partition_label) {
ESP_LOGI(TAG, "Adding external Flash as a partition, label=\"%s\", size=%" PRIu32 " KB", partition_label, ext_flash->size / 1024);
const esp_partition_t* fat_partition;
const size_t offset = 0;
ESP_ERROR_CHECK(esp_partition_register_external(ext_flash, offset, ext_flash->size, partition_label, ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, &fat_partition));
// Erase space of partition on the external flash chip
ESP_LOGI(TAG, "Erasing partition range, offset=%u size=%" PRIu32 " KB", offset, ext_flash->size / 1024);
ESP_ERROR_CHECK(esp_partition_erase_range(fat_partition, offset, ext_flash->size));
return fat_partition;
}
static void example_list_data_partitions(void) {
ESP_LOGI(TAG, "Listing data partitions:");
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL);
for (; it != NULL; it = esp_partition_next(it)) {
const esp_partition_t* part = esp_partition_get(it);
ESP_LOGI(TAG, "- partition '%s', subtype %d, offset 0x%" PRIx32 ", size %" PRIu32 " kB",
part->label, part->subtype, part->address, part->size / 1024);
}
esp_partition_iterator_release(it);
}
static bool example_mount_fatfs(const char* partition_label) {
ESP_LOGI(TAG, "Mounting FAT filesystem");
const esp_vfs_fat_mount_config_t mount_config = {
.format_if_mount_failed = true,
.max_files = 4,
.allocation_unit_size = CONFIG_WL_SECTOR_SIZE,
};
esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl(base_path, partition_label, &mount_config, &s_wl_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
return false;
}
return true;
}
void loop() {
}
Output :
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:4832
load:0x40078000,len:16460
load:0x40080400,len:4
load:0x40080404,len:3504
entry 0x400805cc
E (20) spi: spi_bus_initialize(776): intr flag not allowed
i dont know what to about this error .
E (20) spi: spi_bus_initialize(776): intr flag not allowed
