Skip to content

Repository files navigation

P2 microSD FAT32 Filesystem

A high-performance FAT32-compliant microSD card filesystem driver for the Parallax Propeller 2 (P2) microcontroller. (Why FAT32?)

Project Status Platform License

Overview

This project provides a robust, high-performance SD card driver for the P2 microcontroller with full FAT32 filesystem support. The driver uses P2 smart pins for hardware-accelerated SPI communication and supports multiple simultaneous file handles.

Features

  • FAT32 Filesystem Support: Full read/write access to FAT32-formatted SD cards
  • High-Performance SPI: Smart pin hardware acceleration with streamer DMA
  • Multi-File Handles: Up to 6 simultaneous file and directory handles (configurable)
  • Cross-OS Compatibility: Works with cards formatted on Windows, macOS, and Linux
  • SDHC/SDXC Support: Block-addressed cards tested up to 128GB (reformatted as FAT32)
  • CRC Validation: Hardware-accelerated CRC-16 on all data transfers
  • Directory Operations: Create, navigate, and enumerate directories (index-based and handle-based)
  • File Operations: Create, open, read, write, seek, rename, delete
  • Live Timestamps: setDate()/getDate() with 2-second auto-advance for file creation and modification stamps
  • Auto-Flush: Dirty handles flushed after 200ms idle — protects against card removal data loss
  • Non-Blocking Async I/O: Optional startReadHandle()/startWriteHandle() for overlapping computation with SD I/O (SD_INCLUDE_ASYNC)
  • Defragmentation: compactFile() relocates fragmented files into contiguous clusters; createFileContiguous() pre-allocates contiguous space (SD_INCLUDE_DEFRAG)
  • Built-in Card Formatter: Format any SD card as FAT32 directly from the P2 — no PC required
  • Filesystem Repair: Two tools sharing one four-pass engine — audit (read-only) and fsck (repairs)
  • Multi-Cog Safe: Dedicated worker cog with hardware lock serialization
  • Per-Cog Working Directory: Each cog maintains its own CWD for safe concurrent navigation
  • Regression Tested: 590 automated tests across 28 test suites, certified on two cluster geometries

Documentation

Document Description
Driver Tutorial Complete guide with practical examples — start here
Driver Theory of Operations Architecture, handle system, SPI engine, and internals
Error Handling Guide Detecting and responding to every error the driver reports
Migration Guide v1.7.0 Moving from v1.6.x
Driver Evolution v1.6.0–v1.7.0 Technical account of the defects fixed across three releases, and why the obvious guards missed them
Case Study: The Card That Would Not Start Full root-cause study of cards wedged by boot-time traffic on shared pins — evidence, the theories that were wrong, and the one-command fix
Case Study: What a Socket Costs How two microSD sockets on one board were measured against each other — the read and write phase maps that came out of it, and the driver defaults they changed
Card Performance SD card selection guide and ranked performance comparisons
Card Catalog All tested cards with register data and throughput
FAT32 API Concepts FAT32 background for embedded developers
Utilities Guide Standalone utility programs (format, audit, fsck, benchmark)
Utility Internals Theory of operations for each utility
Regression Testing Test infrastructure, 590 tests across 28 suites (as of v1.8.0)
Example Programs Compilable examples: read/write, data logger, directory walk, multi-cog
Demo Shell Full-featured terminal shell with card formatting, filesystem repair, file management, and benchmarking

