• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

C project organization: software, hardware.

Status
Not open for further replies.

astronomerroyal

New Member
Hello,

I'd like your advice on matters concerning designing/organising firmware projects using C.

Being a 30 year old novice I've finally realized I'm going to have to take responsibility for my behaviour and rewrite my firmware - complete misuse of header files, too many global variables etc. I'd like to get it right this time, hence this request for advice. For the record I'm using MPLAB, C18 compiler and 18F devices, naturally.

1) Michael Pont (Professor Michael J. Pont, ESL, University of Leicester) in his book 'Embedded C' (Section 5.2) discusses a 'file-based object oriented' style using C. I believe the source file is analogous to the class, and the declarations of static variables and function prototypes in the source file are then the private members of the class, as opposed to things declared in the header file which are visible publicly. He suggests this approach for its maintainability and code reusability.

Any thoughts/experience with this approach? Pros/cons, when to choose it etc...

2) Pont also advocates the use of special-purpose header files e.g. MAIN.H is the project header that contains oscillator freq, #includes the device header, perhaps also statements like

Code:
typedef unsigned char tByte;
which offer a shorthand, but also, brilliantly, allows one to change from an 8bit system to a 16bit system, for example, with relative ease. Then another header PORT.H containing #defines for pin names etc.

Maximizing the use of headers is probably a no-brainer but it took me weeks to understand this aspect of C. Anything to add here?

3) Jack Ganssle (The Ganssle Group - Home) in 'The art of designing embedded systems' (mostly for large teams of programmers rather than hobbyists) advocates modular hardware design e.g. uC for purpose A and another uC for purpose B, rather than one uC that does both. (Recommended for reducing development times of huge projects = $$$.) Personally, I like putting an LCD+keypad interface on almost all my projects - that's ~20pins used straight away. I was wondering if it made sense to have not just modular code for the user interface but also a dedicated uC that dealt with the keypresses/menu system/LCD and sent any resultant data to the other uC(s) via, say, I2C. Since I'm always pin-limited it would finally allow me to use In-circuit programming and debugging - seems like a huge motivation. Your thoughts?

As always, many thanks.

Here's my project - a motorized dolly for fancy time-lapse photography. Shiny on the outside, rubbish on the inside. And apparently 90 degrees rotated.
 

Attachments

Last edited:

Papabravo

Well-Known Member
You need to take what the experts say with a slighly jaundiced eye. Their motivation is to sell books and magazine articles. Just like every writer develops a style, so does every programmer. In order of importance
  1. First make it work
  2. Then make it fast(small)
  3. Then make it elegant
 

Mr RB

Well-Known Member
I think i'm with Papabravo here.

With embedded the micro itself uses globals. I use global variables everywhere as the only alternative is compiler handling variable stacking, and the compiler does a worse job of it than me.

And header files are nice on large projects (like a large Windows C program) but really for embedded? I've done commercial apps with 10 char size variables total, 5 functions, and maybe 200 lines of code. So the most professional way (to my thinking) for that project was ONE file... Why would you want to mess about switching from one file to another to see separate parts of the same code??

Of course if a professor said that he'd have nothing else to put in a book.

And I think Mr Ganssle has never been a commercial prodcut developer asked to get 20 complex functions all done at the same time by one tiny cheap 12F675 chip...

A pro can get that one chip to do the job, where a Uni student can afford to use a chip for the keyboard, one for the display one for comms, one to scratch his butt, etc etc. Which is why so many of those students turn out to be "academically challenged" pros severely limited by outdated concepts like the "proper way' of doing things they have no clue about the REAL best way of doing things.

PS. Cool motorised dolly. :)
 
Last edited:

Torben

Well-Known Member
I have to (mostly) agree with Papabravo and Mr RB--but only for stuff like embedded programming or very small one-off programs or scripts. In such cases you need to take the limitations of the environment into account first, and squeeze every last bit of performance out that you can.

In real life I'm a professional programmer but I program mostly for larger systems, often hosted in multi-server farms. The projects are large in such cases (sometimes several tens or hundreds of thousands of lines of code) and in those cases, I would *definitely* recommend a well-thought-out, modular code structure. In embedded programming the problem set is different, though. In the larger environments you often have to deal with multiple programmers; you need to make sure that one part of the code won't scribble on another part's memory or name space, and so on.

