The 2.6.24 kernel should have the high resolution timers that Thomas Gleixner and all have developed, but, you are still looking at a wake-up time of +/- 50-100 micro-seconds depending on the CPU, system loading, etc. So, you really should not go for a frequency of more than 1kHz under software control, and also only if you can tollerate a little error in the duty cycle and frequency. By the way, usleep just calls nanosleep, so you should probably just use nanosleep. nanosleep has the advantage that if the wait is interrupted by another interrupt, it tells you how much remaining you have to sleep, and you can sleep again. They created nanosleep with the idea that we will eventually get down into the nanosecond range for timer resolutions, but, that could be a ways off.
Finally, you really should start a thread that is woken up periodically. With using usleep, if there is a context switch after you are woken up, before you do the next sleep, your timing will be way off.
Below is some code I wrote to test periodic threads if you are interested.
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <pthread.h>
#include <sys/time.h>
timer_t timer_id;
pthread_t pthread_last;
struct timeval tv_last;
int sum;
bool first = true;;
void sig_thread_fn(union sigval sv)
{
struct itimerspec cur_value;
int over;
int diff;
pid_t pid;
struct timeval tv, tv_diff;
timer_gettime(timer_id, &cur_value);
gettimeofday(&tv, NULL);
timersub(&tv, &tv_last, &tv_diff);
diff = (cur_value.it_interval.tv_nsec / 1000) - tv_diff.tv_usec;
if (!first) sum += diff;
first = false;
over = timer_getoverrun(timer_id);
pthread_t self = pthread_self();
printf("expired!! (%s) overrun = %d, next in %ld ns, %ld µs late, %d, %d\n",
pthread_equal(self, pthread_last) ? "SAME!": "different",
over,
//cur_value.it_interval.tv_sec,
//cur_value.it_interval.tv_nsec,
//cur_value.it_value.tv_sec,
cur_value.it_value.tv_nsec,
(cur_value.it_interval.tv_nsec - cur_value.it_value.tv_nsec) / 1000,
diff, sum);
pthread_last = self;
tv_last = tv;
}
int main(int argc, char *argv[])
{
struct sigevent sigs;
struct itimerspec new_time;
int retval;
pid_t pid;
gettimeofday(&tv_last, NULL);
pthread_last = pthread_self();
sigs.sigev_notify = SIGEV_THREAD;
sigs.sigev_signo = 0;
sigs.sigev_value.sival_int = 0;
sigs.sigev_notify_function = sig_thread_fn;
sigs.sigev_notify_attributes = NULL;
//sigs.sigev_notify_thread_id;
//sigs.sigev_notify_thread_id = 0;
retval = timer_create(CLOCK_MONOTONIC, &sigs, &timer_id);
new_time.it_interval.tv_sec = 0;
new_time.it_interval.tv_nsec = 500000000; //
new_time.it_value.tv_sec = 0;
new_time.it_value.tv_nsec = 500000000; //
printf("return value from timer_create(): %d\n", retval);
retval = timer_settime(timer_id, 0, &new_time, NULL);
printf("return value from timer_settime(): %d\n", retval);
while(true)
{
printf("main_loop !!\n");
sleep(5);
}
}
On Tue, Jul 19, 2011 at 1:07 PM, Jon L
<m("yahoo.com","jleslie48");" target="_blank" href="/mc/compose?to=">> wrote:
say I want to pulse a digital output pin to pulse with a ts-7500 with a 50% duty cycle.
what is the fastest signal I can get and what is the best way to program such a signal?
I can only think of this in C:
do {
sbuslock();
setdiopin(pin, 0);
usleep(1);
setdiopin(pin,1);
sbusunlock();
}
while ( hell_not_frozen_over);
but is this reliable?
and what will this do to the other processes running on the system?
is this a cpu hog or is there a better way to do this?
--
Dr. Donald W. Carr
Arrayán #21, Zapopan, Mexico
Work +52-333-836-4511 (direct)
Work +52-333-836-4500 ext 2930
Home +52-331-562-4370
Cell 331-269-3416