Experiment: Wondering on T4.1 supporting SDFat on SDIO2

KurtE

Senior Member+
Not sure if anyone will be interested or not. But with the talk of maybe using SDIO to support some different WIFI controllers,
wondering how hard it would be to support SDFat on SDIO2, and with this could one use both of them on the same T4.1
Or custom boards.

Sorry, in advance - probably long and convoluted and confusing.

On T4.1 I am using:
CLK = 23, CMD = 22, Data: 40, 41, 17, 16

So, I am starting to experiment...

Steps I have done so far: Split off Teensy SDIO4 into two different source files. T3.x and T4.x.

Started updates to teensy\cores\imxrt.h - Created typedef structure for SDIO:
Code:
typedef struct {
        volatile uint32_t DS_ADDR;                  //offset000)
        volatile uint32_t BLK_ATT;                  //offset004)
        volatile uint32_t CMD_ARG;                  //offset008)
        volatile uint32_t CMD_XFR_TYP;              //offset00C)
        volatile uint32_t CMD_RSP0;                 //offset010)
        volatile uint32_t CMD_RSP1;                 //offset014)
        volatile uint32_t CMD_RSP2;                 //offset018)
        volatile uint32_t CMD_RSP3;                 //offset01C)
        volatile uint32_t DATA_BUFF_ACC_PORT;       //offset020)
        volatile uint32_t PRES_STATE;               //offset024)
        volatile uint32_t PROT_CTRL;                //offset028)
        volatile uint32_t SYS_CTRL;                 //offset02C)
        volatile uint32_t INT_STATUS;               //offset030)
        volatile uint32_t INT_STATUS_EN;            //offset034)
        volatile uint32_t INT_SIGNAL_EN;            //offset038)
        volatile uint32_t AUTOCMD12_ERR_STATUS;     //offset03C)
        volatile uint32_t HOST_CTRL_CAP;            //offset040)
        volatile uint32_t WTMK_LVL;                 //offset044)
        volatile uint32_t MIX_CTRL;                 //offset048)
        uint32_t unused1;
        volatile uint32_t FORCE_EVENT;              //offset050)
        volatile uint32_t ADMA_ERR_STATUS;          //offset054)
        volatile uint32_t ADMA_SYS_ADDR;            //offset058)
        uint32_t unused2;
        volatile uint32_t DLL_CTRL;                 //offset060)
        volatile uint32_t DLL_STATUS;               //offset064)
        volatile uint32_t CLK_TUNE_CTRL_STATUS;     //offset068)
        uint32_t unused3[21];                       //6c 70 80 90 A0 B0
        volatile uint32_t VEND_SPEC;                //offset0C0)
        volatile uint32_t MMC_BOOT;                 //offset0C4)
        volatile uint32_t VEND_SPEC2;               //offset0C8)
        volatile uint32_t TUNING_CTRL;              //offset0CC)
} IMXRT_USDHC_t;
So far I have not created pointers to the different objects within IMXRT.h.
@PaulStoffregen - Assuming something like other updates like this? Should I update the current defines as well?
like:
Code:
#define IMXRT_USDHC1        (*(IMXRT_REGISTER32_t *)IMXRT_USDHC1_ADDRESS)
// USDHC1 requires CCM_CCGR6_USDHC1
#define USDHC1_DS_ADDR            (IMXRT_USDHC1.offset000)
#define USDHC1_BLK_ATT            (IMXRT_USDHC1.offset004)
#define USDHC1_CMD_ARG            (IMXRT_USDHC1.offset008)
#define USDHC1_CMD_XFR_TYP        (IMXRT_USDHC1.offset00C)
Would go to something like:
Code:
#define IMXRT_USDHC1        (*(IMXRT_USDHC_t *)IMXRT_USDHC1_ADDRESS)
// USDHC1 requires CCM_CCGR6_USDHC1
#define USDHC1_DS_ADDR            (IMXRT_USDHC1.DS_ADR)
#define USDHC1_BLK_ATT            (IMXRT_USDHC1.BLK_ATT)
#define USDHC1_CMD_ARG            (IMXRT_USDHC1.CMD_ARG)
#define USDHC1_CMD_XFR_TYP        (IMXRT_USDHC1.XFR_TYP)
...

Moved all of the state variables and functions to be private in SDCardIO.h - not sure if that will fly. Currently SDIO in your fork only supported by Teensy, but I believe maybe supports RPI... or was it ESP...

