NI Linux Real-Time Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Help to solve a problem with C++ on cRIO 9068

Solved!
Go to solution

I have been trying to create a timer function what could provide a millisecond and second "signal" to my application.  I have done very little with Linux and this is the first activity on NI equipment.  I have started with "getting started guide for C/C++with Linux RT" and the "Hello World" project.  I am trying to move an application from a legacy system, and with the help of the Linux Man Pages and the Eclipse help function, been able to perform many of the necessary functionality.  I have need to have a timer that can be used to time stamp data and have it synchronized with the wall clock. 

I have attempted to setup a timer function using the timer_create and timer_settime API calls.  The compiler portion seems to not have a problem with the calls, but the linker gives me the following error for both routines:

     undefined reference to "timer_create"

     undefined reference to "timer_settime"

From the Google searches that I made it indicated that it was necessary to have pthread as a specific library in the linker settings under the properties.  This was already in place.

Here is a copy of the routine I am trying to include in my build:

Thanks for the help

Ray

0 Kudos
Message 1 of 11
(5,022 Views)
Solution
Accepted by topic author RayManyik

You also need to link to"librt" to get those timer functions. "-lrt" should be added to the linker line. I don't think you need the pthread library for what you have in your code so far.

Eric

0 Kudos
Message 2 of 11
(4,384 Views)

Thanks Eric

I that seemed to remove the build errors.

I am building a multi threaded routine, so I am using the pthread library for other things (I believe)

Very much appreciated!

Regards

Ray

0 Kudos
Message 3 of 11
(4,384 Views)

I seem to be having a new problem.  A while back when I was working on creating multiple threads, I expected the program to terminate when the main thread exited.  I had to end up creating a call to pthread_kill and it had a signal handler (for SIGALRM).  At that point I was able to continue with development and debugging.

Now when I tried to add the code to create and set a timer with a real time signal, the program terminated right away.  From all I read on Google searches, it should be possible to have multiple handlers defined and not all handlers should cause the program to exit.  I put an #if 0 and #endif around all the code in my handler to be sure it was not inadvertently causing the program to exit.

Am I using the right tools?  What could I be missing?

0 Kudos
Message 4 of 11
(4,384 Views)

Can you expand a bit on what parameters are you using for the timer_create() call?

If you don't specify the second parameter (i.e. struct sigevent *sevp == NULL) the default behaviour is to send SIGALRM.

The trouble with SIGALRM is that it is a per-process signal.

Quoting 'man 7 signal':

A process-directed signal may be delivered to any one of the threads

that does not currently have the signal blocked.  If more than one of the  threads  has

the  signal  unblocked, then the kernel chooses an arbitrary thread to which to deliver

the signal.

0 Kudos
Message 5 of 11
(4,384 Views)

I attached the code in the original post that sets up the timer.  My objective is to have a timer that would run a handler to provide my application with a millisecond interrupt and a one second interrupt.  I don't know how the NI hardware and the Linux OS handle the clock and the timers.  I will eventually plan to provide my own system clock that I will keep in sync to about the millisecond accuracy with SNTP.  But for right now I will just try to use the OS's wall clock as the master.  I have moved my initial setup of the static clock structures to the setup routine, But the current code does the same setup for the "time_handle".  I did print out the SIG and it was 34, which I thought was a real time signal. 

Are you thinking that I could direct the signal to a specific thread?  I would like to do that as I would want the handler to run at the highest priority.  It has little to do and is going to be the most "real time" of the whole application.  Is there some way to block a signal for a thread during the create steps?

If I didn't answer all your questions, I would appreciate you asking me to clarify any points.  I can attach more information as pasting into this window with my browser.

I am most grateful for the help, as this has me stumped.

0 Kudos
Message 6 of 11
(4,384 Views)

   

I attached the code in the original post that sets up the timer.  My objective is to have a timer that would run a handler to provide my application with a millisecond interrupt and a one second interrupt.  I don't know how the NI hardware and the Linux OS handle the clock and the timers.

