Board: Jetson Orin NX
Kernel: 5.15.148
Hello,
we are experiencing a problem with the clock not being stable after ~6 minutes after boot.
When using simple code that sends one byte over UART every second, it works well for ~6 minutes, but starts to send each 0.92 seconds afterwards.
The code to test this is as follows:
int main() {
const char* uart_path = "/dev/ttyTHS1";
int uart_fd = open(uart_path, O_WRONLY | O_NOCTTY | O_SYNC);
if (!configureUART(uart_fd)) {
close(uart_fd);
return 1;
}
using namespace std::chrono;
auto next = steady_clock::now();
while (true) {
const char message = 255;
ssize_t bytes_written = write(uart_fd, &message, 1);
next += seconds(1);
std::this_thread::sleep_until(next);
}
close(uart_fd);
return 0;
}
I used a Saleae logic to measure the diff between two messages sent:
- I tried different modes using
nvpmodel, it did not change the behavior - I used jetson_clocks, it did not change the behavior
- I tried using the
performancegovernor, it did not change the behavior - I tried using different clocksources than
arch_sys_counter, it did not change the behavior
The behavior is always the same. After a reboot it works well for ~6 minutes, then it will always take 0.92 seconds instead of 1 second. It does not get worse, even after an hour it will still take 0.92 seconds instead of 1 second, so it is not some small drift, but one specific event.
Except of that 1 byte there is no other traffic on UART.
Based on the measured diffs I assume that the CPU frequency changes after some time and causes the time to be calculated incorrectly.
This is also confirmed by the following test:
#include <chrono>
#include <iostream>
#include <thread>
int main() {
using namespace std::chrono;
auto next = steady_clock::now();
uint64_t ticks_last = 0;
while (true) {
uint64_t freq;
asm volatile("mrs %0, cntfrq_el0" : "=r" (freq));
uint64_t ticks;
asm volatile("mrs %0, cntvct_el0" : "=r" (ticks));
std::cout << "ticks: " << ticks << " " << "freq: " << freq << std::endl;
std::cout << "diff: " << (ticks - ticks_last) / static_cast<double>(freq) << std::endl;
ticks_last = ticks;
next += seconds(1);
std::this_thread::sleep_until(next);
}
return 0;
}
Which prints the following in the problematic state:
ticks: 33085888182 freq: 31250000
diff: 0.923026
ticks: 33114742542 freq: 31250000
diff: 0.92334
ticks: 33143579730 freq: 31250000
diff: 0.92279
ticks: 33172436056 freq: 31250000
diff: 0.923402
ticks: 33201276706 freq: 31250000
diff: 0.922901
Did anyone observe similar problems already? Thanks.
