-
Notifications
You must be signed in to change notification settings - Fork 0
/
README
1198 lines (921 loc) · 45.2 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
----------------------------------------------------
spm2 - an open source Software Package with
kernel Modules and sample applications for
Scanning Probe Microscopy
----------------------------------------------------
Marcello Carla' <carla@fi.infn.it>
----------------------------------------------------
25-Nov-2009
----------------------------------------------------
=== Table of Contents
=== 1 Overview
=== 2 Supported Hardware
=== 3 Build
=== 4 Install
--- 4.1 Install options
=== 5 Operation of the feedback loop
--- 5.1 Add your own feedback algorithm
=== 6 The 'scan' device
--- 6.1 Operation of the device
--- 6.2 The scan parameters
--- 6.3 Stopping a scan
=== 7 User space programs
--- 7.1 frame
--- 7.2 gamp
--- 7.3 show
--- 7.4 genevent
=== 8 The utility devices nibac and iobac
--- 8.1 nibac and niconf
--- 8.2 iobac and ioconf
--- 8.3 mcbac
--- 8.4 nobac
=== 9 Measurement of interrupt response latency time
--- 9.1 latim_pp
--- 9.2 latim_pp options
--- 9.3 latim
=== 10 Credits
=== 1 Overview
This package implements in kernel space a digital feedback loop for the
control of a Scanning Probe Microscope apparatus. It can work with one or
two DAQ boards of different models made by several manufacturers. The first
DAQ board (the master) provides a clock in the form of a stream of interrupt
requests at regular time intervals (default value is 200 usec), an analog
input with typically eight ADC channels, an analog output, typically two DAC
channels, and some digital output lines.
Usually two DAC channels are not enough for a Scanning Probe Microscope, hence
two or more DACs can be provided by a second board (the slave). In this
implementation further resources from the slave board are not used (apart, if
desired, some more digital output line).
The spm code is arranged into several stacked kernel modules:
1) spm_dev: the core and base module, in charge of the 'scan'
device, through which an user space application has access
to the microscope operations.
2) one or two modules for specific hardware management, out of:
nibac: National Instruments Board Access Code
iobac: IOtech Board Access Code
mcbac: Measurement Computing Board Access Code
for the control of several models of DAQ boards, or
nobac: the no-board module for event simulation
(for debug and testing purposes)
3) spm_fc: the code that implements the feedback algorithm
In the package you should find the following:
spm_dev/ all required files to build and install
the 'spm_dev' core module.
nibac/
iobac/
mcbac/
nobac/ all required files to build and install
the 'nibac', 'iobac', 'mcbac' and 'nobac'
modules and the user-space configuration
programs 'niconf' and 'ioconf'.
include/ include files that define data structures
common to kernel modules and application
programs, mainly the 'spm_dev_data.h' file
that contains the description of data
structures common to both user and kernel
space code.
feedback/ a directory that contains the files to
implement the feedback algorithms This is
the place where to add new files for new
algorithms (see par. 5.1).
spm_fc a directory with support files for feedback
algorithm compilation.
user/ a few user application programs, see par. 7.
latim_pp/ all required files to build and install a
parallel port driver to measure the latency
time in response to an interrupt request
(see par. 9).
parameters.def default options for modules install.
Makefile
install
remove script files, see par. 3 and 4
The 'spm' package needs all the usual tools to build a kernel module
and C application programs: make, gcc, and the like, and the source
files for the target kernel properly installed and configured.
Moreover, the application programs contained in the user/ directory
require, properly installed:
gnuplot version 4.0 or later
Tcl/Tk version 8.3 or later
=== 2 Supported Hardware
National Instruments PCI-6221 id 1093:70af
PCI-6221 37-pin id 1093:71bc
Measurement Computing DAS-6014 id 1307:0079
Iotech DAQ-2001 id 1616:0409
(The Iotech DAQ-2001 board offers four DAC's, but cannot be
used as master because it has no interrupt circuitry).
Very likely many other boards of similar models can work
quite well; they are not in the list as it was not possible
to test them.
=== 3 Build
After downloading the spm-xxxxx.tgz package, place it in the preferred
<work directory> and give, as user, the following commands:
cd <work directory>
tar -xzvf spm-xxxxxx.tgz
cd spm
make
The command make should build recursively:
- the core module 'spm_dev'
- the driver for National Instruments boards (nibac)
- a user space program for N.I. boards setup (niconf)
- the driver for Iotech boards (iobac)
- a user space program for Iotech boards setup (ioconf)
- the driver for Measurement Computing boards (mcbac)
- the dummy no-board driver (nobac)
- a driver for the Parallel Port to measure the latency time to
the interrupt requests (latim_pp)
- a user program to perform a sample frame scan (frame)
- a user program to mesaure latency times (latim)
- a user program to generate dummy events with the nobac driver
(genevent)
- all feedback algorithms, both given with the package and
added by user
=== 4 Install
Become root and give the following command:
./install
The script file 'install' should do the following:
- scan the PCI devices list and identify the available supported
DAQ boards
- install the 'spm_dev' module, create the /dev/spm directory and
the 'scan' device
- assign the master and slave role to the DAQ boards previously found
- install the required nibac, iobac, mcbac, nobac modules
- populate /dev/spm with the utility devices nibac0, nibac1, iobac0 ...
as required
- set up the DAQ boards in their respective role and start the game
- install and link to other modules the feedback code ('spm_fc'
module)
This is the only step that requires root privileges. After that, revert to
normal user and verify that everything is o.k.
With the build procedure in par. 3, only a dummy feedback algorithm has
been loaded, that will read values from ADCs and simply write them to DACs.
However, this is enough to verify that the package is working correctly:
cd <work directory>/spm/user
./gamp & a window should open showing the 'spm_dev' and
'spm_fc' module parameters (see par. 6.2 for more
details)
./frame a dummy frame scan should start and complete
with informative messages and (possibly) no error
condition
Other informative messages (and possibly error conditions) are available with
the 'dmesg' command.
--- 4.1 Install options
Several options can be used with the install script; some of them
directly affect the install procedure, others are passed on to the
modules:
points=<int>
Number of points in each line of the frame, in the
range 1 ... whatever is reasonable.
lines=<int>
Number of lines in each frame. Range 0 ...
The value 0 stands for an endless scan, like in an
old chart recorder.
cadence=<int>
The interval time between two consecutive measurements
performed by the ADC (in usec).
The interrupt rate (cadence * samples) must be in the
range 100 usec ... 2 sec; the ADC sampling rate
(cadence / adc) must be not less than 5 us.
samples=<int>
Each point in the line contains 'samples' measurements
performed by the ADC with the given cadence. The valid
range depends on the DAQ board characteristics,
typically samples*adc <= 2047. This option, with n>1,
can be used only DMA is available.
adc=<int>
Number of ADC channels to be converted at each
'cadence' time interval. Typically DAQ boards have
one ADC with an 1 ... 8 channels multiplexer.
dac=<int>
Size of the DAC area in the event buffer. It may be
specified smaller than the available number of DAC
channels and extra DAC channels will be left unused
or written with zeros. It may also be specified
greater than the available number of DAC channels and
data in excess used to pass extra information to user
space. Range: whatever is reasonable, in the range 0
to infinity.
feedback=<name>
ufc=<name>
Name of the user feedback algorithm, i.e.the name of
the (suitable) file put by the user into the 'spm/
feedback' directory. If the option is not specified,
the install procedure will try in the order:
feedback_code
template
simple
and will load the first found.
All '.c' files that are in the 'feedback/' directory
at build time are compiled into feedback algorithms
to be loaded at run time; the algorithms are named
after their source files, without the '.c' suffix;
in the original package there is a 'template.c' and
a 'simple.c', but no 'feedback_code.c'; hence the
user can write his own code with that name and it will
become the default.
new
feedback code can be loaded, unloaded and reloaded
after other modules have been installed; if a
feedback module has already been loaded, you have
to specify 'ufc=<name> new' to get the previous
module unloaded and the new one installed; it is
safe from the point of view of the system to unload
the feedback algorithm even during a scan, but likely
this is a very crazy idea from the point of view of
an SPM experiment.
dma=<0/1>
Use DMA to read data from the ADC, if possible.
Usually this option is always on and it is left to
the DAQ board driver the choice to use it, if possible.
This option *must* be on in order to use samples > 1.
shared=<yes/no/try>
By default, while registering the interrupt handler
for the master board, the driver will try to play
unfair and request exclusive use of the interrupt
line; this is not the common practice with a PCI
device, but it can really give an advantage in the
interrupt servicing time and in the last this is what
we really want from the computer when using this
software; if the request fails, it will be repeated
for a shared line; with the option "shared=yes", the
first request for an exclusive line will be skipped,
with "shared=no" the handler registration will fail
if exclusive use of the irq line cannot be obtained
swap=<0/1>
When the system has two identical DAQ boards, the
first detected is master, the second slave. With
swap=1 the order is reversed.
major=<int>
Statically specify the 'major' device number. For
diagnostics and debug only.
irq=<int>
Statically specify an irq line. Only for diagnostics
and problems with the interrupt subsystem.
dummy try a dummy installation, writing the commands,
without really executing them
ni,io,mc,no=<int,int>
by default the install script looks for available
boards and assigns the roles according to two
preference rules:
master board: 1) NI 2) MC 3) NO
slave board: 1) IO 2) NI 3) MC
With the ni,io,mc,no options it is possible to override
default preferences, explicitly assigning the board
roles. For example, "ni=2,1" means "use the second
detected board as master, the first one as slave".
The first given value says which board is to be used
as master, the second value as slave. The boards are
numbered: 1=first detected board, 2:second detected
board etc.; the value 0 means "no board in this role".
Hence, 'ni=2,0' means "use second N.I. board as
master, do not use any of the N.I. boards as slave
latim with this option the latim_pp module is installed;
this option must appear as the first parameter after
the ./install command; other latim_pp options may
follow (see par. 9.2) and none of the options above
is recognized, but dummy.
All these options have a built-in default. Alternative defaults can
be specified in the file 'spm/parameters.def' (read it for know-how);
values given with the 'install' command override both.
=== 5 Operation of the feedback loop
The 'spm' package implements in kernel space, in a module, a Digital Signal
Processor (DSP), using a slice of the resources of the CPU, about from 5 to
20%.
As soon as the 'spm_dev' module and the driver(s) for the DAQ board(s) are
up, a stream of interrupts is generated by the master board with a given
cadence (default 200 usec). Each interrupt request comes at the end of one
or more ADC conversion cycle, according to the value given to the "samples"
option with the install command; in servicing the interrupt, the handler
performs all the required housekeeping to correctly acknoweledge the
interrupt, then reads the ADC values and executes a user-supplied function
in charge of the feedback algorithm; at the end of the function, the
'decisions' of the feedback algorithm are passed back to the handler in the
form of a vector of values to be written to the DAC to control the probe
movement(s). Then the handler exits.
This is an endless loop, that stays always active until the module(s) are
unloaded. It is in the nature of the Scanning Probe Microscopy: the
distance between the probe and the sample has to be continuously controlled,
even if no scan is actually performed.
--- 5.1 Add your own feedback algorithm
The main purpose of the 'spm' package is to offer an environment
that allows you to implement your own digital feedback algorithm
in a simple way, writing only the relevant code in plain C.
All other aspects of the hardware and software management should
be care of the package.
These are the rules of the game:
- When the master board is recognized and configured, a specific
interrupt handler is registered, nibac_irq_handler() or
mcbac_irq_handler(), depending upon the board brand and model.
This function is invoked after every interrupt generated by the
master board and is in charge of handling all the interrupt
bits and bytes with the hardware; (usually) you should not have
to worry about it.
- When the nibac/mcbac_irq_handler() function is done with its
bits and bytes, it executes the spm_irq_handler() function
that lives in the 'spm_dev' module, passing it a structure that
contains the data read from the ADC. The spm_irq_handler()
function takes care of the frame scan process. All of this also
should not worry the user.
- When everything is ready, spm_irq_handler() calls the user
supplied function feedback_code(), passing it all relevant
data; this function will perform all the computations the user
desires for his feedback algorithms, thereafter it will return
back to spm_irq_handler() and to the the hardware handler with
the data to be written to the DAC channels and, if the case,
to some digital output lines.
'feedback_code()' is the function that the user has to write and
drop into a file into the feedback/ directory. All '*.c' files
found in that directory at build time will result into a feedback
algorithm that will be available to be loaded and used as a module
at run time (see par. 4.1). So, please, no stale .c file in
feedback/.
The feedback/ directory originally contains three files:
template.c
a template file with a detailed description of the
passed data structure and many other useful
informations;
simple.c
an inspiring example of a simple but effective
feedback algorithm.
testchans.c
a simple routine to test all available ADC and DAC
channels: values from ADC's and to DAC's can be read
and written in the 'gamp' window (see par. 7.2)
=== 6 The 'scan' device
The device '/dev/spm/scan' is the normal access from user space to the
'spm_dev' module; it is created at install time with access permissions 0644
and the same owner and group as the spm_dev/install script.
An operation on the 'scan' device is started by a write, e.g.:
echo 's' > /dev/spm/scan
followed by a sequence of read's, e.g.:
od -w52 -t x4 /dev/spm/scan
The 's' is the start command; it can be followed by parameters, see later.
The command 'od ...' reads and displays in a raw way the (binary) data coming
from the device in operation, 52 bytes a time. This corresponds to the
built-in default of adc=8 dac=8 samples=1.
Data are arranged as events, each event being a data block composed of a
'struct event_head' data structure and two 'int16_t' data vectors of variable
size, for DAC's and ADC's values respectively, closely packed.
struct event_head {
struct irq_time { /* interrupt service time */
int32_t nsec;
int32_t sec;
} irq_time;
u_int8_t n_adc, n_dac; /* number of ADC's and DAC's */
u_int16_t samples; /* ADC samples per point */
u_int16_t adc_time; /* ADC read time */
u_int16_t service_time; /* total sevice time */
int8_t byte[2]; /* values to digital lines */
u_int16_t r_adc; /* actually read ADC values */
}
int16_t[n_dac]
int16_t[n_adc*samples]
The event data block cannot be statically defined as a structure because
the second and third fields are vectors of variable length. Macros are
given (and described) in the include/spm_dev_data.h file to handle a vector
of such data blocks as obtained from the 'scan' device.
The actual size of the event data block, in bytes, is shown in the 'slot'
variable among the 'spm_dev' parameters.
--- 6.1 Operation of the device.
Only a single user at a time can open the device. A second open request
is blocked until the current user releases the device. If a request
is made O_NONBLOCK, it returns immediately with error condition -EBUSY.
Concurrent operation is not accepted by the device: when there is a
pending read/write operation, a second one is blocked until the first
one completes.
Actually, writing the 's' command only arms the device, but it is the
first read request that really triggers the start of the frame scan.
This is so because after an operation has been started, data are
produced at the rate of an event data block for every interrupt; with
default values, this happens every 200 usec, producing data at a rate
of 260000 bytes per sec.
Data are stored in a circular buffer and must be retrieved by the
user through one or more read request. If enough data are in the
circular buffer at the time the user issues the request, the request
is satisfied immediately; otherwise, the requesting process is put to
sleep until enough data have been collected and transferred into the
user buffer.
Apart the standard error conditions recognized by the operating
system while validating the call, other possible error conditions
from a read/write request are:
write:
-EINTR a blocked request has been interrupted by a signal (Ctrl-C)
-EOMEM memory allocation failed
-EFAULT error while copying data from user space
-EBUSY previous operation has not been correctly completed
-EINVAL the request contained an invalid parameter
read:
-EINTR a blocked request has been interrupted by a signal (Ctrl-C)
-EPERM reading has been attempted but device was not armed
-EBUSY the device is in an odd state and needs to be reset
-EFAULT error while copying data to user space
-EIO data buffer overrun
-ECANCELED running operation stopped before completion
-ETIME the operation did not complete in due time
--- 6.2 The scan parameters
The parameters that characterize a scan operation are all accessible
through the /sys filesystem, as pseudo-files in '/sys/module/spm_dev
/parameters'. Their ownership is set to the owner of the install file,
hence they can be modified by the user (the writable ones).
There is a Tcl/Tk script ('gamp') to access graphically the parameters
(see example in par. 4). When 'gamp' starts, a window should open,
containing one entry per parameter. Parameters that can be modified
have a grey background; read-only ones have an orange background.
When a parameter is modified, its background switches to yellow, until
the new value is really committed, either pressing 'Enter' or
executing the 'apply' command in the 'actions' menu.
The command written to the scan device can be a single character,
as already seen:
's' arm a scan operation
'C' clear any pending operation and reset the device
(mainly useful to reset the 'scan' device after
some operating anomaly)
and can be followed by a second optional character (e.g. a line
feed), that is ignored.
The 's' command can be also issued as a part of a structure containing
the same information you can pass through the 'gamp' window, together
with further user data.
Clearly, this is not intended to be used with the simple command
echo 's' > /dev/spm/scan
as seen before (though not impossible); its purpose is to give a
user program a channel to pass the parameters for the scan it is
requiring. The sample program 'frame' uses this procedure to set
the scan characteristics.
The structure you can pass on is defined in 'include/spm_dev_data.h':
struct scan_params {
char code[2];
u16 mask;
u32 lines_per_frame;
u32 points_per_line;
u32 cadence_usec;
u32 buffer_size;
u32 buffer_size_min;
u32 high_water;
u32 timeout;
u32 samples_per_point;
u32 sample_adc;
u32 sample_dac;
};
and can be followed by a raw binary area
char pay_load[];
of whatever size, that will be made available to the feedback
code during the scan process.
The first byte of the structure (code[0]) is the 's' character;
it can be replaced by a ' ' (space character) to mean that you are
passing the scan parameters, but you do not want the scan be really
armed. A further single, repeatable, 's' will arm the scan operation.
The second byte of the structure is ignored.
The fields that follow specify the values for the scan parameters.
Every field that is filled with valid data must be declared in
'mask' with the flags defined in the include file:
...->mask =
LINES_PER_FRAME | POINTS_PER_LINE | .... | SAMPLE_DAC | PAY_LOAD;
Fields that are not declared in the mask are ignored, that is, they
retain their previous value, as shown in the 'gamp' window.
'lines_per_frame' and 'points_per_line' are self-explaining;
'lines_per_frame' can be set to zero. In this case the
line scan will go forever, until explicitly stopped
(see par. 6.3).
'cadence_usec' is the time interval between two successive ADC
conversions. If a value is given in this field, the master
board timer is set to this value before starting the new
scan. Valid values for 'cadence_usec' are in the range
100 usec <= cadence_usec * samples <= 1000000 usec, with
the further limit cadence_usec >= 40 usec; otherwise the
request is rejected with error code -EINVAL.
'buffer_size' is the size (in unit of 'event') of the circular
buffer used by the interrupt handler to save data; a
bigger buffer increases the probability of a failure in
memory allocation, but decrease the probabilty of a
data overrun if data are not retrieved in due time by
the user program.
The size of the buffer can be calculated roughly as
buffer_size = max_delay / cadence
where 'max_delay' is the maximum foreseeable delay that can
be expected between two data retrievals.
Example: max_delay = 2 sec, cadence = 200 usec
buffer_size = 2 / 200e-6 = 10000
'buffer_size_min': indeed, 'buffer_size' is only a hint for 'spm_dev';
a smaller buffer may be allocated if not enough memory is
available, but the smaller size is guaranteed to be not
smaller than 'buffer_size_min' or 2*points_per_line, whatever
is greater; otherwise the operation fails with the -ENOMEM
error code.
'high_water' specifies the filling level of the circular buffer
(as percent) at which data are transferred anyhow into the
user buffer, even if partially (default: 70%); however,
the read operation never returns with partial data only,
except in case of error or external stop.
'timeout' is the period of inactivity of the feedback loop after
which the module declares that something has gone wrong
and gives up. It is a severe condition of error usually due
to a hardware failure or bad configuration. 'timeout' is
expressed in msec.
'samples_per_point' specifies how many samplings the ADC has to
perform with the given cadence in a single event.
The event, hence the interrupt request, cadence is:
cadence * samples_per_point.
'sample_adc' specifies how many ADC channels are to be used for the
conversion. Only channels 1 ... sample_adc are read and
saved into the event buffer.
'sample_dac' is the size of the DAC vector.
'pay_load' is a raw area, as large as you want, where data can be
stored; this data will be made available to the user feedback
algorithm during the execution of the scan process.
The way these parameters are made available in the feedback code
is described in more detail in the file spm/feedback/template.c.
Note: some of the parameters can be selected only if the DAQ board
driver supports the operation. A request that cannot be satisfied
is rejected with a -EINVAL return code.
--- 6.3 Stopping a scan
Usually a frame is started and completes after 'lines_per_frame'
lines have been scanned, each line being composed of
'points_per_line' points; i.e., usually a frame contains
exactly 'points_per_line' * 'lines_per_frame' events.
Apart an error condition that may force a premature end of
a frame scan, a channel is provided through which a scan can
be cleanly stopped before its natural end. This is also the
natural way a scan is terminated after being started with
a zero value in 'lines_per_frame', which means "endless scan".
The stop request has two possible sources:
- the user feedback algorithm rises the flag
irq->request = Go_Idle;
and returns (see feedback/template.c); the current event is
completed, the user program is awakened with all completed
events in its buffer and a -ECANCELED condition is issued on
next data request.
- a stop code (65) is sent by the user to the 'spm_dev'
module either writing it into the 'irq_stop_request'
entry in the 'gamp' window, or directly into the /sys
pseudo-filesystem:
echo 65 > /sys/module/spm_dev/parameters/irq_stop_request
On the occurrence of next interrupt, the course of action
will be exactly as in the first case.
=== 7 User space programs
A few user space utilities are included in the 'spm2' package to implement
a few basic functionalities. You have already seen their usage in the
descriptions above. Here is a more detailed description.
--- 7.1 frame
'frame' is an user space process that starts a frame scan, collects
the data from the 'scan' device and stores and displays them.
Usage: spm/user/frame [OPTIONS]
Available options, as you can see with 'frame -h', are:
-a <int> minimum buffer size (events)
-b <int> buffer size (events)
-c <int> cadence (usec)
-h this help
-l <int> lines per frame
-p <int> points per line
-t <int> timeout (msec)
-v activate debug
-w <int> high water level
-D <string> command for distribution time analysis
-F show the frame
-C <int> ADC channel for image [0]
-R rescale data according to calibration table
-L <int> plot last n lines (0 ... 5) [3]
-S save frame data to file
Options -abclptw define the value of a scan parameter that corresponds
to a field in the 'scan_params' structure; their meaning is explained
in par. 6.2.
Every scan parameter that is not specified through some option retains
its value as it appears in the 'gamp' window.
The values in the 'gamp' window can be changed at any time, but
they are taken into effect only on the occurrence of next start
command.
Upper case options direct on line data display and analysis:
-D " " frame invokes the 'latim' utility to build and
analyze the distribution of the interrupt service
times; the string parameter with this option,
enclosed between quotation marks " ... ", is the
command line to 'latim' (see par. 9)
-F on line display of the frame that is being acquired;
a file is built in the tmpfs file system, containing
a PNM image, and updated continuously as new data
become available; a Tcl/Tk utility (show) opens a
window and plots the image, refreshing it after every
update; the path to the 'show' script is coded into
'frame' at build time; if you move the spm package
to another location, you have to rebuild it for this
feature to be usable.
-C <n> when using the -F option, -C <n> allows you to select
the ADC channel to be used as data source for the
image to be plotted; default is ADC 0.
-L <n> last <n> acquired lines are plotted in a xy graph,
using the 'gnuplot' program, that must be present
in the system, properly installed; the data channel
is selected through the -C option as in the case
of the frame display (-F); '-L 0' deactivates the
plot.
-S all data obtained from the frame scan, that is exactly
'lines_per_frame * points_per_line' event structures,
are stored in a binary file; the file name is time
stamped as 'log-yyyymmddhhmmss.dat'.
--- 7.2 gamp (Graphical Access to Module Parameters)
You have already encountered this Tcl/Tk script: it allows a graphical
access to a module parameters.
It is invoked as
spm/user/gamp
or
spm/user/gamp <module name> <module name> ...
A window will be opened with one entry for each parameter that is
declared by the module in '/sys/module/<module_name>/parameters/'.
By default 'gamp' opens two window, with access to the 'spm_dev'
and 'spm_fc' parameters, that control respectively the frame scan
process and the user feedback algorithm.
Parameters that can be modified have a grey background; read-only
ones have an orange background.
When a parameter is modified, its background switches to yellow,
until the new value is really committed, either pressing 'Enter'
or executing the 'apply' command in the 'actions' menu.
You must have write access to the parameters to be able to modify
them.
The values shown in 'gamp' window are refreshed with an interval
of 1 sec.
--- 7.3 show
A Tcl/Tk script for a very very light viewer of PNM images.
--- 7.4 genevent
This user space program builds pseudo-events that are delivered
from user space to the interrupt and feedback algorithms through
the 'nobac' module and device (par. 8.4).
Each delivered event contains a value in adc[0] computed according
a selected pattern.
Usage: genevent [OPTION]
-c <int> rate of event generation; this has nothing to do
with the time written into the event structure,
that will be computed from the 'cadence_usec'
parameter in 'spm_dev';
-t <int> top value for the adc scale [20000];
-b <int> bottom value for the adc scale [-20000];
-p <int> repetition period for the data pattern [200];
-r <int> reverse pattern after so many periods [0];
-s <...> select the pattern type among: ramp, triangle,
square, sin;
-f <...> read adc data from user data file
-v print some work statistics;
-h this help;
Moreover, an empty function is provided that can be used to add
manipulation of the event packets for any test and diagnostic
requirements.
=== 8 The utility devices and applications
National Instruments and Iotech DAQ boards are handled by their own drivers
'nibac' and 'iobac', but their configuration and set up is care of a user
space program, respectively 'niconf' and 'ioconf'.
--- 8.1 nibac and niconf
When the nibac module is loaded, the available supported boards
are recognized, taken over and registered; but they are not really
activated. In order to actually configure and activate the boards,
the nibac module implements the 'open', 'close' and 'mmap' file
operations. For each one board, the 'install' script creates a
device in /dev/spm: nibac0 for a master board, nibac1 for a slave
one. Then, after the module is up, 'install' starts the user space
program 'niconf', that maps the board register regions into its
address space and performs all required operations for complete
configuration and activation.
The code for 'niconf' is deeply a rewrite in plain C of the examples
in nimhddk_linux26.zip and nimseries.zip by N.I.
A few more information are available with "spm/nibac/niconf -h",
but, Warning:
the use of 'niconf' can be dangerous for the system
integrity, specially after the board has been made
operative; for this reason, access to nibac devices
is allowed only to the root user.
--- 8.2 iobac and ioconf
The same as in par. 8.1, for the Iotech DAQ boards.
The code for 'ioconf' has been adapted from the daqboard2000.c
driver in the comedi-0.7.76 package.
--- 8.3 mcbac
All work for Measurement Computing boards is made by the 'mcbac'
module; neverthless, the 'mmap' file operation is available, if
you want (dangerously) twiddle with the board registers.
--- 8.4 nobac
This module can be loaded instead of a true DAQ board driver and
its associated device (nobac0) used to generate dummy events.
Two different operating modes are possible:
- a user program (e.g. genevent, see par. 7.4) writes
prepacked events to nobac;
- nobac can be instructed to generate events under true
interrupt control and accurate timing (using the hrtimers).
This function is started with:
echo s > /dev/spm/nobac0
and stopped with
echo c > /dev/spm/nobac0
Events will contain a faked reading for ADC 0, built
according to a pattern selected among 'ramp', 'square'
and 'triangle', with three adjustable fields:
pattern_period: the pattern repetition period (in
events);
pattern_base: starting value of the pattern at
beginning of the period;
pattern_step: increment in ADC value after each
event.
These fields are accessible as parameters of the nobac
modules, hence through a 'gamp' window.
=== 9 Measurement of interrupt response latency time
Before using the 'spm' package for real work, you have to test if the time
response of the system to a lasting stream of interrupt requests is fast
enough.
This analysis can be performed collecting the service times of a sequence
of interrupts comparable with a typical application. Usually, we have used
a stream of six million events, with a cadence of one event every 128 usec.
You can get those time data directly from the 'spm_dev' module, if the
system already has a DAQ board that can act as master board; if you only
want to test the performance of some hardware configuration, with no DAQ
board installed, you can can use the 'latim_pp' module and a Parallel Port,
both the old legacy parallel port on the MotherBoard or a parallel port
adapter to be plugged into the PCI bus.
In any case, you can use the 'latim' user application, included in the
package, to acquire and analyze the response time distribution.
--- 9.1 latim_pp
True interrupt latency can be measured connecting a counter to the
parallel port; the counter increments at a stable and accurate rate
given by a clock and sends the computer an interrupt signal at some
predefined count values, thereafter goes on counting.
As soon as the interrupt service routine starts, it reads the counter
value, and this gives the interrupt servicing latency in units of the
counter clock period.
Alternatively, latency can be obtained measuring the time of occurrence
of a sequence of accurately spaced interrupt requests, as obtained
connecting an accurate external generator to the interrupt pin of the
parallel port; this alternative procedure can be used also programming
a DAQ board to generate such a sequence of events.
Only the external counter method can give the true distribution of
the latency times. The alternative approach will give the correct
distribution, but shifted along the time axis by an unknown constant
whose value has to be obtained by other means.
The 'latim_pp' module has been designed to handle both procedures;
it is built at the time the 'spm' package is built (see par. 3) and
can be installed with (as root):
cd <work directory>/spm/latim_pp
./install
The module should not be installed while the other modules of the
package are active; there is no problem about compatibility or
stability, but having both 'latim_pp' and 'spm_dev'+'xxbac' active
doubles the overhead on the system and may affect the responsiveness.
By converse, do not use 'latim_pp' while 'spm_dev' is working, unless
you are trying to stress your system.
When loaded, 'latim_pp' looks for a counter connected to the parallel
port. By the way, the port has to be configured as 'bidirectional' or
'EPP'. If an active counter is found, time measurements will be made
both with the external counter and the machine high resolution
internal clock; otherwise, the job will go on with the internal clock
alone. Anyway, a bit is always toggled, and can be read on a pin of
the parallel port, as soon as each interrupt request is serviced;
measuring with an oscilloscope the minimum delay between the interrupt
request and the response pulse the unknown constant is obtained.
The normal use of the toggle bit is to freeze the counter output
during the read operation.
Counter and PP bits are connected as follows:
PP PP counter PP PP counter
pin signal signal pin signal signal
1 strobe enable 10 acq irq
2 D0 out-0 11 busy out-11
3 D1 1 12 perror out-10
4 D2 2 13 select out-9
5 D3 3 14 autofd freeze
6 D4 4 15 fault out-8
7 D5 5 16 init freeze
8 D6 6 17 selectin freeze
9 D7 out-7 18-25 ground ground