LabVIEW RT, on our Linux RT targets, takes advantage of the very good quality high-resolution timers support in the Linux kernel + PREEMT_RT patch.

We use the system clocks (CLOCK_REALTIME, CLOCK_MONOTONIC) for absolute and relative timing. This applies to the time based clock sources that drive our timed structures in LabVIEW Real-Time.

The absolute or real (i.e. wall-clock) system clock, CLOCK_REALTIME, can be synchronized by various means:

  • sntp utility - can be installed on the target by running:

          opkg update

          opkg install sntp

     as user 'admin' in a serial or ssh console connected to the target 9068.

  • NI-TimeSync - can be installed on the target via MAX. NI-TimeSync synchronizes your system time using the IEEE 1588-2008 Precision Time Protocol (PTP)
  • Because we are talking about Linux here there are a lot of other libraries and utilities for time synchronization you can re-use.
  • If you do end up writing your own implementation I recommend using adjtime() or adjtimex() to gradually adjust the system clock (applications can misbehave otherwise).

Are you thinking that I could direct the signal to a specific thread?  I would like to do that as I would want the handler to run at the highest priority.  It has little to do and is going to be the most "real time" of the whole application.  Is there some way to block a signal for a thread during the create steps?

The manual page for timer_create() http://man7.org/linux/man-pages/man2/timer_create.2.html explains how a signal could be directed to a specific thread in this section:

SIGEV_THREAD_ID (Linux-specific)

              As for SIGEV_SIGNAL, but the signal is targeted at the thread

              whose ID is given in sigev_notify_thread_id, which must be a

              thread in the same process as the caller.  The

              sigev_notify_thread_id field specifies a kernel thread ID,

              that is, the value returned by clone(2) or gettid(2).  This

              flag is intended only for use by threading libraries.

For your requirements (1 millisecond) using signals is probably going to work fine but you should know that signals have some overhead due to the mechanics of how they work in the Linux kernel - i.e. signals are delivered on the return path from a system call so if you have high priority threads doing a lot of work and not making calls into the kernel it can add latency.

From our benchmarks the lowest latency way to have a thread wake up at an absolute or relative time in the future is to use  clock_nanosleep(). Btw. clock_gettime() is the lowest latency way to get the time. When using clock_nanosleep() in a high priority thread the kernel will preempt other lower priority threads when the timer expires and will start running your thread (with some caveats of course; some sections of code in the kernel are not preemptable).

0 Kudos
Message 7 of 11
(4,384 Views)

Thanks for getting back to me.  Sorry but I have a number of other commitments so will need to time share this project. 

Sorry that Linus isn't something that I have had a lot of experience with.  I was going to load the preempt_rt but it doesn't look like something for Window and Eclipse, and I don't see anything like an installation guide or getting started.  Could you point me how to go about getting the patch installed or seeing if it already exists on my system?

The man page you referenced what I thought I was using to do the create and set timer actions.  As I read and re-read the page, I am beginning to see that it is not as simple as I thought it should be. 

But I did want to express that I appreciate your help.  I will get back with more once I can spend some time with this later in the week.

0 Kudos
Message 8 of 11
(4,384 Views)

PREEMPT_RT is a patch to the Linux kernel. It improves the determinism of the kernel. We already patch the kernels on our targets to include it so you don't actually have to do anything about it. It was more FYI.

Message 9 of 11
(4,384 Views)

Thanks for the input.  I gave on trying to use the timer and did use clock_nanosleep and was able to accomplish the objectives.  Since I use clock_gettime to measure how long I need to wait for the next wall clock time to be awaken, I can insure that the "signal" is going to be closely tied to the wall clock and I don't need to worry about any drift.

The is the "correct answer" for the issue uncovered with my first correct answer on just getting it to build.

Thanks for the support.

0 Kudos
Message 10 of 11
(4,384 Views)