Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,51 @@

Firmware for M5Stack Cardputer ADV (ESP32-S3)

## Which Branch to Use?

**Use the `copilot/optimize-flashing-to-sd-card` branch for the latest stable version with SD card support and optimized memory usage.**

This branch includes:
- ✅ Optimized partition scheme for 16MB flash
- ✅ SD card support for external data storage
- ✅ Reduced flash memory usage
- ✅ OTA update capability

## Hardware
- **Device**: M5Stack Cardputer ADV
- **MCU**: ESP32-S3-WROOM-1-N16R8
- **Flash**: 16MB
- **PSRAM**: 8MB
- **Display**: 1.14" LCD (240x135)
- **Keyboard**: Full QWERTY matrix
- **SD Card**: microSD card slot (optional but recommended)

## Memory Optimization

### Flash Memory Management
This firmware uses an optimized partition scheme that allocates:
- **App partitions**: 2 × 3.75MB (for OTA updates)
- **SPIFFS**: ~8.5MB (for file storage)
- **NVS**: 20KB (for settings)
- **Total**: Efficient use of 16MB flash

### SD Card Support
To avoid running out of flash memory:
1. **Insert a microSD card** into your Cardputer's SD slot
2. The firmware will automatically detect and mount it
3. Store large files, assets, and data on the SD card
4. Flash memory is reserved for firmware only

**Benefits of using SD card:**
- Prevents "out of memory" errors during flashing
- Store unlimited data externally
- Easy to swap and backup data
- Faster development iterations

## Build & Flash

**📖 For detailed SD card setup instructions, see [docs/SD_CARD_SETUP.md](docs/SD_CARD_SETUP.md)**

### Using PlatformIO CLI
```bash
# Install PlatformIO
Expand Down Expand Up @@ -39,12 +74,64 @@ pio device monitor
- Drivers: `drivers/cardputer_adv_driver.cpp`
- Utilities: `lib/utilities.cpp`

### Using SD Card for Data Storage
The firmware automatically initializes the SD card on boot. You can use it to:
- Store configuration files
- Save logs and debug data
- Store images, fonts, and other assets
- Cache downloaded data

Example code to write to SD card:
```cpp
#include <SD.h>

// Write to SD card
File file = SD.open("/data/myfile.txt", FILE_WRITE);
if (file) {
file.println("Hello from Cardputer!");
file.close();
}

// Read from SD card
file = SD.open("/data/myfile.txt");
if (file) {
while (file.available()) {
Serial.write(file.read());
}
file.close();
}
```

## Features
- Full M5Unified library integration
- USB CDC serial debugging
- Keyboard input handling
- LCD display control
- 16MB Flash + 8MB PSRAM support
- **SD card support for external storage**
- **Optimized partition scheme for memory efficiency**

## Troubleshooting

### "Out of Memory" Error When Flashing
If you encounter memory errors during flashing:
1. Make sure you're using the `copilot/optimize-flashing-to-sd-card` branch
2. The custom partition scheme (`default_16MB.csv`) is now optimized for your device
3. Insert an SD card to store data externally instead of in flash
4. Clean and rebuild: `pio run --target clean && pio run`

### SD Card Not Detected
If the SD card isn't mounting:
1. Ensure the SD card is properly inserted
2. Try formatting the card as FAT32
3. Check the serial monitor for initialization messages
4. Some SD cards may need lower SPI speeds (already set to 25MHz)

### Partition Scheme Issues
The firmware uses a custom 16MB partition scheme:
- Located in: `default_16MB.csv`
- Configured in: `platformio.ini`
- Provides optimal space allocation for OTA updates and storage

## License
See LICENSE file for details.
Expand Down
7 changes: 7 additions & 0 deletions default_16MB.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x3C0000,
app1, app, ota_1, 0x3D0000,0x3C0000,
spiffs, data, spiffs, 0x790000,0x860000,
coredump, data, coredump,0xFF0000,0x10000,
6 changes: 5 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Documentation

This directory contains documentation and setup instructions for the UltimatumCardputerKey firmware.
This directory contains documentation and setup instructions for the UltimatumCardputerKey firmware.

## Available Guides

- **[SD Card Setup Guide](SD_CARD_SETUP.md)** - Complete guide for setting up SD card storage to avoid flash memory issues
165 changes: 165 additions & 0 deletions docs/SD_CARD_SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# SD Card Setup Guide

## Overview
The M5Stack Cardputer ADV has a built-in microSD card slot that can be used to store data externally, preventing flash memory overflow issues.

## Why Use SD Card?

### Problem
When flashing the Cardputer ADV firmware, you may encounter "out of memory" errors because:
- The firmware binary is large
- ESP32-S3 has 16MB flash, but partition overhead reduces available space
- OTA updates require two app partitions

### Solution
By using an SD card:
- Store application data externally
- Keep flash memory for firmware only
- Eliminate memory errors during flashing
- Easy data backup and transfer

## Setup Instructions

### 1. Prepare SD Card
- Use a microSD card (Class 10 or better recommended)
- Format as FAT32
- Insert into Cardputer's SD slot (bottom of device)

### 2. Use the Correct Branch
```bash
git checkout copilot/optimize-flashing-to-sd-card
```

### 3. Flash the Firmware
```bash
pio run --target upload
```

The firmware will automatically:
- Detect the SD card
- Create a `/data` directory
- Report SD card status via serial monitor

### 4. Verify SD Card
Check serial monitor output for:
```
Initializing SD card...
SD Card Type: SDHC
SD Card Size: 32000MB
Total space: 32000MB
Used space: 0MB
Created /data directory on SD card
SD card initialized successfully
```

## Using SD Card in Your Code

### Writing Files
```cpp
#include <SD.h>

