QP/C is a lightweight, real-time event framework (RTEF) designed for embedded systems, such as microcontrollers but also embedded Linux/POSIX. The QP/C software framework provides the core runtime services needed to build event-driven applications based on Active Objects, Hierarchical State Machines, and asynchronous event delivery.
As a software component, QP/C supplies a well-defined set of abstractions and execution semantics that can be integrated into a larger system architecture. It provides both:
The primary goals of the QP/C component are:
The following diagram (Figure SRS-BLK) illustrates the context in which the QP/C component operates within an embedded system.
[01] The integratin QP Application:
[02] The QP Framework component:
[03] The Board Support Package (BSP) provides:
[04A] The Real-Time Kernel provides scheduling and execution context for the Active Objects. This could be one of the kernels built-into QP/C Frameworks (QV, QK, or QXK); or
[04B] Alternatively, QP/C Framework can operate with a 3-rd party RTOS kernel, or alternatively, a General-Purpose OS (e.g., Linux/POSIX or Windows);
[05] The Target Hardware (MCU + external components). The underlying microcontroller or processor on which QP/C executes.
Like most event-driven systems, the QP/C Framework is based on inversion of control, which means that the control of code execution resides in the QP/C Framework rather than the QP/C Application based on QP. Specifically, to handle events, QP/C Framework component calls the QP/C Application, and not the other way around. Of course, QP/C Applications can also call services provided in QP/C Framework, but the main flow of control always begins with the QP/C Framework.
That inversion of control gives the event-driven infrastructure (QP/C) all the defining characteristics of a framework rather than a library.
The main difference between a framework and a library is that when you use a library, such as a conventional RTOS, you write the main body of each thread, and you call the library code that you want to reuse (e.g., a semaphore). When you use a framework, such as QP/C, you reuse the main body and write the code it calls (inversion of control).
The mechanism for deriving an application from a software framework, such as QP/C, is by inheriting the base classes provided by the framework and specializing them for the application at hand. (See also the extensibility characteristics of a framework enumerated above.)
The use case diagram depicted in Figure SRS-USE shows the main users and typical use cases they engage in.
[1] QP/C Application use cases (use QP/C Framework [2] use cases):
[2] QP/C Framework use cases:
A reusable architecture, like the QP/C software framework, needs to be adaptable to a wide range of application areas and target hardware selections. For that, QP/C needs to be highly configurable. Whenever this SRS mentions "configurability", it explicitly specifies which of the following types of configurability is required:
Compile-time configurability means that the specific configuration option (out of a given range of possibilities) is chosen at compile-time and cannot be changed later (e.g., at run-time). Compile-time configurability is typically used for:
Run-time configurability means that the specific configuration option is chosen at run-time. Unlike compile-time configurability, run-time configurability has a finer granularity, usually on an object-by-object basis. It is typically used for: