How to put a file to extern Flash?

Mike0675

Member
Hi, I´m using Teensy4.1 with Mongoose.ws, which works very nice by now.
Now I want to put a FAVICON in my soldered FLASH and serve it to the Webserver.

But this is the second step - first I have to put this Icon on FLASH.
How can it be done?
 
I really wish the MTP support libraries would get folded into the Teensy base.

You need to download KurtE or WMXZ's MTP support libraries from:

Then you need to build your Teensy sketch with either MTP (experimental) or MTP + serial (experimental) set. The app then runs in MTP mode, and you can access the files from your system's file explorer.

Here is a modification of the example programs that I use, with the WMXZ-EU/MTP_t4 library:

<edit>
I replaced the program with the variant that will enable both NOR (16MB) and NAND (128MB) at the same time, and also checked if pin 6 has SPI flash attached (i.e. the flash memory that can be soldered to the audio adapter board or the memory available on the prop shield).
</edit>

Code:
// From /shared/arduino/git/MTP_t4.git/trunk/examples/mtp-basic/mtp-basic.ino

#include <SPI.h>
#include <SD.h>
#include <MTP.h>

#if defined(ARDUINO_TEENSY41)
// The Teensy 4.1 has two sets of solder pads underneath the Teensy that you
// can solder either 2 PSram chips, 1 flash memory chip, or 1 flash memory chip
// and a PSram chip.  The smaller flash chips tend to use NOR flash while the
// larger flash chips tend to use NAND flash.
#define USE_LFS_RAM                     1       // T4.1 PSRAM (or RAM)
#define USE_LFS_QSPI_NOR                1       // T4.1 QSPI NOR flash (16MB)
#define USE_LFS_QSPI_NAND               1       // T4.1 QSPI NAND flash (128MB)

#else
#define USE_LFS_RAM                     0       // T4.1 PSRAM (or RAM)
#define USE_LFS_QSPI_NOR                0       // T4.1 QSPI NOR flash (16MB)
#define USE_LFS_QSPI_NAND               0       // T4.1 QSPI NAND flash (128MB)
#endif

#if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41)
// Teensy 4.0 and 4.1 can use the upper flash memory as a file system via
// LittleFS.  The top bytes (64K for Teensy 4.0 and 256K for Teensy 4.1) of
// this memory is reserved for EEPROM emulation and the LED blink restore
// program.  On the Teensy 4.0 you have 1 megabyte - 64K of flash for a
// filesystem.  On the Teensy 4.1, you have 7 megabytes - 256K of flash for the
// filesystem.
#define USE_LFS_PROGM                   1       // T4.0/T4.1 Progam Flash
#else
#define USE_LFS_PROGM                   0       // T4.0/T4.1 Progam Flash
#endif

#define USE_SD                          1       // Use either the built-in micro SD card reader or the reader on pin 10 (audio adapter)
#define USE_LFS_SPI                     1       // SPI Flash (soldered to the audio adapter or the built-in flash on the prop shield)

// If you use the audio adapter revision A through C on a Teensy LC, 3.2, 3.5,
// or 3.6, it needs to remap the MOSI/SCK pins because those pins (11 and 13)
// are also I2S pins used by the audio shield.  But the prop shield wants to
// use the normal definitions.  In general, I've used the prop shield mostly on
// the Teensy 3.2 and LC, while if I use it, I use the audio shield on the
// Teensy 3.5 or Teensy 3.6.
//
// The Teensy 4.0 and 4.1 uses the audio adapter revision D, and it uses the
// standard SPI pins.
#if defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36)
#define USE_TEENSY3_AUDIO_SHIELD        1       // Whether to use the Audio shield MOSI/SCLK for Teensy 3.x processors
#else
#define USE_TEENSY3_AUDIO_SHIELD        0       // Use standard configuration
#endif

#if USE_EVENTS==1
  extern "C" int usb_init_events(void);
#else
  int usb_init_events(void) {}
#endif

#if USE_LFS_RAM==1 ||  USE_LFS_PROGM==1 || USE_LFS_QSPI_NOR==1 || USE_LFS_QSPI_NAND==1 || USE_LFS_SPI==1
  #include "LittleFS.h"
#endif

#if defined(__IMXRT1062__)
  // following only as long usb_mtp is not included in cores
  #if !__has_include("usb_mtp.h")
    #include "usb1_mtp.h"
  #endif
#else
  #ifndef BUILTIN_SDCARD
    #define BUILTIN_SDCARD 254
  #endif
  void usb_mtp_configure(void) {}
#endif


/****  Start device specific change area  ****/
// SDClasses
#if USE_SD==1
  // edit SPI to reflect your configuration
