Update the BSP howto.

Closes #2590.
This commit is contained in:
Chris Johns 2016-06-17 15:05:41 +10:00
parent 54514fe292
commit 6d7a4d2ee7
21 changed files with 2638 additions and 2587 deletions

View File

@ -1,81 +1,75 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2008.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Ada95 Interrupt Support Ada95 Interrupt Support
####################### #######################
Introduction Introduction
============ ============
This chapter describes what is required to enable Ada interrupt This chapter describes what is required to enable Ada interrupt and error
and error exception handling when using GNAT over RTEMS. exception handling when using GNAT over RTEMS.
The GNAT Ada95 interrupt support RTEMS was developed by The GNAT Ada95 interrupt support RTEMS was developed by Jiri Gaisler
Jiri Gaisler <jgais@ws.estec.esa.nl> who also wrote this <jgais@ws.estec.esa.nl> who also wrote this chapter.
chapter.
Mapping Interrupts to POSIX Signals Mapping Interrupts to POSIX Signals
=================================== ===================================
In Ada95, interrupts can be attached with the interrupt_attach pragma. In Ada95, interrupts can be attached with the interrupt_attach pragma. For
For most systems, the gnat run-time will use POSIX signal to implement most systems, the gnat run-time will use POSIX signal to implement the
the interrupt handling, mapping one signal per interrupt. For interrupts interrupt handling, mapping one signal per interrupt. For interrupts to be
to be propagated to the attached Ada handler, the corresponding signal propagated to the attached Ada handler, the corresponding signal must be raised
must be raised when the interrupt occurs. when the interrupt occurs.
The same mechanism is used to generate Ada error exceptions. The same mechanism is used to generate Ada error exceptions. Three error
Three error exceptions are defined: program, constraint and storage exceptions are defined: program, constraint and storage error. These are
error. These are generated by raising the predefined signals: SIGILL, generated by raising the predefined signals: SIGILL, SIGFPE and SIGSEGV. These
SIGFPE and SIGSEGV. These signals should be raised when a spurious signals should be raised when a spurious or erroneous trap occurs.
or erroneous trap occurs.
To enable gnat interrupt and error exception support for a particular To enable gnat interrupt and error exception support for a particular BSP, the
BSP, the following has to be done: following has to be done:
# Write an interrupt/trap handler that will raise the corresponding - Write an interrupt/trap handler that will raise the corresponding signal
signal depending on the interrupt/trap number. depending on the interrupt/trap number.
# Install the interrupt handler for all interrupts/traps that will be - Install the interrupt handler for all interrupts/traps that will be handled
handled by gnat (including spurious). by gnat (including spurious).
# At startup, gnat calls ``__gnat_install_handler()``. The BSP - At startup, gnat calls ``__gnat_install_handler()``. The BSP must provide
must provide this function which installs the interrupt/trap handlers. this function which installs the interrupt/trap handlers.
Which CPU-interrupt will generate which signal is implementation Which CPU-interrupt will generate which signal is implementation defined. There
defined. There are 32 POSIX signals (1 - 32), and all except the are 32 POSIX signals (1 - 32), and all except the three error signals (SIGILL,
three error signals (SIGILL, SIGFPE and SIGSEGV) can be used. I SIGFPE and SIGSEGV) can be used. I would suggest to use the upper 16 (17 - 32)
would suggest to use the upper 16 (17 - 32) which do not which do not have an assigned POSIX name.
have an assigned POSIX name.
Note that the pragma interrupt_attach will only bind a signal Note that the pragma interrupt_attach will only bind a signal to a particular
to a particular Ada handler - it will not unmask the Ada handler - it will not unmask the interrupt or do any other things to enable
interrupt or do any other things to enable it. This have to be it. This have to be done separately, typically by writing various device
done separately, typically by writing various device register. register.
Example Ada95 Interrupt Program Example Ada95 Interrupt Program
=============================== ===============================
An example program (``irq_test``) is included in the An example program (``irq_test``) is included in the Ada examples package to
Ada examples package to show how interrupts can be handled show how interrupts can be handled in Ada95. Note that generation of the test
in Ada95. Note that generation of the test interrupt interrupt (``irqforce.c``) is BSP specific and must be edited.
(``irqforce.c``) is BSP specific and must be edited.
NOTE: The ``irq_test`` example was written for the SPARC/ERC32 .. note::
BSP.
The ``irq_test`` example was written for the SPARC/ERC32 BSP.
Version Requirements Version Requirements
==================== ====================
With RTEMS 4.0, a patch was required to psignal.c in RTEMS With RTEMS 4.0, a patch was required to psignal.c in RTEMS sources (to correct
sources (to correct a bug associated to the default action of a bug associated to the default action of signals 15-32). The SPARC/ERC32
signals 15-32). The SPARC/ERC32 RTEMS BSP includes the``gnatsupp`` subdirectory that can be used as an example RTEMS BSP includes the``gnatsupp`` subdirectory that can be used as an example
for other BSPs. for other BSPs.
With GNAT 3.11p, a patch is required for ``a-init.c`` to invoke With GNAT 3.11p, a patch is required for ``a-init.c`` to invoke the BSP
the BSP specific routine that installs the exception handlers. specific routine that installs the exception handlers.
.. COMMENT: COPYRIGHT (c) 1988-2008.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.

View File

@ -1,12 +1,15 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Analog Driver Analog Driver
############# #############
The Analog driver is responsible for providing an The Analog driver is responsible for providing an interface to Digital to
interface to Digital to Analog Converters (DACs) and Analog Converters (DACs) and Analog to Digital Converters (ADCs). The
Analog to Digital Converters (ADCs). The capabilities provided capabilities provided by this class of device driver are:
by this class of device driver are:
- Initialize an Analog Board - Initialize an Analog Board
@ -22,64 +25,61 @@ by this class of device driver are:
- Reinitialize DACS - Reinitialize DACS
Most analog devices are found on I/O cards that support multiple Most analog devices are found on I/O cards that support multiple DACs or ADCs
DACs or ADCs on a single card. on a single card.
There are currently no analog device drivers included in the There are currently no analog device drivers included in the RTEMS source tree.
RTEMS source tree. The information provided in this chapter The information provided in this chapter is based on drivers developed for
is based on drivers developed for applications using RTEMS. applications using RTEMS. It is hoped that this driver model information can
It is hoped that this driver model information can form the form the basis for a standard analog driver model that can be supported in
basis for a standard analog driver model that can be supported future RTEMS distribution.
in future RTEMS distribution.
Major and Minor Numbers Major and Minor Numbers
======================= =======================
The *major* number of a device driver is its index in the The ``major`` number of a device driver is its index in the RTEMS Device
RTEMS Device Address Table. Address Table.
A *minor* number is associated with each device instance A ``minor`` number is associated with each device instance managed by a
managed by a particular device driver. An RTEMS minor number particular device driver. An RTEMS minor number is an ``unsigned32`` entity.
is an ``unsigned32`` entity. Convention calls for Convention calls for dividing the bits in the minor number down into categories
dividing the bits in the minor number down into categories
like the following: like the following:
- *board* - indicates the board a particular device is located on - ``board`` - indicates the board a particular device is located on
- *port* - indicates the particular device on a board. - ``port`` - indicates the particular device on a board.
From the above, it should be clear that a single device driver From the above, it should be clear that a single device driver can support
can support multiple copies of the same board in a single system. multiple copies of the same board in a single system. The minor number is used
The minor number is used to distinguish the devices. to distinguish the devices.
Analog Driver Configuration Analog Driver Configuration
=========================== ===========================
There is not a standard analog driver configuration table but some There is not a standard analog driver configuration table but some fields are
fields are common across different drivers. The analog driver common across different drivers. The analog driver configuration table is
configuration table is typically an array of structures with each typically an array of structures with each structure containing the information
structure containing the information for a particular board. for a particular board. The following is a list of the type of information
The following is a list of the type of information normally required normally required to configure an analog board:
to configure an analog board:
*board_offset* ``board_offset``
is the base address of a board. is the base address of a board.
*DAC_initial_values* ``DAC_initial_values``
is an array of the voltages that should be written to each DAC is an array of the voltages that should be written to each DAC during
during initialization. This allows the driver to start the board initialization. This allows the driver to start the board in a known
in a known state. state.
Initialize an Analog Board Initialize an Analog Board
========================== ==========================
At system initialization, the analog driver's initialization entry point At system initialization, the analog driver's initialization entry point will
will be invoked. As part of initialization, the driver will perform be invoked. As part of initialization, the driver will perform whatever board
whatever board initialization is required and then set all initialization is required and then set all outputs to their configured initial
outputs to their configured initial state. state.
The analog driver may register a device name for each DAC and ADC in The analog driver may register a device name for each DAC and ADC in the
the system. system.
Open a Particular Analog Open a Particular Analog
======================== ========================
@ -88,8 +88,8 @@ This is the driver open call. Usually this call does nothing other than
validate the minor number. validate the minor number.
With some drivers, it may be necessary to allocate memory when a particular With some drivers, it may be necessary to allocate memory when a particular
device is opened. If that is the case, then this is often the place device is opened. If that is the case, then this is often the place to do this
to do this operation. operation.
Close a Particular Analog Close a Particular Analog
========================= =========================
@ -97,77 +97,69 @@ Close a Particular Analog
This is the driver close call. Usually this call does nothing. This is the driver close call. Usually this call does nothing.
With some drivers, it may be necessary to allocate memory when a particular With some drivers, it may be necessary to allocate memory when a particular
device is opened. If that is the case, then this is the place device is opened. If that is the case, then this is the place where that
where that memory should be deallocated. memory should be deallocated.
Read from a Particular Analog Read from a Particular Analog
============================= =============================
This corresponds to the driver read call. After validating the minor This corresponds to the driver read call. After validating the minor number
number and arguments, this call reads the indicated device. Most analog and arguments, this call reads the indicated device. Most analog devices store
devices store the last value written to a DAC. Since DACs are output the last value written to a DAC. Since DACs are output only devices, saving
only devices, saving the last written value gives the appearance that the last written value gives the appearance that DACs can be read from also.
DACs can be read from also. If the device is an ADC, then it is sampled. If the device is an ADC, then it is sampled.
*NOTE:* Many boards have multiple analog inputs but only one ADC. On .. note::
these boards, it will be necessary to provide some type of mutual exclusion
during reads. On these boards, there is a MUX which must be switched
before sampling the ADC. After the MUX is switched, the driver must
delay some short period of time (usually microseconds) before the
signal is stable and can be sampled. To make matters worse, some ADCs
cannot respond to wide voltage swings in a single sample. On these
ADCs, one must do two samples when the voltage swing is too large.
On a practical basis, this means that the driver usually ends up
double sampling the ADC on these systems.
The value returned is a single precision floating point number Many boards have multiple analog inputs but only one ADC. On these boards,
representing the voltage read. This value is stored in the``argument_block`` passed in to the call. By returning the it will be necessary to provide some type of mutual exclusion during reads.
voltage, the caller is freed from having to know the number of On these boards, there is a MUX which must be switched before sampling the
bits in the analog and board dependent conversion algorithm. ADC. After the MUX is switched, the driver must delay some short period of
time (usually microseconds) before the signal is stable and can be sampled.
To make matters worse, some ADCs cannot respond to wide voltage swings in a
single sample. On these ADCs, one must do two samples when the voltage
swing is too large. On a practical basis, this means that the driver
usually ends up double sampling the ADC on these systems.
The value returned is a single precision floating point number representing the
voltage read. This value is stored in the ``argument_block`` passed in to the
call. By returning the voltage, the caller is freed from having to know the
number of bits in the analog and board dependent conversion algorithm.
Write to a Particular Analog Write to a Particular Analog
============================ ============================
This corresponds to the driver write call. After validating the minor This corresponds to the driver write call. After validating the minor number
number and arguments, this call writes the indicated device. If the and arguments, this call writes the indicated device. If the specified device
specified device is an ADC, then an error is usually returned. is an ADC, then an error is usually returned.
The value written is a single precision floating point number The value written is a single precision floating point number representing the
representing the voltage to be written to the specified DAC. voltage to be written to the specified DAC. This value is stored in the
This value is stored in the ``argument_block`` passed in to the ``argument_block`` passed in to the call. By passing the voltage to the device
call. By passing the voltage to the device driver, the caller is driver, the caller is freed from having to know the number of bits in the
freed from having to know the number of bits in the analog analog and board dependent conversion algorithm.
and board dependent conversion algorithm.
Reset DACs Reset DACs
========== ==========
This is one of the IOCTL functions supported by the I/O control This is one of the IOCTL functions supported by the I/O control device driver
device driver entry point. When this IOCTL function is invoked, entry point. When this IOCTL function is invoked, all of the DACs are written
all of the DACs are written to 0.0 volts. to 0.0 volts.
Reinitialize DACS Reinitialize DACS
================= =================
This is one of the IOCTL functions supported by the I/O control This is one of the IOCTL functions supported by the I/O control device driver
device driver entry point. When this IOCTL function is invoked, entry point. When this IOCTL function is invoked, all of the DACs are written
all of the DACs are written with the initial value configured with the initial value configured for this device.
for this device.
Get Last Written Values Get Last Written Values
======================= =======================
This is one of the IOCTL functions supported by the I/O control This is one of the IOCTL functions supported by the I/O control device driver
device driver entry point. When this IOCTL function is invoked, entry point. When this IOCTL function is invoked, the following information is
the following information is returned to the caller: returned to the caller:
- last value written to the specified DAC - last value written to the specified DAC
- timestamp of when the last write was performed - timestamp of when the last write was performed
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.

View File

@ -1,5 +1,9 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
ATA Driver ATA Driver
########## ##########
@ -11,10 +15,10 @@ ATA device - physical device attached to an IDE controller
Introduction Introduction
============ ============
ATA driver provides generic interface to an ATA device. ATA driver is ATA driver provides generic interface to an ATA device. ATA driver is hardware
hardware independent implementation of ATA standard defined in working draft independent implementation of ATA standard defined in working draft "AT
"AT Attachment Interface with Extensions (ATA-2)" X3T10/0948D revision 4c, Attachment Interface with Extensions (ATA-2)" X3T10/0948D revision 4c, March
March 18, 1996. ATA Driver based on IDE Controller Driver and may be used for 18, 1996. ATA Driver based on IDE Controller Driver and may be used for
computer systems with single IDE controller and with multiple as well. Although computer systems with single IDE controller and with multiple as well. Although
current implementation has several restrictions detailed below ATA driver current implementation has several restrictions detailed below ATA driver
architecture allows easily extend the driver. Current restrictions are: architecture allows easily extend the driver. Current restrictions are:
@ -24,34 +28,39 @@ architecture allows easily extend the driver. Current restrictions are:
- Only PIO mode is supported but both poll and interrupt driven - Only PIO mode is supported but both poll and interrupt driven
The reference implementation for ATA driver can be found in``cpukit/libblock/src/ata.c``. The reference implementation for ATA driver can be found in
``cpukit/libblock/src/ata.c``.
Initialization Initialization
============== ==============
The ``ata_initialize`` routine is responsible for ATA driver The ``ata_initialize`` routine is responsible for ATA driver
initialization. The main goal of the initialization is to detect and initialization. The main goal of the initialization is to detect and register
register in the system all ATA devices attached to IDE controllers in the system all ATA devices attached to IDE controllers successfully
successfully initialized by the IDE Controller driver. initialized by the IDE Controller driver.
In the implementation of the driver, the following actions are performed: In the implementation of the driver, the following actions are performed:
.. code:: c
.. code-block:: c
rtems_device_driver ata_initialize( rtems_device_driver ata_initialize(
rtems_device_major_number major, rtems_device_major_number major,
rtems_device_minor_number minor, rtems_device_minor_number minor,
void \*arg void *arg
) )
{ {
initialize internal ATA driver data structure initialize internal ATA driver data structure
for each IDE controller successfully initialized by the IDE Controller
driver for each IDE controller successfully initialized by the IDE Controller driver
if the controller is interrupt driven if the controller is interrupt driven
set up interrupt handler set up interrupt handler
obtain information about ATA devices attached to the controller obtain information about ATA devices attached to the controller
with help of EXECUTE DEVICE DIAGNOSTIC command with help of EXECUTE DEVICE DIAGNOSTIC command
for each ATA device detected on the controller for each ATA device detected on the controller
obtain device parameters with help of DEVICE IDENTIFY command obtain device parameters with help of DEVICE IDENTIFY command
register new ATA device as new block device in the system register new ATA device as new block device in the system
} }
@ -61,17 +70,19 @@ multitasking environment during the driver initialization.
Detected ATA devices are registered in the system as physical block devices Detected ATA devices are registered in the system as physical block devices
(see libblock library description). Device names are formed based on IDE (see libblock library description). Device names are formed based on IDE
controller minor number device is attached to and device number on the controller minor number device is attached to and device number on the
controller (0 - Master, 1 - Slave). In current implementation 64 minor controller (0 - Master, 1 - Slave). In current implementation 64 minor numbers
numbers are reserved for each ATA device which allows to support up to 63 are reserved for each ATA device which allows to support up to 63 logical
logical partitions per device. partitions per device.
.. code:: c
================ ============= =========== ================
controller minor device number device name ata device minor controller minor device number device name ata device minor
================ ============= =========== ================
0 0 hda 0 0 0 hda 0
0 1 hdb 64 0 1 hdb 64
1 0 hdc 128 1 0 hdc 128
1 1 hdd 172 1 1 hdd 172
... ... ... ... ... ... ...
================ ============= =========== ================
ATA Driver Architecture ATA Driver Architecture
======================= =======================
@ -79,102 +90,92 @@ ATA Driver Architecture
ATA Driver Main Internal Data Structures ATA Driver Main Internal Data Structures
---------------------------------------- ----------------------------------------
ATA driver works with ATA requests. ATA request is described by the ATA driver works with ATA requests. ATA request is described by the following
following structure: structure:
.. code:: c
/* ATA request \*/ .. code-block:: c
/* ATA request */
typedef struct ata_req_s { typedef struct ata_req_s {
Chain_Node link; /* link in requests chain \*/ Chain_Node link; /* link in requests chain */
char type; /* request type \*/ char type; /* request type */
ata_registers_t regs; /* ATA command \*/ ata_registers_t regs; /* ATA command */
uint32_t cnt; /* Number of sectors to be exchanged \*/ uint32_t cnt; /* Number of sectors to be exchanged */
uint32_t cbuf; /* number of current buffer from breq in use \*/ uint32_t cbuf; /* number of current buffer from breq in use */
uint32_t pos; /* current position in 'cbuf' \*/ uint32_t pos; /* current position in 'cbuf' */
blkdev_request \*breq; /* blkdev_request which corresponds to the blkdev_request *breq; /* blkdev_request which corresponds to the ata request */
* ata request
\*/
rtems_id sema; /* semaphore which is used if synchronous rtems_id sema; /* semaphore which is used if synchronous
* processing of the ata request is required * processing of the ata request is required */
\*/ rtems_status_code status; /* status of ata request processing */
rtems_status_code status; /* status of ata request processing \*/ int error; /* error code */
int error; /* error code \*/
} ata_req_t; } ata_req_t;
ATA driver supports separate ATA requests queues for each IDE ATA driver supports separate ATA requests queues for each IDE controller (one
controller (one queue per controller). The following structure contains queue per controller). The following structure contains information about
information about controller's queue and devices attached to the controller: controller's queue and devices attached to the controller:
.. code:: c
.. code-block:: c
/* /*
* This structure describes controller state, devices configuration on the * This structure describes controller state, devices configuration on the
* controller and chain of ATA requests to the controller. * controller and chain of ATA requests to the controller.
\*/ */
typedef struct ata_ide_ctrl_s { typedef struct ata_ide_ctrl_s {
bool present; /* controller state \*/ bool present; /* controller state */
ata_dev_t device[2]; /* ata devices description \*/ ata_dev_t device[2]; /* ata devices description */
Chain_Control reqs; /* requests chain \*/ Chain_Control reqs; /* requests chain */
} ata_ide_ctrl_t; } ata_ide_ctrl_t;
Driver uses array of the structures indexed by the controllers minor Driver uses array of the structures indexed by the controllers minor number.
number.
The following structure allows to map an ATA device to the pair (IDE The following structure allows to map an ATA device to the pair (IDE controller
controller minor number device is attached to, device number minor number device is attached to, device number on the controller):
on the controller):
.. code:: c .. code-block:: c
/* /*
* Mapping of rtems ATA devices to the following pairs: * Mapping of rtems ATA devices to the following pairs:
* (IDE controller number served the device, device number on the controller) * (IDE controller number served the device, device number on the controller)
\*/ */
typedef struct ata_ide_dev_s { typedef struct ata_ide_dev_s {
int ctrl_minor;/* minor number of IDE controller serves rtems ATA device \*/ int ctrl_minor;/* minor number of IDE controller serves rtems ATA device */
int device; /* device number on IDE controller (0 or 1) \*/ int device; /* device number on IDE controller (0 or 1) */
} ata_ide_dev_t; } ata_ide_dev_t;
Driver uses array of the structures indexed by the ATA devices minor Driver uses array of the structures indexed by the ATA devices minor number.
number.
ATA driver defines the following internal events: ATA driver defines the following internal events:
.. code:: c
/* ATA driver events \*/ .. code-block:: c
/* ATA driver events */
typedef enum ata_msg_type_s { typedef enum ata_msg_type_s {
ATA_MSG_GEN_EVT = 1, /* general event \*/ ATA_MSG_GEN_EVT = 1, /* general event */
ATA_MSG_SUCCESS_EVT, /* success event \*/ ATA_MSG_SUCCESS_EVT, /* success event */
ATA_MSG_ERROR_EVT, /* error event \*/ ATA_MSG_ERROR_EVT, /* error event */
ATA_MSG_PROCESS_NEXT_EVT /* process next ata request event \*/ ATA_MSG_PROCESS_NEXT_EVT /* process next ata request event */
} ata_msg_type_t; } ata_msg_type_t;
Brief ATA Driver Core Overview Brief ATA Driver Core Overview
------------------------------ ------------------------------
All ATA driver functionality is available via ATA driver ioctl. Current All ATA driver functionality is available via ATA driver ioctl. Current
implementation supports only two ioctls: BLKIO_REQUEST and implementation supports only two ioctls: ``BLKIO_REQUEST`` and
ATAIO_SET_MULTIPLE_MODE. Each ATA driver ioctl() call generates an ``ATAIO_SET_MULTIPLE_MODE``. Each ATA driver ``ioctl()`` call generates an ATA
ATA request which is appended to the appropriate controller queue depending request which is appended to the appropriate controller queue depending on ATA
on ATA device the request belongs to. If appended request is single request in device the request belongs to. If appended request is single request in the
the controller's queue then ATA driver event is generated. controller's queue then ATA driver event is generated.
ATA driver task which manages queue of ATA driver events is core of ATA ATA driver task which manages queue of ATA driver events is core of ATA
driver. In current driver version queue of ATA driver events implemented driver. In current driver version queue of ATA driver events implemented as
as RTEMS message queue. Each message contains event type, IDE controller RTEMS message queue. Each message contains event type, IDE controller minor
minor number on which event happened and error if an error occurred. Events number on which event happened and error if an error occurred. Events may be
may be generated either by ATA driver ioctl call or by ATA driver task itself. generated either by ATA driver ioctl call or by ATA driver task itself. Each
Each time ATA driver task receives an event it gets controller minor number time ATA driver task receives an event it gets controller minor number from
from event, takes first ATA request from controller queue and processes it event, takes first ATA request from controller queue and processes it depending
depending on request and event types. An ATA request processing may also on request and event types. An ATA request processing may also includes sending
includes sending of several events. If ATA request processing is finished of several events. If ATA request processing is finished the ATA request is
the ATA request is removed from the controller queue. Note, that in current removed from the controller queue. Note, that in current implementation maximum
implementation maximum one event per controller may be queued at any moment one event per controller may be queued at any moment of the time.
of the time.
(This part seems not very clear, hope I rewrite it soon) (This part seems not very clear, hope I rewrite it soon)
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.

View File

@ -1,5 +1,9 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Clock Driver Clock Driver
############ ############
@ -9,14 +13,16 @@ Introduction
The purpose of the clock driver is to provide two services for the operating The purpose of the clock driver is to provide two services for the operating
system. system.
- A steady time basis to the kernel, so that the RTEMS primitives that need - A steady time basis to the kernel, so that the RTEMS primitives that need a
a clock tick work properly. See the *Clock Manager* chapter of the*RTEMS Application C User's Guide* for more details. clock tick work properly. See the *Clock Manager* chapter of the *RTEMS
Application C User's Guide* for more details.
- An optional time counter to generate timestamps of the uptime and wall - An optional time counter to generate timestamps of the uptime and wall clock
clock time. time.
The clock driver is usually located in the :file:`clock` directory of the BSP. The clock driver is usually located in the :file:`clock` directory of the BSP.
Clock drivers should use the :dfn:`Clock Driver Shell` available via the:file:`clockdrv_shell.h` include file. Clock drivers should use the :dfn:`Clock Driver Shell` available via the
:file:`clockdrv_shell.h` include file.
Clock Driver Shell Clock Driver Shell
================== ==================
@ -29,12 +35,13 @@ then the clock driver is registered and should provide its services to the
operating system. A hardware specific clock driver must provide some operating system. A hardware specific clock driver must provide some
functions, defines and macros for the :dfn:`Clock Driver Shell` which are functions, defines and macros for the :dfn:`Clock Driver Shell` which are
explained here step by step. A clock driver file looks in general like this. explained here step by step. A clock driver file looks in general like this.
.. code:: c
.. code-block:: c
/* /*
* A section with functions, defines and macros to provide hardware specific * A section with functions, defines and macros to provide hardware specific
* functions for the Clock Driver Shell. * functions for the Clock Driver Shell.
\*/ */
#include "../../../shared/clockdrv_shell.h" #include "../../../shared/clockdrv_shell.h"
Initialization Initialization
@ -45,9 +52,9 @@ must be selected.
- The most basic clock driver provides only a periodic interrupt service - The most basic clock driver provides only a periodic interrupt service
routine which calls ``rtems_clock_tick()``. The interval is determined by routine which calls ``rtems_clock_tick()``. The interval is determined by
the application configuration via ``#define the application configuration via ``#define CONFIGURE_MICROSECONDS_PER_TICK``
CONFIGURE_MICROSECONDS_PER_TICK`` and can be obtained via``rtems_configuration_get_microseconds_per_tick()``. The timestamp and can be obtained via ``rtems_configuration_get_microseconds_per_tick()``.
resolution is limited to the clock tick interval. The timestamp resolution is limited to the clock tick interval.
- In case the hardware lacks support for a free running counter, then the - In case the hardware lacks support for a free running counter, then the
module used for the clock tick may provide support for timestamps with a module used for the clock tick may provide support for timestamps with a
@ -60,34 +67,42 @@ must be selected.
Clock Tick Only Variant Clock Tick Only Variant
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
.. code:: c .. code-block:: c
static void some_support_initialize_hardware( void ) static void some_support_initialize_hardware( void )
{ {
/* Initialize hardware \*/ /* Initialize hardware */
} }
#define Clock_driver_support_initialize_hardware() \\
#define Clock_driver_support_initialize_hardware() \
some_support_initialize_hardware() some_support_initialize_hardware()
/* Indicate that this clock driver lacks a proper timecounter in hardware \*/
/* Indicate that this clock driver lacks a proper timecounter in hardware */
#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER #define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
#include "../../../shared/clockdrv_shell.h" #include "../../../shared/clockdrv_shell.h"
Simple Timecounter Variant Simple Timecounter Variant
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: c .. code-block:: c
#include <rtems/timecounter.h> #include <rtems/timecounter.h>
static rtems_timecounter_simple some_tc; static rtems_timecounter_simple some_tc;
static uint32_t some_tc_get( rtems_timecounter_simple \*tc )
static uint32_t some_tc_get( rtems_timecounter_simple *tc )
{ {
return some.counter; return some.counter;
} }
static bool some_tc_is_pending( rtems_timecounter_simple \*tc )
static bool some_tc_is_pending( rtems_timecounter_simple *tc )
{ {
return some.is_pending; return some.is_pending;
} }
static uint32_t some_tc_get_timecount( struct timecounter \*tc )
static uint32_t some_tc_get_timecount( struct timecounter *tc )
{ {
return rtems_timecounter_simple_downcounter_get( return rtems_timecounter_simple_downcounter_get(
tc, tc,
@ -95,17 +110,20 @@ Simple Timecounter Variant
some_tc_is_pending some_tc_is_pending
); );
} }
static void some_tc_tick( void ) static void some_tc_tick( void )
{ {
rtems_timecounter_simple_downcounter_tick( &some_tc, some_tc_get ); rtems_timecounter_simple_downcounter_tick( &some_tc, some_tc_get );
} }
static void some_support_initialize_hardware( void ) static void some_support_initialize_hardware( void )
{ {
uint32_t frequency = 123456; uint32_t frequency = 123456;
uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
uint32_t timecounter_ticks_per_clock_tick = uint32_t timecounter_ticks_per_clock_tick =
( frequency * us_per_tick ) / 1000000; ( frequency * us_per_tick ) / 1000000;
/* Initialize hardware \*/
/* Initialize hardware */
rtems_timecounter_simple_install( rtems_timecounter_simple_install(
&some_tc, &some_tc,
frequency, frequency,
@ -113,10 +131,12 @@ Simple Timecounter Variant
some_tc_get_timecount some_tc_get_timecount
); );
} }
#define Clock_driver_support_initialize_hardware() \\
#define Clock_driver_support_initialize_hardware() \
some_support_initialize_hardware() some_support_initialize_hardware()
#define Clock_driver_timecounter_tick() \\ #define Clock_driver_timecounter_tick() \
some_tc_tick() some_tc_tick()
#include "../../../shared/clockdrv_shell.h" #include "../../../shared/clockdrv_shell.h"
Timecounter Variant Timecounter Variant
@ -126,42 +146,52 @@ This variant is preferred since it is the most efficient and yields the most
accurate timestamps. It is also mandatory on SMP configurations to obtain accurate timestamps. It is also mandatory on SMP configurations to obtain
valid timestamps. The hardware must provide a periodic interrupt to service valid timestamps. The hardware must provide a periodic interrupt to service
the clock tick and a free running counter for the timecounter. The free the clock tick and a free running counter for the timecounter. The free
running counter must have a power of two period. The ``tc_counter_mask`` running counter must have a power of two period. The ``tc_counter_mask`` must
must be initialized to the free running counter period minus one, e.g. for a be initialized to the free running counter period minus one, e.g. for a 32-bit
32-bit counter this is 0xffffffff. The ``tc_get_timecount`` function must counter this is 0xffffffff. The ``tc_get_timecount`` function must return the
return the current counter value (the counter values must increase, so if the current counter value (the counter values must increase, so if the counter
counter counts down, a conversion is necessary). Use``RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER`` for the ``tc_quality``. Set``tc_frequency`` to the frequency of the free running counter in Hz. All counts down, a conversion is necessary). Use
other fields of the ``struct timecounter`` must be zero initialized. ``RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER`` for the ``tc_quality``. Set
Install the initialized timecounter via ``rtems_timecounter_install()``. ``tc_frequency`` to the frequency of the free running counter in Hz. All other
.. code:: c fields of the ``struct timecounter`` must be zero initialized. Install the
initialized timecounter via ``rtems_timecounter_install()``.
.. code-block:: c
#include <rtems/timecounter.h> #include <rtems/timecounter.h>
static struct timecounter some_tc; static struct timecounter some_tc;
static uint32_t some_tc_get_timecount( struct timecounter \*tc )
static uint32_t some_tc_get_timecount( struct timecounter *tc )
{ {
some.free_running_counter; some.free_running_counter;
} }
static void some_support_initialize_hardware( void ) static void some_support_initialize_hardware( void )
{ {
uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
uint32_t frequency = 123456; uint32_t frequency = 123456;
/* /*
* The multiplication must be done in 64-bit arithmetic to avoid an integer * The multiplication must be done in 64-bit arithmetic to avoid an integer
* overflow on targets with a high enough counter frequency. * overflow on targets with a high enough counter frequency.
\*/ */
uint32_t interval = (uint32_t) ( ( frequency * us_per_tick ) / 1000000 ); uint32_t interval = (uint32_t) ( ( frequency * us_per_tick ) / 1000000 );
/* /*
* Initialize hardware and set up a periodic interrupt for the configuration * Initialize hardware and set up a periodic interrupt for the configuration
* based interval. * based interval.
\*/ */
some_tc.tc_get_timecount = some_tc_get_timecount; some_tc.tc_get_timecount = some_tc_get_timecount;
some_tc.tc_counter_mask = 0xffffffff; some_tc.tc_counter_mask = 0xffffffff;
some_tc.tc_frequency = frequency; some_tc.tc_frequency = frequency;
some_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; some_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
rtems_timecounter_install( &some_tc ); rtems_timecounter_install( &some_tc );
} }
#define Clock_driver_support_initialize_hardware() \\
#define Clock_driver_support_initialize_hardware() \
some_support_initialize_hardware() some_support_initialize_hardware()
#include "../../../shared/clockdrv_shell.h" #include "../../../shared/clockdrv_shell.h"
Install Clock Tick Interrupt Service Routine Install Clock Tick Interrupt Service Routine
@ -169,10 +199,12 @@ Install Clock Tick Interrupt Service Routine
The clock driver must provide a function to install the clock tick interrupt The clock driver must provide a function to install the clock tick interrupt
service routine via ``Clock_driver_support_install_isr()``. service routine via ``Clock_driver_support_install_isr()``.
.. code:: c
.. code-block:: c
#include <bsp/irq.h> #include <bsp/irq.h>
#include <bsp/fatal.h> #include <bsp/fatal.h>
static void some_support_install_isr( rtems_interrupt_handler isr ) static void some_support_install_isr( rtems_interrupt_handler isr )
{ {
rtems_status_code sc; rtems_status_code sc;
@ -187,39 +219,50 @@ service routine via ``Clock_driver_support_install_isr()``.
bsp_fatal( SOME_FATAL_IRQ_INSTALL ); bsp_fatal( SOME_FATAL_IRQ_INSTALL );
} }
} }
#define Clock_driver_support_install_isr( isr, old ) \\
#define Clock_driver_support_install_isr( isr, old ) \
some_support_install_isr( isr ) some_support_install_isr( isr )
#include "../../../shared/clockdrv_shell.h" #include "../../../shared/clockdrv_shell.h"
Support At Tick Support At Tick
--------------- ---------------
The hardware specific support at tick is specified by``Clock_driver_support_at_tick()``. The hardware specific support at tick is specified by
.. code:: c ``Clock_driver_support_at_tick()``.
.. code-block:: c
static void some_support_at_tick( void ) static void some_support_at_tick( void )
{ {
/* Clear interrupt \*/ /* Clear interrupt */
} }
#define Clock_driver_support_at_tick() \\
#define Clock_driver_support_at_tick() \
some_support_at_tick() some_support_at_tick()
#include "../../../shared/clockdrv_shell.h" #include "../../../shared/clockdrv_shell.h"
System Shutdown Support System Shutdown Support
----------------------- -----------------------
The :dfn:`Clock Driver Shell` provides the routine ``Clock_exit()`` that is The :dfn:`Clock Driver Shell` provides the routine ``Clock_exit()`` that is
scheduled to be run during system shutdown via the ``atexit()`` routine. scheduled to be run during system shutdown via the ``atexit()`` routine. The
The hardware specific shutdown support is specified by``Clock_driver_support_shutdown_hardware()`` which is used by``Clock_exit()``. It should disable the clock tick source if it was hardware specific shutdown support is specified by
enabled. This can be used to prevent clock ticks after the system is shutdown. ``Clock_driver_support_shutdown_hardware()`` which is used by ``Clock_exit()``.
.. code:: c It should disable the clock tick source if it was enabled. This can be used to
prevent clock ticks after the system is shutdown.
.. code-block:: c
static void some_support_shutdown_hardware( void ) static void some_support_shutdown_hardware( void )
{ {
/* Shutdown hardware \*/ /* Shutdown hardware */
} }
#define Clock_driver_support_shutdown_hardware() \\
#define Clock_driver_support_shutdown_hardware() \
some_support_shutdown_hardware() some_support_shutdown_hardware()
#include "../../../shared/clockdrv_shell.h" #include "../../../shared/clockdrv_shell.h"
Multiple Clock Driver Ticks Per Clock Tick Multiple Clock Driver Ticks Per Clock Tick
@ -228,14 +271,17 @@ Multiple Clock Driver Ticks Per Clock Tick
In case the hardware needs more than one clock driver tick per clock tick (e.g. In case the hardware needs more than one clock driver tick per clock tick (e.g.
due to a limited range of the hardware timer), then this can be specified with due to a limited range of the hardware timer), then this can be specified with
the optional ``#define CLOCK_DRIVER_ISRS_PER_TICK`` and ``#define the optional ``#define CLOCK_DRIVER_ISRS_PER_TICK`` and ``#define
CLOCK_DRIVER_ISRS_PER_TICK_VALUE`` defines. This is currently used only for x86 CLOCK_DRIVER_ISRS_PER_TICK_VALUE`` defines. This is currently used only for
and it hopefully remains that way. x86 and it hopefully remains that way.
.. code:: c
/* Enable multiple clock driver ticks per clock tick \*/ .. code-block:: c
/* Enable multiple clock driver ticks per clock tick */
#define CLOCK_DRIVER_ISRS_PER_TICK 1 #define CLOCK_DRIVER_ISRS_PER_TICK 1
/* Specifiy the clock driver ticks per clock tick value \*/
/* Specifiy the clock driver ticks per clock tick value */
#define CLOCK_DRIVER_ISRS_PER_TICK_VALUE 123 #define CLOCK_DRIVER_ISRS_PER_TICK_VALUE 123
#include "../../../shared/clockdrv_shell.h" #include "../../../shared/clockdrv_shell.h"
Clock Driver Ticks Counter Clock Driver Ticks Counter
@ -245,13 +291,7 @@ The :dfn:`Clock Driver Shell` provide a global variable that is simply a count
of the number of clock driver interrupt service routines that have occurred. of the number of clock driver interrupt service routines that have occurred.
This information is valuable when debugging a system. This variable is This information is valuable when debugging a system. This variable is
declared as follows: declared as follows:
.. code:: c
.. code-block:: c
volatile uint32_t Clock_driver_ticks; volatile uint32_t Clock_driver_ticks;
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.

