04-12-2012, 06:43 PM
Porting a Program to Dynamic C
Porting Differences.pdf (Size: 371.98 KB / Downloads: 60)
Introduction
Dynamic C has a number of improvements and differences compared to many other C compiler systems.
This application note gives instructions and suggestions for porting a C program from other compilers to
Dynamic C.
Generally, other C compilers require a large number of include files, potentially different for each source
file, to provide function prototypes. Dynamic C function prototypes are automatically handled by the
Dynamic C source libraries. The major porting task is reorganizing the source files and function prototypes
into Dynamic C libraries.
There are some differences in the scoping rules between Dynamic C and various other compilers intended
for embedded systems. These mostly result from the fact that Dynamic C compiles the entire program
from source code and source libraries rather than compiling numerous modules independently and then
linking them as a separate step.
Dynamic C follows the ISO/ANSI C standard when feasible and desirable. Because the standard does not
take into account the special needs of embedded systems, it is necessary to depart from the standard in
some areas and desirable in others. The standard does not take into account important embedded systems
issues such as read only memory and embedded assembly language. For this reason, practical compilers
intended for embedded systems do not completely comply with the standard, but use it as a guide.
As a rough estimate, it will require a day’s work to port 1,000 lines of source code. This does not include
resolving differences in I/O hardware, I/O drivers and startup code.
This document does not discuss Dynamic C extensions to the C language, such as costatements, since they
will not appear in code you port from another compiler.
Modular Programming with Dynamic C Libraries
Many programs consist of a number of files (*.c files in some compilers) that may be compiled separately.
The programs may also have libraries of code blocks that are included optionally, depending on
whether they are needed for a particular configuration. In addition, there are usually include (*.h) files
that provide function prototypes, structure definitions and, often, various macros. The definitions in the
include files effectively have global scope because they are included in every file where they are used.
Dynamic C does not support file-scoped variables. In other compilers, file scoped global variables are
declared with the keyword static. These global variables only become a problem in porting if there
are symbol name conflicts between such variables declared in different file scopes. Simply rename the
variables to resolve conflicts.
A C program has the following elements:
• Function prototypes, macro definitions, structure and typedef definitions
• Source code (C functions) and global data definitions
• Supplied libraries and user-defined libraries
• Assembly language (non-portable)
Dynamic C supports these same elements and, if you like, your program can be split between separate
files. In other compilers, the separate modules have .c extensions (or whatever file type is used) and the
include filenames have .h extensions. In Dynamic C, only the main program file ends with a .c extension
(the file with the function “main”). If desired, this program file could contain your entire program except
for the standard libraries and the BIOS. The alternative is to break your program up into separate modules
called libraries or .lib files. These library files encourage modular design since Dynamic C compiles
these library files together with your main program file.
Dynamic C improves upon the concept of header files by using special “header” sections for two primary
reasons. First, function prototypes and global data declarations are placed in the header section next to the
implementation of the associated function for convenient reference. Second, this organization also allows
the compiler to generate smaller code, since it conditionally compiles smaller sections of code depending
on whether or not the symbols in that section are needed (e.g., referenced in the main program file).
Dynamic C library files serve the same purpose as object module libraries because sections of code will be
compiled as a part of the user’s program if they are needed to satisfy undefined global symbols. When a
program is compiled under Dynamic C the compilation is as follows:
1. The BIOS, if it has not already been compiled, is compiled. Usually the BIOS is compiled and downloaded
to the target at the start of a session; then you can recompile your program without having to
recompile the BIOS. The BIOS is recompiled only if it crashes or compiler options change that require
a recompile (e.g., changing memory devices). You can add modules from your program to the BIOS to
avoid having to recompile them frequently.
Default Storage Class
The default storage class for local variables in most compilers is auto. In Dynamic C versions prior to 8.01,
the default storage class is static. Starting with Dynamic C 8.01 the default storage class for local variables
is auto. Whether variables are auto or static usually determines if the function is reentrant or not.
Starting with Dynamic C 7.02, the #class directive allows you to change the default storage class.
Initialized Variables
In Dynamic C, when a variable is initialized upon declaration, e.g. int x = 0, it is treated as a constant
and is stored in flash. In order to facilitate porting, the Dynamic C compiler generates a warning that the
variable is stored in flash. Using the const keyword for initialized variables eliminates the warning. In
Dynamic C, the const keyword use is restricted to data with global or static scope. In other words, the
const keyword is not applicable to auto variables, function parameters, or function return types. Refer to
the Dynamic C User’s Manual for more details on using the const keyword.