High-speed digital I/O in teensy 4.1

kkutis1989

New member
Hi there,
I was trying to get fast digital iIO in teensy 4.1. Only use digitalWriteFast gives me a ~50ns window for GPIO toggling between HIGH and LOW. So I followed the code from https://forum.pjrc.com/index.php?th...ast-ring-oscillator-example.41874/post-132359

But when I compile there is an error:

C:
Arduino/my_project/sketch_jun4d/sketch_jun4d.ino:25:25: error: 'PORT_PCR_MUX' was not declared in this scope
   25 |     CORE_PIN20_CONFIG = PORT_PCR_MUX(1);
      |                         ^~~~~~~~~~~~

Error during build: exit status 1

My full code is:

C:
const int my_pulse_pin = 20;

void setup()
{
    pinMode(my_pulse_pin, OUTPUT);
    CORE_PIN20_CONFIG = PORT_PCR_MUX(1);
}

void loop()
{
    while(1){
        digitalWriteFast(my_pulse_pin, HIGH);
        digitalWriteFast(my_pulse_pin, LOW);
    }
}

Any hints for that?
 
Linked code was for T_3.6. Seems changing the slew rate that way doesn't apply to the T_4.x
For fastest TOGGLE use : digitalToggleFast(uint8_t pin)
Change in slew rate may still help.
 
For Teensy 4.x, use "CORE_PIN20_PADCONFIG |= 0xF9;" to configure pin 20 for the fastest possible mode.

Here is the complete code:

Code:
const int my_pulse_pin = 20;

void setup()
{
  pinMode(my_pulse_pin, OUTPUT);
  CORE_PIN20_PADCONFIG |= 0xF9;
}

void loop()
{
  while (1) {
    digitalWriteFast(my_pulse_pin, HIGH);
    digitalWriteFast(my_pulse_pin, LOW);
  }
}

I ran this just now, with all settings at defaults (CPU = 600 MHz). My scope sees a 150 MHz waveform on pin 20.

file.png



Should mention, measuring 150 MHz is not simple. My scope is rated for only 200 MHz (but I suspect it might actually have 350 MHz hardware) and my scope probes are rated for 700 MHz. But getting a good measurement requires directly touching the probe tip to pin 20, and a short wire from the probe's shield to the GND pin next to VIN and also the USB host header. If a normal length ground wire (a few inches, or ~8cm) is used the inductance of the wire ruins the high bandwidth measurement.


use digitalWriteFast gives me a ~50ns window for GPIO toggling between HIGH and LOW

As you can see in the scope screen capture, the entire waveform period is only 6.67ns, not anything like 50ns.
 
For measuring 150 MHz with a higher bandwidth scope, short ground wire is essential. Here is the wire I used for the measurement.

gndwire.jpg


If you use the ordinary ground wire clip, the measurement will be highly distorted and may not show the high frequency at all. Ground lead inductance is important for high bandwidth measurements!

Those ground clips on scope probes are really convenient for low bandwidth measurements, but a lot of people don't realize how they become problematic for higher bandwidth usage.
 
Last edited:
Thanks Paul for your Tips.

My 150 MHz signal with an Rigol MSO5104 (hacked to 350 MHz). I set the probe to x10 to make the measurement more precise.

C:
Code:
const int my_pulse_pin = 20;

void setup()
{
  pinMode(my_pulse_pin, OUTPUT);
  CORE_PIN20_PADCONFIG |= 0xF9;
}

void loop()
{
  while (1) {
    digitalWriteFast(my_pulse_pin, HIGH);
    digitalWriteFast(my_pulse_pin, LOW);
  }
}

RigolDS5.png
 
Last edited:
For this sort of signal speed a low-impedance probe might be the best option, basically a 10:1 probe with 500 ohms input impedance and using 50 ohm setting at the scope. High impedance probes are capacitive-dividers at the top end of their range which adds significant capacitive loading to the circuit still (6pF at 150MHz is 175 ohms or so, and at the 3rd harmonic is 60 ohms - this causes waveform distortion).

If your 'scope has a 50ohm option you can make a low-impedance probe with a bit of 50 ohm coax and a 470 ohm resistor soldered on the end. There are also 50ohm in-line BNC terminators you can use at the 'scope end to fake this.
 
The maximum current load for the GPIO output on the Teensy4 is 4mA. A 50 Ohm terminating resistor would overload the output

Teensy_GPIO_Current.png
 
50MHz pulse measurement with 1x probe and 50R Scope impedanz resistor

Scope 50R Impedanz Adapter
Scope 50R Impedanz.png

Bandbreitenmessung.png
RigolDS24.png
 
Last edited:
50MHz pulse measurement with 10x Probe, series 450R resistor and 50R Scope impedanz resistor.
I hope the measurement is correct :unsure:
Bandbreitenmessung2.png

RigolDS23.png
 
Last edited:
My best result was with a 50 ohm series resistor and a 50 ohm coaxial cable. Oscilloscope input impedance of 50 ohms.
Bandbreitenmessung_4.png

RigolDS28.png



Set GPPIO output impedance on Teensy4

C:
// 50MHz Puls signal on Teensy4
const int my_pulse_pin = 22;

void setup()
{
  pinMode(my_pulse_pin, OUTPUT);
 // CORE_PIN20_PADCONFIG |= 0xF9;

  int DRIVE_STRENGTH = 3; // vlaue from 0 to 7. (3 = 53R 3.3V)
  int SPEED = 3; // value 0 to 3  (3 = max GPIO speed 200MHz)
  *(portControlRegister(my_pulse_pin)) = IOMUXC_PAD_DSE(DRIVE_STRENGTH) | IOMUXC_PAD_SPEED(SPEED);
}

void loop()
{
  while (1) {
     digitalWriteFast(my_pulse_pin, HIGH);
    digitalWriteFast(my_pulse_pin, HIGH);
    digitalWriteFast(my_pulse_pin, LOW);
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
  }
}
 
Last edited:
Back
Top