I don't know about professional embedded programming (other than for embedded Linux on ARM, which is different from ASM/C on a PIC or 8051) but I'm a hobbyist with a little experience there, and I've found it useful to ignore many of the rules that I've typically considered vitally important in programming projects in order to get the code to make sense.

For one thing, many of these rules for large projects are there because without the compartmentalization you get from modularized code stucture you don't stand a hope in hell of understanding the whole application once it gets past a certain size. It might work but trust me, you'll never be quite sure why. With embedded programs you don't have that problem so much, since the code size is self-limiting. A couple of years back I wrote some C for a sonar rangefinder based on an AT89C4051. With only 2k of code space it is totally reasonable to have all the C code in one file (with includes for #defines etc., of course, so I have mnemonics for the various ports and so on).

Having said all that, I still find it handy to keep particularly useful code snippets around in .h files for easy inclusion in future projects, or even just for copy-pasting into new projects. (Back in the early 90's I replaced many of the Turbo Pascal built-in routines with faster assembly routines or just implemented things which TP didn't include, and did the same thing--Google 'SWAG pascal' and you'll get the idea.) Just make sure that if you do this, you use a reasonable naming convention for constants, globals, and functions so that one .h file's stuff doesn't conflict with others, and you'll be fine.

Wow. That was wordy. Forgive me, it's my birthday, and I like to talk. So I'm talkin'. :) Good luck.


Regards,

Torben

P.S. One thing I've learned over the years: it's easy to fall into the trap of not letting a job get done because you get all tied up in trying to do things in the best possible way. Don't. You'll figure out how you work best as time goes on, and if it matters enough, you'll go back and fix your past mistakes. That's just experience. It's a pain in the butt and it's totally worth it. And it never ends. ;)
 

Pommie

Well-Known Member
Most Helpful Member
I have to agree with everything stated above. For an example of how unwieldy a project can get when you use too many files, have a look at the Microchip USB files.

Mike.
 

Papabravo

Well-Known Member
A word about elegant code. Justice Potter Stewart once observed "...I can't define [WORD CENSORED]ography, but I know it when I see it." Once you see a piece of elegant code you will know it when you see it. The most elegant code I ever saw was by Alan Holub in his book "Compiler Design in C". The most inelegant code I've ever seen is the Gnu Compiler Collection. It is obtuse, incomprehensible, and totally opaque, but it works.

Elegant code is a joy to read, intuitive, and highly educational. Seek it out and respect it.

Wow! That's pretty cool censoring technology, I'm impressed.
 
Last edited:

astronomerroyal

New Member
Thanks for the replies - you write it, I'll read it.

I'll leave the object-oriented style for desktop-sized applications - I was just surprised to see the topic raised as an option for hobby-sized embedded projects.

Now for the bits I'm unsure about. If I may, I'd like to dwell upon the modular hardware issue.

In order of importance
  1. First make it work
  2. Then make it fast(small)
  3. Then make it elegant
1) Yes, get it to work.

2) Fast, small? I like modular code, small functions that more or less fit on the computer screen in one go. Inline assembly - there's nothing sexier. As for hardware - is using two interconnected uCs, instead of one large uC, 'small/fast'? The parallel nature makes it fast, individually smaller, fewer interrupt conflicts.

3) Is it 'elegant' to be able to physically plug a 'UI module' into a 'functional module'? This is sort of how I arrange my breadboards - albeit still using one uC. Seems a rather elegant way of avoiding memory and pin-limit problems. I have several practical (i.e. not philosophical) reasons for going with modular hardware (for certain projects), and wonder why more hobbyists don't go for it.

This is something of an inspiration for my projects - completely modular hardware,
camBLOCK - Now you have control

Don't get me wrong, I do have a mind of my own, just keen to get as many opinions as possible.
 
Last edited:

astronomerroyal

New Member
"...I can't define [WORD CENSORED]ography,..."

I believe 'pronography' is the generally accepted solution to that problem. I've ordered a cheap copy of holub, shall give the code a look. Thanks.
 
Last edited:

DirtyLude

Well-Known Member
Now having three microcontrollers that I'm working on, it's of particular interest to me to seperate all hardware specific functions and generic logic so I can reuse code. I try to avoid anything hardware or uC specific within my main source files.

Unfortunately, you work with both uC's that have 512KB ROM and uC's that work with 4K ROM, it only helps so much. Still, I'm starting to get a very simple standard of my own down for hardware interface libraries and I've got two projects now (well, one project with 2 parts) that I can share the main code and functionality with different hardware routines for two different uC's.
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top