Synchronization with external CLK 50MHz

Sayansen

New member
I'm trying to set up an interrupt on the falling edge of an external clock to toggle a pin and replicate the clock on another output for analysis. It works up to around 5–8 MHz, but fails at higher frequencies. This is my first time using PlatformIO and Teensy programming—I started just yesterday. Most resources I found are for Teensyduino. I also attempted to implement a GP2 interrupt in bare-metal but wasn't successful. Any suggestions would be appreciated.

C:
#include <Arduino.h>

#define CLK_PIN 14 

#define TOGGLE_PIN 0



// Ultra-fast interrupt handler - placed in RAM for maximum speed

void __attribute__((section(".fastrun"))) clock_interrupt() {

    *(&CORE_PIN0_PORTREG) ^= CORE_PIN0_BITMASK;  // Single XOR instruction

}



void setup() {

    // Pin 0 setup using Teensy core macros

    *(&CORE_PIN0_CONFIG) = 5;  // Set mux mode to GPIO

    *(&CORE_PIN0_PORTREG + 1) |= CORE_PIN0_BITMASK;  // Set as output (GDIR register)

    *(&CORE_PIN0_PORTREG) &= ~CORE_PIN0_BITMASK;  // Set pin low (data register)

   

    // LED setup using Teensy core macros 

    *(&CORE_PIN13_CONFIG) = 5;  // Set mux mode to GPIO

    *(&CORE_PIN13_PORTREG + 1) |= CORE_PIN13_BITMASK;  // Set as output (GDIR register)

    *(&CORE_PIN13_PORTREG) &= ~CORE_PIN13_BITMASK;  // Set pin low (data register)

   

    // Pin 14 input setup

    *(&CORE_PIN14_CONFIG) = 5;  // Set mux mode to GPIO

    *(&CORE_PIN14_PORTREG + 1) &= ~CORE_PIN14_BITMASK;  // Set as input (GDIR register)

   

    // Test pin 0 toggle works

    for(int i = 0; i < 6; i++) {

        *(&CORE_PIN0_PORTREG) ^= CORE_PIN0_BITMASK;  // XOR toggle data register

        delay(100);

    }

   

    // Test LED toggle works 

    for(int i = 0; i < 6; i++) {

        *(&CORE_PIN13_PORTREG) ^= CORE_PIN13_BITMASK;  // XOR toggle data register

        delay(100);

    }

   

    // Attach interrupt

    attachInterrupt(digitalPinToInterrupt(CLK_PIN), clock_interrupt, FALLING);

}



void loop() {

    // LED blink using correct data register

    static uint32_t last_millis = 0;

    if (millis() - last_millis > 500) {

        last_millis = millis();

        *(&CORE_PIN13_PORTREG) ^= CORE_PIN13_BITMASK;  // XOR toggle LED data register

    }

}
 
I doubt 50 million interrupts per second is practical no matter what you do, but to go faster you'll need to use attachInterruptVector() instead of attachInterrupt(). You'll need to set up the hardware and ack the interrupt and other low-level details, which are details handled by the software layer of normal attachInterrupt() which is slower but handles all the hardware register stuff for you.

Here are some prior conversations with details.





To toggle the pin, writing to the toggle register will be slightly faster than XOR which involves a slow read, then modify and write.
 
What are you trying to do? I don't think the approach you are taking is viable, there may be a simple way to do it in hardware...
 
Sounds like a job for an FPGA at that speed, unless you can map the protocol onto a UART or SPI hardware, or build from discrete 74AHCxx logic perhaps, that series will clock at 50MHz at 3.3V.
 
Back
Top