SMD Flash with Teensy 4.1 design

AndyMeyer

Well-known member
Still working the bringup of my Teensy 4.1 based data acquisition board. I have a Zetta ZDSD04GLGEAG attached right near the 1062.
pin1 (DAT2) to ball H2
pin2 (DAT3) to ball J2
pin3 (CLK) to ball J2
pin5 (CMD) to ball J4
pin6 (DAT0) to ball J1
pin7 (DAT1) to ball K1

Power and decoupling fairly standard. Trace lengths are within a few mils.
It's not even start to talk with the SD libraries.
Running any of the SD card sketches gives me:
-> error: card init failed.
-> SD errorCode: SD_CARD_ERROR_ACMD41 = 0x17
-> SD errorData = 0x18000

Any thoughts? Any other easy way to get a couple of Gig of storage onto a teensy / PCBA that's good for a higher vibration environment... So far, the rest of the connections seem good - display is working, boots up fine, so I'm not suspecting a bad BGA ball solder joint but... Any other way to test? (I could pull the chip and do a diode test on the pins, but before I dive in that far...)

Thanks!

Andy
 
Last edited:
JMarsh - Thanks! Typo here. Pin 3 to J3.
pin1 (DAT2) to ball H2
pin2 (DAT3) to ball J2
pin3 (CLK) to ball J3
pin5 (CMD) to ball J4
pin6 (DAT0) to ball J1
pin7 (DAT1) to ball K1
 
Please give 1.60-beta a try, if you're not already using it. I'll admit it's a long shot, but trying is so simple. Just put the beta URL into Arduino IDE preferences, then use Boards Manager to switch from 1.59 (or whatever version you have) to 0.60.6.

Since 1.59 at least a couple workarounds when into SdFat to handle troublesome cards. One handles cards that don't support CMD8 and another deals with cards that claim support for 50 MHz clock but then don't actually work at that speed. Many other small improvements have gone into the code since 1.59, but those are the two I can remember which might make a difference here.
 
I curious if this Zetta ZDSD04G part is really the same as XTX Tech XTSD04G?

We had a report of problems with XTSD01G a couple years ago. The fix should be in version 1.59.

Their 2 datasheets look nearly identical, even the same words in the intro section and same part number ordering info, other than the "ZD" vs "XT" prefix. Zetta's datasheet has a lot of info about accessing the card, but it's just a verbatim copy of parts of the SD card specification.
 

Attachments

  • XTX_XTSD01G.pdf
    763.6 KB · Views: 11
  • Zetta_ZDSD01G.pdf
    1.1 MB · Views: 17
I tried 0.60.6 - no joy. :( Same error. Trying the SdFormatter.ino and the TeensySdioDemo.ino examples. I slowed the clock way town to 25, then 5 MHz to see if that was an issue as well.
I'm not missing something that I must do first to initiate one of these cards (format / put a filesystem on it in the first place)?

TeensySdioDemo.ino gave ... (Option 3 and 4 did not display the "Try Power Cycling message")
Code:
Error: begin failed
Try power cycling the SD card.
SD_CARD_ERROR_CMD0, ErrorData: 0X0
 
I'm at wits end with this one... I pulled the IC and verified that the Teensy can control each pin (ran blink on all 6 pins and they all work.)
Tried a new Zetta IC from a different batch / order.
Resoldered the IC and inspected the connections again as close as I can with a microscope.
Tried adding a 6.8k pull-up on CS (pin 2 of the Zetta)
I've tried SPI and SDIO modes (I think I've tested SDIO correctly)
Ran over the pinout about 5 times - can't see anything I might have missed.

Any other thoughts?
One last ditch I may try is white wiring an SD card on to see if it's my PCBA or the Zetta IC.

Thinking my next spin might end up with a uSD card going back on, my environments (vibration) probably ain't best for a uSD card, though they are used in other systems exposed to similar...

1771720118006.png
1771720264543.png
 
I ordered the Zetta chip from LCSC and this PCB from OSH Park. Might be a couple weeks, since Chinese vendors are just now reopening from Lunar New Year holiday.

Soldering wires from your PC to a SD socket seems like a pretty good test to try. Best to keep the wires under a couple inches and try to get them similar length, since 50 MHz clock will be used with any modern card. If you can, might also be worthwhile to solder a 0.1uF capacitor directly to the socket's 3.3V and GND pins.
 
