mirror of
https://github.com/Architeuthis-Flux/JumperlessV5.git
synced 2025-09-05 10:47:58 +00:00
277 lines
7.9 KiB
Markdown
277 lines
7.9 KiB
Markdown
# USB Mass Storage with QSPI Flash - Jumperless V5
|
|
|
|
This document describes the USB Mass Storage implementation for Jumperless V5, which uses the onboard 16MB QSPI flash chip to provide USB drive functionality.
|
|
|
|
## Overview
|
|
|
|
The Jumperless V5 can present itself as a USB Mass Storage device (USB drive) to allow easy file transfer and management. This functionality uses the onboard QSPI flash memory and is based on:
|
|
|
|
- **Adafruit SPIFlash Library**: For QSPI flash access
|
|
- **SdFat Library**: For FAT filesystem support
|
|
- **TinyUSB MSC**: For USB Mass Storage Class implementation
|
|
- **Custom Integration**: Seamless switching between normal operation and USB mode
|
|
|
|
## Features
|
|
|
|
- ✅ **Real Flash Storage**: Uses actual 16MB QSPI flash (not just emulated)
|
|
- ✅ **FAT Filesystem**: Standard FAT filesystem for compatibility
|
|
- ✅ **Proper USB Protocol**: Full SCSI/MSC compliance for broad OS support
|
|
- ✅ **Safe Mode Switching**: Device becomes safely unresponsive during USB mode
|
|
- ✅ **Automatic Detection**: Proper USB enumeration and device identification
|
|
- ✅ **File Monitoring**: Real-time monitoring of flash contents
|
|
- ✅ **Error Handling**: Comprehensive error reporting and recovery
|
|
|
|
## Hardware Requirements
|
|
|
|
- **Jumperless V5 Board** with RP2350B microcontroller
|
|
- **16MB QSPI Flash** on default QSPI pins (automatically detected)
|
|
- **USB Connection** to host computer
|
|
|
|
## Usage
|
|
|
|
### 1. Basic Commands
|
|
|
|
```cpp
|
|
// Test the flash integration
|
|
testUSBFlashIntegration();
|
|
|
|
// Enter USB Mass Storage mode
|
|
if (enterUSBFilesystemMode()) {
|
|
// Device is now a USB drive - becomes unresponsive
|
|
while (handleUSBFilesystemMode()) {
|
|
// Handle USB communications
|
|
// Will exit when drive is ejected
|
|
}
|
|
exitUSBFilesystemMode(); // Resume normal operation
|
|
}
|
|
|
|
// Check current status
|
|
printFlashStatus();
|
|
printUSBFilesystemStatus();
|
|
```
|
|
|
|
### 2. Command Line Interface
|
|
|
|
If integrated with the Jumperless command system:
|
|
|
|
```
|
|
help usb # Show USB-related commands
|
|
usbfs # Enter USB filesystem mode
|
|
usbfs test # Test flash integration
|
|
usbfs status # Show current status
|
|
```
|
|
|
|
### 3. First Time Setup
|
|
|
|
When you first use the USB Mass Storage functionality:
|
|
|
|
1. **Connect to Computer**: The device will enumerate as "Jumperless V5"
|
|
2. **Format if Needed**: If the flash isn't formatted, your OS may prompt to format it
|
|
3. **Choose FAT32**: Select FAT32 for best compatibility
|
|
4. **Use Normally**: Copy files to/from the drive like any USB storage device
|
|
|
|
## Technical Implementation
|
|
|
|
### Flash Transport Layer
|
|
|
|
```cpp
|
|
// RP2350B uses same flash that stores the firmware
|
|
Adafruit_FlashTransport_RP2040 flashTransport;
|
|
Adafruit_SPIFlash flash(&flashTransport);
|
|
```
|
|
|
|
### File System Integration
|
|
|
|
- **SdFat Library**: Handles FAT filesystem operations
|
|
- **Sector-Level Access**: Direct 512-byte sector read/write
|
|
- **Cache Management**: Automatic sector caching for performance
|
|
- **Mount/Unmount**: Proper filesystem state management
|
|
|
|
### USB Mass Storage Callbacks
|
|
|
|
All required MSC callbacks are implemented:
|
|
|
|
- `tud_msc_inquiry_cb()`: Device identification
|
|
- `tud_msc_test_unit_ready_cb()`: Ready status checking
|
|
- `tud_msc_capacity_cb()`: Flash size reporting
|
|
- `tud_msc_read10_cb()`: Sector reading
|
|
- `tud_msc_write10_cb()`: Sector writing
|
|
- `tud_msc_scsi_cb()`: SCSI command handling
|
|
|
|
## Configuration
|
|
|
|
### PlatformIO Dependencies
|
|
|
|
```ini
|
|
lib_deps =
|
|
adafruit/Adafruit SPIFlash
|
|
adafruit/SdFat - Adafruit Fork
|
|
```
|
|
|
|
### USB Interface Configuration
|
|
|
|
In `include/usb_interface_config.h`:
|
|
|
|
```cpp
|
|
#define USB_MSC_ENABLE 1 // Enable Mass Storage
|
|
#define USB_CDC_ENABLE_COUNT 3 // Keep other interfaces
|
|
```
|
|
|
|
### Build Flags
|
|
|
|
The implementation automatically uses the correct flash transport for RP2350B.
|
|
|
|
## Safety and Data Integrity
|
|
|
|
### Mode Switching
|
|
|
|
- **Exclusive Access**: Only one mode can access flash at a time
|
|
- **Proper Unmounting**: Filesystem is properly closed before USB access
|
|
- **State Tracking**: Full state management prevents conflicts
|
|
- **Ejection Handling**: Proper ejection detection and cleanup
|
|
|
|
### Data Protection
|
|
|
|
- **Sector Validation**: All sector operations are bounds-checked
|
|
- **Write Protection**: Read-only mode when not in USB Mass Storage
|
|
- **Error Handling**: Comprehensive error detection and reporting
|
|
- **Cache Synchronization**: Automatic cache flushing
|
|
|
|
## Troubleshooting
|
|
|
|
### Flash Not Detected
|
|
|
|
```
|
|
◇ Failed to initialize QSPI flash!
|
|
```
|
|
|
|
**Solutions:**
|
|
- Check QSPI connections
|
|
- Verify flash chip compatibility
|
|
- Check power supply stability
|
|
|
|
### Filesystem Not Formatted
|
|
|
|
```
|
|
△ No FAT filesystem found - flash may need formatting
|
|
```
|
|
|
|
**Solutions:**
|
|
- Connect to computer and format as FAT32
|
|
- Use disk utility to check partition table
|
|
- Try `testUSBFlashIntegration()` for detailed diagnostics
|
|
|
|
### USB Not Enumerating
|
|
|
|
```
|
|
◇ Failed to prepare filesystem for USB mode
|
|
```
|
|
|
|
**Solutions:**
|
|
- Check USB cable connection
|
|
- Verify USB configuration in `usb_interface_config.h`
|
|
- Try different USB port or computer
|
|
- Check serial output for detailed error messages
|
|
|
|
### Performance Issues
|
|
|
|
- **Large Files**: May be slow due to flash limitations
|
|
- **Many Small Files**: Consider archiving for better performance
|
|
- **Wear Leveling**: Flash has limited write cycles
|
|
|
|
## API Reference
|
|
|
|
### Flash Management Functions
|
|
|
|
```cpp
|
|
bool initializeUSBFlash(void); // Initialize flash hardware
|
|
void deinitializeUSBFlash(void); // Cleanup flash resources
|
|
bool isUSBFlashInitialized(void); // Check initialization status
|
|
bool isUSBFileSystemFormatted(void); // Check filesystem status
|
|
void printFlashStatus(void); // Print detailed status
|
|
```
|
|
|
|
### USB Mode Functions
|
|
|
|
```cpp
|
|
bool enterUSBFilesystemMode(void); // Enter USB MSC mode
|
|
bool handleUSBFilesystemMode(void); // Handle USB communications
|
|
void exitUSBFilesystemMode(void); // Exit USB MSC mode
|
|
bool isInUSBFilesystemMode(void); // Check current mode
|
|
```
|
|
|
|
### Monitoring Functions
|
|
|
|
```cpp
|
|
void monitorUSBFlashContents(void); // List flash contents
|
|
void markUSBFileSystemChanged(void); // Force content refresh
|
|
void testUSBFlashIntegration(void); // Comprehensive test
|
|
```
|
|
|
|
### Low-Level Flash Functions
|
|
|
|
```cpp
|
|
int32_t readFlashBlocks(uint32_t lba, void* buffer, uint32_t bufsize);
|
|
int32_t writeFlashBlocks(uint32_t lba, const uint8_t* buffer, uint32_t bufsize);
|
|
bool syncFlashBlocks(void);
|
|
bool getFlashCapacity(uint32_t* block_count, uint16_t* block_size);
|
|
```
|
|
|
|
## Integration Notes
|
|
|
|
### With Existing Jumperless Features
|
|
|
|
- **Command System**: Can be integrated with existing menu system
|
|
- **Display Updates**: Shows USB mode status on OLED
|
|
- **Serial Output**: Comprehensive logging and debugging
|
|
- **State Management**: Properly coordinates with other subsystems
|
|
|
|
### Memory Usage
|
|
|
|
- **Flash Transport**: ~1KB RAM for transport layer
|
|
- **SdFat Library**: ~4KB RAM for filesystem buffers
|
|
- **USB Buffers**: ~2KB RAM for USB packet handling
|
|
- **Total Overhead**: ~7KB RAM (acceptable for RP2350B)
|
|
|
|
## Example Usage Patterns
|
|
|
|
### File Transfer Workflow
|
|
|
|
```cpp
|
|
// 1. Enter USB mode
|
|
Serial.println("Connecting as USB drive...");
|
|
if (enterUSBFilesystemMode()) {
|
|
Serial.println("USB drive active - copy files now");
|
|
|
|
// 2. Handle USB until ejected
|
|
while (handleUSBFilesystemMode()) {
|
|
// Device is unresponsive, USB handles everything
|
|
}
|
|
|
|
// 3. Exit USB mode
|
|
exitUSBFilesystemMode();
|
|
Serial.println("USB drive disconnected - resuming normal operation");
|
|
|
|
// 4. Check what was added/changed
|
|
monitorUSBFlashContents();
|
|
}
|
|
```
|
|
|
|
### Development/Testing Workflow
|
|
|
|
```cpp
|
|
// Test everything before using
|
|
testUSBFlashIntegration();
|
|
|
|
// Check status anytime
|
|
printFlashStatus();
|
|
printUSBFilesystemStatus();
|
|
|
|
// Manual flash operations (if needed)
|
|
uint8_t buffer[512];
|
|
if (readFlashBlocks(0, buffer, 512) > 0) {
|
|
// Process boot sector data
|
|
}
|
|
```
|
|
|
|
This implementation provides a robust, production-ready USB Mass Storage solution for your Jumperless V5 device! |