I'm having
trouble catching every instance of a 1Khz interrupt. Most of the time
things are fine, but occasionally, my code misses an interrupt. I'm
using a modified version of andygryc's gps_pps device driver (see the
Files/Examples section of this website). I've changed that code to
watch a DIO pin for interrupts. When an interrupt arrives (1khz) the
device driver does 25 8-bit reads of the LCD header. I'm using the LCD
pins as an 8-bit wide input. These 200 bytes are available in
/dev/gps_pps (I haven't bothered to change the name's of Andy device.
Why break what's already fixed). I have a user-space program (included
below) which reads 6,000,000 bytes 200 at a time into a giant array,
then writes them to cf card. My data are 4-byte ints which means that
every time I run this program I get 1,500,000 samples in my data file.
At the moment my input data is simply a counter. Every group of 200
bytes is the same number, the next group is incremented by one, etc.
When I analyze the data I should have 50 samples of one number
followed by 50 samples of number + 1. Most of the time this is what I
get.
When I run my
user-space program (below) 905 times, I get
878 files just
as I expect
27 files which
missed at least one interrupt, many of these missing more than one
interrupt
286 total
missed interrupts
percentage-wise
this isn't bad. When there's a missing interrupt, it is usually just
one in a file, but sometimes a single file will have not only more than
one drop, but a drop that misses more than one interrupt. For instance
a file may have 37 drops, 2 individual drops (one near the front of the
file and one near the end) and a drop of 35 consecutive interrupts in
the middle! This is what's killing me.
I can't explain
why this happens. I didn't think I was doing that much. I know (by
watching the scope) that the transfer of 200 bytes from off board onto
the TS7260 takes less than 200 us. Leaving 800us before the next
interrupt arrives. My assumption is that the linux box itself gets
distracted once in a while and isn't free to service the interrupt.
I've tried to avoid this by including the setpriority and mlockall
commands in my user-space program. Both of those additions to the
program really helped improve the performance. I also turned off the
apache webserver. I've included a view of the system while the
user-space program is running below.
Based on the
PID number of those first few process, I probably can't get rid of
those. But I don't really know what they each do.
What can I do
to get this system to be stable? Any tips or tricks?
I should
mention that I'm using the TS-7260 running under busybox (and I'd
really like to keep it this way). The only thing NOT stock about this
board/system, is the user-space code and the device driver I've
installed. Otherwise, it's straight from TS. I just plugged it in and
copied my code over to it.
Thanks in
advance.
Peter
$ more
/proc/loadavg 0.74 0.68 0.65 1/19 18639$ ps PID Uid VmSize Stat Command
1 root 432 S /sbin/init 2 root SW [keventd] 3 root SWN [ksoftirqd_CPU0]
4 root SW [kswapd] 5 root SW [bdflush] 6 root SW [kupdated] 7 root SW
[mtdblockd] 67 root 564 S /sbin/udhcpc -H Default ts7260 -b -i eth0 80
1 368 S /sbin/portmap 85 root 648 S /usr/sbin/inetd 90 root 476 S
/usr/sbin/telnetd 110 root 520 S /sbin/getty -L 115200 ttyAM0 111 root
520 S /sbin/getty -L 115200 ttyAM1 117 root 756 S -sh 120 root 752 S
-sh 11089 root 372 S time ./dowritePeter.sh 11090 root 576 S
/bin/sh ./dowritePeter.sh 18638 root 7280 S < /root/read_gps_pps_LA
18640 root 592 R ps $
$ more
/proc/meminfo total: used: free: shared: buffers: cached:Mem: 62558208
20738048 41820160 0 266240 2285568Swap: 0 0 0MemTotal: 61092 kBMemFree:
40840 kBMemShared: 0 kBBuffers: 260 kBCached: 2232 kBSwapCached: 0
kBActive: 2128 kBInactive: 7416 kBHighTotal: 0 kBHighFree: 0
kBLowTotal: 61092 kBLowFree: 40840 kBSwapTotal: 0 kBSwapFree: 0 kB$
<code>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <stdint.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/mman.h>
int main(int argc, char **argv)
{
FILE*
file;
int buf_size=200;
char
buffer[buf_size];
int
i,j,k;
char *samples;
int num_seconds
= 30;
int num_bytes =
0;
int priority =
-20;
num_bytes
= num_seconds * 5 * 10000 * 4; // 5 chan * 10000 sps * seconds
sleep(2);
fprintf(stderr,
"read_device: setting priority to: %d\n", priority);
if(setpriority(PRIO_PROCESS,
0, priority)) {
fprintf(stderr,
"read_device: error setting priority\n");
return(-1);
}
fprintf(stderr,
"Trying to set aside %d byte array...", num_bytes * sizeof(char));
samples
= (char *)calloc(num_bytes,sizeof (char));
//
force 0 into every entry of samples
for
(i=0; i<num_bytes; i++) {
samples[i]=0;
}
if(samples
== NULL) {
fprintf(stderr,"\nNot
enough memory\n");
exit(1);
}
fprintf(stderr,
"Succeeded!\n");
file
= fopen("/dev/gps_pps", "rt");
if(file
== NULL) {
printf("Can't
open device\n");
return
-1;
}
fprintf(stderr,
"Result of mlockall command: %d\n",mlockall(MCL_CURRENT|MCL_FUTURE);
fprintf(stderr,"Starting
to read %d seconds of data.\n", num_seconds);
for
(j=0; j<num_bytes; j+=200) {
if
( (k=fread(samples+j, 1, sizeof(buffer), file) ) == NULL) {
break;
}
}
fprintf(stderr,"Read
%d of %d requested bytes.\n",j,num_bytes);
fwrite(samples,
sizeof(char), num_bytes, stdout); // dump the 8 bits we just read
to stdio
free(samples);
fclose(file);
return
0;
}
</code>