<< Previous | Index | Next >> | |
|
A
keyword is a reserved word in C that represents a basic C construct. It cannot be used for any other purpose. There are many keywords, and they are summarized in the following pages.
abandon
Used in single-user cofunctions,
abandon{}
must be the first statement in the body of the cofunction. The statements inside the curly braces will be executed only if the cofunction is forcibly abandoned and if a call toloophead()
is made inmain()
before calling the single-user cofunction. SeeSamples\Cofunc\Cofaband.c
for an example of abandonment handling.
abort
for(;;){
costate {
...
if(condition
)abort;
}
...
}
align
Used in assembly blocks, the
align
keyword outputs a padding of nops so that the next instruction to be compiled is placed at the boundary based onVALUE
.#asm
...
align <VALUE>
...
#endasm
VALUE
can have any (positive) integer expression or the special operandseven
andodd
. The operandeven
aligns the instruction on an even address, andodd
on an odd address. Integer expressions align on multiples of the value of the expression.align odd ; This aligns on the next odd address
align 2 ; Aligns on a 16-bit (2-byte) boundary
align 4 ; Aligns on a 32-bit (4-byte) boundary
align 100h ; Aligns the code to the next address that is evenly divisible by 0x100
align sizeof(int)+4 ; Complex expression, involvingsizeof
and integer constantNote that integer expressions are treated the same way as operand expressions for other asm operators, so variable labels are resolved to their addresses, not their values.
always_on
The costatement is always active. (Unnamed costatements are always on.)
anymem
Allows the compiler to determine in which part of memory a function will be placed.
anymem int func(){
...
}
#memmap anymem
#asm anymem
...
#endasm
asm
Use in Dynamic C code to insert one assembly language instruction. If more than one assembly instruction is desired use the compiler directive
#asm
instead.int func() {
int x,y,z;asm ld hl,0x3333
...}
auto
A functions's local variable is located on the system stack and exists as long as the function call does.
int func(){
auto float x;
...
}
bbram
Identifies a variable to be placed into a second data area reserved for battery-backed RAM. Generally, the battery-backed RAM is attached to CS1 due to the low-power requirements. In the case of a reset or power failure, the value of a
bbram
variable is preserved, but not atomically like withprotected
variables. No software check is possible to ensure that the RAM is battery-backed. This requirement must be enforced by the user.If interested, please see the Rabbit 3000 Microprocessor Designer's Handbook for information on how the second data area is reserved.
break
Jumps out of a loop,
if
, orcase
statement.while( expression ){
...
if( condition)
break;
}
switch( expression){
...
case 3:
...
break;
...
}
c
Use in assembly block to insert one Dynamic C instruction.
#asm
InitValues::
cstart_time = 0;
ccounter = 256;
ld hl,0xa0;
ret
#endasm
case
Identifies the next case in a
switch
statement.switch( expression ){
caseconst:
...
caseconst
:
...
caseconst
:
...
...
}
char
Declares a variable or array element as an unsigned 8-bit character.
char c, x, *string = "hello";
int i;
...
c = (char)i; // type casting operator
const
This keyword declares that a value will be stored in flash, thus making it unavailable for modification.
const
is a type qualifier and may be used with any static or global type specifier (char
,int
,struct
, etc.). Theconst
qualifier appears before the type unless it is modifying a pointer. When modifying a pointer, the
const
keyword appears after the `
*
'.In each of the following examples, if
const
was missing the compiler would generate a trivial warning. Warnings forconst
can be turned off by changing the compiler options to report serious warnings only. Note thatconst
is not currently permitted with return types, automatic locals or parameters and does not change the default storage class for cofunctions.
Example 1:
// ptr_to_x is a constant pointer to an integer
int x;
int * const cptr_to_x = &x;
Example 2:
// cptr_to_i is a constant pointer to a constant integer
const int i = 3;
const int * const cptr_to_i = &i;
Example 3:
// ax is a constant 2 dimensional integer array
const int ax[2][2] = {{2,3}, {1,2}};
Example 4:
struct rec {
int a;
char b[10];
};// zed is a constant struct
const struct rec zed = {5, "abc"};
Example 5:
// cptr is a constant pointer to an integer
typedef int * ptr_to_int;
const ptr_to_int cptr = &i;// this declaration is equivalent to the previous one
int * const cptr = &i;
continue
Skip to the next iteration of a loop.
while( expression ){
if( nothing to do ) continue;
...
}
costate
Indicates the beginning of a costatement.
costate [
name [
state
] ] {
...
}Name can be absent. If name is present,
state
can bealways_on
orinit_on
. Ifstate
is absent, the costatement is initially off.
debug
Indicates a function is to be compiled in debug mode. This is the default case for Dynamic C functions with the exception of pure assembly language functions.
Library functions compiled in debug mode can be single stepped into, and breakpoints can be set in them.
debug int func(){
...
}
#asm debug
...
#endasm
default
Identifies the default case in a switch statement. The default case is optional. It executes only when the switch expression does not match any other case.
switch( expression ){
caseconst1
:
...
caseconst2
:
...
default:
...
}
do
Indicates the beginning of a
do
loop. Ado
loops tests at the end and executes at least once.do
...
while( expression );The statement must have a semicolon at the end.
else
Indicates a false branch of an
if
statementif( expression )
statement // executes when expression is true
else
statement // executes when expression is false
enum
Defines a list of named integer constants:
enum foo {
white, // default is 0 for the first item
black, // will be 1
brown, // will be 2
spotted = -2, // will be -2
striped, // will be -3
};An
enum
can be declared in local or global scope. The tagfoo
is optional; but it allows further declarations:enum foo rabbits;
This keyword is available starting with Dynamic C version 7.20. To see a colorful sample, run
/samples/enum.c
.
extern
Indicates that a variable is defined in the BIOS, later in a library file, or in another library file. Its main use is in module headers.
/*** BeginHeader ..., var */
extern int var;
/*** EndHeader */
int var;
...
firsttime
firsttime
in front of a function body declares the function to have an implicit*CoData
parameter as the first parameter. This parameter should not be specified in the call or the prototype, but only in the function body parameter list. The compiler generates the code to automatically pass the pointer to the
CoData
structure associated with the costatement from which the call is made. Afirstime
function can only be called from inside of a costatement, cofunction, or slice statement. TheDelayTick
function fromCOSTATE.LIB
below is an example of afirsttime
function.firsttime nodebug int DelayTicks(CoData *pfb, unsigned int ticks){
if(ticks==0) return 1;
if(pfb->firsttime){
fb->firsttime=0;/* save current ticker */
fb->content.ul=(unsigned long)TICK_TIMER;
}
else if (TICK_TIMER - pfb->content.ul >= ticks)
return 1;return 0;
}
float
Declares variables, function return values, or arrays, as 32-bit IEEE floating point.
int func(){
float x, y, *p;
float PI = 3.14159265;
...
}
float func( float par ){
...
}
for
Indicates the beginning of a
for
loop. Afor
loop has an initializing expression, a limiting expression, and a stepping expression. Each expression can be empty.for(;;) { // an endless loop
...
}
for( i = 0; i < n; i++ ) { // counting loop
...
}
goto
Causes a program to go to a labeled section of code.
...
if(condition
) goto RED;
...
RED:Use
goto
to jump forward or backward in a program. Never usegoto
to jumpinto
a loop body or aswitch
case. The results are unpredictable. However, it is possible to jumpout of
a loop body orswitch
case.
if
Indicates the beginning of an
if
statement.if( tank_full ) shut_off_water();
if( expression ){
statements}else if( expression ){
statements}else if( expression ){
statements}else if( expression ){
statements
...
}else{
statements
}If one of the expressions is true (they are evaluated in order), the statements controlled by that expression are executed.
An
if
statement can have zero or moreelse
if
parts. Theelse
is optional and executes only when none of theif
or
else if
expressions are true (non-zero).
init_on
The costatement is initially on and will automatically execute the first time it is encountered in the execution thread. The costatement becomes inactive after it completes (or aborts).
int
Declares variables, function return values, or array elements to be 16-bit integers. If nothing else is specified,
int
implies a 16-bitsigned
integer.int i, j, *k; // 16-bit signed
unsigned int x; // 16-bit unsigned
long int z; // 32-bit signed
unsigned long int w; // 32-bit unsigned
int funct ( int arg ){
...
}
interrupt
Indicates that a function is an interrupt service routine. All registers, including alternates, are saved when an interrupt function is called and restored when the interrupt function returns. Writing ISRs in C is not recommended when timing is critical.
interrupt isr (){
...
}An interrupt service routine returns no value and takes no arguments.
interrupt_vector
Sets up an interrupt vector at compile time. This keyword is available starting with Dynamic C version 7.30. It is intended for use with separate I&D space.
interrupt_vector <INT_VECTOR_NAME> <ISR_NAME>
// Set up an Interrupt Service Routine for Timer B
#asm
timerb_isr::
; ISR code
...
ret
#endasmmain() {
// Variables
...// Set up ISR
interrupt_vector timerb_intvec timerb_isr; // Compile time setup// Code
...
}
interrupt_vector
overrides run time setup. For run time setup, you would replace theinterrupt_vector
statement above with:#rcodorg <INT_VEC_NAME> apply
#asm
INTVEC_RELAY_SETUP(timerb_intvec + TIMERB_OFS)#endasm
#rcodorg rootcode resume
This results in a slower interrupt (80 clock cycles are added), but a interrupt vector can be modified at run time. Interrupt vectors that are set up using
interrupt_vector
are fast, but can't be modified at run time since they are set at compile time.
long
Declares variables, function return values, or array elements to be 32-bit integers. If nothing else is specified,
long
implies asigned integer.
long i, j, *k; // 32-bit signed
unsigned long int w; // 32-bit unsigned
long funct ( long arg ){
...
}
main
Identifies the
main
function. All programs start at the beginning of themain
function. (main
is actually not a keyword, but is a function name.)
nodebug
Indicates a function is not compiled in debug mode. This is the default for assembly blocks.
nodebug int func(){
...
}
#asm nodebug
...
#endasmSee also
debug
and directives#debug #nodebug
.
norst
Indicates that a function does not use the
RST
instruction for breakpoints.norst void func(){
...
}
nouseix
Indicates a function does not use the IX register as a stack frame reference pointer. This is the default case.
nouseix void func(){
...
}
NULL
The null pointer. (This is actually a macro, not a keyword.) Same as
(void *)0
.
protected
An important feature of Dynamic C is the ability to declare variables as protected. Such a variable is protected against loss in case of a power failure or other system reset because the compiler generates code that creates a backup copy of a protected variable before the variable is modified. If the system resets while the protected variable is being modified, the variable's value can be restored when the system restarts. Battery-backed RAM is required for this operation.
A system that shares data among different tasks or among interrupt routines can find its shared data corrupted if an interrupt occurs in the middle of a write to a multibyte variable (such as type
int
orfloat
). The variable might be only partially written at its next use.Declaring a multibyte variable
shared
means that changes to the variable are atomic, i.e., interrupts are disabled while the variable is being changed.Declaring a variable to be "protected" guards against system failure. This means that a copy of the variable is made before it is modified. If a transient effect such as power failure occurs when the variable is being changed, the system will restore the variable from the copy.
main(){
protected int state1, state2, state3;
...
_sysIsSoftReset(); // restore any protected variables
}The call to
_sysIsSoftReset
checks to see if the previous board reset was due to the compiler restarting the program (i.e. a "soft" reset). If so, then it initializes the protected variable flags and callssysResetChain()
, a function chain that can be used to initialize any protected variables or do other initialization. If the reset was due to a power failure or watchdog time-out, then any protected variables that were being written when the reset occurred are restored.
return
Explicit return from a function. For functions that return values, this will return the function result.
void func (){
...
if(expression
) return;
...
}float func (int x){
...
float temp;
...
return ( temp * 10 + 1 );
}
root
Indicates a function is to be placed in root memory. This keyword is semantically meaningful in function prototypes and produces more efficient code when used. Its use must be consistent between the prototype and the function definition.
root int func(){
...
}
#memmap root
#asm root
...
#endasm
segchain
Identifies a function chain segment (within a function).
int func ( int arg ){
...
int vec[10];
...
segchain _GLOBAL_INIT{
for( i = 0; i<10; i++ ){ vec[i] = 0; }
}
...
}This example adds a segment to the function chain
_GLOBAL_INIT
. Usingsegchain
is equivalent to using the#GLOBAL_INIT
directive. When this function chain executes, this and perhaps other segments elsewhere execute. The effect in this example is to (re)initializevec
.
shared
Indicates that changes to a multi-byte variable (such as a
float
) are atomic. Interrupts are disabled when the variable is being changed. Local variables cannot be shared.shared float x, y, z;
shared int j;
...
main(){
...
}If
i
is a shared variable, expressions of the formi++
(or
i
=
i+ 1
) constitutetwo
atomic references to variablei
, a read and a write. Be careful becausei++
is not an atomic operation.
short
Declares that a variable or array is short integer (16 bits). If nothing else is specified, short implies a 16-bit
signed
integer.short i, j, *k; // 16-bit, signed
unsigned short int w; // 16-bit, unsigned
short funct ( short arg ){
...
}
size
Declares a function to be optimized for size (as opposed to speed).
size int func (){
...
}
sizeof
A built-in function that returns the size in bytes of a variable, array, structure, union, or of a data type. Starting with Dynamic C 7.05,
sizeof()
can be used inside of assembly blocks.int list[] = { 10, 99, 33, 2, -7, 63, 217 };
...
x = sizeof(list); // x will be assigned 14
speed
Declares a function to be optimized for speed (as opposed to size).
speed int func (){
...
}
static
Declares a local variable to have a permanent fixed location in memory, as opposed to
auto
, where the variable exists on the system stack. Global variables are by definitionstatic
. Local variables arestatic
by default, unlike standard C.int func (){
...
int i; // static by default
static float x; // explicitly static
...
}
struct
This keyword introduces a structure declaration, which defines a type.
struct {
...
int x;
int y;
int z;
} thing1; // defines the variablething1
to be a structstruct speed{
int x;
int y;
int z;
}; // declares a struct type namedspeed
struct speed thing2; // defines the variablething2
to be of typespeed
Structure declarations can be nested.
struct {
struct speed slow;
struct speed slower;
} tortoise; // defines the variabletortoise
to be a nested struct
struct rabbit {
struct speed fast;
struct speed faster;
}; // declares a nested struct type namedrabbit
struct rabbit chips; // defines the variable
chips
to be of typerabbit
switch
Indicates the start of a
switch
statement.switch( expression ){
case const1:
...
break;
case const2:
...
break;
case const3:
...
break
default :
...
}The
switch
statement may contain any number of cases. The constants of the case statements are compared with expression. If there is a match, the statements for that case execute. Thedefault
case, if it is present, executes if none of the constants of the case statements match expression.If the statements for a
case
do not include abreak
,return
,continue
, or some means of exiting theswitch
statement, the cases following the selected case will also execute, regardless of whether their constants match theswitch
expression.
typedef
This keyword provides a way to create new names for existing data types.
typedef struct {
int x;
int y;
} xyz; // defines a struct type...
xyz thing; // ...and a thing of type xyz
typedef uint node; // meaningful type name
node master, slave1, slave2;
union
Identifies a variable that can contain objects of different types and sizes at different times. Items in a
union
have the same address. The size of aunion
is that of its largest member.union {
int x;
float y;
} abc; // overlays a float and anint
unsigned
Declares a variable or array to be unsigned. If nothing else is specified in a declaration,
unsigned
means 16-bit unsigned integer.unsigned i, j, *k; // 16-bit, unsigned
unsigned int x; // 16-bit, unsigned
unsigned long w; // 32-bit, unsigned
unsigned funct ( unsigned arg ){
...
}Values in a 16-bit unsigned integer range from 0 to 65,535 instead of -32768 to +32767. Values in an unsigned long integer range from 0 to 232 - 1.
useix
Indicates that a function uses the IX register as a stack frame pointer.
useix void func(){
...
}See also
nouseix
and directives
#useix #nouseix
.
waitfor
Used in a costatement, this keyword identifies a point of suspension pending the outcome of a condition, completion of an event, or some other delay.
for(;;){
costate {
waitfor ( input(1) == HIGH );
...
}
...
}
waitfordone
(wfd)The
waitfordone
keyword can be abbreviated aswfd
. It is part of Dynamic C's cooperative multitasking constructs. Used inside a costatement or a cofunction, it executes cofunctions andfirsttime
functions. When all the cofunctions andfirsttime
functions in thewfd
statement are complete, or one of them aborts, execution proceeds to the statement followingwfd
. Otherwise a jump is made to the ending brace of the costatement or cofunction where thewfd
statement appears; when the execution thread comes around again, control is given back to thewfd
statement.The
wfd
statements below are fromSamples\cofunc\cofterm.c
x=wfd login(); //
wfd
with one cofunctionwfd { //
wfd
with several cofunctions
clrscr();
putat(5,5,"name:");
putat(5,6,"password:");
echoon();
}As shown,
wfd
may return an argument.
while
Identifies the beginning of a
while
loop. Awhile
loop tests at the beginning and may execute zero or more times.while( expression ){
...
}
xdata
Declares a block of data in extended flash memory.
xdata name { value_1, ... value_n };
The 20-bit physical address of the block is assigned to
name
by the compiler as an unsigned long variable. The amount of memory allocated depends on the data type. Eachchar
is allocated one byte, and eachint
is allocated two bytes. If an integer fits into one byte, it is still allocated two bytes. Eachfloat
andlong
cause four bytes to be allocated.The value list may include constant expressions of type
int
,float
,unsigned
int
,long
,unsigned long
,char
, and (quoted) strings. For example:xdata name1 {'\x46','\x47','\x48','\x49','\x4A','\x20','\x20'};
xdata name2 {'R','a','b','b','i','t'};
xdata name3 {" Rules! "};
xdata name4 {1.0,2.0,(float)3,40e-01,5e00,.6e1};The data can be viewed directly in the dump window by doing a physical memory dump using the 20-bit address of the xdata block. See
Samples\Xmem\xdata.c
for more information.
xmem
Indicates that a function is to be placed in extended memory. This keyword is semantically meaningful in function prototypes. Its use must be consistent between the prototype and the function definition.
xmem int func(){
...
}#memmap xmem
xstring
Declares a table of strings in extended memory. The strings are allocated in flash memory at compile time which means they can not be rewritten directly.
The table entries are 20-bit physical addresses. The
name
of the table represents the 20-bit physical address of the table; this address is assigned toname
by the compiler.xstring name { "string_1", . . . "string_n" };
yield
Used in a costatement, this keyword causes the costatement to pause temporarily, allowing other costatements to execute. The
yield
statement does not alter program logic, but merely postpones it.for(;;){
costate {
...
yield;
...
}
...
}12.1 Compiler Directives
Compiler directives are special keywords prefixed with the symbol
#
. They tell the compiler how to proceed. Only one directive per line is allowed, but a directive may span more than one line if a backslash (\
) is placed at the end of the line(s).
#asm
Begins a block of assembly code. The available options are:
debug
: Enables debug code during assembly.
nodebug
: Disables debug code during assembly. This is the default condition. It is still possible to single step through assembly code as long as the assembly window is open.
xmem
: Places a block of code in extended memory, overriding any previous memory directives. The block is limited to 4KB. If the#asm
block is unmarked, it will be compiled to root.
#class
Controls the storage class for local variables. The available options are:
auto
: Place local variables on the stack.
static
: Place local variables in permanent, fixed storage.The default storage class is
static
.
#debug
#nodebugEnables or disables
debug
code compilation.#debug
is the default condition. These directives override thedebug
andnodebug
keywords used on function declarations or assembly blocks.#nodebug
prevents RST 28h instructions from being inserted between C statements and assembly instructions.
#define
Syntax:
#define
name text or#define
name (parameters . . . ) textDefines a macro with or without parameters according to ANSI standard. A macro without parameters may be considered a symbolic constant. Supports the
#
and##
macro operators. Macros can have up to 32 parameters and can be nested to 126 levels.
#endasm
Ends a block of assembly code.
#fatal
Instructs the compiler to act as if a fatal error. The string in quotes following the directive is the message to be printed
#GLOBAL_INIT
Syntax:
#GLOBAL_INIT
{ variables }
#GLOBAL_INIT
sections are blocks of code that are run once beforemain()
is called. They should appear in functions after variable declarations and before the first executable code. If a local static variable must be initialized once only before the program runs, it should be done in a#GLOBAL_INIT
section, but other inititialization may also be done. For example:
#error
Instructs the compiler to act as if an error was issued. The string in quotes following the directive is the message to be printed
#funcchain
Syntax:
#funcchain
chainname nameAdds a function, or another function chain, to a function chain.
#if
#elif
#else
#endifSyntax:
#if
constant_expression
#elif
constant_expression
#else
#endif
These directives control conditional compilation. Combined, they form a multiple-choice
if
. When the condition of one of the choices is met, the Dynamic C code selected by the choice is compiled. Code belonging to the other choices is ignored.
main(){
#if BOARD_TYPE == 1
#define product "Ferrari"#elif BOARD_TYPE == 2
#define product "Maserati"#elif BOARD_TYPE == 3
#define product "Lamborghini"#else
#define product "Chevy"#endif
...
}The
#elif
and#else
directives are optional. Any code between an#else
and an#endif
is compiled if all values for constant_expression are false.
#ifdef
This directive enables code compilation if name has been defined with a
#define
directive. This directive must have a matching#endif
.
#ifndef
This directive enables code compilation if name has not been defined with a
#define
directive. This directive must have a matching#endif
.
#interleave
#nointerleaveControls whether Dynamic C will intersperse library functions with the program's functions during compilation.
#nointerleave
forces the user-written functions to be compiled first.
#KILL
To redefine a symbol found in the BIOS of a controller, first
KILL
the prior name.
#makechain
Creates a function chain. When a program executes the function chain named in this directive, all of the functions or segments belonging to the function chain execute.
#memmap
Controls the default memory area for functions. The following options are available.
anymem NNNN
: When code comes within NNNN bytes of the end of root code space, start putting it in xmem. Default memory usage is#memmap anymem 0x2000
.
root
: Allfunctions not declared as
xmem
go to root memory.
xmem
: All C functions not declared asroot
go to extended memory. Assembly blocks not marked asxmem
go to root memory.
#precompile
Allows library functions in a comma separated list to be compiled immediately after the BIOS.
The
#precompile
directive is useful for decreasing the download time when developing your program. Precompiled functions will be compiled and downloaded with the BIOS, instead of each time you compile and download your program. The following limitations exist:
Precompile functions must be defined
nodebug
.Any functions to be precompiled must be in a library, and that library must be included either in the BIOS using a
#use
, or recursively included by those libraries.Internal BIOS functions will precompile, but will not result in any improvement.
Libraries that require the user to define parameters before being used can only be precompiled if those parameters are defined before the
#precompile
statement. An example of this is included inprecompile.lib
.Function chains and functions using segment chains cannot be precompiled.
Precompiled functions will be placed in extended memory, unless specifically marked
root
.All dependencies must be resolved (Macros, variables, other functions, etc.) before a function can be precompiled. This may require precompiling other functions first.
See
precompile.lib
for more information and examples.
#undef
Removes (undefines) a defined macro.
#use
Activates a library named in
lib.dir
so modules in the library can be linked with the application program. This directive immediately reads in all the headers in the library unless they have already been read.
#useix
#nouseixControls whether functions use the IX register as a stack frame reference pointer or the SP (stack pointer) register.
#nouseix
is the default.Note that when the IX register is used as a stack frame reference pointer, it is corrupted when any stack-variable using function is called from within a cofunction, or if a stack-variable using function contains a call to a cofunction.
#warns
Instructs the compiler to act as if a serious warning was issued. The string in quotes following the directive is the message to be printed.
#warnt
Instructs the compiler to act as if a trivial warning was issued. The string in quotes following the directive is the message to be printed.
#ximport
Syntax:
#ximport
"filename" symbolThis compiler directive places the length of filename (stored as a
long
) and its binary contents at the next available place in xmem flash. filename is assumed to be either relative to the Dynamic C installation directory or a fully qualified path. symbol is a compiler generated macro that gives the physical address where the length and contents were stored.The sample program
ximport.c
illustrates the use of this compiler directive.
| |
<< Previous | Index | Next >> | |
Z-World, Inc. www.zworld.com Phone: 1.530.757.3737 Fax: 1.530.757.3792 |
Rabbit Semiconductor www.rabbitsemiconductor.com Phone: 1.530.757.8400 Fax: 1.530.757.8402 |