These assumptions do no longer hold in the field of distributed embedded real-time systems. There is a variety of different hardware architectures and operating systems on the embedded market which creates a large number of diverse execution platforms. Resources like processor time and memory are scarce and one component can easily influence others by consuming too many resources. Distribution issues play an important role as well. Execution times are much larger when a component on different node has to be contacted.
So on the one hand, to produce a correctly working embedded real-time system all properties of the execution environment have to be taken into account and the components have to be adapted to this environment. On the other hand, the (base) functionality of these components is still independent of a special execution environment. To overcome platform-specific components we propose a component model that separates the component's functionality from platform-specific issues like concurrency, synchronization, and distribution. Components are developed in a platform-independent model and are later mapped to execution environments that introduce platform-specific features.
In principle, a component can receive any number of events at the same time and therefore many event handlers may be executed concurrently. When event handler access shared data these accesses have to be synchronized. As shown in [3] synchronization can be separated from the algorithmic code by attaching special objects that encapsulate the synchronization strategy. Each synchronization object can either implement one basic synchronization strategy or can be built from a set of basic synchronization objects. In our model synchronization takes place when a component receives an event on an input port. So each synchronized component has to specify a synchronization strategy and a mapping of its ports to that strategy.
An embedded application that was developed using our component model consists of a directed graph of connected components. Since all components are passive there is no internal activity inside the application. Instead the application is activated by external events that are created by the environment, e.g. in response to a hardware interrupt or an expiring timer. Each external input event generates a chain of internal events when it is propagated through the graph of components. Ultimately these events will generate external output events that are consumed by the environment. The application developer can annotate such event chains with timing information that is essential for the correct behavior of the embedded system. Like in [4] the timing information shows end-to-end constraints for related input and output events.
After the location of a component is known the execution times of its event handlers can be estimated or measured. From the event handler's execution times the execution time for a chain of events can be computed.
The next step is to assign tasks to chains of events. Although it would
be possible to create a new task for each event handler activation this
is highly inefficient and can be avoided, e.g. when only one output event
is generated by this event handler. For these tasks a schedule has to be
created.
This schedule must also take into account the synchronization requirements
of the components.
Finally when a schedule has been found, localized versions of the components
are generated.
These localized versions contain the event handlers, synchronization
code, and code to implement the task schedule.