accurate time resolution in ucLinux

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
I am developing on Moxa ucLinux box (200+mhz arm9), and I need to
execute either a process or pthread exactly once every 50ms +- 1ms.

I can poll the RTC and get usec resolution times, but I see that when
your timeslice is over, the scheduler does not get back to you until
10ms later, so polling alone won't guarantee accuracy. This happens for
blocking functions including usleep(). usleep(100) gives up a 10ms
slice. I need a low-latency pre-emptive mechanism. Is there one?

I was thinking of an interrupt routine, but there appear to be no hw
timers I can access directly.


Re: accurate time resolution in ucLinux
Quoted text here. Click to load it

I'm not sure if it is available also in ucLinux. Maybe you could try it.

Use a recent kernel with HRT (High Resolution Timer) support, add the RT
Preempt patch to this kernel and you will get what you want with the simple
POSIX function clock_nanosleep() for your purpose. With this kernel feature
you don't need a interrupt routine any more, everything can happen in
userspace (including hard realtime behaviour)

Here an example (works reliably only on HRT + RT Preempt kernels!):

/**
 * compile with:
 * gcc -lrt -o periodic periodic.c
 **/

#include <time.h>
#include <stdio.h>

#define NSEC_PER_SEC    1000000000L

static inline void timespec_add_ns(struct timespec *a, unsigned int ns)
{
        ns += a->tv_nsec;
        while(ns >= NSEC_PER_SEC) {
                ns -= NSEC_PER_SEC;
                a->tv_sec++;
        }
        a->tv_nsec = ns;
}

static inline int timespec_compare(const struct timespec *lhs, const struct
timespec *rhs)
{
        if (lhs->tv_sec < rhs->tv_sec)
                return -1;
        if (lhs->tv_sec > rhs->tv_sec)
                return 1;
        return lhs->tv_nsec - rhs->tv_nsec;
}

int main()
{
        struct timespec time, now;
        unsigned int interval = 100000000;

        clock_gettime(CLOCK_MONOTONIC, &time);
        while (1)
        {
                clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &time, 0);

                /**
                 * Do the periodic work here.
                 **/
                printf("Hello World\n");

                timespec_add_ns(&time, interval);

                /**
                 * Drop cycles if we are too slow.
                 * This is a failsave that might not be necessary or desired.
                 **/
                clock_gettime(CLOCK_MONOTONIC, &now);
                if (timespec_compare(&time, &now) < 0)
                {
                        time = now;
                        timespec_add_ns(&time, interval);
                        printf("Too Slow.\n");
                }
        }
        return 0;
}

Hope it helps
JB

Re: accurate time resolution in ucLinux

Quoted text here. Click to load it
<snip>

This sounds great.

After more reading I see that vanilla Linux could not meet my hard
real-time requirement even if my app were only a single process, and
probably even if put my crucial code in an isr. I am surprised that
these features were not built into the kernel long ago. After all I am
only trying to do what is easy for much slower 8-bit uCs (no OS).

I have been trying to see if the ucLinux kernel ported to this board
already has the HRT support and/or if it is suitable for this patch. I
don't have the uCLinux kernel source right now, but it is based on
2.6.19. The wiki on rt suggests I may need a newer version and that
uClib used by uCLinux has some problems with rt. There is a full Linux
kernel available for this board, but I believe it is kernel 2.6.9 which
may be too old.


Re: accurate time resolution in ucLinux

Quoted text here. Click to load it

2.6.9 *is* ways to old...

JB

Re: accurate time resolution in ucLinux
There is a full Linux
Quoted text here. Click to load it

What do you think is the oldest kernel that can still be used?

Re: accurate time resolution in ucLinux
Quoted text here. Click to load it

For HRT I believe you need at least 2.6.18 (or was it 2.6.20?). For RT
preempt you always should start with the most recent one. Our first ARM
XSCALE board support package with (a working) HRT support was 2.6.21 (but
without RT preempt). An ARM i.MX1 one was 2.6.20 (with HRT and RT preempt).
And a PowerPC one was 2.6.20 (which included RT preempt).

Is there mainline support for your platform?

JB

Re: accurate time resolution in ucLinux
Quoted text here. Click to load it

Not sure what 'mainline support' means. The specs are here:
http://www.moxa.com/product/UC-7110-LX.htm
I currently have the uClinux version, but a standard Linux is available
using the kernel versions I mentioned. The kernel/fs source is available
on request. I don't think it would be that easy to move to a new kernel
  and get all the custom pieces working in just a day or two (at least
for me). I've rebuilt a kernel before, but this seems like it could turn
into a porting effort. The processor is a custom die built for the
vendor and they already have many drivers/kernel modules the app depends
on. If all that had to be rebuilt and debugged it would just take too
long. I need a pretty quick solution.

This RT preempt seems too good for any embedded Linux vendor to pass up.
I need to ask Moxa about adding this.


Re: accurate time resolution in ucLinux
Quoted text here. Click to load it

This is not possible. Linux is not a hard real time OS so there is not
guarantee that you get a scheduling delay _much_ larger than 50 ms now
and then which will result in no execution in one of your 50 ms
intervals. There are several means to add hard realtime features t6o
Linux (e.g. RTAI).

-Michael


Re: accurate time resolution in ucLinux
Quoted text here. Click to load it
If it helps, I can simplify the chunk of code I need to be hard-realtime
to just a few writes to HW, something that could easily be done in an isr.

Re: accurate time resolution in ucLinux
Quoted text here. Click to load it
I now see that simply adding an isr does not guarantee real-time since
isrs on linux are all gated and not real-time isrs.

A second revelation is that the few writes I want to do in real-time are
writes to a serial port which are writes to a kernel driver buffer and
not to HW. Even with the RT preempt for the app code, the actual latency
will depend on when the driver code is run. I would probably need to
re-write the driver too.

Site Timeline