shootao/esp-vfs-mem

0.1.0

Latest
uploaded 11 months ago
Memory-based virtual file system component for ESP-IDF

Readme

# 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.

Links

Supports all targets

To add this component to your project, run:

idf.py add-dependency "shootao/esp-vfs-mem^0.1.0"

download archive

Stats

  • Archive size
    Archive size ~ 12.89 KB
  • Downloaded in total
    Downloaded in total 380 times
  • Weekly Downloads Weekly Downloads (All Versions)
  • Downloaded this version
    This version: 380 times

Badge

shootao/esp-vfs-mem version: 0.1.0
|