- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
Hallo liebe community,
für mein Projekt auf der Intel Edison Plattform benötige ich einen Timer/Timer-interrupt, welches alle 0,1ms (10kHz) ausgelöst wird. Soweit ich das sehe, ist der hrtimer in der aktuellen Poky-Distro nicht verfügbar, oder habe ich etwas übersehen? Mein Ziel ist, ein Signal mit 10 KHz über einen exteren Sensor (SPI) abzutasten und die Werte zu speichern. Besteht irgendeine Möglichkeit, das Problem auf Linuxebene zu lösen. Ich Arbeite mit Eclipse und C/C++ (kein Arduino)
Vielen Dank!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
Pedro's answer is great and it runs in a tight loop.
Here are a couple of helper-functions that I use, to create timers which send a signal (similar to an interrupt) to the app at specified intervals. You can specify the interval in seconds or nano-seconds.
// When any timer fires it will call here.
// The ID of the timer is stored in the si_value.sival_ptr member.
static void handler(int sig, siginfo_t *si, void *uc)
{
UNUSED(uc); // The user-context is almost universally never used.
UNUSED(sig); // We could check SIG against TIMER_SIG but why bother since it's the only signal we registered for?
static uint64_t seconds = 0;
// off_t filesize;
uint32_t param;
// Get the timer ID.
param = (uint32_t)si->si_value.sival_ptr;
switch (param) {
case ONE_SECOND_TIMER:
seconds++;
//discovery_tick();
if((seconds % 120)==0)
{
if(mcp->opts.logfd)
{
// Tell world how many lines we have logged.
sprintf(g_buf, "Logged %d Lines",mcp->opts.loglines);
mc->sendMqttIDMessge(g_buf, (char*)"canlog");
}
}
break;
case TWENY_MILLISECOND_TIMER:
mcp->tick(); // Call the Microchip-Can-Controller tick.
break;
default:
break;
}
}
// Schedule and start a timer. Specify a uniuqe ID and time in seconds and nano-seconds.
void startTimer(uint32_t id, long sec, long nsec)
{
struct sigaction sa;
struct itimerspec ts;
struct sigevent sev;
timer_t tid;
// Configure the signal action.
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler; // When the timer fires, it will call handler(...);
sigemptyset(&sa.sa_mask); // No masks.
// Establish a handler for our custom signal TIMER_SIG
if(sigaction(TIMER_SIG, &sa, NULL)==-1)
{
std::cerr << "Error in sigaction\n";
return;
}
// Configure the signal event structure
sev.sigev_notify = SIGEV_SIGNAL; // We wish to be notified using a SIGNAL
sev.sigev_signo = TIMER_SIG; // Use our custom signal number: TIMER_SIG
sev.sigev_value.sival_ptr = (void*)id;
// Configure the time-spec
ts.it_value.tv_sec = sec;
ts.it_value.tv_nsec = nsec;
ts.it_interval.tv_sec = sec;
ts.it_interval.tv_nsec = nsec;
// Create the timer
if(timer_create(CLOCK_REALTIME, &sev, &tid) == -1)
{
std::cerr << "Error in timer_create\n";
return;
}
// Start the timer.
if(timer_settime(tid,0,&ts, NULL)==-1)
{
std::cerr << "Error in settime\n";
}
}
I hope this helps too!
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
Hello tuma84,
Thanks for reaching out!
As you mentioned, Edison's standard image doesn't have hrtimer installed, therefore it is not possible to create a timer with this library by default. However, I created this small script that might help you. The script creates a loop that, I believe, will get you as close to 100us as a non-RTOS OS will get you.
# include
# include
int main (int argc, char** argv) {
struct timeval tvalBefore;
struct timeval tvalAfter;
long time_elapsed = 0;
gettimeofday (&tvalBefore, NULL);
long time_b_sec = tvalBefore.tv_sec;
long time_b_usec = tvalBefore.tv_usec;
while (time_elapsed < 100)
{
gettimeofday (&tvalAfter, NULL);
long time_a_sec = tvalAfter.tv_sec;
long time_a_usec = tvalAfter.tv_usec;
time_elapsed = ((time_a_sec - time_b_sec) * 1000000L + time_a_usec) - time_b_usec;
}
printf("Time in microseconds: %ld microseconds\n", time_elapsed);
return 0;
}
I hope this information helps you, and if you have any doubts, please don't hesitate to ask.
Pedro M.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
Pedro's answer is great and it runs in a tight loop.
Here are a couple of helper-functions that I use, to create timers which send a signal (similar to an interrupt) to the app at specified intervals. You can specify the interval in seconds or nano-seconds.
// When any timer fires it will call here.
// The ID of the timer is stored in the si_value.sival_ptr member.
static void handler(int sig, siginfo_t *si, void *uc)
{
UNUSED(uc); // The user-context is almost universally never used.
UNUSED(sig); // We could check SIG against TIMER_SIG but why bother since it's the only signal we registered for?
static uint64_t seconds = 0;
// off_t filesize;
uint32_t param;
// Get the timer ID.
param = (uint32_t)si->si_value.sival_ptr;
switch (param) {
case ONE_SECOND_TIMER:
seconds++;
//discovery_tick();
if((seconds % 120)==0)
{
if(mcp->opts.logfd)
{
// Tell world how many lines we have logged.
sprintf(g_buf, "Logged %d Lines",mcp->opts.loglines);
mc->sendMqttIDMessge(g_buf, (char*)"canlog");
}
}
break;
case TWENY_MILLISECOND_TIMER:
mcp->tick(); // Call the Microchip-Can-Controller tick.
break;
default:
break;
}
}
// Schedule and start a timer. Specify a uniuqe ID and time in seconds and nano-seconds.
void startTimer(uint32_t id, long sec, long nsec)
{
struct sigaction sa;
struct itimerspec ts;
struct sigevent sev;
timer_t tid;
// Configure the signal action.
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler; // When the timer fires, it will call handler(...);
sigemptyset(&sa.sa_mask); // No masks.
// Establish a handler for our custom signal TIMER_SIG
if(sigaction(TIMER_SIG, &sa, NULL)==-1)
{
std::cerr << "Error in sigaction\n";
return;
}
// Configure the signal event structure
sev.sigev_notify = SIGEV_SIGNAL; // We wish to be notified using a SIGNAL
sev.sigev_signo = TIMER_SIG; // Use our custom signal number: TIMER_SIG
sev.sigev_value.sival_ptr = (void*)id;
// Configure the time-spec
ts.it_value.tv_sec = sec;
ts.it_value.tv_nsec = nsec;
ts.it_interval.tv_sec = sec;
ts.it_interval.tv_nsec = nsec;
// Create the timer
if(timer_create(CLOCK_REALTIME, &sev, &tid) == -1)
{
std::cerr << "Error in timer_create\n";
return;
}
// Start the timer.
if(timer_settime(tid,0,&ts, NULL)==-1)
{
std::cerr << "Error in settime\n";
}
}
I hope this helps too!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
Hi SpiderKenny,
thanks a lot! That is exactly what I was looking for. It's working so far. I will do some further tests but it's already more accurate than my thread-based solution. I also thought about putting an external clock on one input pin and using the edison's interrupt. Of course I don't want to change my PCB-layout again

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page