How to write better code for your projects ?

Hi all...

I've written code for my stuff at home. You know, the stuff you experiment with. Not meant to be pretty or a full blown project. If it is something I will use in the future - like an LCD init function - I fully document it and place it in a special "custom" folder.

I can write code and it is good. I have a EE and I've being working for 2 years now. Little stuff like test boxes and the like are no problem. At work, I was told I'm going to get a whole project soon - the boss was impressed with a silly test box I made, now he thinks I can make a space shuttle. Are they all this clueless ?. I know each part of the design so I'm not panicking just yet :-). I'm thinking how to implement the different parts but I don't feel comfortable writing this project like I did my senior project. BTW my senior project worked with very few glitches.

I just feel I need more info on writing code for embedded systems (that's a good magazine: Embedded Systems Programming ). Before I start cranking out code, I'd like to get more info on ways of writing code. Can you suggest a book or reference where to start ?

Thanks

BTW no need for a RTOS. The project is not that complex. It's going to use a microchip PIC18Fxxxx. I haven't decided which one yet.

Reply to
Rodo
Loading thread data ...

No. You're probably just being tested. Just about every programmer eventually gets a "I'll never be able to do all this by myself" project. Ie, the boss knows you can write the components, but wants to see how you handle having to organize a larger project.

I'd look at an existing projects or programs that are similar to what you will do and see how they were laid out. I don't know any books off the top of my head.

I'd start by mapping out what the high level components are going to be and how they will interact with each other. When you've got the large chunky jobs and modules figured out, then subdivide them into smaller pieces. It doesn't have to be incredibly detailed, just enough to give you a roadmap.

You don't have to do everything by yourself either; draw up a diagram of what you are planning and show it to your boss and coworkers to see what they think.

--
Darin Johnson
    "Floyd here now!"
Reply to
Darin Johnson

I'd recommend reading a few books on software engineering, if you haven't done that yet. Look for books that aren't about how to program, but about how to manage programming.

"Code Complete" by Steve McConnell is as good a place to start as any. You can read it a bit at a time, and it's a fast read. I've been doing embedded programming for over 20 years and while I don't agree with everything McConnell says, I would guess I learned about 70% of what he's teaching (preaching) the hard way.

I'd recommend programming the PIC in C if you don't need blazing speed. If you're in need of a decent compiler, take a look at CCS

formatting link

Have fun. Learning to design and manage a project longer than a few hundred lines of code is something you need to learn through experience.

Mark

Reply to
mark hahn

The standard text:

"The Elements of Programming Style - 2nd Ed." Brian W. Kernighan & P. J. Plauger McGraw Hill, 1988

--
  Max
Reply to
Max

For magazines check out

formatting link
and
formatting link

gm

Reply to
George

"The Practice of Programming" (AKA, "The Wienerdog Book") Kernighan and Pike Addison & Wesley

is also good.

Regards,

-=Dave

--
Change is inevitable, progress is not.
Reply to
Dave Hansen
[...]

Erm -- That should be:

Addison Wesley, 1999

Not sure how that ampersand got there. Oh well.

-=Dave

--
Change is inevitable, progress is not.
Reply to
Dave Hansen

[%X]

Some are but not all of them. As someone else said, you may be getting tested to see how you manage the project.

With any project you will see immediately how to do some of the low level bits (usually based on things you did before or they are so simple they need little thought). However, spend some time just organising your thoughts on the project, write any technical specification documents you need (especially those that fill in the detail from the client requirements), check the applicable legislation/standards/codes of practice, and draw a structural map of how the system is going to hang together.

Factoring the project into smaller sub-projects and planning your project time-line will help you keep focussed on what needs to be done by when. Allow some time for performing things like risk assessments and holding technical design reviews (where you can gain some help from your colleagues). Testing any sub-system parts as they become ready an in accordance with a pre-written test plan (these don't have to be very long but should be comprehensive enough to inicate whether the sub-system component meets the client requirements).

Writing inter-module interface specifications (Interface Control Documents or ICD's) is worthwhile even for the simplest interfaces. Many of these will be re-usable so they are not wasted effort at all. Testing from these interfaces should then indicate how robust your system is.

Sadly, the ones I would normally reccommend are out of print now. Keeping track of where you are with the design becomes quite important (more-so as the project size increases). Adopt a decent tracking system to pick up problem reports and review issues raised, and ensure that each new version has incorporate all the approved changes to the development.

You will certainly find a large amount of useful material within the various threads that have ocurred within this newsgroup. The Rover OS thread is one case in point. Well worth looking back with Google for the others.

--
********************************************************************
Paul E. Bennett ....................
Forth based HIDECS Consultancy .....
Mob: +44 (0)7811-639972 .........NOW AVAILABLE:- HIDECS COURSE......
Tel: +44 (0)1235-811095 .... see http://www.feabhas.com for details.
Going Forth Safely ..... EBA. www.electric-boat-association.org.uk..
********************************************************************
Reply to
Paul E. Bennett

If you'll be working in C, here are some mistakes I've noticed that beginners do:

  1. Turn off warnings. In college, students are in a rush to get their programs running. They see all these warnings when they compile their codeand thinkt "those are just warnings, not errors" so nothing is really wrong. They turn them off so they don't see them. Once it compiles, they spend weeks tryng to find the bugs that the warnings were trying to tell them about. Understand what the warnings really mean. Don't turn warnings off. Work on getting your code to compile with no warnings.

  1. Don't use function prototypes Again, the beginners want to start coding and they feel that function prototypes are a waste of time. They aren't. They are one of the features of modern C that I got down on my knees and thanked God for.

A few years back, I was called in to work on a project where a start-up company decided to save $$$ and use student programmers to program the product (a handheld device and a Windows program). I fixed many bugs by fixing the reasons for the warnings and making function prototypes for all functions.

One good thing is that you are coming from the hardware side. It can be a disadvatage coming from the software world (these days) as they are used to programming with Megabytes of RAM, Gigabytes of disk, Gighertz clock rates, and system software that takes care of hardware dependencies. Programming an embedded system can be a rough and rude transition for them.

It's a healthy sign that you are worried about these things. It means you're interested in turning out a quality product, and not just quality from the end user point of view. I wish you well.

Reply to
Gary Kato

beginners

all

warnings,

see

really

no

Where I am, some of the engineers have a slavish attitude to the use of lint.

But some of lint's warnings are a complete WOT (the one that checks you have used *every* external in a header file comes to mind) and they are often turned off.

So in the code I have inherited I have:

lint -xxx /* file not used */ (whatever the correct format is?) #include "abc.h"

Um if abc.h isn't used, surely it's better not to include it in the first place, turning off the lint warning instead is silly?

And on one occassion with a complex cast someone had turned off a lint warning, I recompiled with a different compiler and it produced an error!

OTOH, I get really annoyed every time I have to explicitely add a cast to:

Byte_a = Byte_b & Byte_c;

because the blasted compiler has widened the RHS to a word to cope with the, impossible, overflow and then squeeks because it can't fit it back into the LHS. Did I say this annoys me immensely?

If they are there just to tick a box, they are. They are only useful if included via the header, just putting then at the top of the file and carrying on regardless achieves very little IMHO.

company

reasons

to

rates,

an

you're

end

Reply to
tim
[...]

/*lint -e766 */

Bingo. Fix the code, not the error.

PC-lint is smart enough not to complain about this:

---begin included file--- C:\Dave>type lintest.c extern unsigned char get_byte(void);

unsigned char f(void) { unsigned char Byte_a, Byte_b, Byte_c;

Byte_b = get_byte(); Byte_c = get_byte(); Byte_a = Byte_b & Byte_c;

return Byte_a; }

C:\Dave>lint-nt -u lintest.c PC-lint for C/C++ (NT) Ver. 8.00n, Copyright Gimpel Software 1985-2003

--- Module: lintest.c

C:\Dave>

---end included file---

(The -u option means "unit lint," suppresses errors like "f defined but not called" and "get_byte called but not defined.")

A C compiler once sold by a certain large operating system company reported an error for

extern void f(unsigned char x);

f(0);

because significant bits might be truncated when converting the int (0) to an unsigned char. Sigh. As you say, annoying.

In this particular case, I would use lint to perform static analysis, then turn off warnings during compilation. Drastic, perhaps, but it worked for me...

It's less work that way, too.

To take it one step further, the header file must be included by the module defining the function. Otherwise, you're little better off than you were before.

Regards,

-=Dave

--
Change is inevitable, progress is not.
Reply to
Dave Hansen

Absolutely! I should have mentioned that. I have seen code that used function prototypes in the C files instead of the header files and ran into the same sort of problems as when prototypes aren't used at all.

Reply to
Gary Kato

But as it doesn't generate code for a particular word size, it won't do any widening of data types.

Arm ADS is not so smart.

I assumed that was implicit in my comment.

But anyhow, I think that the reason it is often not done is because people who have been around as long as I have, once worked where this resulted in syntax which was illegal (though there are workarounds). I still meet the occasional person who queries its legallity

tim

Reply to
tim

There are two classical approached to this problem. The so called Top-Down or Bottom-Up approaches. I personally tend to use a combination of the two. The top down part lets you look at the whole thing from a broader concept point of view.

The bottom up part, you take the specific hardware interfaces etc. that you have and allocate them to the specific low level functions you need to perform.

The big thing is not to just start to program and hope for the best. A balanced approach with the appropriate planning will make any job doable, or at least show you where you have a problem.

Regards Anton Erasmus

Reply to
Anton Erasmus

A few books (relatively short ones) that you should peruse:

"The Practice of Programming" -- Kernighan & Pike, Addison Wesley

"The Mythical Man-Month" -- Fred Brooks, Addison Wesley

"The Elements of Programming Style" -- Kernighan & Plauger, McGraw-Hill

"Enough Rope to Shoot Yourself in the Foot" -- Allen Holub, McGraw-Hill

That should give you good coverage of both low-level coding (how to write good code) issues and high-level engineering issues (how to manage people, including yourself, writing code). Altogether, the four books are about 900 pages of material, but you should be able to cherry pick (or even just skim) the highlights to good effect.

I've got my own set of rules for good coding, but not knowing your specific strengths and weaknesses, I don't presume that my list would be much help. Besides, most everything that I have learned is mentioned in those books.

-- Jeff Dutky

Reply to
Jeffrey Dutky

Au contraire. PC-lint pays close attention to the size of the various types (and whether char is signed). The defaults are ILP32, but different options can change sizes as required. Consider

int i; unsigned char b1, b2, b3, b4;

i = (int) (b1 Arm ADS is not so smart.

I've mentioned before that some compiler "warnings" are worse than useless. That's why I let lint decide if my code is OK (before it ever sees the compiler).

Ahh, the bad old days. I've worked with (pre-ANSI) compilers where

extern int x; int x = 0;

would generate an error. Made declaring variables in a header, uh, interesting. My workaround was

#ifndef GLOBAL #define GLOBAL extern #define INIT(v) #else #define INIT(v) = v #endif

GLOBAL int x INIT(0);

Most c files would

#include "x.h"

but one would

#define GLOBAL #include "x.h"

Regards,

-=Dave

--
Change is inevitable, progress is not.
Reply to
Dave Hansen

immensely?

Please re-read what I wrote.

"it doesn't *generate* code for a particular word size".

It therefore respects the sizes of the data that the programmer has given it without further consideration.

The compiler OTOH, thinks in terms of the internal word size of the target and (presumably) sees a benefit in wideing the 8 bit bytes into 32 bit words to do mathmetical calculations. Quite why this then becomes my problem is beyond me.

tim

Reply to
tim

[...]
[...]

Yes, and...? The fact that lint doesn't generate code doesn't change anything. It must still be aware of when data types will be widened.

For example, in the above referenced code, the values of Byte_b and Byte_c must be widened to int before the AND operation takes place, and the int result must be converted to a byte before it is stored in Byte_a. Lint is smart enough to realize that these conversions will not change the result, so it doesn't complain.

Lint "thinks in terms of" the size of int, long, long long, double, and long double, and widens operands when required. For example,

char a = 100, b; int i;

i = a * a; b = a * a;

will store 10,000 into i. Otherwise the compiler is broken. Lint realizes this and does not complain.

However, lint *will* complain that the (int) result of the second multiplication may not fit in b.

Look up "usual arithmetic conversions" and "integer promotions" for more info.

It becomes your problem because your compiler's warnings are, umm, less then optimal. Which is why they must sometimes be ignored.

In the past I have disabled all compiler warnings if the code lints clean. In particular, a certain compiler I once used warned that, given

extern void f(unsigned char);

f(0);

the conversion of the integer (0) to unsigned char may cause the loss of significant bits. Even though that was not true, and the compiler knew (or at least could know) that.

Regards,

-=Dave

--
Change is inevitable, progress is not.
Reply to
Dave Hansen

why *must* they?

Why is this not for the compiler (author) to decide whether this will happen?

I don't need lessons in basic arithmetic thanks, all I need is to know why bytes variables used in logical operations need to be widened.

tim

Reply to
tim
[... slightly reordered and clipped ...]

Because that's what the definition of the C language says happens in such a case. All integers shorter than int will be extended to int (or unsigned int) before *any* operator is applied to them. This is known as "integral promotion", and is a central aspect of how C works.

Mainly because the compiler author promised to make a C compiler, not a "some strange language superficially looking like C" compiler.

What the compiler author *can* do, in a case like this, is invoke the C Standard's "as if" rule. I.e. if he can prove that the result of doing the entire operation on single bytes without actually constructing the promoted ints is guaranteed to be the same as what the C definition requires, he can do it that way. [The "as if" rule is that as long as the program behaves "as if" the predefined semantics had been used, the compiler can do whatever it pleases.]

For the '&' operator on unsigned bytes, on a typical platform, that's the case. For other operators it isn't, and for signed bytes, it's hard to be sure. And that's before you consider the uglier cases like platforms with sizeof(int)==sizeof(char).

--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply to
Hans-Bernhard Broeker

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.