#if USE_TEENSY3_AUDIO_SHIELD
 // Teensy audio adapter for Teensy 3.2, 3.5, and 3.6 (revision A-C) needs to remap the MOSI and SCK pins
  #define SD_MOSI  7
  #define SD_MISO 12
  #define SD_SCK  14
#else
 // Standard Teensy configuration
  #define SD_MOSI 11
  #define SD_MISO 12
  #define SD_SCK  13
#endif

  #define SPI_SPEED SD_SCK_MHZ(33)                              // adjust to sd card

  #if defined (BUILTIN_SDCARD)
    const char *sd_str[]={"BUILTIN-SD", "AUDIO-SD"};            // edit to reflect your configuration
    const int cs[] = {BUILTIN_SDCARD, 10};                      // edit to reflect your configuration
  #else
    const char *sd_str[]={"AUDIO-SD"};                          // edit to reflect your configuration
    const int cs[] = {10};                                      // edit to reflect your configuration
  #endif
  const int nsd = sizeof(sd_str)/sizeof(const char *);

SDClass sdx[nsd];
#endif

//LittleFS classes
#if USE_LFS_RAM==1
  const char *lfs_ram_str[]     = {"RAM1","RAM2"};              // edit to reflect your configuration
  const int lfs_ram_size[]      = {2'000'000, 4'000'000};       // edit to reflect your configuration
  const int nfs_ram             = sizeof(lfs_ram_str)/sizeof(const char *);

  LittleFS_RAM ramfs[nfs_ram];
#endif

#if USE_LFS_QSPI_NOR==1
  const char *lfs_qspi_nor_str[]        = {"QSPI-NOR"};         // edit to reflect your configuration
  const int nfs_qspi_nor                = sizeof(lfs_qspi_nor_str)/sizeof(const char *);

  LittleFS_QSPIFlash qspifs_nor[nfs_qspi_nor];
#endif

#if USE_LFS_QSPI_NAND==1
  const char *lfs_qspi_nand_str[]       = {"QSPI-NAND"};        // edit to reflect your configuration
  const int nfs_qspi_nand               = sizeof(lfs_qspi_nand_str)/sizeof(const char *);

  LittleFS_QPINAND qspifs_nand[nfs_qspi_nand];
#endif

#if USE_LFS_PROGM==1
  const char *lfs_progm_str[]={"PROGRAM"};                      // edit to reflect your configuration
  const int lfs_progm_size[] = {1'000'000};                     // edit to reflect your configuration
  const int nfs_progm = sizeof(lfs_progm_str)/sizeof(const char *);

  LittleFS_Program progmfs[nfs_progm];
#endif

#if USE_LFS_SPI==1
  const char *lfs_spi_str[]={"SPI-FLASH"};                      // edit to reflect your configuration
  const int lfs_cs[] = {6};                                     // edit to reflect your configuration
  const int nfs_spi = sizeof(lfs_spi_str)/sizeof(const char *);

LittleFS_SPIFlash spifs[nfs_spi];
#endif


MTPStorage_SD storage;
MTPD    mtpd(&storage);

