Escolar Documentos
Profissional Documentos
Cultura Documentos
Datum
31.03.2004
Version
2.0.3
Seite 1/23
API IO Library
1 History
Version
Date
Author
Comments
1.5
25.11.2002
CS
Duda
feedback from DC
06.02.2003
CS
15.02.2003
CS
25.02.2003
CS
Cleanup (wording)
27.02.2003
Kraneis
2.0
27.02.2003
CS
Cleanup (wording)
2.0.1
02.09.2003
CS
2.0.2
15.12.2003
Spohr
2.0.3
31.03.2004
Spohr
Page 2/23
API IO Library
2 Contents
1
History..........................................................................................................................................................2
Contents.......................................................................................................................................................3
Introduction .................................................................................................................................................5
Constants ..........................................................................................................................................7
4.2
Types..................................................................................................................................................7
4.3
4.4
4.3.1
4.3.2
4.3.3
4.3.4
Asynchronous API..........................................................................................................................10
4.4.1
4.4.2
4.4.3
4.4.4
4.5
4.6
Overview ..........................................................................................................................................14
5.2
Driver API.........................................................................................................................................14
5.2.1
5.2.2
5.3
Error hook........................................................................................................................................18
5.4
Driver configuration........................................................................................................................19
5.5
6.2
Code generation..............................................................................................................................21
6.1.1
6.1.2
6.1.3
Overview...............................................................................................................................21
6.2.2
6.2.3
API IO Library
Page 4/23
API IO Library
3 Introduction
This document describes an interface for drivers in deeply embedded systems. Typically these systems only
have a few resources and overhead has to be omitted. Nevertheless a standardized interface between the
application and hardware drivers is useful e.g. to force modularisation and portability of application software. The
tools and concepts described herein provide one way of implementing such an interface. The interface is referred
to as the IO library.
The main goal is to offer a standardized interface to access low-level drivers, which may be accessed in the
following two ways: Either in a synchronous way where the caller blocks until the service is finished or in an
asynchronous way where a caller is informed from the driver once the work has been done. A driver which uses
the asynchronous model can also be used in conjunction with a buffer. This buffer contains the latest work for the
driver and the buffer services provides new work for the driver once it is ready again. The handling of the buffer is
done by the IO library and is independent of a specific asynchronous driver. The described interface supports the
synchronous and asynchronous models as well as buffered asynchronous methods. Since the IO library itself
1
also needs resources and some management, it uses an OSEK/VDX operating system.
The following picture shows the different interfaces of the IO library which are also described in this document.
application
synchronous
API
asynchronous
notification
IO library
asynchronous
asynchronous
asynchronous
synchronous
synchronous
synchronous
driver 1
driver 2
.....
driver N
Since hardware is sometimes very different, the IO library supports also different types of drivers. Depending on
the type of the driver specific services are available. Driver types can be either Standard, Random or Channel
drivers. Each of these driver types has its own set of services. (There are also services which are general
available for each driver. These are called common services.)
Drivers need not support the synchroneous interface and the asynchroneous interface in parallel. Also, drivers
need only be able to cope with one service at a time. Either the caller has to to make sure that only one service
request is issued at a time, or asynchroneous mode with sufficient buffering has to be used. The only exception
to this rule is the service to get the software version (IO_GetVersionOfDriver), which may always be called. The
IO driver specification can define more driver specific exceptions to this rule, for example a call to preliminary
terminate a running service request.
The IO library and the drivers have to be configured by the user before they can be used. With this approach the
drivers and the IO library can be tailored to the needs of the application and can be implemented in an optimised
1
API IO Library
way. Typically the configuration information has to be saved in order to reuse it later. The language used for this
purpose is called DIL (device implementation language). DIL is used for saving user configurations and to specify
driver information by people writing drivers for the IO library.
Page 6/23
API IO Library
4 IO library API interface
This chapter describes the API of the IO library which can be used by the application programmer. The API is
provided as a C language interface.
4.1
Constants
4.2
Types
IO_SymbolicName
IO_DeviceType
API IO Library
4.3
IO_FunctionNrType
IO_DeviceStateType
IO_SizeType
IO_MemPtrType
IO_PositionType
IO_ValueType
(Type for values of channel devices, fix type: 16 bit unsigned value)
IO_ChannelType
IO_ModeType
IO_U32
Synchronous API
The following services are provided by the IO library to access a synchronous driver. In synchronous mode the
API call returns after the work is done. This means that the call can block for some time (e.g. while programming
a flash EEPROM).
4.3.1
4.3.2
API IO Library
This service implements the read functionality of the driver device. The argument address is a pointer to
the destination of the data to be read. After size units has been read, the service returns. It returns either
IO_E_OK, IO_E_INVALID_SIZE (size is '0') or a driver specific code.
IO_ErrorType IO_WriteSync(IO_SymbolicName device, const IO_MemPtrType
address, IO_SizeType size)
This service implements the write functionality of the driver device. The argument address is a pointer to
the destination of the data to be written. After writing size units, the service returns. It returns either
IO_E_OK, IO_E_INVALID_SIZE (size is '0') or a driver specific code.
4.3.3
4.3.4
Page 9/23
API IO Library
4.4
Asynchronous API
Accessing a driver using an asynchronous API causes an immediate return to the caller. The driver will inform the
caller via a function call after the work is finished. This function call is given to the driver as an argument during
the initial call. The function itself is called a callback. The callback always takes the following three arguments:
IO_DeviceType : This contains a number of the device. The number is generated from the
configuration tool and is named <device>_number.
IO_FunctionNrType: This argument contains the type of call. Possible values are IO_FUNC_Read,
IO_FUNC_Write, etc.
IO_ErrorType: This contains the return value of the call. A value of E_IO_OK indicates that the
service finished successfully. IO_E_INVALID_SIZE informs the user that an invalid size ('0' or too
large) has been passed as parameter. For random devices, , IO_E_INVALID_POSITION yields a
location which is not accessible. Other values indicate device specific problems.
Instead of supplying a callback function the user can also use the null pointer (NULL) as a argument. In this case
no function is called.
Depending on the configuration, calls to a asynchronous driver are buffered by the IOLibrary. This option can be
enabled during the configuration stage and is transparent to the user. Buffered requests are handed to the driver
in the order they arrive. Currently no checks are implemented to handle buffer overflow of these buffers.
Since the address of the callback is stored within the IO library, a successive service call can only be made if
either there is a free buffer, or after finishing the currently running service call via the callback function. Violating
this rule may cause undefined behaviour in the whole system!
The currently running service is only finished after the callback has returned. A successive service call within a
callback is therefor only possible if there is a free buffer. It should also be noted that calling a service in a callback
will add to the required stack space of the calling driver. Device drivers should have all work done before calling
the callback to be able to cope with the situation of back-to-back calls.
The following services are provided by the IO library to access an asynchronous driver.
4.4.1
API IO Library
This service can be used to check the state of the driver device. It does not use any callback functions,
but returns the current state to the user. Possible state values are: IO_STATE_IDLE or
IO_STATE_ACTIVE or other driver specific values.
4.4.2
4.4.3
4.4.4
Page 11/23
API IO Library
void IO_SetAsync(IO_SymbolicName device, IO_ChannelType channel, IO_ValueType
value, void (* completion)(IO_DeviceType, IO_FunctionNrType, IO_ErrorType))
This service implements the channel based set functionality of the driver device. The argument channel
identifies the channel where to set the new value. After writing value, the service calls the supplied
callback function.
4.5
4.6
Error Hook
The IO Library supports a central error logging mechanism called error hook. The error hook is a global function
provided by the user. For each driver the user can enable the error hook by setting the IO_ERRORHOOK variable
of the driver to TRUE. The context where the hook will be called is not specified (it can be the user or driver
2
context) . This means that no other calls to drivers are allowed within the hook function.
The prototype of the error hook is:
void IO_ErrorHook (IO_DeviceType device, IO_ErrorType error);
The parameter device identifies the calling driver. The second parameter holds information about the
occurred problem.
The hook may also be called with an interrupt context or within a task if an OSEK OS is used.
Page 12/23
API IO Library
Note: it is the responsibility of the entity which encounters the error (library or driver) to call IO_ErrorHook.
Page 13/23
API IO Library
5 Driver implementation
5.1
Overview
This chapter explains how to implement a driver in a way that it can be used by the IO library.
5.2
Driver API
The driver must conform to a given application interface in order to be recognized by the IO library. These
interfaces depends on the type of driver. It must correspond to either the synchronous or asynchronous interface,
or alternatively may support both types. When buffering is used, the asynchronous interface will be used by the
IO library.
5.2.1
5.2.1.1
5.2.1.2
Page 14/23
API IO Library
5.2.1.3
5.2.1.4
Note: A driver must either implement the random, channel or the standard services. Drivers which are supporting
more than one service type are not supported.
5.2.2
For the asynchronous interface, the following services have to be provided by the driver. The services return
immediately and inform the user once the actual call is finished via the callback routine.
The callback functionality works as follows: After the user calls a service of the IO library (e.g.
IO_ReadAsync()) the supplied callback function is stored in a global variable. The driver function is called and
returns immediately. After the actual work is done, the driver must call the callback function using the global
Page 15/23
API IO Library
variable. If the callback variable contains a value of NULL, the callback must not be used! The variable which
hold the callback value is generated and has a fixed name: <Drivername>_Callback. It should be used by the
driver like this:
If (<Drivername>_Callback != NULL)
(* <Drivername>_Callback)(devicename, functionname, errorcode);
where devicename is IO_DEVICENR_<Drivername> (supplied by the IO library), functionname is
IO_FUNC_<Functionnr> (also supplied by the IO library) and errorcode should contain a valid error code, or in
the case of no error IO_E_OK.
Note that it is the responsibility of the user to avoid additional calls to a driver whilst a service call is already busy.
The services are:
5.2.2.1
5.2.2.2
API IO Library
5.2.2.3
5.2.2.4
Note: A driver must either implement the random, the channel or the standard services. Drivers which are
supporting more than one service type are not supported.
Page 17/23
API IO Library
5.3
Error hook
If the user enables the error hook for a driver the driver must call the error hook if the return value of a service is
not IO_E_OK. For synchronous drivers the call to the hook function must be done before the service returns. For
asynchronous drivers the hook must be called before calling the user callback function.
Page 18/23
API IO Library
5.4
Driver configuration
The drivers configuration is stored in a configuration file. This file is parsed by a generator to get information
about the options which are needed by the driver. The format of the configuration file is described in the next
chapter. It contains definitions of driver specific parameters called variables. Most of these variables will belong to
driver specific features like register settings, driver modi etc. On the other hand there are some specific variables
which do not control the driver, but rather configure the IO library for the driver. These variables are:
-
IO_DRIVERMODUS : Contains the modus of the driver (as text) and must be either SYNCHRON,
ASYNCHRON or BOTH , depending on the supported modes. If the variable is missing the default is
SYNCHRON.
IO_NUMBEROFBUFFERS : Number of buffers (max. 255 per driver supported), if the drivers supports
asynchronous mode. The IO library can buffer up to IO_NUMBEROFBUFFERS requests, besides the
running request. If the variable is missing the default will be 0.
IO_DEVICETYPE : Specifies the type of the device. Depending on the type specific services of the driver
are available. Currently the following types are defined: STANDARD, CHANNEL or RANDOM. The variable
must be set to one value. If the variable is missing the default will be STANDARD.
IO_LINKEDDRIVER : Name of the real driver if this driver links to another. See 5.5 below for details. If
the variable is missing the device is not linked.
IO_ERRORHOOK : Specifies whether this driver must call the error hook function. Must be either TRUE
or FALSE. TRUE means that the driver must call the IO_ErrorHook function if a error occurs. If the
variable is missing, the default is FALSE.
IO_GENERATEDRIVER : allows to suppress generation of driver code. Values can be TRUE or FALSE.
The value should be set to FALSE if a configuration describes a driver which is not used. In this case no
buffers etc. are allocated for this driver and no driver files are copied during the generation process. If the
parameter is set to TRUE the code for the driver is generated. Default is TRUE.
Page 19/23
API IO Library
When implementing driver functions in C or assembly language, you can refer to variables of the configuration in
your source files. To refer a variable, you have to put two percent signs to the left and right of the variable name.
This sequence is recognized by the generator whilst copying the driver files to the user directory.
Example: Within your C files you may refer to a buffer whose size will be controlled via the configuration tool. To
do this, you should write the following in your source code:
unsigned char buffer[%%BUFFSIZE%%];
and after the configuration, the source will contain the actual user value of the buffer size instead of
%%BUFFSIZE%%. If the user selects a value of 50 for example, the variable name (with %% characters) is
replaced by the actual value:
unsigned char buffer[50];
5.5
Linked drivers
Sometimes it is necessary that drivers although they are defined independently must be handled by the IO library
as one device with respect to asynchronous IO. There are 2 cases which are handled by the IO library:
1. More than one driver share another IO library driver
nd
Example is a driver which does not use the hardware directly but uses another (2 ) driver for access.
This can happen, e.g if the real device is hidden across a bus system. In this case the user has to link the
nd
2 driver within the configuration to the original driver with the IO_LINKEDDRIVER variable.
nd
Since the 2 driver is typically also used by the application directly (or even by other drivers) the calls to
nd
the 2 driver are buffered by the IO library to avoid problems when user call services of these drivers
simultaneously. As a consequence the specified linked driver must be asynchronous, because only
asynchronous drivers can be buffered. Also the IO_GENERATEDRIVER variable must be set to TRUE
for the linked driver to avoid a linking to an unused driver.
2. More than one driver share another non IO library driver
Example is a bus system to which some external devices are connected. To access these devices the
access to the bus must be coordinated. Since the driver of the bus is not a real IO library driver, the
access must be serialized by the IO library itself. This is achieved by using one common buffer for all IO
devices which are using the same non IO driver. As a consequence the drivers must be configured to
use asynchronous mode, because only asynchronous drivers can be buffered. The IO_LINKEDDRIVER
variable must contain the name of the non IO library driver. All calls for IO library drivers which use the
same name are then queued using one buffer. The name of the non IO library driver must not match the
name of an existing IO library driver!
Page 20/23
API IO Library
6 I/O Library Configurator
6.1
Code generation
When using the IO library the user has to configure his/her application by selecting driver or IO library specific
variables. After the selection the IO library and the used drivers are generated into a user specific directory.
The generated files are:
IO_gen.h
IO_gen.c
IOLibrary.h
IOLibrary.c
Driver specific files: header, sources, assembly, OIL or any other files.
Depending on the configuration the generated IOLibrary.c and/or IO_gen.c may be empty.
The user must include the IOLibrary.h header file before he/she can use the services of the IO library.
6.1.1
The code generated for synchronous drivers must make the transition from the user call to the driver function.
This is done by doing C preprocessor concatenation. In this way the call is made directly to the driver and no
additional code is needed.
6.1.2
The code generated for asynchronous drivers must also redirect the user call to the driver function, and have to
take care that calls are buffered if more users call the same driver. This is reached by using a buffer mechanism,
where the user have to supply the number of buffers. The buffer is realized as a FIFO buffer, so calls to the driver
are made according to the order they are arrived.
6.1.3
Linked drivers are using other drivers and so buffering must be used if more users access the used driver. The
generation takes care of this behaviour and enables the buffing of calls depending on the configuration.
6.2
DIL Format
6.2.1
Overview
The format which is used to save configurations and to configure a driver is called DIL Device Implementation
Language. DIL is a plain ASCII format which is line oriented to allow easy understanding of the code and easy
programming of DIL readers and writers.
The general format of a DIL file consists of
1) lines of comments starting with a # are ignored
2) empty lines are also ignored
3) lines which have the form of NAME[.NAME]*=VALUE where NAME consists of alphanumeric characters
and VALUE consists of printable characters. The first NAME must be present, followed by other NAMEs
separated by dots (.). The depth of the NAME cascading is not limited, but should not be deeper than
10. The length of a single NAME is not limited. Between the last NAME element and the VALUE
element, there must be an equals sign (=). The VALUE part ends where the line ends. Note that the left
part of the equal sign is always case significant.
6.2.2
Page 21/23
API IO Library
The following rules apply to driver config files. These files describe the possible parameters a driver offers
(including the IO specific variables from the last chapter). The filenames for these config files should end with
.cnf . The generator currently recognizes the following lines:
1) Lines starting with NAME have the form NAME=<VALUE> where the value is recognized as the driver
name. This driver name must be used if the user wants to call functions of the driver e.g.
IO_ReadSync(<drivername>,). The driver name is therefore case sensitive. Example:
NAME=Eeprom
Note that the driver name must be equal to the directory name where the driver files exists:
$OSEK_IOLIBRARY/src/drivers/<arch>/<drivername>
(<arch> = microprocessor architecture, see 6.2.3)
2) Lines starting with VAR define variables. The general form is VAR.<varname>.<field>=<value>. The
field value must be one of the following:
a. DISPLAY defines the type of input field for the variable. Possible values are: TEXT, LIST ,
RADIO or CHECKBOX. The values are case dependent.
i. TEXT defines that the variable will contain any sort of text, e.g. names, defines,
numbers, etc. Typically the user will get a text field as input within the configuration tool.
The value of a variable is the whole typed text. Example: VAR.MyVar.DISPLAY=TEXT
ii. LIST contains a list of different possibilities which are separated by colons. The value of
a variable is always one of the possible values which are specified. For example:
VAR.MyVar.DISPLAY=LIST:First Possibility,Second Possibility,Third Possibility
In this line the value of the variable MyVar is either First Possibility, Second
Possibility or Third Possibility.
iii. RADIO specifies the same as LIST with the exception that the visualization from a
configuration tool may differ from LIST.
Example: VAR.MyVar.DISPLAY=RADIO:First Possibility,Second Possibility,Third
Possibility
iv. The CHECKBOX is a special case of a LIST/RADIO field with exactly 2 options, mostly
used in conjunction with boolean cases (YES/NO or TRUE/FALSE). For example:
VAR.MyVar.DISPLAY=CHECKBOX:YES,NO
b. COMMENT defines a description of the field. The value contains the description.
c.
The following example show a variable named Start which uses a text field as input and has a default
value of 0x100:
VAR.Start.DISPLAY=TEXT
VAR.Start.COMMENT=Start of EEPROM
VAR.Start.DEFAULT=0x100
3) Lines starting with GROUP are used for the GUI layout. The general form is GROUP.<groupname>=
<groupname>|<varname>,[<groupname>|<varname>]* where groupname is the name of another
group and varname is the name of a variable. The configurator tries to put the members of one group
together to visualise dependencies of the input fields.
4) Lines starting with TABS are used for the GUI layout. The general form is
TABS=<groupname>|<varname>,[<groupname>|<varname>]* , where groupname is the name of
another group and varname is the name of a variable. The configurator sets up a tabbed pane on top
level for every group or variable which is listed. The visible identifier for the specific tab is equal to the
corresponding group or variable name. Groups and variables which are not listed will be put in the top
level group. This improves clarity if a larger number of variables has to be configured.
Page 22/23
API IO Library
6.2.3
The following rules apply to saved configuration files. Generally spoken these file contain the current values of a
specific application which uses some drivers managed by the IO Library. For files containing these data the
ending .dil should be used. These file consists of the following lines:
1) Lines starting with ARCH. The format is ARCH=<VALUE> where <VALUE> is a valid architecture
supported by the IO library. <VALUE> is used to find the right drivers for the generation and is placed in
the architecture section of the search path ($OSEK_IOLIBRARY/src/drivers/<ARCH>/driver). A
Example of such a line is:
ARCH=HC12
2) Lines in the form of DRIVER.<drivername>.VAR.<variablname>.VALUE=<VALUE>. These lines set the
driver specific variables to the specified values. Examples:
DRIVER.EEprom.VAR.Start.VALUE=1000
DRIVER.EEprom.VAR.UrgentWrite.VALUE=TRUE
Page 23/23