Electronic Design

  
Reprints     Printer-Friendly    Email this Article    RSS        Font Size     What's This?


[Design View / Design Solution]
Partition Hybrid Linux/RTOS-Based Systems
Analyzing "hard" and "soft" real-time deadlines is critical when determining whether to assign application-software containers to Linux or an RTOS.

David Kalinsky  |   ED Online ID #10269  |   May 12, 2005


Partitioning a multiprocessor system poses a challenge to embedded-systems architectural designers. This is particularly true in complex multifaceted systems that must provide both "hard" time-critical functionality and large-scale information-processing services. To deal with these disparate requirements, such systems often contain a mix of different processors to handle hard real-time aspects, such as digital signal processors (DSPs), plus powerful conventional processors (CPUs) for computation-intensive information processing aspects of the system.

Different operating systems, such as embedded Linux and real-time operating systems (RTOSs) best support these different processors in achieving their disparate objectives. Of course, software running under one operating system on one type of processor may well need to communicate with software running on another type of processor with a different operating system. Hence, a globally uniform communication mechanism to support such interprocessor communication is desirable.

High-Level Partioning Of Complex Systems
One methodic approach to multiprocessor software design is the CODARTS/DA approach of Hassan Gomaa (Software Design Methods for Concurrent and Real-Time Systems, Addison Wesley SEI Series in Software Engineering, Reading Mass., 1993. ISBN: 0201525771). CODARTS/DA is short for COncurrent Design Approach for Real-Time Systems/Distributed Applications. Many of its ideas can be brought forward and tweaked for use with new technologies, such as heterogeneous multicore system-on-a-chip (SoC) hardware platforms that may contain both DSPs and powerful conventional CPUs in an integrated package.

When doing system partitioning, eventually one wants to identify the software "tasks" of the system. Each task will be single-threaded (internally sequential) and can run in parallel with one another in a concurrent software system. However, this is not necessarily the first goal of system partitioning. In highly complex embedded systems, the system may eventually be implemented as hundreds or thousands of concurrent tasks, each possibly containing tens or hundreds of software functions. Those amounts of tasks and functions make decomposition of a system directly into tasks unwieldy. Hence, it's best to approach the identification software tasks gradually. Initially, that involves identifying larger-scale "chunks" of system functionality that may later be broken down into individual tasks.

Fortunately, many of today's operating systems are embedded, and can provide for such a "chunking" mechanism. Each chunk can be considered a "container" that holds a number of software tasks (Fig. 1).

Different embedded operating systems have different naming conventions for these chunks or containers. For example, the containers are called "Processes" in Embedded Linux, and the tasks are called "Threads." On the other hand, the OSE RTOS calls containers "Blocks" and tasks are "Processes." (Be careful of the differing terminologies. The word "process" can mean vastly different things to the particular OS.) Other RTOSs may refer to their containers by names such as "Address Spaces" or "Partitions." Some RTOSs lack a chunking or container mechanism altogether.

Embedded operating systems that support such chunking or containerization make it possible to set up memory-protection barriers between the containers (in conjunction with processor silicon providing appropriate hardware MMU support), as shown in Figure 2.

In this way, the tasks collected in one container are protected against many failures caused by the incorrect operation of tasks in other containers. For instance, a task attempting to point a stray pointer across an intercontainer memory-protection barrier and overwrite data or program memory on the other side would be barred from doing so. Consequently, a fault would be declared. Each container also could have its own local pool of RAM memory buffers. Therefore, tasks in other containers could not exhaust buffer capacity even if they misbehaved badly. As a result, faults would be localized rather than damaging other containers.