void storage_configure()
{
  #if USE_SD==1
    #if defined SD_SCK
      SPI.setMOSI(SD_MOSI);
      SPI.setMISO(SD_MISO);
      SPI.setSCK(SD_SCK);
    #endif

    for(int ii=0; ii<nsd; ii++)
    {
      #if defined(BUILTIN_SDCARD)
        if(cs[ii] == BUILTIN_SDCARD)
        {
          if(!sdx[ii].sdfs.begin(SdioConfig(FIFO_SDIO)))
          { Serial.printf("SDIO Storage %d %d %s failed or missing",ii,cs[ii],sd_str[ii]);  Serial.println();
          }
          else
          {
            storage.addFilesystem(sdx[ii], sd_str[ii]);
            uint64_t totalSize = sdx[ii].totalSize();
            uint64_t usedSize  = sdx[ii].usedSize();
            Serial.printf("SDIO Storage %d %d %s ",ii,cs[ii],sd_str[ii]);
            Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
          }
        }
        else if(cs[ii]<BUILTIN_SDCARD)
      #endif
      {
        pinMode(cs[ii],OUTPUT); digitalWriteFast(cs[ii],HIGH);
        if(!sdx[ii].sdfs.begin(SdSpiConfig(cs[ii], SHARED_SPI, SPI_SPEED)))
        { Serial.printf("SD Storage %d %d %s failed or missing",ii,cs[ii],sd_str[ii]);  Serial.println();
        }
        else
        {
          storage.addFilesystem(sdx[ii], sd_str[ii]);
          uint64_t totalSize = sdx[ii].totalSize();
          uint64_t usedSize  = sdx[ii].usedSize();
          Serial.printf("SD Storage %d %d %s ",ii,cs[ii],sd_str[ii]);
          Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
        }
      }
    }
    #endif

    #if USE_LFS_RAM==1
    for(int ii=0; ii<nfs_ram;ii++)
    {
      if(!ramfs[ii].begin(lfs_ram_size[ii]))
      { Serial.printf("Ram Storage %d %s failed or missing",ii,lfs_ram_str[ii]); Serial.println();
      }
      else
      {
        storage.addFilesystem(ramfs[ii], lfs_ram_str[ii]);
        uint64_t totalSize = ramfs[ii].totalSize();
        uint64_t usedSize  = ramfs[ii].usedSize();
        Serial.printf("RAM Storage %d %s ",ii,lfs_ram_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
      }
    }
    #endif

    #if USE_LFS_PROGM==1
    for(int ii=0; ii<nfs_progm;ii++)
    {
      if(!progmfs[ii].begin(lfs_progm_size[ii]))
      { Serial.printf("Program Storage %d %s failed or missing",ii,lfs_progm_str[ii]); Serial.println();
      }
      else
      {
        storage.addFilesystem(progmfs[ii], lfs_progm_str[ii]);
        uint64_t totalSize = progmfs[ii].totalSize();
        uint64_t usedSize  = progmfs[ii].usedSize();
        Serial.printf("Program Storage %d %s ",ii,lfs_progm_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
      }
    }
    #endif

    #if USE_LFS_QSPI_NOR==1
    for(int ii=0; ii<nfs_qspi_nor;ii++)
    {
      if(!qspifs_nor[ii].begin())
      { Serial.printf("QSPI Storage %d %s failed or missing",ii,lfs_qspi_nor_str[ii]); Serial.println();
      }
      else
      {
        storage.addFilesystem(qspifs_nor[ii], lfs_qspi_nor_str[ii]);
        uint64_t totalSize = qspifs_nor[ii].totalSize();
        uint64_t usedSize  = qspifs_nor[ii].usedSize();
        Serial.printf("QSPI NOR Storage %d %s ",ii,lfs_qspi_nor_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
      }
    }
    #endif

    #if USE_LFS_QSPI_NAND==1
    for(int ii=0; ii<nfs_qspi_nand;ii++)
    {
      if(!qspifs_nand[ii].begin())
      { Serial.printf("QSPI Storage %d %s failed or missing",ii,lfs_qspi_nand_str[ii]); Serial.println();
      }
      else
      {
        storage.addFilesystem(qspifs_nand[ii], lfs_qspi_nand_str[ii]);
        uint64_t totalSize = qspifs_nand[ii].totalSize();
        uint64_t usedSize  = qspifs_nand[ii].usedSize();
        Serial.printf("QSPI NAND Storage %d %s ",ii,lfs_qspi_nand_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
      }
    }
    #endif

    #if USE_LFS_SPI==1
    for(int ii=0; ii<nfs_spi;ii++)
    {
      if(!spifs[ii].begin(lfs_cs[ii]))
      { Serial.printf("SPIFlash Storage %d %d %s failed or missing",ii,lfs_cs[ii],lfs_spi_str[ii]); Serial.println();
      }
      else
      {
        storage.addFilesystem(spifs[ii], lfs_spi_str[ii]);
        uint64_t totalSize = spifs[ii].totalSize();
        uint64_t usedSize  = spifs[ii].usedSize();
        Serial.printf("SPIFlash Storage %d %d %s ",ii,lfs_cs[ii],lfs_spi_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
      }
    }
    #endif
}

void setup()
{
  while (!Serial && millis () < 3000)
    ;

  Serial.println("MTP_test");
  Serial.printf ("USE_LFS_RAM              = %d\n", USE_LFS_RAM);
  Serial.printf ("USE_LFS_QSPI_NOR         = %d\n", USE_LFS_QSPI_NOR);
  Serial.printf ("USE_LFS_QSPI_NAND        = %d\n", USE_LFS_QSPI_NAND);
  Serial.printf ("USE_LFS_PROGM            = %d\n", USE_LFS_PROGM);
  Serial.printf ("USE_SD                   = %d\n", USE_SD);
  Serial.printf ("USE_LFS_SPI              = %d\n", USE_LFS_SPI);
  Serial.printf ("USE_TEENSY3_AUDIO_SHIELD = %d\n", USE_TEENSY3_AUDIO_SHIELD);
  Serial.println ("");

  #if USE_EVENTS==1
    usb_init_events();
  #endif

  #if !__has_include("usb_mtp.h")
    usb_mtp_configure();
  #endif
  storage_configure();

}

void loop()
{
  mtpd.loop();

#if USE_EVENTS==1
  if(Serial.available())
  {
    char ch=Serial.read();
    Serial.println(ch);
    if(ch=='r')
    {
      Serial.println("Reset");
      mtpd.send_DeviceResetEvent();
    }
  }
#endif
}
 
Last edited:
Back
Top