1 |
28 |
unneback |
|
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 |
|
|
Programming With eCos
|
35 |
|
|
|
36 |
|
|
|
37 |
|
|
Programming With eCos
|
38 |
|
|
|
39 |
|
|
The following chapters of this manual comprise a simple tutorial
|
40 |
|
|
for configuring and building eCos, building and running eCos tests,
|
41 |
|
|
and finally building three stand-alone example programs which use
|
42 |
|
|
the eCos API to perform some simple tasks.
|
43 |
|
|
|
44 |
|
|
You will need a properly installed eCos system, with the correct
|
45 |
|
|
versions of the GNU toolchain. On Windows
|
46 |
|
|
you will be using the bash command line interpreter that comes with
|
47 |
|
|
Cygwin, with the environment variables set as described in the
|
48 |
|
|
toolchain documentation.
|
49 |
|
|
|
50 |
|
|
|
51 |
|
|
The Development Process
|
52 |
|
|
|
53 |
|
|
Most development projects using eCos would contain some (or
|
54 |
|
|
most) of the following:
|
55 |
|
|
|
56 |
|
|
|
57 |
|
|
eCos Configuration
|
58 |
|
|
|
59 |
|
|
eCos is configured to provide the desired API (the inclusion
|
60 |
|
|
of libc, uitron, and the disabling of certain undesired funtions,
|
61 |
|
|
etc.), and semantics (selecting scheduler, mutex behavior, etc.).
|
62 |
|
|
See .
|
63 |
|
|
|
64 |
|
|
It would normally make sense to enable eCos assertion checking
|
65 |
|
|
at this time as well, to catch as many programming errors during
|
66 |
|
|
the development phase as possible.
|
67 |
|
|
|
68 |
|
|
Note that it should not be necessary to spend much time on
|
69 |
|
|
eCos configuration initially. It may be important to perform fine
|
70 |
|
|
tuning to reduce the memory footprint and to improve performance
|
71 |
|
|
later when the product reaches a testable state.
|
72 |
|
|
|
73 |
|
|
|
74 |
|
|
|
75 |
|
|
Integrity check of the eCos configuration
|
76 |
|
|
|
77 |
|
|
While we strive to thoroughly test eCos, the vast number
|
78 |
|
|
of configuration permutations mean that the particular configuration
|
79 |
|
|
parameters used for your project may not have been tested. Therefore,
|
80 |
|
|
we advise running the eCos tests after the project's
|
81 |
|
|
eCos configuration has been determined. See .
|
82 |
|
|
|
83 |
|
|
Obviously, this should be repeated if the configuration changes
|
84 |
|
|
later on in the development process.
|
85 |
|
|
|
86 |
|
|
|
87 |
|
|
|
88 |
|
|
Application Development - Target Neutral Part
|
89 |
|
|
|
90 |
|
|
While your project is probably targeting a specific architecture
|
91 |
|
|
and platform, possibly custom hardware, it may be possible to perform
|
92 |
|
|
part of the application development using simulated or synthetic
|
93 |
|
|
targets.
|
94 |
|
|
|
95 |
|
|
There are three good reasons for doing this:
|
96 |
|
|
|
97 |
|
|
|
98 |
|
|
|
99 |
|
|
|
100 |
|
|
It may be possible by this means to perform application
|
101 |
|
|
development in parallel with the design/implementation
|
102 |
|
|
of the target hardware, thus providing more time for developing
|
103 |
|
|
and testing functionality, and reducing time-to-market.
|
104 |
|
|
|
105 |
|
|
|
106 |
|
|
|
107 |
|
|
The build-run-debug-cycle may be faster when the application
|
108 |
|
|
does not have to be downloaded to a target via a serial interface.
|
109 |
|
|
Debugging is also likely to be more responsive when you do not have to
|
110 |
|
|
to communicate with the remote GDB stubs in RedBoot via serial. It
|
111 |
|
|
also removes the need for manually or automatically resetting the
|
112 |
|
|
target hardware.
|
113 |
|
|
|
114 |
|
|
|
115 |
|
|
|
116 |
|
|
|
117 |
|
|
New hardware can often be buggy. Comparing the behaviour of the
|
118 |
|
|
program on the hardware and in the simulator or synthetic target may
|
119 |
|
|
allow you to identify where the problems lie.
|
120 |
|
|
|
121 |
|
|
|
122 |
|
|
|
123 |
|
|
|
124 |
|
|
|
125 |
|
|
This approach is possible because all targets (including
|
126 |
|
|
simulators and synthetic ones) provide the same basic API: that
|
127 |
|
|
is, kernel, libc, libm, uitron, infra, and to some extent, HAL and
|
128 |
|
|
IO.
|
129 |
|
|
|
130 |
|
|
Synthetic targets are especially suitable as they allow you
|
131 |
|
|
to construct simulations of elaborate devices by interaction with
|
132 |
|
|
the host system, where an IO device API can hide the details from
|
133 |
|
|
the application. When switching to hardware later in the development
|
134 |
|
|
cycle, the IO driver is properly implemented.
|
135 |
|
|
|
136 |
|
|
|
137 |
|
|
|
138 |
|
|
Simulators can also do this, but it all depends on the
|
139 |
|
|
design and capabilities of the simulator you use. Some, like
|
140 |
|
|
SID or
|
141 |
|
|
Bochs provide
|
142 |
|
|
complete hardware emulation, while others just support enough of the
|
143 |
|
|
instruction set to run compiled code.
|
144 |
|
|
|
145 |
|
|
|
146 |
|
|
Therefore, select a simulator or synthetic target and use
|
147 |
|
|
it for as long as possible for application development. That is,
|
148 |
|
|
configure for the selected target, build eCos, build the application
|
149 |
|
|
and link with eCos, run and debug. Repeat the latter two steps until
|
150 |
|
|
you are happy with it.
|
151 |
|
|
|
152 |
|
|
Obviously, at some time you will have to switch to the intended
|
153 |
|
|
target hardware, for example when adding target specific feature
|
154 |
|
|
support, for memory footprint/performance characterization,
|
155 |
|
|
and for final tuning of eCos and the application.
|
156 |
|
|
|
157 |
|
|
|
158 |
|
|
|
159 |
|
|
|
160 |
|
|
Application Development - Target Specific Part
|
161 |
|
|
|
162 |
|
|
Repeat the build-run-debug-cycle while performing final tuning
|
163 |
|
|
and debugging of application. Remember to disable eCos assertion
|
164 |
|
|
checking if you are testing any performance-related aspects, it can
|
165 |
|
|
make a big difference.
|
166 |
|
|
|
167 |
|
|
It may be useful to switch between this and the previous step
|
168 |
|
|
repeatedly through the development process; use the simulator/synthetic
|
169 |
|
|
target for actual development, and use the target hardware to continually
|
170 |
|
|
check memory footprint and performance. There should be little cost
|
171 |
|
|
in switching between the two targets when using two separate build
|
172 |
|
|
trees.
|
173 |
|
|
|
174 |
|
|
|
175 |
|
|
|
176 |
|
|
|
177 |
|
|
|
178 |
|
|
|
179 |
|
|
|
180 |
|
|
|
181 |
|
|
|
182 |
|
|
Configuring and Building eCos from Source
|
183 |
|
|
|
184 |
|
|
This chapter documents the configuration of eCos. The process is
|
185 |
|
|
the same for any of the supported targets: you may select a
|
186 |
|
|
hardware target (if you have a board available), any one of the
|
187 |
|
|
simulators, or a synthetic target (if your host platform has synthetic
|
188 |
|
|
target support).
|
189 |
|
|
|
190 |
|
|
|
191 |
|
|
|
192 |
|
|
|
193 |
|
|
eCos Start-up Configurations
|
194 |
|
|
|
195 |
|
|
There are various ways to download an executable image to a
|
196 |
|
|
target board, and these involve different ways of preparing the
|
197 |
|
|
executable image. In the eCos Hardware Abstraction Layer (HAL package)
|
198 |
|
|
there are configuration options to support the different download
|
199 |
|
|
methods. summarizes the
|
200 |
|
|
ways in which an eCos image can be prepared for different types of
|
201 |
|
|
download. This is not an exhaustive list, some targets define
|
202 |
|
|
additional start-up types of their own. Where a ROM Monitor is
|
203 |
|
|
mentioned, this will usually be RedBoot, although on some older, or
|
204 |
|
|
low resource, targets you may need to use CygMon or the GDB stubs ROM,
|
205 |
|
|
see the target documentation for details.
|
206 |
|
|
|
207 |
|
|
|
208 |
|
|
209 |
|
|
Configuration for various download methods
|
210 |
|
|
|
211 |
|
|
212 |
|
|
|
|
213 |
|
|
Download method
|
214 |
|
|
HAL configuration
|
215 |
|
|
|
216 |
|
|
|
|
217 |
|
|
218 |
|
|
|
|
219 |
|
|
Burn hardware ROM
|
220 |
|
|
ROM or ROMRAM start-up
|
221 |
|
|
|
222 |
|
|
|
|
223 |
|
|
Download to ROM emulator
|
224 |
|
|
ROM or ROMRAM start-up
|
225 |
|
|
|
226 |
|
|
|
|
227 |
|
|
Download to board with ROM Monitor
|
228 |
|
|
RAM start-up
|
229 |
|
|
|
230 |
|
|
|
|
231 |
|
|
Download to simulator without ROM Monitor
|
232 |
|
|
ROM start-up
|
233 |
|
|
|
234 |
|
|
|
|
235 |
|
|
Download to simulator with ROM Monitor
|
236 |
|
|
RAM start-up
|
237 |
|
|
|
238 |
|
|
|
|
239 |
|
|
Download to simulator ignoring devices
|
240 |
|
|
SIM configuration
|
241 |
|
|
|
242 |
|
|
|
|
243 |
|
|
Run synthetic target
|
244 |
|
|
RAM start-up
|
245 |
|
|
|
246 |
|
|
|
|
247 |
|
|
|
248 |
|
|
|
|
249 |
|
|
|
250 |
|
|
|
251 |
|
|
|
252 |
|
|
You cannot run an application configured for RAM start-up
|
253 |
|
|
on the simulator directly: it will fail during start-up. You can
|
254 |
|
|
only download it to the simulator if
|
255 |
|
|
you are already running RedBoot in the simulator,
|
256 |
|
|
as described in the toolchain documentation
|
257 |
|
|
or you load through the
|
258 |
|
|
SID
|
259 |
|
|
GDB debugging component. This is not the same as the simulated
|
260 |
|
|
stub, since it does not require a target program to be running to
|
261 |
|
|
get GDB to talk to it. It can be done before letting the simulator
|
262 |
|
|
run
|
263 |
|
|
or you use the ELF loader component to get a program into memory.
|
264 |
|
|
|
265 |
|
|
|
266 |
|
|
|
267 |
|
|
|
268 |
|
|
Configuring eCos' HAL package for simulation should
|
269 |
|
|
rarely be needed for real development; binaries built with such
|
270 |
|
|
a kernel will not run on target boards at all,
|
271 |
|
|
and the MN10300 and
|
272 |
|
|
TX39 simulators can run binaries built for stdeval1 and jmr3904
|
273 |
|
|
target boards.
|
274 |
|
|
The main use for a ``simulation'' configuration
|
275 |
|
|
is if you are trying to work around problems with the device drivers
|
276 |
|
|
or with the simulator. Also note that when using a TX39 system configured
|
277 |
|
|
for simulator start-up you should then invoke the simulator with
|
278 |
|
|
the
|
279 |
|
|
option instead of
|
280 |
|
|
|
281 |
|
|
|
282 |
|
|
|
283 |
|
|
|
284 |
|
|
If your chosen architecture does not have simulator support,
|
285 |
|
|
then the combinations above that refer to the simulator do not apply.
|
286 |
|
|
Similarly, if your chosen platform does not have RedBoot
|
287 |
|
|
ROM support, the combinations listed above that use
|
288 |
|
|
RedBoot do not apply.
|
289 |
|
|
|
290 |
|
|
|
291 |
|
|
The debugging environment for most developers will be either
|
292 |
|
|
a hardware board or the simulator, in which case they will be able
|
293 |
|
|
to select a single HAL configuration.
|
294 |
|
|
|
295 |
|
|
|
296 |
|
|
|
297 |
|
|
|
298 |
|
|
|
299 |
|
|
|
300 |
|
|
|
301 |
|
|
Configuration Tool on Windows and Linux Quick Start
|
302 |
|
|
|
303 |
|
|
|
304 |
|
|
|
305 |
|
|
Note that the use of the Configuration Tool
|
306 |
|
|
is described in detail in
|
307 |
|
|
LINKEND="THE-ECOS-CONFIGURATION-TOOL">.
|
308 |
|
|
|
309 |
|
|
The Configuration Tool (see )
|
310 |
|
|
has five main elements: the configuration window,
|
311 |
|
|
the conflicts window,
|
312 |
|
|
the properties window, the short
|
313 |
|
|
description window,
|
314 |
|
|
and the output window.
|
315 |
|
|
|
316 |
|
|
|
317 |
|
|
Configuration Tool
|
318 |
|
|
![]()
|
319 |
|
|
|
320 |
|
|
|
321 |
|
|
Start by opening the templates window via Build->Templates.
|
322 |
|
|
Select the desired target (see ).
|
323 |
|
|
|
324 |
|
|
|
325 |
|
|
Template selection
|
326 |
|
|
![]()
|
327 |
|
|
|
328 |
|
|
|
329 |
|
|
Make sure that the configuration is correct for the target
|
330 |
|
|
in terms of endianness, CPU model, Startup type, etc. (see ).
|
331 |
|
|
|
332 |
|
|
|
333 |
|
|
Configuring
|
334 |
|
|
for the target
|
335 |
|
|
![]()
|
336 |
|
|
|
337 |
|
|
|
338 |
|
|
Next, select the Build->Library menu
|
339 |
|
|
item to start building eCos (see
|
340 |
|
|
LINKEND="FIGURE-SELECTING-THE-BUILD-LIBRARY-MENU-ITEM">). The
|
341 |
|
|
application will configure the sources, prepare a build tree, and
|
342 |
|
|
build the libtarget.a library, which contains the
|
343 |
|
|
eCos kernel and other packages.
|
344 |
|
|
|
345 |
|
|
|
346 |
|
|
Selecting the Build Library menu item
|
347 |
|
|
![]()
|
348 |
|
|
|
349 |
|
|
|
350 |
|
|
|
351 |
|
|
The Save As dialog box will appear, asking
|
352 |
|
|
you to specify a directory in which to place your save file. You
|
353 |
|
|
can use the default, but it is a good idea to make a subdirectory,
|
354 |
|
|
called ecos-work for example.
|
355 |
|
|
|
356 |
|
|
|
357 |
|
|
Save file dialog
|
358 |
|
|
![]()
|
359 |
|
|
|
360 |
|
|
|
361 |
|
|
The first time you build an eCos library for a specific
|
362 |
|
|
architecture, the Configuration Tool may prompt
|
363 |
|
|
you for the location of the appropriate build tools (including
|
364 |
|
|
make and
|
365 |
|
|
TARGET-gcc) using a
|
366 |
|
|
Build Tools dialog box (as shown in
|
367 |
|
|
LINKEND="FIGURE-BUILD-TOOLS-DIALOG">). You can select a location from
|
368 |
|
|
the drop down list, browse to the directory using the
|
369 |
|
|
Browse button, or type in the location of the
|
370 |
|
|
build tools manually.
|
371 |
|
|
|
372 |
|
|
|
373 |
|
|
Build tools dialog
|
374 |
|
|
![]()
|
375 |
|
|
|
376 |
|
|
|
377 |
|
|
The Configuration Tool may also prompt you
|
378 |
|
|
for the location of the user tools (such as cat and
|
379 |
|
|
ls) using a User Tools dialog
|
380 |
|
|
box (as shown in ). As with
|
381 |
|
|
the Build Tools dialog, you can select a location
|
382 |
|
|
from the drop down list, browse to the directory using the
|
383 |
|
|
Browse button, or type in the location of the
|
384 |
|
|
user tools manually. Note that on Linux, this will often be
|
385 |
|
|
unnecessary as the tools will already be on your PATH.
|
386 |
|
|
|
387 |
|
|
|
388 |
|
|
User tools dialog
|
389 |
|
|
![]()
|
390 |
|
|
|
391 |
|
|
|
392 |
|
|
When the tool locations have been entered, the Configuration
|
393 |
|
|
Tool will configure the sources, prepare a build tree,
|
394 |
|
|
and build the libtarget.a library, which contains
|
395 |
|
|
the eCos kernel and other packages.
|
396 |
|
|
|
397 |
|
|
The output from the configuration process and the building
|
398 |
|
|
of libtarget.a will be shown in the output
|
399 |
|
|
window.
|
400 |
|
|
|
401 |
|
|
Once the build process has finished you will have a kernel
|
402 |
|
|
with other packages in libtarget.a. You should
|
403 |
|
|
now build the eCos tests for your particular configuration.
|
404 |
|
|
|
405 |
|
|
You can do this by selecting Build -> Tests.
|
406 |
|
|
Notice that you could have selected Tests instead
|
407 |
|
|
of Library in the earlier step and it would
|
408 |
|
|
have built both the library and the tests,
|
409 |
|
|
but this would increase the build time substantially, and if you
|
410 |
|
|
do not need to build the tests it is unnecessary.
|
411 |
|
|
|
412 |
|
|
|
413 |
|
|
Selecting the Build Tests menu item
|
414 |
|
|
![]()
|
415 |
|
|
|
416 |
|
|
|
417 |
|
|
will guide you through running one
|
418 |
|
|
of the test cases you just built on the selected target,
|
419 |
|
|
using GDB.
|
420 |
|
|
|
421 |
|
|
|
422 |
|
|
|
423 |
|
|
|
424 |
|
|
|
425 |
|
|
|
426 |
|
|
Ecosconfig on Windows and Linux Quick Start
|
427 |
|
|
|
428 |
|
|
As an alternative to using the graphical
|
429 |
|
|
Configuration Tool, it is still possible to
|
430 |
|
|
configure and build a kernel by editing a configuration file manually
|
431 |
|
|
and using the ecosconfig command.
|
432 |
|
|
|
433 |
|
|
|
434 |
|
|
Manual configuration and the ecosconfig command are
|
435 |
|
|
described in detail in .
|
436 |
|
|
|
437 |
|
|
|
438 |
|
|
|
439 |
|
|
To use the ecosconfig command you need to start a
|
440 |
|
|
shell. In Windows you need to start a
|
441 |
|
|
CygWin bash shell, not a
|
442 |
|
|
DOS command line.
|
443 |
|
|
|
444 |
|
|
|
445 |
|
|
|
451 |
|
|
|
452 |
|
|
The following instructions assume that the
|
453 |
|
|
PATH and ECOS_REPOSITORY
|
454 |
|
|
environment variables have been setup correctly as described in
|
455 |
|
|
LINKEND="user-guide-installation-linux">. They also assume Linux
|
456 |
|
|
usage but equally well apply to Windows running Cygwin.
|
457 |
|
|
|
458 |
|
|
Before invoking ecosconfig you need to
|
459 |
|
|
choose a directory in which to work. For the purposes of this tutorial,
|
460 |
|
|
the default path will be BASE_DIR/ecos-work.
|
461 |
|
|
Create this directory and change to it by typing:
|
462 |
|
|
|
463 |
|
|
|
464 |
|
|
$ mkdir BASE_DIR/ecos-work
|
465 |
|
|
$ cd BASE_DIR/ecos-work
|
466 |
|
|
|
467 |
|
|
|
468 |
|
|
To see what options can be used with ecosconfig,
|
469 |
|
|
type:
|
470 |
|
|
|
471 |
|
|
$ ecosconfig --help
|
472 |
|
|
|
473 |
|
|
The available packages, targets and templates may be listed
|
474 |
|
|
as follows:
|
475 |
|
|
|
476 |
|
|
|
477 |
|
|
$ ecosconfig list
|
478 |
|
|
|
479 |
|
|
|
480 |
|
|
Here is sample output from ecosconfig showing
|
481 |
|
|
the usage message.
|
482 |
|
|
|
483 |
|
|
|
484 |
|
|
Getting help from ecosconfig
|
485 |
|
|
|
486 |
|
|
|
487 |
|
|
$ ecosconfig --help
|
488 |
|
|
Usage: ecosconfig [ qualifier ... ] [ command ]
|
489 |
|
|
commands are:
|
490 |
|
|
list : list repository contents
|
491 |
|
|
new TARGET [ TEMPLATE [ VERSION ] ] : create a configuration
|
492 |
|
|
target TARGET : change the target hardware
|
493 |
|
|
template TEMPLATE [ VERSION ] : change the template
|
494 |
|
|
add PACKAGE [ PACKAGE ... ] : add package(s)
|
495 |
|
|
remove PACKAGE [ PACKAGE ... ] : remove package(s)
|
496 |
|
|
version VERSION PACKAGE [ PACKAGE ... ] : change version of package(s)
|
497 |
|
|
export FILE : export minimal config info
|
498 |
|
|
import FILE : import additional config info
|
499 |
|
|
check : check the configuration
|
500 |
|
|
resolve : resolve conflicts
|
501 |
|
|
tree : create a build tree
|
502 |
|
|
qualifiers are:
|
503 |
|
|
--config=FILE : the configuration file
|
504 |
|
|
--prefix=DIRECTORY : the install prefix
|
505 |
|
|
--srcdir=DIRECTORY : the source repository
|
506 |
|
|
--no-resolve : disable conflict
|
507 |
|
|
resolution
|
508 |
|
|
--version : show version and copyright
|
509 |
|
|
$
|
510 |
|
|
|
511 |
|
|
|
512 |
|
|
|
513 |
|
|
|
514 |
|
|
|
515 |
|
|
ecosconfig output —
|
516 |
|
|
list of available packages, targets and templates
|
517 |
|
|
|
518 |
|
|
|
519 |
|
|
$ ecosconfig list
|
520 |
|
|
Package CYGPKG_CYGMON (CygMon support via eCos):
|
521 |
|
|
aliases: cygmon
|
522 |
|
|
versions: &Version;
|
523 |
|
|
Package CYGPKG_DEVICES_WALLCLOCK_DALLAS_DS1742 (Wallclock driver for Dallas 1742):
|
524 |
|
|
aliases: devices_wallclock_ds1742 device_wallclock_ds1742
|
525 |
|
|
versions: &Version;
|
526 |
|
|
Package CYGPKG_DEVICES_WALLCLOCK_SH3 (Wallclock driver for SH3 RTC module):
|
527 |
|
|
aliases: devices_wallclock_sh3 device_wallclock_sh3
|
528 |
|
|
versions: &Version;
|
529 |
|
|
Package CYGPKG_DEVICES_WATCHDOG_ARM_AEB (Watchdog driver for ARM/AEB board):
|
530 |
|
|
aliases: devices_watchdog_aeb device_watchdog_aeb
|
531 |
|
|
versions: &Version;
|
532 |
|
|
Package CYGPKG_DEVICES_WATCHDOG_ARM_EBSA285 (Watchdog driver for ARM/EBSA285 board):
|
533 |
|
|
aliases: devices_watchdog_ebsa285 device_watchdog_ebsa285
|
534 |
|
|
versions: &Version;
|
535 |
|
|
…
|
536 |
|
|
|
537 |
|
|
|
538 |
|
|
|
539 |
|
|
|
540 |
|
|
|
541 |
|
|
Selecting a Target
|
542 |
|
|
|
543 |
|
|
To configure for a listed target, type:
|
544 |
|
|
|
545 |
|
|
|
546 |
|
|
$ ecosconfig new <target>
|
547 |
|
|
|
548 |
|
|
|
549 |
|
|
For example, to configure for the ARM PID development board,
|
550 |
|
|
type:
|
551 |
|
|
|
552 |
|
|
|
553 |
|
|
$ ecosconfig new pid
|
554 |
|
|
|
555 |
|
|
|
556 |
|
|
You can then edit the generated file,
|
557 |
|
|
ecos.ecc, setting the options as required for the
|
558 |
|
|
target (endianess, CPU model, Startup type, etc.). For detailed
|
559 |
|
|
information about how to edit the ecos.ecc file,
|
560 |
|
|
see the CDL Writer's Guide and
|
561 |
|
|
LINKEND="editing-an-ecos-savefile">.
|
562 |
|
|
|
563 |
|
|
|
564 |
|
|
Create a build tree for the configured target by typing:
|
565 |
|
|
|
566 |
|
|
|
567 |
|
|
$ ecosconfig tree
|
568 |
|
|
|
569 |
|
|
|
570 |
|
|
|
571 |
|
|
If there are any problem with the configuration,
|
572 |
|
|
ecosconfig will tell you. The most likely cause of
|
573 |
|
|
this is mistakes when editing the ecos.ecc file.
|
574 |
|
|
You can check whether the configuration you have made is correct,
|
575 |
|
|
without building the tree with the following command:
|
576 |
|
|
|
577 |
|
|
|
578 |
|
|
|
579 |
|
|
$ ecosconfig check
|
580 |
|
|
|
581 |
|
|
|
582 |
|
|
|
583 |
|
|
If this reports any conflicts you can get
|
584 |
|
|
ecosconfig to try and resolve them itself by typing:
|
585 |
|
|
|
586 |
|
|
|
587 |
|
|
|
588 |
|
|
$ ecosconfig resolve
|
589 |
|
|
|
590 |
|
|
|
591 |
|
|
|
592 |
|
|
See for more details.
|
593 |
|
|
|
594 |
|
|
|
595 |
|
|
You can now run the command make or make
|
596 |
|
|
tests, after which you will be at the same point you
|
597 |
|
|
would be after running the Configuration Tool
|
598 |
|
|
— you can start developing your own applications,
|
599 |
|
|
following the steps in .
|
600 |
|
|
|
601 |
|
|
The procedure shown above allows you to do very coarse-grained
|
602 |
|
|
configuration of the eCos kernel: you can select which packages
|
603 |
|
|
to include in your kernel, and give target and start-up options.
|
604 |
|
|
But you cannot select components within a package, or set the very
|
605 |
|
|
fine-grained options.
|
606 |
|
|
|
607 |
|
|
To select fine-grained configuration options you will need to
|
608 |
|
|
edit the configuration file ecos.ecc in the
|
609 |
|
|
current directory and regenerate the build tree.
|
610 |
|
|
|
611 |
|
|
|
612 |
|
|
You should follow the manual configuration process described
|
613 |
|
|
above very carefully, and you should read the comments in each file
|
614 |
|
|
to see when one option depends on other options or packages being
|
615 |
|
|
enabled or disabled. If you do not, you might end up with an inconsistently
|
616 |
|
|
configured kernel which could fail to build or might execute
|
617 |
|
|
incorrectly.
|
618 |
|
|
|
619 |
|
|
|
620 |
|
|
|
621 |
|
|
|
622 |
|
|
|
623 |
|
|
|
624 |
|
|
|
625 |
|
|
|
626 |
|
|
|
627 |
|
|
|
628 |
|
|
Running an eCos Test Case
|
629 |
|
|
|
630 |
|
|
In or
|
631 |
|
|
LINKEND="using-ecosconfig-on-linux"> you created the eCos test cases
|
632 |
|
|
as part of the build process. Now it is time to try and run one.
|
633 |
|
|
|
634 |
|
|
|
635 |
|
|
|
636 |
|
|
|
637 |
|
|
|
638 |
|
|
Using the Configuration Tool
|
639 |
|
|
|
640 |
|
|
Test executables that have been linked using the
|
641 |
|
|
Build->Tests operation against the current
|
642 |
|
|
configuration can be executed by selecting Tools->Run
|
643 |
|
|
Tests.
|
644 |
|
|
|
645 |
|
|
When a test run is invoked, a property sheet is displayed, see
|
646 |
|
|
. Press the Uncheck
|
647 |
|
|
All button and then find and check just one test,
|
648 |
|
|
bin_sem0 for example.
|
649 |
|
|
|
650 |
|
|
|
651 |
|
|
|
652 |
|
|
Run tests
|
653 |
|
|
![]()
|
654 |
|
|
|
655 |
|
|
|
656 |
|
|
|
657 |
|
|
Now press the Properties button to set up
|
658 |
|
|
communications with the target. This will bring up a properties dialog
|
659 |
|
|
shown in . If you have
|
660 |
|
|
connected the target board via a serial cable, check the
|
661 |
|
|
Serial radio button, and select the serial port
|
662 |
|
|
and baud rate for the board. If the target is connected via the
|
663 |
|
|
network select the TCP/IP button and enter the IP
|
664 |
|
|
address that the board has been given, and the port number (usually
|
665 |
|
|
9000).
|
666 |
|
|
|
667 |
|
|
|
668 |
|
|
|
669 |
|
|
Properties dialog box
|
670 |
|
|
![]()
|
671 |
|
|
|
672 |
|
|
|
673 |
|
|
|
674 |
|
|
Click OK on this dialog and go back to the Run
|
675 |
|
|
Tests dialog. Press the Run button and
|
676 |
|
|
the selected test will be downloaded and run. The
|
677 |
|
|
Output tab will show you how this is
|
678 |
|
|
progressing. If it seems to stop for a long time, check that the
|
679 |
|
|
target board is correctly connected, and that eCos has been correctly
|
680 |
|
|
configured -- especially the start-up type.
|
681 |
|
|
|
682 |
|
|
|
683 |
|
|
|
684 |
|
|
When the program runs you should see a couple of line similar to this appear:
|
685 |
|
|
|
686 |
|
|
|
687 |
|
|
|
688 |
|
|
PASS:<Binary Semaphore 0 OK>
|
689 |
|
|
EXIT:<done>
|
690 |
|
|
|
691 |
|
|
|
692 |
|
|
|
693 |
|
|
This indicates that the test has run successfully.
|
694 |
|
|
|
695 |
|
|
|
696 |
|
|
See for
|
697 |
|
|
further details.
|
698 |
|
|
|
699 |
|
|
|
700 |
|
|
|
701 |
|
|
|
702 |
|
|
|
703 |
|
|
|
704 |
|
|
Using the command line
|
705 |
|
|
|
706 |
|
|
Start a command shell (such as a Cygwin shell window in Windows)
|
707 |
|
|
with the environment variables set as described in the toolchain
|
708 |
|
|
documentation. Change to the directory in which you set up your build
|
709 |
|
|
tree, and invoke GDB on the test
|
710 |
|
|
program.
|
711 |
|
|
|
712 |
|
|
To run the bin_sem0 test (which will
|
713 |
|
|
test the kernel for the correct creation and destruction of binary
|
714 |
|
|
semaphores) type:
|
715 |
|
|
|
716 |
|
|
|
717 |
|
|
$ TARGET-gdb -nw install/tests/kernel/&Version;/tests/bin_sem0
|
718 |
|
|
|
719 |
|
|
|
720 |
|
|
You should see output similar to the following in the command
|
721 |
|
|
window:
|
722 |
|
|
|
723 |
|
|
|
724 |
|
|
GNU gdb THIS-GDB-VERSION
|
725 |
|
|
Copyright 2001 Free Software Foundation, Inc.
|
726 |
|
|
GDB is free software, covered by the GNU General Public License, and you are
|
727 |
|
|
welcome to change it and/or distribute copies of it under certain conditions.
|
728 |
|
|
Type "show copying" to see the conditions.
|
729 |
|
|
There is absolutely no warranty for GDB. Type "show warranty" for details.
|
730 |
|
|
This GDB was configured as "--host=THIS-HOST --target=THIS-TARGET".
|
731 |
|
|
(gdb)
|
732 |
|
|
|
733 |
|
|
|
734 |
|
|
If you are trying to run a synthetic target test on Linux, skip the following connection and download
|
736 |
|
|
steps. Otherwise, connect to the target by typing:
|
737 |
|
|
|
738 |
|
|
|
739 |
|
|
(gdb) set remotebaud 38400
|
740 |
|
|
(gdb) target remote /dev/ttyS0
|
741 |
|
|
|
742 |
|
|
on Linux or
|
743 |
|
|
|
744 |
|
|
(gdb) set remotebaud 38400
|
745 |
|
|
(gdb) target remote com1
|
746 |
|
|
|
747 |
|
|
on Windows or
|
748 |
|
|
|
749 |
|
|
(gdb) target sim
|
750 |
|
|
|
751 |
|
|
to use a simulator in either host O/S.
|
752 |
|
|
|
753 |
|
|
|
754 |
|
|
Check the documentation for the target board for the actual baud rate
|
755 |
|
|
to use when connecting to real targets.
|
756 |
|
|
|
757 |
|
|
|
758 |
|
|
|
759 |
|
|
You will see output similar to the following:
|
760 |
|
|
|
761 |
|
|
|
762 |
|
|
Remote debugging using /dev/ttyS1
|
763 |
|
|
0x0000d50c in ?? ()
|
764 |
|
|
at BASE_DIR/kernel/&Version;/src/common/kapi.cxx:345
|
765 |
|
|
|
766 |
|
|
Current language: auto; currently c++
|
767 |
|
|
(gdb)
|
768 |
|
|
|
769 |
|
|
|
770 |
|
|
|
771 |
|
|
Or if you are using the simulator:
|
772 |
|
|
|
773 |
|
|
|
774 |
|
|
|
775 |
|
|
Connected to the simulator.
|
776 |
|
|
(gdb)
|
777 |
|
|
|
778 |
|
|
|
779 |
|
|
Now download the program to the target with
|
780 |
|
|
|
781 |
|
|
|
782 |
|
|
(gdb) load
|
783 |
|
|
|
784 |
|
|
|
785 |
|
|
You should see output similar to the following on your screen:
|
786 |
|
|
|
787 |
|
|
|
788 |
|
|
Loading section .text, size 0x4b04 lma 0x108000
|
789 |
|
|
Loading section .rodata, size 0x738 lma 0x10cb08
|
790 |
|
|
Loading section .data, size 0x1c0 lma 0x10d240
|
791 |
|
|
Start address 0x108000, load size 21500
|
792 |
|
|
Transfer rate: 24571 bits/sec, 311 bytes/write.
|
793 |
|
|
(gdb)
|
794 |
|
|
|
795 |
|
|
|
796 |
|
|
You are now ready to run your program. If you type:
|
797 |
|
|
|
798 |
|
|
|
799 |
|
|
(gdb) continue
|
800 |
|
|
|
801 |
|
|
|
802 |
|
|
you will see output similar to the following:
|
803 |
|
|
|
804 |
|
|
|
805 |
|
|
Continuing.
|
806 |
|
|
PASS:<Binary Semaphore 0 OK>
|
807 |
|
|
EXIT:<done>
|
808 |
|
|
|
809 |
|
|
|
810 |
|
|
|
811 |
|
|
If you are using a simulator or the synthetic target rather
|
812 |
|
|
than real hardware, you must use the GDB command
|
813 |
|
|
“run” rather than “continue” to
|
814 |
|
|
start your program.
|
815 |
|
|
|
816 |
|
|
|
817 |
|
|
You can terminate your GDB session with
|
818 |
|
|
Control+C, otherwise it will sit in the
|
819 |
|
|
“idle” thread and use up CPU time. This is not a problem
|
820 |
|
|
with real targets, but may have undesirable effects in simulated or
|
821 |
|
|
synthetic targets. Type quit and you are
|
822 |
|
|
done.
|
823 |
|
|
|
824 |
|
|
|
825 |
|
|
|
826 |
|
|
|
827 |
|
|
|
828 |
|
|
|
829 |
|
|
Testing Filters
|
830 |
|
|
|
831 |
|
|
While most test cases today run solely in the target environment,
|
832 |
|
|
some packages may require external testing infrastructure and/or
|
833 |
|
|
feedback from the external environment to do complete testing.
|
834 |
|
|
|
835 |
|
|
The serial package is an example of this. The network package
|
836 |
|
|
also contains some tests that require programs to be run on a
|
837 |
|
|
host. See the network Tests and Demonstrations
|
838 |
|
|
section in the network documentation in the eCos Reference
|
839 |
|
|
Guide. Here we will concentrate on the serial tests since
|
840 |
|
|
these are applicable to more targets.
|
841 |
|
|
|
842 |
|
|
|
843 |
|
|
Since the serial line is also used for communication with
|
844 |
|
|
GDB, a filter is inserted in the communication pathway between
|
845 |
|
|
GDB and the serial device which is connected to the hardware target.
|
846 |
|
|
The filter forwards all communication between the two, but also
|
847 |
|
|
listens for special commands embedded in the data stream from the
|
848 |
|
|
target.
|
849 |
|
|
|
850 |
|
|
When such a command is seen, the filter stops forwarding data
|
851 |
|
|
to GDB from the target and enters a special mode. In this mode
|
852 |
|
|
the test case running on the target is able to control the filter,
|
853 |
|
|
commanding it to run various tests. While these tests run, GDB is
|
854 |
|
|
isolated from the target.
|
855 |
|
|
|
856 |
|
|
As the test completes (or if the filter detects a target crash)
|
857 |
|
|
the communication path between GDB and the hardware target is re-established,
|
858 |
|
|
allowing GDB to resume control.
|
859 |
|
|
|
860 |
|
|
In theory, it is possible to extend the filter to provide
|
861 |
|
|
a generic framework for other target-external testing components,
|
862 |
|
|
thus decoupling the testing infrastructure from the (possibly limited)
|
863 |
|
|
communication means provided by the target (serial, JTAG, Ethernet,
|
864 |
|
|
etc).
|
865 |
|
|
|
866 |
|
|
Another advantage is that the host tools do not need to
|
867 |
|
|
know about the various testing environments required by the eCos
|
868 |
|
|
packages, since all contact with the target continues to happen
|
869 |
|
|
via GDB.
|
870 |
|
|
|
871 |
|
|
|
872 |
|
|
|
873 |
|
|
|
874 |
|
|
|
875 |
|
|
|
876 |
|
|
|
877 |
|
|
|
878 |
|
|
|
879 |
|
|
Building and Running Sample Applications
|
880 |
|
|
|
881 |
|
|
The example programs in this tutorial are included, along
|
882 |
|
|
with a Makefile, in the examples directory
|
883 |
|
|
of the eCos distribution. The first program you will run is a hello
|
884 |
|
|
world-style application, then you will run a more complex
|
885 |
|
|
application that demonstrates the creation of threads and the use
|
886 |
|
|
of cyg_thread_delay(), and finally you will run
|
887 |
|
|
one that uses clocks and alarm handlers.
|
888 |
|
|
|
889 |
|
|
The Makefile depends on an externally
|
890 |
|
|
defined variable to find the eCos library and header files. This
|
891 |
|
|
variable is INSTALL_DIR and must be set to the
|
892 |
|
|
pathname of the install directory created in
|
893 |
|
|
linkend="using-configtool-windows-linux">.
|
894 |
|
|
|
895 |
|
|
|
896 |
|
|
|
897 |
|
|
INSTALL_DIR may be either be set in the shell
|
898 |
|
|
environment or may be supplied on the command line. To set it in the
|
899 |
|
|
shell do the following in a bash shell:
|
900 |
|
|
|
901 |
|
|
|
902 |
|
|
|
903 |
|
|
$ export INSTALL_DIR=BASE_DIR/ecos-work/arm_install
|
904 |
|
|
|
905 |
|
|
|
906 |
|
|
|
907 |
|
|
You can then run make without any extra parameters
|
908 |
|
|
to build the examples.
|
909 |
|
|
|
910 |
|
|
|
911 |
|
|
|
912 |
|
|
Alternatively, if you can do the following:
|
913 |
|
|
|
914 |
|
|
|
915 |
|
|
|
916 |
|
|
$ make INSTALL_DIR=BASE_DIR/ecos-work/arm_install
|
917 |
|
|
|
918 |
|
|
|
919 |
|
|
|
920 |
|
|
|
921 |
|
|
|
922 |
|
|
eCos Hello World
|
923 |
|
|
|
924 |
|
|
The following code is found in the file hello.c
|
925 |
|
|
in the examples directory:
|
926 |
|
|
|
927 |
|
|
|
928 |
|
|
eCos hello world program listing
|
929 |
|
|
|
930 |
|
|
|
931 |
|
|
/* this is a simple hello world program */
|
932 |
|
|
#include <stdio.h>
|
933 |
|
|
int main(void)
|
934 |
|
|
{
|
935 |
|
|
printf("Hello, eCos world!\n");
|
936 |
|
|
return 0;
|
937 |
|
|
}
|
938 |
|
|
|
939 |
|
|
|
940 |
|
|
To compile this or any other program that is not part of the
|
941 |
|
|
eCos distribution, you can follow the procedures described below. Type
|
942 |
|
|
this explicit compilation command (assuming your current working
|
943 |
|
|
directory is also where you built the eCos kernel):
|
944 |
|
|
|
945 |
|
|
|
946 |
|
|
$ TARGET-gcc -g -IBASE_DIR/ecos-work/install/include hello.c -LBASE_DIR/ecos-work/install/lib -Ttarget.ld -nostdlib
|
947 |
|
|
|
948 |
|
|
|
949 |
|
|
The compilation command above contains some standard GCC
|
950 |
|
|
options (for example, enables debugging), as well
|
951 |
|
|
as some mention of paths
|
952 |
|
|
( allows files
|
953 |
|
|
like cyg/kernel/kapi.h to be found, and
|
954 |
|
|
allows the linker to
|
955 |
|
|
find ).
|
956 |
|
|
|
957 |
|
|
The executable program will be called a.out.
|
958 |
|
|
|
959 |
|
|
|
960 |
|
|
Some target systems require special options to be passed to
|
961 |
|
|
gcc to compile correctly for that system. Please examine the Makefile
|
962 |
|
|
in the examples directory to see if this applies to your target.
|
963 |
|
|
|
964 |
|
|
|
965 |
|
|
You can now run the resulting program using GDB in exactly the
|
966 |
|
|
same the way you ran the test case before. The procedure will be the
|
967 |
|
|
same, but this time run
|
968 |
|
|
TARGET-gdb specifying
|
969 |
|
|
on the command line:
|
970 |
|
|
|
971 |
|
|
|
972 |
|
|
$ TARGET-gdb -nw a.out
|
973 |
|
|
|
974 |
|
|
|
975 |
|
|
For targets other than the synthetic linux target, you should
|
976 |
|
|
now run the usual GDB commands described earlier. Once this is done,
|
977 |
|
|
typing the command "continue" at the (gdb) prompt ("run" for
|
978 |
|
|
simulators) will allow the program to execute and print the string
|
979 |
|
|
"Hello, eCos world!" on your screen.
|
980 |
|
|
|
981 |
|
|
On the synthetic linux target, you may use the "run" command
|
982 |
|
|
immediately - you do not need to connect to the target, nor use the
|
983 |
|
|
"load" command.
|
984 |
|
|
|
985 |
|
|
|
986 |
|
|
|
987 |
|
|
|
988 |
|
|
|
989 |
|
|
|
990 |
|
|
|
991 |
|
|
A Sample Program with Two Threads
|
992 |
|
|
|
993 |
|
|
Below is a program that uses some of eCos' system calls. It
|
994 |
|
|
creates two threads, each of which goes into an infinite loop in which
|
995 |
|
|
it sleeps for a while (using cyg_thread_delay()). This code is found
|
996 |
|
|
in the file twothreads.c
|
997 |
|
|
in the examples directory.
|
998 |
|
|
|
999 |
|
|
|
1000 |
|
|
eCos two-threaded program listing
|
1001 |
|
|
|
1002 |
|
|
|
1003 |
|
|
#include <cyg/kernel/kapi.h>
|
1004 |
|
|
#include <stdio.h>
|
1005 |
|
|
#include <math.h>
|
1006 |
|
|
#include <stdlib.h>
|
1007 |
|
|
|
1008 |
|
|
/* now declare (and allocate space for) some kernel objects,
|
1009 |
|
|
like the two threads we will use */
|
1010 |
|
|
cyg_thread thread_s[2]; /* space for two thread objects */
|
1011 |
|
|
|
1012 |
|
|
char stack[2][4096]; /* space for two 4K stacks */
|
1013 |
|
|
|
1014 |
|
|
/* now the handles for the threads */
|
1015 |
|
|
cyg_handle_t simple_threadA, simple_threadB;
|
1016 |
|
|
|
1017 |
|
|
/* and now variables for the procedure which is the thread */
|
1018 |
|
|
cyg_thread_entry_t simple_program;
|
1019 |
|
|
|
1020 |
|
|
/* and now a mutex to protect calls to the C library */
|
1021 |
|
|
cyg_mutex_t cliblock;
|
1022 |
|
|
|
1023 |
|
|
/* we install our own startup routine which sets up threads */
|
1024 |
|
|
void cyg_user_start(void)
|
1025 |
|
|
{
|
1026 |
|
|
printf("Entering twothreads' cyg_user_start() function\n");
|
1027 |
|
|
|
1028 |
|
|
cyg_mutex_init(&cliblock);
|
1029 |
|
|
|
1030 |
|
|
cyg_thread_create(4, simple_program, (cyg_addrword_t) 0,
|
1031 |
|
|
"Thread A", (void *) stack[0], 4096,
|
1032 |
|
|
&simple_threadA, &thread_s[0]);
|
1033 |
|
|
cyg_thread_create(4, simple_program, (cyg_addrword_t) 1,
|
1034 |
|
|
"Thread B", (void *) stack[1], 4096,
|
1035 |
|
|
&simple_threadB, &thread_s[1]);
|
1036 |
|
|
|
1037 |
|
|
cyg_thread_resume(simple_threadA);
|
1038 |
|
|
cyg_thread_resume(simple_threadB);
|
1039 |
|
|
}
|
1040 |
|
|
|
1041 |
|
|
/* this is a simple program which runs in a thread */
|
1042 |
|
|
void simple_program(cyg_addrword_t data)
|
1043 |
|
|
{
|
1044 |
|
|
int message = (int) data;
|
1045 |
|
|
int delay;
|
1046 |
|
|
|
1047 |
|
|
printf("Beginning execution; thread data is %d\n", message);
|
1048 |
|
|
|
1049 |
|
|
cyg_thread_delay(200);
|
1050 |
|
|
|
1051 |
|
|
for (;;) {
|
1052 |
|
|
delay = 200 + (rand() % 50);
|
1053 |
|
|
|
1054 |
|
|
/* note: printf() must be protected by a
|
1055 |
|
|
call to cyg_mutex_lock() */
|
1056 |
|
|
cyg_mutex_lock(&cliblock); {
|
1057 |
|
|
printf("Thread %d: and now a delay of %d clock ticks\n",
|
1058 |
|
|
message, delay);
|
1059 |
|
|
}
|
1060 |
|
|
cyg_mutex_unlock(&cliblock);
|
1061 |
|
|
cyg_thread_delay(delay);
|
1062 |
|
|
}
|
1063 |
|
|
}
|
1064 |
|
|
|
1065 |
|
|
|
1066 |
|
|
|
1067 |
|
|
When you run the program (by typing continue at
|
1068 |
|
|
the (gdb) prompt) the output should look like
|
1069 |
|
|
this:
|
1070 |
|
|
|
1071 |
|
|
|
1072 |
|
|
Starting program: BASE_DIR/examples/twothreads.exe
|
1073 |
|
|
Entering twothreads' cyg_user_start()
|
1074 |
|
|
function
|
1075 |
|
|
Beginning execution; thread data is 0
|
1076 |
|
|
Beginning execution; thread data is 1
|
1077 |
|
|
Thread 0: and now a delay of 240 clock ticks
|
1078 |
|
|
Thread 1: and now a delay of 225 clock ticks
|
1079 |
|
|
Thread 1: and now a delay of 234 clock ticks
|
1080 |
|
|
Thread 0: and now a delay of 231 clock ticks
|
1081 |
|
|
Thread 1: and now a delay of 224 clock ticks
|
1082 |
|
|
Thread 0: and now a delay of 249 clock ticks
|
1083 |
|
|
Thread 1: and now a delay of 202 clock ticks
|
1084 |
|
|
Thread 0: and now a delay of 235 clock ticks
|
1085 |
|
|
|
1086 |
|
|
|
1087 |
|
|
|
1088 |
|
|
When running in a simulator the
|
1089 |
|
|
delays might be quite long. On a hardware board (where the clock
|
1090 |
|
|
speed is 100 ticks/second) the delays should average to
|
1091 |
|
|
about 2.25 seconds. In simulation, the delay will depend on the
|
1092 |
|
|
speed of the host processor and will almost always be much slower than
|
1093 |
|
|
the actual board. You might want to reduce the delay parameter when running
|
1094 |
|
|
in simulation.
|
1095 |
|
|
|
1096 |
|
|
|
1097 |
|
|
|
1098 |
|
|
|
1099 |
|
|
shows how this
|
1100 |
|
|
multitasking program executes. Note that apart from the thread
|
1101 |
|
|
creation system calls, this program also creates and uses a
|
1102 |
|
|
mutex for synchronization
|
1103 |
|
|
between the printf() calls in the two
|
1104 |
|
|
threads. This is because the C library standard I/O (by default) is
|
1105 |
|
|
configured not to be thread-safe, which means that if more than one
|
1106 |
|
|
thread is using standard I/O they might corrupt each other. This is
|
1107 |
|
|
fixed by a mutual exclusion (or mutex) lockout
|
1108 |
|
|
mechanism: the threads do not call printf() until
|
1109 |
|
|
cyg_mutex_lock() has returned, which only happens
|
1110 |
|
|
when the other thread calls
|
1111 |
|
|
cyg_mutex_unlock().
|
1112 |
|
|
|
1113 |
|
|
You could avoid using the mutex by configuring the C library to
|
1114 |
|
|
be thread-safe (by selecting the component
|
1115 |
|
|
CYGSEM_LIBC_STDIO_THREAD_SAFE_STREAMS).
|
1116 |
|
|
|
1117 |
|
|
|
1118 |
|
|
ID="FIGURE-TWOTHREADS-WITH-SIMPLE-PRINTS"> Two
|
1119 |
|
|
threads with simple print statements after random delays
|
1120 |
|
|
![]()
|
1121 |
|
|
|
1122 |
|
|
|
1123 |
|
|
|
1124 |
|
|
|
1125 |
|
|
|
1126 |
|
|
|
1127 |
|
|
|
1128 |
|
|
|
1129 |
|
|
|
1130 |
|
|
|
1131 |
|
|
|
1132 |
|
|
More Features — Clocks and Alarm
|
1133 |
|
|
Handlers
|
1134 |
|
|
|
1135 |
|
|
If a program wanted to execute a task at a given time, or
|
1136 |
|
|
periodically, it could do it in an inefficient way by sitting in a
|
1137 |
|
|
loop and checking the real-time clock to see if the proper amount of
|
1138 |
|
|
time has elapsed. But operating systems usually provide system calls
|
1139 |
|
|
which allow the program to be informed at the desired time.
|
1140 |
|
|
|
1141 |
|
|
eCos provides a rich timekeeping formalism, involving
|
1142 |
|
|
counters, clocks,
|
1143 |
|
|
alarms, and timers. The
|
1144 |
|
|
precise definition, relationship, and motivation of these features is
|
1145 |
|
|
beyond the scope of this tutorial, but these examples illustrate how
|
1146 |
|
|
to set up basic periodic tasks.
|
1147 |
|
|
|
1148 |
|
|
Alarms are events that happen at
|
1149 |
|
|
a given time, either once or periodically. A thread associates an
|
1150 |
|
|
alarm handling function with the alarm, so that the function will
|
1151 |
|
|
be invoked every time the alarm “goes off”.
|
1152 |
|
|
|
1153 |
|
|
|
1154 |
|
|
|
1155 |
|
|
|
1156 |
|
|
A Sample Program with Alarms
|
1157 |
|
|
|
1158 |
|
|
simple-alarm.c (in
|
1159 |
|
|
the examples directory) is a short program that creates a thread that
|
1160 |
|
|
creates an alarm. The alarm is handled by the function
|
1161 |
|
|
test_alarm_func(), which sets a global
|
1162 |
|
|
variable. When the main thread of execution sees that the variable has
|
1163 |
|
|
changed, it prints a message.
|
1164 |
|
|
|
1165 |
|
|
|
1166 |
|
|
A sample program that creates an alarm
|
1167 |
|
|
|
1168 |
|
|
|
1169 |
|
|
/* this is a very simple program meant to demonstrate
|
1170 |
|
|
a basic use of time, alarms and alarm-handling functions in eCos */
|
1171 |
|
|
|
1172 |
|
|
#include <cyg/kernel/kapi.h>
|
1173 |
|
|
|
1174 |
|
|
#include <stdio.h>
|
1175 |
|
|
|
1176 |
|
|
#define NTHREADS 1
|
1177 |
|
|
#define STACKSIZE 4096
|
1178 |
|
|
|
1179 |
|
|
static cyg_handle_t thread[NTHREADS];
|
1180 |
|
|
|
1181 |
|
|
static cyg_thread thread_obj[NTHREADS];
|
1182 |
|
|
static char stack[NTHREADS][STACKSIZE];
|
1183 |
|
|
|
1184 |
|
|
static void alarm_prog( cyg_addrword_t data );
|
1185 |
|
|
|
1186 |
|
|
/* we install our own startup routine which sets up
|
1187 |
|
|
threads and starts the scheduler */
|
1188 |
|
|
void cyg_user_start(void)
|
1189 |
|
|
{
|
1190 |
|
|
cyg_thread_create(4, alarm_prog, (cyg_addrword_t) 0,
|
1191 |
|
|
"alarm_thread", (void *) stack[0],
|
1192 |
|
|
STACKSIZE, &thread[0], &thread_obj[0]);
|
1193 |
|
|
cyg_thread_resume(thread[0]);
|
1194 |
|
|
}
|
1195 |
|
|
|
1196 |
|
|
/* we need to declare the alarm handling function (which is
|
1197 |
|
|
defined below), so that we can pass it to cyg_alarm_initialize() */
|
1198 |
|
|
cyg_alarm_t test_alarm_func;
|
1199 |
|
|
|
1200 |
|
|
/* alarm_prog() is a thread which sets up an alarm which is then
|
1201 |
|
|
handled by test_alarm_func() */
|
1202 |
|
|
static void alarm_prog(cyg_addrword_t data)
|
1203 |
|
|
{
|
1204 |
|
|
cyg_handle_t test_counterH, system_clockH, test_alarmH;
|
1205 |
|
|
cyg_tick_count_t ticks;
|
1206 |
|
|
cyg_alarm test_alarm;
|
1207 |
|
|
unsigned how_many_alarms = 0, prev_alarms = 0, tmp_how_many;
|
1208 |
|
|
|
1209 |
|
|
system_clockH = cyg_real_time_clock();
|
1210 |
|
|
cyg_clock_to_counter(system_clockH, &test_counterH);
|
1211 |
|
|
cyg_alarm_create(test_counterH, test_alarm_func,
|
1212 |
|
|
(cyg_addrword_t) &how_many_alarms,
|
1213 |
|
|
&test_alarmH, &test_alarm);
|
1214 |
|
|
cyg_alarm_initialize(test_alarmH, cyg_current_time()+200, 200);
|
1215 |
|
|
|
1216 |
|
|
/* get in a loop in which we read the current time and
|
1217 |
|
|
print it out, just to have something scrolling by */
|
1218 |
|
|
for (;;) {
|
1219 |
|
|
ticks = cyg_current_time();
|
1220 |
|
|
printf("Time is %llu\n", ticks);
|
1221 |
|
|
/* note that we must lock access to how_many_alarms, since the
|
1222 |
|
|
alarm handler might change it. this involves using the
|
1223 |
|
|
annoying temporary variable tmp_how_many so that I can keep the
|
1224 |
|
|
critical region short */
|
1225 |
|
|
cyg_scheduler_lock();
|
1226 |
|
|
tmp_how_many = how_many_alarms;
|
1227 |
|
|
cyg_scheduler_unlock();
|
1228 |
|
|
if (prev_alarms != tmp_how_many) {
|
1229 |
|
|
printf(" --- alarm calls so far: %u\n", tmp_how_many);
|
1230 |
|
|
prev_alarms = tmp_how_many;
|
1231 |
|
|
}
|
1232 |
|
|
cyg_thread_delay(30);
|
1233 |
|
|
}
|
1234 |
|
|
}
|
1235 |
|
|
|
1236 |
|
|
/* test_alarm_func() is invoked as an alarm handler, so
|
1237 |
|
|
it should be quick and simple. in this case it increments
|
1238 |
|
|
the data that is passed to it. */
|
1239 |
|
|
void test_alarm_func(cyg_handle_t alarmH, cyg_addrword_t data)
|
1240 |
|
|
{
|
1241 |
|
|
++*((unsigned *) data);
|
1242 |
|
|
}
|
1243 |
|
|
|
1244 |
|
|
|
1245 |
|
|
|
1246 |
|
|
When you run this program (by typing continue at
|
1247 |
|
|
the (gdb) prompt) the output should look like
|
1248 |
|
|
this:
|
1249 |
|
|
|
1250 |
|
|
Starting program: BASE_DIR/examples/simple-alarm.exe
|
1251 |
|
|
Time is 0
|
1252 |
|
|
Time is 30
|
1253 |
|
|
Time is 60
|
1254 |
|
|
Time is 90
|
1255 |
|
|
Time is 120
|
1256 |
|
|
Time is 150
|
1257 |
|
|
Time is 180
|
1258 |
|
|
Time is 210
|
1259 |
|
|
--- alarm calls so far: 1
|
1260 |
|
|
Time is 240
|
1261 |
|
|
Time is 270
|
1262 |
|
|
Time is 300
|
1263 |
|
|
Time is 330
|
1264 |
|
|
Time is 360
|
1265 |
|
|
Time is 390
|
1266 |
|
|
Time is 420
|
1267 |
|
|
--- alarm calls so far: 2
|
1268 |
|
|
Time is 450
|
1269 |
|
|
Time is 480
|
1270 |
|
|
|
1271 |
|
|
|
1272 |
|
|
|
1273 |
|
|
When running in a simulator the delays
|
1274 |
|
|
might be quite long. On a hardware board (where the clock speed is 100
|
1275 |
|
|
ticks/second) the delays should average to about 0.3 seconds (and 2
|
1276 |
|
|
seconds between alarms). In simulation, the delay will depend on the
|
1277 |
|
|
speed of the host processor and will almost always be much slower than
|
1278 |
|
|
the actual board. You might want to reduce the delay parameter when
|
1279 |
|
|
running in simulation.
|
1280 |
|
|
|
1281 |
|
|
|
1282 |
|
|
Here are a few things you might notice about this program:
|
1283 |
|
|
|
1284 |
|
|
|
1285 |
|
|
|
1286 |
|
|
It used the cyg_real_time_clock() function;
|
1287 |
|
|
this always returns a handle to the default system real-time clock.
|
1289 |
|
|
|
1290 |
|
|
|
1291 |
|
|
|
1292 |
|
|
Clocks are based on counters, so the function cyg_alarm_create()
|
1294 |
|
|
uses a counter handle. The program used the function
|
1295 |
|
|
cyg_clock_to_counter() to strip the clock handle
|
1296 |
|
|
to the underlying counter handle.
|
1297 |
|
|
|
1298 |
|
|
|
1299 |
|
|
|
1300 |
|
|
Once the alarm is created it is
|
1301 |
|
|
initialized with cyg_alarm_initialize(), which
|
1302 |
|
|
sets the time at which the alarm should go off, as well as the period
|
1303 |
|
|
for repeating alarms. It is set to go off at the current time and
|
1304 |
|
|
then to repeat every 200 ticks.
|
1305 |
|
|
|
1306 |
|
|
|
1307 |
|
|
|
1308 |
|
|
The alarm handler function
|
1309 |
|
|
test_alarm_func() conforms to the guidelines for
|
1310 |
|
|
writing alarm handlers and other delayed service routines: it does not invoke any
|
1312 |
|
|
functions which might lock the scheduler. This is discussed in detail
|
1313 |
|
|
in the eCos Reference Manual, in the chapter
|
1314 |
|
|
The eCos Kernel.
|
1315 |
|
|
|
1316 |
|
|
|
1317 |
|
|
|
1318 |
|
|
There is a critical region in this program:
|
1319 |
|
|
the variable how_many_alarms is accessed in the
|
1320 |
|
|
main thread of control and is also modified in the alarm handler. To
|
1321 |
|
|
prevent a possible (though unlikely) race condition on this variable,
|
1322 |
|
|
access to how_many_alarms in the principal thread
|
1323 |
|
|
is protected by calls to cyg_scheduler_lock() and
|
1324 |
|
|
cyg_scheduler_unlock(). When the scheduler is
|
1325 |
|
|
locked, the alarm handler will not be invoked, so the problem is
|
1326 |
|
|
averted.
|
1327 |
|
|
|
1328 |
|
|
|
1329 |
|
|
|
1330 |
|
|
|
1331 |
|
|
|
1332 |
|
|
|
1333 |
|
|
|