accurate time resolution in ucLinux

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.

Reply to
tns1
Loading thread data ...

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 #include

#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

Reply to
Juergen Beisert

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

Reply to
Michael Schnell

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.

Reply to
tns1

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.
Reply to
tns1

2.6.9 *is* ways to old...

JB

Reply to
Juergen Beisert

Juergen Beisert wrote: There is a full Linux

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

Reply to
tns1

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

Reply to
Juergen Beisert

Not sure what 'mainline support' means. The specs are here:

formatting link
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.

Reply to
tns1

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.

Reply to
tns1

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.