cancel
Showing results for 
Search instead for 
Did you mean: 

What is a good methodology for object oriented peripheral code in C?

Roth.Ian
Associate II

I have a project that involves a STM32F7 controlling a stepper motor through GPIO. I have now been tasked with redesigning it with a ST L6470, a motor control IC which has a SPI interface. I would like have a shared codebase so that a simple #define could be used at compile time to choose between GPIO or SPI code depending on the board used. Examples of polymorphism in C such as the linux device driver code and GObject are difficult to understand and perhaps not a good example for microcontroller code.

The solution must be C11 compatible and compiled in IAR EWARM.

13 REPLIES 13
Pavel A.
Evangelist III

Keep It Simple is the best of methodologies for embedded C.

Another is to make it Somebody Else's Problem (hire a contractor, let him sweat instead of you).

-- pa

MikeDB
Lead

OOD sounds like a bit of overkill for a motor controller.

Piranha
Chief II

OOD is needed only if You have multiple motor instances in one project. In C it can be implemented by defining a structure for object and passing a pointer to it in API functions. If it's only one motor instance in a project, then make one .h file with API definition (set of functions) and multiple .c files for different API implementations. To switch between .c files with a #define, put #ifdef/#endif pair on top/bottom of .c files so that unneeded files are effectively empty.

S.Ma
Principal

Unclear what you want to do and where OO makes things more modular.

More details are needed.

Are the higher level source code the same and plumbing below either to GPIO or SPI?

gw48
Associate II

OOP in C is doable, but for small projects, not likely worth the complexity. However, you can gain many of the advantages of OOP through well structured code, using opaque data types, and using C’s built-in techniques for separating private/public interfaces. Don’t worry about inheritance, use composition instead. Those steps alone keep C plain and simple for none-OOP readers, but give OOP-experienced folks a lot of the “structure�? they like to see.

As for polymorphism, there are fancy ways, but in your case, I’m inclined to think #ifdef is suitable. I use it a lot for the same purpose you’re looking at (building with various optional hardware drivers).

I have a master mProject.h file which declares project level constants. That file #includes mLocal.h which is specifically for the purpose of triggering versions of builds.

(I prefix our code with a “namespace�? of “m�? so I can easily identify “ours�? vs. “theirs.�?)

Two techniques come to mind:

In mProject.h, before mLocal.h is included, you have

// Define a build options  to choose from, and a build variable 
 
#define mMOTOR_CTLR_GPIO  (1U)
#define mMOTOR_CTLR_SPI   (2U)
 
#define mBUILD_WITH_MTR_CTLR_TYPE    mMOTOR_CTLR_GPIO // this is the default build

In mLocal.h you have

// Affirm or override the mProject build variable in your own personalized mLocal file
 
#undef mBUILD_WITH_MTR_CTLR_TYPE
#define mBUILD_WITH_MTR_CTLR_TYPE    mMOTOR_CTLR_SPI // this overrides mProject.h

Next, in your application code files, where you might have

#include “mCtlr_motorGpio.h�?

You would now have

// The file to include is determined based on your build option variable
#if (mBUILD_WITH_MTR_CTLR_TYPE == mMOTOR_CTLR_SPI)
#include “mCtlr_motorSpi.h�?
#else
#include “mCtlr_motorGpio.h�?
#endif

Obviously you could skip mLocal.h and use just mProject.h. However, the advantages of mLocal.h are 

  • mProject.h is always defined as the baseline default and doesn’t get butchered by whoever needed a special version and didn’t undo the changes. (mLocal.h needs to exist, but it doesn’t need any content.)
  • mLocal.h is NOT checked into source code control so that each developer can have their own version to manage local builds during development.

Think it just needs to use structures passed as pointers, and not use a shed load of global variables.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Yes that's how I do my real-time (audio) designs. A proper OOD design would add too much non-determism to the timing which I imagine would be bad for a motor

This is a tempting solution for the short term, but multiple motors is a possibility in the future.

Right, I don't need a complete OO solution. I am thinking just a shared structure with pointers to the to functions that each codebase would have such as:

initialize

start motion

stop motion

is moving