As well as the usual things a good programmer will do, there are some issues specific to mspgcc which you should be aware of.
If you are sure your main routine will never exit, you can use the “-mendup-at=main” flag when compiling. This will save 6 bytes of ROM.
Avoid passing long argument list to functions. Avoid returning long values from functions. The best functions types to use are void, int, or pointer.
Avoid the initialization of global variables within a small function call. Instead, assign a value during variable definition.
Avoid converting chars to another type. char variables can be located anywhere in RAM, while word variables can only be at even addresses. Because of this, the following code:
const char *a = "1234"; int k; k = *((int *)((char *a) + 3));
will result in unpredictable CPU behaviour.
Avoid using global variables of small size - it is a waste of RAM.
Avoid using volatiles, unless they are really necessary.
Use int instead of char or unsigned char if you want an 8 bit integer.
Inspect assembler code (-S compiler flag). The compiler cannot eliminate dead code in some cases. Do not write dead code :)
Do not declare your own SFRs. They are all declared in include files in the right way to achieve maximum code performance.
Try to minimise the use of addition and subtraction with floating point numbers. These are slow operations.
Use shift instead of multiplication by constants which are 2^N (actually, the compiler may to do this for you when optimization is switched on).
Use unsigned int for indices - the compiler will snip _lots_ of code.
Use 'switch/case' constructs rather than a chain of 'if/else' constructs.
Use logical "or" ('|') instead of '+' for bitmasks.
When defining bit fields, try to use signed integers. This produces more compact code that bit fields of unsigned integers.
Use 'alloca' instead of 'malloc' for locals. In embedded applications trying to avoid any dynamic memory allocation is usually even better ;).
Apart from C++ recomendations ;), it would be better to use:
#define SMTS 1234567890l
instead of declaring
const long smts = 1234567890l;
If you execute
while ((long) a & 0x80000l);
the program will hang, unless 'a' is declared volatile. So, do it!
Delay loops are very sophisticated routines. Normally, users do something like:
int i = 1234; while (i--);
or
int i; for (i = 0; i < 1234; i++);
NEITHER WILL WORK AS YOU EXPECT when optimisation is switched on!!! The optimizer will detect dead code in both examples and will eliminate it. It might even eliminate the loop completely. Adding the volatile attribute to the definition of 'i' might help, but don't count on it if 'i' is a local variable. The compiler can still detect the calculations are wasteful, and eliminate them.
Regardless of these optimisation issues, this type of delay loop is poor programming style - you have no idea how long or short a delay it might produce (although there is an obvious minimum bound!). It would be better, and more reliable to define something like:
static void __inline__ brief_pause(register unsigned int n) { __asm__ __volatile__ ( "1: \n" " dec %[n] \n" " jne 1b \n" : [n] "+r"(n)); }
and call this routine where needed. This is simple, compact, and predictable.
Do not do anything unless you know what you're doing :)