Teensy 4.1 Beta Test

Going on line to USPS seems like there are delays in shipping to and from all countries outside of US due to COVID-19 due to limited international flights and precautions other countries are taking as well. So only fast way right now is DHL or probably UPS.
 
I found the problem, I was incorrectly reporting the number of bytes being written to the wrapper, so the wrapper was thinking it was sending the whole 100,000 bytes when it actually wasn't. Also the MSS is normal now, I forgot to reset it after I was done doing some other testing.

I did some tuning experiments with your NativeEthernet.
  • increased ethernet ring buffers from 2 to 5 in port/cpu/fnet_cpu_config.h. No change in TCP Tx or Rx performance
  • reference manual says ENETx_MRBR should be multiple of 64 (NXP SDK uses 0x600), but changing it in port/netif/fec/fnet_fec.c had no effect on TCP performance.
  • in NativeEthernet.h increased FNET_SOCKET_DEFAULT_SIZE from 2048 to 4*1460, T4.1 TCP recv increased from 60.5 mbs to 78.4 mbs and TCP xmit increased from 45.2 mbs to 92 mbs!
I also successfully ran a simple UDP multicast test.
 
Last edited:
@defragster - @KurtE
Here is a slightly modified version of the version in the zip. I adds 2 new commands:
  • 'E' - erase PSRAM
  • 'd' - dump PSRAM after second buffer is full while running 'R'

Code:
/**************************************************************
  timing PSRAM datalogger for Teensy 4.1 with PSRAM - NO SD LOGGING - ONLY extRAM_t4.h required

  https://forum.pjrc.com/threads/60754-Teensy-3-6-SD-Card-missing-time-in-milliseconds?p=238352&viewfull=1#post238352
  Written for Teensy 3.6 by M. Borgerson  May 7, 2020
********************************************************************/

elapsedMicros logTime;
//#define USE_logtime
#define LOG_US (1000000 / SAMPLERATE)
#ifdef USE_logtime
#else
IntervalTimer ADCTimer;
#endif

struct datrec {
  uint32_t millitime;
  uint32_t microtime;
  uint32_t DWTCount;
  uint32_t byteswritten;
};

uint32_t logIndex = 0;
#define SAMPLERATE 20000
#define USE_PSRAM 1
#ifdef USE_PSRAM
#include <extRAM_t4.h>
extRAM_t4 eRAM;
#define BUFFSIZE  9190*2
//uint8_t config = 2; //0 - init eram only, 1-init flash only, 2-init both
//These have been replaced with defines for:
//INIT_PSRAM_ONLY
//INIT_FLASH_ONLY
//INIT_PSRM_FLASH
uint8_t config = INIT_PSRAM_ONLY;
// FAILS with 0x70050000 at offset 0x4000
struct datrec *dbuff0 = (datrec *)0x70000000;
struct datrec *dbuff1 = (datrec *)0x70090000;
uint32_t psram_base_addr = 0x70000000;
uint32_t sbuff0_addr = 0x70000000-psram_base_addr;
uint32_t sbuff1_addr = 0x70090000-psram_base_addr;

//define a struct joining MYDATA_t to an array of bytes to be stored
uint32_t arraySize = sizeof(datrec);
typedef union MYDATA4RAM_t {
 datrec datastruct;
 uint8_t Packet[sizeof(datrec)];
};
MYDATA4RAM_t readdata; //data read from memory
MYDATA4RAM_t mydata;   //data write to memory

#else  // THIS USES RAM1 and RAM2 buffer to show _isr() log works with same size buffers
#define BUFFSIZE  9190*2
struct datrec dbuff1[BUFFSIZE];
struct datrec *dbuff0 = (datrec *)malloc(BUFFSIZE*sizeof(datrec));
#endif


#define DEBUGPRINT true

int logging = 0;

char method = 0;

// these variables are declared volatile because they are changed or used in the
// interrupt handler
volatile uint16_t saveidx = 0;
volatile int16_t writebuffnum = -1;
volatile uint16_t savebuffnum = 0;
volatile uint32_t filestartmilli = 0;
volatile uint32_t byteswritten = 0;

const int ledpin = 13;

#define LEDON  digitalWriteFast(ledpin, HIGH);
#define LEDOFF digitalWriteFast(ledpin, LOW);

const char compileTime [] = "Timing Data Logger  Compiled on " __DATE__ " " __TIME__;
void setup() {
  if ( ARM_DWT_CYCCNT == ARM_DWT_CYCCNT ) {   // activate ARM cycle counter
    ARM_DEMCR |= ARM_DEMCR_TRCENA; // Assure Cycle Counter active
    ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
  }

  pinMode(ledpin, OUTPUT);
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial && millis() < 4000 );
  Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
  Serial.println(compileTime);
  // see if the card is present and can be initialized:
  Serial.print("Initializing SD card...");

#ifdef USE_PSRAM
  eRAM.begin(config);
  Serial.print("Start PSRAM for LOGGING :: ");
#else
  Serial.print("LOGGING from RAM :: ");
#endif

  Serial.printf("\nTwin buffers of size %u Bytes\n" , sizeof(datrec)*BUFFSIZE );
  Serial.println("Enter command selected from ( r, R{eRAM}, q, s, f, E(Erase), d(eRAM dump))");
}

void FastBlink(void) {  // blink forever
  while (1) {
    LEDON
    delay(50);
    LEDOFF
    delay(50);
  }
}

static uint32_t elapsedUS = 0;
uint32_t loopCnt = 0, loopSpd;
elapsedMillis elapsedLoop = 0;
void loop() {
  // put your main code here, to run repeatedly:
  char ch;
  uint32_t microselapsed;
  elapsedMicros wrtelapsed = 0;
  loopCnt++;
  if ( elapsedLoop >= 1000 ) {
    loopSpd = loopCnt;
    loopCnt = 0;
    elapsedLoop -= 1000;
  }

#ifdef USE_logtime
  if ( logging && logTime > LOG_US ) {
    logTime -= LOG_US;
    if ( logging == 1 )
      ADCChore();
    esle if ( logging == 2 )
      ADCChore_eRAM();
  }
#endif

  if (Serial.available()) {
    ch = Serial.read();
    if (ch == 'r') {
      method = 'r';
      StartLogging(1);
    }
    if (ch == 'R') {
#ifdef USE_PSRAM
      method = 'R';
      Serial.println(method);
      StartLogging(2);
#endif
    }
    if (ch == 'E') {
      eRAM.eraseDevice();
    }
    if (ch == 'd') {
      method = 'd';
    }
    if (ch == 's') {
      StopLogging();
      Serial.printf("SUCCESS:: working address ZERO at 0x70000000\n");
      dbuff0 = (datrec *)0x70000000;
      dbuff1 = (datrec *)0x70090000;
      sbuff0_addr = 0x70000000 - psram_base_addr;
      sbuff1_addr = 0x70090000 - psram_base_addr;
      Serial.printf("Buf0 Addr = %x, Buf1 Addr = %x\n", sbuff0_addr, sbuff1_addr);
    }

    if (ch == 'f') {  // FAILS with 0x70050000 at offset 0x4000
      StopLogging();
      Serial.printf("FAIL:: working address ZERO at 0x70050000\n");
      dbuff0 = (datrec *)0x70050000;
      dbuff1 = (datrec *)0x70090000;
      sbuff0_addr = 0x70050000 - psram_base_addr;
      sbuff1_addr = 0x70090000 - psram_base_addr;
      Serial.printf("Buf0 Addr = %x, Buf1 Addr = %x\n", sbuff0_addr, sbuff1_addr);
    }

    if (ch == 'q') {
      StopLogging();
      Serial.println("Enter command selected from ( r, R{eRAM}, q, s, f, E(Erase), d(eRAM dump))");
    }
  }
  // Now check to see if a buffer is ready to be written to SD
  // writebuffnum will be set in the interrupt handler
  if (writebuffnum == 0) { //is dbuff0 ready?
    LEDON
    writebuffnum = -1;
    if (1) { //if the file is open write dbuff0
      wrtelapsed = 0;
      WriteBinary(&dbuff0[0], BUFFSIZE);
      microselapsed = wrtelapsed;
      if (DEBUGPRINT) {
        loopCnt = loopCnt / (micros() - elapsedUS);
        Serial.printf("0] %6.2f mSec fill [lp#%lu] \t", (float)(micros() - elapsedUS) / 1000.0, loopSpd );
        Serial.print("Writing dbuff0 to data file.  tmilli = ");
        Serial.printf(" %lu  took %6.2f mSec\n", dbuff0[0].millitime, (float)microselapsed / 1000.0);
        elapsedUS = micros();
      }
    }
    LEDOFF
  }
  else if (writebuffnum == 1) { // is dbuff1 ready?
    LEDON
    writebuffnum = -1;
    if (1) { //if the file is open write dbuff0
      wrtelapsed = 0;
      WriteBinary(&dbuff1[0], BUFFSIZE);
      microselapsed = wrtelapsed;
      if (DEBUGPRINT) {
        loopCnt = loopCnt / (micros() - elapsedUS);
        Serial.printf("1] %6.2f mSec fill [lp#%lu] \t", (float)(micros() - elapsedUS) / 1000.0, loopSpd );
        Serial.print("Writing dbuff1 to data file.  tmilli = ");
        Serial.printf(" %lu  took %6.2f mSec\n", dbuff1[0].millitime, (float)(microselapsed) / 1000.0);
        elapsedUS = micros();
      }
    }
    LEDOFF
  }
  //delay(5);
}  // end of the loop() function

// write a buffer to the file as binary record. This  takes more time and file space than
// binary format, but can be directly read on PC.
// Note that we have to cast datrec pointer to a uint8_t pointer
// to keep the SD libraryhappy
static uint32_t firstWrap = 999;
static uint32_t overWrap = 999;
void WriteBinary(volatile struct datrec *drp, size_t numstructs) {

//  dataFile.write((uint8_t *)drp, numstructs * sizeof(datrec));

  Serial.printf(" \t BUFF at %lX\n", drp );
  uint32_t lastM = 0;
  uint32_t kk, lastB;
  uint32_t ii = 0, iiL = 0;
  if(method == 'r'){
      lastB = drp[0].byteswritten;
      for ( kk = 0; kk < numstructs; kk++) {
        if ( lastM != drp[kk].millitime || lastB != drp[kk].byteswritten ) {
          if ( overWrap == 999 ) {
            overWrap = ii - 1;
            Serial.printf(" \t HIDE overWrap of %lu  <<<<< \n", overWrap );
          }
          else if ( firstWrap == 999 ) {
            firstWrap = ii;
            Serial.printf(" \t HIDE firstWrap of %lu  <<<<< \n", firstWrap );
          }
          if ( lastM != drp[kk].millitime )
            lastM = drp[kk].millitime;
    
          if ( ii != iiL && ii != firstWrap && ii != overWrap ) {
            Serial.printf("skipped %lu\t", ii);
            Serial.printf("%lu, %lu, %lX, %lu\t", drp[kk].millitime, drp[kk].microtime, drp[kk].DWTCount, drp[kk].byteswritten);
            Serial.printf(" \t kk==%lu  ????\n", kk );
          }
          iiL = ii;
          ii = 0;
        }
        else
          ii++;
      }
      kk = numstructs - 1;
      Serial.printf("\tDONE %lu >> %lu, %lu, %lX, %lu\n", kk, drp[kk].millitime, drp[kk].microtime, drp[kk].DWTCount, drp[kk].byteswritten);
    
      //dataFile.write((uint8_t *)drp, numstructs * sizeof(datrec));
  } else if(method == 'R') {
      uint32_t ramAddr = (uint32_t *)drp;
      ramAddr -= psram_base_addr;
      uint32_t vmillitime = 0, vmicrotime = 0, vDWTCount = 0, vbyteswritten = 0;
      eRAM.readArray(ramAddr, arraySize, readdata.Packet);
      lastB = vbyteswritten;
      for ( kk = 0; kk < numstructs/sizeof(datrec); kk++) {
        eRAM.readArray(ramAddr+arraySize*kk, arraySize, readdata.Packet);
        vmillitime = readdata.datastruct.millitime;
        vmicrotime = readdata.datastruct.microtime;
        vDWTCount = readdata.datastruct.DWTCount;
        vbyteswritten = readdata.datastruct.byteswritten;
        if ( lastM != vmillitime || lastB != vbyteswritten ) {
          if ( overWrap == 999 ) {
            overWrap = ii - 1;
            Serial.printf(" \t HIDE overWrap of %lu  <<<<< \n", overWrap );
          }
          else if ( firstWrap == 999 ) {
            firstWrap = ii;
            Serial.printf(" \t HIDE firstWrap of %lu  <<<<< \n", firstWrap );
          }
          if ( lastM != vmillitime )
            lastM = vmillitime;
    
          if ( ii != iiL && ii != firstWrap && ii != overWrap ) {
            Serial.printf("skipped %lu\t", ii);
            Serial.printf("%lu, %lu, %lX, %lu\t", vmillitime, vmicrotime, vDWTCount, vbyteswritten);
            Serial.printf(" \t kk==%lu  ????\n", kk );
          }
          iiL = ii;
          ii = 0;
        }
        else
          ii++;
        } 
        kk = numstructs/sizeof(datrec) - 1;
        Serial.printf("\tDONE %lu >> %lu, %lu, %lX, %lu\n", kk, vmillitime, vmicrotime, vDWTCount, vbyteswritten);
    
        //dataFile.write((uint8_t *)drp, numstructs * sizeof(datrec));
   }
}

void ADCChore_eRAM(void) { // eRAM function access
  uint32_t tmilli;
  tmilli = millis() - filestartmilli;
  byteswritten += sizeof(datrec); // update global bytes written count
  // save in  the proper buffer--defined by savebuffnum
  if (savebuffnum == 0) { // put data in dbuff0
    mydata.datastruct.millitime = tmilli;
    mydata.datastruct.microtime = logIndex++;
    mydata.datastruct.DWTCount = (uint32_t)sbuff0_addr+psram_base_addr + (sizeof(datrec) * saveidx);
    mydata.datastruct.byteswritten = 0;
    eRAM.writeArray(sbuff0_addr + saveidx*sizeof(datrec), arraySize, mydata.Packet);
    //Serial.printf("%x\n", sbuff0_addr + saveidx*sizeof(datrec)+psram_base_addr);
    saveidx ++;
    if (saveidx >= BUFFSIZE) { // mark buffer for write to  SD
      Serial.printf("\t\t %d FULL e @ %lu sbuff>%lX \n", savebuffnum, saveidx, sbuff0_addr+ saveidx);
      writebuffnum = 0;
      savebuffnum = 1;   // start saving in other buffer on next interrupt
      saveidx = 0;  // start at beginning of next buffer
    }
  } else {  // must be saving to dbuff1
    mydata.datastruct.millitime = tmilli;
    mydata.datastruct.microtime = logIndex++;
    mydata.datastruct.DWTCount = (uint32_t)sbuff1_addr+psram_base_addr + (sizeof(datrec) * saveidx);
    mydata.datastruct.byteswritten = 1;
    eRAM.writeArray(sbuff1_addr + saveidx*sizeof(datrec), arraySize, mydata.Packet);
    saveidx ++; 
    if (saveidx >= BUFFSIZE) { // mark buffer for write to  SD
      Serial.printf("\t\t %d FULL e @ %lu sbuff>%lX \n", savebuffnum, saveidx, sbuff1_addr+ saveidx);
      writebuffnum = 1;
      savebuffnum = 0;   // start saving in other buffer on next interrupt
      saveidx = 0;   // start at beginning of next buffer
      if(method == 'd'){
        StopLogging();
        dump();
      }
    }
  }
}

void ADCChore(void) { // DIRECT ACCESS
  uint32_t tmilli;
  tmilli = millis() - filestartmilli;
  byteswritten += sizeof(datrec); // update global bytes written count
  // save in  the proper buffer--defined by savebuffnum
  if (savebuffnum == 0) { // put data in dbuff0
    dbuff0[saveidx].millitime = tmilli;
    dbuff0[saveidx].microtime =  logIndex++;
    dbuff0[saveidx].DWTCount = (uint32_t)dbuff0 + (sizeof(datrec) * saveidx);;
    dbuff0[saveidx].byteswritten = 0;
    saveidx++;
    if (saveidx >= BUFFSIZE) { // mark buffer for write to  SD
      Serial.printf("\t\t %d FULL D @ %lu &dbuff>%lX\n", savebuffnum, saveidx, (uint32_t)&dbuff0[saveidx]);
      writebuffnum = 0;
      savebuffnum = 1;   // start saving in other buffer on next interrupt
      saveidx = 0;  // start at beginning of next buffer
    }
  } else {  // must be saving to dbuff1
    dbuff1[saveidx].millitime = tmilli;
    dbuff1[saveidx].microtime =  logIndex++;
    dbuff1[saveidx].DWTCount = (uint32_t)dbuff1 + (sizeof(datrec) * saveidx);;
    //dbuff1[saveidx].byteswritten = byteswritten;
    dbuff1[saveidx].byteswritten = 1;
    saveidx++;
    if (saveidx >= BUFFSIZE) { // mark buffer for write to  SD
      Serial.printf("\t\t %d FULL D @ %lu &dbuff>%lX\n", savebuffnum, saveidx, (uint32_t)&dbuff1[saveidx]);
      writebuffnum = 1;
      savebuffnum = 0;   // start saving in other buffer on next interrupt
      saveidx = 0;   // start at beginning of next buffer
    }
  }
}

void StartLogging(int logType) {
  // we open in a mode that creates a new file each time
  // instead of appending as in the Arduino example
  if ( logging ) return;
  logging = logType;
  elapsedUS = micros();
  loopCnt = 0;
  firstWrap = 999;
  overWrap = 999;
  logIndex = 0;

  Serial.println("Starting logging");

  // initialize some variables for the buffers
  saveidx = 0;   // start saving at beginning of buffer
  savebuffnum = 0;  // start saving in dbuff0
  writebuffnum = -1;  // indicates no buffer ready yet
  //  start the interval timer to begin logging
  filestartmilli = millis();
  byteswritten = 0;
#ifdef USE_logtime
  logTime = 0;
#else
  if ( logging == 1 ) {
    Serial.println("PSRAM DIRECT _isr() logging");
    ADCTimer.begin(ADCChore, 1000000 / SAMPLERATE); //begin() expects timer period in microseconds
  }
  else if ( logging == 2 ) {
    Serial.println("PSRAM eRAM _isr() logging");
    ADCTimer.begin(ADCChore_eRAM, 1000000 / SAMPLERATE); //begin() expects timer period in microseconds
  }
#endif

}

void StopLogging(void) {
  if ( 0 == logging ) return;
  Serial.println("Stopping logging");
  logging = 0;
#ifdef USE_logtime
  logTime = 0;
  if (DEBUGPRINT) Serial.println("eMicros Log halted");
#else
  ADCTimer.end();
  if (DEBUGPRINT) Serial.println("ADCTimer halted");
#endif
  delay(10);
  writebuffnum = -1;
  Serial.printf("%lu KBytes written to file.\n", byteswritten / 1024);
  // in the interest of simplicity, we ignore any partial buffer at the end
}


void dump(){
  uint32_t kk;
  uint32_t vmillitime = 0, vmicrotime = 0, vDWTCount = 0, vbyteswritten = 0;
  uint32_t numstructs = BUFFSIZE;
  
  Serial.printf("DUMP OF BUFFER 0 at %x offset\n", sbuff0_addr);
  for ( kk = 0; kk < numstructs/sizeof(datrec); kk++) {
        eRAM.readArray(sbuff0_addr+arraySize*kk, arraySize, readdata.Packet);
        vmillitime = readdata.datastruct.millitime;
        vmicrotime = readdata.datastruct.microtime;
        vDWTCount = readdata.datastruct.DWTCount;
        vbyteswritten = readdata.datastruct.byteswritten;
        Serial.printf("\tbuff0 %lu >> %lu, %lu, %lX, %lu\n", kk, vmillitime, vmicrotime, vDWTCount, vbyteswritten);
  }
  
  Serial.printf("DUMP OF BUFFER 1 at %x offset\n", sbuff1_addr);
  for ( kk = 0; kk < numstructs/sizeof(datrec); kk++) {
        eRAM.readArray(sbuff1_addr+arraySize*kk, arraySize, readdata.Packet);
        vmillitime = readdata.datastruct.millitime;
        vmicrotime = readdata.datastruct.microtime;
        vDWTCount = readdata.datastruct.DWTCount;
        vbyteswritten = readdata.datastruct.byteswritten;
        Serial.printf("\tbuff1 %lu >> %lu, %lu, %lX, %lu\n", kk, vmillitime, vmicrotime, vDWTCount, vbyteswritten);
  }
}
 