Added define for SDIO Options: So currently only way to use SDIO 2 (in my test code)
Code:
if (!SD.sdfs.begin(SdioConfig(FIFO_SDIO | USE_SDIO2))) {

Changes in the code so far:
a) Modify functions to not assume USDHC1... Note: I am trying to remove most of the usage of the code to not use mapping T3.x to T4.x register names...
Code:
static bool isBusyTransferComplete() {
  return !(SDHC_IRQSTAT & (SDHC_IRQSTAT_TC | SDHC_IRQSTAT_ERROR));
}
...
// Return true if timeout occurs.
static bool waitTimeout(bool (*fcn)()) {
  uint32_t m = micros();
  while (fcn()) {
    if ((micros() - m) > BUSY_TIMEOUT_MICROS) {
      return true;
    }
  }
  return false;  // Caller will set errorCode.
}
//------------------------------------------------------------------------------
static bool waitTransferComplete() {
  if (!m_transferActive) {
    return true;
  }
  bool timeOut = waitTimeout(isBusyTransferComplete);
  m_transferActive = false;
...
It is passing different static functions into waitTimeout that is checking fixed status registers...

So modified to be methods on class, which gets called so it has address of the SDIO register structure...
But then had to learn how to call function pointers to non-static class methods. ...

Init the CCM clocks:
Code:
/* Enable USDHC clock. */
  if (!fUseSDIO2) {
    CCM_CCGR6 |= CCM_CCGR6_USDHC1(CCM_CCGR_ON);
    CCM_CSCDR1 &= ~(CCM_CSCDR1_USDHC1_PODF(7));
    CCM_CSCMR1 |= CCM_CSCMR1_USDHC1_CLK_SEL;          // PLL2PFD0
  //  CCM_CSCDR1 |= CCM_CSCDR1_USDHC1_CLK_PODF((7)); / &0x7  WHG
    CCM_CSCDR1 |= CCM_CSCDR1_USDHC1_CLK_PODF((1));
  } else {
    CCM_CCGR6 |= CCM_CCGR6_USDHC2(CCM_CCGR_ON);
    CCM_CSCDR1 &= ~(CCM_CSCDR1_USDHC2_PODF(7));
    CCM_CSCMR1 |= CCM_CSCMR1_USDHC2_CLK_SEL;          // PLL2PFD0
  //  CCM_CSCDR1 |= CCM_CSCDR1_USDHC2_CLK_PODF((7)); / &0x7  WHG
    CCM_CSCDR1 |= CCM_CSCDR1_USDHC2_PODF(1);
  }
}

