Sign in

Not a member? | Forgot your Password?

Search blogs

Search tips

Free PDF Downloads

Advanced Linux Programming

What Every Programmer Should Know About Memory

Introduction to Embedded Systems

C++ Tutorial

Embedded Systems - Theory and Design Methodology

Microcontroller Programming and Interfacing

Introduction to Microcontrollers

More Free PDF Downloads

Recent Blogs on EmbeddedRelated

Two Capacitors Are Better Than One
posted by Jason Sachs

Coding Step 1 - Hello World and Makefiles
posted by Stephen Friederichs

Introduction to Microcontrollers - Ada - 7 Segments and Catching Errors
posted by Mike Silva

OOKLONE: a cheap RF 433.92MHz OOK frame cloner
posted by Fabien Le Mentec

Practical protection against dust and water (i.e. IP protection)
posted by Dr Cagri Tanriover

Specifying the Maximum Amplifier Noise When Driving an ADC
posted by Rick Lyons

How to make a heap profiler
posted by Yossi Kreinin

Vintage robotics!
posted by Lonnie Honeycutt

Little to no benefit from C based HLS
posted by Christopher Felton

DSPRelated and EmbeddedRelated now on Facebook & I will be at EE Live!
posted by Stephane Boucher

Introduction to Microcontrollers

1 - Beginnings

2 - Further Beginnings

3 - Hello World

4 - More On GPIO

5 - Interrupts

6 - More On Interrupts

7 - Timers

8 - Adding Some Real-World Hardware

9 - More Timers and Displays

10 - Buttons and Bouncing

11 - Button Matrix & Auto Repeating

12 - Driving WS2812 RGB LEDs

13 - 7-segment displays & Multiplexing

14 - Ada - 7 Segments and Catching Errors

See Also


Embedded Systems Blogs > Gene Breniman > Lightweight hardware abstraction

Gene Breniman (contact)
Gene Breniman has over 30 years experience in design and development of hardware and software for embedded systems. He has worked in a variety of fields, including full bio

Would you like to be notified by email when Gene Breniman publishes a new blog?


Pageviews: 924

Lightweight hardware abstraction

Posted by Gene Breniman on Jan 31 2012 under Software Development   

Some lessons are tougher than others to master.  You would think that hard fought battles would be easier to remember, but sometimes it just does not work that way.  Recently, I was asked to pick-up a project that had been managed by another employee.  The project was yet another cost reduction project.  The hardware group was tasked with updating a currently shipping product, to reduce the existing failure rate, while at the same time to remove cost from the product.  The redesign caused the engineer to shuffle around pin assignments on the microcontroller in order to free up some of the analog inputs.  There was also a strong desire to make as little change as possible to the existing firmware for this device, so as to limit the scope of revalidating the product.

My first impulse was to jump right in and hack in the changes and move on to something more interesting.  I isolated the changed signals, and started searching through the code for occurrences of the effected pin names.  I was quite surprised when I found over 100 references to one of the pin names.  Fighting against my better judgment, I jumped in and proceeded to go instance by instance and modified the code with #ifdef statements to change all of the reference of one signal for another.  In a day's time, I had the code converted and soon it was happily running on the new prototype.  Not my best work, or my proudest moment, but the work was done and I was free to move back to my real interesting work.

For example:

#ifdef OLD
        PORTB.4 = 1;            // Turn LED off
        PORTB.7 = 1;            // Turn LED off

Soon, it was decided that a few more hardware changes were needed.  A new version of the hardware was developed, with even further pin changes.  We had shipped some of the earlier prototypes off to a remote engineering location, where some testing was being done on both versions of the prototype.  Now I needed to maintain multiple versions of the firmware to support the two different prototypes.  This was already beginning to get ugly quickly.  Now the already messy code was getting even messier.

With the new changes in place the code now looked like this:

#ifdef OLD
        PORTB.4 = 1;            // Turn LED off
        PORTB.7 = 1;            // Turn LED off
        PORTC.2 = 0;            // Turn LED off

One simple change would not have looked so bad.  But take multiple changes, multiplied by a varying number of occurrences and soon the code is really a mess.  But wait, what could I have done differently?  The simple answer is abstraction. From webopedia, I found the following definition for abstraction:

The process of picking out (abstracting) common features of objects and procedures. A programmer would use abstraction, for example, to note that two functions perform almost the same task and can be combined into a single function. Abstraction is one of the most important techniques in software engineering and is closely related to two other important techniques -- encapsulation and information hiding. All three techniques are used to reduce complexity.

Here the idea would be to come up with a way to represent the required functions into a single include file for each version of the hardware.  In this way, a single include statement could be changed in order to build a unique version of the firmware for each of the hardware versions.  In the simplest form,  each portion of the statement in the example could be defined in concept and the actions could be abstracted from the code.

The modified code would then read:

        MODE_LED = LED_ON;

In order for this to work, we need to create include files that contain the actions that have been abstracted from the code.  Three include files are need: old.h, proto1.h and proto2.h.  Each of these files would need the necessary defines to represent the higher level functions or representations of MODE_LED and LED_ON.

For old.h:

#define MODE_LED        (PORTB.4)
#define TURN_ON         1

For proto1.h:

#define MODE_LED        (PORTB.7)
#define TURN_ON         1

For proto2.h:

#define MODE_LED        (PORTC.2)
#define TURN_ON         0

Now by including the correct include file all of the necessary changes can be hidden, leaving the code cleaner and far more readable.  Again, I had learned this lesson before, but somehow when I was faced with a similar problem, my first choice was the wrong one.

May your first choices serve you better.


Rate this article:
Rating: 3.5 | Votes: 2
posted by Gene Breniman
Gene Breniman has over 30 years experience in design and development of hardware and software for embedded systems. He has worked in a variety of fields, including avionics, life sciences and automatic test equipment engineering.

Previous post by Gene Breniman: A true pioneer passes away... A farewell to Ritchie.
all articles by Gene Breniman

Comments / Replies

There are no comments yet!

Sorry, you need javascript enabled to post any comments.