View File

@ -3,10 +3,11 @@ sys.path.append(os.path.abspath('../common/'))
from conf import * from conf import *
version = '1.0' version = '4.11.0'
release = '5.0' release = '4.11.0'
project = "RTEMS BSP and Device Driver Development Guide"
latex_documents = [ latex_documents = [
('index', 'bsp_howto.tex', u'RTEMS BSP Howto Documentation', u'RTEMS Documentation Project', 'manual'), ('index', 'bsp_howto.tex', u'RTEMS BSP and Device Driver Development Guide', u'RTEMS Documentation Project', 'manual'),
] ]

View File

@ -1,51 +1,53 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Console Driver Console Driver
############## ##############
Introduction Introduction
============ ============
This chapter describes the operation of a console driver using This chapter describes the operation of a console driver using the RTEMS POSIX
the RTEMS POSIX Termios support. Traditionally RTEMS has referred Termios support. Traditionally RTEMS has referred to all serial device drivers
to all serial device drivers as console device drivers. A as console device drivers. A console driver can be used to do raw data
console driver can be used to do raw data processing in addition processing in addition to the "normal" standard input and output device
to the "normal" standard input and output device functions required functions required of a console.
of a console.
The serial driver may be called as the consequence of a C Library The serial driver may be called as the consequence of a C Library call such as
call such as ``printf`` or ``scanf`` or directly via the``read`` or ``write`` system calls. ``printf`` or ``scanf`` or directly via the``read`` or ``write`` system calls.
There are two main functioning modes: There are two main functioning modes:
- console: formatted input/output, with special characters (end of - console: formatted input/output, with special characters (end of line,
line, tabulations, etc.) recognition and processing, tabulations, etc.) recognition and processing,
- raw: permits raw data processing. - raw: permits raw data processing.
One may think that two serial drivers are needed to handle these two types One may think that two serial drivers are needed to handle these two types of
of data, but Termios permits having only one driver. data, but Termios permits having only one driver.
Termios Termios
======= =======
Termios is a standard for terminal management, included in the POSIX Termios is a standard for terminal management, included in the POSIX 1003.1b
1003.1b standard. As part of the POSIX and Open Group Single UNIX standard. As part of the POSIX and Open Group Single UNIX Specification, is
Specification, is commonly provided on UNIX implementations. The commonly provided on UNIX implementations. The Open Group has the termios
Open Group has the termios portion of the POSIX standard online portion of the POSIX standard online at
at http://opengroup.org/onlinepubs/007908775/xbd/termios.html. http://opengroup.org/onlinepubs/007908775/xbd/termios.html. The requirements
The requirements for the ``<termios.h>`` file are also provided for the ``<termios.h>`` file are also provided and are at
and are at http://opengroup.org/onlinepubs/007908775/xsh/termios.h.html. http://opengroup.org/onlinepubs/007908775/xsh/termios.h.html.
Having RTEMS support for Termios is beneficial because: Having RTEMS support for Termios is beneficial because:
- from the user's side because it provides standard primitive operations - from the user's side because it provides standard primitive operations to
to access the terminal and change configuration settings. These operations access the terminal and change configuration settings. These operations are
are the same under UNIX and RTEMS. the same under UNIX and RTEMS.
- from the BSP developer's side because it frees the - from the BSP developer's side because it frees the developer from dealing
developer from dealing with buffer states and mutual exclusions on them. with buffer states and mutual exclusions on them. Early RTEMS console device
Early RTEMS console device drivers also did their own special drivers also did their own special character processing.
character processing.
- it is part of an internationally recognized standard. - it is part of an internationally recognized standard.
@ -55,13 +57,11 @@ Termios support includes:
- raw and console handling, - raw and console handling,
- blocking or non-blocking characters receive, with or without - blocking or non-blocking characters receive, with or without Timeout.
Timeout.
At this time, RTEMS documentation does not include a thorough discussion At this time, RTEMS documentation does not include a thorough discussion of the
of the Termios functionality. For more information on Termios, Termios functionality. For more information on Termios, type ``man termios``
type ``man termios`` on a Unix box or point a web browser on a Unix box or point a web browser athttp://www.freebsd.org/cgi/man.cgi.
athttp://www.freebsd.org/cgi/man.cgi.
Driver Functioning Modes Driver Functioning Modes
======================== ========================
@ -75,37 +75,34 @@ Asynchronous Receiver-Transmitter, i.e. the serial chip):
- task driven mode - task driven mode
In polled mode, the processor blocks on sending/receiving characters. In polled mode, the processor blocks on sending/receiving characters. This
This mode is not the most efficient way to utilize the UART. But mode is not the most efficient way to utilize the UART. But polled mode is
polled mode is usually necessary when one wants to print an usually necessary when one wants to print an error message in the event of a
error message in the event of a fatal error such as a fatal error fatal error such as a fatal error in the BSP. This is also the simplest mode
in the BSP. This is also the simplest mode to to program. Polled mode is generally preferred if the serial port is to be
program. Polled mode is generally preferred if the serial port is used primarily as a debug console. In a simple polled driver, the software
to be used primarily as a debug console. In a simple polled driver, will continuously check the status of the UART when it is reading or writing to
the software will continuously check the status of the UART when the UART. Termios improves on this by delaying the caller for 1 clock tick
it is reading or writing to the UART. Termios improves on this between successive checks of the UART on a read operation.
by delaying the caller for 1 clock tick between successive checks
of the UART on a read operation.
In interrupt driven mode, the processor does not block on sending/receiving In interrupt driven mode, the processor does not block on sending/receiving
characters. Data is buffered between the interrupt service routine characters. Data is buffered between the interrupt service routine and
and application code. Two buffers are used to insulate the application application code. Two buffers are used to insulate the application from the
from the relative slowness of the serial device. One of the buffers is relative slowness of the serial device. One of the buffers is used for
used for incoming characters, while the other is used for outgoing characters. incoming characters, while the other is used for outgoing characters.
An interrupt is raised when a character is received by the UART. An interrupt is raised when a character is received by the UART. The interrupt
The interrupt subroutine places the incoming character at the end subroutine places the incoming character at the end of the input buffer. When
of the input buffer. When an application asks for input, an application asks for input, the characters at the front of the buffer are
the characters at the front of the buffer are returned. returned.
When the application prints to the serial device, the outgoing characters When the application prints to the serial device, the outgoing characters are
are placed at the end of the output buffer. The driver will place placed at the end of the output buffer. The driver will place one or more
one or more characters in the UART (the exact number depends on the UART) characters in the UART (the exact number depends on the UART) An interrupt will
An interrupt will be raised when all the characters have been transmitted. be raised when all the characters have been transmitted. The interrupt service
The interrupt service routine has to send the characters routine has to send the characters remaining in the output buffer the same way.
remaining in the output buffer the same way. When the transmitting side When the transmitting side of the UART is idle, it is typically necessary to
of the UART is idle, it is typically necessary to prime the transmitter prime the transmitter before the first interrupt will occur.
before the first interrupt will occur.
The task driven mode is similar to interrupt driven mode, but the actual data The task driven mode is similar to interrupt driven mode, but the actual data
processing is done in dedicated tasks instead of interrupt routines. processing is done in dedicated tasks instead of interrupt routines.
@ -113,16 +110,17 @@ processing is done in dedicated tasks instead of interrupt routines.
Serial Driver Functioning Overview Serial Driver Functioning Overview
================================== ==================================
The following Figure shows how a Termios driven serial driver works: The following Figure shows how a Termios driven serial driver works: Figure not
Figure not included in ASCII version included in ASCII version
The following list describes the basic flow. The following list describes the basic flow.
- the application programmer uses standard C library call (printf, - the application programmer uses standard C library call (printf, scanf, read,
scanf, read, write, etc.), write, etc.),
- C library (ctx.g. RedHat (formerly Cygnus) Newlib) calls - C library (ctx.g. RedHat (formerly Cygnus) Newlib) calls the RTEMS system
the RTEMS system call interface. This code can be found in the:file:`cpukit/libcsupport/src` directory. call interface. This code can be found in the:file:`cpukit/libcsupport/src`
directory.
- Glue code calls the serial driver entry routines. - Glue code calls the serial driver entry routines.
@ -133,31 +131,30 @@ The low-level driver API changed between RTEMS 4.10 and RTEMS 4.11. The legacy
callback API is still supported, but its use is discouraged. The following callback API is still supported, but its use is discouraged. The following
functions are deprecated: functions are deprecated:
- ``rtems_termios_open()`` - use ``rtems_termios_device_open()`` in - ``rtems_termios_open()`` - use ``rtems_termios_device_open()`` in combination
combination with ``rtems_termios_device_install()`` instead. with ``rtems_termios_device_install()`` instead.
- ``rtems_termios_close()`` - use ``rtems_termios_device_close()`` - ``rtems_termios_close()`` - use ``rtems_termios_device_close()`` instead.
instead.
This manual describes the new API. A new console driver should consist of This manual describes the new API. A new console driver should consist of
three parts. three parts.
# The basic console driver functions using the Termios support. Add this - The basic console driver functions using the Termios support. Add this the
the BSPs Makefile.am: BSPs Makefile.am:
.. code:: c .. code-block:: makefile
[...] [...]
libbsp_a_SOURCES += ../../shared/console-termios.c libbsp_a_SOURCES += ../../shared/console-termios.c
\[...] [...]
# A general serial module specific low-level driver providing the handler - A general serial module specific low-level driver providing the handler table
table for the Termios ``rtems_termios_device_install()`` function. This for the Termios ``rtems_termios_device_install()`` function. This low-level
low-level driver could be used for more than one BSP. driver could be used for more than one BSP.
# A BSP specific initialization routine ``console_initialize()``, that - A BSP specific initialization routine ``console_initialize()``, that calls
calls ``rtems_termios_device_install()`` providing a low-level driver ``rtems_termios_device_install()`` providing a low-level driver context for
context for each installed device. each installed device.
You need to provide a device handler structure for the Termios device You need to provide a device handler structure for the Termios device
interface. The functions are described later in this chapter. The first open interface. The functions are described later in this chapter. The first open
@ -167,9 +164,11 @@ case one is available or minus one otherwise.
If you want to use polled IO it should look like the following. Termios must If you want to use polled IO it should look like the following. Termios must
be told the addresses of the handler that are to be used for simple character be told the addresses of the handler that are to be used for simple character
IO, i.e. pointers to the ``my_driver_poll_read()`` and``my_driver_poll_write()`` functions described later in `Termios and Polled IO`_. IO, i.e. pointers to the ``my_driver_poll_read()`` and
``my_driver_poll_write()`` functions described later in `Termios and Polled
IO`_.
.. code:: c .. code-block:: c
const rtems_termios_handler my_driver_handler_polled = { const rtems_termios_handler my_driver_handler_polled = {
.first_open = my_driver_first_open, .first_open = my_driver_first_open,
@ -187,9 +186,10 @@ functioning is quite different in this mode. There is no device driver read
handler to be passed to Termios. Indeed a ``console_read()`` call returns the handler to be passed to Termios. Indeed a ``console_read()`` call returns the
contents of Termios input buffer. This buffer is filled in the driver contents of Termios input buffer. This buffer is filled in the driver
interrupt subroutine, see also `Termios and Interrupt Driven IO`_. The driver interrupt subroutine, see also `Termios and Interrupt Driven IO`_. The driver
is responsible for providing a pointer to the``my_driver_interrupt_write()`` function. is responsible for providing a pointer to the``my_driver_interrupt_write()``
function.
.. code:: c .. code-block:: c
const rtems_termios_handler my_driver_handler_interrupt = { const rtems_termios_handler my_driver_handler_interrupt = {
.first_open = my_driver_first_open, .first_open = my_driver_first_open,
@ -203,19 +203,23 @@ is responsible for providing a pointer to the``my_driver_interrupt_write()`` fun
.mode = TERMIOS_IRQ_DRIVEN .mode = TERMIOS_IRQ_DRIVEN
}; };
You can also provide hander for remote transmission control. This You can also provide hander for remote transmission control. This is not
is not covered in this manual, so they are set to ``NULL`` in the above covered in this manual, so they are set to ``NULL`` in the above examples.
examples.
The low-level driver should provide a data structure for its device context. The low-level driver should provide a data structure for its device context.
The initialization routine must provide a context for each installed device via``rtems_termios_device_install()``. For simplicity of the console The initialization routine must provide a context for each installed device via
initialization example the device name is also present. Her is an example header file. ``rtems_termios_device_install()``. For simplicity of the console
.. code:: c initialization example the device name is also present. Here is an example
header file.
.. code-block:: c
#ifndef MY_DRIVER_H #ifndef MY_DRIVER_H
#define MY_DRIVER_H #define MY_DRIVER_H
#include <rtems/termiostypes.h> #include <rtems/termiostypes.h>
#include <some-chip-header.h> #include <some-chip-header.h>
/* Low-level driver specific data structure \*/ /* Low-level driver specific data structure \*/
typedef struct { typedef struct {
rtems_termios_device_context base; rtems_termios_device_context base;
@ -223,10 +227,11 @@ initialization example the device name is also present. Her is an example heade
volatile module_register_block \*regs; volatile module_register_block \*regs;
/* More stuff \*/ /* More stuff \*/
} my_driver_context; } my_driver_context;
extern const rtems_termios_handler my_driver_handler_polled; extern const rtems_termios_handler my_driver_handler_polled;
extern const rtems_termios_handler my_driver_handler_interrupt; extern const rtems_termios_handler my_driver_handler_interrupt;
#endif /* MY_DRIVER_H \*/
#endif /* MY_DRIVER_H \*/
Termios and Polled IO Termios and Polled IO
--------------------- ---------------------
@ -236,17 +241,18 @@ Termios for simple character IO.
The ``my_driver_poll_write()`` routine is responsible for writing ``n`` The ``my_driver_poll_write()`` routine is responsible for writing ``n``
characters from ``buf`` to the serial device specified by ``tty``. characters from ``buf`` to the serial device specified by ``tty``.
.. code:: c
.. code-block:: c
static void my_driver_poll_write( static void my_driver_poll_write(
rtems_termios_device_context \*base, rtems_termios_device_context *base,
const char \*buf, const char *buf,
size_t n size_t n
) )
{ {
my_driver_context \*ctx = (my_driver_context \*) base; my_driver_context *ctx = (my_driver_context *) base;
size_t i; size_t i;
/* Write \*/ /* Write */
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
my_driver_write_char(ctx, buf[i]); my_driver_write_char(ctx, buf[i]);
} }
@ -255,17 +261,18 @@ characters from ``buf`` to the serial device specified by ``tty``.
The ``my_driver_poll_read`` routine is responsible for reading a single The ``my_driver_poll_read`` routine is responsible for reading a single
character from the serial device specified by ``tty``. If no character is character from the serial device specified by ``tty``. If no character is
available, then the routine should return minus one. available, then the routine should return minus one.
.. code:: c
static int my_driver_poll_read(rtems_termios_device_context \*base) .. code-block:: c
static int my_driver_poll_read(rtems_termios_device_context *base)
{ {
my_driver_context \*ctx = (my_driver_context \*) base; my_driver_context *ctx = (my_driver_context *) base;
/* Check if a character is available \*/ /* Check if a character is available */
if (my_driver_can_read_char(ctx)) { if (my_driver_can_read_char(ctx)) {
/* Return the character \*/ /* Return the character */
return my_driver_read_char(ctx); return my_driver_read_char(ctx);
} else { } else {
/* Return an error status \*/ /* Return an error status */
return -1; return -1;
} }
} }
@ -285,65 +292,70 @@ transmitter is ready for another character.
In the simplest case, the ``my_driver_interrupt_handler()`` will have to check In the simplest case, the ``my_driver_interrupt_handler()`` will have to check
the status of the UART and determine what caused the interrupt. The following the status of the UART and determine what caused the interrupt. The following
describes the operation of an ``my_driver_interrupt_handler`` which has to describes the operation of an ``my_driver_interrupt_handler`` which has to do
do this: this:
.. code:: c
.. code-block:: c
static void my_driver_interrupt_handler( static void my_driver_interrupt_handler(
rtems_vector_number vector, rtems_vector_number vector,
void \*arg void *arg
) )
{ {
rtems_termios_tty \*tty = arg; rtems_termios_tty *tty = arg;
my_driver_context \*ctx = rtems_termios_get_device_context(tty); my_driver_context *ctx = rtems_termios_get_device_context(tty);
char buf[N]; char buf[N];
size_t n; size_t n;
/* /*
* Check if we have received something. The function reads the * Check if we have received something. The function reads the
* received characters from the device and stores them in the * received characters from the device and stores them in the
* buffer. It returns the number of read characters. * buffer. It returns the number of read characters.
\*/ */
n = my_driver_read_received_chars(ctx, buf, N); n = my_driver_read_received_chars(ctx, buf, N);
if (n > 0) { if (n > 0) {
/* Hand the data over to the Termios infrastructure \*/ /* Hand the data over to the Termios infrastructure */
rtems_termios_enqueue_raw_characters(tty, buf, n); rtems_termios_enqueue_raw_characters(tty, buf, n);
} }
/* /*
* Check if we have something transmitted. The functions returns * Check if we have something transmitted. The functions returns
* the number of transmitted characters since the last write to the * the number of transmitted characters since the last write to the
* device. * device.
\*/ */
n = my_driver_transmitted_chars(ctx); n = my_driver_transmitted_chars(ctx);
if (n > 0) { if (n > 0) {
/* /*
* Notify Termios that we have transmitted some characters. It * Notify Termios that we have transmitted some characters. It
* will call now the interrupt write function if more characters * will call now the interrupt write function if more characters
* are ready for transmission. * are ready for transmission.
\*/ */
rtems_termios_dequeue_characters(tty, n); rtems_termios_dequeue_characters(tty, n);
} }
} }
The ``my_driver_interrupt_write()`` function is responsible for telling the The ``my_driver_interrupt_write()`` function is responsible for telling the
device that the ``n`` characters at ``buf`` are to be transmitted. It device that the ``n`` characters at ``buf`` are to be transmitted. It the
the value ``n`` is zero to indicate that no more characters are to send. value ``n`` is zero to indicate that no more characters are to send. The
The driver can disable the transmit interrupts now. This routine is invoked driver can disable the transmit interrupts now. This routine is invoked either
either from task context with disabled interrupts to start a new transmission from task context with disabled interrupts to start a new transmission process
process with exactly one character in case of an idle output state or from the with exactly one character in case of an idle output state or from the
interrupt handler to refill the transmitter. If the routine is invoked to interrupt handler to refill the transmitter. If the routine is invoked to
start the transmit process the output state will become busy and Termios starts start the transmit process the output state will become busy and Termios starts
to fill the output buffer. If the transmit interrupt arises before Termios was to fill the output buffer. If the transmit interrupt arises before Termios was
able to fill the transmit buffer you will end up with one interrupt per able to fill the transmit buffer you will end up with one interrupt per
character. character.
.. code:: c
.. code-block:: c
static void my_driver_interrupt_write( static void my_driver_interrupt_write(
rtems_termios_device_context \*base, rtems_termios_device_context *base,
const char \*buf, const char *buf,
size_t n size_t n
) )
{ {
my_driver_context \*ctx = (my_driver_context \*) base; my_driver_context *ctx = (my_driver_context *) base;
/* /*
* Tell the device to transmit some characters from buf (less than * Tell the device to transmit some characters from buf (less than
* or equal to n). When the device is finished it should raise an * or equal to n). When the device is finished it should raise an
@ -351,12 +363,12 @@ character.
* characters have been transmitted and this may trigger this write * characters have been transmitted and this may trigger this write
* function again. You may have to store the number of outstanding * function again. You may have to store the number of outstanding
* characters in the device data structure. * characters in the device data structure.
\*/ */
/* /*
* Termios will set n to zero to indicate that the transmitter is * Termios will set n to zero to indicate that the transmitter is
* now inactive. The output buffer is empty in this case. The * now inactive. The output buffer is empty in this case. The
* driver may disable the transmit interrupts now. * driver may disable the transmit interrupts now.
\*/ */
} }
Initialization Initialization
@ -366,44 +378,50 @@ The BSP specific driver initialization is called once during the RTEMS
initialization process. initialization process.
The ``console_initialize()`` function may look like this: The ``console_initialize()`` function may look like this:
.. code:: c
.. code-block:: c
#include <my-driver.h> #include <my-driver.h>
#include <rtems/console.h> #include <rtems/console.h>
#include <bsp.h> #include <bsp.h>
#include <bsp/fatal.h> #include <bsp/fatal.h>
static my_driver_context driver_context_table[M] = { /* Some values \*/ };
static my_driver_context driver_context_table[M] = { /* Some values */ };
rtems_device_driver console_initialize( rtems_device_driver console_initialize(
rtems_device_major_number major, rtems_device_major_number major,
rtems_device_minor_number minor, rtems_device_minor_number minor,
void \*arg void *arg
) )
{ {
rtems_status_code sc; rtems_status_code sc;
#ifdef SOME_BSP_USE_INTERRUPTS #ifdef SOME_BSP_USE_INTERRUPTS
const rtems_termios_handler \*handler = &my_driver_handler_interrupt; const rtems_termios_handler *handler = &my_driver_handler_interrupt;
#else #else
const rtems_termios_handler \*handler = &my_driver_handler_polled; const rtems_termios_handler *handler = &my_driver_handler_polled;
#endif #endif
/* /*
* Initialize the Termios infrastructure. If Termios has already * Initialize the Termios infrastructure. If Termios has already
* been initialized by another device driver, then this call will * been initialized by another device driver, then this call will
* have no effect. * have no effect.
\*/ */
rtems_termios_initialize(); rtems_termios_initialize();
/* Initialize each device \*/
/* Initialize each device */
for ( for (
minor = 0; minor = 0;
minor < RTEMS_ARRAY_SIZE(driver_context_table); minor < RTEMS_ARRAY_SIZE(driver_context_table);
++minor ++minor
) { ) {
my_driver_context \*ctx = &driver_context_table[minor]; my_driver_context *ctx = &driver_context_table[minor];
/* /*
* Install this device in the file system and Termios. In order * Install this device in the file system and Termios. In order
* to use the console (i.e. being able to do printf, scanf etc. * to use the console (i.e. being able to do printf, scanf etc.
* on stdin, stdout and stderr), one device must be registered as * on stdin, stdout and stderr), one device must be registered as
* "/dev/console" (CONSOLE_DEVICE_NAME). * "/dev/console" (CONSOLE_DEVICE_NAME).
\*/ */
sc = rtems_termios_device_install( sc = rtems_termios_device_install(
ctx->device_name, ctx->device_name,
major, major,
@ -416,58 +434,68 @@ The ``console_initialize()`` function may look like this:
bsp_fatal(SOME_BSP_FATAL_CONSOLE_DEVICE_INSTALL); bsp_fatal(SOME_BSP_FATAL_CONSOLE_DEVICE_INSTALL);
} }
} }
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} }
Opening a serial device Opening a serial device
----------------------- -----------------------
The ``console_open()`` function provided by :file:`console-termios.c` is The ``console_open()`` function provided by :file:`console-termios.c` is called
called whenever a serial device is opened. The device registered as``"/dev/console"`` (``CONSOLE_DEVICE_NAME``) is opened automatically whenever a serial device is opened. The device registered as
during RTEMS initialization. For instance, if UART channel 2 is registered as``"/dev/tty1"``, the ``console_open()`` entry point will be called as the ``"/dev/console"`` (``CONSOLE_DEVICE_NAME``) is opened automatically during
RTEMS initialization. For instance, if UART channel 2 is registered as
``"/dev/tty1"``, the ``console_open()`` entry point will be called as the
result of an ``fopen("/dev/tty1", mode)`` in the application. result of an ``fopen("/dev/tty1", mode)`` in the application.
During the first open of the device Termios will call the``my_driver_first_open()`` handler. During the first open of the device Termios will call the
.. code:: c ``my_driver_first_open()`` handler.
.. code-block:: c
static bool my_driver_first_open( static bool my_driver_first_open(
rtems_termios_tty \*tty, rtems_termios_tty *tty,
rtems_termios_device_context \*base, rtems_termios_device_context *base,
struct termios \*term, struct termios *term,
rtems_libio_open_close_args_t \*args rtems_libio_open_close_args_t *args
) )
{ {
my_driver_context \*ctx = (my_driver_context \*) base; my_driver_context *ctx = (my_driver_context *) base;
rtems_status_code sc; rtems_status_code sc;
bool ok; bool ok;
/* /*
* You may add some initialization code here. * You may add some initialization code here.
\*/ */
/* /*
* Sets the initial baud rate. This should be set to the value of * Sets the initial baud rate. This should be set to the value of
* the boot loader. This function accepts only exact Termios baud * the boot loader. This function accepts only exact Termios baud
* values. * values.
\*/ */
sc = rtems_termios_set_initial_baud(tty, MY_DRIVER_BAUD_RATE); sc = rtems_termios_set_initial_baud(tty, MY_DRIVER_BAUD_RATE);
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
/* Not a valid Termios baud \*/ /* Not a valid Termios baud */
} }
/* /*
* Alternatively you can set the best baud. * Alternatively you can set the best baud.
\*/ */
rtems_termios_set_best_baud(term, MY_DRIVER_BAUD_RATE); rtems_termios_set_best_baud(term, MY_DRIVER_BAUD_RATE);
/* /*
* To propagate the initial Termios attributes to the device use * To propagate the initial Termios attributes to the device use
* this. * this.
\*/ */
ok = my_driver_set_attributes(base, term); ok = my_driver_set_attributes(base, term);
if (!ok) { if (!ok) {
/* This is bad \*/ /* This is bad */
} }
/* /*
* Return true to indicate a successful set attributes, and false * Return true to indicate a successful set attributes, and false
* otherwise. * otherwise.
\*/ */
return true; return true;
} }
@ -480,18 +508,20 @@ driver close entry point.
Termios will call the ``my_driver_last_close()`` handler if the last close Termios will call the ``my_driver_last_close()`` handler if the last close
happens on the device. happens on the device.
.. code:: c
.. code-block:: c
static void my_driver_last_close( static void my_driver_last_close(
rtems_termios_tty \*tty, rtems_termios_tty *tty,
rtems_termios_device_context \*base, rtems_termios_device_context *base,
rtems_libio_open_close_args_t \*args rtems_libio_open_close_args_t *args
) )
{ {
my_driver_context \*ctx = (my_driver_context \*) base; my_driver_context *ctx = (my_driver_context *) base;
/* /*
* The driver may do some cleanup here. * The driver may do some cleanup here.
\*/ */
} }
Reading Characters from a Serial Device Reading Characters from a Serial Device
@ -511,44 +541,39 @@ device driver write entry point.
Changing Serial Line Parameters Changing Serial Line Parameters
------------------------------- -------------------------------
The ``console_control()`` provided by :file:`console-termios.c` is invoked The ``console_control()`` provided by :file:`console-termios.c` is invoked when
when the line parameters for a particular serial device are to be changed. the line parameters for a particular serial device are to be changed. This
This entry point corresponds to the device driver IO control entry point. entry point corresponds to the device driver IO control entry point.
The application writer is able to control the serial line configuration with The application writer is able to control the serial line configuration with
Termios calls (such as the ``ioctl()`` command, see the Termios Termios calls (such as the ``ioctl()`` command, see the Termios documentation
documentation for more details). If the driver is to support dynamic for more details). If the driver is to support dynamic configuration, then it
configuration, then it must have the ``console_control()`` piece of code. must have the ``console_control()`` piece of code. Basically ``ioctl()``
Basically ``ioctl()`` commands call ``console_control()`` with the serial commands call ``console_control()`` with the serial line configuration in a
line configuration in a Termios defined data structure. Termios defined data structure.
The driver is responsible for reinitializing the device with the correct The driver is responsible for reinitializing the device with the correct
settings. For this purpose Termios calls the ``my_driver_set_attributes()`` settings. For this purpose Termios calls the ``my_driver_set_attributes()``
handler. handler.
.. code:: c
.. code-block:: c
static bool my_driver_set_attributes( static bool my_driver_set_attributes(
rtems_termios_device_context \*base, rtems_termios_device_context *base,
const struct termios \*term const struct termios *term
) )
{ {
my_driver_context \*ctx = (my_driver_context \*) base; my_driver_context *ctx = (my_driver_context *) base;
/* /*
* Inspect the termios data structure and configure the device * Inspect the termios data structure and configure the device
* appropriately. The driver should only be concerned with the * appropriately. The driver should only be concerned with the
* parts of the structure that specify hardware setting for the * parts of the structure that specify hardware setting for the
* communications channel such as baud, character size, etc. * communications channel such as baud, character size, etc.
\*/ */
/* /*
* Return true to indicate a successful set attributes, and false * Return true to indicate a successful set attributes, and false
* otherwise. * otherwise.
\*/ */
return true; return true;
} }
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.

