eCos programs do not have to satisfy any unusual requirements, but there are always some differences between a program written for a real-time operating system as opposed to one written for a time sharing, virtual memory system like UNIX or Windows NT.
This chapter contains checklist of things to remember when writing eCos programs.
The entry point for
eCos
user programs is usually
cyg_user_start()
instead of
main()
, although
main()
can
be used if the ISO C library package is selected. Complete detail on the start-up sequence is given in
System start-up
.
Any program which uses eCos system calls must have the following line at the top of the file:
#include <cyg/kernel/kapi.h>
and the programmer must make sure that
cyg/kernel/kapi.h
is available in the compiler include path. This can be done by setting the
C_INCLUDE_PATH
environment variable or by including the
-I
flag on the compiler command line.
The
eCos
configuration and building process (described in
Getting Started with
eCos
and
eCos
User's Guide
) builds a single library,
libtarget.a
, which contains the selected
eCos
components. The
libtarget.a
library does
not
contain any user libraries: If you put some of your source in libraries, you will have to explicitly include those libraries in the linking instruction.
You also need to link to the
GNU C Compiler
runtime support library (
libgcc.a
).
You should not link to the standard C++ library. This can be achieved with the -nostdlib option.
You should only link to
libtarget.a
and
libgcc.a
using the linker script
target.ld
provided with
eCos.
The command line for linking should look like
gcc [options] [object files] -Ttarget.ld -nostdlib
In eCos a distinction is made between exceptions and interrupts.
are the result of some action by the currently executing code. Examples of exceptions are divide by zero, illegal instruction, bad memory access, etc.
are the result of a signal source which is conceptually asynchronous with the currently executing code. Examples of interrupts sources are the real-time clock, external and on chip peripherals and so forth.
This distinction is made in the eCos hardware abstraction layer (HAL) to provide a cleaner and more portable mechanism for installing interrupt handlers and exception handlers. Individual hardware platforms can have different ways of naming and handling interrupts, which is why this abstraction layer was chosen.
Interrupts and exceptions are both associated with vectors , which are labeled by vector numbers (see Exception handling and Interrupt handling ).
There are distinct spaces for exception and interrupt vectors. These are called "exception vector numbers" and "interrupt vector numbers". System calls which install exception handlers use the exception vector number, and the system calls which install interrupt handlers use the interrupt vector number to specify which interrupt or exception should be handled by the handler.
The details of the vector layout depend on the microprocessor and interrupt controller, and are documented in the relevant API sections.
Interrupt handlers are actually a pair of functions, one of which (the interrupt service routine, or ISR ) is executed immediately and runs with that interrupt disabled. Since interrupts are disabled for the duration of the ISR, the ISR should be very brief and should not use any system services.
After the ISR exits, but before the kernel scheduler is invoked again, a
delayed service routine
(
DSR
) will be invoked. It executes with scheduling disabled, but with interrupts enabled, so that further invocations of the same DSR can be queued. The DSR can use some producer-side system calls, but it should be carefully crafted to avoid using any call that might put its thread to sleep. One of the few examples of safe calls is
cyg_semaphore_post()
; the non-blocking versions of some system calls are also safe. A call that is unsafe is
cyg_mutex_lock()
, since it will block if the mutex is already locked by another thread.
Finally, eCos has a formalism for installing low level handlers which bypass the kernel mechanisms described above. A program can install a vector service routine ( VSR ) which will be invoked instead of the kernel's usual exception or interrupt handling. The VSR will typically be written in assembly language.
VSRs are associated with vector numbers in the exception space, just like exception handlers (although there are some variations -- architectures in which there are no exceptions in the eCos sense). The main difference between VSRs and exception handlers is that VSRs bypass the kernel's usual mechanisms.
Most eCos system calls expect you to pass the address of pre-allocated memory for the objects created in that system call. This is frequently the preferred way of doing things for embedded applications, where programmers want to allocate all memory statically and have fine control over that resource.
In contrast, some
eCos
system calls also allow a
NULL
pointer to be passed. In such a case the kernel will allocate the memory or select default size. This feature is not supported in the current release, and a warning flag is placed in the documentation for those routines (like
cyg_thread_create()
).
eCos provides dynamic memory allocation, based on memory pools, a useful and flexible approach to memory management inspired by the µ ITRON compatibility layer. These are described in Memory pools .
If you configure your system to use the Standard C Library you can also use the standard
malloc()
library call.
This section describes how the eCos kernel and basic packages behave when system calls are invoked with bad parameters.
In eCos, the basic kernel assertion behavior is configuration-dependent.
By default, assertions are turned off in the kernel. If the kernel is configured to turn them on, the kernel will make basic assertions, such as checking for invalid parameters when system calls are invoked. If an assertion fails, the kernel will print a message to the diagnostic output channel and stop executing.
If the kernel is configured with assertions disabled (usually when the application has been thoroughly debugged), it will not do any checking.
The configuration sections referenced above also describe the use of preconditions, postconditions and loop invariants. These are no different from ordinary assertions, but they are used in specialized circumstances, and the programmer would wish to select their presence individually.
Requirements for programs | ||
---|---|---|