arduino / ArduinoCore-mbed

345 stars 199 forks source link

QSPIFBlockDevice.h: No such file or directory (re Raspberry Pi Pico) #489

Closed Gerriko closed 2 years ago

Gerriko commented 2 years ago

Using mbed_rp2040/3.1.1

Board Variant: Raspberry Pi Pico

Have included the following libraries in my test example code (based off the AccessFlashAsUSBDisk example):

#include "PluggableUSBMSD.h"
#include "QSPIFBlockDevice.h"
#include "MBRBlockDevice.h"
#include "FATFileSystem.h"

When compiling I get the following response:

Alternatives for QSPIFBlockDevice.h: []
ResolveLibrary(QSPIFBlockDevice.h)
  -> candidates: []
AccessFlashAsUSBDisk:10:10: fatal error: QSPIFBlockDevice.h: No such file or directory
 #include "QSPIFBlockDevice.h"
          ^~~~~~~~~~~~~~~~~~~~
compilation terminated.

Searching through the previous issues, I assume the fix will be similar to the one given in @facchinm response & clarifications. Issue number: https://github.com/arduino/ArduinoCore-mbed/issues/377

If so, please could someone confirm, especially with regard to macros (e.g. I assume NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS should not be included as nRF52840 specific) and pin numbers. Maybe some sort of guidance/instruction could be added to documentation and/or in the examples.

facchinm commented 2 years ago

Hi @Gerriko , on RP2040 based boards the QSPI flash is also the "system" flash, so it's not recommended to access it bypassing the internal flash APIs. For this reason, QSPIFBlockDevice is not available for this platform, but you can safely use FlashIAPBlockDevice as demonstrated in this example https://github.com/arduino/ArduinoCore-mbed/blob/master/libraries/MLC/examples/RP2040_DataLogger_FIFO/RP2040_DataLogger_FIFO.ino#L45 .

Let me know if you have any issue with this approach!

Gerriko commented 2 years ago

@facchinm Thanks, I will try this out. BTW, I did wonder why I hadn't noticed this library before for Pico so I checked the library.properties file and noticed that the architectures attribute is missing mbed_rp2040 (it has architectures=mbed,mbed_nano,mbed_nicla). Also within the mbed_rp2040/3.1.1/libraries folder there is the USBMSD folder, which is where I got the example from.... based on your comment, maybe this needs amending or removing.

facchinm commented 2 years ago

It may be worth amending USBMSD examples (since the library is perfectly supported on RP2040 "plain"). MLC library only applies to boards with ST 6 axis accelerometer onboard, so the fact that it's missing from mbed_rp2040 is correct.

Gerriko commented 2 years ago

This works great thanks. Here's a simple example - not sure if MassStorage.process(); is really required... I noticed it's used in MbedOS examples:

#include "PluggableUSBMSD.h"
#include "FlashIAPBlockDevice.h"

static FlashIAPBlockDevice bd(XIP_BASE + 0x100000, 0x100000);
USBMSD MassStorage(&bd);

static FILE *f = nullptr;
// Note that file is written to the actual root directory as created when USBMSD is mounted
// File is not stored within a folder called root.
// File is only found when you remove usb and replace again
const char *fname = "/root/myfile.txt";

void USBMSD::begin()
{
  int err = getFileSystem().mount(&bd);
  if (err) {
   Serial.println(" filesystem mount failed\ntry to reformat device...");
    err = getFileSystem().reformat(&bd);
  }
  if (err) {
    Serial.println("Error: Unable to format/mount the device.");
    while(1);
  }
}

mbed::FATFileSystem &USBMSD::getFileSystem()
{
  static mbed::FATFileSystem fs("root");
  return fs;
}

void writeContents() {
    f = fopen(fname, "w+");
    if (f != nullptr) {
      fprintf(f, "Hello World\n");
      fflush(f);      
      fclose(f);
      Serial.println("Written to File");
    }
    else {
      Serial.println("File not found");
    }  
}

void readContents() {
    f = fopen(fname, "r");
    if (f != nullptr) {
      fclose(f);
      Serial.println("File found");
    }
    else {
      Serial.println("File not found");
    }  
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  MassStorage.begin();
  // If you do not want to wait for Serial Monitor to load then use a long delay here.
  // Found a delay helps if you want to capture the initial serial output.
  //while(!Serial) {;;}
  delay(1000);
  Serial.println("MassStorage mounted");
  writeContents();
  //readContents();

}

void loop() {
  // put your main code here, to run repeatedly:
  MassStorage.process();
}
facchinm commented 2 years ago

MassStorage.process() is already being called in the background by an helper thread so there's no need to call it explicitly (it doesn't hurt anyway, just losing some cycles). Glad it worked! :wink: