Testing DMA on T4.1

ochsenkopf

New member
Hey,

I've tried to get the DMA running on my Teensy4.1. Until now unsuccessful. Im using Arduino2.0.3 on Windows. I've read through this post by miciwan trying to write from a single uint32_t to the GPIO1_DR to light up a LED connected to pin 23 (GPIO1_IO25 when i understood correctly).

I'm using
Code:
<DMAChannel.h>
and first tried to set it up with source() and destination() and trigger it by triggerManual() as well as triggerContinously().

I then looked into output_pwm.cpp in the Audio Library to set the DMA TCD up manually, but it didn't work as well.

I tested my GPIO configuration by just writing to GPIO1_DR directly and it worked fine.

Here's my full test code:

Code:
#include <DMAChannel.h>

DMAChannel dma;

// The content of this should be written to GPIO1_DR
uint32_t DMAMEM dmasource = 1 <<25;

void setup() {

  // Setup Pin23 / GPIO1_IO25 as Output on the low speed GPIO port

  IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_09 = 5;
  IOMUXC_GPR_GPR26 &= ~(0x0FCC0000u);

  GPIO1_GDIR |= 1 << 25;

  //GPIO1_DR = 1 <<25; // Tested the LED and wether my pin config is right. It worked

  dma.begin(true);
  dma.TCD->SADDR = &dmasource;       // getting data from the variable above
  dma.TCD->SOFF = 0;                         // dont change the adress afterwards
  dma.TCD->NBYTES = 4;                     // uint32_t is 4 bytes in size
  dma.TCD->DOFF = 0;                        // dont make changes to the destination adress
  dma.TCD->CITER = 1;                       // One minor loop of getting the 4 bytes
  dma.TCD->BITER = 1;
  dma.TCD->DADDR = &GPIO1_DR;     // Destination adress
  dma.enable(); // enabling the DMA 
  dma.triggerContinously();                 // triggering the DMA
  
}

void loop() {
  
}


Did I miss something obvious? Im kind of stuck at this point. Or does this even make sense? I just wanted to test the DMA functionality so I can use it later if needed
 
Sorry, each time I do DMA it takes a bit to get it working. And I have never tried triggerContinously. I typically would want it driven at some specific speed or the like.

Most of my usages have been with SPI and some with ADC pins.

Some example code in the system, to look at:

Paul has DMA output to pins in the OctoWS2811 library (part of Teensyduino release). Look at the OctoWS2811_imxrt.cpp file. - Note it uses timer and XBAR to connect up the timer.

The ADC library has code to do DMA inputs from ADC pins. It has examples of triggering it by completion of ADC operation, likewise it has example of triggering by timer.

Note: when I am working with DMA, whenever possible I try to avoid doing the direct mucking of the TCD registers, like SOFF, NBYTES...

Instead, I prefer to use the helper code/classes, that are port of the core code. Look at DMAChannel.h and .cpp which you are partially using.

But a lot of your code could be setup like:

Code:
  dma.begin(true);
  dma.source(&dmasource);
  dma.destination(&GPIO1_DR);
  dma.enable(); // enabling the DMA 
  dma.triggerContinously();                 // triggering the DMA

But again, would probably try to setup to do something, like timer
 
Thanks for your reply,

I actually tried it with the setup functions from the library at first. They didn't work neither.

I also looked into the WS2811_imxrt.cpp, but Paul mostly sets the DMAs up by writing to the TCD directly
I also tried attaching an interrupt on completion to test wether the DMA does anything and finishes. The interrupt did not execute once. So it really might has something to do with triggering.

I'll try setting up a timer and also will take a look into the reference manual later.
 
Here is one that blinks the LED...

Code:
// Quick and dirty sketch to see if I can blink the LED on T4.x using DMA.
//Which is pin GPIO 2 pin 3 
#define PIN_NUMBER 13
#include <DMAChannel.h>
DMAChannel dma1;
extern "C" {
  extern void xbar_connect(unsigned int input, unsigned int output);
  extern void quadtimer_init(IMXRT_TMR_t *p);
  extern void quadtimerWrite(IMXRT_TMR_t *p, unsigned int submodule, uint16_t val);
  extern void quadtimerFrequency(IMXRT_TMR_t *p, unsigned int submodule, float frequency);
}

uint32_t g_out_mask = 0;
uint8_t  g_pin_bit;
uint8_t  g_low_port_number; // 0 biased.


volatile uint32_t *standard_gpio_addr(volatile uint32_t *fastgpio)
{
	return (volatile uint32_t *)((uint32_t)fastgpio - 0x01E48000);
}

void initPin(uint8_t pin) 
{
  pinMode(pin, OUTPUT);  // make sure we start off as output.
  uint8_t bit = digitalPinToBit(pin);
  uint8_t offset = ((uint32_t)portOutputRegister(pin) - (uint32_t)&GPIO6_DR) >> 14;
  Serial.printf("pin %d, offset=%d, bit=%d\n", pin, offset, bit);
  g_pin_bit = bit;
  g_low_port_number = offset;
  g_out_mask = 1 << bit;
  Serial.printf("Mask: %x\n", g_out_mask);
  //bitmask[offset] |= g_out_mask;
  *(&IOMUXC_GPR_GPR26 + offset) &= ~g_out_mask;
  *standard_gpio_addr(portModeRegister(pin)) |= g_out_mask;
} 


void  qtimer_init(float freq)  // try at 20 hz for test...
{
  Serial.println("Try to init QTimer"); Serial.flush();
  quadtimer_init(&IMXRT_TMR4);
  quadtimerFrequency(&IMXRT_TMR4, 0, freq);
  quadtimerWrite(&IMXRT_TMR4, 0, 5);

  Serial.println("After Qtimer init"); Serial.flush();
}
void xbar_init() {
  CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON);   //turn clock on for xbara1
  xbar_connect(XBARA1_IN_QTIMER4_TIMER0, XBARA1_OUT_DMA_CH_MUX_REQ30);   // QTimer to adc_etc
	XBARA1_CTRL0 = 	XBARA_CTRL_STS0 | XBARA_CTRL_EDGE0(3) | XBARA_CTRL_DEN0;

  Serial.println("After xbar_init");
}

void dumpDMA(DMABaseClass *dmabc)
{
  typedef struct  __attribute__((packed, aligned(4))) {
  uint32_t SADDR;
  int16_t SOFF;
  uint16_t ATTR;
  uint32_t NBYTES;
  int32_t SLAST;
  uint32_t DADDR;
  int16_t DOFF;
  uint16_t CITER;
  int32_t DLASTSGA;
  uint16_t CSR;
  uint16_t BITER;
} TCD_DEBUG;
TCD_DEBUG *tcd = (TCD_DEBUG*)dmabc->TCD;
  Serial.printf("%08x %04x %04x %08x %08x ", tcd->SADDR, tcd->SOFF, tcd->ATTR, tcd->NBYTES, tcd->SLAST);
  Serial.printf("%08x %04x %04x %08x %04x %04x\n", tcd->DADDR, tcd->DOFF, tcd->CITER, tcd->DLASTSGA,
                tcd->CSR, tcd->BITER);
}


void dma_init() {
	dma1.begin();
  dma1.source(g_out_mask); 
  switch (g_low_port_number) {
    case 0: dma1.destination(GPIO1_DR_TOGGLE); break;
    case 1: dma1.destination(GPIO2_DR_TOGGLE); break;
    case 2: dma1.destination(GPIO3_DR_TOGGLE); break;
    case 3: dma1.destination(GPIO4_DR_TOGGLE); break;
  }
	dma1.triggerAtHardwareEvent(DMAMUX_SOURCE_XBAR1_0);
  dma1.transferCount(100);
	dma1.disableOnCompletion();

  dumpDMA(&dma1);
}

void setup() {
  // let pinMode setup pin 13 for us:
  while (!Serial && millis() < 4000) ; // don't need it but for debug
  initPin(PIN_NUMBER);
  qtimer_init(10.0);
  xbar_init();
  dma_init();
  dma1.clearComplete();
  dma1.enable();
  
  // Lets see if it completes
  Serial.println("Setup complete");
  elapsedMillis em;
  while (!dma1.complete()) {
    if (em > 1000) {
      Serial.printf("\tCITER:%u BITER:%u\n", dma1.TCD->CITER, dma1.TCD->BITER);
      em = 0;
    }
  }
  Serial.println("Completed DMA operation");
}

void loop() {
  // put your main code here, to run repeatedly:
  

}
Note: I probably cannot go as slow as I would like here, but could with some additional stuff, like maybe instead of fixed one value output,
Could be an array of N elements set up as a Circular buffer, with only one value that is not zero...
 
Quick update, here it is slightly extended.

Code:
// Quick and dirty sketch to see if I can blink the LED on T4.x using DMA.
//Which is pin GPIO 2 pin 3 
#define PIN_NUMBER 13
#include <DMAChannel.h>
DMAChannel dma1;
extern "C" {
  extern void xbar_connect(unsigned int input, unsigned int output);
  extern void quadtimer_init(IMXRT_TMR_t *p);
  extern void quadtimerWrite(IMXRT_TMR_t *p, unsigned int submodule, uint16_t val);
  extern void quadtimerFrequency(IMXRT_TMR_t *p, unsigned int submodule, float frequency);
}

uint32_t g_output_array[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t  g_pin_bit;
uint8_t  g_low_port_number; // 0 biased.


volatile uint32_t *standard_gpio_addr(volatile uint32_t *fastgpio)
{
	return (volatile uint32_t *)((uint32_t)fastgpio - 0x01E48000);
}

void initPin(uint8_t pin) 
{
  pinMode(pin, OUTPUT);  // make sure we start off as output.
  uint8_t bit = digitalPinToBit(pin);
  uint8_t offset = ((uint32_t)portOutputRegister(pin) - (uint32_t)&GPIO6_DR) >> 14;
  Serial.printf("pin %d, offset=%d, bit=%d\n", pin, offset, bit);
  g_pin_bit = bit;
  g_low_port_number = offset;
  g_output_array[0] = 1 << bit;
  Serial.printf("Mask: %x\n", g_output_array[0]);
  //bitmask[offset] |= g_output_array;
  *(&IOMUXC_GPR_GPR26 + offset) &= ~g_output_array[0];
  *standard_gpio_addr(portModeRegister(pin)) |= g_output_array[0];
} 


void  qtimer_init(float freq)  // try at 20 hz for test...
{
  Serial.println("Try to init QTimer"); Serial.flush();
  quadtimer_init(&IMXRT_TMR4);
  quadtimerFrequency(&IMXRT_TMR4, 0, freq);
  quadtimerWrite(&IMXRT_TMR4, 0, 5);

  uint32_t high = IMXRT_TMR4.CH[0].CMPLD1;
  uint32_t low = 65537 - IMXRT_TMR4.CH[0].LOAD;
  uint32_t highPlusLow = high + low; //
  uint8_t pcs = (IMXRT_TMR4.CH[0].CTRL >> 9) & 0x7;
  float actual_freq = (float)(F_BUS_ACTUAL >> pcs) / (float)highPlusLow;
  Serial.printf("Qtimer freq:%f, actual:%f low:%u, high:%u, hpl:%u\n", freq, actual_freq, low, high, highPlusLow);


  Serial.println("After Qtimer init"); Serial.flush();
}
void xbar_init() {
  CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON);   //turn clock on for xbara1
  xbar_connect(XBARA1_IN_QTIMER4_TIMER0, XBARA1_OUT_DMA_CH_MUX_REQ30);   // QTimer to adc_etc
	XBARA1_CTRL0 = 	XBARA_CTRL_STS0 | XBARA_CTRL_EDGE0(3) | XBARA_CTRL_DEN0;

  Serial.println("After xbar_init");
}

void dumpDMA(DMABaseClass *dmabc)
{
  typedef struct  __attribute__((packed, aligned(4))) {
  uint32_t SADDR;
  int16_t SOFF;
  uint16_t ATTR;
  uint32_t NBYTES;
  int32_t SLAST;
  uint32_t DADDR;
  int16_t DOFF;
  uint16_t CITER;
  int32_t DLASTSGA;
  uint16_t CSR;
  uint16_t BITER;
} TCD_DEBUG;
TCD_DEBUG *tcd = (TCD_DEBUG*)dmabc->TCD;
  Serial.printf("%08x %04x %04x %08x %08x ", tcd->SADDR, tcd->SOFF, tcd->ATTR, tcd->NBYTES, tcd->SLAST);
  Serial.printf("%08x %04x %04x %08x %04x %04x\n", tcd->DADDR, tcd->DOFF, tcd->CITER, tcd->DLASTSGA,
                tcd->CSR, tcd->BITER);
}


void dma_init() {
	dma1.begin();
  dma1.sourceCircular(g_output_array, sizeof(g_output_array)); 
  switch (g_low_port_number) {
    case 0: dma1.destination(GPIO1_DR_TOGGLE); break;
    case 1: dma1.destination(GPIO2_DR_TOGGLE); break;
    case 2: dma1.destination(GPIO3_DR_TOGGLE); break;
    case 3: dma1.destination(GPIO4_DR_TOGGLE); break;
  }
	dma1.triggerAtHardwareEvent(DMAMUX_SOURCE_XBAR1_0);
  
  dma1.transferCount(2000);
	dma1.disableOnCompletion();

  dumpDMA(&dma1);
}

void setup() {
  // let pinMode setup pin 13 for us:
  while (!Serial && millis() < 4000) ; // don't need it but for debug
  initPin(PIN_NUMBER);
  qtimer_init(50.0);
  xbar_init();
  dma_init();
  dma1.clearComplete();
  dma1.enable();
  
  // Lets see if it completes
  Serial.println("Setup complete");
  elapsedMillis em;
  elapsedMillis emTotal;
  while (!dma1.complete()) {
    if (em > 1000) {
      Serial.printf("\tCITER:%u BITER:%u Source:%x\n", dma1.TCD->CITER, dma1.TCD->BITER, dma1.sourceAddress());
      em = 0;
    }
  }
  Serial.printf("Completed DMA operation %u\n", (uint32_t)emTotal);
}

void loop() {
  // put your main code here, to run repeatedly:
  

}
 
Thanks for the quick reply!

I meanwhile found another solution using the PIT timers. They dont need setup through XBAR and only need DMAMUX to be enabled. (I guess they are hardwired, since the PIT number and DMA Channel number have to be the same).

On the other side, your XBAR setup and "auto detection" of the pin setup is more flexible and probably a better foundation for other triggers aside from PIT.

I really like both approaches. Maybe also these examples could provide a good starting point for getting into DMA stuff.

Code:
#include <DMAChannel.h>

DMAChannel dmaChannel0;
uint32_t DMAMEM buffer = 1<<25; // the buffer we want to write to


void dmaInterrupt(){
  dmaChannel0.clearInterrupt();	// tell system we processed it. 
  asm volatile("dsb"); // Got this from another thread, wait until the change to the register has been made, only works with this line

  buffer ^= 1 << 25; // modify data, in this case toggle bit 25, this could happen in otther places in code async
  arm_dcache_flush(&buffer, 1); // flush from cache directly to physical memory, otherwise it stays in cache.
}

void setup()
{

  // Setting up pin 23
  IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_09 = 5;
  IOMUXC_GPR_GPR26 &= ~(0x0FCC0000u);
  GPIO1_GDIR |= 1 << 25;

  dmaChannel0.channel = 0; // Ensure this is DMA channel 0 (Must be same as PIT)

  //Setting the source and destination
  dmaChannel0.source(buffer);
  dmaChannel0.destination(GPIO1_DR);
	
  // transferring 1 uint32 (= 4 bytes) once
  dmaChannel0.transferSize(4);
  dmaChannel0.transferCount(1);

  // attach Interrupt on completion
  dmaChannel0.interruptAtCompletion();  
  dmaChannel0.attachInterrupt( dmaInterrupt );
	
  DMAMUX_CHCFG0 = DMAMUX_CHCFG_ENBL | DMAMUX_CHCFG_TRIG | DMAMUX_CHCFG_A_ON ; //0xE0000000; Always On, Trigger On and DMAMUX enable
  dmaChannel0.enable();

  // Turn on PIT
  PIT_MCR = 0x00;
  PIT_LDVAL0 = 12000000 - 1; // 1/2 seconds
  PIT_TCTRL0 = PIT_TCTRL_TEN |  PIT_TCTRL_TIE; // 0x00000003; timer 0 enable and interrupt enable
    
}

void loop(){

}
 
Where is it documented that Teensy 4.1 pin 23 (AD_B1_09) is IO25 of GPIO1?
Is it in the processor reference manual?
Reference Manual
Yes, it is in the reference manual... It takes a little work to find all of the information.
So once Paul starts a Beta of a new board I will typically generate something like an excel document with information.
For example on the T4.1 I have a few pages including:
PinNameGPIOSerialI2CSPIPWMCANAudioXBARFlexIOAnalogSD/CSI/LCD
0AD_B0_031.3Serial1(6) RXSPI1(3) CS0PWM1_X12_RXIO-17
1AD_B0_021.2Serial1(6) TXSPI1(3) MISOPWM1_X02_TXIO-16
2EMC_044.4PWM4_A22:TX_DATAIO-061:4
3EMC_054.5PWM4_B22:TX_SYNCIO-071:5
4EMC_064.6PWM2_A02:TX_BCLKIO-081:6
5EMC_084.8PWM2_A12:RX_DATAIO-171:8
6B0_102.10PWM2_A2, QT4_11:TX3_RX12:10
7B1_012.17Serial2(4) RXPWM1_B31:TX_DATAIO-152:17, 3:17
8B1_002.16Serial2(4) TXPWM1_A31:RX_DATAIO-142:16, 3:16
9B0_112.11PWM2_B2,QT4_21:TX2_RX22:11
10B0_002.0SPI(4) CS0QT1_0MQS_RIGHT2:0
11B0_022.2SPI(4) MOSIQT1_21_TX2:2
12B0_012.1SPI(4) MISOQT1_1MQS_LEFT2:1
13B0_032.3SPI(4) SCKQT2_01_RX2:3
14/A0AD_B1_021.18Serial3(2) TXQT3_2SPDIF_OUT3:2A1:7, A2:7
15/A1AD_B1_031.19Serial3(2) RXQT3_3SPDIF_IN3:3A1:8, A2:8
16/A2AD_B1_071.23Serial4(3) RXWire1(3) SCLSPDIF_EXTCLK3:7A1:12, A2:12CSI_HSYNC
17/A3AD_B1_061.22Serial4(3) TXWire1(3) SDASPDIF_LOCK3:6A1:11, A2:11CSI_VSYNC
18/A4AD_B1_011.17Serial3(2) RTSWire(1) SDAQT3_13:1A1:6, A2:6
19/A5AD_B1_001.16Serial3(2) CTSWire(1) SCLQT3_03:0A1:5, A2:5
20/A6AD_B1_101.26Serial5(8) TX1:RX_SYNC3:10A1:15, A2:15CSI_D7
21/A7AD_B1_111.27Serial5(8) RX1:RX_BCLK3:11A1:0, A2:0CSI_D6
22/A8AD_B1_081.24PWM4_A01_TX3:8A1:13, A2:13CSI_D9
23/A9AD_B1_091.25PWM4_A11_RX1:MCLK3:9A1:14, A2:14CSI_D8
------------------------------------------------
24/A10AD_B0_121.12Serial6(1) TXWire2(4) SCLPWM1_X2A1:1
25/A11AD_B0_131.13Serial6(1) RXWire2(4) SDAPWM1_X3GPT1_CLKA1:2
26/A12AD_B1_141.30SPI1(3) MOSI1:TX_BCLK3:14A2:3CSI_D3
27/A13AD_B1_151.31SPI1(3) SCK1:TX_SYNC3:15A2:4CSI_D2
28EMC_323.18Serial7(7) RXPWM3_B1
29EMC_314.31Serial7(7) TXSPI2(1) CS1PWM3_A1
30EMC_373.23GPT1_33_RX3:MCLKIO-23
31EMC_363.22GPT1_23_TX3:TX_DATAIO-22
32B0_122.121:TX1_RX3IO-102:12
33EMC_074.7PWM2_B02:MCLKIO-091:7
34B1_132.29Serial8(5) RX2:29,3:29
35B1_122.28Serial8(5) TX2:28,3:28
36B1_022.18SPI(4) CS2PWM2_A31:TX_BCLKIO-162:18,3:18
37B1_032.19SPI(4) CS1PWM2_B31:TX_SYNCIO-172:19,3:19
38/A14AD_B1_121.28SPI1(3) CS01:rx_data3:12A2:1CSI_D5
39/A5AD_B1_131.29SPI1(3) MISO1:tx_data3:13A2:2CSI_D4
40/A16AD_B1_041.203:4A1:9,A2:9CSI_PIXCLK
41/A17AD_B1_051.21GPT2_13:5A1:10,A2:10CSI_MCLK
SD Pins - Cable connector(T4 34-39)
42SD_B0_033.15Serial5(8) RTSSPI2(1) MISOPWM1_B1IO-07DATA1
43SD_B0_023.14Serial5(8) CTSSPI2(1) MOSIPWM1_A1IO-06DATA0
44SD_B0_013.13Wire1(3) SDASPI2(1) CS0PWM1_B0IO-05CLK
45SD_B0_003.12Wire1(3) SCLSPI2(1) SCKPWM1_A0IO-04CMD
46SD_B0_053.17Serial5(8) RXFLEXSPI B_DQSPWM1_B2IO-09DATA3
47SD_B0_043.16Serial5(8) TXFLEXSPI B_SSO_BPWM1_A2IO-08DATA2
Bottom Memory Connectors
48EMC_244:24Serial8(5) RXFLEXSPI2_A_SS0_BPWM1_B0
49EMC_274:27Serial8(5) RTSFLEXSPI2_A_DATA01, SPI2(1) SCKPWM1_A21:13
50EMC_284:28Serial8(5) CTSFLEXSPI2_A_DATA02, SPI2(1) MOSIPWM1_B21:14
51EMC_224:22Wire1(3) SCLFLEXSPI2_A_SS1_BPWM3_B3, QT2_3
52EMC_264:26Serial1(6) RXFLEXSPI2_A_DATA00PWM1_B11:12
53EMC_254:25Serial1(6) TXFLEXSPI2_A_SCLKPWM1_A1
54EMC_294:29Serial1(6) RTSFLEXSPI2_A_DATA03, SPI2(1) MISOPWM3_A01:15

So it shows in 3rd column that is is 1.25 or GPIO 1 pin 25 (GPIO in normal mode), which is also GPIO 6 pin 25 (GPIO in fast mode)

How to derive: You can look at the source file ...\cores\teensy4\core_pins.h
You will see:

Code:
#define CORE_PIN23_BIT        25
#define CORE_PIN23_PORTREG    GPIO6_DR
So it shows GPIO6 and pin 25...

And then look through Reference manual for which pins are GPIO1 (manual shows normal mode)... You find:
1703109604666.png

There are other IOMUX pages and the like that show this as well: Probably the easiest to start with is this one:

1703110031880.png
 
Yes, it is in the reference manual... It takes a little work to find all of the information.
So once Paul starts a Beta of a new board I will typically generate something like an excel document with information.
For example on the T4.1 I have a few pages including:
PinNameGPIOSerialI2CSPIPWMCANAudioXBARFlexIOAnalogSD/CSI/LCD
0AD_B0_031.3Serial1(6) RXSPI1(3) CS0PWM1_X12_RXIO-17
1AD_B0_021.2Serial1(6) TXSPI1(3) MISOPWM1_X02_TXIO-16
2EMC_044.4PWM4_A22:TX_DATAIO-061:4
3EMC_054.5PWM4_B22:TX_SYNCIO-071:5
4EMC_064.6PWM2_A02:TX_BCLKIO-081:6
5EMC_084.8PWM2_A12:RX_DATAIO-171:8
6B0_102.10PWM2_A2, QT4_11:TX3_RX12:10
7B1_012.17Serial2(4) RXPWM1_B31:TX_DATAIO-152:17, 3:17
8B1_002.16Serial2(4) TXPWM1_A31:RX_DATAIO-142:16, 3:16
9B0_112.11PWM2_B2,QT4_21:TX2_RX22:11
10B0_002.0SPI(4) CS0QT1_0MQS_RIGHT2:0
11B0_022.2SPI(4) MOSIQT1_21_TX2:2
12B0_012.1SPI(4) MISOQT1_1MQS_LEFT2:1
13B0_032.3SPI(4) SCKQT2_01_RX2:3
14/A0AD_B1_021.18Serial3(2) TXQT3_2SPDIF_OUT3:2A1:7, A2:7
15/A1AD_B1_031.19Serial3(2) RXQT3_3SPDIF_IN3:3A1:8, A2:8
16/A2AD_B1_071.23Serial4(3) RXWire1(3) SCLSPDIF_EXTCLK3:7A1:12, A2:12CSI_HSYNC
17/A3AD_B1_061.22Serial4(3) TXWire1(3) SDASPDIF_LOCK3:6A1:11, A2:11CSI_VSYNC
18/A4AD_B1_011.17Serial3(2) RTSWire(1) SDAQT3_13:1A1:6, A2:6
19/A5AD_B1_001.16Serial3(2) CTSWire(1) SCLQT3_03:0A1:5, A2:5
20/A6AD_B1_101.26Serial5(8) TX1:RX_SYNC3:10A1:15, A2:15CSI_D7
21/A7AD_B1_111.27Serial5(8) RX1:RX_BCLK3:11A1:0, A2:0CSI_D6
22/A8AD_B1_081.24PWM4_A01_TX3:8A1:13, A2:13CSI_D9
23/A9AD_B1_091.25PWM4_A11_RX1:MCLK3:9A1:14, A2:14CSI_D8
------------------------------------------------
24/A10AD_B0_121.12Serial6(1) TXWire2(4) SCLPWM1_X2A1:1
25/A11AD_B0_131.13Serial6(1) RXWire2(4) SDAPWM1_X3GPT1_CLKA1:2
26/A12AD_B1_141.30SPI1(3) MOSI1:TX_BCLK3:14A2:3CSI_D3
27/A13AD_B1_151.31SPI1(3) SCK1:TX_SYNC3:15A2:4CSI_D2
28EMC_323.18Serial7(7) RXPWM3_B1
29EMC_314.31Serial7(7) TXSPI2(1) CS1PWM3_A1
30EMC_373.23GPT1_33_RX3:MCLKIO-23
31EMC_363.22GPT1_23_TX3:TX_DATAIO-22
32B0_122.121:TX1_RX3IO-102:12
33EMC_074.7PWM2_B02:MCLKIO-091:7
34B1_132.29Serial8(5) RX2:29,3:29
35B1_122.28Serial8(5) TX2:28,3:28
36B1_022.18SPI(4) CS2PWM2_A31:TX_BCLKIO-162:18,3:18
37B1_032.19SPI(4) CS1PWM2_B31:TX_SYNCIO-172:19,3:19
38/A14AD_B1_121.28SPI1(3) CS01:rx_data3:12A2:1CSI_D5
39/A5AD_B1_131.29SPI1(3) MISO1:tx_data3:13A2:2CSI_D4
40/A16AD_B1_041.203:4A1:9,A2:9CSI_PIXCLK
41/A17AD_B1_051.21GPT2_13:5A1:10,A2:10CSI_MCLK
SD Pins - Cable connector(T4 34-39)
42SD_B0_033.15Serial5(8) RTSSPI2(1) MISOPWM1_B1IO-07DATA1
43SD_B0_023.14Serial5(8) CTSSPI2(1) MOSIPWM1_A1IO-06DATA0
44SD_B0_013.13Wire1(3) SDASPI2(1) CS0PWM1_B0IO-05CLK
45SD_B0_003.12Wire1(3) SCLSPI2(1) SCKPWM1_A0IO-04CMD
46SD_B0_053.17Serial5(8) RXFLEXSPI B_DQSPWM1_B2IO-09DATA3
47SD_B0_043.16Serial5(8) TXFLEXSPI B_SSO_BPWM1_A2IO-08DATA2
Bottom Memory Connectors
48EMC_244:24Serial8(5) RXFLEXSPI2_A_SS0_BPWM1_B0
49EMC_274:27Serial8(5) RTSFLEXSPI2_A_DATA01, SPI2(1) SCKPWM1_A21:13
50EMC_284:28Serial8(5) CTSFLEXSPI2_A_DATA02, SPI2(1) MOSIPWM1_B21:14
51EMC_224:22Wire1(3) SCLFLEXSPI2_A_SS1_BPWM3_B3, QT2_3
52EMC_264:26Serial1(6) RXFLEXSPI2_A_DATA00PWM1_B11:12
53EMC_254:25Serial1(6) TXFLEXSPI2_A_SCLKPWM1_A1
54EMC_294:29Serial1(6) RTSFLEXSPI2_A_DATA03, SPI2(1) MISOPWM3_A01:15

So it shows in 3rd column that is is 1.25 or GPIO 1 pin 25 (GPIO in normal mode), which is also GPIO 6 pin 25 (GPIO in fast mode)

How to derive: You can look at the source file ...\cores\teensy4\core_pins.h
You will see:

Code:
#define CORE_PIN23_BIT        25
#define CORE_PIN23_PORTREG    GPIO6_DR
So it shows GPIO6 and pin 25...

And then look through Reference manual for which pins are GPIO1 (manual shows normal mode)... You find:
View attachment 32691
There are other IOMUX pages and the like that show this as well: Probably the easiest to start with is this one:

View attachment 32692
Wow, Thank you for the detailed response! This is great information!
 
Back
Top