Hi guys, I ran into a very strange problem. I have a C program which has a for loop and a usleep(100000) on the end, to execute this loop in 10 times per second. After I've measured the whole seconds delay in comparison with a usual handheld stopper it turned out, that the seconds on my mini2440 are slower than on a real clock - in a 45 seconds period I had a 10 seconds difference! The loop execution time using gettimeofday() takes something about 0.000006 seconds, so I don't think it's the content of the loop. How can I fix this?
usleep problem
usleep doesn't guarantee that your application will sleep for exactly 100000 nsecs, it guarantees that it will sleep for *at least* 100000 nsecs. The actual time depends on the kernel clock tickrate, so a small difference in timing is expected, but 10sec sounds a bit extreme. Did you try measuring the difference using the RTC on the mini2440? Its clock source is completely separate from the CPU core signal, so if the difference is really there the RTC and expected time should differ too. Perhaps you should also try and run a sleep(45) in a parallel thread (or something); if both sleeps are delayed by ~10 secs, then it's most likely a kernel issue (miscalculated HW timer freq); otherwise i suspect the kernel call overheads and timer imprecision slowly adds up.
Thanks Ceiliedgh, I tried to test the RTC with the test program which is given here: http://kernel.org/doc/Documentation/rtc.txt but I get some strange errors. The hwclock runs fine, /dev/rtc is also present, but in /proc/interrupts there is no information about the RTC. Seems like the RTC is not giving any IRQs? The test program gives me this error: "RTC_UIE_ON ioctl: Invalid argument" - I have not even the slightest idea why this happens. Is this because of a kernel config or is the error caused by something else?
The RTC_UIE_ON stuff isn't an issue I think. This is from the s3c RTC code: 324 case RTC_UIE_ON: 325 case RTC_UIE_OFF: 326 ret = -EINVAL; So I think UIE_ON its not supported for the S3C2440. Having 0 interrupts for the RTC is normal; the RTC only gives an interrupt if the RTC alarm registers are set up, otherwise the kernel simply polls it to read the hw clock.
Since I am not so familiar with using the RTC (/dev/rtc) in C, I tried to figure out what amount of time in the usleep command will delay the loop for exact a 1/10th of a second. Surprisingly at the amount of 70000 the delay was exactly the 1/10th of a second. I have checked this at a 15 minutes period with a stopwatch and there were no time difference. This is of course the dirty way, to achieve the right delay, but instead of this solution I would like to use the RTC. Have any of you guys any example code, how I could use the RTC as a 1/10th sleep timer? Thank you very much!
AFAIK the RTC doesn't have subsecond resolution (so it only stores seconds, but not milliseconds), so it cannot be used to sleep < 1 seconds. If the kernel timers are working properly, you could use something like this (though it's a bit of a hack): void sleep_hack(long interval_ms) { struct timespec start_ts; clock_gettime(CLOCK_MONOTONIC, &start_ts); long start_ms = start_ts.tv_sec * 1000 + start_ts.tv_nsec / 1000000; for (;;) { usleep(1000); struct timespec cur_ts; clock_gettime(CLOCK_MONOTONIC, &cur_ts); long cur_ms = cur_ts.tv_sec * 1000 + cur_ts.tv_nsec / 1000000; if (start_ms + interval_ms <= cur_ms) break; } } (untested code, i don't even know if it compiles!)