Hardware Requirements

  • Parallax Propeller 2 (P2) microcontroller
  • P2 Edge Module (P2-EC or P2-EC32MB)
  • microSD Add-on Board (#64009) - provides the microSD card slot
  • microSD card (SDHC or SDXC — format with the included format utility or any OS formatter)

Default Pin Configuration (P2 Edge)

Signal Pin Description
CS (DAT3) P60 Chip Select
MOSI (CMD) P59 Master Out, Slave In
MISO (DAT0) P58 Master In, Slave Out
SCK (CLK) P61 Serial Clock

The microSD add-on board plugs into any P2 8-pin header group. See the Driver Tutorial for pin reassignment and a complete header group reference table.

Quick Start

OBJ
    sd : "micro_sd_fat32_fs"

CON
    SD_CS   = 60
    SD_MOSI = 59
    SD_MISO = 58
    SD_SCK  = 61

PUB main() | handle, buffer[128], bytes_read
    ' Mount the SD card
    if not sd.mount(SD_CS, SD_MOSI, SD_MISO, SD_SCK)
        debug("Mount failed!")
        return

    ' Read a file using handle-based API
    handle := sd.openFileRead(@"CONFIG.TXT")
    if handle >= 0
        bytes_read := sd.readHandle(handle, @buffer, 512)
        sd.closeFileHandle(handle)
        debug("Read ", udec(bytes_read), " bytes")

    ' Create and write a file
    handle := sd.createFileNew(@"OUTPUT.TXT")
    if handle >= 0
        sd.writeHandle(handle, @"Hello, P2!", 10)
        sd.closeFileHandle(handle)

    ' Unmount when done
    sd.unmount()

For multi-file operations, directory navigation, and the full API reference, see the Driver Tutorial.

Performance

Measured at 350 MHz sysclk with 25 MHz SPI, smart pin hardware acceleration, streamer DMA, and multi-sector commands (CMD18/CMD25):

Operation SanDisk Industrial 16GB Lexar Blue 128GB Amazon Basics 64GB Samsung PRO Endurance 128GB
File Read (256KB) 745 KB/s 1,444 KB/s 1,386 KB/s 1,419 KB/s
File Write (32KB) 321 KB/s 616 KB/s 774 KB/s 758 KB/s
Raw Multi-sector Read (32KB) 2,393 KB/s 2,420 KB/s 2,425 KB/s 2,427 KB/s
Raw Multi-sector Write (32KB) 2,170 KB/s 2,275 KB/s 2,305 KB/s 2,319 KB/s
Mount 486 ms 400 ms 233 ms 243 ms

Raw SPI efficiency reaches 80% of theoretical maximum (2,427 / 3,052 KB/s). Multi-sector commands provide 46-69% improvement over single-sector operations. 23 cards tested across 9 manufacturers — see Card Performance for ranked comparisons and card selection guidance.

Sysclk and performance: Both 350 MHz and 250 MHz sysclk produce the same 25 MHz SPI clock, but higher sysclk reduces Spin2 inter-transfer overhead between SPI bursts, yielding 10-20% better file throughput. For best performance, use _CLKFREQ = 350_000_000. See the Performance Guide for detailed analysis.

Socket timing: Two sockets wired to the same P2 can differ measurably in signal timing — on our bench, an external header-wired adapter adds a ~3 ns-class round-trip delay over the P2 Edge module's onboard socket. At the standard 25 MHz both carry wide margin, but a card that is itself timing-marginal may misbehave in one socket and work in the other. If you see socket-dependent card behavior, see Socket Timing Differences and the Receive Alignment and Socket Timing section of the Theory of Operations; the full characterization — how the two sockets were measured, the read and write phase maps, and the recipe for measuring your own board — is in Case Study: What a Socket Costs. Since v1.8.0 the read-path alignment sits at the centre of its measured passing band rather than the lower edge, which equalises read margin between sockets. The one socket-dependent failure we had under investigation turned out not to be a timing effect at all: it was a card left mid-transfer by the boot sequence on shared flash/microSD pins, and v1.8.0 fixes it at card initialisation. The full investigation is written up in Case Study: The Card That Would Not Start.

Project Structure

P2-uSD-FAT32-FS/
├── src/                        # Driver and application source
│   ├── micro_sd_fat32_fs.spin2     # The SD card driver
│   ├── isp_mem_strings.spin2       # String formatting (shared: demo shell + utilities)
│   ├── isp_stack_check.spin2       # Stack usage diagnostic
│   ├── UTILS/                      # Standalone utility programs
│   │   ├── SD_format_card.spin2           # FAT32 card formatter
│   │   ├── SD_card_identify.spin2         # Two-line card identification
│   │   ├── SD_card_characterize.spin2     # Card register reader (CID/CSD/SCR)
│   │   ├── SD_performance_benchmark.spin2 # Read/write throughput bench
│   │   ├── SD_FAT32_audit.spin2           # Filesystem validator (read-only)
│   │   ├── SD_FAT32_fsck.spin2            # Filesystem check & repair
│   │   ├── isp_format_utility.spin2       # FAT32 format library
│   │   ├── isp_fsck_utility.spin2         # Combined FSCK + Audit library
│   │   └── isp_string_fifo.spin2          # Inter-cog string FIFO
│   ├── EXAMPLES/                    # Compilable example programs
│   │   ├── SD_example_read_write.spin2    # Basic file read/write
│   │   ├── SD_example_data_logger.spin2   # Append-mode logging with sync
│   │   ├── SD_example_directory_walk.spin2 # Directory operations
│   │   └── SD_example_multicog.spin2      # Multi-cog concurrent access
│   ├── DEMO/                       # Interactive demo application
│   │   ├── SD_demo_shell.spin2        # Terminal shell (dir, cd, type, etc.)
│   │   └── isp_serial_singleton.spin2 # Serial terminal driver
│   └── regression-tests/          # Regression test suite (590 tests as of v1.8.0)
│       ├── SD_RT_*_tests.spin2        # 28 test files (mount, file ops, seek, fatchain, write integrity, async, defrag, etc.)
│       ├── isp_rt_utilities.spin2     # Shared test framework
│       └── TestCard/                  # Test card setup and validation
│
├── diagnostic-tests/           # Characterization & diagnostic tests
│   ├── SD_card_info_tests.spin2         # Struct-based register access
│   ├── SD_diag_fsck_window_test.spin2   # FSCK windowed bitmap diagnostic
│   ├── SD_freq_sweep_tests.spin2        # SPI frequency sweep (15-25 MHz)
│   └── SD_spi_limit_test.spin2          # Single SPI frequency probe
│
├── tools/                      # Build and test scripts
│   └── run_test.sh                 # Test runner (compile + download + capture)
│
├── DOCs/                       # Documentation
│   ├── SD-CARD-DRIVER-TUTORIAL.md   # Complete guide with examples
│   ├── SD-CARD-DRIVER-THEORY.md     # Architecture and driver internals
│   ├── SD-CARD-PERFORMANCE.md       # Card selection and performance rankings
│   ├── SD-CARD-UTILITIES.md            # Utility program documentation
│   ├── Analysis/                    # Design explorations and studies
│   ├── cards/                       # Per-card data sheets and catalog
│   ├── Decisions/                   # Architecture decision records
│   ├── Plans/                       # Active plans and punch list
│   ├── Reference/                   # Technical references and guides
│   ├── Research/                    # Hardware research and investigations
│   └── Utils/                       # Utility theory of operations

Known Limitations

  • 8.3 filenames only — no long filename (LFN) support
  • SDXC cards need reformatting — cards >32 GB ship as exFAT; use the included format utility (no PC needed)
  • SPI mode only — no SD native 4-bit bus mode
  • 25 MHz SPI by default — the SD specification's SPI-mode ceiling, and where the driver clamps. CMD6 High Speed mode does work on many cards (three of four modern cards retested negotiate it, reaching 43.75 MHz at 350 MHz sysclk, with sequential reads gaining up to 47%), but it is opt-in via attemptHighSpeed() and the driver never negotiates it automatically — write behaviour at that clock varies by card and is under investigation. See Key Observations.

Card Size Support

The driver's goal is full support for cards up to 2 TB (the FAT32 and SDXC maximum defined by the Microsoft FAT32 specification and SD Physical Layer Specification). Tested with cards up to 128 GB across 23 cards from 9 manufacturers.

The FSCK utility provides full cluster-chain validation on cards of any size. For cards exceeding approximately 64 GB, a windowed bitmap approach processes the cluster space in 2M-cluster passes, extending full 4-pass validation (chain integrity, cross-link detection, lost cluster recovery, FAT sync) to any card.

Right-size your card. Larger cards mean larger FAT tables, longer mount times, and longer FSCK scans. Choose the smallest card that comfortably meets your storage needs. For most embedded applications, 8–32 GB provides ample capacity with the best overall performance. See the Card Performance Guide for details.


Why FAT32?

Our storage subsystem uses FAT32 rather than exFAT to avoid the patent and licensing constraints that still apply to exFAT in commercial products. exFAT remains covered by Microsoft intellectual property, and compliant implementations are generally expected to be licensed, which can add cost, legal complexity, and contractual obligations that are disproportionate for many embedded systems. In contrast, the relevant FAT patents (including those covering long filenames) have expired, so a clean-room FAT32 implementation can be shipped royalty-free, making it a safer and more predictable choice from an IP and compliance standpoint.

Technically, FAT32 also remains the most broadly compatible filesystem for removable media in the embedded space. It is supported by virtually all major desktop and mobile operating systems, works out of the box with common SD and microSD cards up to 32 GB, and has a relatively small code and RAM footprint -- important advantages on microcontrollers. By standardizing on FAT32, our driver delivers simple integration, excellent cross-platform interoperability, and a clear legal posture, which together make it a practical and low-risk foundation for products that need removable storage without the overhead of exFAT licensing.


Credits

  • Original Driver Concept: Chris Gadd (OB4269 from Parallax OBEX)
  • Driver Development: Stephen M. Moraco, Iron Sheep Productions

License

MIT License - See LICENSE for details.


Part of the Iron Sheep Productions Propeller 2 Projects Collection

About

Chris Gadd's SD Driver updated for OS Interchange and write failure protection and now certified high performance use with uSD on P2 Edge Modules and P2 microSD Add-on Board #64009

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Contributors

Languages