Last edited:
Tried the SD Card direct - Ughhh. No joy. Wires ~1.5 inches long. Adapter had the caps for power.
Code I'm running is: (I dropped everything after setup since I never get past setup.)
Tried swapping MISO and MOSI - honestly, who here hasn't hooked RX to RX and TX to TX?
:/
Code:
#include <SD.h>

const int chipSelect = 44;

void setup()
{
  SPI2.setMOSI(43);
  SPI2.setMISO(42);
  SPI2.setSCK(45);
 
  Serial.begin(9600);
  while (!Serial) ; // wait for Arduino Serial Monitor
delay(1000);
  Serial.print("Initializing SD card...");
  bool ok;
  ok = SD.sdfs.begin(SdSpiConfig(chipSelect, SHARED_SPI, SD_SCK_MHZ(24), &SPI2));

  if (!ok) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  File root = SD.open("/");
 
  printDirectory(root, 0);
 
  Serial.println("done!");
}
 
Let's backtrack a bit here.... are you intending to drive the SD chip using SPI2, or the native SDHC controller (USDHC1) ?
 
JMarsh,
I'm open to either - tried both. I need to record data at a modest rate (data logger) and then when the Teensy is connected to a laptop and one hits the right button in the menus, files are pulled from the Zetta and sent via USB (text strings sent over USB) to the laptop. (Modest rate being < 1kB / second)
It currently works with an SD card on the Teensy (previous revision), but I've implemented the Teensy functionality on my own PCBA with the Zetta IC and not having luck. I didn't have luck directly wiring the uSD card reader either.
Ultimately, I'd like to be able to store > 256MB of data. Stretch would be 2GB.
 
Can you show the code you've tried using SDIO? It won't work as SPI2 since the pins don't match up in that configuration.
 
Last edited:
I tried all 3 options for the Teensy4.1 and still get
-> Initializing SD card...initialization failed!

Could you help me understand where I've got the pins mis-aligned? I must be missing something here.

