PTP (IEEE 1588) Library

All the examples should compile. I removed `stdPrint` (in favour of some other things) in v0.20.0. Are you sure you have the latest library version with all the matching examples?
 
I had cloned your repo under my ~/Arduino directory and was trying to build/run from there. I was getting the compile error. I went into the Arduino IDE and installed QNEthernet from there, which copied it to ~/Arduino/libraries/QNEthernet. Now when I load/build/run from there it works. Thanks.
 
I am starting work using the QNEEthernet library and I am trying to run an ISR whenever the IEEE1588 timer reaches a value. (mode kClearOnCompare)
This timer is very advantageous as it can be adjusted finely.
I Checked that the timer runs in the main loop and it indeed works.
If I understand well the default clocking makes the timer reach one second at 1e9

Here is the code :
C++:
#include <Arduino.h>
#include <QNEthernet.h>
#include <avr/io.h>
#include <avr/interrupt.h>
using namespace qindesign::network;

void GetSample() {
  // Read the timestamp of the last transmitted frame and clear the interrupt.
  //struct timespec timestamp;
  Serial.println("Interrupt triggered!");
  /*
  if (EthernetIEEE1588.readAndClearTxTimestamp(timestamp)) {
    // Do something with the timestamp, e.g., print it to the serial monitor.
    Serial.print("Timestamp: ");
    Serial.print(timestamp.tv_sec);
    Serial.print(" seconds and ");
    Serial.print(timestamp.tv_nsec);
    Serial.println(" nanoseconds");
  } else {
    Serial.println("Failed to read timestamp.");
  }
  */
}


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Starting Ethernet IEEE 1588 example...");
  qindesign::network::Ethernet.begin();
  qindesign::network::EthernetIEEE1588.begin();
  qindesign::network::EthernetIEEE1588.setChannelMode(0, qindesign::network::EthernetIEEE1588Class::TimerChannelModes::kClearOnCompare);
  //qindesign::network::EthernetIEEE1588.setChannelCompareValue(0, 20000); // 20 us 
  qindesign::network::EthernetIEEE1588.setChannelCompareValue(0, 50000000); // 500 ms
  qindesign::network::EthernetIEEE1588.setChannelInterruptEnable(0, true);
  IRQ_NUMBER_t irqNumber = IRQ_ENET_TIMER;
  attachInterruptVector(irqNumber, GetSample);
 NVIC_ENABLE_IRQ(IRQ_ENET_TIMER);
 

}

void loop() {
  // put your main code here, to run repeatedly:
  delay(1000);
  Serial.println("Main loop running...");
  Serial.print("Timer value: ");
   struct timespec timestamp;

  Serial.println(qindesign::network::EthernetIEEE1588.readTimer(timestamp));
  Serial.print(timestamp.tv_sec);
  Serial.print(" seconds and ");
  Serial.print(timestamp.tv_nsec);
  Serial.println(" nanoseconds");
}


However, the ISR (GetSample) does run, but not at the expected frequency. probably a lot faster than 500ms, seems to spam the serial monitor heavily, as if the compare mode or value was not set properly, or the order of operations is bad.
Has anyone already made it work ?
ps : this seems to be a reference thread for QNEEthernet1588, so I posted here...
 
The only application I know of that uses the 1588 timer is Teensy-NTP. In that application, the 1588 clock frequency is 25 MHz, which I think may be the default.

I don't think it could be 1 GHz. You could determine the approximate frequency by read the running timer at some interval (1 sec) and printing the value.
 
Well the i.MXRT1060 rev 3 reference manual states that this is a 1ns resolution timer, wrapping at 10e9.
I suppose it uses some PLL to increase its clocking to 1Ghz.
TSM.png

Extract from the reference manual, page 2115 and later.
As for my issue, the most relevant information in the manual is this, on page 2249, :
TCCR.png

I tried the correct sequence, setting the outputconpare value, then the channel mode to disable before setting outputCompare modes, and then setting outputcompare value again inside the ISR, but to no avail. I think I may disable the interrupt, and check in the loop() the frequency at which the TF flag is set, which means that the outputcompare has a match, reset the TF flag, and test again. It seems that the interrupt frequency is extremely high, since without a serial.print inside the ISR, serial prints inside the main loop do not display while the ISR is called continuously.
The code inside lw41.c seems all good and coherent with the reference manual registers at first glance.
 
Did you mean to put 500M in your call in Setup()? You only put 50M.

The only advice I can give is to look at Teensy-NTP and review its code. It does input capture using the 1588 timer but it must reduce its frequency to 25 MHz
 
Last edited:
The issue is resolved.

I forgot to clear the timer TF flag of the corresponding channel, 1 in my case in the ISR.
Also, I did not follow the full procedure.
The updated working properly full sketch is attached

Here is the relevant procedure in the Reference manual, page 2249 :

page_2249.png


ENET_TCSR1 |= ENET_TCSR_TF; // Clear the timer flag

Note that QNEEthernet fork library mention in my original post with IEEE1588 support does not expose this bit natively.

So I added :
#define ENET_TCSR_TF ((uint32_t)(1U << 7))
in my sketch.

The IRQ_ENET_TIMER is the correct vector.

ps : yes, there was a typo in the outputcompare value.
 

Attachments

  • IEEE1588_outputcompare_ISR.ino
    3.6 KB · Views: 13
Back
Top