mirror of
https://github.com/markqvist/RNode_Firmware.git
synced 2026-04-27 22:35:36 +00:00
SharedSPI.h: FreeRTOS mutex protecting the shared SPI bus (pins 33/34/35) used by LoRa (SX1262), SD card, and future NFC. sx126x.cpp: All 6 SPI transaction blocks wrapped with shared_spi_mutex acquire/release. LoRa uses portMAX_DELAY (always gets access, just delayed by SD if needed). USBSD.h: USB MSC SD card access uses shared_spi_mutex with 200ms timeout. Deferred init (3s after boot) for SPI bus readiness. Metrics: sd_ready, sd_reads, sd_fails counters. IMULogger.h, Gui.h: SD card writes wrapped in shared_spi_mutex. Status: SD card correctly reports 29.7GB via USB MSC. Reads work intermittently (~50% success). Root cause: main loop takes ~700ms per iteration, causing mutex timeout for MSC callbacks. Needs loop time investigation to achieve reliable USB mass storage. The CO5300 display uses a separate SPI3 bus — not affected.
92 lines
2.7 KiB
C
92 lines
2.7 KiB
C
// USB Mass Storage — exposes SD card via USB alongside CDC serial
|
|
// Requires USBMode=default (TinyUSB) in the FQBN build flags.
|
|
// Uses shared_spi_mutex from SharedSPI.h to coordinate with LoRa radio.
|
|
|
|
#ifndef USBSD_H
|
|
#define USBSD_H
|
|
|
|
#if BOARD_MODEL == BOARD_TWATCH_ULT && HAS_SD && !ARDUINO_USB_MODE
|
|
|
|
#include "USB.h"
|
|
#include "USBMSC.h"
|
|
#include <SD.h>
|
|
#include "SharedSPI.h"
|
|
|
|
static USBMSC usb_msc;
|
|
bool usb_sd_ready = false;
|
|
|
|
uint32_t usb_sd_read_count = 0;
|
|
uint32_t usb_sd_read_fail = 0;
|
|
|
|
static int32_t usb_sd_read(uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize) {
|
|
if (!usb_sd_ready) { usb_sd_read_fail++; return -1; }
|
|
if (xSemaphoreTake(shared_spi_mutex, pdMS_TO_TICKS(500)) != pdTRUE) {
|
|
usb_sd_read_fail++;
|
|
return -1;
|
|
}
|
|
int32_t result = bufsize;
|
|
uint32_t sec = lba + (offset / 512);
|
|
uint32_t cnt = bufsize / 512;
|
|
for (uint32_t i = 0; i < cnt; i++) {
|
|
if (!SD.readRAW((uint8_t *)buffer + i * 512, sec + i)) {
|
|
usb_sd_read_fail++;
|
|
result = -1;
|
|
break;
|
|
}
|
|
}
|
|
xSemaphoreGive(shared_spi_mutex);
|
|
usb_sd_read_count++;
|
|
return result;
|
|
}
|
|
|
|
static int32_t usb_sd_write(uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) {
|
|
if (!usb_sd_ready) return -1;
|
|
if (xSemaphoreTake(shared_spi_mutex, pdMS_TO_TICKS(200)) != pdTRUE) return -1;
|
|
int32_t result = bufsize;
|
|
uint32_t sec = lba + (offset / 512);
|
|
uint32_t cnt = bufsize / 512;
|
|
for (uint32_t i = 0; i < cnt; i++) {
|
|
if (!SD.writeRAW(buffer + i * 512, sec + i)) { result = -1; break; }
|
|
}
|
|
xSemaphoreGive(shared_spi_mutex);
|
|
return result;
|
|
}
|
|
|
|
static bool usb_sd_start_stop(uint8_t power_condition, bool start, bool load_eject) {
|
|
return true;
|
|
}
|
|
|
|
bool usb_sd_init() {
|
|
usb_msc.vendorID("RNode");
|
|
usb_msc.productID("R-Watch SD");
|
|
usb_msc.productRevision("1.0");
|
|
usb_msc.onRead(usb_sd_read);
|
|
usb_msc.onWrite(usb_sd_write);
|
|
usb_msc.onStartStop(usb_sd_start_stop);
|
|
|
|
// Init SD card — acquire mutex since LoRa may already be using the bus
|
|
if (shared_spi_mutex) xSemaphoreTake(shared_spi_mutex, portMAX_DELAY);
|
|
SPI.begin(SD_CLK, SD_MISO, SD_MOSI, SD_CS);
|
|
bool ok = SD.begin(SD_CS, SPI, 4000000, "/sd", 5);
|
|
uint32_t sectors = 0;
|
|
uint16_t secsize = 512;
|
|
if (ok) {
|
|
sectors = SD.numSectors();
|
|
secsize = SD.sectorSize();
|
|
}
|
|
if (shared_spi_mutex) xSemaphoreGive(shared_spi_mutex);
|
|
|
|
if (!ok || sectors == 0) {
|
|
usb_msc.mediaPresent(false);
|
|
usb_msc.begin(0, 512);
|
|
return false;
|
|
}
|
|
|
|
usb_msc.mediaPresent(true);
|
|
usb_msc.begin(sectors, secsize);
|
|
usb_sd_ready = true;
|
|
return true;
|
|
}
|
|
|
|
#endif
|
|
#endif
|