View File

@ -3,9 +3,8 @@
Discrete Driver Discrete Driver
############### ###############
The Discrete driver is responsible for providing an The Discrete driver is responsible for providing an interface to Discrete
interface to Discrete Input/Outputs. The capabilities provided Input/Outputs. The capabilities provided by this class of device driver are:
by this class of device driver are:
- Initialize a Discrete I/O Board - Initialize a Discrete I/O Board
@ -21,76 +20,73 @@ by this class of device driver are:
- Reinitialize DACS - Reinitialize DACS
Most discrete I/O devices are found on I/O cards that support many Most discrete I/O devices are found on I/O cards that support many bits of
bits of discrete I/O on a single card. This driver model is centered discrete I/O on a single card. This driver model is centered on the notion of
on the notion of reading bitfields from the card. reading bitfields from the card.
There are currently no discrete I/O device drivers included in the There are currently no discrete I/O device drivers included in the RTEMS source
RTEMS source tree. The information provided in this chapter tree. The information provided in this chapter is based on drivers developed
is based on drivers developed for applications using RTEMS. for applications using RTEMS. It is hoped that this driver model information
It is hoped that this driver model information can form the can form the discrete I/O driver model that can be supported in future RTEMS
discrete I/O driver model that can be supported in future RTEMS
distribution. distribution.
Major and Minor Numbers Major and Minor Numbers
======================= =======================
The *major* number of a device driver is its index in the The ``major`` number of a device driver is its index in the RTEMS Device
RTEMS Device Address Table. Address Table.
A *minor* number is associated with each device instance A ``minor`` number is associated with each device instance managed by a
managed by a particular device driver. An RTEMS minor number particular device driver. An RTEMS minor number is an ``unsigned32`` entity.
is an ``unsigned32`` entity. Convention calls for Convention calls for dividing the bits in the minor number down into categories
dividing the bits in the minor number down into categories that specify a particular bitfield. This results in categories like the
that specify a particular bitfield. This results in categories following:
like the following:
- *board* - indicates the board a particular bitfield is located on - ``board`` - indicates the board a particular bitfield is located on
- *word* - indicates the particular word of discrete bits the - ``word`` - indicates the particular word of discrete bits the bitfield is
bitfield is located within located within
- *start* - indicates the starting bit of the bitfield - ``start`` - indicates the starting bit of the bitfield
- *width* - indicates the width of the bitfield - ``width`` - indicates the width of the bitfield
From the above, it should be clear that a single device driver From the above, it should be clear that a single device driver can support
can support multiple copies of the same board in a single system. multiple copies of the same board in a single system. The minor number is used
The minor number is used to distinguish the devices. to distinguish the devices.
By providing a way to easily access a particular bitfield from By providing a way to easily access a particular bitfield from the device
the device driver, the application is insulated with knowing how driver, the application is insulated with knowing how to mask fields in and out
to mask fields in and out of a discrete I/O. of a discrete I/O.
Discrete I/O Driver Configuration Discrete I/O Driver Configuration
================================= =================================
There is not a standard discrete I/O driver configuration table but some There is not a standard discrete I/O driver configuration table but some fields
fields are common across different drivers. The discrete I/O driver are common across different drivers. The discrete I/O driver configuration
configuration table is typically an array of structures with each table is typically an array of structures with each structure containing the
structure containing the information for a particular board. information for a particular board. The following is a list of the type of
The following is a list of the type of information normally required information normally required to configure an discrete I/O board:
to configure an discrete I/O board:
*board_offset* ``board_offset``
is the base address of a board. is the base address of a board.
*relay_initial_values* ``relay_initial_values``
is an array of the values that should be written to each output is an array of the values that should be written to each output word on the
word on the board during initialization. This allows the driver board during initialization. This allows the driver to start with the
to start with the board's output in a known state. board's output in a known state.
Initialize a Discrete I/O Board Initialize a Discrete I/O Board
=============================== ===============================
At system initialization, the discrete I/O driver's initialization entry point At system initialization, the discrete I/O driver's initialization entry point
will be invoked. As part of initialization, the driver will perform will be invoked. As part of initialization, the driver will perform whatever
whatever board initializatin is required and then set all board initializatin is required and then set all outputs to their configured
outputs to their configured initial state. initial state.
The discrete I/O driver may register a device name for bitfields of The discrete I/O driver may register a device name for bitfields of particular
particular interest to the system. Normally this will be restricted interest to the system. Normally this will be restricted to the names of each
to the names of each word and, if the driver supports it, an "all words". word and, if the driver supports it, an "all words".
Open a Particular Discrete Bitfield Open a Particular Discrete Bitfield
=================================== ===================================
@ -99,8 +95,8 @@ This is the driver open call. Usually this call does nothing other than
validate the minor number. validate the minor number.
With some drivers, it may be necessary to allocate memory when a particular With some drivers, it may be necessary to allocate memory when a particular
device is opened. If that is the case, then this is often the place device is opened. If that is the case, then this is often the place to do this
to do this operation. operation.
Close a Particular Discrete Bitfield Close a Particular Discrete Bitfield
==================================== ====================================
@ -108,82 +104,87 @@ Close a Particular Discrete Bitfield
This is the driver close call. Usually this call does nothing. This is the driver close call. Usually this call does nothing.
With some drivers, it may be necessary to allocate memory when a particular With some drivers, it may be necessary to allocate memory when a particular
device is opened. If that is the case, then this is the place device is opened. If that is the case, then this is the place where that
where that memory should be deallocated. memory should be deallocated.
Read from a Particular Discrete Bitfield Read from a Particular Discrete Bitfield
======================================== ========================================
This corresponds to the driver read call. After validating the minor This corresponds to the driver read call. After validating the minor number
number and arguments, this call reads the indicated bitfield. A and arguments, this call reads the indicated bitfield. A discrete I/O devices
discrete I/O devices may have to store the last value written to may have to store the last value written to a discrete output. If the bitfield
a discrete output. If the bitfield is output only, saving the last is output only, saving the last written value gives the appearance that it can
written value gives the appearance that it can be read from also. be read from also. If the bitfield is input, then it is sampled.
If the bitfield is input, then it is sampled.
*NOTE:* Many discrete inputs have a tendency to bounce. The application .. note::
may have to take account for bounces.
The value returned is an ``unsigned32`` number Many discrete inputs have a tendency to bounce. The application may have to
representing the bitfield read. This value is stored in the``argument_block`` passed in to the call. take account for bounces.
*NOTE:* Some discrete I/O drivers have a special minor number The value returned is an ``unsigned32`` number representing the bitfield read.
used to access all discrete I/O bits on the board. If this special This value is stored in the ``argument_block`` passed in to the call.
minor is used, then the area pointed to by ``argument_block`` must
be the correct size. .. note::
Some discrete I/O drivers have a special minor number used to access all
discrete I/O bits on the board. If this special minor is used, then the
area pointed to by ``argument_block`` must be the correct size.
Write to a Particular Discrete Bitfield Write to a Particular Discrete Bitfield
======================================= =======================================
This corresponds to the driver write call. After validating the minor This corresponds to the driver write call. After validating the minor number
number and arguments, this call writes the indicated device. If the and arguments, this call writes the indicated device. If the specified device
specified device is an ADC, then an error is usually returned. is an ADC, then an error is usually returned.
The value written is an ``unsigned32`` number The value written is an ``unsigned32`` number representing the value to be
representing the value to be written to the specified written to the specified bitfield. This value is stored in the
bitfield. This value is stored in the``argument_block`` passed in to the call. ``argument_block`` passed in to the call.
*NOTE:* Some discrete I/O drivers have a special minor number .. note::
used to access all discrete I/O bits on the board. If this special
minor is used, then the area pointed to by ``argument_block`` must Some discrete I/O drivers have a special minor number used to access all
be the correct size. discrete I/O bits on the board. If this special minor is used, then the
area pointed to by ``argument_block`` must be the correct size.
Disable Discrete Outputs Disable Discrete Outputs
======================== ========================
This is one of the IOCTL functions supported by the I/O control This is one of the IOCTL functions supported by the I/O control device driver
device driver entry point. When this IOCTL function is invoked, entry point. When this IOCTL function is invoked, the discrete outputs are
the discrete outputs are disabled. disabled.
*NOTE:* It may not be possible to disable/enable discrete output on all .. note::
discrete I/O boards.
It may not be possible to disable/enable discrete output on all discrete I/O
boards.
Enable Discrete Outputs Enable Discrete Outputs
======================= =======================
This is one of the IOCTL functions supported by the I/O control This is one of the IOCTL functions supported by the I/O control device driver
device driver entry point. When this IOCTL function is invoked, entry point. When this IOCTL function is invoked, the discrete outputs are
the discrete outputs are enabled. enabled.
*NOTE:* It may not be possible to disable/enable discrete output on all .. note::
discrete I/O boards.
It may not be possible to disable/enable discrete output on all discrete
I/O boards.
Reinitialize Outputs Reinitialize Outputs
==================== ====================
This is one of the IOCTL functions supported by the I/O control This is one of the IOCTL functions supported by the I/O control device driver
device driver entry point. When this IOCTL function is invoked, entry point. When this IOCTL function is invoked, the discrete outputs are
the discrete outputs are rewritten with the configured initial rewritten with the configured initial output values.
output values.
Get Last Written Values Get Last Written Values
======================= =======================
This is one of the IOCTL functions supported by the I/O control This is one of the IOCTL functions supported by the I/O control device driver
device driver entry point. When this IOCTL function is invoked, entry point. When this IOCTL function is invoked, the following information is
the following information is returned to the caller: returned to the caller:
- last value written to the specified output word - last value written to the specified output word
- timestamp of when the last write was performed - timestamp of when the last write was performed

View File