void saveToSD() {
File file = SD.open("/data/config.txt", FILE_WRITE);
if (file) {
file.println("My configuration data");
file.close();
Serial.println("Data saved to SD card");
}
}
```

### Reading Files
```cpp
void readFromSD() {
File file = SD.open("/data/config.txt");
if (file) {
while (file.available()) {
String line = file.readStringUntil('\n');
Serial.println(line);
}
file.close();
}
}
```

### Listing Files
```cpp
void listFiles() {
File root = SD.open("/data");
File file = root.openNextFile();

while (file) {
Serial.print("FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
file = root.openNextFile();
}
}
```

## Partition Scheme

The optimized partition scheme (`default_16MB.csv`) allocates:

| Partition | Size | Purpose |
|-----------|------|---------|
| app0 | 3.75MB | Main firmware |
| app1 | 3.75MB | OTA update slot |
| spiffs | 8.5MB | File system |
| nvs | 20KB | Settings storage |
| coredump | 64KB | Debug info |

**Total: 16MB efficiently utilized**

## Troubleshooting

### SD Card Not Detected
1. Check card is properly inserted
2. Try different SD card (some cards have compatibility issues)
3. Reformat card as FAT32
4. Check serial monitor for error messages

### Still Running Out of Memory
1. Verify you're using the `copilot/optimize-flashing-to-sd-card` branch
2. Clean build: `pio run --target clean`
3. Check `platformio.ini` references `default_16MB.csv`
4. Reduce code size by removing unused libraries

### Build Errors
```bash
# Clean and rebuild
pio run --target clean
pio run

# Update dependencies
pio pkg update
```

## Best Practices

1. **Always check SD card presence before writing**
```cpp
if (SD.exists("/data")) {
// SD card is available
}
```

2. **Close files after use**
```cpp
file.close(); // Always close files to prevent corruption
```

3. **Use `/data` directory for organization**
- Firmware automatically creates this
- Keeps your files organized

4. **Handle SD card removal gracefully**
- Don't assume SD card is always present
- Provide fallback to internal storage if needed

## Additional Resources

- [M5Stack Cardputer Documentation](https://docs.m5stack.com/en/core/Cardputer)
- [ESP32 Partition Tables](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html)
- [Arduino SD Library](https://www.arduino.cc/reference/en/libraries/sd/)
65 changes: 64 additions & 1 deletion drivers/cardputer_adv_driver.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,77 @@
#include <Arduino.h>
#include <M5Unified.h>
#include <SD.h>
#include <FS.h>
#include <SPI.h>
#include "cardputer_adv_driver.h"

// SD Card configuration for M5Stack Cardputer
#define SD_CS_PIN GPIO_NUM_4
#define SD_SPI_FREQ 25000000 // 25MHz

bool initialize_sd_card() {
Serial.println("Initializing SD card...");

// Note: This function should be called after M5.begin() in setup()
// M5Unified configures the SPI pins automatically for M5Stack devices

// Try to mount SD card with explicit CS pin and frequency
if (!SD.begin(SD_CS_PIN, SPI, SD_SPI_FREQ)) {
Serial.println("SD Card mount failed or not present");
Serial.println("Note: Insert SD card and restart if you want to use external storage");
return false;
}

uint8_t cardType = SD.cardType();
if (cardType == CARD_NONE) {
Serial.println("No SD card attached");
return false;
}

// Print SD card info
Serial.print("SD Card Type: ");
if (cardType == CARD_MMC) {
Serial.println("MMC");
} else if (cardType == CARD_SD) {
Serial.println("SDSC");
} else if (cardType == CARD_SDHC) {
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}

uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));

// Create data directory if it doesn't exist
if (!SD.exists("/data")) {
SD.mkdir("/data");
Serial.println("Created /data directory on SD card");
}

Serial.println("SD card initialized successfully");
return true;
}

void initialize_driver() {
Serial.println("Initializing Cardputer ADV driver...");

// Initialize SD card for external storage
// This reduces flash memory usage by storing data externally
// NOTE: M5.begin() must be called before this function
if (initialize_sd_card()) {
Serial.println("SD card available for data storage");
Serial.println("Use SD card to store large files and reduce flash memory usage");
} else {
Serial.println("SD card not available - using internal flash only");
Serial.println("To use SD card: Insert card and restart device");
}

// Add your custom driver initialization here
// Examples:
// - WiFi setup
// - SD card mounting
// - Custom peripheral initialization

Serial.println("Driver initialized successfully");
Expand Down
4 changes: 4 additions & 0 deletions drivers/cardputer_adv_driver.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#ifndef CARDPUTER_ADV_DRIVER_H
#define CARDPUTER_ADV_DRIVER_H

#include <SD.h>
#include <FS.h>

void initialize_driver();
bool initialize_sd_card();

#endif // CARDPUTER_ADV_DRIVER_H
Loading