Initialize the pins: Note: Different pins and different mode of pins for the SDIO2 pins I am using.
Code:
void SdioCard::gpioMux(uint8_t mode, bool fUseSDIO2) {
  if (!fUseSDIO2) {
    IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_04 = mode;  // DAT2
    IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_05 = mode;  // DAT3
    IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_00 = mode;  // CMD
    IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_01 = mode;  // CLK
    IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_02 = mode;  // DAT0
    IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_03 = mode;  // DAT1
  } else {
    IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_07 = mode; //USDHC2_DATA3
    IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06 = mode; //USDHC2_DATA2
    IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_08 = mode; //USDHC2_CMD
    IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_09 = mode; //USDHC2_CLK
    IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_04 = mode; //USDHC2_DATA0
    IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_05 = mode; //USDHC2_DATA1
  }
}
//------------------------------------------------------------------------------
// add speed strength args?
void SdioCard::enableGPIO(bool enable, bool fUseSDIO2) {
  const uint32_t CLOCK_MASK = IOMUXC_SW_PAD_CTL_PAD_PKE |
                              IOMUXC_SW_PAD_CTL_PAD_DSE(7) |
                              IOMUXC_SW_PAD_CTL_PAD_SPEED(2);

  const uint32_t DATA_MASK = CLOCK_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE |
                             IOMUXC_SW_PAD_CTL_PAD_PUS(1);
  if (enable) {
    gpioMux(fUseSDIO2? 6 : 0, fUseSDIO2);  // SDIO2 is on ALT6
    if (!fUseSDIO2) {
      IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_04 = DATA_MASK;   // DAT2
      IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_05 = DATA_MASK;   // DAT3
      IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_00 = DATA_MASK;   // CMD
      IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_01 = CLOCK_MASK;  // CLK
      IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_02 = DATA_MASK;   // DAT0
      IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_03 = DATA_MASK;   // DAT1
    } else {     
      IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_07 = DATA_MASK; //USDHC2_DATA3
      IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_06 = DATA_MASK; //USDHC2_DATA2
      IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_08 = DATA_MASK; //USDHC2_CMD
      IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_09 = CLOCK_MASK; //USDHC2_CLK
      IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_04 = DATA_MASK; //USDHC2_DATA0
      IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_05 = DATA_MASK; //USDHC2_DATA1
    }

Initialize IRQ: ...

DMA: ? not sure we doing much yet here.

Now starting to test: First issue I ran into none of the pins were outputting anything...
Need to Input select them:
Code:
// We need to set select input bits...
      IOMUXC_USDHC2_CLK_SELECT_INPUT = 0x1;
      IOMUXC_USDHC2_CMD_SELECT_INPUT = 0x01;
      IOMUXC_USDHC2_DATA0_SELECT_INPUT = 0x01;
      IOMUXC_USDHC2_DATA1_SELECT_INPUT = 0x01;
      IOMUXC_USDHC2_DATA2_SELECT_INPUT = 0x01;
      IOMUXC_USDHC2_DATA3_SELECT_INPUT = 0x01;

Code is still erroring out with Test program. Just using ListFiles with the change
Code:
  if (!SD.sdfs.begin(SdioConfig(FIFO_SDIO | USE_SDIO2))) {
  //if (!SD.sdfs.begin(SdioConfig(FIFO_SDIO))) {
  //if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed! ");
    return;
  }
  Serial.println("initialization done.");

Still getting errors, but some output as partial output:
Code:
Initializing SD card...SdioCard::begin: 1
351 IRQSTAT 2
911 IRQSTAT 2
351 IRQSTAT 2
initialization done.
cardCommand(cdb0000, 0) error return false
LINE: 942
BLKATTR 10200
XFERTYP CDB0000 CMD12 TYP0
PRSSTAT F0888088 SDOFF SDSTB
PROCTL 8800022 EMODE2 DWT1
IRQSTAT 28001 CC
m_irqstat 88000
x.txt                                           32012    12:42  October 13, 2021
FS.h                                             8732    16:50  October 3, 2021
T4LargeIndexedTestfile.txt                   22014964    07:20  November 5, 2021
test1.txt                                          21    00:00  ??? 0, 1980
mtpindex.dat                              0
foo/
911 IRQSTAT 28001
351 IRQSTAT 28001
cardCommand(d1a0000, b3680000) error return false351 IRQSTAT 18000
cardCommand(d1a0000, b3680000) error isBusyCommandInhibit)

LINE: 913
BLKATTR 10200
XFERTYP D1A0000 CMD13 TYP0
PRSSTAT FF888089 SDOFF SDSTB CIHB
PROCTL 8800022 EMODE2 DWT1
IRQSTAT 18000
m_irqstat 28001
333/
911 IRQSTAT 18000
351 IRQSTAT 18000
cardCommand(d1a0000, b3680000) error isBusyCommandInhibit)

So it looks like somethings are limping along and maybe hope...
1736206984612.png

Thought I would mention it and also say I pushed the WIP stuff up to:

Have not pushed up the imxrt.h changes yet, but...
 
@KurtE Just a note - I used that base PCB for SPI SerialFlash testing - that you helped with the PTR rewrite for SPI2.

With just SPI to that Flash the runs from the first headers to the fourth and fifth header rows was too long for reliable CHIP ID and usage.
Might assure better signal integrity to move the T_4.1 over two header sets toward the SDIO/LA pins? That will drop ~1.5" of PCB traces.
 
Thanks all,
With just SPI to that Flash the runs from the first headers to the fourth and fifth header rows was too long for reliable CHIP ID and usage.
Might assure better signal integrity to move the T_4.1 over two header sets toward the SDIO/LA pins? That will drop ~1.5" of PCB traces.
I moved the T4.1 to the nearest slot on the board and I think it helped, thanks.

Will finish the editing of the imxrt.h file and do PR of it...

Also just installed a Protocol analyzer for SDIO to the Saleae setup...

I downloaded and built it, but you can also go to the release and there are artifacts which include builds for Windows, Mac, Linux...
1736260673454.png


Back to playing
 