@ -1,29 +1,40 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Frame Buffer Driver Frame Buffer Driver
################### ###################
In this chapter, we present the basic functionality implemented by a In this chapter, we present the basic functionality implemented by a frame
frame buffer driver: ``frame_buffer_initialize()``, ``frame_buffer_open()``,``frame_buffer_close()``, ``frame_buffer_read()``, ``frame_buffer_write()`` buffer driver:
and ``frame_buffer_control()``.
- ``frame_buffer_initialize()``
- ``frame_buffer_open()``
- ``frame_buffer_close()``
- ``frame_buffer_read()``
- ``frame_buffer_write()``
- ``frame_buffer_control()``
Introduction Introduction
============ ============
The purpose of the frame buffer driver is to provide an abstraction for The purpose of the frame buffer driver is to provide an abstraction for
graphics hardware. graphics hardware. By using the frame buffer interface, an application can
By using the frame buffer interface, an application can display graphics display graphics without knowing anything about the low-level details of
without knowing anything about the low-level details of interfacing to a interfacing to a particular graphics adapter. The parameters governing the
particular graphics adapter. The parameters governing the mapping of mapping of memory to displayed pixels (planar or linear, bit depth, etc) is
memory to displayed pixels (planar or linear, bit depth, etc) is still still implementation-specific, but device-independent methods are provided to
implementation-specific, but device-independent methods are provided to
determine and potentially modify these parameters. determine and potentially modify these parameters.
The frame buffer driver is commonly located in the ``console`` The frame buffer driver is commonly located in the ``console`` directory of the
directory of the BSP and registered by the name */dev/fb0*. BSP and registered by the name :file:`/dev/fb0`. Additional frame buffers (if
Additional frame buffers (if available) are named */dev/fb1*,*/dev/fb2*, etc. available) are named :file:`/dev/fb1*,*/dev/fb2`, etc.
To work with the frame buffer, the following operation sequence is used:``open()``, ``ioctls()`` to get the frame buffer info, ``read()`` and/or``write()``, and ``close()``. To work with the frame buffer, the following operation sequence is
used:``open()``, ``ioctls()`` to get the frame buffer info, ``read()``
and/or ``write()``, and ``close()``.
Driver Function Overview Driver Function Overview
======================== ========================
@ -32,66 +43,74 @@ Initialization
-------------- --------------
The driver initialization is called once during the RTEMS initialization The driver initialization is called once during the RTEMS initialization
process and returns RTEMS_SUCCESSFUL when the device driver is successfully process and returns ``RTEMS_SUCCESSFUL`` when the device driver is successfully
initialized. During the initialization, a name is assigned to the frame initialized. During the initialization, a name is assigned to the frame buffer
buffer device. If the graphics hardware supports console text output, device. If the graphics hardware supports console text output, as is the case
as is the case with the pc386 VGA hardware, initialization into graphics with the pc386 VGA hardware, initialization into graphics mode may be deferred
mode may be deferred until the device is ``open()`` ed. until the device is ``open()`` ed.
The ``frame_buffer_initialize()`` function may look like this: The ``frame_buffer_initialize()`` function may look like this:
.. code:: c .. code-block:: c
rtems_device_driver frame_buffer_initialize( rtems_device_driver frame_buffer_initialize(
rtems_device_major_number major, rtems_device_major_number major,
rtems_device_minor_number minor, rtems_device_minor_number minor,
void \*arg) void *arg)
{ {
rtems_status_code status; rtems_status_code status;
printk( "frame buffer driver initializing..\\n" );
printk( "frame buffer driver initializing..\n" );
/* /*
* Register the device * Register the device
\*/ */
status = rtems_io_register_name("/dev/fb0", major, 0); status = rtems_io_register_name("/dev/fb0", major, 0);
if (status != RTEMS_SUCCESSFUL) if (status != RTEMS_SUCCESSFUL)
{ {
printk("Error registering frame buffer device!\\n"); printk("Error registering frame buffer device!\n");
rtems_fatal_error_occurred( status ); rtems_fatal_error_occurred( status );
} }
/* /*
* graphics hardware initialization goes here for non-console * graphics hardware initialization goes here for non-console
* devices * devices
\*/ */
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} }
Opening the Frame Buffer Device Opening the Frame Buffer Device
------------------------------- -------------------------------
The ``frame_buffer_open()`` function is called whenever a frame buffer device is opened. The ``frame_buffer_open()`` function is called whenever a frame buffer device
If the frame buffer is registered as "/dev/fb0", the ``frame_buffer_open`` entry point is opened. If the frame buffer is registered as :file:`/dev/fb0`, the
will be called as the result of an ``open("/dev/fb0", mode)`` in the application. ``frame_buffer_open`` entry point will be called as the result of an
``open("/dev/fb0", mode)`` in the application.
Thread safety of the frame buffer driver is implementation-dependent. Thread safety of the frame buffer driver is implementation-dependent. The VGA
The VGA driver shown below uses a mutex to prevent multiple open() driver shown below uses a mutex to prevent multiple open() operations of the
operations of the frame buffer device. frame buffer device.
The ``frame_buffer_open()`` function returns RTEMS_SUCCESSFUL when the device driver The ``frame_buffer_open()`` function returns ``RTEMS_SUCCESSFUL`` when the
is successfully opened, and RTEMS_UNSATISFIED if the device is already open: device driver is successfully opened, and ``RTEMS_UNSATISFIED`` if the device
.. code:: c is already open:
.. code-block:: c
rtems_device_driver frame_buffer_close( rtems_device_driver frame_buffer_close(
rtems_device_major_number major, rtems_device_major_number major,
rtems_device_minor_number minor, rtems_device_minor_number minor,
void \*arg void *arg
) )
{ {
if (pthread_mutex_unlock(&mutex) == 0) { if (pthread_mutex_unlock(&mutex) == 0) {
/* restore previous state. for VGA this means return to text mode. /* restore previous state. for VGA this means return to text mode.
* leave out if graphics hardware has been initialized in * leave out if graphics hardware has been initialized in
* frame_buffer_initialize() \*/ * frame_buffer_initialize()
*/
ega_hwterm(); ega_hwterm();
printk( "FBVGA close called.\\n" ); printk( "FBVGA close called.\n" );
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} }
return RTEMS_UNSATISFIED; return RTEMS_UNSATISFIED;
@ -103,82 +122,92 @@ hardware-specific initialization.
Closing the Frame Buffer Device Closing the Frame Buffer Device
------------------------------- -------------------------------
The ``frame_buffer_close()`` is invoked when the frame buffer device The ``frame_buffer_close()`` is invoked when the frame buffer device is closed.
is closed. It frees up any resources allocated in``frame_buffer_open()``, and should restore previous hardware state. It frees up any resources allocated in ``frame_buffer_open()``, and should
The entry point corresponds to the device driver close entry point. restore previous hardware state. The entry point corresponds to the device
driver close entry point.
Returns RTEMS_SUCCESSFUL when the device driver is successfully closed: Returns ``RTEMS_SUCCESSFUL`` when the device driver is successfully closed:
.. code:: c
.. code-block:: c
rtems_device_driver frame_buffer_close( rtems_device_driver frame_buffer_close(
rtems_device_major_number major, rtems_device_major_number major,
rtems_device_minor_number minor, rtems_device_minor_number minor,
void \*arg) void *arg)
{ {
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
/* TODO check mutex return value, RTEMS_UNSATISFIED if it failed. we /* TODO check mutex return value, RTEMS_UNSATISFIED if it failed. we
* don't want to unconditionally call ega_hwterm()... \*/ * don't want to unconditionally call ega_hwterm()... */
/* restore previous state. for VGA this means return to text mode. /* restore previous state. for VGA this means return to text mode.
* leave out if graphics hardware has been initialized in * leave out if graphics hardware has been initialized in
* frame_buffer_initialize() \*/ * frame_buffer_initialize() */
ega_hwterm(); ega_hwterm();
printk( "frame buffer close called.\\n" ); printk( "frame buffer close called.\n" );
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} }
Reading from the Frame Buffer Device Reading from the Frame Buffer Device
------------------------------------ ------------------------------------
The ``frame_buffer_read()`` is invoked from a ``read()`` operation The ``frame_buffer_read()`` is invoked from a ``read()`` operation on the frame
on the frame buffer device. buffer device. Read functions should allow normal and partial reading at the
Read functions should allow normal and partial reading at the end of frame buffer memory. end of frame buffer memory. This method returns ``RTEMS_SUCCESSFUL`` when the
This method returns RTEMS_SUCCESSFUL when the device is successfully read from: device is successfully read from:
.. code:: c
.. code-block:: c
rtems_device_driver frame_buffer_read( rtems_device_driver frame_buffer_read(
rtems_device_major_number major, rtems_device_major_number major,
rtems_device_minor_number minor, rtems_device_minor_number minor,
void \*arg void *arg
) )
{ {
rtems_libio_rw_args_t \*rw_args = (rtems_libio_rw_args_t \*)arg; rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count; rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ?
memcpy(rw_args->buffer, (const void \*) (fb_fix.smem_start + rw_args->offset), rw_args->bytes_moved); (fb_fix.smem_len - rw_args->offset) : rw_args->count;
memcpy(rw_args->buffer,
(const void *) (fb_fix.smem_start + rw_args->offset),
rw_args->bytes_moved);
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} }
Writing to the Frame Buffer Device Writing to the Frame Buffer Device
---------------------------------- ----------------------------------
The ``frame_buffer_write()`` is invoked from a ``write()`` The ``frame_buffer_write()`` is invoked from a ``write()`` operation on the
operation on the frame buffer device. frame buffer device. The frame buffer write function is similar to the read
The frame buffer write function is similar to the read function, and function, and should handle similar cases involving partial writes.
should handle similar cases involving partial writes.
This method returns RTEMS_SUCCESSFUL when the device is successfully This method returns ``RTEMS_SUCCESSFUL`` when the device is successfully
written to: written to:
.. code:: c
.. code-block:: c
rtems_device_driver frame_buffer_write( rtems_device_driver frame_buffer_write(
rtems_device_major_number major, rtems_device_major_number major,
rtems_device_minor_number minor, rtems_device_minor_number minor,
void \*arg void *arg
) )
{ {
rtems_libio_rw_args_t \*rw_args = (rtems_libio_rw_args_t \*)arg; rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count; rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ?
memcpy( (void \*) (fb_fix.smem_start + rw_args->offset), rw_args->buffer, rw_args->bytes_moved); (fb_fix.smem_len - rw_args->offset) : rw_args->count;
memcpy((void *) (fb_fix.smem_start + rw_args->offset),
rw_args->buffer,
rw_args->bytes_moved);
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} }
Frame Buffer IO Control Frame Buffer IO Control
----------------------- -----------------------
The frame buffer driver allows several ioctls, partially compatible with The frame buffer driver allows several ioctls, partially compatible with the
the Linux kernel, Linux kernel, to obtain information about the hardware.
to obtain information about the hardware.
All ``ioctl()`` operations on the frame buffer device invoke``frame_buffer_control()``. All ``ioctl()`` operations on the frame buffer device invoke
``frame_buffer_control()``.
Ioctls supported: Ioctls supported:
@ -186,16 +215,18 @@ Ioctls supported:
- ioctl to set and get palette. - ioctl to set and get palette.
.. code:: c .. code-block:: c
rtems_device_driver frame_buffer_control( rtems_device_driver frame_buffer_control(
rtems_device_major_number major, rtems_device_major_number major,
rtems_device_minor_number minor, rtems_device_minor_number minor,
void \*arg void *arg
) )
{ {
rtems_libio_ioctl_args_t \*args = arg; rtems_libio_ioctl_args_t *args = arg;
printk( "FBVGA ioctl called, cmd=%x\\n", args->command );
printk( "FBVGA ioctl called, cmd=%x\n", args->command );
switch( args->command ) { switch( args->command ) {
case FBIOGET_FSCREENINFO: case FBIOGET_FSCREENINFO:
args->ioctl_return = get_fix_screen_info( ( struct fb_fix_screeninfo * ) args->buffer ); args->ioctl_return = get_fix_screen_info( ( struct fb_fix_screeninfo * ) args->buffer );
@ -217,15 +248,9 @@ Ioctls supported:
args->ioctl_return = 0; args->ioctl_return = 0;
break; break;
} }
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} }
See ``rtems/fb.h`` for more information on the list of ioctls and See ``rtems/fb.h`` for more information on the list of ioctls and data
data structures they work with. structures they work with.
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.

View File

@ -1,14 +1,17 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
IDE Controller Driver IDE Controller Driver
##################### #####################
Introduction Introduction
============ ============
The IDE Controller driver is responsible for providing an The IDE Controller driver is responsible for providing an interface to an IDE
interface to an IDE Controller. The capabilities provided by this Controller. The capabilities provided by this driver are:
driver are:
- Read IDE Controller register - Read IDE Controller register
@ -18,35 +21,37 @@ driver are:
- Write data block through IDE Controller Data Register - Write data block through IDE Controller Data Register
The reference implementation for an IDE Controller driver can The reference implementation for an IDE Controller driver can be found in
be found in ``$RTEMS_SRC_ROOT/c/src/libchip/ide``. This driver ``$RTEMS_SRC_ROOT/c/src/libchip/ide``. This driver is based on the libchip
is based on the libchip concept and allows to work with any of the IDE concept and allows to work with any of the IDE Controller chips simply by
Controller chips simply by appropriate configuration of BSP. Drivers for a appropriate configuration of BSP. Drivers for a particular IDE Controller chips
particular IDE Controller chips locate in the following directories: drivers locate in the following directories: drivers for well-known IDE Controller
for well-known IDE Controller chips locate into``$RTEMS_SRC_ROOT/c/src/libchip/ide``, drivers for IDE Controller chips chips locate into ``$RTEMS_SRC_ROOT/c/src/libchip/ide``, drivers for IDE
integrated with CPU locate into``$RTEMS_SRC_ROOT/c/src/lib/libcpu/myCPU`` and Controller chips integrated with CPU locate into
drivers for custom IDE Controller chips (for example, implemented on FPGA) ``$RTEMS_SRC_ROOT/c/src/lib/libcpu/myCPU`` and drivers for custom IDE
locate into ``$RTEMS_SRC_ROOT/c/src/lib/libbsp/myBSP``. Controller chips (for example, implemented on FPGA) locate into
There is a README file in these directories for each supported ``$RTEMS_SRC_ROOT/c/src/lib/libbsp/myBSP``. There is a README file in these
IDE Controller chip. Each of these README explains how to configure a BSP directories for each supported IDE Controller chip. Each of these README
for that particular IDE Controller chip. explains how to configure a BSP for that particular IDE Controller chip.
Initialization Initialization
============== ==============
IDE Controller chips used by a BSP are statically configured into``IDE_Controller_Table``. The ``ide_controller_initialize`` routine is IDE Controller chips used by a BSP are statically configured into
``IDE_Controller_Table``. The ``ide_controller_initialize`` routine is
responsible for initialization of all configured IDE controller chips. responsible for initialization of all configured IDE controller chips.
Initialization order of the chips based on the order the chips are defined in Initialization order of the chips based on the order the chips are defined in
the ``IDE_Controller_Table``. the ``IDE_Controller_Table``.
The following actions are performed by the IDE Controller driver The following actions are performed by the IDE Controller driver initialization
initialization routine: routine:
.. code:: c
.. code-block:: c
rtems_device_driver ide_controller_initialize( rtems_device_driver ide_controller_initialize(
rtems_device_major_number major, rtems_device_major_number major,
rtems_device_minor_number minor_arg, rtems_device_minor_number minor_arg,
void \*arg void *arg
) )
{ {
for each IDE Controller chip configured in IDE_Controller_Table for each IDE Controller chip configured in IDE_Controller_Table
@ -62,13 +67,18 @@ Read IDE Controller Register
The ``ide_controller_read_register`` routine reads the content of the IDE The ``ide_controller_read_register`` routine reads the content of the IDE
Controller chip register. IDE Controller chip is selected via the minor Controller chip register. IDE Controller chip is selected via the minor
number. This routine is not allowed to be called from an application. number. This routine is not allowed to be called from an application.
.. code:: c
void ide_controller_read_register(rtems_device_minor_number minor, .. code-block:: c
unsigned32 reg, unsigned32 \*value)
void ide_controller_read_register(
rtems_device_minor_number minor,
unsigned32 reg,
unsigned32 *value
)
{ {
get IDE Controller chip configuration information from get IDE Controller chip configuration information from
IDE_Controller_Table by minor number IDE_Controller_Table by minor number
invoke read register routine for the chip invoke read register routine for the chip
} }
@ -78,65 +88,69 @@ Write IDE Controller Register
The ``ide_controller_write_register`` routine writes IDE Controller chip The ``ide_controller_write_register`` routine writes IDE Controller chip
register with specified value. IDE Controller chip is selected via the minor register with specified value. IDE Controller chip is selected via the minor
number. This routine is not allowed to be called from an application. number. This routine is not allowed to be called from an application.
.. code:: c
void ide_controller_write_register(rtems_device_minor_number minor, .. code-block:: c
unsigned32 reg, unsigned32 value)
void ide_controller_write_register(
rtems_device_minor_number minor,
unsigned32 reg,
unsigned32 value
)
{ {
get IDE Controller chip configuration information from get IDE Controller chip configuration information from
IDE_Controller_Table by minor number IDE_Controller_Table by minor number
invoke write register routine for the chip invoke write register routine for the chip
} }
Read Data Block Through IDE Controller Data Register Read Data Block Through IDE Controller Data Register
==================================================== ====================================================
The ``ide_controller_read_data_block`` provides multiple consequent read The ``ide_controller_read_data_block`` provides multiple consequent read of the
of the IDE Controller Data Register. IDE Controller chip is selected via the IDE Controller Data Register. IDE Controller chip is selected via the minor
minor number. The same functionality may be achieved via separate multiple number. The same functionality may be achieved via separate multiple calls of
calls of ``ide_controller_read_register`` routine but``ide_controller_read_data_block`` allows to escape functions call ``ide_controller_read_register`` routine but ``ide_controller_read_data_block``
overhead. This routine is not allowed to be called from an application. allows to escape functions call overhead. This routine is not allowed to be
.. code:: c called from an application.
.. code-block:: c
void ide_controller_read_data_block( void ide_controller_read_data_block(
rtems_device_minor_number minor, rtems_device_minor_number minor,
unsigned16 block_size, unsigned16 block_size,
blkdev_sg_buffer \*bufs, blkdev_sg_buffer *bufs,
uint32_t \*cbuf, uint32_t *cbuf,
uint32_t \*pos uint32_t *pos
) )
{ {
get IDE Controller chip configuration information from get IDE Controller chip configuration information from
IDE_Controller_Table by minor number IDE_Controller_Table by minor number
invoke read data block routine for the chip invoke read data block routine for the chip
} }
Write Data Block Through IDE Controller Data Register Write Data Block Through IDE Controller Data Register
===================================================== =====================================================
The ``ide_controller_write_data_block`` provides multiple consequent write The ``ide_controller_write_data_block`` provides multiple consequent write into
into the IDE Controller Data Register. IDE Controller chip is selected via the the IDE Controller Data Register. IDE Controller chip is selected via the minor
minor number. The same functionality may be achieved via separate multiple number. The same functionality may be achieved via separate multiple calls of
calls of ``ide_controller_write_register`` routine but``ide_controller_write_data_block`` allows to escape functions call ``ide_controller_write_register`` routine but
``ide_controller_write_data_block`` allows to escape functions call
overhead. This routine is not allowed to be called from an application. overhead. This routine is not allowed to be called from an application.
.. code:: c
.. code-block:: c
void ide_controller_write_data_block( void ide_controller_write_data_block(
rtems_device_minor_number minor, rtems_device_minor_number minor,
unsigned16 block_size, unsigned16 block_size,
blkdev_sg_buffer \*bufs, blkdev_sg_buffer *bufs,
uint32_t \*cbuf, uint32_t *cbuf,
uint32_t \*pos uint32_t *pos
) )
{ {
get IDE Controller chip configuration information from get IDE Controller chip configuration information from
IDE_Controller_Table by minor number IDE_Controller_Table by minor number
invoke write data block routine for the chip invoke write data block routine for the chip
} }
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.

View File

@ -4,41 +4,41 @@
BSP and Device Driver Development Guide BSP and Device Driver Development Guide
======================================= =======================================
COPYRIGHT (c) 1988 - 2015. BSP and Device Driver Development Guide
---------------------------------------
On-Line Applications Research Corporation (OAR). | COPYRIGHT (c) 1988 - 2015.
| On-Line Applications Research Corporation (OAR).
The authors have used their best efforts in preparing The authors have used their best efforts in preparing this material. These
this material. These efforts include the development, research, efforts include the development, research, and testing of the theories and
and testing of the theories and programs to determine their programs to determine their effectiveness. No warranty of any kind, expressed
effectiveness. No warranty of any kind, expressed or implied, or implied, with regard to the software or the material contained in this
with regard to the software or the material contained in this document is provided. No liability arising out of the application or use of
document is provided. No liability arising out of the any product described in this document is assumed. The authors reserve the
application or use of any product described in this document is right to revise this material and to make changes from time to time in the
assumed. The authors reserve the right to revise this material content hereof without obligation to notify anyone of such revision or changes.
and to make changes from time to time in the content hereof
without obligation to notify anyone of such revision or changes.
The RTEMS Project is hosted at http://www.rtems.org. Any The RTEMS Project is hosted at http://www.rtems.org. Any inquiries concerning
inquiries concerning RTEMS, its related support components, or its RTEMS, its related support components, or its documentation should be directed
documentation should be directed to the Community Project hosted athttp://www.rtems.org. to the Community Project hosted at http://www.rtems.org.
Any inquiries for commercial services including training, support, custom .. topic:: RTEMS Online Resources
development, application development assistance should be directed tohttp://www.rtems.com.
Table of Contents
-----------------
.. toctree::
preface
================ =============================
Home https://www.rtems.org/
Developers https://devel.rtems.org/
Documentation https://docs.rtems.org/
Bug Reporting https://devel.rtems.org/query
Mailing Lists https://lists.rtems.org/
Git Repositories https://git.rtems.org/
================ =============================
.. toctree:: .. toctree::
:maxdepth: 3 :maxdepth: 3
:numbered: :numbered:
preface
target_dependant_files target_dependant_files
makefiles makefiles
linker_script linker_script
@ -59,8 +59,5 @@ Table of Contents
discrete discrete
command command
* :ref:`genindex` * :ref:`genindex`
* :ref:`search` * :ref:`search`

View File

@ -1,5 +1,9 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2008.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Initialization Code Initialization Code
################### ###################
@ -7,87 +11,85 @@ Introduction
============ ============
The initialization code is the first piece of code executed when there's a The initialization code is the first piece of code executed when there's a
reset/reboot. Its purpose is to initialize the board for the application. reset/reboot. Its purpose is to initialize the board for the application. This
This chapter contains a narrative description of the initialization chapter contains a narrative description of the initialization process followed
process followed by a description of each of the files and routines by a description of each of the files and routines commonly found in the BSP
commonly found in the BSP related to initialization. The remainder of related to initialization. The remainder of this chapter covers special issues
this chapter covers special issues which require attention such which require attention such as interrupt vector table and chip select
as interrupt vector table and chip select initialization. initialization.
Most of the examples in this chapter will be based on the SPARC/ERC32 and Most of the examples in this chapter will be based on the SPARC/ERC32 and
m68k/gen68340 BSP initialization code. Like most BSPs, the initialization m68k/gen68340 BSP initialization code. Like most BSPs, the initialization for
for these BSP is divided into two subdirectories under the BSP source these BSP is divided into two subdirectories under the BSP source directory.
directory. The BSP source code for these BSPs is in the following The BSP source code for these BSPs is in the following directories:
directories:
.. code:: c .. code:: c
c/src/lib/libbsp/m68k/gen68340 c/src/lib/libbsp/m68k/gen68340
c/src/lib/libbsp/sparc/erc32 c/src/lib/libbsp/sparc/erc32
Both BSPs contain startup code written in assembly language and C. Both BSPs contain startup code written in assembly language and C. The
The gen68340 BSP has its early initialization start code in the``start340`` subdirectory and its C startup code in the ``startup`` gen68340 BSP has its early initialization start code in the ``start340``
directory. In the ``start340`` directory are two source files. subdirectory and its C startup code in the ``startup`` directory. In the
The file ``startfor340only.s`` is the simpler of these files as it only ``start340`` directory are two source files. The file ``startfor340only.s`` is
has initialization code for a MC68340 board. The file ``start340.s`` the simpler of these files as it only has initialization code for a MC68340
contains initialization for a 68349 based board as well. board. The file ``start340.s`` contains initialization for a 68349 based board
as well.
Similarly, the ERC32 BSP has startup code written in assembly language and C.
However, this BSP shares this code with other SPARC BSPs. Thus the
``Makefile.am`` explicitly references the following files for this
functionality.
Similarly, the ERC32 BSP has startup code written in assembly language
and C. However, this BSP shares this code with other SPARC BSPs.
Thus the ``Makefile.am`` explicitly references the following files
for this functionality.
.. code:: c .. code:: c
../../sparc/shared/start.S ../../sparc/shared/start.S
*NOTE:* In most BSPs, the directory named ``start340`` in the .. note::
gen68340 BSP would be simply named ``start`` or start followed by a
BSP designation. In most BSPs, the directory named ``start340`` in the gen68340 BSP would be
simply named ``start`` or start followed by a BSP designation.
Required Global Variables Required Global Variables
========================= =========================
Although not strictly part of initialization, there are a few global Although not strictly part of initialization, there are a few global variables
variables assumed to exist by reusable device drivers. These global assumed to exist by reusable device drivers. These global variables should
variables should only defined by the BSP when using one of these device only defined by the BSP when using one of these device drivers.
drivers.
The BSP author probably should be aware of the ``Configuration`` The BSP author probably should be aware of the ``Configuration`` Table
Table structure generated by ``<rtems/confdefs.h>`` during debug but structure generated by ``<rtems/confdefs.h>`` during debug but should not
should not explicitly reference it in the source code. There are helper explicitly reference it in the source code. There are helper routines provided
routines provided by RTEMS to access individual fields. by RTEMS to access individual fields.
In older RTEMS versions, the BSP included a number of required global In older RTEMS versions, the BSP included a number of required global
variables. We have made every attempt to eliminate these in the interest variables. We have made every attempt to eliminate these in the interest of
of simplicity. simplicity.
Board Initialization Board Initialization
==================== ====================
This section describes the steps an application goes through from the This section describes the steps an application goes through from the time the
time the first BSP code is executed until the first application task first BSP code is executed until the first application task executes.
executes. The following figure illustrates the program flow during
this sequence:
IMAGE NOT AVAILABLE IN ASCII VERSION The initialization flows from assembly language start code to the shared
``bootcard.c`` framework then through the C Library, RTEMS, device driver
initialization phases, and the context switch to the first application task.
After this, the application executes until it calls ``exit``,
``rtems_shutdown_executive``, or some other normal termination initiating
routine and a fatal system state is reached. The optional
``bsp_fatal_extension`` initial extension can perform BSP specific system
termination.
The above figure illustrates the flow from assembly language start code The routines invoked during this will be discussed and their location in the
to the shared ``bootcard.c`` framework then through the C Library, RTEMS source tree pointed out as we discuss each.
RTEMS, device driver initialization phases, and the context switch
to the first application task. After this, the application executes
until it calls ``exit``, ``rtems_shutdown_executive``, or some
other normal termination initiating routine and a fatal system state is
reached. The optional ``bsp_fatal_extension`` initial extension can perform
BSP specific system termination.
The routines invoked during this will be discussed and their location
in the RTEMS source tree pointed out as we discuss each.
Start Code - Assembly Language Initialization Start Code - Assembly Language Initialization
--------------------------------------------- ---------------------------------------------
The assembly language code in the directory ``start`` is the first part The assembly language code in the directory ``start`` is the first part of the
of the application to execute. It is responsible for initializing the application to execute. It is responsible for initializing the processor and
processor and board enough to execute the rest of the BSP. This includes: board enough to execute the rest of the BSP. This includes:
- initializing the stack - initializing the stack
@ -97,29 +99,29 @@ processor and board enough to execute the rest of the BSP. This includes:
- copy the initialized data from ROM to RAM - copy the initialized data from ROM to RAM
The general rule of thumb is that the start code in assembly should The general rule of thumb is that the start code in assembly should do the
do the minimum necessary to allow C code to execute to complete the minimum necessary to allow C code to execute to complete the initialization
initialization sequence. sequence.
The initial assembly language start code completes its execution by The initial assembly language start code completes its execution by invoking
invoking the shared routine ``boot_card()``. the shared routine ``boot_card()``.
The label (symbolic name) associated with the starting address of the The label (symbolic name) associated with the starting address of the program
program is typically called ``start``. The start object file is the is typically called ``start``. The start object file is the first object file
first object file linked into the program image so it is ensured that linked into the program image so it is ensured that the start code is at offset
the start code is at offset 0 in the ``.text`` section. It is the 0 in the ``.text`` section. It is the responsibility of the linker script in
responsibility of the linker script in conjunction with the compiler conjunction with the compiler specifications file to put the start code in the
specifications file to put the start code in the correct location in correct location in the application image.
the application image.
boot_card() - Boot the Card boot_card() - Boot the Card
--------------------------- ---------------------------
The ``boot_card()`` is the first C code invoked. This file is the The ``boot_card()`` is the first C code invoked. This file is the core
core component in the RTEMS BSP Initialization Framework and provides component in the RTEMS BSP Initialization Framework and provides the proper
the proper sequencing of initialization steps for the BSP, RTEMS and sequencing of initialization steps for the BSP, RTEMS and device drivers. All
device drivers. All BSPs use the same shared version of ``boot_card()`` BSPs use the same shared version of ``boot_card()`` which is located in the
which is located in the following file: following file:
.. code:: c .. code:: c
c/src/lib/libbsp/shared/bootcard.c c/src/lib/libbsp/shared/bootcard.c
@ -131,33 +133,38 @@ The ``boot_card()`` routine performs the following functions:
- It sets the command line argument variables - It sets the command line argument variables
for later use by the application. for later use by the application.
- It invokes the BSP specific routine ``bsp_work_area_initialize()`` - It invokes the BSP specific routine ``bsp_work_area_initialize()`` which is
which is supposed to initialize the RTEMS Workspace and the C Program Heap. supposed to initialize the RTEMS Workspace and the C Program Heap. Usually
Usually the default implementation in``c/src/lib/libbsp/shared/bspgetworkarea.c`` should be sufficient. Custom the default implementation in ``c/src/lib/libbsp/shared/bspgetworkarea.c``
implementations can use ``bsp_work_area_initialize_default()`` or``bsp_work_area_initialize_with_table()`` available as inline functions from``#include <bsp/bootcard.h>``. should be sufficient. Custom implementations can use
``bsp_work_area_initialize_default()`` or
``bsp_work_area_initialize_with_table()`` available as inline functions
from``#include <bsp/bootcard.h>``.
- It invokes the BSP specific routine ``bsp_start()`` which is - It invokes the BSP specific routine ``bsp_start()`` which is written in C and
written in C and thus able to perform more advanced initialization. thus able to perform more advanced initialization. Often MMU, bus and
Often MMU, bus and interrupt controller initialization occurs here. Since the interrupt controller initialization occurs here. Since the RTEMS Workspace
RTEMS Workspace and the C Program Heap was already initialized by``bsp_work_area_initialize()``, this routine may use ``malloc()``, etc. and the C Program Heap was already initialized by
``bsp_work_area_initialize()``, this routine may use ``malloc()``, etc.
- It invokes the RTEMS directive``rtems_initialize_data_structures()`` to initialize the RTEMS - It invokes the RTEMS directive ``rtems_initialize_data_structures()`` to
executive to a state where objects can be created but tasking is not initialize the RTEMS executive to a state where objects can be created but
enabled. tasking is not enabled.
- It invokes the BSP specific routine ``bsp_libc_init()`` to initialize - It invokes the BSP specific routine ``bsp_libc_init()`` to initialize the C
the C Library. Usually the default implementation in``c/src/lib/libbsp/shared/bsplibc.c`` should be sufficient. Library. Usually the default implementation in
``c/src/lib/libbsp/shared/bsplibc.c`` should be sufficient.
- It invokes the RTEMS directive``rtems_initialize_before_drivers()`` to initialize the MPCI Server - It invokes the RTEMS directive ``rtems_initialize_before_drivers()`` to
thread in a multiprocessor configuration and execute API specific initialize the MPCI Server thread in a multiprocessor configuration and
extensions. execute API specific extensions.
- It invokes the BSP specific routine ``bsp_predriver_hook``. For - It invokes the BSP specific routine ``bsp_predriver_hook``. For most BSPs,
most BSPs, the implementation of this routine does nothing. the implementation of this routine does nothing.
- It invokes the RTEMS directive``rtems_initialize_device_drivers()`` to initialize the statically - It invokes the RTEMS directive ``rtems_initialize_device_drivers()`` to
configured set of device drivers in the order they were specified in initialize the statically configured set of device drivers in the order they
the Configuration Table. were specified in the Configuration Table.
- It invokes the BSP specific routine ``bsp_postdriver_hook``. For - It invokes the BSP specific routine ``bsp_postdriver_hook``. For
most BSPs, the implementation of this routine does nothing. However, some most BSPs, the implementation of this routine does nothing. However, some
@ -166,19 +173,19 @@ The ``boot_card()`` routine performs the following functions:
for the BSP to insert BSP specific code into the initialization sequence. for the BSP to insert BSP specific code into the initialization sequence.
- It invokes the RTEMS directive ``rtems_initialize_start_multitasking()`` - It invokes the RTEMS directive ``rtems_initialize_start_multitasking()``
which initiates multitasking and performs a context switch to the which initiates multitasking and performs a context switch to the first user
first user application task and may enable interrupts as a side-effect of application task and may enable interrupts as a side-effect of that context
that context switch. The context switch saves the executing context. The switch. The context switch saves the executing context. The application
application runs now. The directive rtems_shutdown_executive() will return runs now. The directive ``rtems_shutdown_executive()`` will return to the
to the saved context. The exit() function will use this directive. saved context. The ``exit()`` function will use this directive. After a
After a return to the saved context a fatal system state is reached. The return to the saved context a fatal system state is reached. The fatal
fatal source is RTEMS_FATAL_SOURCE_EXIT with a fatal code set to the value source is ``RTEMS_FATAL_SOURCE_EXIT`` with a fatal code set to the value
passed to rtems_shutdown_executive(). passed to rtems_shutdown_executive(). The enabling of interrupts during the
The enabling of interrupts during the first context switch is often the source first context switch is often the source for fatal errors during BSP
for fatal errors during BSP development because the BSP did not clear and/or development because the BSP did not clear and/or disable all interrupt
disable all interrupt sources and a spurious interrupt will occur. sources and a spurious interrupt will occur. When in the context of the
When in the context of the first task but before its body has been first task but before its body has been entered, any C++ Global Constructors
entered, any C++ Global Constructors will be invoked. will be invoked.
That's it. We just went through the entire sequence. That's it. We just went through the entire sequence.
@ -189,15 +196,18 @@ This is the first BSP specific C routine to execute during system
initialization. It must initialize the support for allocating memory from the initialization. It must initialize the support for allocating memory from the
C Program Heap and RTEMS Workspace commonly referred to as the work areas. C Program Heap and RTEMS Workspace commonly referred to as the work areas.
Many BSPs place the work areas at the end of RAM although this is certainly not Many BSPs place the work areas at the end of RAM although this is certainly not
a requirement. Usually the default implementation in:file:`c/src/lib/libbsp/shared/bspgetworkarea.c` should be sufficient. Custom a requirement. Usually the default implementation
implementations can use ``bsp_work_area_initialize_default()`` or``bsp_work_area_initialize_with_table()`` available as inline functions from``#include <bsp/bootcard.h>``. in:file:`c/src/lib/libbsp/shared/bspgetworkarea.c` should be sufficient.
Custom implementations can use ``bsp_work_area_initialize_default()``
or``bsp_work_area_initialize_with_table()`` available as inline functions from
``#include <bsp/bootcard.h>``.
bsp_start() - BSP Specific Initialization bsp_start() - BSP Specific Initialization
----------------------------------------- -----------------------------------------
This is the second BSP specific C routine to execute during system This is the second BSP specific C routine to execute during system
initialization. It is called right after ``bsp_work_area_initialize()``. initialization. It is called right after ``bsp_work_area_initialize()``. The
The ``bsp_start()`` routine often performs required fundamental hardware ``bsp_start()`` routine often performs required fundamental hardware
initialization such as setting bus controller registers that do not have a initialization such as setting bus controller registers that do not have a
direct impact on whether or not C code can execute. The interrupt controllers direct impact on whether or not C code can execute. The interrupt controllers
are usually initialized here. The source code for this routine is usually are usually initialized here. The source code for this routine is usually
@ -206,52 +216,56 @@ It is not allowed to create any operating system objects, e.g. RTEMS
semaphores. semaphores.
After completing execution, this routine returns to the ``boot_card()`` After completing execution, this routine returns to the ``boot_card()``
routine. In case of errors, the initialization should be terminated via``bsp_fatal()``. routine. In case of errors, the initialization should be terminated via
``bsp_fatal()``.
bsp_predriver_hook() - BSP Specific Predriver Hook bsp_predriver_hook() - BSP Specific Predriver Hook
-------------------------------------------------- --------------------------------------------------
The ``bsp_predriver_hook()`` method is the BSP specific routine that is The ``bsp_predriver_hook()`` method is the BSP specific routine that is invoked
invoked immediately before the the device drivers are initialized. RTEMS immediately before the the device drivers are initialized. RTEMS initialization
initialization is complete but interrupts and tasking are disabled. is complete but interrupts and tasking are disabled.
The BSP may use the shared version of this routine which is empty. The BSP may use the shared version of this routine which is empty. Most BSPs
Most BSPs do not provide a specific implementation of this callback. do not provide a specific implementation of this callback.
Device Driver Initialization Device Driver Initialization
---------------------------- ----------------------------
At this point in the initialization sequence, the initialization At this point in the initialization sequence, the initialization routines for
routines for all of the device drivers specified in the Device all of the device drivers specified in the Device Driver Table are invoked.
Driver Table are invoked. The initialization routines are invoked The initialization routines are invoked in the order they appear in the Device
in the order they appear in the Device Driver Table. Driver Table.
The Driver Address Table is part of the RTEMS Configuration Table. It The Driver Address Table is part of the RTEMS Configuration Table. It defines
defines device drivers entry points (initialization, open, close, read, device drivers entry points (initialization, open, close, read, write, and
write, and control). For more information about this table, please control). For more information about this table, please refer to the
refer to the *Configuring a System* chapter in the*RTEMS Application C User's Guide*. *Configuring a System* chapter in the *RTEMS Application C User's Guide*.
The RTEMS initialization procedure calls the initialization function for The RTEMS initialization procedure calls the initialization function for every
every driver defined in the RTEMS Configuration Table (this allows driver defined in the RTEMS Configuration Table (this allows one to include
one to include only the drivers needed by the application). only the drivers needed by the application).
All these primitives have a major and a minor number as arguments: All these primitives have a major and a minor number as arguments:
- the major number refers to the driver type, - the major number refers to the driver type,
- the minor number is used to control two peripherals with the same - the minor number is used to control two peripherals with the same driver (for
driver (for instance, we define only one major number for the serial instance, we define only one major number for the serial driver, but two
driver, but two minor numbers for channel A and B if there are two minor numbers for channel A and B if there are two channels in the UART).
channels in the UART).
RTEMS Postdriver Callback RTEMS Postdriver Callback
------------------------- -------------------------
The ``bsp_postdriver_hook()`` BSP specific routine is invoked The ``bsp_postdriver_hook()`` BSP specific routine is invoked immediately after
immediately after the the device drivers and MPCI are initialized. the the device drivers and MPCI are initialized. Interrupts and tasking are
Interrupts and tasking are disabled. disabled.
Most BSPs use the shared implementation of this routine which is responsible
for opening the device ``/dev/console`` for standard input, output and error if
the application has configured the Console Device Driver. This file is located
at:
Most BSPs use the shared implementation of this routine which is responsible for opening the device ``/dev/console`` for standard input, output and error if the application has configured the Console Device Driver. This file is located at:
.. code:: c .. code:: c
c/src/lib/libbsp/shared/bsppost.c c/src/lib/libbsp/shared/bsppost.c
@ -259,121 +273,110 @@ Most BSPs use the shared implementation of this routine which is responsible for
The Interrupt Vector Table The Interrupt Vector Table
========================== ==========================
The Interrupt Vector Table is called different things on different The Interrupt Vector Table is called different things on different processor
processor families but the basic functionality is the same. Each families but the basic functionality is the same. Each entry in the Table
entry in the Table corresponds to the handler routine for a particular corresponds to the handler routine for a particular interrupt source. When an
interrupt source. When an interrupt from that source occurs, the interrupt from that source occurs, the specified handler routine is invoked.
specified handler routine is invoked. Some context information is Some context information is saved by the processor automatically when this
saved by the processor automatically when this happens. RTEMS saves happens. RTEMS saves enough context information so that an interrupt service
enough context information so that an interrupt service routine routine can be implemented in a high level language.
can be implemented in a high level language.
On some processors, the Interrupt Vector Table is at a fixed address. If On some processors, the Interrupt Vector Table is at a fixed address. If this
this address is in RAM, then usually the BSP only has to initialize address is in RAM, then usually the BSP only has to initialize it to contain
it to contain pointers to default handlers. If the table is in ROM, pointers to default handlers. If the table is in ROM, then the application
then the application developer will have to take special steps to developer will have to take special steps to fill in the table.
fill in the table.
If the base address of the Interrupt Vector Table can be dynamically If the base address of the Interrupt Vector Table can be dynamically changed to
changed to an arbitrary address, then the RTEMS port to that processor an arbitrary address, then the RTEMS port to that processor family will usually
family will usually allocate its own table and install it. For example, allocate its own table and install it. For example, on some members of the
on some members of the Motorola MC68xxx family, the Vector Base Register Motorola MC68xxx family, the Vector Base Register (``vbr``) contains this base
(``vbr``) contains this base address. address.
Interrupt Vector Table on the gen68340 BSP Interrupt Vector Table on the gen68340 BSP
------------------------------------------ ------------------------------------------
The gen68340 BSP provides a default Interrupt Vector Table in the The gen68340 BSP provides a default Interrupt Vector Table in the file
file ``$BSP_ROOT/start340/start340.s``. After the ``entry`` ``$BSP_ROOT/start340/start340.s``. After the ``entry`` label is the definition
label is the definition of space reserved for the table of of space reserved for the table of interrupts vectors. This space is assigned
interrupts vectors. This space is assigned the symbolic name the symbolic name of ``__uhoh`` in the ``gen68340`` BSP.
of ``__uhoh`` in the ``gen68340`` BSP.
At ``__uhoh`` label is the default interrupt handler routine. This At ``__uhoh`` label is the default interrupt handler routine. This routine is
routine is only called when an unexpected interrupts is raised. One can only called when an unexpected interrupts is raised. One can add their own
add their own routine there (in that case there's a call to a routine - routine there (in that case there's a call to a routine -
$BSP_ROOT/startup/dumpanic.c - that prints which address caused the $BSP_ROOT/startup/dumpanic.c - that prints which address caused the interrupt
interrupt and the contents of the registers, stack, etc.), but this should and the contents of the registers, stack, etc.), but this should not return.
not return.
Chip Select Initialization Chip Select Initialization
========================== ==========================
When the microprocessor accesses a memory area, address decoding is When the microprocessor accesses a memory area, address decoding is handled by
handled by an address decoder, so that the microprocessor knows which an address decoder, so that the microprocessor knows which memory chip(s) to
memory chip(s) to access. The following figure illustrates this: access. The following figure illustrates this:
.. code:: c .. code::
+-------------------+ +-------------------+
------------| | ------------| |
------------| \|------------ ------------| |------------
------------| Address \|------------ ------------| Address |------------
------------| Decoder \|------------ ------------| Decoder |------------
------------| \|------------ ------------| |------------
------------| | ------------| |
+-------------------+ +-------------------+
CPU Bus Chip Select CPU Bus Chip Select
The Chip Select registers must be programmed such that they match The Chip Select registers must be programmed such that they match the
the ``linkcmds`` settings. In the gen68340 BSP, ROM and RAM ``linkcmds`` settings. In the gen68340 BSP, ROM and RAM addresses can be found
addresses can be found in both the ``linkcmds`` and initialization in both the ``linkcmds`` and initialization code, but this is not a great way
code, but this is not a great way to do this. It is better to to do this. It is better to define addresses in the linker script.
define addresses in the linker script.
Integrated Processor Registers Initialization Integrated Processor Registers Initialization
============================================= =============================================
The CPUs used in many embedded systems are highly complex devices The CPUs used in many embedded systems are highly complex devices with multiple
with multiple peripherals on the CPU itself. For these devices, peripherals on the CPU itself. For these devices, there are always some
there are always some specific integrated processor registers specific integrated processor registers that must be initialized. Refer to the
that must be initialized. Refer to the processors' manuals for processors' manuals for details on these registers and be VERY careful
details on these registers and be VERY careful programming them. programming them.
Data Section Recopy Data Section Recopy
=================== ===================
The next initialization part can be found in``$BSP340_ROOT/start340/init68340.c``. First the Interrupt The next initialization part can be found in
Vector Table is copied into RAM, then the data section recopy is initiated ``$BSP340_ROOT/start340/init68340.c``. First the Interrupt Vector Table is
(_CopyDataClearBSSAndStart in ``$BSP340_ROOT/start340/startfor340only.s``). copied into RAM, then the data section recopy is initiated
(``_CopyDataClearBSSAndStart`` in ``$BSP340_ROOT/start340/startfor340only.s``).
This code performs the following actions: This code performs the following actions:
- copies the .data section from ROM to its location reserved in RAM - copies the .data section from ROM to its location reserved in RAM (see
(see `Initialized Data`_ for more details about this copy), `Initialized Data`_ for more details about this copy),
- clear ``.bss`` section (all the non-initialized - clear ``.bss`` section (all the non-initialized data will take value 0).
data will take value 0).
The RTEMS Configuration Table The RTEMS Configuration Table
============================= =============================
The RTEMS configuration table contains the maximum number of objects RTEMS The RTEMS configuration table contains the maximum number of objects RTEMS can
can handle during the application (e.g. maximum number of tasks, handle during the application (e.g. maximum number of tasks, semaphores,
semaphores, etc.). It's used to allocate the size for the RTEMS inner data etc.). It's used to allocate the size for the RTEMS inner data structures.
structures.
The RTEMS configuration table is application dependent, which means that The RTEMS configuration table is application dependent, which means that one
one has to provide one per application. It is usually defined by defining has to provide one per application. It is usually defined by defining macros
macros and including the header file ``<rtems/confdefs.h>``. In simple and including the header file ``<rtems/confdefs.h>``. In simple applications
applications such as the tests provided with RTEMS, it is commonly found such as the tests provided with RTEMS, it is commonly found in the main module
in the main module of the application. For more complex applications, of the application. For more complex applications, it may be in a file by
it may be in a file by itself. itself.
The header file ``<rtems/confdefs.h>`` defines a constant table The header file ``<rtems/confdefs.h>`` defines a constant table named
named ``Configuration``. With RTEMS 4.8 and older, it was accepted ``Configuration``. With RTEMS 4.8 and older, it was accepted practice for the
practice for the BSP to copy this table into a modifiable copy named``BSP_Configuration``. This copy of the table was modified to define BSP to copy this table into a modifiable copy named ``BSP_Configuration``.
the base address of the RTEMS Executive Workspace as well as to reflect This copy of the table was modified to define the base address of the RTEMS
any BSP and device driver requirements not automatically handled by the Executive Workspace as well as to reflect any BSP and device driver
application. In 4.9 and newer, we have eliminated the BSP copies of the requirements not automatically handled by the application. In 4.9 and newer,
configuration tables and are making efforts to make the configuration we have eliminated the BSP copies of the configuration tables and are making
information generated by ``<rtems/confdefs.h>`` constant and read only. efforts to make the configuration information generated by
``<rtems/confdefs.h>`` constant and read only.
For more information on the RTEMS Configuration Table, refer to the*RTEMS Application C User's Guide*.
.. COMMENT: COPYRIGHT (c) 1988-2008.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
For more information on the RTEMS Configuration Table, refer to the *RTEMS
Application C User's Guide*.

View File

@ -1,5 +1,10 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2011.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Linker Script Linker Script
############# #############
@ -7,27 +12,25 @@ What is a "linkcmds" file?
========================== ==========================
The ``linkcmds`` file is a script which is passed to the linker at linking The ``linkcmds`` file is a script which is passed to the linker at linking
time. This file describes the memory configuration of the board as needed time. This file describes the memory configuration of the board as needed to
to link the program. Specifically it specifies where the code and data link the program. Specifically it specifies where the code and data for the
for the application will reside in memory. application will reside in memory.
The format of the linker script is defined by the GNU Loader ``ld`` The format of the linker script is defined by the GNU Loader ``ld`` which is
which is included as a component of the GNU Binary Utilities. If you included as a component of the GNU Binary Utilities. If you are using
are using GNU/Linux, then you probably have the documentation installed GNU/Linux, then you probably have the documentation installed already and are
already and are using these same tools configured for *native* use. using these same tools configured for *native* use. Please visit the Binutils
Please visit the Binutils project http://sourceware.org/binutils/ project http://sourceware.org/binutils/ if you need more information.
if you need more information.
Program Sections Program Sections
================ ================
An embedded systems programmer must be much more aware of the An embedded systems programmer must be much more aware of the placement of
placement of their executable image in memory than the average their executable image in memory than the average applications programmer. A
applications programmer. A program destined to be embedded as well program destined to be embedded as well as the target system have some specific
as the target system have some specific properties that must be properties that must be taken into account. Embedded machines often mean
taken into account. Embedded machines often mean average performances average performances and small memory usage. It is the memory usage that
and small memory usage. It is the memory usage that concerns us concerns us when examining the linker command file.
when examining the linker command file.
Two types of memories have to be distinguished: Two types of memories have to be distinguished:
@ -35,90 +38,88 @@ Two types of memories have to be distinguished:
- ROM - non-volatile but read only - ROM - non-volatile but read only
Even though RAM and ROM can be found in every personal computer, Even though RAM and ROM can be found in every personal computer, one generally
one generally doesn't care about them. In a personal computer, doesn't care about them. In a personal computer, a program is nearly always
a program is nearly always stored on disk and executed in RAM. Things stored on disk and executed in RAM. Things are a bit different for embedded
are a bit different for embedded targets: the target will execute the targets: the target will execute the program each time it is rebooted or
program each time it is rebooted or switched on. The application switched on. The application program is stored in non-volatile memory such as
program is stored in non-volatile memory such as ROM, PROM, EEPROM, ROM, PROM, EEPROM, or Flash. On the other hand, data processing occurs in RAM.
or Flash. On the other hand, data processing occurs in RAM.
This leads us to the structure of an embedded program. In rough terms, This leads us to the structure of an embedded program. In rough terms, an
an embedded program is made of sections. It is the responsibility of embedded program is made of sections. It is the responsibility of the
the application programmer to place these sections in the appropriate application programmer to place these sections in the appropriate place in
place in target memory. To make this clearer, if using the COFF target memory. To make this clearer, if using the COFF object file format on
object file format on the Motorola m68k family of microprocessors, the Motorola m68k family of microprocessors, the following sections will be
the following sections will be present: present:
- *code (``.text``) section*: - code (``.text``) section:
is the program's code and it should not be modified. is the program's code and it should not be modified. This section may be
This section may be placed in ROM. placed in ROM.
- *non-initialized data (``.bss``) section*: - non-initialized data (``.bss``) section:
holds uninitialized variables of the program. It can stay in RAM. holds uninitialized variables of the program. It can stay in RAM.
- *initialized data (``.data``) section*: - initialized data (``.data``) section:
holds the initialized program data which may be modified during the holds the initialized program data which may be modified during the program's
program's life. This means they have to be in RAM. life. This means they have to be in RAM. On the other hand, these variables
On the other hand, these variables must be set to predefined values, and must be set to predefined values, and those predefined values have to be
those predefined values have to be stored in ROM. stored in ROM.
*NOTE:* Many programs and support libraries unknowingly assume that the``.bss`` section and, possibly, the application heap are initialized .. note::
to zero at program start. This is not required by the ISO/ANSI C Standard
but is such a common requirement that most BSPs do this.
That brings us up to the notion of the image of an executable: it consists Many programs and support libraries unknowingly assume that the ``.bss``
of the set of the sections that together constitute the application. section and, possibly, the application heap are initialized to zero at
program start. This is not required by the ISO/ANSI C Standard but is such
a common requirement that most BSPs do this.
That brings us up to the notion of the image of an executable: it consists of
the set of the sections that together constitute the application.
Image of an Executable Image of an Executable
====================== ======================
As a program executable has many sections (note that the user can define As a program executable has many sections (note that the user can define their
their own, and that compilers define theirs without any notice), one has to own, and that compilers define theirs without any notice), one has to specify
specify the placement of each section as well as the type of memory the placement of each section as well as the type of memory (RAM or ROM) the
(RAM or ROM) the sections will be placed into. sections will be placed into. For instance, a program compiled for a Personal
For instance, a program compiled for a Personal Computer will see all the Computer will see all the sections to go to RAM, while a program destined to be
sections to go to RAM, while a program destined to be embedded will see embedded will see some of his sections going into the ROM.
some of his sections going into the ROM.
The connection between a section and where that section is loaded into The connection between a section and where that section is loaded into memory
memory is made at link time. One has to let the linker know where is made at link time. One has to let the linker know where the different
the different sections are to be placed once they are in memory. sections are to be placed once they are in memory.
The following example shows a simple layout of program sections. With The following example shows a simple layout of program sections. With some
some object formats, there are many more sections but the basic object formats, there are many more sections but the basic layout is
layout is conceptually similar. conceptually similar.
.. code:: c
+-----------------+-------------+ ============ =============
| .text | RAM or ROM | .text RAM or ROM
+-----------------+-------------+ .data RAM
| .data | RAM | .bss RAM
+-----------------+-------------+ ============ =============
| .bss | RAM |
+-----------------+-------------+
Example Linker Command Script Example Linker Command Script
============================= =============================
The GNU linker has a command language to specify the image format. This The GNU linker has a command language to specify the image format. This
command language can be quite complicated but most of what is required command language can be quite complicated but most of what is required can be
can be learned by careful examination of a well-documented example. learned by careful examination of a well-documented example. The following is
The following is a heavily commented version of the linker script a heavily commented version of the linker script used with the the ``gen68340``
used with the the ``gen68340`` BSP This file can be found at BSP This file can be found at $BSP340_ROOT/startup/linkcmds.
$BSP340_ROOT/startup/linkcmds.
.. code:: c .. code:: c
/* /*
* Specify that the output is to be coff-m68k regardless of what the * Specify that the output is to be coff-m68k regardless of what the
* native object format is. * native object format is.
\*/ */
OUTPUT_FORMAT(coff-m68k) OUTPUT_FORMAT(coff-m68k)
/* /*
* Set the amount of RAM on the target board. * Set the amount of RAM on the target board.
* *
* NOTE: The default may be overridden by passing an argument to ld. * NOTE: The default may be overridden by passing an argument to ld.
\*/ */
RamSize = DEFINED(RamSize) ? RamSize : 4M; RamSize = DEFINED(RamSize) ? RamSize : 4M;
/* /*
* Set the amount of RAM to be used for the application heap. Objects * Set the amount of RAM to be used for the application heap. Objects
@ -134,7 +135,7 @@ $BSP340_ROOT/startup/linkcmds.
* *
* NOTE 3: The GNAT/RTEMS run-time requires additional memory in * NOTE 3: The GNAT/RTEMS run-time requires additional memory in
* the Heap. * the Heap.
\*/ */
HeapSize = DEFINED(HeapSize) ? HeapSize : 0x10000; HeapSize = DEFINED(HeapSize) ? HeapSize : 0x10000;
/* /*
* Set the size of the starting stack used during BSP initialization * Set the size of the starting stack used during BSP initialization
@ -142,7 +143,7 @@ $BSP340_ROOT/startup/linkcmds.
* by RTEMS are used. * by RTEMS are used.
* *
* NOTE: The default may be overridden by passing an argument to ld. * NOTE: The default may be overridden by passing an argument to ld.
\*/ */
StackSize = DEFINED(StackSize) ? StackSize : 0x1000; StackSize = DEFINED(StackSize) ? StackSize : 0x1000;
/* /*
* Starting addresses and length of RAM and ROM. * Starting addresses and length of RAM and ROM.
@ -150,7 +151,7 @@ $BSP340_ROOT/startup/linkcmds.
* The addresses must be valid addresses on the board. The * The addresses must be valid addresses on the board. The
* Chip Selects should be initialized such that the code addresses * Chip Selects should be initialized such that the code addresses
* are valid. * are valid.
\*/ */
MEMORY { MEMORY {
ram : ORIGIN = 0x10000000, LENGTH = 4M ram : ORIGIN = 0x10000000, LENGTH = 4M
rom : ORIGIN = 0x01000000, LENGTH = 4M rom : ORIGIN = 0x01000000, LENGTH = 4M
@ -158,7 +159,7 @@ $BSP340_ROOT/startup/linkcmds.
/* /*
* This is for the network driver. See the Networking documentation * This is for the network driver. See the Networking documentation
* for more details. * for more details.
\*/ */
ETHERNET_ADDRESS = ETHERNET_ADDRESS =
DEFINED(ETHERNET_ADDRESS) ? ETHERNET_ADDRESS : 0xDEAD12; DEFINED(ETHERNET_ADDRESS) ? ETHERNET_ADDRESS : 0xDEAD12;
/* /*
@ -170,73 +171,73 @@ $BSP340_ROOT/startup/linkcmds.
* ensure that the variable is accessible from C code with a * ensure that the variable is accessible from C code with a
* single underscore. Some object formats automatically add * single underscore. Some object formats automatically add
* a leading underscore to all C global symbols. * a leading underscore to all C global symbols.
\*/ */
SECTIONS { SECTIONS {
/* /*
* Make the RomBase variable available to the application. * Make the RomBase variable available to the application.
\*/ */
_RamSize = RamSize; _RamSize = RamSize;
__RamSize = RamSize; __RamSize = RamSize;
/* /*
* Boot PROM - Set the RomBase variable to the start of the ROM. * Boot PROM - Set the RomBase variable to the start of the ROM.
\*/ */
rom : { rom : {
_RomBase = .; _RomBase = .;
__RomBase = .; __RomBase = .;
} >rom } >rom
/* /*
* Dynamic RAM - set the RamBase variable to the start of the RAM. * Dynamic RAM - set the RamBase variable to the start of the RAM.
\*/ */
ram : { ram : {
_RamBase = .; _RamBase = .;
__RamBase = .; __RamBase = .;
} >ram } >ram
/* /*
* Text (code) goes into ROM * Text (code) goes into ROM
\*/ */
.text : { .text : {
/* /*
* Create a symbol for each object (.o). * Create a symbol for each object (.o).
\*/ */
CREATE_OBJECT_SYMBOLS CREATE_OBJECT_SYMBOLS
/* /*
* Put all the object files code sections here. * Put all the object files code sections here.
\*/ */
\*(.text) *(.text)
. = ALIGN (16); /* go to a 16-byte boundary \*/ . = ALIGN (16); /* go to a 16-byte boundary */
/* /*
* C++ constructors and destructors * C++ constructors and destructors
* *
* NOTE: See the CROSSGCC mailing-list FAQ for * NOTE: See the CROSSGCC mailing-list FAQ for
* more details about the "\[......]". * more details about the "\[......]".
\*/ */
__CTOR_LIST__ = .; __CTOR_LIST__ = .;
\[......] [......]
__DTOR_END__ = .; __DTOR_END__ = .;
/* /*
* Declares where the .text section ends. * Declares where the .text section ends.
\*/ */
etext = .; etext = .;
_etext = .; _etext = .;
} >rom } >rom
/* /*
* Exception Handler Frame section * Exception Handler Frame section
\*/ */
.eh_fram : { .eh_fram : {
. = ALIGN (16); . = ALIGN (16);
\*(.eh_fram) *(.eh_fram)
} >ram } >ram
/* /*
* GCC Exception section * GCC Exception section
\*/ */
.gcc_exc : { .gcc_exc : {
. = ALIGN (16); . = ALIGN (16);
\*(.gcc_exc) *(.gcc_exc)
} >ram } >ram
/* /*
* Special variable to let application get to the dual-ported * Special variable to let application get to the dual-ported
* memory. * memory.
\*/ */
dpram : { dpram : {
m340 = .; m340 = .;
_m340 = .; _m340 = .;
@ -244,47 +245,47 @@ $BSP340_ROOT/startup/linkcmds.
} >ram } >ram
/* /*
* Initialized Data section goes in RAM * Initialized Data section goes in RAM
\*/ */
.data : { .data : {
copy_start = .; copy_start = .;
\*(.data) *(.data)
. = ALIGN (16); . = ALIGN (16);
_edata = .; _edata = .;
copy_end = .; copy_end = .;
} >ram } >ram
/* /*
* Uninitialized Data section goes in ROM * Uninitialized Data section goes in ROM
\*/ */
.bss : { .bss : {
/* /*
* M68K specific: Reserve some room for the Vector Table * M68K specific: Reserve some room for the Vector Table
* (256 vectors of 4 bytes). * (256 vectors of 4 bytes).
\*/ */
M68Kvec = .; M68Kvec = .;
_M68Kvec = .; _M68Kvec = .;
. += (256 * 4); . += (256 * 4);
/* /*
* Start of memory to zero out at initialization time. * Start of memory to zero out at initialization time.
\*/ */
clear_start = .; clear_start = .;
/* /*
* Put all the object files uninitialized data sections * Put all the object files uninitialized data sections
* here. * here.
\*/ */
\*(.bss) *(.bss)
\*(COMMON) *(COMMON)
. = ALIGN (16); . = ALIGN (16);
_end = .; _end = .;
/* /*
* Start of the Application Heap * Start of the Application Heap
\*/ */
_HeapStart = .; _HeapStart = .;
__HeapStart = .; __HeapStart = .;
. += HeapSize; . += HeapSize;
/* /*
* The Starting Stack goes after the Application Heap. * The Starting Stack goes after the Application Heap.
* M68K stack grows down so start at high address. * M68K stack grows down so start at high address.
\*/ */
. += StackSize; . += StackSize;
. = ALIGN (16); . = ALIGN (16);
stack_init = .; stack_init = .;
@ -293,76 +294,66 @@ $BSP340_ROOT/startup/linkcmds.
* The RTEMS Executive Workspace goes here. RTEMS * The RTEMS Executive Workspace goes here. RTEMS
* allocates tasks, stacks, semaphores, etc. from this * allocates tasks, stacks, semaphores, etc. from this
* memory. * memory.
\*/ */
_WorkspaceBase = .; _WorkspaceBase = .;
__WorkspaceBase = .; __WorkspaceBase = .;
} >ram } >ram
}
Initialized Data Initialized Data
================ ================
Now there's a problem with the initialized data: the ``.data`` section Now there's a problem with the initialized data: the ``.data`` section has to
has to be in RAM as this data may be modified during the program execution. be in RAM as this data may be modified during the program execution. But how
But how will the values be initialized at boot time? will the values be initialized at boot time?
One approach is to place the entire program image in RAM and reload One approach is to place the entire program image in RAM and reload the image
the image in its entirety each time the program is run. This is fine in its entirety each time the program is run. This is fine for use in a debug
for use in a debug environment where a high-speed connection is available environment where a high-speed connection is available between the development
between the development host computer and the target. But even in this host computer and the target. But even in this environment, it is cumbersome.
environment, it is cumbersome.
The solution is to place a copy of the initialized data in a separate The solution is to place a copy of the initialized data in a separate area of
area of memory and copy it into the proper location each time the memory and copy it into the proper location each time the program is started.
program is started. It is common practice to place a copy of the initialized ``.data`` section at the end of the code (``.text``) section It is common practice to place a copy of the initialized ``.data`` section at
in ROM when building a PROM image. The GNU tool ``objcopy`` the end of the code (``.text``) section in ROM when building a PROM image. The
can be used for this purpose. GNU tool ``objcopy`` can be used for this purpose.
The following figure illustrates the steps a linked program goes through The following figure illustrates the steps a linked program goes through
to become a downloadable image. to become a downloadable image.
+--------------+------+--------------------------+--------------------+
| .data (RAM) | | .data (RAM) | |
+--------------+ +--------------------------+ |
| .bss (RAM) | | .bss (RAM) | |
+--------------+ +--------------------------+--------------------+
| .text (ROM) | | .text (ROM) | .text |
+--------------+------+---------+----------+-----+--------------------+
| copy of .data (ROM) | | copy of .data | |
+---------------------+---------+----------------+--------------------+
| Step 1 | Step 2 | Step 3 |
+---------------------+--------------------------+--------------------+
+--------------+-----+--------------------+--------------------------+
| .data RAM | | .data RAM | |
+--------------+ +--------------------+ |
| .bss RAM | | .bss RAM | |
+--------------+ +--------------------+-----+--------------------+
| .text ROM | | .text ROM | | .text |
+--------------+-----+---------+----------+-----+--------------------+
| copy of .data ROM | | copy of .data | |
+--------------------+---------+----------------+--------------------+
| Step 1 |Step 2 Step 3 |
+--------------------+--------------------------+--------------------+
In Step 1, the program is linked together using the BSP linker script. In Step 1, the program is linked together using the BSP linker script.
In Step 2, a copy is made of the ``.data`` section and placed In Step 2, a copy is made of the ``.data`` section and placed after the
after the ``.text`` section so it can be placed in PROM. This step ``.text`` section so it can be placed in PROM. This step is done after the
is done after the linking time. There is an example linking time. There is an example of doing this in the file
of doing this in the file $RTEMS_ROOT/make/custom/gen68340.cfg: $RTEMS_ROOT/make/custom/gen68340.cfg:
.. code:: c
.. code-block:: shell
# make a PROM image using objcopy # make a PROM image using objcopy
m68k-rtems-objcopy \\ m68k-rtems-objcopy --adjust-section-vma \
--adjust-section-vma .data= \\ .data=`m68k-rtems-objdump --section-headers $(basename $@).exe | awk '[...]'` \
\`m68k-rtems-objdump --section-headers \\
$(basename $@).exe \\
| awk '\[...]` \\
$(basename $@).exe $(basename $@).exe
NOTE: The address of the "copy of ``.data`` section" is .. note::
created by extracting the last address in the ``.text``
section with an ``awk`` script. The details of how
this is done are not relevant.
Step 3 shows the final executable image as it logically appears in The address of the "copy of ``.data`` section" is created by extracting the
the target's non-volatile program memory. The board initialization last address in the ``.text`` section with an ``awk`` script. The details
code will copy the ""copy of ``.data`` section" (which are stored in of how this is done are not relevant.
ROM) to their reserved location in RAM.
.. COMMENT: COPYRIGHT (c) 1988-2011.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Step 3 shows the final executable image as it logically appears in the target's
non-volatile program memory. The board initialization code will copy the
""copy of ``.data`` section" (which are stored in ROM) to their reserved
location in RAM.

View File

@ -1,169 +1,169 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Makefiles Makefiles
######### #########
This chapter discusses the Makefiles associated with a BSP. It does not This chapter discusses the Makefiles associated with a BSP. It does not
describe the process of configuring, building, and installing RTEMS. describe the process of configuring, building, and installing RTEMS. This
This chapter will not provide detailed information about this process. chapter will not provide detailed information about this process. Nonetheless,
Nonetheless, it is important to remember that the general process consists it is important to remember that the general process consists of four phases as
of four phases as shown here: shown here:
- .. code:: c - ``bootstrap``
bootstrap - ``configure``
- .. code:: c - ``build``
configure - ``install``
- .. code:: c During the bootstrap phase, you are using the ``configure.ac`` and
``Makefile.am`` files as input to GNU autoconf and automake to generate a
variety of files. This is done by running the ``bootstrap`` script found at
the top of the RTEMS source tree.
build During the configure phase, a number of files are generated. These generated
files are tailored for the specific host/target combination by the configure
script. This set of files includes the Makefiles used to actually compile and
install RTEMS.
- .. code:: c During the build phase, the source files are compiled into object files and
libraries are built.
install During the install phase, the libraries, header files, and other support files
are copied to the BSP specific installation point. After installation is
During the bootstrap phase, you are using the ``configure.ac`` and``Makefile.am`` files as input to GNU autoconf and automake to successfully completed, the files generated by the configure and build phases
generate a variety of files. This is done by running the ``bootstrap`` may be removed.
script found at the top of the RTEMS source tree.
During the configure phase, a number of files are generated. These
generated files are tailored for the specific host/target combination
by the configure script. This set of files includes the Makefiles used
to actually compile and install RTEMS.
During the build phase, the source files are compiled into object files
and libraries are built.
During the install phase, the libraries, header files, and other support
files are copied to the BSP specific installation point. After installation
is successfully completed, the files generated by the configure and build
phases may be removed.
Makefiles Used During The BSP Building Process Makefiles Used During The BSP Building Process
============================================== ==============================================
RTEMS uses the *GNU automake* and *GNU autoconf* automatic RTEMS uses the *GNU automake* and *GNU autoconf* automatic configuration
configuration package. Consequently, there are a number of package. Consequently, there are a number of automatically generated files in
automatically generated files in each directory in the RTEMS each directory in the RTEMS source tree. The ``bootstrap`` script found in the
source tree. The ``bootstrap`` script found in the top level top level directory of the RTEMS source tree is executed to produce the
directory of the RTEMS source tree is executed to produce the automatically generated files. That script must be run from a directory with a
automatically generated files. That script must be run from ``configure.ac`` file in it. The ``bootstrap`` command is usually invoked in
a directory with a ``configure.ac`` file in it. The ``bootstrap`` one of the following manners:
command is usually invoked in one of the following manners:
- ``bootstrap`` to regenerate all files that are generated by - ``bootstrap`` to regenerate all files that are generated by autoconf and
autoconf and automake.
- ``bootstrap -c`` to remove all files generated by autoconf and
automake. automake.
- ``bootstrap -c`` to remove all files generated by autoconf and automake.
- ``bootstrap -p`` to regenerate ``preinstall.am`` files. - ``bootstrap -p`` to regenerate ``preinstall.am`` files.
There is a file named ``Makefile.am`` in each directory of There is a file named ``Makefile.am`` in each directory of a BSP. This file is
a BSP. This file is used by *automake* to produce the file named``Makefile.in`` which is also found in each directory of a BSP. used by *automake* to produce the file named ``Makefile.in`` which is also
When modifying a ``Makefile.am``, you can probably find examples of found in each directory of a BSP. When modifying a ``Makefile.am``, you can
anything you need to do in one of the BSPs. probably find examples of anything you need to do in one of the BSPs.
The configure process specializes the ``Makefile.in`` files at the time that RTEMS The configure process specializes the ``Makefile.in`` files at the time that
is configured for a specific development host and target. Makefiles RTEMS is configured for a specific development host and target. Makefiles are
are automatically generated from the ``Makefile.in`` files. It is automatically generated from the ``Makefile.in`` files. It is necessary for
necessary for the BSP developer to provide the ``Makefile.am`` the BSP developer to provide the ``Makefile.am`` files and generate the
files and generate the ``Makefile.in`` files. Most of the ``Makefile.in`` files. Most of the time, it is possible to copy the
time, it is possible to copy the ``Makefile.am`` from another ``Makefile.am`` from another similar directory and edit it.
similar directory and edit it.
The ``Makefile`` files generated are processed when configuring The ``Makefile`` files generated are processed when configuring and building
and building RTEMS for a given BSP. RTEMS for a given BSP.
The BSP developer is responsible for generating ``Makefile.am`` The BSP developer is responsible for generating ``Makefile.am`` files which
files which properly build all the files associated with their BSP. properly build all the files associated with their BSP. Most BSPs will only
Most BSPs will only have a single ``Makefile.am`` which details have a single ``Makefile.am`` which details the set of source files to build to
the set of source files to build to compose the BSP support library compose the BSP support library along with the set of include files that are to
along with the set of include files that are to be installed. be installed.
This single ``Makefile.am`` at the top of the BSP tree specifies This single ``Makefile.am`` at the top of the BSP tree specifies the set of
the set of header files to install. This fragment from the SPARC/ERC32 header files to install. This fragment from the SPARC/ERC32 BSP results in
BSP results in four header files being installed. four header files being installed.
.. code:: c
.. code-block:: makefile
include_HEADERS = include/bsp.h include_HEADERS = include/bsp.h
include_HEADERS += include/tm27.h include_HEADERS += include/tm27.h
include_HEADERS += include/erc32.h include_HEADERS += include/erc32.h
include_HEADERS += include/coverhd.h include_HEADERS += include/coverhd.h
When adding new include files, you will be adding to the set of``include_HEADERS``. When you finish editing the ``Makefile.am`` When adding new include files, you will be adding to the set of
file, do not forget to run ``bootstrap -p`` to regenerate the``preinstall.am``. ``include_HEADERS``. When you finish editing the ``Makefile.am`` file, do not
forget to run ``bootstrap -p`` to regenerate the ``preinstall.am``.
The ``Makefile.am`` also specifies which source files to build. The ``Makefile.am`` also specifies which source files to build. By convention,
By convention, logical components within the BSP each assign their logical components within the BSP each assign their source files to a unique
source files to a unique variable. These variables which define variable. These variables which define the source files are collected into a
the source files are collected into a single variable which instructs single variable which instructs the GNU autotools that we are building
the GNU autotools that we are building ``libbsp.a``. This fragment ``libbsp.a``. This fragment from the SPARC/ERC32 BSP shows how the startup
from the SPARC/ERC32 BSP shows how the startup related, miscellaneous related, miscellaneous support code, and the console device driver source is
support code, and the console device driver source is managed managed in the ``Makefile.am``.
in the ``Makefile.am``.
.. code:: c
startup_SOURCES = ../../sparc/shared/bspclean.c ../../shared/bsplibc.c \\ .. code-block:: makefile
../../shared/bsppredriverhook.c \\
../../shared/bsppost.c ../../sparc/shared/bspstart.c \\ startup_SOURCES = ../../sparc/shared/bspclean.c ../../shared/bsplibc.c \
../../shared/bootcard.c ../../shared/sbrk.c startup/setvec.c \\ ../../shared/bsppredriverhook.c \
../../shared/bsppost.c ../../sparc/shared/bspstart.c \
../../shared/bootcard.c ../../shared/sbrk.c startup/setvec.c \
startup/spurious.c startup/erc32mec.c startup/boardinit.S startup/spurious.c startup/erc32mec.c startup/boardinit.S
clock_SOURCES = clock/ckinit.c clock_SOURCES = clock/ckinit.c
... ...
noinst_LIBRARIES = libbsp.a noinst_LIBRARIES = libbsp.a
libbsp_a_SOURCES = $(startup_SOURCES) $(console_SOURCES) ... libbsp_a_SOURCES = $(startup_SOURCES) $(console_SOURCES) ...
When adding new files to an existing directory, do not forget to add When adding new files to an existing directory, do not forget to add the new
the new files to the list of files to be built in the corresponding``XXX_SOURCES`` variable in the ``Makefile.am`` and run``bootstrap``. files to the list of files to be built in the corresponding ``XXX_SOURCES``
variable in the ``Makefile.am`` and run``bootstrap``.
Some BSPs use code that is built in ``libcpu``. If you BSP does Some BSPs use code that is built in ``libcpu``. If you BSP does this, then you
this, then you will need to make sure the objects are pulled into your will need to make sure the objects are pulled into your BSP library. The
BSP library. The following from the SPARC/ERC32 BSP pulls in the cache, following from the SPARC/ERC32 BSP pulls in the cache, register window
register window management and system call support code from the directory management and system call support code from the directory corresponding to its
corresponding to its ``RTEMS_CPU`` model. ``RTEMS_CPU`` model.
.. code:: c
libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/cache.rel \\ .. code-block:: makefile
../../../libcpu/@RTEMS_CPU@/reg_win.rel \\
libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/cache.rel \
../../../libcpu/@RTEMS_CPU@/reg_win.rel \
../../../libcpu/@RTEMS_CPU@/syscall.rel ../../../libcpu/@RTEMS_CPU@/syscall.rel
*NOTE:* The ``Makefile.am`` files are ONLY processed by``bootstrap`` and the resulting ``Makefile.in`` files are only .. note:
processed during the configure process of a RTEMS build. Therefore,
when developing a BSP and adding a new file to a ``Makefile.am``, The ``Makefile.am`` files are ONLY processed by ``bootstrap`` and the resulting
the already generated ``Makefile`` will not automatically ``Makefile.in`` files are only processed during the configure process of a
include the new references unless you configured RTEMS with the``--enable-maintainer-mode`` option. Otherwise, the new file not RTEMS build. Therefore, when developing a BSP and adding a new file to a
being be taken into account! ``Makefile.am``, the already generated ``Makefile`` will not automatically
include the new references unless you configured RTEMS with the
``--enable-maintainer-mode`` option. Otherwise, the new file will not being be
taken into account!
Creating a New BSP Make Customization File Creating a New BSP Make Customization File
========================================== ==========================================
When building a BSP or an application using that BSP, it is necessary When building a BSP or an application using that BSP, it is necessary to tailor
to tailor the compilation arguments to account for compiler flags, use the compilation arguments to account for compiler flags, use custom linker
custom linker scripts, include the RTEMS libraries, etc.. The BSP scripts, include the RTEMS libraries, etc.. The BSP must be built using this
must be built using this information. Later, once the BSP is installed information. Later, once the BSP is installed with the toolset, this same
with the toolset, this same information must be used when building the information must be used when building the application. So a BSP must include
application. So a BSP must include a build configuration file. The a build configuration file. The configuration file is ``make/custom/BSP.cfg``.
configuration file is ``make/custom/BSP.cfg``.
The configuration file is taken into account when building one's The configuration file is taken into account when building one's application
application using the RTEMS template Makefiles (``make/templates``). using the RTEMS template Makefiles (``make/templates``). These application
These application template Makefiles have been included with the template Makefiles have been included with the RTEMS source distribution since
RTEMS source distribution since the early 1990's. However there is the early 1990's. However there is a desire in the RTEMS user community to
a desire in the RTEMS user community to move all provided examples to move all provided examples to GNU autoconf. They are included in the 4.9
GNU autoconf. They are included in the 4.9 release series and used for release series and used for all examples provided with RTEMS. There is no
all examples provided with RTEMS. There is no definite time table for definite time table for obsoleting them. You are free to use these but be
obsoleting them. You are free to use these but be warned they have warned they have fallen out of favor with many in the RTEMS community and may
fallen out of favor with many in the RTEMS community and may disappear disappear in the future.
in the future.
The following is a slightly shortened version of the make customization The following is a slightly shortened version of the make customization file
file for the gen68340 BSP. The original source for this file can be for the gen68340 BSP. The original source for this file can be found in the
found in the ``make/custom`` directory. ``make/custom`` directory.
.. code:: c
.. code-block:: makefile
# The RTEMS CPU Family and Model # The RTEMS CPU Family and Model
RTEMS_CPU=m68k RTEMS_CPU=m68k
@ -177,20 +177,12 @@ found in the ``make/custom`` directory.
# optimize flag: typically -O2 # optimize flag: typically -O2
CFLAGS_OPTIMIZE_V = -O2 -g -fomit-frame-pointer CFLAGS_OPTIMIZE_V = -O2 -g -fomit-frame-pointer
The make customization files have generally grown simpler and simpler The make customization files have generally grown simpler and simpler with each
with each RTEMS release. Beginning in the 4.9 release series, the rules RTEMS release. Beginning in the 4.9 release series, the rules for linking an
for linking an RTEMS application are shared by all BSPs. Only BSPs which RTEMS application are shared by all BSPs. Only BSPs which need to perform a
need to perform a transformation from linked ELF file to a downloadable transformation from linked ELF file to a downloadable format have any
format have any additional actions for program link time. In 4.8 and additional actions for program link time. In 4.8 and older, every BSP specified
older, every BSP specified the "make executable" or ``make-exe`` the "make executable" or ``make-exe`` rule and duplicated the same actions.
rule and duplicated the same actions.
It is generally easier to copy a ``make/custom`` file from a
BSP similar to the one being developed.
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
It is generally easier to copy a ``make/custom`` file from a BSP similar to the
one being developed.

View File

@ -1,70 +1,73 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Miscellaneous Support Files Miscellaneous Support Files
########################### ###########################
GCC Compiler Specifications File GCC Compiler Specifications File
================================ ================================
The file ``bsp_specs`` defines the start files and libraries The file ``bsp_specs`` defines the start files and libraries that are always
that are always used with this BSP. The format of this file used with this BSP. The format of this file is admittedly cryptic and this
is admittedly cryptic and this document will make no attempt document will make no attempt to explain it completely. Below is the
to explain it completely. Below is the ``bsp_specs`` ``bsp_specs`` file from the PowerPC psim BSP:
file from the PowerPC psim BSP:
.. code:: c .. code-block:: c
%rename endfile old_endfile %rename endfile old_endfile
%rename startfile old_startfile %rename startfile old_startfile
%rename link old_link %rename link old_link
\*startfile: *startfile:
%{!qrtems: %(old_startfile)} \\ %{!qrtems: %(old_startfile)} \
%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s start.o%s}} %{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s start.o%s}}
\*link: *link:
%{!qrtems: %(old_link)} %{qrtems: -Qy -dp -Bstatic -e _start -u __vectors} %{!qrtems: %(old_link)} %{qrtems: -Qy -dp -Bstatic -e _start -u __vectors}
\*endfile: *endfile:
%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} %{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s}
The first section of this file renames the built-in definition of The first section of this file renames the built-in definition of some
some specification variables so they can be augmented without specification variables so they can be augmented without embedded their
embedded their original definition. The subsequent sections original definition. The subsequent sections specify what behavior is expected
specify what behavior is expected when the ``-qrtems`` option is specified. when the ``-qrtems`` option is specified.
The ``*startfile`` section specifies that the BSP specific file``start.o`` will be used instead of ``crt0.o``. In addition, The ``*startfile`` section specifies that the BSP specific file ``start.o``
various EABI support files (``ecrti.o`` etc.) will be linked in with will be used instead of ``crt0.o``. In addition, various EABI support files
the executable. (``ecrti.o`` etc.) will be linked in with the executable.
The ``*link`` section adds some arguments to the linker when it is The ``*link`` section adds some arguments to the linker when it is invoked by
invoked by GCC to link an application for this BSP. GCC to link an application for this BSP.
The format of this file is specific to the GNU Compiler Suite. The The format of this file is specific to the GNU Compiler Suite. The argument
argument used to override and extend the compiler built-in specifications used to override and extend the compiler built-in specifications is available
is available in all recent GCC versions. The ``-specs`` option is in all recent GCC versions. The ``-specs`` option is present in all ``egcs``
present in all ``egcs`` distributions and ``gcc`` distributions distributions and ``gcc`` distributions starting with version 2.8.0.
starting with version 2.8.0.
README Files README Files
============ ============
Most BSPs provide one or more ``README`` files. Generally, there Most BSPs provide one or more ``README`` files. Generally, there is a
is a ``README`` file at the top of the BSP source. This file ``README`` file at the top of the BSP source. This file describes the board
describes the board and its hardware configuration, provides vendor and its hardware configuration, provides vendor information, local
information, local configuration information, information on downloading configuration information, information on downloading code to the board,
code to the board, debugging, etc.. The intent of this debugging, etc.. The intent of this file is to help someone begin to use the
file is to help someone begin to use the BSP faster. BSP faster.
A ``README`` file in a BSP subdirectory typically explains something A ``README`` file in a BSP subdirectory typically explains something about the
about the contents of that subdirectory in greater detail. For example, contents of that subdirectory in greater detail. For example, it may list the
it may list the documentation available for a particular peripheral documentation available for a particular peripheral controller and how to
controller and how to obtain that documentation. It may also explain some obtain that documentation. It may also explain some particularly cryptic part
particularly cryptic part of the software in that directory or provide of the software in that directory or provide rationale on the implementation.
rationale on the implementation.
times times
===== =====
This file contains the results of the RTEMS Timing Test Suite. It is This file contains the results of the RTEMS Timing Test Suite. It is in a
in a standard format so that results from one BSP can be easily compared standard format so that results from one BSP can be easily compared with those
with those of another target board. of another target board.
If a BSP supports multiple variants, then there may be multiple ``times`` If a BSP supports multiple variants, then there may be multiple ``times``
files. Usually these are named ``times.VARIANTn``. files. Usually these are named ``times.VARIANTn``.
@ -72,75 +75,74 @@ files. Usually these are named ``times.VARIANTn``.
Tools Subdirectory Tools Subdirectory
================== ==================
Some BSPs provide additional tools that aid in using the target board. Some BSPs provide additional tools that aid in using the target board. These
These tools run on the development host and are built as part of building tools run on the development host and are built as part of building the BSP.
the BSP. Most common is a script to automate running the RTEMS Test Suites Most common is a script to automate running the RTEMS Test Suites on the BSP.
on the BSP. Examples of this include: Examples of this include:
- ``powerpc/psim`` includes scripts to ease use of the simulator - ``powerpc/psim`` includes scripts to ease use of the simulator
- ``m68k/mvme162`` includes a utility to download across the - ``m68k/mvme162`` includes a utility to download across the VMEbus into target
VMEbus into target memory if the host is a VMEbus board in the same memory if the host is a VMEbus board in the same chasis.
chasis.
bsp.h Include File bsp.h Include File
================== ==================
The file ``include/bsp.h`` contains prototypes and definitions The file ``include/bsp.h`` contains prototypes and definitions specific to this
specific to this board. Every BSP is required to provide a ``bsp.h``. board. Every BSP is required to provide a ``bsp.h``. The best approach to
The best approach to writing a ``bsp.h`` is copying an existing one writing a ``bsp.h`` is copying an existing one as a starting point.
as a starting point.
Many ``bsp.h`` files provide prototypes of variables defined Many ``bsp.h`` files provide prototypes of variables defined in the linker
in the linker script (``linkcmds``). script (``linkcmds``).
tm27.h Include File tm27.h Include File
=================== ===================
The ``tm27`` test from the RTEMS Timing Test Suite is designed to measure the length of time required to vector to and return from an interrupt handler. This test requires some help from the BSP to know how to cause and manipulate the interrupt source used for this measurement. The following is a list of these: The ``tm27`` test from the RTEMS Timing Test Suite is designed to measure the
length of time required to vector to and return from an interrupt handler. This
test requires some help from the BSP to know how to cause and manipulate the
interrupt source used for this measurement. The following is a list of these:
- ``MUST_WAIT_FOR_INTERRUPT`` - modifies behavior of ``tm27``. - ``MUST_WAIT_FOR_INTERRUPT`` - modifies behavior of ``tm27``.
- ``Install_tm27_vector`` - installs the interrupt service - ``Install_tm27_vector`` - installs the interrupt service routine for the
routine for the Interrupt Benchmark Test (``tm27``). Interrupt Benchmark Test (``tm27``).
- ``Cause_tm27_intr`` - generates the interrupt source - ``Cause_tm27_intr`` - generates the interrupt source used in the Interrupt
used in the Interrupt Benchmark Test (``tm27``). Benchmark Test (``tm27``).
- ``Clear_tm27_intr`` - clears the interrupt source - ``Clear_tm27_intr`` - clears the interrupt source used in the Interrupt
used in the Interrupt Benchmark Test (``tm27``). Benchmark Test (``tm27``).
- ``Lower_tm27_intr`` - lowers the interrupt mask so the - ``Lower_tm27_intr`` - lowers the interrupt mask so the interrupt source used
interrupt source used in the Interrupt Benchmark Test (``tm27``) in the Interrupt Benchmark Test (``tm27``) can generate a nested interrupt.
can generate a nested interrupt.
All members of the Timing Test Suite are designed to run *WITHOUT* All members of the Timing Test Suite are designed to run *WITHOUT* the Clock
the Clock Device Driver installed. This increases the predictability Device Driver installed. This increases the predictability of the tests'
of the tests' execution as well as avoids occassionally including the execution as well as avoids occassionally including the overhead of a clock
overhead of a clock tick interrupt in the time reported. Because of tick interrupt in the time reported. Because of this it is sometimes possible
this it is sometimes possible to use the clock tick interrupt source to use the clock tick interrupt source as the source of this test interrupt.
as the source of this test interrupt. On other architectures, it is On other architectures, it is possible to directly force an interrupt to occur.
possible to directly force an interrupt to occur.
Calling Overhead File Calling Overhead File
===================== =====================
The file ``include/coverhd.h`` contains the overhead associated The file ``include/coverhd.h`` contains the overhead associated with invoking
with invoking each directive. This overhead consists of the execution each directive. This overhead consists of the execution time required to
time required to package the parameters as well as to execute the "jump to package the parameters as well as to execute the "jump to subroutine" and
subroutine" and "return from subroutine" sequence. The intent of this "return from subroutine" sequence. The intent of this file is to help separate
file is to help separate the calling overhead from the actual execution the calling overhead from the actual execution time of a directive. This file
time of a directive. This file is only used by the tests in the is only used by the tests in the RTEMS Timing Test Suite.
RTEMS Timing Test Suite.
The numbers in this file are obtained by running the "Timer Overhead"``tmoverhd`` test. The numbers in this file may be 0 and no The numbers in this file are obtained by running the "Timer
overhead is subtracted from the directive execution times reported by Overhead"``tmoverhd`` test. The numbers in this file may be 0 and no overhead
the Timing Suite. is subtracted from the directive execution times reported by the Timing Suite.
There is a shared implementation of ``coverhd.h`` which sets all of the
overhead constants to 0. On faster processors, this is usually the best
alternative for the BSP as the calling overhead is extremely small. This file
is located at:
There is a shared implementation of ``coverhd.h`` which sets all of
the overhead constants to 0. On faster processors, this is usually the
best alternative for the BSP as the calling overhead is extremely small.
This file is located at:
.. code:: c .. code:: c
c/src/lib/libbsp/shared/include/coverhd.h c/src/lib/libbsp/shared/include/coverhd.h
@ -148,20 +150,28 @@ This file is located at:
sbrk() Implementation sbrk() Implementation
===================== =====================
Although nearly all BSPs give all possible memory to the C Program Heap Although nearly all BSPs give all possible memory to the C Program Heap at
at initialization, it is possible for a BSP to configure the initial initialization, it is possible for a BSP to configure the initial size of the
size of the heap small and let it grow on demand. If the BSP wants heap small and let it grow on demand. If the BSP wants to dynamically extend
to dynamically extend the heap used by the C Library memory allocation the heap used by the C Library memory allocation routines (i.e. ``malloc``
routines (i.e. ``malloc`` family), then the``sbrk`` routine must family), then the``sbrk`` routine must be functional. The following is the
be functional. The following is the prototype for this routine: prototype for this routine:
.. code:: c .. code:: c
void * sbrk(size_t increment) void * sbrk(size_t increment)
The ``increment`` amount is based upon the ``sbrk_amount`` The ``increment`` amount is based upon the ``sbrk_amount`` parameter passed to
parameter passed to the ``bsp_libc_init`` during system initialization... index:: CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK the ``bsp_libc_init`` during system initialization.
If your BSP does not want to support dynamic heap extension, then you do not have to do anything special. However, if you want to support ``sbrk``, you must provide an implementation of this method and define ``CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK`` in ``bsp.h``. This informs ``rtems/confdefs.h`` to configure the Malloc Family Extensions which support ``sbrk``. .. index:: CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK
If your BSP does not want to support dynamic heap extension, then you do not
have to do anything special. However, if you want to support ``sbrk``, you
must provide an implementation of this method and define
``CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK`` in ``bsp.h``. This informs
``rtems/confdefs.h`` to configure the Malloc Family Extensions which support
``sbrk``.
bsp_fatal_extension() - Cleanup the Hardware bsp_fatal_extension() - Cleanup the Hardware
============================================ ============================================
@ -170,81 +180,83 @@ The ``bsp_fatal_extension()`` is an optional BSP specific initial extension
invoked once a fatal system state is reached. Most of the BSPs use the same invoked once a fatal system state is reached. Most of the BSPs use the same
shared version of ``bsp_fatal_extension()`` that does nothing or performs a shared version of ``bsp_fatal_extension()`` that does nothing or performs a
system reset. This implementation is located in the following file: system reset. This implementation is located in the following file:
.. code:: c .. code:: c
c/src/lib/libbsp/shared/bspclean.c c/src/lib/libbsp/shared/bspclean.c
The ``bsp_fatal_extension()`` routine can be used to return to a ROM The ``bsp_fatal_extension()`` routine can be used to return to a ROM monitor,
monitor, insure that interrupt sources are disabled, etc.. This routine is the insure that interrupt sources are disabled, etc.. This routine is the last
last place to ensure a clean shutdown of the hardware. The fatal source, place to ensure a clean shutdown of the hardware. The fatal source, internal
internal error indicator, and the fatal code arguments are available to error indicator, and the fatal code arguments are available to evaluate the
evaluate the fatal condition. All of the non-fatal shutdown sequences fatal condition. All of the non-fatal shutdown sequences ultimately pass their
ultimately pass their exit status to ``rtems_shutdown_executive`` and this exit status to ``rtems_shutdown_executive`` and this is what is passed to this
is what is passed to this routine in case the fatal source is routine in case the fatal source is ``RTEMS_FATAL_SOURCE_EXIT``.
RTEMS_FATAL_SOURCE_EXIT.
On some BSPs, it prints a message indicating that the application On some BSPs, it prints a message indicating that the application completed
completed execution and waits for the user to press a key before execution and waits for the user to press a key before resetting the board.
resetting the board. The PowerPC/gen83xx and PowerPC/gen5200 BSPs do The PowerPC/gen83xx and PowerPC/gen5200 BSPs do this when they are built to
this when they are built to support the FreeScale evaluation boards. support the FreeScale evaluation boards. This is convenient when using the
This is convenient when using the boards in a development environment boards in a development environment and may be disabled for production use.
and may be disabled for production use.
Configuration Macros Configuration Macros
==================== ====================
Each BSP can define macros in bsp.h which alter some of the the default configuration parameters in ``rtems/confdefs.h``. This section describes those macros: Each BSP can define macros in bsp.h which alter some of the the default
configuration parameters in ``rtems/confdefs.h``. This section describes those
macros:
- .. index:: CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK .. index:: CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK
``CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK`` must be defined if the - ``CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK`` must be defined if the BSP has proper
BSP has proper support for ``sbrk``. This is discussed in more detail support for ``sbrk``. This is discussed in more detail in the previous
in the previous section. section.
- .. index:: BSP_IDLE_TASK_BODY .. index:: BSP_IDLE_TASK_BODY
``BSP_IDLE_TASK_BODY`` may be defined to the entry point of a - ``BSP_IDLE_TASK_BODY`` may be defined to the entry point of a BSP specific
BSP specific IDLE thread implementation. This may be overridden if the IDLE thread implementation. This may be overridden if the application
application provides its own IDLE task implementation. provides its own IDLE task implementation.
- .. index:: BSP_IDLE_TASK_STACK_SIZE .. index:: BSP_IDLE_TASK_STACK_SIZE
``BSP_IDLE_TASK_STACK_SIZE`` may be defined to the desired - ``BSP_IDLE_TASK_STACK_SIZE`` may be defined to the desired default stack size
default stack size for the IDLE task as recommended when using this BSP. for the IDLE task as recommended when using this BSP.
- .. index:: BSP_INTERRUPT_STACK_SIZE .. index:: BSP_INTERRUPT_STACK_SIZE
``BSP_INTERRUPT_STACK_SIZE`` may be defined to the desired default interrupt stack size as recommended when using this BSP. This is sometimes required when the BSP developer has knowledge of stack intensive interrupt handlers. - ``BSP_INTERRUPT_STACK_SIZE`` may be defined to the desired default interrupt
stack size as recommended when using this BSP. This is sometimes required
when the BSP developer has knowledge of stack intensive interrupt handlers.
- .. index:: BSP_ZERO_WORKSPACE_AUTOMATICALLY .. index:: BSP_ZERO_WORKSPACE_AUTOMATICALLY
``BSP_ZERO_WORKSPACE_AUTOMATICALLY`` is defined when the BSP - ``BSP_ZERO_WORKSPACE_AUTOMATICALLY`` is defined when the BSP requires that
requires that RTEMS zero out the RTEMS C Program Heap at initialization. RTEMS zero out the RTEMS C Program Heap at initialization. If the memory is
If the memory is already zeroed out by a test sequence or boot ROM, already zeroed out by a test sequence or boot ROM, then the boot time can be
then the boot time can be reduced by not zeroing memory twice. reduced by not zeroing memory twice.
- .. index:: BSP_DEFAULT_UNIFIED_WORK_AREAS .. index:: BSP_DEFAULT_UNIFIED_WORK_AREAS
``BSP_DEFAULT_UNIFIED_WORK_AREAS`` is defined when the BSP - ``BSP_DEFAULT_UNIFIED_WORK_AREAS`` is defined when the BSP recommends that
recommends that the unified work areas configuration should always the unified work areas configuration should always be used. This is
be used. This is desirable when the BSP is known to always have very desirable when the BSP is known to always have very little RAM and thus
little RAM and thus saving memory by any means is desirable. saving memory by any means is desirable.
set_vector() - Install an Interrupt Vector set_vector() - Install an Interrupt Vector
========================================== ==========================================
On targets with Simple Vectored Interrupts, the BSP must provide On targets with Simple Vectored Interrupts, the BSP must provide an
an implementation of the ``set_vector`` routine. This routine is implementation of the ``set_vector`` routine. This routine is responsible for
responsible for installing an interrupt vector. It invokes the support installing an interrupt vector. It invokes the support routines necessary to
routines necessary to install an interrupt handler as either a "raw" install an interrupt handler as either a "raw" or an RTEMS interrupt handler.
or an RTEMS interrupt handler. Raw handlers bypass the RTEMS interrupt Raw handlers bypass the RTEMS interrupt structure and are responsible for
structure and are responsible for saving and restoring all their own saving and restoring all their own registers. Raw handlers are useful for
registers. Raw handlers are useful for handling traps, debug vectors, handling traps, debug vectors, etc.
etc..
The ``set_vector`` routine is a central place to perform interrupt The ``set_vector`` routine is a central place to perform interrupt controller
controller manipulation and encapsulate that information. It is usually manipulation and encapsulate that information. It is usually implemented as
implemented as follows: follows:
.. code:: c .. code:: c
@ -258,95 +270,95 @@ implemented as follows:
install the raw vector install the raw vector
else else
use rtems_interrupt_catch to install the vector use rtems_interrupt_catch to install the vector
perform any interrupt controller necessary to unmask perform any interrupt controller necessary to unmask the interrupt source
the interrupt source
return the previous handler return the previous handler
} }
*NOTE:* The i386, PowerPC and ARM ports use a Programmable .. note::
Interrupt Controller model which does not require the BSP to implement``set_vector``. BSPs for these architectures must provide a different
set of support routines. The i386, PowerPC and ARM ports use a Programmable Interrupt Controller
model which does not require the BSP to implement ``set_vector``. BSPs for
these architectures must provide a different set of support routines.
Interrupt Delay Profiling Interrupt Delay Profiling
========================= =========================
The RTEMS profiling needs support by the BSP for the interrupt delay times. In The RTEMS profiling needs support by the BSP for the interrupt delay times. In
case profiling is enabled via the RTEMS build configuration option``--enable-profiling`` (in this case the pre-processor symbol``RTEMS_PROFILING`` is defined) a BSP may provide data for the interrupt case profiling is enabled via the RTEMS build configuration option
delay times. The BSP can feed interrupt delay times with the``_Profiling_Update_max_interrupt_delay()`` function ``--enable-profiling`` (in this case the pre-processor symbol
(``#include <rtems/score/profiling.h>``). For an example please have a look ``RTEMS_PROFILING`` is defined) a BSP may provide data for the interrupt delay
at ``c/src/lib/libbsp/sparc/leon3/clock/ckinit.c``. times. The BSP can feed interrupt delay times with the
``_Profiling_Update_max_interrupt_delay()`` function (``#include
<rtems/score/profiling.h>``). For an example please have a look at
``c/src/lib/libbsp/sparc/leon3/clock/ckinit.c``.
Programmable Interrupt Controller API Programmable Interrupt Controller API
===================================== =====================================
A BSP can use the PIC API to install Interrupt Service Routines through A BSP can use the PIC API to install Interrupt Service Routines through a set
a set of generic methods. In order to do so, the header files of generic methods. In order to do so, the header files
libbsp/shared/include/irq-generic.h and libbsp/shared/include/irq-info.h libbsp/shared/include/irq-generic.h and ``libbsp/shared/include/irq-info.h``
must be included by the bsp specific irq.h file present in the include/ must be included by the bsp specific irq.h file present in the include/
directory. The irq.h acts as a BSP interrupt support configuration file which directory. The irq.h acts as a BSP interrupt support configuration file which
is used to define some important MACROS. It contains the declarations for is used to define some important MACROS. It contains the declarations for any
any required global functions like bsp_interrupt_dispatch(). Thus later on, required global functions like bsp_interrupt_dispatch(). Thus later on, every
every call to the PIC interface requires including <bsp/irq.h> call to the PIC interface requires including ``<bsp/irq.h>``
The generic interrupt handler table is intitalized by invoking the``bsp_interrupt_initialize()`` method from bsp_start() in the bspstart.c The generic interrupt handler table is intitalized by invoking the
file which sets up this table to store the ISR addresses, whose size is based ``bsp_interrupt_initialize()`` method from bsp_start() in the bspstart.c file
on the definition of macros, BSP_INTERRUPT_VECTOR_MIN & BSP_INTERRUPT_VECTOR_MAX which sets up this table to store the ISR addresses, whose size is based on the
in include/bsp.h definition of macros, ``BSP_INTERRUPT_VECTOR_MIN`` and
``BSP_INTERRUPT_VECTOR_MAX`` in include/bsp.h
For the generic handler table to properly function, some bsp specific code is For the generic handler table to properly function, some bsp specific code is
required, that should be present in irq/irq.c . The bsp-specific functions required required, that should be present in ``irq/irq.c``. The bsp-specific functions
to be writen by the BSP developer are : required to be writen by the BSP developer are :
- .. index:: bsp_interrupt_facility_initialize() .. index:: bsp_interrupt_facility_initialize()
``bsp_interrupt_facility_initialize()`` contains bsp specific interrupt - ``bsp_interrupt_facility_initialize()`` contains bsp specific interrupt
initialization code(Clear Pending interrupts by modifying registers, etc.). initialization code(Clear Pending interrupts by modifying registers, etc.).
This method is called from bsp_interrupt_initialize() internally while setting up This method is called from ``bsp_interrupt_initialize()`` internally while
the table. setting up the table.
- .. index:: bsp_interrupt_handler_default() .. index:: bsp_interrupt_handler_default()
``bsp_interrupt_handler_default()`` acts as a fallback handler when - ``bsp_interrupt_handler_default()`` acts as a fallback handler when no ISR
no ISR address has been provided corresponding to a vector in the table. address has been provided corresponding to a vector in the table.
- .. index:: bsp_interrupt_dispatch() .. index:: bsp_interrupt_dispatch()
``bsp_interrupt_dispatch()`` service the ISR by handling - ``bsp_interrupt_dispatch()`` service the ISR by handling any bsp specific
any bsp specific code & calling the generic method bsp_interrupt_handler_dispatch() code & calling the generic method ``bsp_interrupt_handler_dispatch()`` which
which in turn services the interrupt by running the ISR after looking it up in in turn services the interrupt by running the ISR after looking it up in the
the table. It acts as an entry to the interrupt switchboard, since the bsp table. It acts as an entry to the interrupt switchboard, since the bsp
branches to this function at the time of occurrence of an interrupt. branches to this function at the time of occurrence of an interrupt.
- .. index:: bsp_interrupt_vector_enable() .. index:: bsp_interrupt_vector_enable()
``bsp_interrupt_vector_enable()`` enables interrupts and is called in - ``bsp_interrupt_vector_enable()`` enables interrupts and is called in
irq-generic.c while setting up the table. irq-generic.c while setting up the table.
- .. index:: bsp_interrupt_vector_disable() .. index:: bsp_interrupt_vector_disable()
``bsp_interrupt_vector_disable()`` disables interrupts and is called in - ``bsp_interrupt_vector_disable()`` disables interrupts and is called in
irq-generic.c while setting up the table & during other important parts. irq-generic.c while setting up the table & during other important parts.
An interrupt handler is installed or removed with the help of the following functions : An interrupt handler is installed or removed with the help of the following functions :
.. code:: c .. code:: c
rtems_status_code rtems_interrupt_handler_install( /* returns status code \*/ rtems_status_code rtems_interrupt_handler_install( /* returns status code */
rtems_vector_number vector, /* interrupt vector \*/ rtems_vector_number vector, /* interrupt vector */
const char \*info, /* custom identification text \*/ const char *info, /* custom identification text */
rtems_option options, /* Type of Interrupt \*/ rtems_option options, /* Type of Interrupt */
rtems_interrupt_handler handler, /* interrupt handler \*/ rtems_interrupt_handler handler, /* interrupt handler */
void \*arg /* parameter to be passed to handler at the time of invocation \*/ void *arg /* parameter to be passed
to handler at the time of
invocation */
) )
rtems_status_code rtems_interrupt_handler_remove( /* returns status code \*/ rtems_status_code rtems_interrupt_handler_remove( /* returns status code */
rtems_vector_number vector, /* interrupt vector \*/ rtems_vector_number vector, /* interrupt vector */
rtems_interrupt_handler handler, /* interrupt handler \*/ rtems_interrupt_handler handler, /* interrupt handler */
void \*arg /* parameter to be passed to handler \*/ void *arg /* parameter to be passed to handler */
) )
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.

View File

@ -1,185 +1,183 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Networking Driver Networking Driver
################# #################
Introduction Introduction
============ ============
This chapter is intended to provide an introduction to the This chapter is intended to provide an introduction to the procedure for
procedure for writing RTEMS network device drivers. writing RTEMS network device drivers. The example code is taken from the
The example code is taken from the 'Generic 68360' network device 'Generic 68360' network device driver. The source code for this driver is
driver. The source code for this driver is located in the``c/src/lib/libbsp/m68k/gen68360/network`` directory in the RTEMS located in the ``c/src/lib/libbsp/m68k/gen68360/network`` directory in the
source code distribution. Having a copy of this driver at RTEMS source code distribution. Having a copy of this driver at hand when
hand when reading the following notes will help significantly. reading the following notes will help significantly.
.. sidebar:: *Legacy Networking Stack*
This docuemntation is for the legacy FreeBSD networking stack in the RTEMS
source tree.
Learn about the network device Learn about the network device
============================== ==============================
Before starting to write the network driver become completely Before starting to write the network driver become completely familiar with the
familiar with the programmer's view of the device. programmer's view of the device. The following points list some of the details
The following points list some of the details of the of the device that must be understood before a driver can be written.
device that must be understood before a driver can be written.
- Does the device use DMA to transfer packets to and from - Does the device use DMA to transfer packets to and from memory or does the
memory or does the processor have to processor have to copy packets to and from memory on the device?
copy packets to and from memory on the device?
- If the device uses DMA, is it capable of forming a single - If the device uses DMA, is it capable of forming a single outgoing packet
outgoing packet from multiple fragments scattered in separate from multiple fragments scattered in separate memory buffers?
memory buffers?
- If the device uses DMA, is it capable of chaining multiple - If the device uses DMA, is it capable of chaining multiple outgoing packets,
outgoing packets, or does each outgoing packet require or does each outgoing packet require intervention by the driver?
intervention by the driver?
- Does the device automatically pad short frames to the minimum - Does the device automatically pad short frames to the minimum 64 bytes or
64 bytes or does the driver have to supply the padding? does the driver have to supply the padding?
- Does the device automatically retry a transmission on detection - Does the device automatically retry a transmission on detection of a
of a collision? collision?
- If the device uses DMA, is it capable of buffering multiple - If the device uses DMA, is it capable of buffering multiple packets to
packets to memory, or does the receiver have to be restarted memory, or does the receiver have to be restarted after the arrival of each
after the arrival of each packet? packet?
- How are packets that are too short, too long, or received with - How are packets that are too short, too long, or received with CRC errors
CRC errors handled? Does the device automatically continue handled? Does the device automatically continue reception or does the driver
reception or does the driver have to intervene? have to intervene?
- How is the device Ethernet address set? How is the device - How is the device Ethernet address set? How is the device programmed to
programmed to accept or reject broadcast and multicast packets? accept or reject broadcast and multicast packets?
- What interrupts does the device generate? Does it generate an - What interrupts does the device generate? Does it generate an interrupt for
interrupt for each incoming packet, or only for packets received each incoming packet, or only for packets received without error? Does it
without error? Does it generate an interrupt for each packet generate an interrupt for each packet transmitted, or only when the transmit
transmitted, or only when the transmit queue is empty? What queue is empty? What happens when a transmit error is detected?
happens when a transmit error is detected?
In addition, some controllers have specific questions regarding In addition, some controllers have specific questions regarding board specific
board specific configuration. For example, the SONIC Ethernet configuration. For example, the SONIC Ethernet controller has a very
controller has a very configurable data bus interface. It can configurable data bus interface. It can even be configured for sixteen and
even be configured for sixteen and thirty-two bit data buses. This thirty-two bit data buses. This type of information should be obtained from
type of information should be obtained from the board vendor. the board vendor.
Understand the network scheduling conventions Understand the network scheduling conventions
============================================= =============================================
When writing code for the driver transmit and receive tasks, When writing code for the driver transmit and receive tasks, take care to
take care to follow the network scheduling conventions. All tasks follow the network scheduling conventions. All tasks which are associated with
which are associated with networking share various networking share various data structures and resources. To ensure the
data structures and resources. To ensure the consistency consistency of these structures the tasks execute only when they hold the
of these structures the tasks network semaphore (``rtems_bsdnet_semaphore``). The transmit and receive tasks
execute only when they hold the network semaphore (``rtems_bsdnet_semaphore``). must abide by this protocol. Be very careful to avoid 'deadly embraces' with
The transmit and receive tasks must abide by this protocol. Be very the other network tasks. A number of routines are provided to make it easier
careful to avoid 'deadly embraces' with the other network tasks. for the network driver code to conform to the network task scheduling
A number of routines are provided to make it easier for the network conventions.
driver code to conform to the network task scheduling conventions.
- ``void rtems_bsdnet_semaphore_release(void)`` - ``void rtems_bsdnet_semaphore_release(void)``
This function releases the network semaphore. This function releases the network semaphore. The network driver tasks must
The network driver tasks must call this function immediately before call this function immediately before making any blocking RTEMS request.
making any blocking RTEMS request.
- ``void rtems_bsdnet_semaphore_obtain(void)`` - ``void rtems_bsdnet_semaphore_obtain(void)``
This function obtains the network semaphore. This function obtains the network semaphore. If a network driver task has
If a network driver task has released the network semaphore to allow other released the network semaphore to allow other network-related tasks to run
network-related tasks to run while the task blocks, then this function must while the task blocks, then this function must be called to reobtain the
be called to reobtain the semaphore immediately after the return from the semaphore immediately after the return from the blocking RTEMS request.
blocking RTEMS request.
- ``rtems_bsdnet_event_receive(rtems_event_set, rtems_option, rtems_interval, rtems_event_set \*)`` - ``rtems_bsdnet_event_receive(rtems_event_set, rtems_option, rtems_interval,
The network driver task should call this function when it wishes to wait rtems_event_set *)``
for an event. This function releases the network semaphore, The network driver task should call this function when it wishes to wait for
calls ``rtems_event_receive`` to wait for the specified event an event. This function releases the network semaphore, calls
or events and reobtains the semaphore. ``rtems_event_receive`` to wait for the specified event or events and
The value returned is the value returned by the ``rtems_event_receive``. reobtains the semaphore. The value returned is the value returned by the
``rtems_event_receive``.
Network Driver Makefile Network Driver Makefile
======================= =======================
Network drivers are considered part of the BSD network package and as such Network drivers are considered part of the BSD network package and as such are
are to be compiled with the appropriate flags. This can be accomplished by to be compiled with the appropriate flags. This can be accomplished by adding
adding ``-D__INSIDE_RTEMS_BSD_TCPIP_STACK__`` to the ``command line``. ``-D__INSIDE_RTEMS_BSD_TCPIP_STACK__`` to the ``command line``. If the driver
If the driver is inside the RTEMS source tree or is built using the is inside the RTEMS source tree or is built using the RTEMS application
RTEMS application Makefiles, then adding the following line accomplishes Makefiles, then adding the following line accomplishes this:
this:
.. code:: c .. code-block:: makefile
DEFINES += -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ DEFINES += -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
This is equivalent to the following list of definitions. Early versions This is equivalent to the following list of definitions. Early versions of the
of the RTEMS BSD network stack required that all of these be defined. RTEMS BSD network stack required that all of these be defined.
.. code:: c .. code-block:: makefile
-D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS \\ -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS -DDIAGNOSTIC -DBOOTP_COMPAT
-DDIAGNOSTIC -DBOOTP_COMPAT
Defining these macros tells the network header files that the driver Defining these macros tells the network header files that the driver is to be
is to be compiled with extended visibility into the network stack. This compiled with extended visibility into the network stack. This is in sharp
is in sharp contrast to applications that simply use the network stack. contrast to applications that simply use the network stack. Applications do
Applications do not require this level of visibility and should stick not require this level of visibility and should stick to the portable
to the portable application level API. application level API.
As a direct result of being logically internal to the network stack, As a direct result of being logically internal to the network stack, network
network drivers use the BSD memory allocation routines This means, drivers use the BSD memory allocation routines This means, for example, that
for example, that malloc takes three arguments. See the SONIC malloc takes three arguments. See the SONIC device driver
device driver (``c/src/lib/libchip/network/sonic.c``) for an example (``c/src/lib/libchip/network/sonic.c``) for an example of this. Because of
of this. Because of this, network drivers should not include``<stdlib.h>``. Doing so will result in conflicting definitions this, network drivers should not include ``<stdlib.h>``. Doing so will result
of ``malloc()``. in conflicting definitions of ``malloc()``.
*Application level* code including network servers such as the FTP *Application level* code including network servers such as the FTP daemon are
daemon are *not* part of the BSD kernel network code and should not be *not* part of the BSD kernel network code and should not be compiled with the
compiled with the BSD network flags. They should include``<stdlib.h>`` and not define the network stack visibility BSD network flags. They should include ``<stdlib.h>`` and not define the
macros. network stack visibility macros.
Write the Driver Attach Function Write the Driver Attach Function
================================ ================================
The driver attach function is responsible for configuring the driver The driver attach function is responsible for configuring the driver and making
and making the connection between the network stack the connection between the network stack and the driver.
and the driver.
Driver attach functions take a pointer to an``rtems_bsdnet_ifconfig`` structure as their only argument. Driver attach functions take a pointer to an ``rtems_bsdnet_ifconfig``
and set the driver parameters based on the structure as their only argument. and set the driver parameters based on the
values in this structure. If an entry in the configuration values in this structure. If an entry in the configuration structure is zero
structure is zero the attach function chooses an the attach function chooses an appropriate default value for that parameter.
appropriate default value for that parameter.
The driver should then set up several fields in the ifnet structure The driver should then set up several fields in the ifnet structure in the
in the device-dependent data structure supplied and maintained by the driver: device-dependent data structure supplied and maintained by the driver:
``ifp->if_softc`` ``ifp->if_softc``
Pointer to the device-dependent data. The first entry Pointer to the device-dependent data. The first entry in the
in the device-dependent data structure must be an ``arpcom`` device-dependent data structure must be an ``arpcom`` structure.
structure.
``ifp->if_name`` ``ifp->if_name``
The name of the device. The network stack uses this string The name of the device. The network stack uses this string and the device
and the device number for device name lookups. The device name should number for device name lookups. The device name should be obtained from
be obtained from the ``name`` entry in the configuration structure. the ``name`` entry in the configuration structure.
``ifp->if_unit`` ``ifp->if_unit``
The device number. The network stack uses this number and the The device number. The network stack uses this number and the device name
device name for device name lookups. For example, if``ifp->if_name`` is '``scc``' and ``ifp->if_unit`` is '``1``', for device name lookups. For example, if ``ifp->if_name`` is ``scc`` and
the full device name would be '``scc1``'. The unit number should be ``ifp->if_unit`` is ``1``, the full device name would be ``scc1``. The
obtained from the 'name' entry in the configuration structure. unit number should be obtained from the ``name`` entry in the configuration
structure.
``ifp->if_mtu`` ``ifp->if_mtu``
The maximum transmission unit for the device. For Ethernet The maximum transmission unit for the device. For Ethernet devices this
devices this value should almost always be 1500. value should almost always be 1500.
``ifp->if_flags`` ``ifp->if_flags``
The device flags. Ethernet devices should set the flags The device flags. Ethernet devices should set the flags to
to ``IFF_BROADCAST|IFF_SIMPLEX``, indicating that the ``IFF_BROADCAST|IFF_SIMPLEX``, indicating that the device can broadcast
device can broadcast packets to multiple destinations packets to multiple destinations and does not receive and transmit at the
and does not receive and transmit at the same time. same time.
``ifp->if_snd.ifq_maxlen`` ``ifp->if_snd.ifq_maxlen``
The maximum length of the queue of packets waiting to be The maximum length of the queue of packets waiting to be sent to the
sent to the driver. This is normally set to ``ifqmaxlen``. driver. This is normally set to ``ifqmaxlen``.
``ifp->if_init`` ``ifp->if_init``
The address of the driver initialization function. The address of the driver initialization function.
@ -191,91 +189,92 @@ in the device-dependent data structure supplied and maintained by the driver:
The address of the driver ioctl function. The address of the driver ioctl function.
``ifp->if_output`` ``ifp->if_output``
The address of the output function. Ethernet devices The address of the output function. Ethernet devices should set this to
should set this to ``ether_output``. ``ether_output``.
RTEMS provides a function to parse the driver name in the RTEMS provides a function to parse the driver name in the configuration
configuration structure into a device name and unit number. structure into a device name and unit number.
.. code:: c
.. code-block:: c
int rtems_bsdnet_parse_driver_name ( int rtems_bsdnet_parse_driver_name (
const struct rtems_bsdnet_ifconfig \*config, const struct rtems_bsdnet_ifconfig *config,
char \**namep char **namep
); );
The function takes two arguments; a pointer to the configuration The function takes two arguments; a pointer to the configuration structure and
structure and a pointer to a pointer to a character. The function a pointer to a pointer to a character. The function parses the configuration
parses the configuration name entry, allocates memory for the driver name entry, allocates memory for the driver name, places the driver name in
name, places the driver name in this memory, sets the second argument this memory, sets the second argument to point to the name and returns the unit
to point to the name and returns the unit number. number. On error, a message is printed and ``-1`` is returned.
On error, a message is printed and -1 is returned.
Once the attach function has set up the above entries it must link the Once the attach function has set up the above entries it must link the driver
driver data structure onto the list of devices by data structure onto the list of devices by calling ``if_attach``. Ethernet
calling ``if_attach``. Ethernet devices should then devices should then call ``ether_ifattach``. Both functions take a pointer to
call ``ether_ifattach``. Both functions take a pointer to the the device's ``ifnet`` structure as their only argument.
device's ``ifnet`` structure as their only argument.
The attach function should return a non-zero value to indicate that The attach function should return a non-zero value to indicate that the driver
the driver has been successfully configured and attached. has been successfully configured and attached.
Write the Driver Start Function. Write the Driver Start Function.
================================ ================================
This function is called each time the network stack wants to start the This function is called each time the network stack wants to start the
transmitter. This occures whenever the network stack adds a packet transmitter. This occures whenever the network stack adds a packet to a
to a device's send queue and the ``IFF_OACTIVE`` bit in the device's send queue and the ``IFF_OACTIVE`` bit in the device's ``if_flags`` is
device's ``if_flags`` is not set. not set.
For many devices this function need only set the ``IFF_OACTIVE`` bit in the``if_flags`` and send an event to the transmit task For many devices this function need only set the ``IFF_OACTIVE`` bit in the
indicating that a packet is in the driver transmit queue. ``if_flags`` and send an event to the transmit task indicating that a packet is
in the driver transmit queue.
Write the Driver Initialization Function. Write the Driver Initialization Function.
========================================= =========================================
This function should initialize the device, attach to interrupt handler, This function should initialize the device, attach to interrupt handler, and
and start the driver transmit and receive tasks. The function start the driver transmit and receive tasks. The function:
.. code:: c
rtems_id .. code-block:: c
rtems_bsdnet_newproc (char \*name,
rtems_id rtems_bsdnet_newproc(
char *name,
int stacksize, int stacksize,
void(\*entry)(void \*), void (*entry)(void *),
void \*arg); void *arg
);
should be used to start the driver tasks. should be used to start the driver tasks.
Note that the network stack may call the driver initialization function more Note that the network stack may call the driver initialization function more
than once. than once. Make sure multiple versions of the receive and transmit tasks are
Make sure multiple versions of the receive and transmit tasks are not accidentally not accidentally started.
started.
Write the Driver Transmit Task Write the Driver Transmit Task
============================== ==============================
This task is reponsible for removing packets from the driver send queue and sending them to the device. The task should block waiting for an event from the This task is reponsible for removing packets from the driver send queue and
driver start function indicating that packets are waiting to be transmitted. sending them to the device. The task should block waiting for an event from
When the transmit task has drained the driver send queue the task should clear the driver start function indicating that packets are waiting to be
the ``IFF_OACTIVE`` bit in ``if_flags`` and block until another outgoing transmitted. When the transmit task has drained the driver send queue the task
packet is queued. should clear the ``IFF_OACTIVE`` bit in ``if_flags`` and block until another
outgoing packet is queued.
Write the Driver Receive Task Write the Driver Receive Task
============================= =============================
This task should block until a packet arrives from the device. If the This task should block until a packet arrives from the device. If the device
device is an Ethernet interface the function ``ether_input`` should be called is an Ethernet interface the function ``ether_input`` should be called to
to forward the packet to the network stack. The arguments to ``ether_input`` forward the packet to the network stack. The arguments to ``ether_input`` are
are a pointer to the interface data structure, a pointer to the ethernet a pointer to the interface data structure, a pointer to the ethernet header and
header and a pointer to an mbuf containing the packet itself. a pointer to an mbuf containing the packet itself.
Write the Driver Interrupt Handler Write the Driver Interrupt Handler
================================== ==================================
A typical interrupt handler will do nothing more than the hardware A typical interrupt handler will do nothing more than the hardware manipulation
manipulation required to acknowledge the interrupt and send an RTEMS event required to acknowledge the interrupt and send an RTEMS event to wake up the
to wake up the driver receive or transmit task waiting for the event. driver receive or transmit task waiting for the event. Network interface
Network interface interrupt handlers must not make any calls to other interrupt handlers must not make any calls to other network routines.
network routines.
Write the Driver IOCTL Function Write the Driver IOCTL Function
=============================== ===============================
@ -283,44 +282,29 @@ Write the Driver IOCTL Function
This function handles ioctl requests directed at the device. The ioctl This function handles ioctl requests directed at the device. The ioctl
commands which must be handled are: commands which must be handled are:
``SIOCGIFADDR`` ``SIOCGIFADDR``, ``SIOCSIFADDR``
If the device is an Ethernet interface these commands should be passed on
``SIOCSIFADDR`` to ``ether_ioctl``.
If the device is an Ethernet interface these
commands should be passed on to ``ether_ioctl``.
``SIOCSIFFLAGS`` ``SIOCSIFFLAGS``
This command should be used to start or stop the device, depending on the
This command should be used to start or stop the device, state of the interface ``IFF_UP`` and``IFF_RUNNING`` bits in ``if_flags``:
depending on the state of the interface ``IFF_UP`` and``IFF_RUNNING`` bits in ``if_flags``:
``IFF_RUNNING`` ``IFF_RUNNING``
Stop the device. Stop the device.
``IFF_UP`` ``IFF_UP``
Start the device. Start the device.
``IFF_UP|IFF_RUNNING`` ``IFF_UP|IFF_RUNNING``
Stop then start the device. Stop then start the device.
``0`` ``0``
Do nothing. Do nothing.
Write the Driver Statistic-Printing Function Write the Driver Statistic-Printing Function
============================================ ============================================
This function should print the values of any statistic/diagnostic This function should print the values of any statistic/diagnostic counters the
counters the network driver may use. The driver ioctl function should call network driver may use. The driver ioctl function should call the
the statistic-printing function when the ioctl command is``SIO_RTEMS_SHOW_STATS``. statistic-printing function when the ioctl command is ``SIO_RTEMS_SHOW_STATS``.
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.

View File

@ -1,12 +1,16 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: Written by Eric Norum
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Non-Volatile Memory Driver Non-Volatile Memory Driver
########################## ##########################
The Non-Volatile driver is responsible for providing an The Non-Volatile driver is responsible for providing an interface to various
interface to various types of non-volatile memory. These types of non-volatile memory. These types of memory include, but are not
types of memory include, but are not limited to, Flash, EEPROM, limited to, Flash, EEPROM, and battery backed RAM. The capabilities provided
and battery backed RAM. The capabilities provided
by this class of device driver are: by this class of device driver are:
- Initialize the Non-Volatile Memory Driver - Initialize the Non-Volatile Memory Driver
@ -23,72 +27,66 @@ by this class of device driver are:
- Erase the Non-Volatile Memory Area - Erase the Non-Volatile Memory Area
There is currently only one non-volatile device driver included in the There is currently only one non-volatile device driver included in the RTEMS
RTEMS source tree. The information provided in this chapter source tree. The information provided in this chapter is based on drivers
is based on drivers developed for applications using RTEMS. developed for applications using RTEMS. It is hoped that this driver model
It is hoped that this driver model information can form the information can form the basis for a standard non-volatile memory driver model
basis for a standard non-volatile memory driver model that that can be supported in future RTEMS distribution.
can be supported in future RTEMS distribution.
Major and Minor Numbers Major and Minor Numbers
======================= =======================
The *major* number of a device driver is its index in the The ``major`` number of a device driver is its index in the RTEMS Device
RTEMS Device Address Table. Address Table.
A *minor* number is associated with each device instance A ``minor`` number is associated with each device instance managed by a
managed by a particular device driver. An RTEMS minor number particular device driver. An RTEMS minor number is an ``unsigned32`` entity.
is an ``unsigned32`` entity. Convention calls Convention calls dividing the bits in the minor number down into categories
dividing the bits in the minor number down into categories that specify an area of non-volatile memory and a partition with that area.
that specify an area of non-volatile memory and a partition This results in categories like the following:
with that area. This results in categories
like the following:
- *area* - indicates a block of non-volatile memory - ``area`` - indicates a block of non-volatile memory
- *partition* - indicates a particular address range with an area - ``partition`` - indicates a particular address range with an area
From the above, it should be clear that a single device driver From the above, it should be clear that a single device driver can support
can support multiple types of non-volatile memory in a single system. multiple types of non-volatile memory in a single system. The minor number is
The minor number is used to distinguish the types of memory and used to distinguish the types of memory and blocks of memory used for different
blocks of memory used for different purposes. purposes.
Non-Volatile Memory Driver Configuration Non-Volatile Memory Driver Configuration
======================================== ========================================
There is not a standard non-volatile driver configuration table but some There is not a standard non-volatile driver configuration table but some fields
fields are common across different drivers. The non-volatile memory driver are common across different drivers. The non-volatile memory driver
configuration table is typically an array of structures with each configuration table is typically an array of structures with each structure
structure containing the information for a particular area of containing the information for a particular area of non-volatile memory. The
non-volatile memory. following is a list of the type of information normally required to configure
The following is a list of the type of information normally required each area of non-volatile memory.
to configure each area of non-volatile memory.
*memory_type* ``memory_type``
is the type of memory device in this area. Choices are battery backed RAM, is the type of memory device in this area. Choices are battery backed RAM,
EEPROM, Flash, or an optional user-supplied type. If the user-supplied type EEPROM, Flash, or an optional user-supplied type. If the user-supplied
is configured, then the user is responsible for providing a set of type is configured, then the user is responsible for providing a set of
routines to program the memory. routines to program the memory.
*memory* ``memory``
is the base address of this memory area. is the base address of this memory area.
*attributes* ``attributes``
is a pointer to a memory type specific attribute block. Some of is a pointer to a memory type specific attribute block. Some of the fields
the fields commonly contained in this memory type specific attribute commonly contained in this memory type specific attribute structure area:
structure area:
*use_protection_algorithm*
``use_protection_algorithm``
is set to TRUE to indicate that the protection (i.e. locking) algorithm is set to TRUE to indicate that the protection (i.e. locking) algorithm
should be used for this area of non-volatile memory. A particular should be used for this area of non-volatile memory. A particular type
type of non-volatile memory may not have a protection algorithm. of non-volatile memory may not have a protection algorithm.
*access*
``access``
is an enumerated type to indicate the organization of the memory is an enumerated type to indicate the organization of the memory
devices in this memory area. The following is a list of the devices in this memory area. The following is a list of the access
access types supported by the current driver implementation: types supported by the current driver implementation:
- simple unsigned8 - simple unsigned8
- simple unsigned16 - simple unsigned16
- simple unsigned32 - simple unsigned32
@ -100,53 +98,48 @@ to configure each area of non-volatile memory.
- single unsigned8 at offset 2 in an unsigned32 - single unsigned8 at offset 2 in an unsigned32
- single unsigned8 at offset 3 in an unsigned32 - single unsigned8 at offset 3 in an unsigned32
*depth* ``depth``
is the depth of the progamming FIFO on this particular chip. Some is the depth of the progamming FIFO on this particular chip. Some
chips, particularly EEPROMs, have the same programming algorithm but chips, particularly EEPROMs, have the same programming algorithm but
vary in the depth of the amount of data that can be programmed in a single vary in the depth of the amount of data that can be programmed in a
block. single block.
*number_of_partitions* ``number_of_partitions``
is the number of logical partitions within this area. is the number of logical partitions within this area.
*Partitions* ``Partitions``
is the address of the table that contains an entry to describe each is the address of the table that contains an entry to describe each
partition in this area. Fields within each element of this partition in this area. Fields within each element of this table are
table are defined as follows: defined as follows:
*offset*
``offset``
is the offset of this partition from the base address of this area. is the offset of this partition from the base address of this area.
*length* ``length``
is the length of this partition. is the length of this partition.
By dividing an area of memory into multiple partitions, it is possible By dividing an area of memory into multiple partitions, it is possible to
to easily divide the non-volatile memory for different purposes. easily divide the non-volatile memory for different purposes.
Initialize the Non-Volatile Memory Driver Initialize the Non-Volatile Memory Driver
========================================= =========================================
At system initialization, the non-volatile memory driver's At system initialization, the non-volatile memory driver's initialization entry
initialization entry point will be invoked. As part of point will be invoked. As part of initialization, the driver will perform
initialization, the driver will perform
whatever initializatin is required on each non-volatile memory area. whatever initializatin is required on each non-volatile memory area.
The discrete I/O driver may register device names for memory The discrete I/O driver may register device names for memory partitions of
partitions of particular interest to the system. Normally this particular interest to the system. Normally this will be restricted to the
will be restricted to the device "/dev/nv_memory" to indicate device "/dev/nv_memory" to indicate the entire device driver.
the entire device driver.
Disable Read and Write Handlers Disable Read and Write Handlers
=============================== ===============================
Depending on the target's non-volatile memory configuration, it may be Depending on the target's non-volatile memory configuration, it may be possible
possible to write to a status register and make the memory area completely to write to a status register and make the memory area completely inaccessible.
inaccessible. This is target dependent and beyond the standard capabilities This is target dependent and beyond the standard capabilities of any memory
of any memory type. The user has the optional capability to provide type. The user has the optional capability to provide handlers to disable and
handlers to disable and enable access to a partiticular memory area. enable access to a partiticular memory area.
Open a Particular Memory Partition Open a Particular Memory Partition
================================== ==================================
@ -155,8 +148,8 @@ This is the driver open call. Usually this call does nothing other than
validate the minor number. validate the minor number.
With some drivers, it may be necessary to allocate memory when a particular With some drivers, it may be necessary to allocate memory when a particular
device is opened. If that is the case, then this is often the place device is opened. If that is the case, then this is often the place to do this
to do this operation. operation.
Close a Particular Memory Partition Close a Particular Memory Partition
=================================== ===================================
@ -164,30 +157,29 @@ Close a Particular Memory Partition
This is the driver close call. Usually this call does nothing. This is the driver close call. Usually this call does nothing.
With some drivers, it may be necessary to allocate memory when a particular With some drivers, it may be necessary to allocate memory when a particular
device is opened. If that is the case, then this is the place device is opened. If that is the case, then this is the place where that
where that memory should be deallocated. memory should be deallocated.
Read from a Particular Memory Partition Read from a Particular Memory Partition
======================================= =======================================
This corresponds to the driver read call. After validating the minor This corresponds to the driver read call. After validating the minor number
number and arguments, this call enables reads from the specified and arguments, this call enables reads from the specified memory area by
memory area by invoking the user supplied "enable reads handler" invoking the user supplied "enable reads handler" and then reads the indicated
and then reads the indicated memory area. When memory area. When invoked the ``argument_block`` is actually a pointer to the
invoked the ``argument_block`` is actually a pointer to the following following structure type:
structure type:
.. code:: c .. code-block:: c
typedef struct { typedef struct {
uint32_t offset; uint32_t offset;
void \*buffer; void *buffer;
uint32_t length; uint32_t length;
uint32_t status; uint32_t status;
} Non_volatile_memory_Driver_arguments; } Non_volatile_memory_Driver_arguments;
The driver reads ``length`` bytes starting at ``offset`` into The driver reads ``length`` bytes starting at ``offset`` into the partition and
the partition and places them at ``buffer``. The result is returned places them at ``buffer``. The result is returned in ``status``.
in ``status``.
After the read operation is complete, the user supplied "disable reads handler" After the read operation is complete, the user supplied "disable reads handler"
is invoked to protect the memory area again. is invoked to protect the memory area again.
@ -195,40 +187,31 @@ is invoked to protect the memory area again.
Write to a Particular Memory Partition Write to a Particular Memory Partition
====================================== ======================================
This corresponds to the driver write call. After validating the minor This corresponds to the driver write call. After validating the minor number
number and arguments, this call enables writes to the specified and arguments, this call enables writes to the specified memory area by
memory area by invoking the "enable writes handler", then unprotecting invoking the "enable writes handler", then unprotecting the memory area, and
the memory area, and finally actually writing to the indicated memory finally actually writing to the indicated memory area. When invoked the
area. When invoked the ``argument_block`` is actually a pointer to ``argument_block`` is actually a pointer to the following structure type:
the following structure type:
.. code:: c .. code-block:: c
typedef struct { typedef struct {
uint32_t offset; uint32_t offset;
void \*buffer; void *buffer;
uint32_t length; uint32_t length;
uint32_t status; uint32_t status;
} Non_volatile_memory_Driver_arguments; } Non_volatile_memory_Driver_arguments;
The driver writes ``length`` bytes from ``buffer`` and The driver writes ``length`` bytes from ``buffer`` and writes them to the
writes them to the non-volatile memory starting at ``offset`` into non-volatile memory starting at ``offset`` into the partition. The result is
the partition. The result is returned in ``status``. returned in ``status``.
After the write operation is complete, the "disable writes handler" After the write operation is complete, the "disable writes handler" is invoked
is invoked to protect the memory area again. to protect the memory area again.
Erase the Non-Volatile Memory Area Erase the Non-Volatile Memory Area
================================== ==================================
This is one of the IOCTL functions supported by the I/O control This is one of the IOCTL functions supported by the I/O control device driver
device driver entry point. When this IOCTL function is invoked, entry point. When this IOCTL function is invoked, the specified area of
the specified area of non-volatile memory is erased. non-volatile memory is erased.
.. COMMENT: Written by Eric Norum
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.

View File

@ -1,13 +1,17 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Introduction Introduction
############ ############
Before reading this documentation, it is strongly advised to read the Before reading this documentation, it is strongly advised to read the RTEMS
RTEMS Development Environment Guide to get acquainted with the RTEMS Development Environment Guide to get acquainted with the RTEMS directory
directory structure. This document describes how to do a RTEMS Board structure. This document describes how to do a RTEMS Board Support Package,
Support Package, i.e. how to port RTEMS on a new target board. Discussions i.e. how to port RTEMS on a new target board. Discussions are provided for the
are provided for the following topics: following topics:
- RTEMS Board Support Package Organization - RTEMS Board Support Package Organization
@ -15,7 +19,8 @@ are provided for the following topics:
- Board Initialization Sequence - Board Initialization Sequence
- Device Drivers Including: - Device Drivers:
- Console Driver - Console Driver
- Clock Driver - Clock Driver
- Timer Driver - Timer Driver
@ -51,10 +56,3 @@ So in this guide we will try to point out good examples from other BSPs.
Our goal is for you to be able to reuse as much code as possible and Our goal is for you to be able to reuse as much code as possible and
write as little board specific code as possible. write as little board specific code as possible.
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.

View File

@ -1,14 +1,17 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Real-Time Clock Driver Real-Time Clock Driver
###################### ######################
Introduction Introduction
============ ============
The Real-Time Clock (*RTC*) driver is responsible for providing an The Real-Time Clock (*RTC*) driver is responsible for providing an interface to
interface to an *RTC* device. \[NOTE: In this chapter, the abbreviation*TOD* is used for *Time of Day*.] The capabilities provided by this an *RTC* device. The capabilities provided by this driver are:
driver are:
- Set the RTC TOD to RTEMS TOD - Set the RTC TOD to RTEMS TOD
@ -20,47 +23,53 @@ driver are:
- Get the Difference Between the RTEMS and RTC TOD - Get the Difference Between the RTEMS and RTC TOD
The reference implementation for a real-time clock driver can .. note::
be found in ``c/src/lib/libbsp/shared/tod.c``. This driver
is based on the libchip concept and can be easily configured In this chapter, the abbreviation `TOD` is used for *Time of Day*.
to work with any of the RTC chips supported by the RTC
chip drivers in the directory ``c/src/lib/lib/libchip/rtc``. The reference implementation for a real-time clock driver can be found in
There is a README file in this directory for each supported ``c/src/lib/libbsp/shared/tod.c``. This driver is based on the libchip concept
RTC chip. Each of these README explains how to configure the and can be easily configured to work with any of the RTC chips supported by the
shared libchip implementation of the RTC driver for that particular RTC chip drivers in the directory ``c/src/lib/lib/libchip/rtc``. There is a
RTC chip. README file in this directory for each supported RTC chip. Each of these
README explains how to configure the shared libchip implementation of the RTC
driver for that particular RTC chip.
The DY-4 DMV177 BSP used the shared libchip implementation of the RTC driver.
There were no DMV177 specific configuration routines. A BSP could use
configuration routines to dynamically determine what type of real-time clock is
on a particular board. This would be useful for a BSP supporting multiple
board models. The relevant ports of the DMV177's ``RTC_Table`` configuration
table is below:
The DY-4 DMV177 BSP used the shared libchip implementation of the RTC
driver. There were no DMV177 specific configuration routines. A BSP
could use configuration routines to dynamically determine what type
of real-time clock is on a particular board. This would be useful for
a BSP supporting multiple board models. The relevant ports of
the DMV177's ``RTC_Table`` configuration table is below:
.. code:: c .. code:: c
#include <bsp.h> #include <bsp.h>
#include <libchip/rtc.h> #include <libchip/rtc.h>
#include <libchip/icm7170.h> #include <libchip/icm7170.h>
bool dmv177_icm7170_probe(int minor); bool dmv177_icm7170_probe(int minor);
rtc_tbl RTC_Table[] = { rtc_tbl RTC_Table[] = {
{ "/dev/rtc0", /* sDeviceName \*/ { "/dev/rtc0", /* sDeviceName */
RTC_ICM7170, /* deviceType \*/ RTC_ICM7170, /* deviceType */
&icm7170_fns, /* pDeviceFns \*/ &icm7170_fns, /* pDeviceFns */
dmv177_icm7170_probe, /* deviceProbe \*/ dmv177_icm7170_probe, /* deviceProbe */
(void \*) ICM7170_AT_1_MHZ, /* pDeviceParams \*/ (void *) ICM7170_AT_1_MHZ, /* pDeviceParams */
DMV170_RTC_ADDRESS, /* ulCtrlPort1 \*/ DMV170_RTC_ADDRESS, /* ulCtrlPort1 */
0, /* ulDataPort \*/ 0, /* ulDataPort */
icm7170_get_register_8, /* getRegister \*/ icm7170_get_register_8, /* getRegister */
icm7170_set_register_8, /* setRegister \*/ icm7170_set_register_8, /* setRegister */
} }
}; };
unsigned long RTC_Count = (sizeof(RTC_Table)/sizeof(rtc_tbl)); unsigned long RTC_Count = (sizeof(RTC_Table)/sizeof(rtc_tbl));
rtems_device_minor_number RTC_Minor; rtems_device_minor_number RTC_Minor;
bool dmv177_icm7170_probe(int minor) bool dmv177_icm7170_probe(int minor)
{ {
volatile unsigned16 \*card_resource_reg; volatile unsigned16 *card_resource_reg;
card_resource_reg = (volatile unsigned16 \*) DMV170_CARD_RESORCE_REG; card_resource_reg = (volatile unsigned16 *) DMV170_CARD_RESORCE_REG;
if ( (\*card_resource_reg & DMV170_RTC_INST_MASK) == DMV170_RTC_INSTALLED ) if ( (*card_resource_reg & DMV170_RTC_INST_MASK) == DMV170_RTC_INSTALLED )
return TRUE; return TRUE;
return FALSE; return FALSE;
} }
@ -68,23 +77,23 @@ the DMV177's ``RTC_Table`` configuration table is below:
Initialization Initialization
============== ==============
The ``rtc_initialize`` routine is responsible for initializing the The ``rtc_initialize`` routine is responsible for initializing the RTC chip so
RTC chip so it can be used. The shared libchip implementation of this it can be used. The shared libchip implementation of this driver supports
driver supports multiple RTCs and bases its initialization order on multiple RTCs and bases its initialization order on the order the chips are
the order the chips are defined in the ``RTC_Table``. Each chip defined in the ``RTC_Table``. Each chip defined in the table may or may not be
defined in the table may or may not be present on this particular board. present on this particular board. It is the responsibility of the
It is the responsibility of the ``deviceProbe`` to indicate the ``deviceProbe`` to indicate the presence of a particular RTC chip. The first
presence of a particular RTC chip. The first RTC found to be present RTC found to be present is considered the preferred RTC.
is considered the preferred RTC.
In the shared libchip based implementation In the shared libchip based implementation of the driver, the following actions
of the driver, the following actions are performed: are performed:
.. code:: c
.. code-block:: c
rtems_device_driver rtc_initialize( rtems_device_driver rtc_initialize(
rtems_device_major_number major, rtems_device_major_number major,
rtems_device_minor_number minor_arg, rtems_device_minor_number minor_arg,
void \*arg void *arg
) )
{ {
for each RTC configured in RTC_Table for each RTC configured in RTC_Table
@ -92,39 +101,42 @@ of the driver, the following actions are performed:
set RTC_Minor to this device set RTC_Minor to this device
set RTC_Present to TRUE set RTC_Present to TRUE
break out of this loop break out of this loop
if RTC_Present is not TRUE if RTC_Present is not TRUE
return RTEMS_INVALID_NUMBER to indicate that no RTC is present return RTEMS_INVALID_NUMBER to indicate that no RTC is present
register this minor number as the "/dev/rtc" register this minor number as the "/dev/rtc"
perform the deviceInitialize routine for the preferred RTC chip perform the deviceInitialize routine for the preferred RTC chip
for RTCs past this one in the RTC_Table for RTCs past this one in the RTC_Table
if the deviceProbe for this RTC indicates it is present if the deviceProbe for this RTC indicates it is present
perform the deviceInitialize routine for this RTC chip perform the deviceInitialize routine for this RTC chip
register the configured name for this RTC register the configured name for this RTC
} }
The ``deviceProbe`` routine returns TRUE if the device The ``deviceProbe`` routine returns TRUE if the device configured by this entry
configured by this entry in the ``RTC_Table`` is present. in the ``RTC_Table`` is present. This configuration scheme allows one to
This configuration scheme allows one to support multiple versions support multiple versions of the same board with a single BSP. For example, if
of the same board with a single BSP. For example, if the first the first generation of a board had Vendor A's RTC chip and the second
generation of a board had Vendor A's RTC chip and the second generation had Vendor B's RTC chip, RTC_Table could contain information for
generation had Vendor B's RTC chip, RTC_Table could contain both. The ``deviceProbe`` configured for Vendor A's RTC chip would need to
information for both. The ``deviceProbe`` configured return TRUE if the board was a first generation one. The ``deviceProbe``
for Vendor A's RTC chip would need to return TRUE if the routines are very board dependent and must be provided by the BSP.
board was a first generation one. The ``deviceProbe``
routines are very board dependent and must be provided by
the BSP.
setRealTimeToRTEMS setRealTimeToRTEMS
================== ==================
The ``setRealTimeToRTEMS`` routine sets the current RTEMS TOD to that The ``setRealTimeToRTEMS`` routine sets the current RTEMS TOD to that
of the preferred RTC. of the preferred RTC.
.. code:: c
.. code-block:: c
void setRealTimeToRTEMS(void) void setRealTimeToRTEMS(void)
{ {
if no RTCs are present if no RTCs are present
return return
invoke the deviceGetTime routine for the preferred RTC invoke the deviceGetTime routine for the preferred RTC
set the RTEMS TOD using rtems_clock_set set the RTEMS TOD using rtems_clock_set
} }
@ -134,12 +146,14 @@ setRealTimeFromRTEMS
The ``setRealTimeFromRTEMS`` routine sets the preferred RTC TOD to the The ``setRealTimeFromRTEMS`` routine sets the preferred RTC TOD to the
current RTEMS TOD. current RTEMS TOD.
.. code:: c
.. code-block:: c
void setRealTimeFromRTEMS(void) void setRealTimeFromRTEMS(void)
{ {
if no RTCs are present if no RTCs are present
return return
obtain the RTEMS TOD using rtems_clock_get obtain the RTEMS TOD using rtems_clock_get
invoke the deviceSetTime routine for the preferred RTC invoke the deviceSetTime routine for the preferred RTC
} }
@ -147,52 +161,51 @@ current RTEMS TOD.
getRealTime getRealTime
=========== ===========
The ``getRealTime`` returns the preferred RTC TOD to the The ``getRealTime`` returns the preferred RTC TOD to the caller.
caller.
.. code:: c
void getRealTime( rtems_time_of_day \*tod ) .. code-block:: c
void getRealTime( rtems_time_of_day *tod )
{ {
if no RTCs are present if no RTCs are present
return return
invoke the deviceGetTime routine for the preferred RTC invoke the deviceGetTime routine for the preferred RTC
} }
setRealTime setRealTime
=========== ===========
The ``setRealTime`` routine sets the preferred RTC TOD to the The ``setRealTime`` routine sets the preferred RTC TOD to the TOD specified by
TOD specified by the caller. the caller.
.. code:: c
void setRealTime( rtems_time_of_day \*tod ) .. code-block:: c
void setRealTime( rtems_time_of_day *tod )
{ {
if no RTCs are present if no RTCs are present
return return
invoke the deviceSetTime routine for the preferred RTC invoke the deviceSetTime routine for the preferred RTC
} }
checkRealTime checkRealTime
============= =============
The ``checkRealTime`` routine returns the number of seconds The ``checkRealTime`` routine returns the number of seconds difference between
difference between the RTC TOD and the current RTEMS TOD. the RTC TOD and the current RTEMS TOD.
.. code:: c .. code:: c
int checkRealTime( void ) int checkRealTime( void )
{ {
if no RTCs are present if no RTCs are present
return -1 return -1
obtain the RTEMS TOD using rtems_clock_get obtain the RTEMS TOD using rtems_clock_get
get the TOD from the preferred RTC using the deviceGetTime routine get the TOD from the preferred RTC using the deviceGetTime routine
convert the RTEMS TOD to seconds convert the RTEMS TOD to seconds
convert the RTC TOD to seconds convert the RTC TOD to seconds
return the RTEMS TOD in seconds - RTC TOD in seconds return the RTEMS TOD in seconds - RTC TOD in seconds
} }
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.

View File

@ -1,86 +1,85 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2009.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Shared Memory Support Driver Shared Memory Support Driver
############################ ############################
The Shared Memory Support Driver is responsible for providing glue The Shared Memory Support Driver is responsible for providing glue routines and
routines and configuration information required by the Shared configuration information required by the Shared Memory Multiprocessor
Memory Multiprocessor Communications Interface (MPCI). The Communications Interface (MPCI). The Shared Memory Support Driver tailors the
Shared Memory Support Driver tailors the portable Shared portable Shared Memory Driver to a particular target platform.
Memory Driver to a particular target platform.
This driver is only required in shared memory multiprocessing This driver is only required in shared memory multiprocessing systems that use
systems that use the RTEMS mulitprocessing support. For more the RTEMS mulitprocessing support. For more information on RTEMS
information on RTEMS multiprocessing capabilities and the multiprocessing capabilities and the MPCI, refer to the *Multiprocessing
MPCI, refer to the *Multiprocessing Manager* chapter Manager* chapter of the *RTEMS Application C User's Guide*.
of the *RTEMS Application C User's Guide*.
Shared Memory Configuration Table Shared Memory Configuration Table
================================= =================================
The Shared Memory Configuration Table is defined in the following The Shared Memory Configuration Table is defined in the following structure:
structure:
.. code:: c .. code-block:: c
typedef volatile uint32_t vol_u32; typedef volatile uint32_t vol_u32;
typedef struct { typedef struct {
vol_u32 \*address; /* write here for interrupt \*/ vol_u32 *address; /* write here for interrupt */
vol_u32 value; /* this value causes interrupt \*/ vol_u32 value; /* this value causes interrupt */
vol_u32 length; /* for this length (0,1,2,4) \*/ vol_u32 length; /* for this length (0,1,2,4) */
} Shm_Interrupt_information; } Shm_Interrupt_information;
struct shm_config_info { struct shm_config_info {
vol_u32 \*base; /* base address of SHM \*/ vol_u32 *base; /* base address of SHM */
vol_u32 length; /* length (in bytes) of SHM \*/ vol_u32 length; /* length (in bytes) of SHM */
vol_u32 format; /* SHM is big or little endian \*/ vol_u32 format; /* SHM is big or little endian */
vol_u32 (\*convert)(); /* neutral conversion routine \*/ vol_u32 (*convert)(); /* neutral conversion routine */
vol_u32 poll_intr; /* POLLED or INTR driven mode \*/ vol_u32 poll_intr; /* POLLED or INTR driven mode */
void (\*cause_intr)( uint32_t ); void (*cause_intr)( uint32_t );
Shm_Interrupt_information Intr; /* cause intr information \*/ Shm_Interrupt_information Intr; /* cause intr information */
}; };
typedef struct shm_config_info shm_config_table; typedef struct shm_config_info shm_config_table;
where the fields are defined as follows: where the fields are defined as follows:
*base* ``base``
is the base address of the shared memory buffer used to pass is the base address of the shared memory buffer used to pass messages
messages between the nodes in the system. between the nodes in the system.
*length* ``length``
is the length (in bytes) of the shared memory buffer used to pass is the length (in bytes) of the shared memory buffer used to pass messages
messages between the nodes in the system. between the nodes in the system.
*format* ``format``
is either SHM_BIG or SHM_LITTLE to indicate that the neutral format is either ``SHM_BIG`` or ``SHM_LITTLE`` to indicate that the neutral format
of the shared memory area is big or little endian. The format of the shared memory area is big or little endian. The format of the
of the memory should be chosen to match most of the inter-node traffic. memory should be chosen to match most of the inter-node traffic.
*convert* ``convert``
is the address of a routine which converts from native format to is the address of a routine which converts from native format to neutral
neutral format. Ideally, the neutral format is the same as the format. Ideally, the neutral format is the same as the native format so
native format so this routine is quite simple. this routine is quite simple.
*poll_intr* ``poll_intr``, ``cause_intr``
is either INTR_MODE or POLLED_MODE to indicate how the node will be is either ``INTR_MODE`` or ``POLLED_MODE`` to indicate how the node will be
informed of incoming messages. informed of incoming messages.
*cause_intr* ``Intr``
*Intr*
is the information required to cause an interrupt on a node. This is the information required to cause an interrupt on a node. This
structure contains the following fields: structure contains the following fields:
*address* ``address``
is the address to write at to cause an interrupt on that node. For a
is the address to write at to cause an interrupt on that node. polled node, this should be NULL.
For a polled node, this should be NULL.
*value*
``value``
is the value to write to cause an interrupt. is the value to write to cause an interrupt.
*length* ``length``
is the length of the entity to write on the node to cause an interrupt. is the length of the entity to write on the node to cause an interrupt.
This can be 0 to indicate polled operation, 1 to write a byte, 2 to This can be 0 to indicate polled operation, 1 to write a byte, 2 to
write a sixteen-bit entity, and 4 to write a thirty-two bit entity. write a sixteen-bit entity, and 4 to write a thirty-two bit entity.
@ -91,16 +90,16 @@ Primitives
Convert Address Convert Address
--------------- ---------------
The ``Shm_Convert_address`` is responsible for converting an address The ``Shm_Convert_address`` is responsible for converting an address of an
of an entity in the shared memory area into the address that should be entity in the shared memory area into the address that should be used from this
used from this node. Most targets will simply return the address node. Most targets will simply return the address passed to this routine.
passed to this routine. However, some target boards will have a special However, some target boards will have a special window onto the shared memory.
window onto the shared memory. For example, some VMEbus boards have For example, some VMEbus boards have special address windows to access
special address windows to access addresses that are normally reserved addresses that are normally reserved in the CPU's address space.
in the CPU's address space.
.. code:: c
void \*Shm_Convert_address( void \*address ) .. code-block:: c
void *Shm_Convert_address( void *address )
{ {
return the local address version of this bus address return the local address version of this bus address
} }
@ -108,13 +107,14 @@ in the CPU's address space.
Get Configuration Get Configuration
----------------- -----------------
The ``Shm_Get_configuration`` routine is responsible for filling in the The ``Shm_Get_configuration`` routine is responsible for filling in the Shared
Shared Memory Configuration Table passed to it. Memory Configuration Table passed to it.
.. code:: c
.. code-block:: c
void Shm_Get_configuration( void Shm_Get_configuration(
uint32_t localnode, uint32_t localnode,
shm_config_table \**shmcfg shm_config_table **shmcfg
) )
{ {
fill in the Shared Memory Configuration Table fill in the Shared Memory Configuration Table
@ -123,53 +123,54 @@ Shared Memory Configuration Table passed to it.
Locking Primitives Locking Primitives
------------------ ------------------
This is a collection of routines that are invoked by the portable This is a collection of routines that are invoked by the portable part of the
part of the Shared Memory Driver to manage locks in the shared Shared Memory Driver to manage locks in the shared memory buffer area.
memory buffer area. Accesses to the shared memory must be Accesses to the shared memory must be atomic. Two nodes in a multiprocessor
atomic. Two nodes in a multiprocessor system must not be manipulating system must not be manipulating the shared data structures simultaneously. The
the shared data structures simultaneously. The locking primitives locking primitives are used to insure this.
are used to insure this.
To avoid deadlock, local processor interrupts should be disabled the entire To avoid deadlock, local processor interrupts should be disabled the entire
time the locked queue is locked. time the locked queue is locked.
The locking primitives operate on the lock``field`` of the ``Shm_Locked_queue_Control`` The locking primitives operate on the lock ``field`` of the
data structure. This structure is defined as follows: ``Shm_Locked_queue_Control`` data structure. This structure is defined as
.. code:: c follows:
.. code-block:: c
typedef struct { typedef struct {
vol_u32 lock; /* lock field for this queue \*/ vol_u32 lock; /* lock field for this queue */
vol_u32 front; /* first envelope on queue \*/ vol_u32 front; /* first envelope on queue */
vol_u32 rear; /* last envelope on queue \*/ vol_u32 rear; /* last envelope on queue */
vol_u32 owner; /* receiving (i.e. owning) node \*/ vol_u32 owner; /* receiving (i.e. owning) node */
} Shm_Locked_queue_Control; } Shm_Locked_queue_Control;
where each field is defined as follows: where each field is defined as follows:
*lock* ``lock``
is the lock field. Every node in the system must agree on how this is the lock field. Every node in the system must agree on how this field
field will be used. Many processor families provide an atomic will be used. Many processor families provide an atomic "test and set"
"test and set" instruction that is used to manage this field. instruction that is used to manage this field.
*front* ``front``
is the index of the first message on this locked queue. is the index of the first message on this locked queue.
*rear* ``rear``
is the index of the last message on this locked queue. is the index of the last message on this locked queue.
*owner* ``owner``
is the node number of the node that currently has this structure locked. is the node number of the node that currently has this structure locked.
Initializing a Shared Lock Initializing a Shared Lock
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``Shm_Initialize_lock`` routine is responsible for The ``Shm_Initialize_lock`` routine is responsible for initializing the lock
initializing the lock field. This routines usually is implemented field. This routines usually is implemented as follows:
as follows:
.. code:: c .. code-block:: c
void Shm_Initialize_lock( void Shm_Initialize_lock(
Shm_Locked_queue_Control \*lq_cb Shm_Locked_queue_Control *lq_cb
) )
{ {
lq_cb->lock = LQ_UNLOCKED; lq_cb->lock = LQ_UNLOCKED;
@ -178,21 +179,21 @@ as follows:
Acquiring a Shared Lock Acquiring a Shared Lock
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
The ``Shm_Lock`` routine is responsible for The ``Shm_Lock`` routine is responsible for acquiring the lock field.
acquiring the lock field. Interrupts should be Interrupts should be disabled while that lock is acquired. If the lock is
disabled while that lock is acquired. If the lock currently unavailble, then the locking routine should delay a few microseconds
is currently unavailble, then the locking routine to allow the other node to release the lock. Doing this reduces bus contention
should delay a few microseconds to allow the other
node to release the lock. Doing this reduces bus contention
for the lock. This routines usually is implemented as follows: for the lock. This routines usually is implemented as follows:
.. code:: c
.. code-block:: c
void Shm_Lock( void Shm_Lock(
Shm_Locked_queue_Control \*lq_cb Shm_Locked_queue_Control *lq_cb
) )
{ {
disable processor interrupts disable processor interrupts
set Shm_isrstat to previous interrupt disable level set Shm_isrstat to previous interrupt disable level
while ( TRUE ) { while ( TRUE ) {
atomically attempt to acquire the lock atomically attempt to acquire the lock
if the lock was acquired if the lock was acquired
@ -204,13 +205,14 @@ for the lock. This routines usually is implemented as follows:
Releasing a Shared Lock Releasing a Shared Lock
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
The ``Shm_Unlock`` routine is responsible for The ``Shm_Unlock`` routine is responsible for releasing the lock field and
releasing the lock field and reenabling processor reenabling processor interrupts. This routines usually is implemented as
interrupts. This routines usually is implemented as follows: follows:
.. code:: c
.. code-block:: c
void Shm_Unlock( void Shm_Unlock(
Shm_Locked_queue_Control \*lq_cb Shm_Locked_queue_Control *lq_cb
) )
{ {
set the lock to the unlocked value set the lock to the unlocked value
@ -222,16 +224,15 @@ interrupts. This routines usually is implemented as follows:
Installing the MPCI ISR Installing the MPCI ISR
======================= =======================
The ``Shm_setvec`` is invoked by the portable portion The ``Shm_setvec`` is invoked by the portable portion of the shared memory to
of the shared memory to install the interrupt service routine install the interrupt service routine that is invoked when an incoming message
that is invoked when an incoming message is announced. Some is announced. Some target boards support an interprocessor interrupt or
target boards support an interprocessor interrupt or mailbox mailbox scheme and this is where the ISR for that interrupt would be installed.
scheme and this is where the ISR for that interrupt would be
installed.
On an interrupt driven node, this routine would be implemented On an interrupt driven node, this routine would be implemented
as follows: as follows:
.. code:: c
.. code-block:: c
void Shm_setvec( void ) void Shm_setvec( void )
{ {
@ -239,10 +240,3 @@ as follows:
} }
On a polled node, this routine would be empty. On a polled node, this routine would be empty.
.. COMMENT: COPYRIGHT (c) 1988-2009.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.

View File

@ -1,14 +1,18 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2008.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Target Dependent Files Target Dependent Files
###################### ######################
RTEMS has a multi-layered approach to portability. This is done to RTEMS has a multi-layered approach to portability. This is done to maximize the
maximize the amount of software that can be reused. Much of the amount of software that can be reused. Much of the RTEMS source code can be
RTEMS source code can be reused on all RTEMS platforms. Other parts reused on all RTEMS platforms. Other parts of the executive are specific to
of the executive are specific to hardware in some sense. hardware in some sense. RTEMS classifies target dependent code based upon its
RTEMS classifies target dependent code based upon its dependencies dependencies into one of the following categories.
into one of the following categories.
- CPU dependent - CPU dependent
@ -19,70 +23,68 @@ into one of the following categories.
CPU Dependent CPU Dependent
============= =============
This class of code includes the foundation This class of code includes the foundation routines for the executive proper
routines for the executive proper such as the context switch and such as the context switch and the interrupt subroutine implementations.
the interrupt subroutine implementations. Sources for the supported Sources for the supported processor families can be found in
processor families can be found in ``cpukit/score/cpu``. ``cpukit/score/cpu``. A good starting point for a new family of processors is
A good starting point for a new family of processors is the``no_cpu`` directory, which holds both prototypes and the ``no_cpu`` directory, which holds both prototypes and descriptions of each
descriptions of each needed CPU dependent function. needed CPU dependent function.
CPU dependent code is further subcategorized if the implementation is CPU dependent code is further subcategorized if the implementation is dependent
dependent on a particular CPU model. For example, the MC68000 and MC68020 on a particular CPU model. For example, the MC68000 and MC68020 processors are
processors are both members of the m68k CPU family but there are significant both members of the m68k CPU family but there are significant differences
differences between these CPU models which RTEMS must take into account. between these CPU models which RTEMS must take into account.
The source code found in the ``cpukit/score/cpu`` is required to The source code found in the ``cpukit/score/cpu`` is required to only depend
only depend upon the CPU model variations that GCC distinguishes upon the CPU model variations that GCC distinguishes for the purposes of
for the purposes of multilib'ing. Multilib is the term the GNU multilib'ing. Multilib is the term the GNU community uses to refer to building
community uses to refer to building a single library source multiple a single library source multiple times with different compiler options so the
times with different compiler options so the binary code generated binary code generated is compatible. As an example, from GCC's perspective,
is compatible. As an example, from GCC's perspective, many PowerPC many PowerPC CPU models are just a PPC603e. Remember that GCC only cares about
CPU models are just a PPC603e. Remember that GCC only cares about the CPU code itself and need not be aware of any peripherals. In the embedded
the CPU code itself and need not be aware of any peripherals. In community, we are exposed to thousands of CPU models which are all based upon
the embedded community, we are exposed to thousands of CPU models only a relative small number of CPU cores.
which are all based upon only a relative small number of CPU cores.
Similarly for the SPARC/ERC32 BSP, the ``RTEMS_CPU`` is specified as``erc32`` which is the name of the CPU model and BSP for this SPARC V7 Similarly for the SPARC/ERC32 BSP, the ``RTEMS_CPU`` is specified as ``erc32``
system on chip. But the multilib variant used is actually ``v7`` which is the name of the CPU model and BSP for this SPARC V7 system on chip.
which indicates the ERC32 CPU core is a SPARC V7. But the multilib variant used is actually ``v7`` which indicates the ERC32 CPU
core is a SPARC V7.
Board Dependent Board Dependent
=============== ===============
This class of code provides the most specific glue between RTEMS and This class of code provides the most specific glue between RTEMS and a
a particular board. This code is represented by the Board Support Packages particular board. This code is represented by the Board Support Packages and
and associated Device Drivers. Sources for the BSPs included in the associated Device Drivers. Sources for the BSPs included in the RTEMS
RTEMS distribution are located in the directory ``c/src/lib/libbsp``. distribution are located in the directory ``c/src/lib/libbsp``. The BSP source
The BSP source directory is further subdivided based on the CPU family directory is further subdivided based on the CPU family and BSP.
and BSP.
Some BSPs may support multiple board models within a single board family. Some BSPs may support multiple board models within a single board family. This
This is necessary when the board supports multiple variants on a is necessary when the board supports multiple variants on a single base board.
single base board. For example, the Motorola MVME162 board family has a For example, the Motorola MVME162 board family has a fairly large number of
fairly large number of variations based upon the particular CPU model variations based upon the particular CPU model and the peripherals actually
and the peripherals actually placed on the board. placed on the board.
Peripheral Dependent Peripheral Dependent
==================== ====================
This class of code provides a reusable library of peripheral device This class of code provides a reusable library of peripheral device drivers
drivers which can be tailored easily to a particular board. The which can be tailored easily to a particular board. The libchip library is a
libchip library is a collection of reusable software objects that collection of reusable software objects that correspond to standard
correspond to standard controllers. Just as the hardware engineer controllers. Just as the hardware engineer chooses a standard controller when
chooses a standard controller when designing a board, the goal of designing a board, the goal of this library is to let the software engineer do
this library is to let the software engineer do the same thing. the same thing.
The source code for the reusable peripheral driver library may be found The source code for the reusable peripheral driver library may be found in the
in the directory ``c/src/lib/libchip``. The source code is further directory ``c/src/lib/libchip``. The source code is further divided based upon
divided based upon the class of hardware. Example classes include serial the class of hardware. Example classes include serial communications
communications controllers, real-time clocks, non-volatile memory, and controllers, real-time clocks, non-volatile memory, and network controllers.
network controllers.
Questions to Ask Questions to Ask
================ ================
When evaluating what is required to support RTEMS applications on When evaluating what is required to support RTEMS applications on a particular
a particular target board, the following questions should be asked: target board, the following questions should be asked:
- Does a BSP for this board exist? - Does a BSP for this board exist?
@ -90,46 +92,47 @@ a particular target board, the following questions should be asked:
- Is the board's CPU supported? - Is the board's CPU supported?
If there is already a BSP for the board, then things may already be ready If there is already a BSP for the board, then things may already be ready to
to start developing application software. All that remains is to verify start developing application software. All that remains is to verify that the
that the existing BSP provides device drivers for all the peripherals existing BSP provides device drivers for all the peripherals on the board that
on the board that the application will be using. For example, the application the application will be using. For example, the application in question may
in question may require that the board's Ethernet controller be used and require that the board's Ethernet controller be used and the existing BSP may
the existing BSP may not support this. not support this.
If the BSP does not exist and the board's CPU model is supported, then If the BSP does not exist and the board's CPU model is supported, then examine
examine the reusable chip library and existing BSPs for a close match. the reusable chip library and existing BSPs for a close match. Other BSPs and
Other BSPs and libchip provide starting points for the development libchip provide starting points for the development of a new BSP. It is often
of a new BSP. It is often possible to copy existing components in possible to copy existing components in the reusable chip library or device
the reusable chip library or device drivers from BSPs from different drivers from BSPs from different CPU families as the starting point for a new
CPU families as the starting point for a new device driver. device driver. This will help reduce the development effort required.
This will help reduce the development effort required.
If the board's CPU family is supported but the particular CPU model on If the board's CPU family is supported but the particular CPU model on that
that board is not, then the RTEMS port to that CPU family will have to board is not, then the RTEMS port to that CPU family will have to be augmented.
be augmented. After this is done, development of the new BSP can proceed. After this is done, development of the new BSP can proceed.
Otherwise both CPU dependent code and the BSP will have to be written. Otherwise both CPU dependent code and the BSP will have to be written.
This type of development often requires specialized skills. If This type of development often requires specialized skills and there are people
you need help in making these modifications to RTEMS, please in the community who provide those services. If you need help in making these
consider using one of the RTEMS Service Providers. The current modifications to RTEMS try a search in a search engine with something like
list of these is at http://www.rtems.org/support.html. "rtems support". The RTEMS Project encourages users to use support services
however we do not endorse any providers.
CPU Dependent Executive Files CPU Dependent Executive Files
============================= =============================
The CPU dependent files in the RTEMS executive source code are found The CPU dependent files in the RTEMS executive source code are found in the
in the following directory: following directory:
.. code:: c .. code:: c
cpukit/score/cpu/*CPU* cpukit/score/cpu/<CPU>
where *CPU* is replaced with the CPU family name. where <CPU> is replaced with the CPU family name.
Within each CPU dependent directory inside the executive proper is a Within each CPU dependent directory inside the executive proper is a file named
file named ``*CPU*.h`` which contains information about each of the ``<CPU>.h`` which contains information about each of the supported CPU models
supported CPU models within that family. within that family.
CPU Dependent Support Files CPU Dependent Support Files
=========================== ===========================
@ -142,93 +145,85 @@ This class of code may be found in the following directory:
.. code:: c .. code:: c
c/src/lib/libcpu/*CPU* c/src/lib/libcpu/<CPU>
CPU model dependent support code is found in the following directory: CPU model dependent support code is found in the following directory:
.. code:: c .. code:: c
c/src/lib/libcpu/*CPU*/*CPU_MODEL* c/src/lib/libcpu/<CPU>/<CPU_MODEL>
*CPU_MODEL* may be a specific CPU model name or a name indicating a CPU <CPU_MODEL> may be a specific CPU model name or a name indicating a CPU core or
core or a set of related CPU models. The file ``configure.ac`` in each ``c/src/lib/libcpu/*CPU*`` directory contains the logic which enables a set of related CPU models. The file ``configure.ac`` in each
the appropriate subdirectories for the specific CPU model your BSP has. ``c/src/lib/libcpu/<CPU>`` directory contains the logic which enables the
appropriate subdirectories for the specific CPU model your BSP has.
Board Support Package Structure Board Support Package Structure
=============================== ===============================
The BSPs are all under the ``c/src/lib/libbsp`` directory. Below this The BSPs are all under the ``c/src/lib/libbsp`` directory. Below this
directory, there is a subdirectory for each CPU family. Each BSP directory, there is a subdirectory for each CPU family. Each BSP is found
is found under the subdirectory for the appropriate processor under the subdirectory for the appropriate processor family (arm, powerpc,
family (m68k, powerpc, etc.). In addition, there is source code sparc, etc.). In addition, there is source code available which may be shared
available which may be shared across all BSPs regardless of across all BSPs regardless of the CPU family or just across BSPs within a
the CPU family or just across BSPs within a single CPU family. This single CPU family. This results in a BSP using the following directories:
results in a BSP using the following directories:
.. code:: c .. code:: c
c/src/lib/libbsp/shared c/src/lib/libbsp/shared
c/src/lib/libbsp/*CPU*/shared c/src/lib/libbsp/<CPU>/shared
c/src/lib/libbsp/*CPU*/*BSP* c/src/lib/libbsp/<CPU>/<BSP>
Under each BSP specific directory, there is a collection of Under each BSP specific directory, there is a collection of subdirectories.
subdirectories. For commonly provided functionality, the BSPs For commonly provided functionality, the BSPs follow a convention on
follow a convention on subdirectory naming. The following list subdirectory naming. The following list describes the commonly found
describes the commonly found subdirectories under each BSP. subdirectories under each BSP.
- *console*: - ``console``:
is technically the serial driver for the BSP rather is technically the serial driver for the BSP rather than just a console
than just a console driver, it deals with the board driver, it deals with the board UARTs (i.e. serial devices).
UARTs (i.e. serial devices).
- *clock*: - ``clock``:
support for the clock tick - a regular time basis to the kernel. support for the clock tick - a regular time basis to the kernel.
- *timer*: - ``timer``:
support of timer devices. support of timer devices.
- *rtc* or ``tod``: - ``rtc`` or ``tod``:
support for the hardware real-time clock. support for the hardware real-time clock.
- *nvmem*: - ``nvmem``:
support for non-volatile memory such as EEPROM or Flash. support for non-volatile memory such as EEPROM or Flash.
- *network*: - ``network``:
the Ethernet driver. the Ethernet driver.
- *shmsupp*: - ``shmsupp``:
support of shared memory driver MPCI layer in a multiprocessor system, support of shared memory driver MPCI layer in a multiprocessor system,
- *include*: - ``include``:
include files for this BSP. include files for this BSP.
- *gnatsupp*: - ``gnatsupp``:
BSP specific support for the GNU Ada run-time. Each BSP that wishes BSP specific support for the GNU Ada run-time. Each BSP that wishes to have
to have the possibility to map faults or exceptions into Ada language the possibility to map faults or exceptions into Ada language exceptions or
exceptions or hardware interrupts into Ada interrupt tasks must provide hardware interrupts into Ada interrupt tasks must provide this support.
this support.
There may be other directories in the BSP tree and the name should There may be other directories in the BSP tree and the name should be
be indicative of the functionality of the code within that directory. indicative of the functionality of the code within that directory.
The build order of the BSP is determined by the Makefile structure. The build order of the BSP is determined by the Makefile structure. This
This structure is discussed in more detail in the `Makefiles`_ structure is discussed in more detail in the `Makefiles`_ chapter.
chapter.
.. sidebar:
This manual refers to the gen68340 BSP for numerous concrete examples. You
should have a copy of the gen68340 BSP available while reading this piece of
documentation. This BSP is located in the following directory:
*NOTE:* This manual refers to the gen68340 BSP for numerous concrete
examples. You should have a copy of the gen68340 BSP available while
reading this piece of documentation. This BSP is located in the
following directory:
.. code:: c .. code:: c
c/src/lib/libbsp/m68k/gen68340 c/src/lib/libbsp/m68k/gen68340
Later in this document, the $BSP340_ROOT label will be used Later in this document, the $BSP340_ROOT label will be used to refer to this
to refer to this directory. directory.
.. COMMENT: COPYRIGHT (c) 1988-2008.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.

View File

@ -1,35 +1,38 @@
.. comment SPDX-License-Identifier: CC-BY-SA-4.0 .. comment SPDX-License-Identifier: CC-BY-SA-4.0
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
Timer Driver Timer Driver
############ ############
The timer driver is primarily used by the RTEMS Timing Tests. The timer driver is primarily used by the RTEMS Timing Tests. This driver
This driver provides as accurate a benchmark timer as possible. provides as accurate a benchmark timer as possible. It typically reports its
It typically reports its time in microseconds, CPU cycles, or time in microseconds, CPU cycles, or bus cycles. This information can be very
bus cycles. This information can be very useful for determining useful for determining precisely what pieces of code require optimization and
precisely what pieces of code require optimization and to measure the to measure the impact of specific minor changes.
impact of specific minor changes.
The gen68340 BSP also uses the Timer Driver to support a high performance The gen68340 BSP also uses the Timer Driver to support a high performance mode
mode of the on-CPU UART. of the on-CPU UART.
Benchmark Timer Benchmark Timer
=============== ===============
The RTEMS Timing Test Suite requires a benchmark timer. The The RTEMS Timing Test Suite requires a benchmark timer. The RTEMS Timing Test
RTEMS Timing Test Suite is very helpful for determining Suite is very helpful for determining the performance of target hardware and
the performance of target hardware and comparing its performance comparing its performance to that of other RTEMS targets.
to that of other RTEMS targets.
This section describes the routines which are assumed to exist by This section describes the routines which are assumed to exist by the RTEMS
the RTEMS Timing Test Suite. The names used are *EXACTLY* what Timing Test Suite. The names used are *EXACTLY* what is used in the RTEMS
is used in the RTEMS Timing Test Suite so follow the naming convention. Timing Test Suite so follow the naming convention.
benchmark_timer_initialize benchmark_timer_initialize
-------------------------- --------------------------
Initialize the timer source. Initialize the timer source.
.. code:: c
.. code-block:: c
void benchmark_timer_initialize(void) void benchmark_timer_initialize(void)
{ {
@ -39,10 +42,11 @@ Initialize the timer source.
Read_timer Read_timer
---------- ----------
The ``benchmark_timer_read`` routine returns the number of benchmark The ``benchmark_timer_read`` routine returns the number of benchmark time units
time units (typically microseconds) that have elapsed since the last (typically microseconds) that have elapsed since the last call to
call to ``benchmark_timer_initialize``. ``benchmark_timer_initialize``.
.. code:: c
.. code-block:: c
benchmark_timer_t benchmark_timer_read(void) benchmark_timer_t benchmark_timer_read(void)
{ {
@ -52,23 +56,23 @@ call to ``benchmark_timer_initialize``.
return the stop time return the stop time
} }
Many implementations of this routine subtract the overhead required Many implementations of this routine subtract the overhead required to
to initialize and read the benchmark timer. This makes the times reported initialize and read the benchmark timer. This makes the times reported more
more accurate. accurate.
Some implementations report 0 if the harware timer value change is Some implementations report 0 if the harware timer value change is sufficiently
sufficiently small. This is intended to indicate that the execution time small. This is intended to indicate that the execution time is below the
is below the resolution of the timer. resolution of the timer.
benchmark_timer_disable_subtracting_average_overhead benchmark_timer_disable_subtracting_average_overhead
---------------------------------------------------- ----------------------------------------------------
This routine is invoked by the "Check Timer" (``tmck``) test in the This routine is invoked by the "Check Timer" (``tmck``) test in the RTEMS
RTEMS Timing Test Suite. It makes the ``benchmark_timer_read`` Timing Test Suite. It makes the ``benchmark_timer_read`` routine NOT subtract
routine NOT subtract the overhead required the overhead required to initialize and read the benchmark timer. This is used
to initialize and read the benchmark timer. This is used by the ``tmoverhd`` test to determine the overhead required to initialize and
by the ``tmoverhd`` test to determine the overhead read the timer.
required to initialize and read the timer.
.. code:: c .. code:: c
void benchmark_timer_disable_subtracting_average_overhead(bool find_flag) void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
@ -76,31 +80,23 @@ required to initialize and read the timer.
disable the subtract overhead feature disable the subtract overhead feature
} }
The ``benchmark_timer_find_average_overhead`` variable is used to The ``benchmark_timer_find_average_overhead`` variable is used to indicate the
indicate the state of the "subtract overhead feature". state of the "subtract overhead feature".
gen68340 UART FIFO Full Mode gen68340 UART FIFO Full Mode
============================ ============================
The gen68340 BSP is an example of the use of the timer to support the UART The gen68340 BSP is an example of the use of the timer to support the UART
input FIFO full mode (FIFO means First In First Out and roughly means input FIFO full mode (FIFO means First In First Out and roughly means
buffer). This mode consists in the UART raising an interrupt when n buffer). This mode consists in the UART raising an interrupt when n characters
characters have been received (*n* is the UART's FIFO length). It results have been received (*n* is the UART's FIFO length). It results in a lower
in a lower interrupt processing time, but the problem is that a scanf interrupt processing time, but the problem is that a scanf primitive will block
primitive will block on a receipt of less than *n* characters. The solution on a receipt of less than *n* characters. The solution is to set a timer that
is to set a timer that will check whether there are some characters will check whether there are some characters waiting in the UART's input
waiting in the UART's input FIFO. The delay time has to be set carefully FIFO. The delay time has to be set carefully otherwise high rates will be
otherwise high rates will be broken: broken:
- if no character was received last time the interrupt subroutine was - if no character was received last time the interrupt subroutine was entered,
entered, set a long delay, set a long delay,
- otherwise set the delay to the delay needed for *n* characters
receipt.
.. COMMENT: COPYRIGHT (c) 1988-2002.
.. COMMENT: On-Line Applications Research Corporation (OAR).
.. COMMENT: All rights reserved.
- otherwise set the delay to the delay needed for ``n`` characters receipt.