@PaulStoffregen
Not sure if its my system but I can not seem to reach the T4.1 store now. Keeps telling site can not be reached?
 
@PaulStoffregen
Not sure if its my system but I can not seem to reach the T4.1 store now. Keeps telling site can not be reached?

I think the horde saw that it was released :D It is taking a few retries to get through!
 
Congrats Paul and Robin on getting the T_4.1 to market! It is a very nice upgrade to the T_4.0.

Indeed the PJRC.COM site is experiencing some traffic and being slow.

hackaday :: New Teensy 4.1 Arrives With 100 Mbps Ethernet, High-Speed USB, 8 MB Flash

hackster :: Teensy 4.1 Is the First Arduino-Compatible Board with 100 Mbit Ethernet

@mjs513 - Will catch up on PSRAM log code shortly

exp-tech shows they have :: Availability: 198

SPARKFUN has this typo/error :: Comment noted there
8MB > 128Mb Flash (64K reserved for recovery & EEPROM emulation)
Flash/RAM > 2 Additional Flash Memory Locations
8 Serial > 7 Serial, all with 4 byte FIFO
 
I tweaked the server config, increased "MaxRequestWorkers" from 150 to 800.

Can anyone confirm if the site is or isn't loading faster now?
 
I tweaked the server config, increased "MaxRequestWorkers" from 150 to 800.

Can anyone confirm if the site is or isn't loading faster now?

Feels much snappier to me!

Is the schematic available yet? It's the easiest way for me to map the pins for CircuitPython. Thanks!
 
Oh sweet Jesus I can finally order one! Sorry I haven't read through the thread in it's entirety but which audio shield is appropriate for the 4.1?
 
Is the schematic available yet? It's the easiest way for me to map the pins for CircuitPython. Thanks!

Nope, sorry. I hope to get to the schematic in a few days.

Here's a set of defines that might help.

Code:
// mux config registers control which peripheral uses the pin
#define CORE_PIN0_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_03
#define CORE_PIN1_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_02
#define CORE_PIN2_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_04
#define CORE_PIN3_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_05
#define CORE_PIN4_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_06
#define CORE_PIN5_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_08
#define CORE_PIN6_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_10
#define CORE_PIN7_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_01
#define CORE_PIN8_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00
#define CORE_PIN9_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_11
#define CORE_PIN10_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_00
#define CORE_PIN11_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02
#define CORE_PIN12_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_01
#define CORE_PIN13_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03
#define CORE_PIN14_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_02
#define CORE_PIN15_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_03
#define CORE_PIN16_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_07
#define CORE_PIN17_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06
#define CORE_PIN18_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_01
#define CORE_PIN19_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_00
#define CORE_PIN20_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_10
#define CORE_PIN21_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_11
#define CORE_PIN22_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_08
#define CORE_PIN23_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_09
#define CORE_PIN24_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_12
#define CORE_PIN25_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_13
#define CORE_PIN26_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_14
#define CORE_PIN27_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_15
#define CORE_PIN28_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_32
#define CORE_PIN29_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_31
#define CORE_PIN30_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_37
#define CORE_PIN31_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_36
#define CORE_PIN32_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_12
#define CORE_PIN33_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_07
#define CORE_PIN34_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_13
#define CORE_PIN35_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_12
#define CORE_PIN36_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_02
#define CORE_PIN37_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_03
#define CORE_PIN38_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_12
#define CORE_PIN39_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_13
#define CORE_PIN40_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_04
#define CORE_PIN41_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_05
#define CORE_PIN42_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_03
#define CORE_PIN43_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_02
#define CORE_PIN44_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_01
#define CORE_PIN45_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_00
#define CORE_PIN46_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_05
#define CORE_PIN47_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_04
#define CORE_PIN48_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_24
#define CORE_PIN49_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_27
#define CORE_PIN50_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_28
#define CORE_PIN51_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_22
#define CORE_PIN52_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_26
#define CORE_PIN53_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_25
#define CORE_PIN54_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_29
 