for the fun of it, I thought I would try MTP with the two SDIO cards on it:
C++:
#include <SD.h>
#include <MTP_Teensy.h>

#define CS_SD BUILTIN_SDCARD  // Works on T_3.6 and T_4.1
//#define CS_SD 10  // Works on SPI with this CS pin

SDClass sd_io2;

void setup()
{
  // mandatory to begin the MTP session.
  MTP.begin();

  // Add SD Card
  SD.begin(CS_SD);
  MTP.addFilesystem(SD, "SD Card");

  sd_io2.sdfs.begin(SdioConfig(FIFO_SDIO | USE_SDIO2));
  MTP.addFilesystem(sd_io2, "2nd SDIO card");

}

void loop() {
  MTP.loop();  //This is mandatory to be placed in the loop code.
}
1736265545165.png
1736265579833.png


Appears to be working at least some. I have not tried modifying files and the like yet
Might be problems... But tried upload and download files and maybe not correct...
 
Quick Note: SD Library
Has hard coded dependencies and/or expectations on the SDFat library.

That is, it looks depends on:
Code:
if (csPin == BUILTIN_SDCARD) {
To know that it is dealing with an SDIO drive.

Which even without this update, may/may not work, as this is only set on call like: SD.begin(csPin);
Which is not called if you are using the SdFat_Uage.ino type calls, like:
//ok = SD.sdfs.begin(SdioConfig(FIFO_SDIO));
or likewise:
ok = SD.sdfs.begin(SdSpiConfig(chipSelect, SHARED_SPI, SD_SCK_MHZ(24)));

Now where is this used, is mostly for card inserted detection. That is for SDIO it changes the SD Dat3 pin to INPUT_PULLDOWN
and then digital reads it. And then it might call sd.restart() to reset that pin after card detected.
..

Also SD Library has hard coded what pin number is SD_DAT3
Code:
#if defined(ARDUINO_TEENSY41)
#define _SD_DAT3 46
#elif defined(ARDUINO_TEENSY40)
#define _SD_DAT3 38
#elif defined(ARDUINO_TEENSY_MICROMOD)
#define _SD_DAT3 39
#elif defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36)

Wishlist:
a) some call to SDFat that tells me if it is running as SDIO or SPI. Note: the restart assumes it by seeing
that the CS backup value is 255... Can we access that?

b) That SD library does not set the state of DAT3 but instead tell SDFat what the state of it should be...
That wy SDFat already knows what IO Signal is associated with that pin...

EDIT: c) Either our version of SDFat is compatible with https://github.com/greiman/SdFat and/or
we split off, and for example maybe the directory name and top header file ( SdFat.h) are renamed to something
like SdFat-Teensy or the like
 
Last edited:
Code:
So far I have not created pointers to the different objects within IMXRT.h.
@PaulStoffregen - Assuming something like other updates like this? Should I update the current defines as well?

Yes, please send a pull request for IMXRT_USDHC_t in imxrt.h. At least putting that into 1.60 should make this easier to maintain.

Changes in SdFat and SD less certain for now...
 
@KurtE
Decided to wire this up and give it a try. Setup pretty much mirrors yours.
MTP does let you see both drives no issues. However

1. Copying files from SDio1 to SDio2 fails. Seems to copy entry but data is corrupted - incomplete.
2. Copying files from PC to SDio2 works and files open no issues. At least for the couple I tried.
3. Copying files from Sdio2 to Sdio1 seems to work. Again small set of files tested
4. Delete on SDIO2 seems to cause some issues for me.
5. Format of SDIO2 seems to work.

Nice work getting this working.
EDIT: c) Either our version of SDFat is compatible with https://github.com/greiman/SdFat and/or
we split off, and for example maybe the directory name and top header file ( SdFat.h) are renamed to something
like SdFat-Teensy or the like
Think probably should break off to Teensy specific. Had another copy of SDFat in the local libraries folder and it wanted to default to that instead of using the one in package, got a error message to that affect.
 
Thanks, I had sort of been holding off doing much more with this as to wait for a quick and dirty adapter, that I ordered from OSHPark.
1736691257989.png


It is setup to use the Adafruit breakout board:
It is easier than soldering the SD connector and may be useful for the WiFi experiments.

And with Paul's comments:
Changes in SdFat and SD less certain for now...
I figured, no hurry as it is a long shot that these changes will be pulled in.

