Name

cyg_hal_sys_xyz — Access Linux system facilities

Synopsis

#include <cyg/hal/hal_io.h>
      

int cyg_hal_sys_xyzzy(...);

Description

On a real embedded target eCos interacts with the hardware by peeking and poking various registers, manipulating special regions of memory, and so on. The synthetic target does not access hardware directly. Instead I/O and other operations are emulated by making appropriate Linux system calls. The HAL package exports a number of functions which allow other packages, or even application code, to make these same system calls. However this facility must be used with care: any code which calls, for example, cyg_hal_sys_write will only ever run on the synthetic target; that functionality is obviously not provided on any real hardware because there is no underlying Linux kernel to implement it.

The synthetic target only provides a subset of the available system calls, specifically those calls which have proved useful to implement I/O emulation. This subset can be extended fairly easily if necessary. All of the available calls, plus associated data structures and macros, are defined in the header file cyg/hal/hal_io.h. There is a simple convention: given a Linux system call such as open, the synthetic target will prefix cyg_hal_sys and provide a function with that name. The second argument to the open system call is a set of flags such as O_RDONLY, and the header file will define a matching constant CYG_HAL_SYS_O_RDONLY. There are also data structures such as cyg_hal_sys_sigset_t, matching the Linux data structure sigset_t.

In most cases the functions provided by the synthetic target behave as per the documentation for the Linux system calls, and section 2 of the Linux man pages can be consulted for more information. There is one important difference: typically the documentation will say that a function returns -1 to indicate an error, with the actual error code held in errno; the actual underlying system call and hence the cyg_hal_sys_xyz provided by eCos instead returns a negative number to indicate an error, with the absolute value of that number corresponding to the error code; usually it is the C library which handles this and manipulates errno, but of course synthetic target applications are not linked with that Linux library.

However, there are some exceptions. The Linux kernel has evolved over the years, and some of the original system call interfaces are no longer appropriate. For example the original select system call has been superseded by _newselect, and that is what the select function in the C library actually uses. The old call is still available to preserve binary compatibility but, like the C library, eCos makes use of the new one because it provides the appropriate functionality. In an attempt to reduce confusion the eCos function is called cyg_hal_sys__newselect, in other words it matches the official system call naming scheme. The authoritive source of information on such matters is the Linux kernel sources themselves, and especially its header files.

eCos packages and applications should never #include Linux header files directly. For example, doing a #include </usr/include/fcntl.h> to access additional macros or structure definitions, or alternatively manipulating the header file search path, will lead to problems because the Linux header files are likely to duplicate and clash with definitions in the eCos headers. Instead the appropriate functionality should be extracted from the Linux headers and moved into either cyg/hal/hal_io.h or into application code, with suitable renaming to avoid clashes with eCos names. Users should be aware that large-scale copying may involve licensing complications.

Adding more system calls is usually straightforward and involves adding one or more lines to the platform-specific file in the appropriate platform HAL, for example syscall-i386-linux-1.0.S. However it is necessary to do some research first about the exact interface implemented by the system call, because of issues such as old system calls that have been superseded. The required information can usually be found fairly easily by searching through the Linux kernel sources and possibly the GNU C library sources.