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
|
README for RTAPI
RTAPI is a wrapper API that allows realtime programs to use either
RTLinux or RTAI with no code changes.
Files:
Makefile : the Makefile
README : this file
rtapi.h : decls for the generic RTAPI functions.
rtapi_app.h : decls for the kernel modules
rtapi_common.h : Collection of typedefs, etc, used internally by RTAPI.
procfs_macros.h : Macros used to impliment the /proc interface
rtapi_proc.h : more stuff implementing the /proc interface
rtai_rtapi.c : implementation of real-time API, for RTAI
rtai_ulapi.c : implementation of user-level API, for RTAI
rtl_rtapi.c : implementation of real-time API, for RTL
rtl_ulapi.c : implementation of user-level API, for RTL
sim_rtapi.c : implementation of real-time API, for Linux simulation
sim_ulapi.c : implementation of user-level API, for Linux simulation
../../Makefile.inc : contains compile-time flags, etc.
../../configure : script that creates Makefile.inc
The Build Process
-----------------
The build process follows the standard Linux convention:
./configure
make
The configure script and make are intended to be run from the
root of the emc2 tree, to make the entire emc2 project. See the
README in that directory for more details.
To run the examples:
1. Open a shell window, and begin watching the kernel log:
tail -f /var/log/messages
leave this running, and go back to your original shell window
you should be in the emc2 directory
2. Load the RTOS and RTAPI modules:
Note: for this and most of the following steps you will need
to be root, or use 'su -c "<command>"'
scripts/load_rtapi
See a number of messages pop up in the kernel log as components
of the RTOS are installed...
One of the last ones will be:
<date> <time> <host> kernel: RTAPI: Init complete
This means that the rtapi module (either rtl_rtapi.o or
rtai_rtapi.o) is loaded.
3. Run the timer task example:
/sbin/insmod rtlib/timertask.o
A few messages will pop up in the kernel log as the task
is created and started:
<date> <time> <host> kernel: timertask init: desired clock 10000000, actual 10000168
<date> <time> <host> kernel: timertask init: started timer task
<date> <time> <host> kernel: timertask init: max delay = 2500042
Wait a few seconds, then remove the module:
/sbin/rmmod timertask
A couple more messages from timertask:
<date> <time> <host> kernel: timertask exit: timer count is 8174
This means that 8174 calls to the task were made. (I let it
run for about 8 seconds.)
4. Run the parallel port interrupt example:
/sbin/insmod rtlib/extint.o
Short pin 10 to pin 25 on the parallel port a couple of times to
generate some interrupts, then view the count in the kernel log:
/sbin/rmmod extint
Again, you'll get messages from the extint module:
<date> <time> <host> kernel: extint: interrupt count is 2522
This means 2,522 interrupts occurred, many for a single short
of pin 10 due to contact noise.
5. Run the shared memory example:
/sbin/insmod rtlib/shmemtask.o
bin/shmemusr
See the shared memory heartbeat incrementing.
Use crtl-C to break out of shmemusr.
Then remove the realtime task
/sbin/rmmod shmemtask
6. Run the semaphore example:
/sbin/insmod rtlib/master.o
The master task will start giving the semaphore once per
second, printing to the log when it does.
/sbin/insmod rtlib/slave.o
The slave attempts to get the semaphore, and prints each
time it succeeds. Since the master has already given the
semaphore several times, and it is a counting semaphore,
the slave will run several times in a row. Once it catches
up with the master, it will run right after the master runs.
Stop the tasks in reverse order:
/sbin/rmmod slave
/sbin/rmmod master
7. Run the FIFO example:
/sbin/insmod rtlib/fifotask.o
The realtime fifotask will begin writing strings to the
fifo once per second, and echoing the strings to the log
file.
bin/fifousr
The user mode program will read strings from the fifo and
and print them out.
Use ctrl-c to exit fifousr, and stop the task:
/sbin/rmmod fifotask
8. More elaborate tests:
In theory, you should be able to run any or all of the
above tests at the same time, doing insmod's and rmmod's
in any order.
9. Shutting down.
To remove the rtapi and the rest of the RTOS modules:
scripts/unload_rtapi
If any tasks are still running, the script should print
the module names and refuse to proceed. Shut down the
modules (rmmod) and try again.
The /proc/rtapi Interface
-------------------------
Various files in /proc/rtapi provide information on the internal status
of RTAPI. In order, these are:
debug : Shows which message types will be printed to /var/log/messages.
This can be altered by writing a digit to debug. See rtapi.h
for the relevant values.
fifos : Lists the fifos currently in use, and by which process ID.
modules : Lists the loaded module names, IDs, and the type
(realtime or user space).
sems : Lists the semaphores currently in use.
shmem : Lists the shared memory allocated and the size.
status : Provides information about the number of tasks, and timer status.
tasks : Lists task ID, priority, etc.
For a quick look at the status of the rtapi, do "cat /proc/rtapi/*"
The Uninstall Process
---------------------
make clean
Code Layout
-----------
The code is split among src/ and example/ directories, each with its
own Makefile. There is also a top-level Makefile and a Makefile.inc
that is included by each of the src/ Makefiles. The 'configure' script
creates Makefile.inc based on some heuristics that determine whether
you have RTL or RTAI, and defines compiler flags accordingly. The
config script is a shell script (/bin/sh), which gives great
flexibility in what can be done. 'config' currently checks to see what
real-time Linux installations exist, using 'find' and checking for
"rtl.mk" and ".buildvars" as the telltale signs. If found, RTDIR is set
to the associated parent directory.
Alternatively, RTDIR can be set via a command line argument as described
in "The Build Process". This gives us the flexibility to cross-compile on
a system not running a realtime kernel.
If an installation is found, then symbols for the RT Linux type,
compile flags, etc. are included in the Makefile.inc. If an invalid
directory is specified, or the correct marker file is not found, configure
will exit with a "Usage" message.
Makefiles
---------
The general form for a makefile entry is:
target : dependencies
rules
where <target> is what you want made, <dependencies> are the things
the target depends on, and <rules> are how to build the target from the
dependencies. Lines can be continued with the \ backslash character at
the end of the line to be continued. Each line of the rules must begin
with a TAB character. In general a makefile entry looks more like
this:
target : dependency_1 dependency_2 \
... \
dependency_n
[TAB] rule_1
[TAB] long rule \
rest of long rule
[TAB] ...
[TAB] rule_n
You can only have one target per entry, but as many dependencies and
rules as you need. You can also have multiple different entries for
the same target; you can see this at the end of the Makefiles with the
header file dependencies generated by 'makedepend', after the "DO NOT
REMOVE THIS LINE" line.
In order to minimize the number of files, each src/ Makefile compiles
directly into the lib/ or bin/ directories. Thus, the targets and
rules aren't as simple as this:
foo.o : foo.c
gcc -c foo.c -o foo.o
but look like this:
LIB_DIR = ../../lib
$(LIB_DIR)/foo.o : foo.c
gcc -c foo.c -o $(LIB_DIR)/foo.o
This means that the resulting .o file doesn't lie around in the
current directory, but is generated directly in the ../../lib
directory.
The actual rules are a little more complicated since we like to use
make's shorthand variables. These are:
$@ for the target
$< for the first dependency
$^ for all the dependencies
The preceding example would then be
LIB_DIR = ../../lib
$(LIB_DIR)/foo.o : foo.c
gcc -c $< -o $@
Configuration Notes
-------------------
chmod a+rw /dev/rtai_shm, for RTAI
chmod a+rw /dev/mem, for mbuff
|