Nope, sorry. I hope to get to the schematic in a few days.

Here's a set of defines that might help.

Code:
// mux config registers control which peripheral uses the pin
#define CORE_PIN0_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_03
#define CORE_PIN1_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_02
#define CORE_PIN2_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_04
#define CORE_PIN3_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_05
#define CORE_PIN4_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_06
#define CORE_PIN5_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_08
#define CORE_PIN6_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_10
#define CORE_PIN7_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_01
#define CORE_PIN8_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00
#define CORE_PIN9_CONFIG        IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_11
#define CORE_PIN10_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_00
#define CORE_PIN11_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02
#define CORE_PIN12_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_01
#define CORE_PIN13_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03
#define CORE_PIN14_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_02
#define CORE_PIN15_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_03
#define CORE_PIN16_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_07
#define CORE_PIN17_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06
#define CORE_PIN18_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_01
#define CORE_PIN19_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_00
#define CORE_PIN20_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_10
#define CORE_PIN21_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_11
#define CORE_PIN22_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_08
#define CORE_PIN23_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_09
#define CORE_PIN24_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_12
#define CORE_PIN25_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_13
#define CORE_PIN26_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_14
#define CORE_PIN27_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_15
#define CORE_PIN28_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_32
#define CORE_PIN29_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_31
#define CORE_PIN30_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_37
#define CORE_PIN31_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_36
#define CORE_PIN32_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_12
#define CORE_PIN33_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_07
#define CORE_PIN34_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_13
#define CORE_PIN35_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_12
#define CORE_PIN36_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_02
#define CORE_PIN37_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_03
#define CORE_PIN38_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_12
#define CORE_PIN39_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_13
#define CORE_PIN40_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_04
#define CORE_PIN41_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_05
#define CORE_PIN42_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_03
#define CORE_PIN43_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_02
#define CORE_PIN44_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_01
#define CORE_PIN45_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_00
#define CORE_PIN46_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_05
#define CORE_PIN47_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_04
#define CORE_PIN48_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_24
#define CORE_PIN49_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_27
#define CORE_PIN50_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_28
#define CORE_PIN51_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_22
#define CORE_PIN52_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_26
#define CORE_PIN53_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_25
#define CORE_PIN54_CONFIG       IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_29

Perfect! That will get me going.
 
Oh sweet Jesus I can finally order one! Sorry I haven't read through the thread in it's entirety but which audio shield is appropriate for the 4.1?

The audio shield revision D (i.e. same as Teensy 4.0) can be used.

The 28 exterior pins for the 4.0 map exactly to to the first 28 pins (14 on each side) on the Teensy 4.1. Like the Teensy 3.5/3.6 in comparison to the Teensy 3.2, the 5 pins on the back of the Teensy are relocated. The audio shield doesn't use these pins. For other shields like the prop shield, you would need to run a wire for any of the pins you want to connect (on/off, program, ground, 3.3v, and Vbat for the real time clock).

Pins 24-33 that were on the bottom pads of the Teensy 4.0, now are exterior pins in the 4.1. The pads on the 4.0 for the micro-SD drive (pads 34-39) have been renumbered on the Teensy 4.1.

I have updated most of the fields in my giant spreadsheet that compares all Teensies:

But there might be a few places that I missed. Note, in that spreadsheet, I have hidden all of the columns that talk about the Teensy 3.0 to save a little bit of space. I also moved the initial comparison of the various Teensys (amount of memory, # of pins, etc.) to a separate sheet.

{edit}
At some point I need to update things that I wrote that compare the various Teensies in the unofficial wiki to mention the 4.1.
 
Last edited:
@tannewt - here is an update of my excel document... Image showing with T4.1 in it
T4.1-Cardlike.jpg

The document is up in my github project: https://github.com/KurtE/TeensyDocuments
Pages in the Teensy 4 xls document
 
congratulations @Paul.
I've seen on exp-tech.de thy will send same working day. :rolleyes: so they have them?
And a burning f***youverymuch to the USPS for freezing the beta for more than two weeks now.
 
Back
Top