I'm using Raspberry Pi 3 @ Raspbian
I've been trying to get the most precise timer or sleep function to achieve around 1-2us (micro seconds) resolution.
I've tried a few approaches and the best I could achieve was around 100-120us
Here is what I tested so far:
1. usleep()
Code: Select all
const useconds_t usec = 200000;
clock_gettime(CLOCK_MONOTONIC, &start);
usleep(usec);
clock_gettime(CLOCK_MONOTONIC, &stop);
exec_time = ( stop.tv_sec - start.tv_sec ) + ( stop.tv_nsec - start.tv_nsec ) / 1000000000.0;
printf("I. Sleep(%d) took time: %f\n", (unsigned int)usec, exec_time);
"I. Sleep(50) took time: 0.000137"
2. Using clock()
Code: Select all
clock_gettime(CLOCK_MONOTONIC, &start);
const clock_t start_tick = clock();
clock_t current_tick = clock();
clock_gettime(CLOCK_MONOTONIC, &stop);
printf("II. Current tick - start to: %u\n", (unsigned int)(current_tick-start_tick));
exec_time = ( stop.tv_sec - start.tv_sec ) + ( stop.tv_nsec - start.tv_nsec ) / 1000000000.0;
printf("II. Sleep took time: %f\n", exec_time);
"II. Current tick - start = 3
II. Sleep took time: 0.000030"
3. Using clock_nanosleep()
Code: Select all
struct timespec deadline;
clock_gettime(CLOCK_MONOTONIC, &deadline);
// Add the time you want to sleep
deadline.tv_nsec += 50000;
// Normalize the time to account for the second boundary
if(deadline.tv_nsec >= 1000000000)
{
deadline.tv_nsec -= 1000000000;
deadline.tv_sec++;
}
struct timespec start3, stop3;
clock_gettime(CLOCK_MONOTONIC, &start3);
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &deadline, NULL);
clock_gettime(CLOCK_MONOTONIC, &stop3);
exec_time = ( stop3.tv_sec - start3.tv_sec ) + (double)( stop3.tv_nsec - start3.tv_nsec ) / (double)1000000000.0;
printf("III. clock_nanosleep took time: %f\n", exec_time);
"III. clock_nanosleep took time: 0.000109"
1. So, as you see, methods I and III can't be lower than 100us. With method II I think clock_gettime() has some overhead, but I don't know how to figure out: "how many clock() ticks is 1us?".
2. I'm aware I'm compiling and running this code in a user space, so that might be a limitation. The question is how low I can get in the user space? 1us is it too much I expect? Would I get it compiling and running this proc in kernel space as a driver or kernel module?
3. Is there something I'm doing wrong with my implementations? Any hints how to make it more precise?
In the meantime I will try invoking asm nop instructions... I'm wondering what I will get.
Thanks for your advice!