Identifying these containers for tasks is an early step in the design of a complex embedded system. Each container will eventually hold a number of software tasks that together perform one major service. This service should be as independent as possible of services provided by other containers. Decomposing a system into containers is closely tied to the application services that the system must provide, as well as to the problems it's expected to solve. The content and structure of the project's requirements-specification document becomes a good guide for initially decomposing the system into containers. In many complex systems, containers typically supply the following kinds of major services:

  • Automatic control
  • Coordination of other services
  • Data collection
  • Data analysis
  • Server (often containing data stores or I/O devices)
  • User services (e.g., operator interface)
  • System services (task scheduling, network communication, file management)
  • Application Example
    A good example is a medical bedside system for a hospital intensive-care application, which could well contain a number of containers of various kinds (Fig. 3). Real-time medical data is acquired in a "patient vital-signs data acquisition" container. It would regularly sample various incoming signals, including core body temperature, peripheral limb temperature, blood pressures at several locations, respiration, blood oxygen concentration, ECG (electrical signals from the heart), cardiac arrhythmia (sequences of abnormal heartbeats), and perhaps EEG ("brain waves"). Note that this one container provides a much larger service than simply handling a single kind of medical measurement.

    If this medical system also were to be involved in the computerized administration of fluids, such as drugs or nutrition to a patient, the system then would need a separate "fluids infusion control" automatic-control container. If the system were to interact with doctors and nurses through voice input and output, it then would also need a "human voice communication" user services container. If the system is going to handle medical records of patients and documentation of their stay in the intensive care unit, the chore can fall to a "patient data" store container.

    Also, if the system were smart enough to check for drug interactions with other drugs and their interactions with the patient's condition and nutrition, this would be done in a "drug interactions checking" coordination container. A separate "drug interactions knowledge base" server container could support processing.

    The various operating-system services supporting each processor in our hybrid multiprocessor embedded system would be in system-services containers-one per processor. Consequently, a processor running embedded Linux would have a "Linux system-services container," and a processor running an RTOS would have an "RTOS system-services container."

    Partitioning Containers Into Tasks
    Once a first-cut partitioning of an application system into high-level containers is accomplished, the containers should be further decomposed internally into the individual tasks that will run within them. Each task is single-threaded (sequential) and can run in parallel with other tasks in its container, as well as in parallel with tasks in other containers in a concurrent software system. Remember that each individual task can possibly contain tens or hundreds of software functions: A task is a unit of concurrency, but it's not the smallest unit of software architectural design. Most tasks consist of a number of functions that are executed sequentially within the task. In embedded systems, individual tasks typically provide the following sorts of services:

  • Handling a single asynchronous input or output device
  • Executing software that must meet a single-time deadline
  • Performing a large calculation
  • Managing a large data store
  • Executing all software that must run at a single point in time
  • Executing all software that must run periodically at a single frequency
  • To continue with our medical intensive-care example, the patient vital-signs data-acquisition container may house a number of tasks that would interact with a number of patient signal sensors. These sensors could supply medical measurements at different frequencies and at different times. Device-handling tasks would include Get Patient Core-Temperature Signal, Get Patient Arterial-Blood-Pressure Signal, and Getting Patient Central Venous-Blood-Pressure Signal.

    The Get Patient Arterial-Blood-Pressure Signal task might provide its output to an additional task called Analyze Arterial Blood Pressure for Systolic, Diastolic, and Mean Values. This extra task would perform some data filtering, waveform analysis, and perhaps pattern recognition on its inputs. We then see that this data-acquisition container could well contain a "pipeline" of several tasks for each sensor from which it's acquiring raw data, resulting in perhaps tens or more tasks within this one container.

    Upon completing a first-cut partitioning of containers into individual tasks, the first-cut higher-level partitioning of the system into containers should be re-evaluated and perhaps modified in an iterative way. This may cause changes in decomposing the containers into tasks, or tasks may be reassigned to different containers. Timing requirements imposed by application needs may also affect this two-level partitioning.


    <-- prev. page     [1] 2     next page -->

    Reprints   Printer-Friendly  Email this Article  RSS    Font Size   What's This?


  • Network-On-Chip Tools Arrive for The Masses
  • Tackling System Design Challenges Through Early Verification
  • ESL Tools Take Center Stage As Designers Move Up
  • Parasitic Extraction Tool Targets Next-Generation Custom ICs
  • Synopsys Jumps Into ESL-Synthesis Pool
  • Verify Control Systems Before Committing To Hardware
  • You're Using How Many FPGAs?
  • Tool Up For The FPGA Blitz
    1) Build A Smart Battery Charger Using A Single-Transistor Circuit
    (179 views today)
    2) Hot Hands For Some Cool Rock: Motion Sensing Meets Audio Engineering
    (168 views today)
    3) What's All This Transimpedance Amplifier Stuff, Anyhow? (Part 1)
    (87 views today)
    4) GPS-Derived Grandmaster Clock Delivers Ultra-Precise Time And Frequency Sync
    (77 views today)
    5) Downconverting Mixers Lower Power Consumption While Improving Performance
    (63 views today)
    ALL TOP 20



    POST YOUR COMMENTS HERE
    Name:

    Email:
    Your Comments:

    Enter the text from the image below


    Please refresh the page if you have trouble reading this text.

    Search Electronic Design
         
      
     
    Web Seminar
    Sponsored By:
    Title: Read Pacing: A Performance Enhancing Feature of PCI Express Gen 2 Switch Devices
    Speakers: 
    Date: 07/01/08
    Register: 

    Electronic Design Europe Electronic Design China EEPN Power Electronics Auto Electronics Microwaves & RF
    Mobile Dev & Design Schematics Find Power Products Military Electronics EE Events Related Resources