The first task when using any new real-time operating system (RTOS) is to get it up and running on your hardware. The open-source eCos RTOS makes that part pretty easy.
eCos is an open-source, royalty-free, real-time operating system targeted to embedded applications and supported by the GNU development tools. This makes test driving eCos extremely inexpensive. Initially, the main hurdle is configuring the tools and source code to get your platform up and running. The source code to eCos is provided and the rights to change or add to the source are granted to the user. These rights are covered by the eCos Public License.1
One of the key aspects of eCos is its configuration system. It allows the programmer to control what functionality and features are included at runtime. Selecting from package modules, the programmer can layer different functionality, such as an Ethernet driver and networking support or a different scheduling algorithm, according to the needs of the application. Unwanted features can be eliminated easily to reduce the resource footprint. The configuration system also enables developers to employ third-party components to extend and enhance the functionality of the operating system.
eCos was designed for portability to a wide variety of 16-, 32-, and 64-bit processors and platforms. eCos is assembled from different components layered on each other to add the needed support for a given system. The base of this layered architecture is the hardware abstraction layer (HAL). Once the HAL has been ported to run on a given target's processor and any specific configuration needed for the target platform itself is added, eCos can be up and running quickly. Currently, numerous target architectures are supported by eCos and more ports will be added as programmers make them available. Table 1 lists some of the supported architectures.2
ARM | NEC V8xx |
SuperH | PowerPC |
Intel x86 | MIPS |
Matsushita AM3x |
Table 1. Processor architectures supported by eCos
eCos is designed to support real-time applications by providing features such as preemptable tasks, low interrupt latency, different methods for synchronization, and a selectable scheduling policy. Device drivers, memory management, exception handling, timers, counters, and standard C and math libraries are all available. Complete development and debug tools are also provided, including software configuration and build tools, GNU-based compilers, assemblers, linkers, debuggers, and simulators. The eCos host tools are available in Linux and Windows versions.
Hardware abstraction layer
The first component in the eCos system architecture is the hardware abstraction layer, which can be broken down into three sub-modules. The first HAL sub-module defines the architecture. Each processor family supported by eCos is said to be a different architecture. Each architecture sub-module contains the code necessary for CPU startup, interrupt delivery, context switching, and other functionality specific to the instruction set architecture of that processor family.
A second HAL sub-module defines the variant. A variant is a specific processor within a processor family. An example of an eCos feature at this level is support for an on-chip peripheral like a memory management unit (MMU).
The third HAL sub-module defines the platform. A platform, or board, is a specific piece of hardware that includes the selected processor architecture and variant. This module includes code for startup, chip select configuration, interrupt controllers, and timer devices.
Kernel
The eCos kernel consists of a scheduler and mechanisms for thread synchronization, exception handling, interrupt handling, and timers.
The scheduler is the heart of the kernel and contains two modes of operation: bitmap and multi-level queue scheduling. Currently, only one scheduler is supported at a time. The bitmap scheduler represents each thread, which must have a unique priority, with a bit in a bitmap. The multi-level queue implements a number of thread priorities, where threads of the same priority can be timesliced.
Thread synchronization is accomplished through the use of mutexes and semaphores. These can be combined with event flags and message queues for thread communication.
Exception handlers are routines for handling machine exceptions raised by hardware and software. Passed to the handler routines are a pointer to context information that was previously registered with the handler, the exception number, and an error code. Exception handlers may be set up globally, per-thread, or both.
Interrupt handlers process events caused by external devices. Since delivery of interrupts to the software is architecture specific, eCos provides a generalized scheme of utilizing an interrupt service routine (ISR) and a deferred service routine to maintain low interrupt latency.
Finally, the timer-related elements of the kernel include counters, clocks, and alarms.
Drivers
The driver component provides different means for I/O, including simple serial ports and Ethernet devices. The general mechanism for accessing a particular device is via a handle. Each device is given a unique name such as "/dev/ser1" or "/dev/tty1". Basic functions are provided to send and receive data from the device, as well as to manipulate the state of the driver or the actual device itself. Typical drivers included for specific platforms are Ethernet, flash, PCMCIA, and serial.
Development tools
The GNU development tools provide the build and debug capabilities and binary utilities support. These tools have been described in Embedded Systems Programming magazine.3, 4
Third-party support
Along with the core functionality, additional features are available that greatly extend the capabilities of eCos for different applications. Additional functionality and third-party support for eCos include:
- POSIX 1003.1-EL/IX compatibility
- uITRON 3.0 compatibility
- RedBoot ROM monitor
- Filesystem
- Networking
- Web server
- PCI library
- USB slave support
Figure 1. eCos configuration table
eCos can be configured and built from either the command line or by using the Configuration Tool. The Configuration Tool gives the programmer a hierarchical representation of the eCos configuration, allowing the programmer to easily change the configuration or add and remove particular packages. Along with this, the Configuration Tool features the capabilities to build eCos and run the platform tests provided. Figure 1 shows the main screen of the Configuration Tool. I used version 1.3.1.2 of the Configuration Tool for this port (the latest is version 2). In addition to the tests for eCos and its individual packages, example applications are included.
Porting the eCos HAL
The first task when using eCos, or any RTOS for that matter, is getting it up and running on your own target hardware. For eCos, this is accomplished by porting the HAL to the new target.
I recently had the task of moving from an evaluation platform supported by eCos to custom hardware. In our application, Motorola's MPC860 PowerPC was the chosen processor. After reviewing the platforms available and supported by eCos for this processor, I decided the Motorola Computer Group's MBX860 board offered the features needed to code much of my application. The choice to utilize a development board was also motivated by the fact that the actual hardware would not be available for a few months. An evaluation board is not necessary to get eCos up and running. A PC can be used as the target platform or one of the supported processor simulators. The MBX860 board gave me a jump start on the software task and also provided a baseline platform to which I could return for testing. In addition to the development board, I obtained a background debug mode (BDM) emulator for the MPC860. The BDM/JTAG emulator assisted in the initial phase of bringing up my custom hardware and was very useful for downloading new code for testing. Using the emulator to download code expedited the process of updating the flash when code modifications were made.
HAL porting can be broken up into three types: platform, variant, and architecture porting. Platform porting typically requires the least amount of effort. Utilizing a current platform as a baseline, additional modifications for specific board initialization and memory layout are areas that need to be addressed.
Variant porting can be a more intensive task than platform porting, depending on what is currently available for a specific processor. Functionality that can be redefined and, therefore, needs to be addressed in the new variant are cache, memory management units, interrupts, and other features that may override implementations in the standard architecture HAL.
The most painstaking porting project is an architecture port. This is because you must ensure that suitable development tools for your target architecture actually exist. If a toolchain is available, you can then proceed to implement the new architecture HAL. Basing the new HAL on an existing architecture (the MIPS architecture should be used if possible) is the starting point. Then a platform port is also needed to get the target board functioning properly.
Prior to taking on the project of a variant or architecture port, it is a good idea to publicize your intention on the eCos discussion board to see if there are others already undertaking the same task.5 If luck is on your side, you may even be able to find a port that has been contributed back to the eCos maintainers for testing and public release.
Before going forward with the eCos port, I have already gone through the initial board debug and have flash ROM properly up and running. Some low-level device testing was performed in order to validate the digital schematic design.
HAL directory and file layout
The main source code root is located in the ecos\packages directory, under which are the specific eCos packages. The HAL sub-module directory structures necessary for this port, based on the PowerPC architecture and MPC8xx variant, are described in Table 2, where the mytarget directory contains the new platform port. Descriptions of some of the key files located in these four sub-modules are given in Table 3.
Battery Type | Vnominal | Maximum Load Current* | Energy by Wgt. (Wh/Kg) | Energy by Vol. (Wh/L) | Operating Temperature | Recharge | Maintenance** | Life Cycle (Recharge) | Shelf life/ Self discharge |
Alkaline | 1.5V | 150 | 375 | -20 to 55C | 5 yrs to 80% | ||||
NiCd | 1.25V | >2C | 45-80 | 125 | -40 to 60C | t | 1/Mo | 1500 | <20% per Mo |
NiMH | 1.25V | 0.5-1C | 60-120 | 180 | -20 to 60C | t | 1/3Mo | 500 | 30% per Mo |
Lithium ion | 3.6V | 1C | 100 | 270-325 | -20 to 60C | t | 50-100 | 10% per Mo | |
Lithium polymer | 3.7V | 0.2C | 120-160 | 230-270 | -20 to 60C | t | 500 | 10+ years | |
Sealed lead acid | 2V | 0.2C | 30 | 80 | -20 to 60C | t | 1/6Mo | 200-500 | 5% per Mo |
>Zinc air | 1.4V | 300 | 1150 | -20 to 60C | 3-12 weeks to 50% | ||||
Silver oxide | 1.55V | 130 | 500 | -20 to 60C | 2 yrs. to 84% | ||||
Lithium poly | 3.0V | -40 to 85C | 10+ years | ||||||
carbon monofluoride | |||||||||
Lithium manganese | 3.0V | 225 | 550 | -20 to 60C | 10+ years | ||||
diode | |||||||||
Lithium thionyl | 3.6V | 710 | 1300 | -55 to 100C | 9 yrs to 80% | ||||
chloride | |||||||||
Lithium sulfur | 3.0V | 290 | 500 | -60 to 85C | 10 yrs to 80% | ||||
* C = Amp-Hour rating of battery divided by 1 Hour, e.g. for a 1500mAH battery, C = 1500mA | |||||||||
** Required interval between deep cycles |
Table 2. Battery chemistry comparison
HAL sub-module | Location and file | Description |
Common | src\hal_if.c | Wrappers from the calling interface API to the features used for the implementation |
Common | src\hal_stub.c | Wrappers for features required by the generic GDB stub |
PowerPC architecture | cdl\hal_powerpc.cdl | Architecture-level package configuration data |
PowerPC architecture | src\hal_intr.c | Interrupt handling functions |
PowerPC architecture | src\powerpc.ld | Linker script file containing architecture-specific linker macros |
PowerPC architecture | src\vectors.S | Exception vector, interrupt vector, and other initialization code, including the reset vector |
MPC8xx variant | cdl\hal_powerpc_mpc8xx.cdl | MPC8xx package configuration data |
MPC8xx variant | src\var_intr.c | MPC8xx-specific interrupt handlers |
MPC8xx variant | src\var_misc.c | Variant initialization and miscellaneous MMU functions |
QUICC variant | src\quicc_smcl.c | Basic serial I/O driver containing initialization, read, and write functions for the SMC1 port |
MY_TARGET platform | cdl\hal_powerpc_mytarget.cdl | Platform package configuration data |
MY_TARGET platform | src\mytarget.S | Platform-specific initialization |
Table 3. Key HAL files
Load-and-go functionality
Now that we are acquainted with the layout of the HAL directories and files, the first goal for the platform port is to create a minimal stub residing in flash that allows code to be downloaded and run from RAM. In order to ease the pain in achieving load-and-go functionality, you can utilize a ROM monitor, or, as in my case, a JTAG/BDM emulator. The emulator provides the ability to configure the PowerPC registers to interface to and program the flash.
Getting the new platform noticed
The name used for this new platform is "MY_TARGET". Since the MBX board is used as the baseline for this porting process, a copy of this platform tree is made into the new hal\powerpc\mytarget directory. Next, files need to be renamed in order to reflect the new MY_TARGET platform. For example, following the eCos file naming convention, the platform package configuration file originally named hal_powerpc_mbx.cdl was changed to hal_powerpc_mytarget.cdl.
# # PowerPC/MY_TARGET platform HAL package configuration data # cdl_package CYGPKG_HAL_POWERPC_MYTARGET { display "MY_TARGET PowerPC board" parent CYGPKG_HAL_POWERPC # Architecture requires CYGPKG_HAL_POWERPC_MPC8xx # Variant define_header hal_powerpc_mytarget.h include_dir cyg/hal description "The MY_TARGET HAL package provides the support needed to run eCos on a MY_TARGET platform equipped with a PowerPC processor." }
Listing 1. hal_powerpc_mytarget.cdl
Now the options in the component definition language (CDL) file need adjusting to reflect the new target. Listing 1 shows an example of the CDL terminology for the new platform.
All references to the MBX platform need to be modified to refer to the new target instead. Other option changes include statically configuring the board clock speed, removal of the option to select a 32-bit flash for booting, and removal of the MBX platform test. Verification of the MPC8xx variant CDL file is necessary since it is utilized by the MY_TARGET platform.
The MBX platform also uses a flash device package that contains driver functions for controlling its on-board flash. This driver is located in the devs\flash\powerpc\mbx subdirectory. A copy of the MBX board flash device driver tree is needed to accommodate the flash used on the new target. The steps needed to accomplish this are the same as the MBX-to-MY_TARGET platform copy detailed previously.
Figure 2. eCos New MY_TARGET platform template selection
Next, the main configuration file, ecos.db (located in the ecos\packages root directory), should be modified to make the configuration tool aware of the new platform. Along with this change, the new MY_TARGET flash device driver package should be added to the ecos.db file. Then selection of the MY_TARGET platform template is possible using the Configuration Tool under the Build->Templates... menu. The templates dialog box with the MY_TARGET selection is shown in Figure 2. I also selected the stub package for the build, to ensure minimal functionality was included. Selecting the stub package also configures the build options such as ROM startup type, ROM monitor behavior, and other necessary functionality.
At this point I have the new MY_TARGET platform template that contains the driver and initialization code tailored to the MBX board platform. To verify the changes I have made to this point, I can build the MY_TARGET stub and run it from the MBX board. This is just a sanity check. Succeeding with this task, I can now proceed with making code modifications for the new board.
Memory layout
The first step is to adjust the memory layout for the new platform. The memory configuration files are made up of the following files found in the powerpc\mytarget\include\pkgconf subdirectory:
- mlt_powerpc_mytarget_rom.mlt: memory configuration file used by the Configuration Tool
- mlt_powerpc_mytarget_rom.ldi: linker script file that defines the memory and section location
- mlt_powerpc_mytarget_rom.h: C macro definition file of memory region details for use at the application layer
Figure 3. Configuration tool memory layout editor
These files are for a ROM startup; the RAM memory configuration files are also found in this subdirectory. Another memory layout linker script file is powerpc.ld, located in the powerpc\arch\src subdirectory, which contains the memory layout macros used. The configuration tool offers the ability to modify the memory layout, as shown in Figure 3. However, this is accomplished initially by hand-editing the .h and .ldi files.
Modifying the memory layout files basically consists of changing the amount of memory-ROM and RAM-in the system, as well as verifying the location of the various sections, such as vectors, code, and heap, to accommodate the MY_TARGET platform. Not being an expert with linker script files, I found it very useful to have linker script documentation available for quick reference while making changes.6
Cache
During this phase of the porting process, data and instruction caches are not necessary in the stub because speed is not a concern until the stub is fully functional. To disable the caches, the macro CYGPRI_ENABLE_CACHES is undefined in the mytarget\include\plf_cache.h file.
Serial communication
For debug purposes, getting a communicating serial port is necessary. A simple polling mode driver can be used to accomplish this. The MBX platform utilizes Serial Management Controller 1 (SMC1) for debug communications. A driver for this serial port is available in the quicc architecture variant. Using this driver, I was able to leverage the existing SMC1 hardware initialization and virtual vector initialization code.
void cyg_hal_plf_serial_init(void) { hal_virtual_comm_table_t *comm; int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM( CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); volatile EPPC *eppc = eppc_base(); static int init = 0; // It's wrong to do this more than once if (init) return; init++; cyg_hal_plf_serial_init_channel(); // Setup procs in the vector table // Set channel 0 CYGACC_CALL_IF_SET_CONSOLE_COMM(0); comm = CYGACC_CALL_IF_CONSOLE_PROCS(); CYGACC_COMM_IF_CH_DATA_SET(*comm, eppc_base()); CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); // Restore original console CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); }
Listing 2. SMC1 serial port initialization
The proper initialization of the virtual vector I/O channel tables is necessary since the stub calls the serial driver through these tables. The virtual vector table, housed at a static location in memory, contains 64 vectors that point to service functions or data. Since these vectors are in a static location, both ROM and RAM startup configurations can use and provide these services. Listing 2 shows the SMC1 serial port initialization function. The call to cyg_hal_plf_serial_init_channel() initializes the PowerPC hardware registers. The CYGACC_COMM_IF_xxx macros set up the virtual vector table I/O channels for serial debugging.
// SIU Initialization lwi r3, 0x00602400 stw r3, SIUMCR(r4) // Enable bus monitor. Disable Watchdog timer. lwi r3, 0xffffff88 stw r3, SYPCR(r4) // Clear REFA & REFB. Enable but freeze timebase. lwi r3, 0x00c2 sth r3, TBSCR(r4) // Unlock some RTC registers lwi r3, 0x55ccaa33 stw r3, RTCSCK(r4) stw r3, RTCK(r4) stw r3, RTSECK(r4) stw r3, RTCALK(r4) // Clear SERC & ALR. RTC runs on freeze. Enable RTC. li r3, 0x00c3 sth r3, RTCSC(r4) // Clear periodic timer interrupt status. // Enable periodic timer and stop it on freeze. li r3, 0x0083 sth r3, PISCR(r4)
Listing 3. PowerPC system interface unit initialization code
Package configuration
The final step before building the MY_TARGET stub template is to remove packages that are not needed at this stage of the porting process. Figure 4 shows the Configuration Tool dialog box for removing the packages. Removing packages can also be accomplished through the command line. The packages removed include the I/O sub-system, serial device drivers, and common error code support. Other packages may be removed to limit the amount of code and functionality in this initial stub build. The packages can be added back once a baseline of operation is achieved.
For this initial build, limited GDB support will be used. This also limits the number of interrupt handlers installed to support these GDB features. To ensure this, we disable the following macros in the saved configuration tool .ecc file:
- CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT
- CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
- CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT
Building the stub
Now we can build the ROM startup stub for the new MY_TARGET platform using the Configuration Tool. The result of the build is a file called gdb_module.img, located in the install\bin subdirectory (this is under the root directory of the saved Configuration Tool .ecc file). Using the GDB binary utilities, this file can be converted to a binary or S-record file for programming into the MY_TARGET platform memory.
Resetting the board and running the new code should cause a GDB protocol message to be sent to the serial port. The message should look something like $T0540:ff05cd8;01:00004664;#92. If this is not received at the serial port, it's time to go through and verify the changes that were made.
Once this stub is up and running, proper board initialization has been achieved. Some additional features that can be added or their operation verified are single-stepping debug support, real-time clock interrupts, interrupt decoding, and asynchronous breakpoints.
Platform porting hints
The following are some basic hints that may be useful when creating a new platform port:
- Since eCos is constantly being maintained, it is important to stay up to date with the latest changes to the platform you used as a baseline. Any new changes and bug fixes can then be rolled into your source code. Each package contains a file named ChangeLog that lists modifications to that package. By using this file and the latest source code, keeping your platform updated can be a manageable process.7
- Use an LED or I/O port to track the program flow through the new stub by switching the LED or I/O port on and off at various points in your HAL code. If no other debug facilities are available, this can be a life saver.
- Trace buffers can be useful to track variable values and other information at different points in the code.
- Assertions can be used to reveal subtle bugs or missing features. By default, eCos does not enable assertions.
- The idle loop can be used to monitor and output variable or hardware registers.
- eCos source contains some test applications that can be used to validate the new platform.
- The eCos ROM monitor program, called RedBoot, can aid in getting additional debug functionality implemented in your system.
Getting some support
Documentation is contained in each of the eCos releases. This documentation includes the eCos User's Guide and eCos Reference Manual. The latest documentation is available, along with the documents in the release package.8
In order to stay updated on the latest code modifications, the eCos repository should be used. The repository can be accessed via browser or through the use of Concurrent Versions System (CVS) tools.
A great source for keeping track of issues and to receive support is the discussion list. I have found the maintainers of this list very responsive, with one- or two-day turnaround on questions-based on the workload of the maintainers. The discussion list is also a good place to post a patch or port that you want considered for adoption into the eCos sources. As a general rule to using the discussion list, it's usually a good idea to go through the documentation and previous posts (using the available search engine) before asking a question on the list. A problem list is also available as a starting point to get issues resolved.9
eCos may not be the solution for every embedded system, but the beauty of it is that you can take it for a test drive at no charge. Additional third-party support packages are increasing the features and functionality offered by eCos all the time, making it an attractive alternative to royalty-based, commercial real-time operating systems.
Related Barr Group Courses:
Reliable Multithreaded Programming
For a full list of Barr Group courses, go to our Course Catalog.
Endnotes
1. Red Hat eCos Public License v1.1 (RHEPL) is available online at http://ecos.sourceware.org/old-license.html [back]
2. For a specific list of processor architectures and platforms supported, take a look at the eCos web site at http://sources.redhat.com/ecos/hardware.html [back]
3. Gatliff, Bill. "Embedding with GNU: GNU Debugger," Embedded Systems Programming, September 1999, p. 80. [back]
4. Gatliff, Bill. "Embedding with GNU: The GNU Compiler and Linker," Embedded Systems Programming, February 2000, p. 66. [back]
5. The eCos discussion list can be found online at http://sources.redhat.com/ml/ecos-discuss/ [back]
6. The Linker Script documentation can be found online at http://www.redhat.com/support/manuals/gnupro99r1/5_ut/b_Usingld/ldLinke… [back]
7. Instructions for configuring a system to use the latest eCos source files can be found online at http://sources.redhat.com/ecos/anoncvs.html [back]
8. The latest eCos documentation can be found online at http://sources.redhat.com/ecos/docs-latest [back]
9. The eCos problem list is available online at http://sources.redhat.com/ecos/problemlist.html [back]
This article was published in the January 2002 issue of Embedded Systems Programming. If you wish to cite this article in your own work, you may find the following MLA-style information helpful:
Massa, Anthony. "eCos Porting Guide," Embedded Systems Programming, January 2002.