Think probably should break off to Teensy specific. Had another copy of SDFat in the local libraries folder and it wanted to default to that instead of using the one in package, got a error message to that affect.
I agree, but might be semi-tricky, as I am not sure how many sketches directly include SDFat.h, how should they work? Maybe depends on if
they include SD.h?

On a different but related subject, I am thinking about @greiman comments in the Issue I create against the official SdFat project:

That is I don't like the code in SdSpiTeensy3.cpp - This code is/was originally set up, such that whenever you read or write multiple
bytes (typically 512), it keeps the code from calling: m_spi->transfer(0xff) 512 times. However instead it is using the old style
SPI.transfer(buffer, count).

Instead we should merge in the current default SPI driver code, where you can define how to do things in the SdFatConfig.h file:
Code:
/**
 * If USE_SPI_ARRAY_TRANSFER is one and the standard SPI library is
 * use, the array transfer function, transfer(buf, count), will be used.
 * This option will allocate a 512 byte temporary buffer for send.
 * This may be faster for some boards.  Do not use this with AVR boards.
 *
 * Warning: the next options are often fastest but only available for some
 * non-Arduino board packages.
 *
 * If USE_SPI_ARRAY_TRANSFER is two use transfer(nullptr, buf, count) for
 * receive and transfer(buf, nullptr, count) for send.
 *
 * If USE_SPI_ARRAY_TRANSFER is three use transfer(nullptr, buf, count) for
 * receive and transfer(buf, rxTmp, count) for send. Try this with Adafruit
 * SAMD51.
 *
 * If USE_SPI_ARRAY_TRANSFER is four use transfer(txTmp, buf, count) for
 * receive and transfer(buf, rxTmp, count) for send. Try this with STM32.
 */
#ifndef USE_SPI_ARRAY_TRANSFER
#if defined(ARDUINO_ARCH_RP2040)
#define USE_SPI_ARRAY_TRANSFER 2
#else  // defined(ARDUINO_ARCH_RP2040)
#define USE_SPI_ARRAY_TRANSFER 1
#endif  // defined(ARDUINO_ARCH_RP2040)
#endif  // USE_SPI_ARRAY_TRANSFER

So we could, instead of using custom driver, we could simply could set:
USE_SPI_ARRAY_TRANSFER 2

Note: our current implementation of: transfer(nullptr, buf, count) defaults to sending 0x00,
could change that to instead send 0xff. We also have a call within SPI that allows us to change it.

Sure would be nice, if Arduino would adopt this call as well into their SPI implementations.

Now back to playing.
 
Playing with the SdSPITeensy3.cpp code in steps.
Code:
//------------------------------------------------------------------------------
uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) {
#if 0
  m_spi->setTransferWriteFill(0xff);
  m_spi->transfer(nullptr, buf, count);
#else
  memset(buf, 0XFF, count);
  m_spi->transfer(buf, count);
#endif
  return 0;
}
//------------------------------------------------------------------------------
void SdSpiArduinoDriver::send(const uint8_t* buf , size_t count) {
#if 0
  m_spi->transfer(buf, nullptr, count);
#else
  uint32_t tmp[128];
  if (0 < count && count <= 512) {
    memcpy(tmp, buf, count);
    m_spi->transfer(tmp, count);
    return;
  }

#endif
}
Shown above in the #if 0 - code runs the same as originally. change if 0 to if 1, new...

With T3.2 using SD on audio adapter it appears to be a win (SDFat bench) for both read and write:
OLD:
Code:
Type any character to start
FreeStack: 59060
Type is FAT32
Card size: 7.95 GB (GB = 1E9 bytes)

Manufacturer ID: 0X3
OEM ID: SD
Product: SL08G
Version: 8.0
Serial number: 0XC536FD28
Manufacturing date: 11/2014

FILE_SIZE_MB = 5
BUF_SIZE = 512 bytes
Starting write test, please wait.

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
2503.76,1139,203,203
2503.76,904,203,203

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
2536.78,203,200,201
2540.65,203,200,200

Done
New:
Code:
Type any character to start
FreeStack: 59060
Type is FAT32
Card size: 7.95 GB (GB = 1E9 bytes)

Manufacturer ID: 0X3
OEM ID: SD
Product: SL08G
Version: 8.0
Serial number: 0XC536FD28
Manufacturing date: 11/2014

