Teensy 4.1 microSD socket type

domingo

Well-known member
Hi everyone,
I just realised that the latest T4.1 comes with a new SD card socket, as mentioned for example here.
Is the newer socket of the push-pull type, like the old one? Or is it perhaps (hopefully) pull-pull?

I'd like to use the board inside a thick enclosure and a pull-pull socket would be ideal. The push-pull system would make it very difficult to remove the card with short nails and I'm afraid it could fall out accidentally.

Cheers,
Domingo
 
The newer SD socket (with 8 tiny holes where you can see the metal contacts) is the same push-pull type as the older SD socket (without tiny holes).

SD sockets with push-push action have a spring inside. Usually they are at least 2mm wider to make room for the spring mechanism. That sort of wider socket can't possibly fit onto Teensy 4.1.
 
Thank you for the answer Paul.
An alternative for me would be leaving the SD card permanently attached to the board inside the enclosure and grab the audio files via USB Mass Storage. But I don't want to lose the USB Audio function. Is it possible for instance to program the Teensy as USB Audio Device and Mass Storage simultaneously? I know this isn't there by default, but I wonder if it is possible/has been done before.
Sorry for this slightly unrelated question to the title.
 
Yes, custom USB interface combinations can be created by editing usb_desc.h. See the comments in that file for details.

When editing any core library file, first confirm you have the right file by adding a simple syntax error. If clicking Verify in Arduino doesn't show the error, you can quickly save yourself from a lot of frustration wondering why none of the edits change anything!
 
If you're going to be connecting it to a PC to copy the files off, you could always just temporarily flash a new program (to enable copying the files off using MTP) and then restore the original one when you're done.
 
If you're going to be connecting it to a PC to copy the files off, you could always just temporarily flash a new program (to enable copying the files off using MTP) and then restore the original one when you're done.
I would be nice if the MTP library could make its way into the official release.
 
I've been trying to transfer WAV files from an SD card via SDIO (T4) and USB, but it is extremely slow. It doesn't even copy a whole 2MB file before it freezes. Is this a normal behavior and meant only for small files?
I'm using WMXZ library, but KurtE lags the same. Reading on linux using the GVFS-MTP nemo browser integration.
 
MTP is pretty slow because it only reads one sector at a time but it shouldn't freeze. The MTP code is probably getting caught in a loop somewhere on a different command, you'd have to dig into it to find out which one.
 
I noticed that at max CPU speed (600MHz) transfers become stable, I had the T4 at 150MHz before. In linux Dolphin seems the only filebrowser to deal fine with MTP files using gvfs, each time you open a file it will copy it to a cache folder before playing it.
I'm trying fuse libraries now, also in osx, to mount the files as normal folders.
Does it make any sense to format the SD card with a higher sector size to increase speed? Or would that compromise behavior when the Teensy is recording audio files into the SD card via SDIO–my primary use?
 
Does it make any sense to format the SD card with a higher sector size to increase speed? Or would that compromise behavior when the Teensy is recording audio files into the SD card via SDIO–my primary use?
You can't change sector size, it's a fixed physical limit (always 512 bytes for SD cards).
You can change the cluster size by reformatting, but that won't change anything for MTP - it reads files directly into the usb transmit buffer, which is only 512 bytes long so it can only read that many bytes at a time.
 
Ok. It was a bit nightmarish but MTP seems to work very well now. Using libmtp (instead of gvfs-mtp) to mount it as folder with simple-mtpfs, over Nemo or Nautilus WAV files preview in real time directly. Quite impressive.
The code in use is WMXZ's mpt-basic, simplified to work only with the BUILTIN_SDCARD.

I suppose that reprogramming the Teensy each time to work as Audio USB or MTP Disk is the only reasonable to use it in both modes, as you suggested before @jmarsh. Or are there already implementations to have both simultaneously? Or, ie. Pressing a button on startup to have it running as MTP Disk, otherwise as Audio USB per default.

Code:
//WMXZ-EU mtp-basic-SDIO

#include "SPI.h"
#include "SD.h"
#include "MTP.h"

#define USE_SD  1         // SDFAT based SDIO and SPI

#if USE_EVENTS==1
  extern "C" int usb_init_events(void);
#else
  int usb_init_events(void) {}
#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 (following is for T4.1)
  #define SD_MOSI 11
  #define SD_MISO 12
  #define SD_SCK  13

  #if defined (BUILTIN_SDCARD)
    const char *sd_str[]={"sdio","sd1"}; // edit to reflect your configuration
    const int cs[] = {BUILTIN_SDCARD,10}; // edit to reflect your configuration
  #else
    const char *sd_str[]={"sd1"}; // 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


MTPStorage_SD storage;
MTPD    mtpd(&storage);

void storage_configure()
{
  // Using SD card for storage
  #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(cs[ii]<BUILTIN_SDCARD)
      {
        pinMode(cs[ii],OUTPUT); digitalWriteFast(cs[ii],HIGH);
      }
      if(!sdx[ii].begin(cs[ii]))
      { Serial.printf("SD/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("; total "); Serial.print(totalSize); Serial.print(" used: "); Serial.println(usedSize);
      }
    }
  #endif
}
 
void setup()
{
  while(!Serial);
  Serial.println("MTP_test");

  #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
}
 
Here is the working code, only for SDIO. Probably not perfect, but it works.
I commented out some serial prints that were putting the Teensy into a loop and libmtp was freezing unless the Serial Monitor in Teensyduino was open. It works super fast, tested in Linux (simple-mtfs) and MacOS (homebrew libmtp, also Android File Transfer). In KDE a UDEV rule is necessary to avoid Plasma kidnapping the device. Incredible work developers, I might be able to live without ever removing the SD card.

Code:
//Uses https://github.com/WMXZ-EU/MTP_t4
#include "SPI.h"
#include "SD.h"
#include "MTP.h"

#define USE_SD  1         // SDFAT based SDIO and SPI

#if USE_EVENTS==1
  extern "C" int usb_init_events(void);
#else
  int usb_init_events(void) {}
#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 (following is for T4.1)
  #define SD_MOSI 11
  #define SD_MISO 12
  #define SD_SCK  13

  #if defined (BUILTIN_SDCARD)
    const char *sd_str[]={"sdio"}; // edit to reflect your configuration
    const int cs[] = {BUILTIN_SDCARD,10}; // edit to reflect your configuration
  #else
    const char *sd_str[]={"sd1"}; // 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


MTPStorage_SD storage;
MTPD    mtpd(&storage);

void storage_configure()
{
  // Using SD card for storage
  #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(cs[ii]<BUILTIN_SDCARD)
      {
        pinMode(cs[ii],OUTPUT); digitalWriteFast(cs[ii],HIGH);
      }
      if(!sdx[ii].begin(cs[ii]))
      { Serial.printf("SD/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("; total "); Serial.print(totalSize); Serial.print(" used: "); Serial.println(usedSize);
      }
    }
  #endif
}
 
void setup()
{
/*  while(!Serial);
  Serial.println("MTP_test");
*/
  #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
}
 
Back
Top