# ESP Memory VFS Component A lightweight, memory-based virtual file system component for ESP-IDF. This component implements a RAM-based filesystem that allows applications to create, read, write, and manipulate files entirely in memory. ## Overview The Memory VFS component provides a virtual file system that operates entirely in RAM, making it useful for: - Temporary file storage - Fast data exchange between components - Testing and development - Scenarios where flash storage is limited or unavailable - Applications that need high-speed file operations ## Features - **Memory-based storage**: All files are stored in RAM - **Standard file operations**: Full support for POSIX-style operations (open, read, write, seek, close) - **File management**: Create, delete, and rename files - **Dynamic memory allocation**: Automatic buffer resizing for growing files - **Configurable capacity**: Set the maximum number of files at initialization - **ESP-IDF integration**: Seamlessly works with ESP-IDF's VFS layer - **Thread safety**: Mutex protection for concurrent access to files ## Directory Structure ``` esp-vfs-mem/ ├── include/ │ └── esp_vfs_mem.h # Public API header ├── src/ │ ├── vfs_mem.c # Main implementation │ └── vfs_mem_internal.h # Internal definitions ├── test_apps/ # Example applications │ └── stdio_example.c # Example using standard C library API ├── CMakeLists.txt # Build configuration └── README.md # This file ``` ## Installation ### As a Component in Your Project 1. Copy this repository into your project's `components` directory: ```bash mkdir -p components cp -r esp-vfs-mem components/ ``` 2. Or add it as a git submodule: ```bash git submodule add https://github.com/yourusername/esp-vfs-mem.git components/esp-vfs-mem ``` ### Using Component Manager Add the following to your project's `idf_component.yml`: ```yaml dependencies: esp-vfs-mem: version: "^1.0.0" # Replace with actual repository URL git: https://github.com/yourusername/esp-vfs-mem.git ``` ## API Reference ### Registering the Filesystem ```c esp_err_t esp_vfs_mem_register(const char* base_path, size_t max_files); ``` - **base_path**: Mount point for the filesystem (e.g., "/mem") - **max_files**: Maximum number of files the filesystem can handle (default: 5) - **Returns**: ESP_OK on success, or an error code ### Unregistering the Filesystem ```c esp_err_t esp_vfs_mem_unregister(const char* base_path); ``` - **base_path**: Mount point of the filesystem to unregister - **Returns**: ESP_OK on success, or an error code ## Usage Examples ### Basic Usage ```c #include "esp_vfs_mem.h" #include "esp_log.h" static const char *TAG = "mem_vfs_example"; void app_main(void) { // Register memory filesystem at /mem path with support for up to 10 files ESP_ERROR_CHECK(esp_vfs_mem_register("/mem", 10)); ESP_LOGI(TAG, "Memory filesystem registered at /mem"); // Create and write to a file FILE *f = fopen("/mem/hello.txt", "w"); if (f == NULL) { ESP_LOGE(TAG, "Failed to open file for writing"); return; } fprintf(f, "Hello, ESP Memory VFS!"); fclose(f); // Read from the file f = fopen("/mem/hello.txt", "r"); if (f == NULL) { ESP_LOGE(TAG, "Failed to open file for reading"); return; } char buf[64]; size_t bytes_read = fread(buf, 1, sizeof(buf) - 1, f); buf[bytes_read] = '\0'; ESP_LOGI(TAG, "Read from file: %s", buf); fclose(f); // Unregister when done ESP_ERROR_CHECK(esp_vfs_mem_unregister("/mem")); } ``` ### POSIX-style File Operations ```c // Open a file for writing int fd = open("/mem/data.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) { ESP_LOGE(TAG, "Failed to open file: %s", strerror(errno)); return; } // Write data const char *data = "POSIX API example"; write(fd, data, strlen(data)); close(fd); // Open for reading fd = open("/mem/data.txt", O_RDONLY); if (fd < 0) { ESP_LOGE(TAG, "Failed to open file for reading"); return; } // Read data char buf[64]; ssize_t bytes_read = read(fd, buf, sizeof(buf) - 1); if (bytes_read > 0) { buf[bytes_read] = '\0'; ESP_LOGI(TAG, "Read content: %s", buf); } close(fd); // File management rename("/mem/data.txt", "/mem/renamed.txt"); unlink("/mem/renamed.txt"); // Delete file ``` ### Advanced Usage ```c // Create a binary file FILE *f = fopen("/mem/binary.dat", "wb"); if (f == NULL) { ESP_LOGE(TAG, "Failed to create binary file"); return; } // Write structured data typedef struct { uint32_t id; float value; char name[16]; } record_t; record_t records[] = { {1, 3.14, "Record 1"}, {2, 2.71, "Record 2"}, {3, 1.41, "Record 3"} }; fwrite(records, sizeof(record_t), 3, f); fclose(f); // Random access f = fopen("/mem/binary.dat", "rb"); if (f == NULL) { ESP_LOGE(TAG, "Failed to open binary file"); return; } // Seek to second record fseek(f, sizeof(record_t), SEEK_SET); // Read just one record record_t record; if (fread(&record, sizeof(record_t), 1, f) == 1) { ESP_LOGI(TAG, "Record ID: %lu, Value: %.2f, Name: %s", record.id, record.value, record.name); } fclose(f); ``` ### Thread Safety The memory filesystem is thread-safe, allowing multiple tasks to safely access files concurrently: ```c // Task 1 void writer_task(void *pvParameters) { while (1) { FILE *f = fopen("/mem/shared.txt", "w"); if (f) { fprintf(f, "Data from writer task"); fclose(f); } vTaskDelay(pdMS_TO_TICKS(100)); } } // Task 2 void reader_task(void *pvParameters) { while (1) { FILE *f = fopen("/mem/shared.txt", "r"); if (f) { char buf[64]; size_t bytes_read = fread(buf, 1, sizeof(buf) - 1, f); buf[bytes_read] = '\0'; ESP_LOGI(TAG, "Read: %s", buf); fclose(f); } vTaskDelay(pdMS_TO_TICKS(150)); } } ``` ## Performance Considerations - **Memory Usage**: Each file consumes memory for both its content and metadata - **Automatic Resizing**: Files grow dynamically as needed, doubling in size when more space is required - **Speed**: Operations are very fast since they occur entirely in RAM - **Volatility**: All data is lost on power cycle or when the filesystem is unregistered - **Mutex Protection**: Thread safety adds a small overhead to file operations ## Limitations - All data is stored in RAM, so it's volatile and limited by available memory - No directory structure support (flat file organization) - No file permissions or access control - Mutex timeout is set to 1000ms by default ## Contributing Contributions to improve the Memory VFS component are welcome! Please feel free to submit issues or pull requests.
8138cfe870f7482ea9e57a903705eb5bdcfc6031
idf.py add-dependency "shootao/esp-vfs-mem^0.1.0"