SPI2 Pins on Teensy 4.1?


I was happy to see the pads on the backside of the Teensy 4.1 for a flash memory chip.
I attempted to put a Cypress 8 Mbit FRAM chip on instead of the flash and use then use the SPI2 pins... but they don't seem to be the same on a Teensy 4.1.

here is the configuration code fragment:

#include <SPI.h>
#include "Adafruit_FRAM_SPI.h" // This works with the pins noted for Teensy 4.0, but not 4.1

uint8_t FRAM_CS = 44; // SPI2 CS is pin 36 for Teensy 4.0 and 44 (?) for Teensy 4.1 I think
Adafruit_FRAM_SPI fram = Adafruit_FRAM_SPI(FRAM_CS, &SPI2); // use hardware SPI2

uint8_t FRAM_SCK = 45; // SPI2 SCK 37 is pin for Teensy 4.0 and 45 (?) for Teensy 4.1 I think
uint8_t FRAM_MISO = 42; // SPI2 MISO is pin 34 for Teensy 4.0 and 42 (?) for Teensy 4.1 I think
uint8_t FRAM_MOSI = 43; // SPI2 MOSI is pin 35 for Teensy 4.0 and 43 (?) for Teensy 4.1 I think

I must have the pins wrong or .... ?

Is there a schematic with right numbers or am I mistaken altogether about trying to put the FRAM on the flash pads? The pinouts are identical.

Thanks in advance for any help.
Those pins when used for QSPI PSRAM or FLASH are not using the SPI2 bus at all. They map direct as QSPI devices with FlexSPI hardware pin function from the 1062.

If the FRAM can do QSPI it may map - but would take different setup. If those pins maps as SPI2 ( need to print the KurtE card back ) it would take wiring connect and setup as needed to do that device.

Well, I guess I'll desolder it and put on a breakout board. It does not use QSPI. The pads on the back board are great, but apparently not usable as I had hoped.

Thanks again.
this thread feels like the best place to ask: support for SPI2 on the pin set
pin 54 - MISO2
pin 49 - SCK2
pin50 - MOSI2

is this impacted if SDIO (42,43,45) is being used? On KurtE's card these are also labelled MISO2, MOSI2, SCK2.
Yes - SPI2 are both on SdIO pins as well as the underpin with memory chip foot prints.


And you can see in SPI.h the alternate pins are defined:
#if defined(ARDUINO_TEENSY41)
const SPIClass::SPI_Hardware_t  SPIClass::spiclass_lpspi1_hardware = {
	[COLOR="#FF0000"]42, 54,[/COLOR]
	4 | 0x10, 3 | 0x10,
	1, 0,
	[COLOR="#FF0000"]43, 50[/COLOR],
	4 | 0x10, 3 | 0x10,
	1, 0,
	[COLOR="#FF0000"]45, 49,[/COLOR]
	4 | 0x10, 3 | 0x10,
	1, 0, 
	[COLOR="#FF0000"]44[/COLOR], 255, 255,
	4 | 0x10, 0, 0,
	1, 0, 0,
	0, 0, 0,
The pin numbers are shown in red. The first one in each list is the default one... i.e. the one you don't have to say SPI2.setMISO... or the like.
Note: With the memory chip area. Currently be default at startup time the startup code pings stuff on those chip areas to see if there is any memory chips. Usually has not impacted my tests.
But earlier I did propose a couple of ways that maybe one could tell system to not do that...

Will try to propose them again.
@KurtE, many thanks for the clarification. As suspected, but good to hear / see RE Class.

priority is SD, I will run tests to see how SPI or SPI1 handle mixed CS for the different chips on same line. Hopefully the MCP23S17 is tri-stated.

thanks again.

I have a question for SPI2 too. I'm migrating a project from T3.6 to T4.1 and i need all three SPI Bus. On T4.1 i'm not sure how to use the pins for SPI2 under the SD card. I saw that i can change SCK2, MOSI2 and MISO2 but no other pin for CS2.

Any advice how to use this pin?

Kind regards
On T4.1 i'm not sure how to use the pins for SPI2 under the SD card.

The SD library SdFat_Usage example was recently updated to show how to use the other SPI ports. The copy in Teensyduino 1.56 doesn't have this info, so please check out the newer code on github. Future versions of Teensyduino will have this updated example.


Also as you can see in the comments, it was discussed here.


Using SPI2 works the same way. Just change the 4th parameter from &SPI1 to &SPI2.

thanks for your reply. Acutally i already understood how to use SPI2 in software - question was more about the idea how to physically connect the pins? When i solder a wire to pins underneath the sd card slot i guess it will be blocked (but i need the sd card too)

Kind regards
two parts to this.

SPI2 - has two sets of alternate pins. That is if you look at post #7, you will see the sd card reader pins are in the 40s and the pins under the
board are in the 50s.

Yes both positions have some primary uses. That is if you try to use the SD card pins for something else you can not use the SD reader for SD. Likewise if you try to use the bottom pins for other things then you can not attach memory or flash chips. With one caveat, that if you are only using one chip, than you might be able to use the one signal CS for the other memory chip location...

So first the sdcard on board does not use SPI instead it uses the SDIO subsystem.

So SPI2 is free game to use on the memory chip locations... However SPI was setup with the SDCard pins being the default pins. So to use the bottom pins, you will have to do things like:
SPI2.setMOSI(50); ...
question was more about the idea how to physically connect the pins?

I wired it up here, just to make sure SPI2 really does work. It does indeed.

Hopefully these photos can answer the question of how to physically connect a SD card to SPI2 without using the SDIO pins on Teensy 4.1's built in SD socket.

(click on any of these images for full size)





This is the exact code I ran.

#include <SD.h>

const int chipSelect = 52;

void setup()
  while (!Serial) ; // wait for Arduino Serial Monitor

  Serial.print("Initializing SD card...");
  bool ok;
  ok = SD.sdfs.begin(SdSpiConfig(chipSelect, DEDICATED_SPI, SD_SCK_MHZ(16), &SPI2));

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

  File root = SD.open("/");
  printDirectory(root, 0);

void loop()
  // nothing happens after setup finishes.

void printDirectory(File dir, int numSpaces) {
   while(true) {
     File entry = dir.openNextFile();
     if (! entry) {
       //Serial.println("** no more files **");
     if (entry.isDirectory()) {
       printDirectory(entry, numSpaces+2);
     } else {
       // files have sizes, directories do not
       int n = log10f(entry.size());
       if (n < 0) n = 10;
       if (n > 10) n = 10;
       printSpaces(50 - numSpaces - strlen(entry.name()) - n);
       Serial.print("  ");
       Serial.print(entry.size(), DEC);
       DateTimeFields datetime;
       if (entry.getModifyTime(datetime)) {

void printSpaces(int num) {
  for (int i=0; i < num; i++) {
    Serial.print(" ");

void printTime(const DateTimeFields tm) {
  const char *months[12] = {
  if (tm.hour < 10) Serial.print('0');
  if (tm.min < 10) Serial.print('0');
  Serial.print("  ");
  Serial.print(tm.mon < 12 ? months[tm.mon] : "???");
  Serial.print(" ");
  Serial.print(", ");
  Serial.print(tm.year + 1900);

And here is a screenshot of the result in the serial monitor.