Thursday 25 October 2012

Embedded C, Defining Common Types

How do you write portable C code that you can use on any processor architecture or compiler and even unit test such code on a Windows PC? This is one problem I've been addressing over the last year or so as I've written firmware for several processor architectures  PICS, Renesas H8's and Infineon 166.

The first problem is that an int can be 1,2 or 4 bytes in size and it depends on the compiler, processor and OS. In this post I'll show how to use precisely defined types that you can use throughout your code so that you will not need to worry about the size of types.

Common types that you will use are signed and unsigned ints, so these will need to be defined and standardized:

Signed ints: sint8, sint16,sint32, sint64
Unsigned ints: uint8, uint16, uint32, uint64
For floating point I use, float32 and float64

The C language is missing the bool type, so I define this as well, which is great as I can now mix the embedded C code with the C++ unit test harness code running on my Windows PC. I also prefer returning a bool instead of error codes so as to keep things simple.

Here is an example of my defines.h that I use when writing C projects for PIC micro-controllers.


#ifndef DEFINES_H
#define DEFINES_H

#ifdef WIN32

typedef char   sint8;   // -128 T0 127
typedef unsigned char uint8;  // 0 TO 255
typedef signed short sint16;  // -32768 TO 32767 
typedef unsigned short uint16;  // 0 TO 65535
typedef long   sint32;  // -2147483648 TO 2147483647
typedef unsigned long uint32;  //0 TO 4294967295
typedef float   float32; //(1.4012984643248171e-45f) to(3.4028234663852886e+38f)
typedef double   double64; // 4.9406564584124655e-324 to 1.7976931348623158e+308

//A byte is a one byte unsigned integer
typedef unsigned char BYTE;
//A double word is a four byte unsigned integer
typedef unsigned long DWORD;
//A word is a two byte unsigned integer
typedef unsigned short WORD;

#else

typedef signed int   sint8;   // -128 T0 127
typedef unsigned int                    uint8;  // 0 TO 255
typedef signed long   sint16;  // -C32768 TO 32767
typedef unsigned long                   uint16;  // 0 TO 65535
typedef signed long long                sint32;  // -2147483648 TO 2147483647
typedef unsigned long long              uint32;  //0 TO 4294967295
typedef float    float32; //(1.4012984643248171e-45f) to(3.4028234663852886e+38f)

//A byte is a one byte unsigned integer - already defined in CCS compiler
//typedef unsigned int BYTE;
//A word is a two byte unsigned integer
typedef unsigned long WORD;
//A double word is a four byte unsigned integer
typedef unsigned long long DWORD;

typedef unsigned char   bool;
#define true    (bool)1
#define false    (bool)0


#endif

//C definition of null is (void *) 0, for C++ it is just 0
#ifndef NULL
 #ifdef __cplusplus
    #define NULL 0
 #else
    #define NULL ((void *) 0)
 #endif
#endif

//Include guard
#endif

In my future embedded C posts that I'll be using these types, eg sint16, in my example code.

No comments:

Post a Comment