CMP EMBEDDED.COM

Login | Register     Welcome Guest  
HOME DESIGN PRODUCTS COLUMNS E-LEARNING CONFERENCES CODE FORUMS/BLOGS NEWSLETTERS CONTACT FEATURES RSS RSS

Guidelines for using C++ as an alternative to C in embedded designs: Part 2
Encapsulation of Expertise Using C++ Objects



Embedded.com

Other Possibilities
The ideas presented here may be developed further to add additional capabilities or to address different, but similar, problems. Possibilities include:

* Add an exclusive-OR operator: ^=

* Provide a means of retrieving the shadow data (perhaps by overloading the int casting operator)

* Treat a port as an array of bits (overloading the [] operator)

* Accommodate arrays of ports (at consecutive addresses)

* Apply the same ideas to handle indexed ports, where the "address" of a device's internal register needs to be written first, followed by the actual data reading or writing

C++ and an RTOS
When an embedded software application is being developed using a real-time operating system, there are some distinct benefits to be gained from the careful use of C++.

The two clear advantages are: application programmers do not need to have detailed knowledge of the RTOS programming interface and the application code is likely to be portable to an alternate RTOS, if a change is necessitated.This topic is quite large and only a few aspects may be considered here:

Task/Object Creation. Most RTOSes have a conventional C function library which serves as an application program interface (API). This may be proprietary or may conform to a standard (like POSIX, for example). In either case, many API calls may be quite complex, with numerous parameters. This is an ideal opportunity for encapsulation of expertise.

Consider the creation of tasks. A base class could be designed which characterizes a generic task. The key components of the class would be a constructor (which creates the task), a destructor (which deletes the task) and an empty virtual (i.e. replaceable) main() function.

An application task could then be defined by deriving a new class, which replaces the main() function with the actual task code and adds in other requirements (like the task stack perhaps).

Instances of the task could then be created by simply instantiating objects from the class. Note the separation of task definition (creating the class) and the actual creation of tasks (object instantiation).

The same kind of approach may be taken to the handling of other RTOS objects like mailboxes, event flags, semaphores, timers, queues, pipes etc.

Thread Local Objects. C++, like C, has no in-built concept of a thread or a task " the language essentially assumes a single thread of execution. By creating a class that represents a task, this shortcoming is effectively overcome. This brings with it some useful benefits. A key one is the ability to have thread local objects (and variables).

When using an RTOS conventionally, it may be quite common to create a number of identical tasks, each of which operates on different data, while sharing code. This is a challenge as there is no straightforward way to have conventional variables that are specific to a particular task (i.e. thread local variables).

By adding member variables to the task definition class, each resulting object has its own copy of each variable (unless they need to be shared, in which case they need to be declared static).

An extension of this idea is thread local variants of other RTOS objects. If the task definition class includes a declaration of a semaphore (for example), that object will be created specifically for each task instance and be inaccessible elsewhere.

Paired Operations. It is a common requirement in real time applications (with or without an RTOS) to define paired operations: two actions that complement one another and are executed at the beginning and end of a code sequence.

For example, if a set of instructions must be executed without any possibility of interruption, it may be preceded by a disable interrupts and succeeded by an enable interrupts. It may be problematic to ensure that both operations are performed, particularly if the code logic is complex.

An object oriented "trick" can provide a simple way out. All that is required is a simple class which only contains a constructor and a destructor. The constructor disables interrupts and destructor enables them again.

<>Then it is simply a matter of instantiating an instance of this class (an object) at the head of a block. Interrupts will be turned off on entry to the block and turned on again when the object goes out of scope " i.e. when execution leaves the block by whatever means. The structure of the code looks like this:

{
object declaration
(constructor disables interrupts)

(destructor re-enables interrupts)
}

This approach has numerous applications. Others include: locking resources, turning on/off an RTOS scheduler and providing pre-amble and post-amble for an ISR.

Here is some possible code for a class to provide device locking using an RTOS semaphore:

class Device_Locked
{
private:
        static Semaphore device;         // NB static
public:
        Device_Locked()

        { device.acquire(); };
        ~ Device_Locked()
        { device.release(); };
};

To read Part 1, go to: Why is C++ not more widely used?

Colin Walls has over twenty-five years experience in the electronics industry, largely involved with embedded software. A frequent presenter at conferences and seminars including the Embedded Systems Conference he is a member of the marketing team of the Embedded Systems Division of Mentor Graphics.

Click here to see Part 1.

1 | 2 | 3 | 4

Rate this article: Low High
Current rating
  • .
Embedded.com Career Center
Looking for a new job?
SEARCH JOBS

Browse all jobs

SPONSOR
RECENT JOB POSTINGS



TECH PAPER
WEBINAR
WEBINAR
WEBINAR




 :