FILE_SIZE_MB = 5
BUF_SIZE = 512 bytes
Starting write test, please wait.

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
2579.98,3590,197,197
2583.98,899,197,197

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
2597.40,199,196,196
2600.10,199,196,196

With Teensy 4.1 SD on Audio adapter:
Old
Code:
Type any character to start

Use a freshly formatted SD for best performance.

Type any character to start
FreeStack: 447320
Type is FAT32
Card size: 7.95 GB (GB = 1E9 bytes)

Manufacturer ID: 0X3
OEM ID: SD
Product: SL08G
Version: 8.0
Serial number: 0XC536FD28
Manufacturing date: 11/2014

FILE_SIZE_MB = 5
BUF_SIZE = 512 bytes
Starting write test, please wait.

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
5165.29,3278,98,99
5181.35,811,98,98

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
5219.21,98,97,98
5230.13,98,97,97

Done
New way:
Code:
Type any character to start
FreeStack: 447320
Type is FAT32
Card size: 7.95 GB (GB = 1E9 bytes)

Manufacturer ID: 0X3
OEM ID: SD
Product: SL08G
Version: 8.0
Serial number: 0XC536FD28
Manufacturing date: 11/2014

FILE_SIZE_MB = 5
BUF_SIZE = 512 bytes
Starting write test, please wait.

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
5208.33,1038,98,98
5208.33,800,98,98

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
5065.86,101,100,101
5076.14,101,100,100

Done
Faster on Writes, Slower on Reads ???
Wonder if maybe in this case the transfer(nullptr, rx, count);
that maybe we are not packing up the SD bus to 16 or 32 bit transfers?
So more gaps... Will have to look at some point.

EDIT: Should not be really any difference?
Code - not showing #if 0 code...

Code:
    void inline transfer(void *buf, size_t count) {
        transfer(buf, buf, count);
    }
And the only difference in the transfer(buf, retbuf, count) and (nullptr, buf, count) is
port().TDR = p_write? *p_write++ : _transferWriteFill;
what is stored in TDR...
 
Last edited:
Thought I would mention, I got my quick and dirty cards back from OSHPark, and I did a quick and very dirty solder job on one
1737143326025.png

I ran a couple of the sketches I tried before, and they appear to be happier...

Code:
//=============================================================================
// Simple Sketch that initializes MTP and adds one SD drive as the only
// storage.
// Notes:
//    If SD.h is included before MTP_Teensy.h, the code will automatically
//    inert a handler callback that will try to detect when the SD is inserted
//    or removed.
//
//    The host often times will not automatically refresh to show the updated
//    status of the drive after events such as this.  However doing a refresh
//    example F5 on Windows, will update and show the new status.
//
//    If MTP_Teensy.h is included before SD.h, by default, this checking
//    for drive insertions is not installed.  You can tell the addFilesystem that
//    the storage is an SD drive like:
//        MTP.addFilesystem(SD, "SD Card", MTP_FSTYPE_SD);
//
//=============================================================================
#include <SD.h>
#include <MTP_Teensy.h>

#define CS_SD BUILTIN_SDCARD  // Works on T_3.6 and T_4.1
//#define CS_SD 10  // Works on SPI with this CS pin

SDClass sd_io2;

void setup()
{
  // mandatory to begin the MTP session.
  MTP.begin();

  // Add SD Card
  SD.begin(CS_SD);
  MTP.addFilesystem(SD, "SD Card");

  sd_io2.sdfs.begin(SdioConfig(FIFO_SDIO | USE_SDIO2));
  MTP.addFilesystem(sd_io2, "2nd SDIO card");

}

void loop() {
  MTP.loop();  //This is mandatory to be placed in the loop code.
}

Was able to run my simple MTP sketch, and was able to upload a jpeg file and then double click on it and it showed up
as the image...
1737143542804.png


I know there are issues with the begin like:
Code:
sd_io2.sdfs.begin(SdioConfig(FIFO_SDIO | USE_SDIO2));
with some SD functions, like detecting if the card is there or not. But that is true of all case where
we call the sdfs.begin(...) method, as only the SD.begin() saves away the CS pin number which is used to determine if
this is SDIO or not...

May not take this much farther as unclear from previous post on if this functionality would be pulled into the core or not.
 
Ordered board set w/SuperSwift from OshPark - panel off to fabricator late today and back in a few days ... Also the AdaF SD breakout that may arrive just before ...
 
Back
Top