Code:
/*
/*
  SdFat usage from SD library
  Starting with Teensyduino 1.54, the SD library is a thin wrapper for SdFat.
  You can access the main SdFat filesystem with "SD.sdfs".  You may wish to
  use SD.sdfs.begin() to cause SdFat to access the SD card using faster
  drivers than the default.  You may also wish to open files as FsFile to
  gain access to SdFat's special file functions which are not available using
  the simpler SD File.
  This example shows some of the ways to select optimized SdFat drivers and
  how to use special file truncation and pre-allocation for optimized data
  logging.
  This example code is in the public domain.
*/
#include <SD.h>
// On Teensy 2.0, SdFat's files are "File32" rather than "FsFat"
#ifdef __AVR__
#define FsFile File32
#endif
void setup()
{
  //Uncomment these lines for Teensy 3.x Audio Shield (Rev C)
  //SPI.setMOSI(7);  // Audio shield has MOSI on pin 7
  //SPI.setSCK(14);  // Audio shield has SCK on pin 14
  Serial.begin(9600);
  while (!Serial); // wait for Arduino Serial Monitor
  Serial.print("Initializing SD card...");
  bool ok;
  const int chipSelect = 45; // only for SPI, can't use BUILTIN_SDCARD here
  // Instead of the usual SD.begin(pin), you can access the underlying
  // SdFat library for much more control over how the SD card is
  // accessed.  Uncomment one of these, or craft your own if you wish
  // to use SdFat's many special features.
  // Faster SPI frequency.  16 MHz is default for longer / messy wiring.
 // ok = SD.sdfs.begin(SdSpiConfig(chipSelect, SHARED_SPI, SD_SCK_MHZ(24)));
  // Very slow SPI frequency.  May be useful for hardware with slow buffers.
  //ok = SD.sdfs.begin(SdSpiConfig(chipSelect, SHARED_SPI, SD_SCK_MHZ(4)));
  // SdFat offers DEDICATED_SPI optimation when no other SPI chips are
  // connected.  More CPU time is used and results may vary depending on
  // interrupts, but for many cases speed is much faster.
  //ok = SD.sdfs.begin(SdSpiConfig(chipSelect, DEDICATED_SPI, SD_SCK_MHZ(16)));
  // Different SPI port (Teensy 4.1 SPI1 is MOSI1:pin26, MISO1:pin1, SCK1:pin27)
  // SPI1 photo: https://forum.pjrc.com/threads/69254?p=297875&viewfull=1#post297875
  // SPI2 photo: https://forum.pjrc.com/threads/60954?p=303782&viewfull=1#post303782
  //ok = SD.sdfs.begin(SdSpiConfig(chipSelect, SHARED_SPI, SD_SCK_MHZ(16), &SPI2));
  // Access the built in SD card on Teensy 3.5, 3.6, 4.1 using FIFO
  ok = SD.sdfs.begin(SdioConfig(FIFO_SDIO));
  // Access the built in SD card on Teensy 3.5, 3.6, 4.1 using DMA (maybe faster)
  //ok = SD.sdfs.begin(SdioConfig(DMA_SDIO));
  if (!ok) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  Serial.println();
  // After the SD card is initialized, you can access it using the ordinary
  // SD library functions, regardless of whether it was initialized by
  // SD library SD.begin() or SdFat library SD.sdfs.begin().
  //
  Serial.println("Print directory using SD functions");
  File root = SD.open("/");
  while (true) {
    File entry = root.openNextFile();
    if (!entry) break; // no more files
    Serial.print(entry.name());
    if (entry.isDirectory()) {
      Serial.println("/");
    } else {
      printSpaces(40 - strlen(entry.name()));
      Serial.print("  ");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
..............
 
Could you help me understand where I've got the pins mis-aligned? I must be missing something here.
I'm not saying they're necessarily misaligned, I'm saying the wiring for SDIO is not compatible with SPI mode, so trying to tell the SD library to use SPI will never work. Keep it simple and just use SD.begin(BUILTIN_SDCARD);
 
Can you double-check the trace to J3? From the earlier picture it looks like it goes through a via, then a straight line down/left to another via, to the clk pin on the SD. But from that pic it passes directly over three other balls and it's not entirely clear that there are no connections.
 
As a next troubleshooting step, I'd recommend running the LED blink example. First run it on the default pin 13 and connect your multimeter. Adjust the delays for the speed of your multimeter (most are quite slow) so you see a clear indication of the voltage changing from 0 to 3.3V and back to zero.

Then change the pin number to 42 and upload. Use your multimeter to check all the wires you soldered from PCB to SD socket. You want to see the voltage changing on the DAT1 wire and *not* on any of the other pins!

1771800659857.png


Repeat for edit and upload to test pins 43, 44, 45, 46, 47.
 
JMarsh, Orange is the top layer, blue the bottom. I route J3 up to the left to keep the 3.3V fill as big as I can, then route it on the bottom layer (4 layer PCB) out from under the iMXRT and bring it back up. I figured the clock would be the least offensive to add a hair of delay / inductance to. I could do a pin swap in the next spin if we think that's not ideal.
Ran both METHOD1 and METHOD2 in this code and both yield the " -> initialization failed!"

Paul, Ran the blink individually on all 6 of the pins. Continuity and isolation all good.

Code:
/* LED Blink, Teensyduino Tutorial #1
   http://www.pjrc.com/teensy/tutorial.html
 
   This example code is in the public domain.
*/

// Teensy 2.0 has the LED on pin 11
// Teensy++ 2.0 has the LED on pin 6
// Teensy 3.x / Teensy LC have the LED on pin 13
const int ledPin = 13;

#include <SD.h>

// the setup() method runs once, when the sketch starts

bool ok;

void setup() {
  // initialize the digital pin as an output.
  pinMode(ledPin, OUTPUT);
 
 SD.begin(BUILTIN_SDCARD);

//METHOD 1 **********************
  ok = SD.sdfs.begin(SdioConfig(FIFO_SDIO));

  if (!ok) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  Serial.println();

//METHOD 2************************

  // if (!SD.begin(BUILTIN_SDCARD))
  //   {
  //   Serial.println("initialization failed!");
  //   }
  //   else
  //   {
  //   Serial.println("initialization done.");
  //   Serial.println();
  //   }
 }
 
Continuity and isolation all good.

I'm surprised, if Continuity means you did indeed observe the voltage changing on each pin.

Can you share a photo of the SD socket and its wires to your PCB? If all 6 signals really are connected, then the only plausible explanation is a mistake or misunderstanding in how the connect to SD socket. Photos showing the wiring are needed to help with that.
 
I'll get a response / photos back soon. I'm in the middle of the High School robotics season right now and haven't had a moment to pick this up again. Teensy is so much easier and seems more powerful then what they make these kids use! (A combination of NI HW, linux RTOS, but Windows only for programming, etc...)
 
Yes Teensy is more powerful and more straight forward to use than most but kids don't learn much if you teach them easy stuff.
 
Back
Top