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

Reentrancy
As mentioned earlier, there is a possible issue with the reentrancy of code. The wop class, as it stands, is vulnerable if objects of this class are likely to be accessed by multiple program threads " i.e. tasks in a multi-tasking system or interrupt service routines as well as mainline code. If the interrupt occurred between updating of the shadow data and writing to the port, problems would result.

As is common in many real-time programming situations, imparting reentrancy is a matter of locking and unlocking a resource. To do this we need to extend the class slightly by adding two further (private) member functions:

class wop
{
            int shadow;
            int* address;
            int initval;
            void lock()                 { };     // dummy functions
            void unlock()             { };
public:
            wop(long, int);                     // constructor
            ~wop(); // destructor
            void operator|=(int);            // overloaded
            void operator&=(int);         //     operators
};

For the moment the two functions " lock() and unlock() " are dummies and do nothing. It is possible to imagine how they might really work. Perhaps they would simply disable and re-enable interrupts. Some possibilities will be discussed later.

These functions are used to make the two operator functions reentrant, thus:

void wop::operator|=(int val)
{
            lock();
            shadow |= val;                      // set bit(s) in copy
            *address = shadow;             // update port
            unlock();
}

void wop::operator&=(int val)
{
            lock();
            shadow &= val;                     // clear bit(s) in copy
            *address = shadow;               // update port
            unlock();
}

To implement these functions in the most flexible way, it is possible to take advantage of the object oriented capabilities of C++. If the functions are made replaceable (virtual), new variants may be deployed without further changes to the class:

class wop
{
        int shadow;
        int* address;
        int initval;
        virtual void lock();                   // replaceable functions
        virtual void unlock();
public:
        wop(long);                                 // constructor
        ~wop();                                      // destructor
        void operator|=(int);                 // overloaded
        void operator&=(int);              // operators
};

A new class - rwop - may be derived from the wop base class, which inherits all of its characteristics, but adds function locking functions:

class rwop : public wop
{
        int         flag;
        void lock()                 // replacement functions
        {
                while (flag)
                        ;
                flag = 1;
        };
        void unlock()
        {
                flag = 0; };
public:
        rwop(long, int);                 // constructor
};

The lock() and unlock() functions now use a private member variable (flag) to control access to the object. (This is not strictly reentrant, but serves to illustrate the point for the moment.) A new constructor is required:

rwop::rwop(long port,     int init=0)   :   wop(port,  init)
{
        unlock();
}

This simply executes the wop constructor code and calls unlock().Now the application programmer can use the rwop class in exactly the same way as wop was used and does not really need to know that anything has been changed:

main()
{
        rwop out(0x10000, 0x0f);

        out |= 0x30;                     // set bits 4 and 5
        out &= ~7;                     // clear bits 0, 1 and 2
}

Using an RTOS
If reentrancy is needed because an RTOS is in use, it is logical to use the services provided by the kernel to create a reentrant derivative of the wop class:

class vwop : public wop
{
        int* mbox;
        int err;
        void lock()             // replacement functions
        {
                sc_pend(&mbox, 0, &err);
        };
        void unlock()
        {
                sc_post(&mbox, (char*)1, &err);
}; public:
        vwop(long, int); // constructor
};

In this case a mailbox is used to store a token. A binary semaphore is another - perhaps more likely - way to implement the flagging. Again the application programmer can use the vwop class in an identical way to the earliest wop class.

The vwop class successfully encapsulates two separate, mutually exclusive fragments of expertise: knowledge of the write-only port hardware and RTOS programming experience. The application programmer needs no awareness of either.

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




 :