Integrated C Development System For Rabbit 2000 and 3000 Microprocessors User’s Manual 019-0125_K
Dynamic C User’s Manual ©2011 Digi International® Inc. All rights reserved. Rabbit, Dynamic C, Rabbit 2000, Rabbit 3000, RabbitSys, Digi, Digi International, Digi International Company, and the Digi and Rabbit logos are trademarks or registered trademarks of Digi International, Inc. in the United States and other countries worldwide. All other trademarks are the property of their respective owners.
Table of Contents 1. Installing Dynamic C ......................................... 9 1.1 Requirements .............................................. 9 1.2 Assumptions ............................................... 9 2. Introduction to Dynamic C.............................. 11 2.1 The Nature of Dynamic C ........................ 11 2.1.1 Speed............................................ 11 2.2 Dynamic C Enhancements and Differences . 12 2.3 Rabbit and Z180 Comparison................... 14 3.
5.6 Patterns of Cooperative Multitasking .......68 5.7 Timing Considerations ..............................69 5.7.1 waitfor Accuracy Limits...............69 5.8 Overview of Preemptive Multitasking ......70 5.9 Slice Statements ........................................70 5.9.1 Slice Syntax ..................................70 5.9.2 Usage ............................................70 5.9.3 Restrictions ...................................71 5.9.4 Slice Data Structure ......................71 5.9.
11.3 Stand-Alone Assembly Code ................. 177 11.3.1 Stand-Alone Assembly Code in Extended Memory ........................... 177 11.3.2 Example of Stand-Alone Assembly Code................................................. 178 11.4 Embedded Assembly Code .................... 178 11.4.1 The Stack Frame....................... 178 11.4.2 Embedded Assembly Example 180 11.4.3 The Disassembled Code Window .. 181 11.4.4 Local Variable Access .............. 182 11.5 C Calling Assembly .......................
/ ............................................................233 ++.........................................................234 –– .........................................................234 %..........................................................234 13.2 Assignment Operators ............................235 =...........................................................235 +=.........................................................235 -= .........................................................235 *=.....
Global Variables ........................................ 341 Exception Types ........................................ 342 Rabbit Registers ........................................ 342 Appendix B: Map File Generation .................. 343 Grammar.................................................... 343 Appendix C: Security Software & Utility Programs 345 Rabbit Embedded Security Pack ............... 345 AES .................................................. 345 SSL ........................................
digi.
1. INSTALLING DYNAMIC C Insert the installation disk or CD in the appropriate disk drive on your PC. The installation should begin automatically. If it doesn’t, issue the Windows “Run...” command and type the following command ‹disk›:\SETUP The installation program will begin and guide you through the installation process. 1.1 Requirements Dynamic C requires an IBM-compatible PC running Windows 2000 or later with at least one free COM or USB port.
digi.
2. INTRODUCTION TO DYNAMIC C Dynamic C is an integrated development system for writing embedded software. It is designed for use with Rabbit controllers and other controllers based on the Rabbit microprocessor. 2.1 The Nature of Dynamic C Dynamic C integrates the following development functions: • • • • • Editing Compiling Linking Loading Debugging into one program. In fact, compiling, linking and loading are one function. Dynamic C has an easy-to-use, built-in, full-featured text editor.
2.2 Dynamic C Enhancements and Differences Dynamic C differs from a traditional C programming system running on a PC or under UNIX. The reason? To better help customers write the most reliable embedded control software possible. It is not possible to use standard C in an embedded environment without making adaptations. Standard C makes many assumptions that do not apply to embedded systems.
2.2.2 Dynamic C Differences The main differences in Dynamic C are summarized in the list below and discussed in detail in Chapter 4. “Language” and Chapter 12. “Keywords”. • If a variable is explicitly initialized in a declaration (e.g., int x = 0;), it is stored in flash memory (EEPROM) and cannot be changed by an assignment statement.
2.3 Rabbit and Z180 Comparison A major difference in the way Dynamic C interacts with a Rabbit-based board compared to a Z180 or 386EX board is that Dynamic C expects no BIOS kernel to be present on the target when it starts up. Dynamic C stores the BIOS kernel as a C source file. Dynamic C compiles and loads it to the Rabbit target when it starts. This is accomplished using the Rabbit CPU’s bootstrap mode and a special programming cable provided in all Rabbit product development kits.
3. QUICK TUTORIAL Sample programs are provided in the Dynamic C Samples folder, which is in the root directory where Dynamic C was installed. The Samples folder contains many subfolders, as shown in Figure 3.1. Sample programs are provided in source code format. You can open the source code file in Dynamic C and read the comment block at the top of the sample program for a description of its purpose and other details. Comments are also provided throughout the source code.
3.1 Run DEMO1.C This sample program will be used to illustrate some of the functions of Dynamic C. Open the file Samples/DEMO1.C using the File menu or the keyboard shortcut . The program will appear in a window, as shown in Figure 3.2 (minus some comments). Use the mouse to place the cursor on the function name printf in the program and press . This brings up a Function Description window for printf().
dialog box must be the same as the one the programming cable is connected to. (The Communications dialog box is accessed via the Communications tab of the Options | Project Options menu.) • To check if you have the correct serial port, press . If the “BIOS successfully compiled …” message does not display, choose a different serial port in the Communications dialog box until you find the serial port you are plugged into. Don’t change anything in this menu except the COM number.
Starting with Dynamic C 9, you can also set breakpoints while in edit mode. Breakpoint information is not only retained when going back and forth from edit mode to debug mode, it is stored when a file is closed and restored when the file is re-opened. 3.1.4 Editing the Program Press to put Dynamic C into edit mode. Use the “Save as” choice on the File menu to save the file with a new name so as not to change the original demo program. Save the file as MYTEST.C.
3.3 Run DEMO3.C The example below, sample program DEMO3.C, uses costatements. A costatement is a way to perform a sequence of operations that involve pauses or waits for some external event to take place. 3.3.1 Cooperative Multitasking Cooperative multitasking is a way to perform several different tasks at virtually the same time. An example would be to step a machine through a sequence of tasks and at the same time carry on a dialog with the operator via a keyboard interface.
The elapsed time message is printed by the costatement starting at the line marked (2). Costatements need to be executed regularly, often at least every 25 ms. To accomplish this, the costatements are enclosed in a while loop. The while loop starts at (1) and ends at (6). The statement at (3) waits for a time delay, in this case 1000 ms (one second). The costatement executes each pass through the while loop.
3.4.1 Trace Macros Trace macros provide more fine-grained control than the menu options. _TRACE The _TRACE macro creates one entry in the trace buffer containing the program state information at the time the macro executes. It is useful if you want to monitor one statement closely rather than follow the flow of part of a program. In Demo4.c, _TRACE is executed at lines 45 and 77, as you can see in the screenshot in Figure 3.3. Figure 3.3 Trace window contents after running Demo4.
3.5 Summary of Features This chapter provided a quick look at the interface of Dynamic C and some of the powerful options available for embedded systems programming. The following several paragraphs are a summary of what we’ve discussed. Development Functions When you load a program it appears in an editor window. You compile by clicking Compile on the task bar or from the Compile menu. The program is compiled into machine language and downloaded to the target over the serial port.
4. LANGUAGE Dynamic C is based on the C language. The programmer is expected to know programming methodologies and the basic principles of the C language. Dynamic C has its own set of libraries, which include user-callable functions. Please see the Dynamic C Function Reference Manual for detailed descriptions of these API functions. Dynamic C libraries are in source code, allowing the creation of customized libraries.
4.2 Punctuation Tokens Punctuation serves as boundaries in C programs. Table 4-2 lists the punctuation tokens. Table 4-2. Punctuation Marks and Tokens Token 24 Description : Terminates a statement label. ; Terminates a simple statement or a do loop. , Separates items in a list, such as an argument list, declaration list, initialization list, or expression list. ( ) Encloses argument or parameter lists. Function calls always require parentheses. Macros with parameters also require parentheses.
4.3 Data Data (variables and constants) have type, size, structure, and storage class. Basic (a.k.a., primitive) data types are shown below. Table 4-3. Dynamic C Basic Data Types Data Type Description char 8-bit unsigned integer. Range: 0 to 255 (0xFF) int 16-bit signed integer. Range: -32,768 to +32,767 unsigned int 16-bit unsigned integer. Range: 0 to +65,535 long 32-bit signed integer. Range: -2,147,483,648 to +2,147,483,647 unsigned long 32-bit unsigned integer.
4.4 Names Names identify variables, certain constants, arrays, structures, unions, functions, and abstract data types. Names must begin with a letter or an underscore (_), and thereafter must be letters, digits, or an underscore. Names may not contain any other symbols, especially operators. Names are distinct up to 32 characters, but may be longer. Names may not be the same as any keyword. Names are case-sensitive.
4.5 Macros Macros may be defined in Dynamic C by using #define. A macro is a name replacement feature. Dynamic C has a text preprocessor that expands macros before the program text is compiled. The programmer assigns a name, up to 31 characters, to a fragment of text. Dynamic C then replaces the macro name with the text fragment wherever the name appears in the program. In this example, #define OFFSET 12 #define SCALE 72 int i, x; i = x * SCALE + OFFSET; the variable i gets the value x * 72 + 12.
4.5.2 Nested Macro Definitions Generally speaking, Dynamic C expands macro calls recursively until they can expand no more. Another way of stating this is that macro definitions can be nested. The exceptions to this rule are 1. Arguments to the # and ## operators are not expanded. 2. To prevent infinite recursion, a macro does not expand within its own expansion. The following complex example illustrates this.
4.5.3 Macro Restrictions The number of arguments in a macro call must match the number of parameters in the macro definition. An empty parameter list is allowed, but the macro call must have an empty argument list. Macros are restricted to 32 parameters and 126 nested calls. A macro or parameter name must conform to the same requirements as any other C name. The C language does not perform macro replacement inside string literals, character constants, comments, or within a #define directive.
4.7 Strings and Character Data A string is a group of characters enclosed in double quotes (""). "Press any key when ready..." Strings in C have a terminating null byte appended by the compiler. Although C does not have a string data type, it does have character arrays that serve the purpose. C does not have string operators, such as concatenate, but library functions strcat() and strncat() are available.
4.7.2 Character Constants Character constants have a slightly different meaning. They are not strings. A character constant is enclosed in single quotes (' ') and is a representation of an 8-bit integer value. 'a' '\n' '\x1B' Any character can be represented by an alternate form, whether in a character constant or in a string. Thus, nonprinting characters and characters that cannot be typed may be used. A character can be written using its numeric value preceded by a backslash.
4.8 Statements Except for comments, everything in a C program is a statement. Almost all statements end with a semicolon. A C program is treated as a stream of characters where line boundaries are (generally) not meaningful. Any C statement may be written on as many lines as needed. Prior to Dynamic C 9.60, the compiler will parse up to 250 bytes for any single C statement in a “.c” or a “.lib” file. Starting with Dynamic C 9.60, the compiler will parse up to 64K bytes for any single C statement in a “.
4.10 Functions The basic unit of a C application program is a function. Most functions accept parameters (a.k.a., arguments) and return results, but there are exceptions. All C functions have a return type that specifies what kind of result, if any, it returns. A function with a void return type returns no result. If a function is declared without specifying a return type, the compiler assumes that it is to return an int (integer) value.
4.12 Type Definitions Both types and variables may be defined. One virtue of high-level languages such as C and Pascal is that abstract data types can be defined. Once defined, the data types can be used as easily as simple data types like int, char, and float. Consider this example.
The program above calculates the sum of squares of two numbers, g and h, which are initialized to 10 and 12, respectively. The main function calls the init function to give values to the global variables g and h. Then it uses the sumSquare function to perform the calculation and assign the result of the calculation to the variable x. It prints the result using the library function printf, which includes a formatting string as the first argument.
4.13.2 Structure Variables may be grouped together in structures (struct in C) or in arrays. Structures may be nested. struct { char flags; struct { int x; int y; } loc; } cursor; Structure members—the variables within a structure—are referenced using the dot operator. j = cursor.loc.x The size of a structure is the sum of the sizes of its components. 4.13.3 Union A union overlays simple or complex data. That is, all the union members have the same address.
4.14 Storage Classes Variable storage can be auto or static. The term “static” means the data occupies a permanent fixed location for the life of the program. The term “auto” refers to variables that are placed on the system stack for the life of a function call.The default storage class is auto, but can be changed by using #class static. The default storage class can be superseded by the use of the keyword auto or static in a variable declaration.
It is possible to do pointer arithmetic, but this is slightly different from ordinary integer arithmetic. Here are some examples. float f[10], *p, *q; p = &f; q = p+5; q++; p = p + q; // // // // // an array and some ptrs point p to array element 0 point q to array element 5 point q to array element 6 illegal! Because the float is a 4-byte storage element, the statement q = p+5 sets the actual value of q to p+20. The statement q++ adds 4 to the actual value of q.
You can pass arguments to functions that are called indirectly by pointers, but the compiler will not check them for correctness. This means that the auto promotions provided by Dynamic C type checking will not occur, so values must be cast to the type that is expected or the size may not be correct. For example, if a function takes a long as a parameter, and you pass it a 16-bit integer value, it must be cast to type long in order for 4 bytes to be put onto the stack.
4.18 Program Flow Three terms describe the flow of execution of a C program: sequencing, branching and looping. Sequencing is simply the execution of one statement after another. Looping is the repetition of a group of statements. Branching is the choice of groups of statements. Program flow is altered by calling a function, that is transferring control to the function. Control is passed back to the calling function when the called function returns. 4.18.
Here, there is no initial condition, no end condition, and no stepping expression. The loop body (some statement(s)) continues to execute endlessly. An endless loop can also be achieved with a while loop. This method is slightly less efficient than the for loop. while(1) { some statement(s) } 4.18.2 Continue and Break Two keywords are available to help in the construction of loops: continue and break. The continue statement causes the program control to skip unconditionally to the next pass of the loop.
4.18.3 Branching The goto statement is the simplest form of a branching statement. Coupled with a statement label, it simply transfers program control to the labeled statement. some statements abc: other statements goto abc; ... more statements goto def; ... def: more statements The colon at the end of the labels is required. In general, the use of the goto statement is discouraged in structured programming. The next simplest form of branching is the if statement.
The switch statement, the most complex branching statement, allows the programmer to phrase a “multiple choice” branch differently. switch( expression ){ case const1 : statements1 break; case const2 : statements2 break; } case const3 : statements3 break; ... default: statementsDEFAULT First the switch expression is evaluated. It must have an integer value. If one of the constN values matches the switch expression, the sequence of statements identified by the constN expression is executed.
4.19 Function Chaining Function chaining allows special segments of code to be distributed in one or more functions. When a named function chain executes, all the segments belonging to that chain execute. Function chains allow the software to perform initialization, data recovery, and other kinds of tasks on request. There are two directives, #makechain and #funcchain, and one keyword, segchain that create and control function chains: #makechain chain_name Creates a function chain.
4.20 Global Initialization Various hardware devices in a system need to be initialized, not only by setting variables and control registers, but often by complex initialization procedures. Dynamic C provides a specific function chain, _GLOBAL_INIT, for this purpose. Your program can add segments to the _GLOBAL_INIT function chain, as shown in the example below.
4.21 Libraries Dynamic C includes many libraries—files of useful functions in source code form. They are located in the \LIB directory where Dynamic C was installed. The default library file extension is .LIB. Dynamic C uses functions and data from library files and compiles them with an application program that is then downloaded to a controller or saved to a .bin file. An application program (the default file extension is .
4.21.1 LIB.DIR Any library that is to be #use’d in a Dynamic C program must be listed in the file LIB.DIR, or another *.DIR file specified by the user. The lib.dir strategy starting with Dynamic C 9.30 allows naming a folder with optional mask(s). No mask implies *.* and multiple masks are separated by “;” so that “lib” and “lib\*.*” both include all files and “lib\*.lib;*.c;*.h*” includes all files with extensions of .lib, .c and .h. Dynamic C generated file (e.g., .mdl, .hxl, etc.
4.23.1 The Parts of a Module A module has three parts: the key, the header, and the body. The structure of a module is: /*** BeginHeader func1, var2, .... */ prototype for func1 extern var2 /*** EndHeader */ definition of func1 declaration for var2 possibly other functions and data A module begins with its BeginHeader comment and continues until either the next BeginHeader comment or the end of the file is encountered. 4.23.1.
Using compiler directives like #class or #memmap inside module headers is inadvisable. If it is important to set, for example, “#class auto” for some library modules and “#class static” for others, the appropriate directives should be placed inside the module body, not in the module header.
4.23.2 Module Sample Code There are many examples of modules in the Lib directory of Dynamic C. The following code will illustrate proper module syntax and show the scope of directives, functions and variables. /*** BeginHeader ticks*/ extern unsigned long ticks; /*** EndHeader */ unsigned long ticks; /*** BeginHeader Get_Ticks */ unsigned long Get_Ticks(); /*** EndHeader */ unsigned long Get_Ticks(){ ...
/*** BeginHeader func_a */ int func_a(); #ifdef SECONDHEADER #define XYZ #endif /*** EndHeader */ int func_a(){ #ifdef SECONDHEADER printf ("I am function A.\n"); #endif } /*** BeginHeader func_b */ int func_b(); #define SECONDHEADER /*** EndHeader */ #ifdef XYZ #define FUNCTION_B #endif int func_b() { #ifdef FUNCTION_B printf ("I am function B.\n"); #endif } Let’s say the above file is named mylibrary.lib. If an application has the statement #use “mylibrary.
4.24 Function Description Headers Each user-callable function in a Dynamic C library has a descriptive header preceding the function to describe the function. Function headers are extracted by Dynamic C to provide on-line help messages. The header is a specially formatted comment, such as the following example. /* START FUNCTION DESCRIPTION ********************** WrIOport SYNTAX: void WrIOport(int portaddr, int value); DESCRIPTION: Writes data to the specified I/O port.
5. MULTITASKING WITH DYNAMIC C In a multitasking environment, more than one task (each representing a sequence of operations) can appear to execute in parallel. In reality, a single processor can only execute one instruction at a time. If an application has multiple tasks to perform, multitasking software can usually take advantage of natural delays in each task to increase the overall performance of the system.
State machines can become quite complicated, involving a large number of state variables and a large number of states. The advantage of the state machine is that it avoids busy waiting, which is waiting in a loop until a condition is satisfied. In this way, one big loop can service a large number of state machines, each performing its own task, and no one is busy waiting.
5.2.1 Solving the Real-Time Problem with a State Machine Here is what a state machine solution might look like.
5.3 Costatements Costatements are Dynamic C extensions to the C language which simplify implementation of state machines. Costatements are cooperative because their execution can be voluntarily suspended and later resumed. The body of a costatement is an ordered list of operations to perform -- a task. Each costatement has its own statement pointer to keep track of which item on the list will be performed when the costatement is given a chance to run.
5.3.2 Costatement Syntax The keyword costate identifies the statements enclosed in the curly braces that follow as a costatement. costate [ name [state] ] { [ statement | yield; | abort; | waitfor( expression ); ] . . .} name can be one of the following: • A valid C name not previously used. This results in the creation of a structure of type CoData of the same name.
Figure 5-2 Execution thread when waitfor evaluates to false costate ... { statement statement ... waitfor( ... ); ... statement statement } costate ... { statement statement ... waitfor( ... ); ... statement statement } (a) First Time (b) Subsequent Times Figure 5-3 shows the execution thread through a costatement when a waitfor evaluates to true. Figure 5-3 Execution thread when waitfor evaluates to true costate ... { statement statement ... waitfor( ... ); ...
abort The abort statement causes the costatement or cofunction to terminate execution. If a costatement is always_on, the next time the program reaches it, it will restart from the top. If the costatement is not always_on, it becomes inactive and will not execute again until turned on by some other software. Figure 5-5 Execution thread with abort statement costate ... { statement statement ... abort; ... statement statement } costate ... { statement statement ... abort; ...
5.4.2 CoData Fields This section describes the fields of the CoData structure. CSState The CSState field contains two flags, STOPPED and INIT. The possible flag values and their meaning are in the table below. Table 5-1. Flags that Specify the Run Status of a Costatement STOPPED INIT State of Costatement yes yes Done, or has been initialized to run, but set to inactive. Set by CoReset(). yes no Paused, waiting to resume. Set by CoPause(). no yes Initialized to run. Set by CoBegin().
Content The content field (a union) is used by the costatement or cofunction delay routines to store a delay count. Check Sum 2 The ChkSum2 field is currently unused. 5.4.3 Pointer to CoData Structure To obtain a pointer to a named costatement’s CoData structure, do the following: static CoData static CoData cost1; *pcost1; pcost1 = &cost1; ... CoBegin (pcost1); costate pcost1 { ...
5.4.5 Firsttime Functions In a function definition, the keyword firsttime causes the function to have an implicit first parameter: a pointer to the CoData structure of the costatement that calls it. User-defined firsttime functions are allowed. The following firsttime functions are defined in COSTATE.LIB. DelayMs(), DelaySec(), DelayTicks() IntervalMs(), IntervalSec(), IntervalTick() For more information see the Dynamic C Function Reference Manual.
type Whichever keyword (cofunc or scofunc) is used is followed by the data type returned (void, int, etc.). name A name can be any valid C name not previously used. This results in the creation of a structure of type CoData of the same name. dim The cofunction name may be followed by a dimension if an indexed cofunction is being defined. cofunction arguments (arg1, . . ., argN) As with other Dynamic C functions, cofunction arguments are passed by value.
5.5.2.1 Costate Within a Cofunc In all but trivial cases (where the costate is really not necessary), a costate within a cofunc causes execution problems ranging from never completing the cofunc to unexpected interrupts or target lockups. To avoid these problems, do not introduce costates with nested wfd cofuncs into a cofunc. If you find yourself coding such a thing, consider these alternatives: 1. Intermediate regular functions can be used between the cofuncs to isolate them. 2.
The indexed cofunction call is a cross between an array access and a normal function call, where the array access selects the specific instance to be run. Typically this type of cofunction is used in a situation where N identical units need to be controlled by the same algorithm. For example, a program to control the door latches in a building could use indexed cofunctions. The same cofunction code would read the key pad at each door, compare the passcode to the approved list, and operate the door latch.
Example // echoes characters main() { int c; serAopen(19200); loopinit(); while (1) { loophead(); costate { wfd c = cof_serAgetc(); wfd cof_serAputc(c); } } serAclose(); } 5.5.6 Types of Cofunction Calls A wfd statement makes one of three types of calls to a cofunction. 5.5.6.1 First Time Call A first time call happens when a wfd statement calls a cofunction for the first time in that statement.
5.5.7 Special Code Blocks The following special code blocks can appear inside a cofunction. everytime { statements } This must be the first statement in the cofunction. The everytime statement block will be executed on every cofunc continuation call no matter where the statement pointer is pointing. After the everytime statement block is executed, control will pass to the statement pointed to by the cofunction’s statement pointer.
5.5.8 Solving the Real-Time Problem with Cofunctions Cofunctions, with their ability to receive arguments and return values, provide more flexibility and specificity than our previous solutions. for(;;){ costate{ wfd emergencystop(); for (i=0; i
5.7 Timing Considerations In most instances, costatements and cofunctions are grouped as periodically executed tasks. They can be part of a real-time task, which executes every n milliseconds as shown below using costatements. Figure 5-6 Costatement as Part of Real-Time Task If all goes well, the first costatement will be executed at the periodic rate. The second costatement will, however, be delayed by the first costatement. The third will be delayed by the second, and so on.
5.8 Overview of Preemptive Multitasking In a preemptive multitasking environment, tasks do not voluntarily relinquish control. Tasks are scheduled to run by priority level and/or by being given a certain amount of time. There are two ways to accomplish preemptive multitasking using Dynamic C. The first way is via a Dynamic C construct called the “slice” statement (described in Section 5.9).
5.9.3 Restrictions Since a slice statement has its own stack, local auto variables and parameters cannot be accessed while in the context of a slice statement. Any function called from the slice statement performs normally. Only one slice statement can be active at any time, which eliminates the possibility of nesting slice statements or using a slice statement inside a function that is either directly or indirectly called from a slice statement.
5.9.5.1 Example 1 Two slice statements and a costatement will appear to run in parallel. Each block will run independently, but the slice statement blocks will suspend their operation after 20 ticks for slice_a and 40 ticks for slice_b. Costate a will not release control until it either explicitly yields, aborts, or completes. In contrast, slice_a will run for at most 20 ticks, then slice_b will begin running. Costate a will get its next opportunity to run about 60 ticks after it relinquishes control.
5.9.5.3 Example 3 This approach is more complicated, but will allow you to spend the idle time doing a low-priority background task. main() { int time_left; long start_time; for(;;) { start_time = TICK_TIMER; slice(500,20) { waitfor(IntervalTick(80)); ... } slice(500,50) { waitfor(IntervalTick(105)); ... } time_left = 75-(TICK_TIMER-start_time); if(time_left>0) { slice(500,75-(TICK_TIMER-start_time)) { ... } } } // slice_a // slice_b // slice_c } Dynamic C User’s Manual digi.
5.10 µC/OS-II µC/OS-II is a simple, clean, efficient, easy-to-use real-time operating system that runs on the Rabbit microprocessor and is fully supported by the Dynamic C development environment. With Dynamic C, there is no fee to pay for the “Object Code Distribution License” that is usually required for embedding µC/OS-II in a product. µC/OS-II is capable of intertask communication and synchronization via the use of semaphores, mailboxes, and queues.
#define OS_TICKS_PER_SEC 32 ... OSInit(); ... OSStart(); 5.10.1.2 Task Creation In a µC/OS-II application, stacks are declared as static arrays, and the address of either the top or bottom (depending on the CPU) of the stack is passed to OSTaskCreate. In a Rabbit-based system, the Dynamic C development environment provides a superior stack allocation mechanism that µC/OS-II incorporates.
If an application uses OSTaskCreateExt, which enables stack checking and allows an extension of the Task Control Block, fewer parameters are needed in the Rabbit version of µC/OS-II.
Figure 5-7 Type 1 ISR Task 1 Interrupt X Interrupt X ISR ipres Task 1 If, however, an ISR needs to signal a task to the ready state, then the ISR must be tasking aware. In the example in Figure 5-8, the TA-ISR increments the interrupt nesting counter, does the work necessary for the ISR, readies a higher priority task, decrements the nesting count, and returns to the higher priority task.
Figure 5-9 Type 2 ISR Nested Inside Type 3 ISR Task 2 Interrupt Z Nesting = 1 Do critical code ipres Interrupt X Interrupt Z TA-ISR Interrupt X TA-ISR Nesting = 2 Task 1 is readied Nesting = 1 ipres Finish ISR Nesting = 0 Task 1 As can be seen here, although the ISR for interrupt Z does not signal any tasks by posting to a semaphore, mailbox, or queue, it must increment and decrement the interrupt nesting count since it re-enables interrupts (ipres) prior to finishing all of its work. 5.10.2.
Figure 5-10 Logical Flow of a TA-ISR Save registers used by TA-ISR Clear interrupt source Increment nesting count Do work necessary for interrupt Reenable interrupts (optional) Call OSIntExit Decrement Nesting Count Is Nesting == 0 ? Yes Is switch pending ? No No Yes Restore Registers used by TA-ISR Switch to new task Return from interrupt Dynamic C User’s Manual digi.
5.10.2.3.1 Sample Code for a TA-ISR Fortunately, the Rabbit BIOS and libraries provide all of the necessary flags to make TA-ISRs work. With the code found in Listing 1, minimal work is needed to make a TA-ISR function correctly with µC/OS-II. TA-ISRs allow µC/OS-II the ability to have ISRs that communicate with tasks as well as the ability to let ISRs nest, thereby reducing interrupt latency. Just like a standard ISR, the first thing a TA-ISR does is to save the registers that it is going to use (1).
taisr_decnesting: push ip ipset 1 (8) ld dec jr hl,bios_intnesting (hl) nz,taisr_noswitch ; nesting counter == 1? ld or jr a,(bios_swpend) a z,taisr_noswitch ; switch pending? push push ex push exx push push push push de bc af,af’ af lcall bios_intexit pop pop pop pop exx pop ex pop pop iy bc de hl (9) (10) (11) hl de bc iy af af,af’ bc de taisr_noswitch: pop ip taisr_done: pop hl pop af ipres ret #endasm Dynamic C User’s Manual (12) digi.
5.10.3 Library Reentrancy When writing a µC/OS-II application, it is important to know which Dynamic C library functions are nonreentrant. If a function is non-reentrant, then only one task may access the function at a time, and access to the function should be controlled with a µC/OS-II semaphore. The following is a list of Dynamic C functions that are non-reentrant. Table 5-3. Dynamic C Non-Reentrant Functions Library Non-Reentrant Functions MATH.LIB randg, randb, rand RS232.LIB All RTCLOCK.
5.10.4 How to Get a µC/OS-II Application Running µC/OS-II is a highly configureable, real-time operating system. It can be customized using as many or as few of the operating system’s features as needed. This section outlines: • The configuration constants used in µC/OS-II • How to override the default configuration supplied in UCOS2.
OS_MEM_EN Disable memory manager Default is 0 OS_MBOX_EN Enable mailboxes Default is 1 OS_SEM_EN Enable semaphores Default is 1 OS_TICKS_PER_SEC Number of ticks in one second Default is 64 STACK_CNT_256 Number of 256 byte stacks (idle task stack) Default is 1 STACK_CNT_512 Number of 512-byte stacks (task stacks + initial program stack) Default is OS_MAX_TASKS+1 (11) If a particular portion of µC/OS-II is disabled, the code for that portion will not be compiled, making the overall size of the ope
application tasks will each have a 1024 byte stack, ten will each have a 2048 byte stack, and an extra stack is declared for the statistics task. 5.10.4.3 Examples The following sample programs demonstrate the use of the default configuration supplied in UCOS2.LIB and a custom configuration which overrides the defaults. Example 1 In this application, ten tasks are created and one semaphore is created.
// 1. Explicitly use µC/OS-II library #use "ucos2.lib" void RandomNumberTask(void *pdata); // 2. Declare semaphore global so all tasks have access OS_EVENT* RandomSem; void main(){ int i; // 3. Initialize OS internals OSInit(); for(i = 0; i < OS_MAX_TASKS; i++) // 4. Create each of the system tasks OSTaskCreate(RandomNumberTask, NULL, 512, i); // 5. semaphore to control access to random number generator RandomSem = OSSemCreate(1); // 6.
Example 2 This application runs exactly the same code as Example 1, except that each of the tasks are created with 1024-byte stacks. The main difference between the two is the configuration of µC/OS-II. First, each configuration constant that differs from the library default is defined.
void RandomNumberTask(void *pdata) { // Declare as auto to ensure reentrancy. auto OS_TCB data; auto INT8U err; auto INT16U RNum; OSTaskQuery(OS_PRIO_SELF, &data); while(1) { // Rand is not reentrant, so access must be controlled via a semaphore. OSSemPend(RandomSem, 0, &err); RNum = (int)(rand() * 100); OSSemPost(RandomSem); printf("Task%02d's random #: %d\n",data.OSTCBPrio,RNum); // Wait 3 seconds in order to view output from each task. OSTimeDlySec(3); } } 5.10.
If MAX_TCP_SOCKET_BUFFERS is not defined in the application program, it will be defined as MAX_SOCKETS. If, however, MAX_SOCKETS is not defined in the application program, MAX_TCP_SOCKET_BUFFERS will be 4. If MAX_UDP_SOCKET_BUFFERS is not defined in the application program, it will be defined as 1 if USE_DHCP is defined, or 0 otherwise. For more information about TCP/IP, please see the Dynamic C TCP/IP User’s Manual, Volumes 1 and 2, available online at www.digi.com/support. 5.10.
digi.
6. DEBUGGING WITH DYNAMIC C This chapter is intended for anyone debugging Dynamic C programs. For the person with little to no experience, we offer general debugging strategies in Section 6.5. Both experienced and inexperienced Dynamic C users can refer to Section 6.3 to see the full set of tools, programs and functions available for debugging Dynamic C programs. Section 6.4 consolidates the information found in the GUI chapter regarding debugging features into an quicker-to-read table of GUI options.
6.2 Debugging Features Introduced in Dynamic C 9 Dynamic C 9 contains all the previous debugging tools and the additional ones listed here. • Execution Trace - Traces at each statement, each function, or customer inserted points. Displays results in the Trace window. The options for execution tracing are configurable. This feature is disabled by default. • Symbolic Stack Trace - Helps customers find out the path of the program at each single step or break point.
6.3 Debugging Tools This section describes the different tools available for debugging, including their pros and cons, as well as when you might want to use them, how to use them and an example of using them. The examples are suggestions and are not meant to be restrictive. While there may be some collaboration, bug hunting is largely a solitary sport, with different people using different tools and methods to solve the same problem. 6.3.
Example There are numerous examples of using printf() in the programs provided in the Samples folder where you installed Dynamic C. To display a string to the Stdio window place the following line of code in your application: printf("Entering my_function().\n"); To do the same thing, but without using root memory: xdata entering {“Entering my_function().”}; ... printf("%ls\n", entering); 6.3.2 Software Breakpoints Software breakpoints have always been available in Dynamic C.
Example Open Samples\Demo1.c. If you are using DC 9, place the cursor on the word “for,” then press F2 to insert a breakpoint. Otherwise, press F5 to compile the program before setting the breakpoint. Now press F9. Every time you press F9 program execution will stop when it hits the start of the for loop. From here you can single step or look at a variety of information through debug windows. For example, let us say there is a problem when you get to the limit of a for loop.
6.3.3 Single Stepping Single stepping has always been available in Dynamic C. In version 7.10, the ability to single step on C statements with the Assembly window open was added. Pros Single stepping allows you to closely supervise program execution at the source code level, either by C statement or assembly statement. This helps in tracing the logic of the program. You can single step any debuggable statement.
6.3.4 Watch Expressions Like many other debugging features, watch expressions have been around since the beginning and have improved over time. Dynamic C 8.01 introduced the ability to evaluate watchable expressions using flyover hints. (The highlighted expression does not need to be set as a watch expression for evaluation in a flyover hint.) Dynamic C 9 introduced a new way of handling structures as watch expressions.
6.3.5 Evaluate Expressions The evaluate expression functionality was separated out from watch expressions in Dynamic C 8.01. It is a special case of a watch expression evaluation in that the evaluation takes place once, when the Evaluate button is clicked, not every time the Watches window is updated. 98 Pros Like watches, you can use the Evaluate Expression feature on any valid C expression. Multiple Evaluate Expression dialogs can be opened simultaneously.
6.3.6 Memory Dump The Dump window was improved in Dynamic C 8.01 in several ways. For example, multiple dump windows can be active simultaneously, flyover hints make it easier to see the correct address, and three different types of dumps are allowed. Read the section titled, “Dump at Address,” for more information on these and the other improvements made in version 8.01. In Dynamic C 9, dump windows were improved again.
6.3.7 MAP File Map files have been generated for compiled programs since Dynamic C 7.02. Pros The map file is full of useful information. It contains, • location and size of code and data segments • a list of all symbols used, their location, size and their file of origin • a list of all macros used, their file of origin and the line number within that file where the macro is defined • function call graph A valid map file is produced after a successful compile, so it is available when a program crashes.
bytes added to the program. The follows action is an advanced topic related to the subject of origin directives. See the Rabbit 3000 Designer’s Handbook for a discussion of origin directives and action qualifiers. The map file provides the logical and physical addresses of the program and its data. The screen shot below shows a small section of demo1.map. The leftmost column shows line numbers, with addresses to their immediate right.
6.3.8 Execution Trace Execution tracing was introduced in Dynamic C 9. The program Samples\demo4.c demonstrates its use. Go to Section 3.4 for a full description of demo4.c. There are basically three ways to toggle tracing during program execution. Two of them are similar: they require that tracing be enabled in the Debugger tab of the Project Options dialog and they do not trace in nodebug functions.
6.3.9 Symbolic Stack Trace Dynamic C has always had the Stack window, but the Stack Trace window is new in Dynamic C 9. The old Stack window is still available to any compiled program, and being able to view the top 32 bytes of the stack could still be useful. The Stack Trace window lets you see where you are and how you got there. It keeps a running depth value, telling you how many bytes have been pushed on the stack in the current program instance, or since the depth value reset button was clicked.
6.3.10 Assert Macro The assert macro was introduced in Dynamic C 8.51. The Dynamic C implementation of assert follows the ANSI standard for the NDEBUG macro, but differs in what the macro is defined to be so as to save code space (ANSI specifies that assert is defined as ((void)0) when NDEBUG is defined, but this generates a NOP in Dynamic C, so it is defined to be nothing). Pros The assert macro is self-checking software.
xalloc_stats() Prints a table of physical addresses that are available for allocation in xmem via xalloc() calls. To display this information in the Stdio window, execute the statement: xalloc_stats(0); in your application or use Inspect | Evaluate Expression. The Stdio window will display something similar to the following: A region is a contiguous piece of memory. Theoretically, up to four regions can exist; a region that is marked “dummy” is a region that does not exist.
Watchdogs Ten virtual watchdogs are provided, in addition to the hardware watchdog(s) of the processor. Watchdogs, whether hardware or software, limit the amount of time a system is in an unknown state. Virtual watchdogs are maintained by the Virtual Driver and described in Section 7.4.2. The sample program Samples\VDRIVER\VIRT_WD.C demonstrates the use of a virtual watchdog. Compiler Options The Compiler tab of the Project Options dialog contains several options that assist debugging.
6.4 Where to Look for Debugger Features Debugger features are accessed from several different Dynamic C menus. The menu to look in depends on whether you want to enable, configure, view or use the debugger feature. This section identifies the various menus that deal with debugging. Table 6-1 summarizes the menus and debugging tools. Table 6-1.
Table 6-1. Summary of Debug Tools and Menus Name of Feature Where Feature is Configured Where Feature is Enabled Where Feature is Toggleda Stdio, Stack and Register windows Environment Options, Debug Windows tab Always enabled Windows Menu a. Keyboard shortcuts and toolbar menu buttons are shown in the dropdown menus, along with their corresponding menu commands. 6.4.1 Run and Inspect Menus The Run and Inspect menus are covered in detail in Section 14.2.5 and Section 14.2.6, respectively.
6.5 Debug Strategies Since bug-free code is a trade-off with time and money, we know that software has bugsi. This section discusses ways to minimize the occurrence of bugs and gives you some strategies for finding and eliminating them when they do occur. 6.5.1 Good Programming Practices There is a big difference between “buggy code” and code that runs with near flawless precision. The latter program may have a bug, but it may be a relatively minor problem that only appears under abnormal circumstances.
• Coding Standards: The use of coding standards increases maintainability, portability and re-use of code. In Dynamic C libraries and sample programsi some of the standards are as follows: - Macros names are capitalized with an underscore separating words, e.g., MY_MACRO. - Function names start with a lowercase letter with an underscore or a capital letter separating words, e.g., my_function() or myFunction(). - Use parenthesis. Do not assume everyone has memorized the rules of precedence. E.g.
6.5.2.1 Reproduce the Problem Keep an open mind. It might not be a bug in the software: you might have a bad cable connection, or something along those lines. Check and eliminate the easy things first. If you are reasonably sure that your hardware is in good working order, then it is time to debug the software. Some bugs are consistent and are easy to reproduce, which means it will be easier to gather the information needed to solve the problem. Other bugs are more elusive.
6.5.2.3 Other Things to Try Get out of your cubicle. It is a well-known fact that there are times when simply walking over to a coworker and explaining your problem can result in a solution. Probably because it is a form of data gathering. The more data you gather (up to a point), the more you know, and the more you know, the more your chances of figuring out the problem increase. Stay in your cubicle. Log on and get involved in one of the online communities.
7. THE VIRTUAL DRIVER Virtual Driver is the name given to some initialization services and a group of services performed by a periodic interrupt.
7.3 Global Timer Variables SEC_TIMER, MS_TIMER and TICK_TIMER are global variables defined as shared unsigned long. These variables should never be changed by an application program. Among other things, the TCP/IP stack depends on the validity of the timer variables. On initialization, SEC_TIMER is synchronized with the real-time clock. The date and time can be accessed more quickly by reading SEC_TIMER than by reading the real-time clock.
7.3.2 Example: Delay Loop An important detail about MS_TIMER is that it overflows (“rolls over”) approximately every 49 days, 17 hours. This behavior causes the following delay loop code to fail: /* THIS CODE WILL FAIL!! */ endtime = MS_TIMER + delay; while (MS_TIMER < endtime) { //do something } If “MS_TIMER + delay” overflows, this returns immediately.
7.4 Watchdog Timers Watchdog timers limit the amount of time your system will be in an unknown state. 7.4.1 Hardware Watchdog The Rabbit CPU has one built-in hardware watchdog timeri. The Virtual Driver hits the watchdog timer (WDT) periodically. The following code fragment could be used to disable this WDT: #asm ld a,0x51 ioi ld (WDTTR),a ld a,0x54 ioi ld (WDTTR),a #endasm However, it is recommended that the watchdog not be disabled.
7.5 Preemptive Multitasking Drivers A simple scheduler for Dynamic C’s preemptive slice statement is serviced by the Virtual Driver. The scheduling for µC/OS-II, a more traditional full-featured real-time kernel, is also done by the Virtual Driver. These two scheduling methods are mutually exclusive—slicing and µC/OS-II must not be used in the same program. Dynamic C User’s Manual digi.
digi.
8. RUN-TIME ERRORS Compiled code generated by Dynamic C calls an exception handling routine for run-time errors. The exception handler supplied with Dynamic C prints internally defined error messages to a Windows message box when run-time errors are detected during a debugging session. When software runs stand-alone (disconnected from Dynamic C), such a run-time error will cause a watchdog timeout and reset. Run-time error logging is available for Rabbit-based target systems with battery-backed RAM. 8.
8.1.2 Fatal Error Codes This table lists the fatal errors generated by Dynamic C. Table 8-2.
8.2 User-Defined Error Handler Dynamic C allows replacement of the default error handler with a custom error handler. This is needed to add run-time error handling that would require treatment not supported by the default handler. A custom error handler can also be used to change how existing run-time errors are handled.
8.3 Run-Time Error Logging Error logging is available as a BIOS enhancement for storing run-time exception history. It can be useful diagnosing problems in deployed Rabbit targets. To support error logging, the target must have batterybacked RAM. The wide range of error logs available with RabbitSys obviates the need for the default error logging described here. 8.3.
8.3.2 Initialization and Defaults An initialization of the error log occurs when the BIOS is compiled, when cloning takes place or when the BIOS is loaded via the Rabbit Field Utility (RFU). By default, error logging is disabled. The error log buffer contains header information as well as an entry for each run-time error. A debug startup will zero out this header structure, but the run-time error entries can still be examined from Dynamic C using the static information in flash.
8.3.4 Error Logging Functions The run-time error logging API consists of the following functions: errlogGetHeaderInfo Reads error log header and formats output. errlogGetNthEntry Loads errLogEntry structure with the Nth entry from the error log buffer. errLogEntry is a pre-allocated global structure. errlogGetMessage Returns a NULL-terminated string containing the 8 byte error message in errLogEntry. errlogFormatEntry Returns a NULL-terminated string containing basic information in errLogEntry.
9. MEMORY MANAGEMENT Processor instructions can specify 16-bit addresses, giving a logical address space of 64K (65,536 bytes). Dynamic C supports a physical address space of 1 MB on all Rabbit-based boards. Dynamic C has been verified to work with Rabbit-based boards with 4.5 MB of memory. An on-chip memory management unit (MMU) translates 16-bit addresses to 20-bit memory addresses for Rabbit 2000- and 3000-based boards.
If BIOS code runs from flash memory, the BIOS code starts in the root code section at address 0x00000 and fills upward. The rest of the root code will continue to fill upward immediately following the BIOS code. If the BIOS code runs from SRAM, the root code section, along with root data and stack sections, will start at address 0x80000. 9.1.1 Memory Mapping Control The advanced user of Dynamic C can control how Dynamic C allocates and maps memory.
Inline Assembly in C Functions Inline assembly code may be written in any C function, regardless of whether it is compiled to extended memory or root memory. All static variables, even those local to extended memory functions, are placed in root memory. Keep this in mind if the functions have many variables or large arrays. Root memory can fill up quickly. 9.
digi.
10. FILE SYSTEMS This chapter describes two separate file systems that can be used on Rabbit-based systems. The file system described in Section 10.1 works with all versions of Dynamic C for the Rabbit 2000 and 3000 microprocessors. The FAT file system described in Section 10.2 requires Dynamic C 8.51 or later. There have been several updates to the FAT file system to include additional flash devices. FAT version 1.02 supports SPI-based serial flash devices. FAT versions 2.01 and 2.
Increase the useful lifetime and performance of the flash by buffering data before writing it to the flash. Accumulating 1000 single byte writes into one multi-byte write can extend the life of the flash by an average of 750 times. FS2 does not currently perform any in-memory buffering. If you write a single byte to a file, that byte will cause write activity on the device. This ensures that data is written to non-volatile storage as soon as possible.
10.1.1.4 Wear Leveling The current code has a rudimentary form of wear leveling. When you write into an existing block it selects a free block with the least number of writes. The file system routines copy the old block into the new block adding in the user’s new data. This has the effect of evening the wear if there is a reasonable turnover in the flash files. This goes for the data as well as the metadata. 10.1.1.
10.1.2.2 FS2 Configuration Macros FS_MAX_DEVICES This macro defines the maximum physical media. If it is not defined in the program code, FS_MAX_DEVICES will default to 1, 2, or 3, depending on the values of FS2_USE_PROGRAM_FLASH, XMEM_RESERVE_SIZE and FS2_RAM_RESERVE. FS_MAX_LX This macro defines the maximum logical extents. You must increase this value by 1 for each new partition your application creates. It this is not defined in the program code it will default to FS_MAX_DEVICES.
FS2_USE_PROGRAM_FLASH The number of kilobytes reserved in the first flash for use by FS2. If not defined in an application, it defaults to zero, meaning that the first flash is not used by FS2. The actual amount of flash used by FS2 is determined by the minimum of this macro and XMEM_RESERVE_SIZE. XMEM_RESERVE_SIZE This macro is the number of bytes (which must be a multiple of 4096) reserved in the first flash for use by FS2 and possibly other customer-defined purposes. This is defined as 0x0000.
10.1.3 File System API Functions These functions are defined in FS2.LIB. For more information please see the Dynamic C Function Reference Manual or from within Dynamic C you can use the Function Lookup feature, with its convenient Ctrl+H shortcut that will take you directly to a function’s description if the cursor is on its name in the active edit window. Table 10-1. FS2 API Command 134 Description fs_setup (FS2) Alters the initial default configuration.
10.1.3.1 FS2 API Error Codes The library ERRNO.LIB contains a list of all possible error codes returnable by the FS2 API. These error codes mostly conform to POSIX standards. If the return value indicates an error, then the global variable errno may be examined to determine a more specific reason for the failure. The possible errno codes returned from each function are documented with the function. 10.1.4 Setting up and Partitioning the File System This step merits some thought before plowing ahead.
10.1.4.2 Logical Extents (LX) The presence of both “devices” causes an initial default configuration of two logical extents (a.k.a., LXs) to be set up. An LX is analogous to disk partitions used in other operating systems. It represents a contiguous area of the device set aside for file system operations. An LX contains sectors that are all the same size, and all contiguously addressable within the one device.
10.1.4.3 Logical Sector Size fs_setup() can also be used to specify non-default logical sector (LS) sizes and other parameters. FS2 allows any logical sector size between 64 and 8192 bytes, providing the LS size is an exact power of 2. Each logical extent, including sub-partitions, can have a different LS size. This allows some performance optimization. Small LSs are better for a RAM LX, since it minimizes wasted space without incurring a performance penalty.
Table 10-2. Flash File System Auxiliary Functions Command 138 Description sspec_addfsfile Associate a name with the flash file system file number. The return value is an index into an array of structures associated with the named files. sspec_readfile Read a file represented by the return value of sspec_addfsfile into a buffer. sspec_getlength Get the length (number of bytes) of the file. sspec_getfileloc Get the file system file number (1- 255). Cast return value to FILENUMBER.
10.1.6 Skeleton Program Using FS2 The following program uses some of the FS2 API. It writes several strings into a file, reads the file back and prints the contents to the Stdio window. #use "FS2.
10.2 FAT File System Dynamic C 8.51 introduced a FAT (File Allocation Table) file system. The small footprint of this welldefined industry-standard file system makes it ideal for embedded systems. The Dynamic C implementation of FAT has a directory structure that can be accessed with either Unix or DOS style paths. The standard directory structure allows monitoring, logging, Web browsing, and FTP updates of files. The FAT filesystem is included with Dynamic C starting with version 9.60.
10.2.1 Overview of FAT Documentation A sample program is reviewed in Section 10.2.2. Two additional sample programs, one for use with the blocking mode of the FAT and the other for use with the non-blocking mode are described in Section 10.2.3. Then Section 10.2.4 gives detailed descriptions of the various FAT file system functions (formatting, opening, reading, writing, and closing). Short, focused examples accompany each description.
The sample program has been broken into two functional parts for the purpose of discussion. The first part deals with getting the file system up and running. The second part is a description of writing and reading files. 10.2.2.1 Bringing Up the File System We will look at the first part of the code as a whole, and then explain some of its details. File Name: Samples\FileSystem\fat_create.c #define FAT_BLOCK #use "fat.
The first two statements: #define FAT_BLOCK #use "fat.lib" cause the FAT library to be used in blocking mode. FAT version 2.01 introduces a configuration library that chooses initialization settings based on the board type.The statement #use “fat.lib” brings in this configuration library, which in turn brings in the appropriate device driver library. The following table lists the device drivers that are available in the different FAT versions. Table 11. FAT Version Device Driver 1.02, 2.01 sflash_fat.
Lastly, a pointer to a partition structure is declared with the statement: fat_part *first_part; This pointer will be used as a handle to an active partition. (The fat_part structure and other data structures needed by the FAT file system are discussed in fat_AutoMount().) The partition pointer will be passed to API functions, such as fat_open(). Now a call is made to fat_AutoMount(). This function was introduced in FAT version 2.01 as a replacement for fat_Init().
10.2.2.2 Using the File System The rest of fat_create.c demonstrates how to use the file system once it is up and running. File Name: Samples\FileSystem\fat_create.c prealloc = 0; rc = fat_Open( first_part, "HELLO.
The call to fat_Open() creates a file in the root directory and names it HELLO.TXT. A file must be opened before you can write or read it. rc = fat_Open(first_part, "HELLO.TXT", FAT_FILE, FAT_CREATE, &my_file, &prealloc); The parameters are as follows: • first_part points to the partition structure initialized by fat_AutoMount(). • "HELLO.TXT" is the file name, and is always an absolute path name relative to the root directory. All paths in Dynamic C must specify the full directory path explicitly.
The file is closed to release the file handle to allow it to be used to identify a different file. rc = fat_Close( &my_file ); The parameter &my_file is a handle to the file to be closed. Remember to check for any return code from fat_Close() since an error return code may indicate the loss of data. The file must be opened for any further work, even though &my_file may still reference the desired file. The file must be open to be active, so we call fat_Open() again. Now the file can be read.
10.2.3 More Sample Programs This section studies blocking sample FAT_SHELL.C and non-blocking sample FAT_NB_Costate.c More sample programs are in the Dynamic C folder Samples\FileSystem\FAT. For example, there is udppages.c, an application that shows how to combine HTTP, FTP and zserver functionality to create web content than can be updated via FTP. As described in Section 10.2.
> ls Listing '' (dir length 16384) hello.txt rhsvdA len=15 > clust=2 This shows the HELLO.TXT file that was created using the FAT_CREATE.C sample program. The file length is 15 bytes. Cluster 2 has been allocated for this file. The “ls” command will display up to the first six clusters allocated to a file. The flag, rhsvdA, displays the file or directory attributes, with upper case indicating that the attribute is turned on and lower case indicating that the attribute is turned off.
To see what was written, use the “rd” command. > rd rabbit.txt rabbit.txt 1024 The quick brown fox jumps over the lazy dog rabbit.txt 1024 The quick brown fox jumps over the lazy dog . . rab Read 1024 bytes out of 1024 > 10.2.3.2 Non-Blocking Sample To use the FAT file system in non-blocking mode, do not include the statement #define FAT_BLOCK in your application.
A while loop accomplishes our goal of blocking on the function call until it returns something other than busy. while ((rc = fat_Open( first_part, name, FAT_FILE, FAT_MUST_CREATE, &file, &alloc)) == -EBUSY); The second difference from our earlier sample is the statement right before fat_Open(): file.state = 0; This is required before opening a file when using non-blocking mode in order to indicate that the file is not in use. Only do this once.
waitfor (filestate == 0); filestate = 1; // Wait until file is available // Show file is being updated The next block of code appends the latest entry into the file that was opened at the start of the application.
The outer while loop controls when to stop reading records from the file. After the last record is read, the fat_Read() function is called once more, returning an end-of-file error. This causes the if statements that are checking for this error to return TRUE, which resets filestate to zero, breaking out of the outer while loop and freeing the lock for the putdata costatement to use.
10.2.4 FAT Operations There are some basic groups of operations involved in using the Dynamic C FAT library. These are described at length in the following sections. Section 10.2.4.1 “Format and Partition the Device” • Default Partitioning • Creating Multiple FAT Partitions • Preserving Existing Partitions Section 10.2.4.
tions will be formatted. Be forewarned that on removable media, using multiple partitions will typically make the device unusable with PC readers. The sample program FAT_Write_MBR.c is distributed with FAT version 2.13. It is also compatible with FAT versions 2.01, 2.05 and 2.10. If you have one of these earlier versions of the FAT and would like a copy of FAT_Write_MBR.c, please contact Technical Support at www.digi.com/support/.
10.2.4.2 File and Directory Operations The Dynamic C FAT implementation supports the basic set of file and directory operations. Remember that a partition must be mounted before it can be used with any of the file, directory or status operations. 10.2.4.2.1 Open and Close Operations The fat_Open() function opens a file or a directory. It can also be used to create a file or a directory.
rc = fat_Close(&my_file); Remember to check the return code from fat_Close() since an error return code may indicate the loss of data. Once you are completely finished, call fat_UnmountDevice() to make sure any data stored in the cache is written to the flash device. 10.2.4.2.2 Read and Write Operations Use fat_Read() to read a file. rc = fat_Read(&my_file, buf, sizeof(buf)); The first parameter, &my_file, is a pointer to the file handle already opened by fat_Open().
files on the device and unmount all mounted FAT partitions. Unmounting the device is the safest method for shutting down after using the device. 10.2.4.2.3 Going to a Specified Position in a File The position pointer is at the start of the file when it is first opened. Two API functions, fat_Tell() and fat_Seek(), are available to help you with the position pointer.
10.2.4.2.4 Creating Files and Subdirectories While the fat_Open() function is versatile enough to not only open a file but also create a file or a subdirectory, there are API functions specific to the tasks of creating files and subdirectories. The fat_CreateDir() function is used to create a subdirectory one level at a time. rc = fat_CreateDir(my_part, "DIR1"); The first parameter, my_part, points to a partition structure. This pointer must point to a mounted partition.
10.2.4.2.5 Reading Directories The fat_ReadDir() function reads the next directory entry from the specified directory. A directory entry can be a file, directory or a label. A directory is treated just like a file. fat_ReadDir(&dir, &dirent, mode); The first parameter specifies the directory; &dir is an open file handle. A directory is opened by a call to fat_OpenDir() or by passing FAT_DIR in a call to fat_Open(). The second parameter, &dirent, is a pointer to a directory entry structure to fill in.
But, if you want the next active file and do not care about the file’s other attributes, mode should be (FAT_INC_ACTIVE | FATATTR_READ_ONLY | FATATTR_HIDDEN | FATATTR_SYSTEM | FATATTR_ARCHIVE). This search would only exclude directory and label entries. Now suppose you want only the next active read-only file, leaving out hidden or system files. The next group of macros allows this search by filtering on whether the requested attribute is set.
2. If you want the next hidden directory: Start with the FAT_INC_DEF macro default flag. To narrow the search to directories only, we want entries with their directory attribute set; therefore, OR the macros FATATTR_DIRECTORY and FAT_FIL_DIR. Then OR the macros FATATTR_HIDDEN and FAT_FIL_HIDDEN to search only for directories with their hidden attribute set. Set mode to: FAT_INC_DEF | FATATTR_DIRECTORY | FAT_FIL_DIR | FATATTR_HIDDEN | FAT_FIL_HIDDEN 3.
10.2.4.3 Error Handling Most routines in the FAT library return an int value error code indicating the status of the requested operation. Table 12 contains a list of error codes specific to the FAT file system. Most of these codes, along with some other error codes, are defined in/Lib/../ERRNO.LIB. Table 12.
10.2.5 More FAT Information The FAT file system stores and organizes files on a storage device such as a hard drive or a memory device. 10.2.5.1 Clusters and Sectors Every file is stored on one or more clusters. A cluster is made up of a contiguous number of bytes called sectors and is the smallest unit of allocation for files. The Dynamic C FAT implementation supports a sector size of 512 bytes. Cluster sizes depend on the media.
Figure 3. High-Level View of an MBR Entry Master Boot Record (MBR) 0x000 Boot Region 0x1CE 0x1DE 0x1EE 0x1FE Partition 0 Partition Table 0x1BE Partition 1 Partition 2 Partition 3 Signature NOTE: Some devices are formatted without an MBR and, therefore, have no partition table. This configuration is not currently supported in the Dynamic C FAT file system. 10.2.5.
The FAT type (FAT12 or FAT16) is determined by the count of clusters on the partition. The “12” and “16” refer to the number of bits used to hold the cluster number. The FAT type is calculated using information found in the BPB. Information from a BPB on a mounted partition is stored in the partition structure (of type fat_part) populated by fat_AutoMount(). Partitions greater than or equal to 2 MB will be FAT16. Smaller partitions will be FAT12.
memset(dev->part, 0, sizeof(mbr_part)); dev->part[0].starthead = 0xFE; dev->part[0].endhead = 0xFE; dev->part[0].startsector = 1; dev->part[0].partsecsize = (MY_PARTITION_SIZE / 512 ) + 1; dev->part[0].parttype = (dev->part[0].partsecsize < SEC_2MB) ? 1 : 6; The memset() function is used to initialize the entry to zero. The values for starthead and endhead should be 0xFE to indicate that the media uses LBA (Logical Block Addressing) instead of head and cylinder addressing.
10.2.5.5 µC/OS-II and FAT Compatibility Versions of the FAT file system prior to version 2.10 are compatible with µC/OS-II only if FAT API calls are confined to one µC/OS-II task. To make the FAT API reentrant from multiple tasks, you must do the following: • Use FAT version 2.10 • #define FAT_USE_UCOS_MUTEX before #use'ing FAT.
10.2.5.8 Hot-Swapping an SD Card Hot-swapping is currently supported on the RCM3900 and the RCM3910. FAT version 2.14 or later is required. A sample program is provided in Samples/FileSystem to demonstrate this feature: FAT_HOT_SWAP_SD.C. The sample tests for a keyboard hit to determine if the user wants to hot-swap the SD card.
digi.
11. USING ASSEMBLY LANGUAGE This chapter gives the rules for mixing assembly language with Dynamic C code. A reference guide to the Rabbit Instruction Set is available from the Help menu of Dynamic C. 11.1 Mixing Assembly and C Dynamic C permits assembly language statements to be embedded in C functions and/or entire functions to be written in assembly language. C statements may also be embedded in assembly code. C-language variables may be accessed by the assembly code. 11.1.
11.1.2 Embedded C Syntax A C statement may be placed within assembly code by placing a “c” in column 1. Note that the registers used in the embedded C statement will be changed. #asm InitValues:: c start_time = 0; c counter = 256; ret #endasm 11.1.3 Setting Breakpoints in Assembly There are two ways to enable software breakpoint support in assembly code. One way is to explicitly mark the assembly block as debug (the default condition is nodebug).
11.2 Assembler and Preprocessor The assembler parses most C language constant expressions. A C language constant expression is one whose value is known at compile time. All operators except the following are supported: Table 11-1. Operators Not Supported By The Assembler Operator Symbol Operator Description ?: conditional . dot -> points to * dereference 11.2.1 Comments C-style comments are allowed in embedded assembly code.
If separate I&D space is enabled, db places bytes in the base segment of the data space when it is used with const. If the const keyword is absent, i.e., #asm myrootconstants:: db 0x40, 0x41, 0x42 #endasm the bytes are placed somewhere in the instruction space. If separate I&D space is disabled (the default condition), the bytes are placed in the base segment (aka, root segment) interspersed with code.
11.2.3 Multiline Macros The Dynamic C preprocessor has a special feature to allow multiline macros in assembly code. The preprocessor expands macros before the assembler parses any text. Putting a $\ at the end of a line inserts a new line in the text. This only works in assembly code. Labels and comments are not allowed in multiline macros. #define SAVEFLAG ld a,b $\ push af $\ pop bc $\ #asm ... ld b,0x32 SAVEFLAG ... #endasm 11.2.4 Labels A label is a name followed by one or two colons.
11.2.6 C Variables C variable names may be used in assembly language. What a variable name represents (the value associated with the name) depends on the variable. For a global or static local variable, the name represents the address of the variable in root memory. For an auto variable or formal argument, the variable name represents its own offset from the frame reference point.
11.3 Stand-Alone Assembly Code A stand-alone assembly function is one that is defined outside the context of a C language function. A stand-alone assembly function has no auto variables and no formal parameters. It can, however, have arguments passed to it by the calling function. When a program calls a function from C, it puts the first argument into a primary register.
11.3.2 Example of Stand-Alone Assembly Code The stand-alone assembly function foo() can be called from a Dynamic C function. int foo ( int ); main(){ int i,j; i=1; j=foo(i); } #asm foo:: ... ld hl,2 ret #endasm // A function prototype can be declared for stand-alone // assembly functions, which will cause the compiler // to perform the appropriate type-checking. // The return value expected by main() is put // in HL just before foo() returns The entire program can be written in assembly. #asm main:: ...
11.4.1.1 Stack Frame Diagram Figure 11.1 shows the general appearance of a stack frame. Figure 11.1 Assembly Code Stack Frame Stack Frame Last Auto Variable SP Optional First Auto Variable Optional IX Register Frame Reference Point Return Address First Parameter (pushed last) Optional Last Parameter (pushed first) Optional Structure Return Space Lower Addresses (stack grows down) Higher Addresses The return address is always necessary.
11.4.2 Embedded Assembly Example The purpose of the following sample program, asm1.c, is to show the different ways to access stackbased variables from assembly code.
11.4.3 The Disassembled Code Window A program may be debugged at the assembly level by opening the Disassembled Code window (aka, the Assembly window). Single stepping and breakpoints are supported in this window. When the “Disassembled Code” window is open, single stepping occurs instruction by instruction rather than statement by statement. The figure below shows the “Disassembled Code” window for the example code, asm1.c. Figure 11.
11.4.4 Local Variable Access Accessing static local variables is simple because the symbol evaluates to the address directly. The following code shows, for example, how to load static variable y into HL. ld hl,(y) ; load hl with contents of y 11.4.4.1 Using the IX Register as a Frame Pointer Using IX as a frame pointer is a convenient way to access stack variables in assembly. Using SP requires extra bookkeeping when values are pushed on or popped off the stack. Now, access to stack variables is easier.
11.4.4.3 Functions in Extended Memory If the xmem keyword is present, Dynamic C compiles the function to extended memory. Otherwise, Dynamic C determines where to compile the function. Functions compiled to extended memory have a 3-byte return address instead of a 2-byte return address. Because the compiler maintains the offsets automatically, there is no need to worry about the change of offsets.
The following code shows how to clear field f1 of a structure (as a returned value) of type struct s. typedef struct ss { int f0; char f1; } xyz; xyz my_struct; ... my_struct = func(); ... xyz func(){ #asm ... xor a ld hl,@SP+@RETVAL+ss+f1 add hl,sp ld (hl),a ... #endasm } // first field // second field ; clear register A. ; hl <- the offset from SP to f1 field of returned struct ; hl now points to f1. ; load a (now 0) to f1.
11.6 Assembly Calling C A program may call a C function from assembly code. To make this happen, set up part of the stack frame prior to the call and “unwind” the stack after the call. The procedure to set up the stack frame is described here. 1. Save all registers that the calling function wants to preserve. A called C function may change the value of any register. (Pushing registers values on the stack is a good way to save their values.) 2.
11.7 Interrupt Routines in Assembly Interrupt Service Routines (ISRs) may be written in Dynamic C (declared with the keyword interrupt). But since an assembly routine may be more efficient than the equivalent C function, assembly is more suitable for an ISR. Even if the execution time of an ISR is not critical, the latency of one ISR may affect the latency of other ISRs. Either stand-alone assembly code or embedded assembly code may be used for ISRs.
11.7.2 Modifying Interrupt Vectors Prior to Dynamic C 7.30, interrupt vector code could be modified directly. By reading the internal and external interrupt registers, IIR and EIR, the location of the vector could be calculated and then written to because it was located in RAM. This method will not work if separate I&D space is enabled because the vectors must be located in flash. To accommodate separate I&D space, the way interrupt vectors are set up and modified has changed slightly.
The following example from RS232.LIB illustrates the new I&D space compatible way of modifying interrupt vectors. The following code fragment to set up the interrupt service routine for the periodic interrupt from Dynamic C 7.
The following example from RS232.LIB illustrates the new I&D space compatible way of modifying interrupt vectors. The following function serAclose() from Dynamic C 7.25, is not compatible with separate I&D space: #asm xmem serAclose:: ld a,iir ld h,a ld l,0xc0 ld a,0xc9 ipset 1 ld (hl),a ld a,0x00 ld (SACRShadow), a ioi ld (SACR), a ipres lret ; hl=spaisr_start, de={iir,0xe0} ; ret in first byte ; disable interrupts for port #endasm This version of serAclose() in Dynamic C 7.
If separate I&D space is enabled, using the modifiable interrupt vector proxy in RAM adds about 80 clock cycles of overhead to the execution time of the ISR. To avoid that, the preferred way to set up interrupt vectors is to use the new keyword, interrupt_vector, to set up the vector location at compile time. When compiling with separate I&D space, modify applications that use SetVectIntern(), SetVectExtern2000() or SetVectExtern3000() to use interrupt_vector instead.
Table 11-5 lists the defined interrupt vector names that may be used with interrupt_vector, along with their ISRs. Table 11-5. Interrupt Vector and ISR Names Interrupt Vector Name ISR Name Default Condition periodic_intvec periodic_isr Fast and nonmodifiable rst10_intvec User defined name User defined rst18_intvec rst20_intvec These interrupt vectors and their ISRs should never be altered by the user because they are reserved for the debug kernel.
11.8 Common Problems If you have problems with your assembly code, consider the possibility of any of the following situations: • Unbalanced stack. Ensure the stack is “balanced” when a routine returns. In other words, the SP must be same on exit as it was on entry. From the caller’s point of view, the SP register must be identical before and after the call instruction. • Using the @SP approach after pushing temporary information on the stack.
12. KEYWORDS A keyword is a reserved word in C that represents a basic C construct. It cannot be used for any other purpose. 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 to loophead() is made in main() before calling the single-user cofunction. See Samples\Cofunc\Cofaband.c for an example of abandonment handling.
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 on VALUE. #asm ... align ... #endasm VALUE can have any (positive) integer expression or the special operands even and odd. The operand even aligns the instruction on an even address, and odd on an odd address. Integer expressions align on multiples of the value of the expression.
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 IMPORTANT: bbram does not provide data integrity; instead, use the keyword protected to ensure integrity of data across power failures.
break Jumps out of a loop, if, or case statement. while( expression ){ ... if( condition ) break; } switch( expression ){ ... case 3: ... break; ... } c Use in assembly block to insert one Dynamic C instruction. #asm InitValues:: c start_time = 0; c counter = 256; ld hl,0xa0; ret #endasm case Identifies the next case in a switch statement. switch( expression ){ case constant: ... case constant: ... case constant: ... ... } 196 digi.
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 cofunc Indicates the beginning of a cofunction. cofunc|scofunc type [name][[dim]]([type arg1, ..., type argN]) { [ statement | yield; | abort; | waitfor(expression);]... }{ ... } cofunc, scofunc The keywords cofunc or scofunc (a single-user cofunction) identify the statements enclosed in curly braces that follow as a cofunction.
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.). The const 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.
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 be always_on or init_on. If state 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.
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 ){ case const1: ... case const2: ... default: ... } do Indicates the beginning of a do loop. A do loops tests at the end and executes at least once. do ... while( expression ); The statement must have a semicolon at the end. else The false branch of an if statement.
enum Defines a list of named integer constants: enum foo { white, black, brown, spotted = -2, striped, }; // // // // // default is 0 for the first item will be 1 will be 2 will be -2 will be -3 An enum can be declared in local or global scope. The tag foo is optional; but it allows further declarations: enum foo rabbits; To see a colorful sample of the enum keyword, run /samples/enum.c. extern Indicates that a variable is defined in the BIOS, later in a library file, or in another library file.
firsttime The keyword 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. A firstime function can only be called from inside of a costatement, cofunction, or slice statement.
for Indicates the beginning of a for loop. A for loop has an initializing expression, a limiting expression, and a stepping expression. Each expression can be empty. for(;;) { ... } for( i = 0; i < n; i++ ) { ... } // an endless loop // 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 use goto to jump into a loop body or a switch case. The results are unpredictable.
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 more else if parts.
int Declares variables, function return values, or array elements to be 16-bit integers. If nothing else is specified, int implies a 16-bit signed integer. int i, j, *k; unsigned int x; long int z; unsigned long int w; int funct ( int arg ){ ... } // // // // 16-bit signed 16-bit unsigned 32-bit signed 32-bit unsigned interrupt Indicates that a function is an interrupt service routine (ISR).
interrupt_vector This keyword, intended for use with separate I&D space, sets up an interrupt vector at compile time. This is its syntax: interrupt_vector Interrupt vector names and ISR names are found in Table 11-5 on page 191. The following code fragment illustrates how interrupt_vector is used. // Set up an Interrupt Service Routine for Timer B #asm timerb_isr:: ; ISR code ... ret #endasm main() { // Variables ...
interrupt_vector (cont’d) As demonstrated in DC 9.
__lcall__ When used in a function definition, the __lcall__ function prefix forces long call and return (lcall and lret) instructions to be generated for that function, even if the function is in root. This allows root functions to be safely called from xmem. In addition to root functions, this prefix also works with function pointers. The __lcall__ prefix works safely with xmem functions, but has no effect on code generation. Its use with cofunctions is prohibited and will generate an error if attempted.
nodebug Indicates a function is not compiled in debug mode. This is the default for assembly blocks. nodebug int func(){ ... } #asm nodebug ... #endasm See also “debug” and directives “#debug #nodebug”. norst Indicates that a function does not use the RST instruction for breakpoints. norst void func(){ ... } The norst keyword in combination with the debug keyword will give you run-time checking without debug.
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.
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(){ ...
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. Using segchain 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 reinitialize vec[].
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; unsigned short int w; short funct ( short arg ){ ... } // 16-bit, signed // 16-bit, unsigned 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. sizeof() can be used inside of assembly blocks.
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 definition static. Local variables are auto by default. int func (){ ... int i; static float x; ... } // auto by default // explicitly static struct This keyword introduces a structure declaration, which defines a type. struct { ...
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. The default case, if it is present, executes if none of the constants of the case statements match expression.
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 a union is that of its largest member. union { int x; float y; } abc; // overlays a float and an int unsigned Declares a variable or array to be unsigned. If nothing else is specified in a declaration, unsigned means 16-bit unsigned integer. unsigned unsigned unsigned unsigned ...
void This keyword conforms to ANSI C. Thus, it can be used in three different ways. 1. Parameter List - used to identify an empty parameter list (a.k.a., argument list). An empty parameter list can also be identified by having nothing in it. The following two statements are functionally identical: int functionName(void); int functionName(); 2. Pointer to Void - used to declare a pointer that points to something that has no type. void *ptr_to_anything; 3.
waitfordone (wfd) The waitfordone keyword can be abbreviated as wfd. It is part of Dynamic C’s cooperative multitasking constructs. Used inside a costatement or a cofunction, it executes cofunctions and firsttime functions. When all the cofunctions and firsttime functions in the wfd statement are complete, or one of them aborts, execution proceeds to the statement following wfd.
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. Each char is allocated one byte, and each int is allocated two bytes. If an integer fits into one byte, it is still allocated two bytes. Each float and long cause four bytes to be allocated.
xmem Indicates that a function is to be placed in extended memory. This keyword is semantically meaningful in function prototypes. Good programing style dictates its use be consistent between the prototype and the function definition.
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; ... } ... } Dynamic C User’s Manual digi.
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). There are some compiler directives used to decide where to place code and data in memory. They are called origin directives and include #rcodorg, #rvarorg and #xcodorg.
#debug #nodebug Enables or disables debug code compilation. #debug is the default condition. A function's local debug or nodebug keyword overrides the global #debug or #nodebug directive. In other words, if a function does not have a local debug or nodebug keyword, the #debug or #nodebug directive would apply. #nodebug prevents RST 28h instructions from being inserted between C statements and assembly instructions. NOTE: These directives do nothing if they are inside of a function. This is by design.
#GLOBAL_INIT Syntax: #GLOBAL_INIT { variables } #GLOBAL_INIT sections are blocks of code that are run once before main() 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: // This function outputs and returns the number of times it has been called.
#if #elif #else #endif Syntax: #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.
#ifndef Syntax: #ifndef name This directive enables code compilation if name has not been defined with a #define directive. This directive must have a matching #endif. #interleave #nointerleave Controls whether Dynamic C will intersperse library functions with the program’s functions during compilation together, separately from the library functions. #nointerleave forces the user-written functions to be compiled first.
#memmap Syntax: #memmap options 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: All functions not declared as xmem go to root memory. • xmem: C functions not declared as root go to extended memory. Assembly blocks not marked as xmem 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.
#useix #nouseix Controls 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 stackvariable using function is called from within a cofunction, or if a stack-variable using function contains a call to a cofunction. #warns Syntax: #warns “...” Instructs the compiler to act as if a serious warning was issued.
#zimport Syntax: #zimport “filename” symbol This compiler directive extends the functionality of #ximport to include file compression by an external utility. filename is the input file (and must be relative to the Dynamic C installation directory or be a fully qualified path) and symbol represents the 20-bit physical address of the downloaded file. The external utility supplied with Dynamic C is zcompress.exe. It outputs the compressed file to the same directory as the input file, appending the extension .
13. OPERATORS An operator is a symbol such as +, –, or & that expresses some kind of operation on data. Most operators are binary—they have two operands. a + 10 // two operands with binary operator "add" Some operators are unary—they have a single operand, -amount // single operand with unary “minus” although, like the minus sign, some unary operators can also be used for binary operations. There are many kinds of operators with operator precedence.
Certain operators, namely *, &, (), [], -> and . (dot), can be used on the left side of an assignment to construct what is called an lvalue. For example, float x; *(char*)&x = 0x17; // low byte of x gets value When the data types for an operation are mixed, the resulting type is the more precise.
* Indirection, or multiplication. As a unary operator, it indicates indirection. When used in a declaration, * indicates that the following item is a pointer. When used as an indirection operator in an expression, * provides the value at the address specified by a pointer. int *p; const int j = 45; p = &j; k = *p; *p = 25; // p is a pointer to an integer // // // // // p now points to j. k gets the value to which p points, namely 45. The integer to which p points gets 25.
++ Pre- or post-increment is a unary operator designed primarily for convenience. If the ++ precedes an operand, the operand is incremented before use. If the ++ operator follows an operand, the operand is incremented after use.
13.2 Assignment Operators = Assignment. This binary operator causes the value of the right operand to be assigned to the left operand. Assignments can be “cascaded” as shown in this example. a = 10 * b + c; // a gets the result of the calculation a = b = 0; // b gets 0 and a gets 0 += Addition assignment. a += 5; // Add 5 to a. Same as a = a + 5 -= Subtraction assignment. a -= 5; // Subtract 5 from a. Same as a = a - 5 *= Multiplication assignment. a *= 5; // Multiply a by 5.
>>= Right shift assignment. a >>= 5; // Shift a right 5 bits. Same as a = a >> 5 &= Bitwise AND assignment. // AND a with b. Same as a = a & b a &= b; ^= Bitwise XOR assignment. a ^= b; // XOR a with b. Same as a = a ^ b |= Bitwise OR assignment. a |= b; // OR a with b. Same as a = a | b 13.3 Bitwise Operators << Shift left. This is a binary operator. The result is the value of the left operand shifted by the number of bits specified by the right operand.
& Address operator, or bitwise AND. As a unary operator, this provides the address of a variable: int x; z = &x; // z gets the address of x As a binary operator, this performs the bitwise AND of two integer (char, int, or long) values. int i = 0xFFF0; int j = 0x0FFF; z = i & j; // z gets 0x0FF0 ^ Bitwise exclusive OR. A binary operator, this performs the bitwise XOR of two integer (8-bit, 16-bit or 32-bit) values. int i = 0xFFF0; int j = 0x0FFF; z = i ^ j; // z gets 0xF00F | Bitwise inclusive OR.
13.4 Relational Operators < Less than. This binary (relational) operator yields a Boolean value. The result is 1 if the left operand is less than the right operand, and 0 otherwise. if( i < j ){ body } // executes if i < j OK = a < b; // true when a < b <= Less than or equal. This binary (relational) operator yields a boolean value. The result is 1 if the left operand is less than or equal to the right operand, and 0 otherwise.
13.5 Equality Operators == Equal. This binary (relational) operator yields a Boolean value. The result is 1 if the left operand equals the right operand, and 0 otherwise. if( i == j ){ body } // executes if i = j OK = a == b; // true when a = b Note that the == operator is not the same as the assignment operator (=). A common mistake is to write if( i = j ){ body } Here, i gets the value of j, and the if condition is true when i is non-zero, not when i equals j. != Not equal.
! Logical NOT. This is a unary operator. Observe that C does not provide a Boolean data type. In C, logical false is equivalent to 0. Logical true is equivalent to non-zero. The NOT operator result is 1 if the operand is 0. The result is 0 otherwise. test = get_input(...); if( !test ){ ... } 13.7 Postfix Expressions ( ) Grouping. Expressions enclosed in parentheses are performed first. Parentheses also enclose function arguments. In the expression a = (b + c) * 10; the term b + c is evaluated first.
-> Right arrow. Used with pointers to structures and unions, instead of the dot operator. typedef struct{ int x; int y; } coord; coord *p; // p is a pointer to structure ... m = p->x; // reference to structure element 13.8 Reference/Dereference Operators & Address operator, or bitwise AND. As a unary operator, this provides the address of a variable: int x; z = &x; // z gets the address of x As a binary operator, this performs the bitwise AND of two integer (char, int, or long) values.
Beware of using uninitialized pointers. Also, the indirection operator can be used in complex ways. int *list[10] int (*list)[10] float** y; z = **y; typedef char **stp; stp my_stuff; // // // // array of 10 ptrs to int ptr to array of 10 ints ptr to a ptr to a float z gets the value of y // my_stuff is typed char** As a binary operator, the * indicates multiplication. a = b * c; // a gets the product of b and c 13.
13.10 Other Operators (type) The cast operator converts one data type to another. A floating-point value is truncated when converted to integer. The bit patterns of character and integer data are not changed with the cast operator, although high-order bits will be lost if the receiving value is not large enough to hold the converted value. unsigned i; float x = 10.5; char c; i = (unsigned)x; // i gets 10; c = *(char*)&x; // c gets the low byte of x typedef ... typeA; typedef ...
, Comma operator. This operator, unique to the C language, is a convenience. It takes two operands: the left operand—typically an expression—is evaluated, producing some effect, and then discarded. The righthand expression is then evaluated and becomes the result of the operation. This example shows somewhat complex initialization and stepping in a for statement. for( i=0,j=strlen(s)-1; i
14. GRAPHICAL USER INTERFACE Dynamic C can be used to edit source files, compile and run programs, and choose options for these activities using pull-down menus or keyboard shortcuts. There are two modes: edit mode and run mode (run mode is also known as debug mode). Various debugging windows can be viewed in run mode. Programs can compile directly to a target controller for debugging in RAM or Flash. Programs can also be compiled to a .bin file, with or without a controller connected to the PC.
The Ctrl key works in conjunction with the arrow keys: Ctrl+Left Move cursor to previous word. Ctrl+Right Move cursor to next word. Ctrl+Up Move editor window up, text moves down one line. Cursor is not moved. Ctrl+Down Move editor window down, text moves up one line. Cursor is not moved. The Ctrl key also works in conjunction with “[” for delimiter matching. Place the cursor before the delimiter you are attempting to match and press “Ctrl+[”.
14.2.2 File Menu To select the File menu: click on its name in Dynamic C’s main menu or press . New Creates a blank, untitled program in a new window, called the text window or the editor window. If you right click anywhere in the text window a popup menu will appear. It is available as a convenience for accessing some frequently used commands. Open Presents a dialog box to specify the name of a file to open.
Print Setup Displays the Page Setup dialog box. Margins, page orientation, page numbers and header and footer properties are all chosen here. The “Printer Setup” button is in the bottom left of the dialog box. It brings up the Print Setup dialog box, which allows a printer to be selected. The “Network’ button allows printers to be added or removed from the list of printers.
14.2.3 Edit Menu Click the menu title or press to select the EDIT menu. Undo This option undoes recent changes in the active edit window. The command may be repeated several times to undo multiple changes. Undo operations have unlimited depth. Two types of undo are supported—applied to a single operation and applied to a group of the same operations (2 continuous deletes are considered a single operation.
Find Finds first occurrence of specified text. Text may be specified by selecting it prior to opening the Find dialog box if the option “Find text at cursor” is checked in the Editor dialog under Environment Options. Only one word may be selected; if more than one word is selected, the last word selected appears as the entry for the search text. More than one word of text may be specified by typing it in or selecting it from the available history of search text.
Find in Files (Grep)... This option searches for text in the currently open file(s) or in any directory (optionally including subdirectories) specified. Standard Unix-style regular expressions are used. A window with the search results is displayed with an entry for each match found. Double-clicking on an entry will open the corresponding file and place the cursor on the search string in that file. Multiple file types can be separated by semicolons.
Editor Window Popup Menu Right click anywhere in the editor window and a popup menu will appear. All of the menu options, with the exception of Open File at Cursor, are available from the main menu, e.g., New is an option in the File menu and was described earlier with the other options for that menu. Open File at Cursor Attempts to open the file whose name is under the cursor. The file will be opened in a new editor window, if the file name is listed in the “lib.
14.2.4 Compile Menu Click the menu title or press to select the Compile menu. Compile Compiles a program and loads it to the target or to a .bin file. When you press or select Compile from the Compile menu, the active file will be compiled according to the current compiler options. Compiler options are set in the Compiler tab of the Project Options dialog.
Compile to .bin File Compiles a program and writes the image to a .bin file. There are two choices available with this option, “Compile to Flash” and “Compile to Flash, Run in Ram.” The target configuration used in the compile is determined in the Compiler tab of the Project Options dialog. From there, under “Default Compile Mode” you can choose to use the attached target or a defined target configuration.
14.2.5 Run Menu Click the menu title or press to select the RUN menu. Run Starts program execution from the current breakpoint. Registers are restored, including interrupt status, before execution begins. If in Edit mode, the program is compiled and downloaded. Stop The “Stop” command stops the program at the current point of execution. Usually, the debugger cannot stop within nodebug code.
Toggle Hard Breakpoint Toggles a hard breakpoint at the current cursor location. A hard breakpoint differs from a soft breakpoint in that interrupts are disabled when the hard breakpoint is reached. Starting with Dynamic C 9, breakpoints can be toggled in edit mode as well as in debug mode. Breakpoint information is not only retained when going back and forth from edit mode to debug mode, it is stored when a file is closed and restored when the file is reopened.
14.2.6 Inspect Menu Click the menu title or press to open the Inspect menu. The Inspect menu provides commands to manipulate watch expressions, view disassembled code, and produce hexadecimal memory dumps. The Inspect menu commands and their functions are described here. Add Watch This command displays the “Add Watch Expression” dialog. Enter watch expressions with this dialog box.
Delete Watch Removes highlighted entry from the Watches window. Delete All Watches Removes all entries from the Watches window. Update Watch Window Forces expressions in the Watches window to be evaluated. If the target is running nodebug code, the Watches window will not be updated, and the PC will lose communication with the target. Inserting an RST 028h instruction into frequently executed nodebug code will allow the Watches window to be updated while running in nodebug code.
memory location 0x0022, which has a value of 0xFF. This information is given in the fly-over text and also in the titlebar. Either or both of these options may be disabled by right clicking in the Memory Dump window or in the Options | Environment Options, Debug Windows tab, under Specific Preferences for the Memory Dump window. Memory Dump windows may be scrolled. Scrolling causes the contents of other memory addresses to appear in the window.
Stop Execution Tracing This command causes the target to stop sending trace information to Dynamic C. You can also do this from within your program with the _TRACEOFF macro. The sample program Samples/Demo4.c describes and uses this trace macro. Start Execution Tracing This command causes the target to send execution tracing information to Dynamic C based on the trace options you choose in the Debugger tab of the Project Options dialog.
14.2.7 Options Menu Click the Options menu title or press to select the Options menu. Environment Options Dynamic C comes with a built-in, full-featured text editor. It may be customized to suit your style using the Environment Options dialog box. The dialog box has tabs for various aspects of the editor.
Use previous indention Uses the same characters for indentation that were used for the last indentation. If the last indentations was 2 tabs and 4 spaces, the next indentation will use the same combination of whitespace characters. Cursor through tabs With this option checked, the right and left arrow keys will move the cursor through the logical spaces of a tab character. If this is unchecked the cursor will move the entire length of the tab character.
Double click line Check this option to allow an entire line to be selected when you double click at any position in the line. When this option is unchecked, double clicking will select the closest word to the left of the cursor. Find text at cursor When either the Search or Replace dialogs are opened, if this option is checked the word at the cursor location in the active editor window will be placed into the “Text to Find” edit box.
tabs. E.g., if the list consists of “3,6,12” the first tab stop is 3 spaces, the second tab stop is 3 more spaces and all subsequent tab stops are 6 spaces. Keymapping The keyboard has five different default key mappings: Default, Classic, Brief, Epsilon and Visual Studio. Change the keymapping with this pulldown menu. Syntax extensions Dynamic C will automatically syntax highlight the text in all files with the extensions listed here.
Editor gutter Check the Visible box to create a gutter in the far left side of the text window. Use the Width scroll bar to set the width of the gutter in pixels. The button to the right updates the width parameter. Changing the width and clicking on OK at the bottom of the dialog does not update the gutter width; you must click on the button. Use the Color pulldown menu to set the color. The button to the right brings up more color choices.
Display Tab Click on the Display tab to display the following dialog. Editor Font This area of the dialog box is for choosing the font style and size. Check Use mono font for fixed spacing with each character; note that this option limits the available font styles. Special Symbols Check the box labeled “Use” to view end of line, end of file, space and/or tab symbols in the editor window.
Foreground Color (non-syntax) If syntax highlighting is not used, the color selected here will be the foreground color used in the editor file. Syntax Colors Tab Click on the Syntax Colors tab to display the following dialog. Element In this text box are the different elements that may be in a file (strings, comments, integers, etc.). For each one you may choose a foreground and a background color. You may also opt to use the default colors: black for foreground and white for background.
without saving the changes, the colors will go back to whatever they were before you opened the .rgb file. Code Templates Tab Click the Code Template tab to display the following dialog. As you can see, there are several predefined templates. The Edit and Delete buttons allow the likenamed operations on existing templates. The Add button gives the ability to create custom templates. To bring up the list of defined templates, Dynamic C must be in edit mode.
Debug Windows Tab Click on the Debug Windows tab to display the following dialog. Here is where you change the behavior and appearance of Dynamic C debug windows. Under General Preferences is where you decide which debug windows will be opened after a successful compile. You may choose one of the radio buttons in this category. Selecting “Open last used windows” makes Dynamic C 8 act like Dynamic C 7.x. Under Specific Preferences is where you customize each window.
Automatic open Check this to open the Stdio window the first time printf() is encountered. Automatic Vertical Scroll Check this to force vertical scroll when text is displayed outside the view of the window. If this option is unchecked, the text display doesn’t change when the bottom of the window is passed; you have to use the scroll bar to see text beyond the bottom of the window. Automatic Horizontal Scroll Check this to force horizontal scroll when text is displayed outside the view of the window.
Assembly Window The Assembly window displays the disassembled code from the program just compiled. All but the opcode information may be toggled off and on using the checkboxes shown below. For more information about this window see Section 11.4.3. Show Addresses Check this to show the logical address of the instruction in the far left column. Show OpCodes Check this to show the hexidecimal number corresponding to the opcode of the instruction.
Show File Name in Source Line Check this to prepend the file name to the Dynamic C statements corresponding to the assembly code. Register Window For this window you must choose one of the following conditions: “Show register history” or “Show registers as editable.” When the Register Contents window opens it will be in editable mode by default. Selecting “Show Register history” will override the default setting.
Show registers as editable In this mode, you can increment or decrement most of the registers, all but the SP, PC and XPC registers. This screen shows the Register Contents window in editable mode. It is divided into registers on the left and flags on the right. A click of the right mouse button on the register side will bring up the menu pictured here. You can switch to history view or change register values for all but the SP, PC and XPC registers.
Memory Dump Window For more information on using the Memory Dump window go to the section titled, Dump at Address . The following are the options relevant to the Memory Dump window. Apply changes to all Changes made in this dialog will be applied to all memory dump windows. Allow automatic updates The memory dump window will be updated every time program execution stops (breakpoint, single step, etc.).
Segmented Dump Range The memory dump window can display 3 different types of dumps. A dump of a logical address will result in a 64k scrollable region (0x0000 - 0xffff). A dump of a physical address will result in a dump of a 1M region (0x00000 - 0xfffff). A dump of an xpc:offset address will result in either a 4k, 64k or 1M dump range, depending on how this option is set. If a 4k or 64k range is selected, the dump window will dump a 4k or 64k chunk of memory using the given xpc.
Print/Alerts Tab Click on the Print/Alerts tab to display the following dialog. You may access both the Page Setup dialog and Print Preview from here. The Page Setup dialog works in conjunction with the Print/Alerts dialog. The Page Setup dialog is where you define the attributes of headers, footers, page numbering and margins for the printed page. The Print/Alerts dialog is where you enable and disable these settings. You may also change the font family and font size that will be used by the printer.
that Dynamic C is working with the most current version. The last checkbox, if checked, causes Dynamic C to query when an attempt is made to compile a library file to make sure that is what is desired. You may choose zero or more of these alerts. Project Options Settings used by Dynamic C to communicate with a target, and to compile and run programs are accessible by using the Project Options dialog box. The dialog box has tabs for various aspects of communicating with the target, the BIOS and the compiler.
Serial Options This is where you setup for serial communication. The following options are available when the Use Serial Connection radio button is selected. Debug Baud Rate This defaults to 115200 bps. It is the baud rate used for target communications after the program has been downloaded. Max Download Baud Rate When baud negotiation is enabled, Dynamic C will start out at the selected baud rate and work downwards until it reaches one both it and the target can handle.
TCP/IP Options To program and debug a controller across a TCP/IP connection, the Network Address field must have the IP address of either the RabbitLink board that is attached to the controller, or the IP address of a RabbitSys-enabled controller. To accept control commands from Dynamic C, the Control Port field must be set to the port used by the Ethernet-enabled controller. The Controller Name is for informational purposes only.
Run-Time Checking These options, if checked, can allow a fatal error at run time. They also increase the amount of code and cause slower execution, but they can be valuable debugging tools. • Array Indices: Check array bounds. This feature adds code for every array reference. • Pointers: Check for invalid pointer assignments. A pointer assignment is invalid if the code attempts to write to a location marked as not writable. Locations marked not writable include the entire root code segment.
Optimize For Allows for optimization of the program for size or speed. When the compiler knows more than one sequence of instructions that perform the same action, it selects either the smallest or the fastest sequence, depending on the programmer’s choice for optimization. The difference made by this option is less obvious in the user application (where most code is not marked nodebug).
Separate Instruction and Data Space When checked, this option enables separate I&D space, doubling the amount of root code and root data space available. Please note that if you are compiling to a 128K RAM, there is only about 12K available for user code when separate I&D space is enabled. Default Compile Mode One of the following options will be used when Compile | Compile is selected from the main menu of Dynamic C or when the keyboard shortcut is used.
User Defined BIOS File Use this option to change from the default BIOS to a user-specified file. Enter or select the file using the browse button/text box underneath this option. The check box labeled use must be selected or else the default file BIOS defined in the system registry will be used. Note that a single BIOS file can be made for compiling both to RAM and Flash by using the preprocessor macros _FLASH_ or _RAM_.
Debug Instructions and BIOS Inclusion Include RST 28 instructions If this is checked, the debug and nodebug keywords and compiler directives work as normal. Debug code consists mainly of RST 28h instructions inserted after every C statement. This option also controls the definition of a compiler-defined macro symbol, DEBUG_RST. If the menu item is checked, then DEBUG_RST is set to one, otherwise it is zero. If the option is not checked, the compiler marks all code as nodebug and debugging is not possible.
Debugger Tab Click on the Debugger tab to display the following dialog. This is where you enable/disable debugging tools. Disabling parts of the debug kernel saves room to fit tight code space requirements. Enable debug kernel This option was added in Dynamic C 9.30. Leaving it unchecked allows you to compile your application without the debug kernel. You must check this option to set any of the other debug options.
Enable breakpoints If this box is checked, the debug kernel will be able to toggle breakpoints on and off and will be able to stop at set breakpoints. This is where you set the maximum number of breakpoints the debug kernel will support. The debug kernel uses a small amount of root RAM for each breakpoint, so reducing the number of breakpoints will slightly reduce the amount of root RAM used.
Enable execution tracing If this is checked, the target will send trace information back to Dynamic C when you turn on tracing by choosing Inspect | Start Execution Tracing or when your program does so by executing a _TRACE or _TRACEON macro. Unchecking this box will disable the menu command and macros.
Defines Tab The Defines tab brings up a dialog box with a window for entering (or modifying) a list of defines that are global to any source file programs that are compiled and run. The macros that are defined here are seen by the BIOS during its compilation. Syntax: DEFINITION[DELIMETER DEFINITION[DELIMETER DEFINITION[...]]] DEFINITION: MACRONAME[[WS]=[WS]VALUE] DELIMETER: ';' or 'newline' MACRONAME: the same as for a macro name in a source file WS: [SPACE[SPACE[...]]] VALUE: CHR[CHR[...
Examples and File Equivalents: Example: DEF1;MAXN=10;DEF2 Equivalent: #define DEF1 #define MAXN 10 #define DEF2 Example: DEF1 MAXN = 10 DEF2 Equivalent: #define DEF1 #define MAXN 10 #define DEF2 Example: STATEMENT = A + B = C\;;DEF1=10 Equivalent: #define STATEMENT A + B = C; #define DEF1 10 Example: STATEMENT = A + B = C\; FORMATSTR = "name = %s\n" DEF1=10 Equivalent: #define STATEMENT A + B = C; #define FORMATSTR "name = %s\n" #define DEF1 10 Dynamic C User’s Manual digi.
Targetless Tab Click on the Targetless tab to reveal three additional tabs: RTI File, Specify Parameters and Board Selection. The setup for targetless compile may differ for some board series. Please check your user manual for differences in setup. RTI File Click on this tab to open a Rabbit Target Information (RTI) file for viewing. The file is readonly. You may not edit RTI files, but you may create one by selecting an entry in the Board Selection list and clicking on the button Save as RTI.
The term “Primary Flash” refers to the Flash device connected to /CS0, not the total amount of Flash available on the board. The result may be saved to a RTI file for later use, or the result may be saved to the list of board configurations. Board Selection The list of board configurations is viewable from the Board Selection tab.
Toolbars Selecting this menu item reveals a list of all menu button groups, i.e., the groups of icons that appear in toolbars beneath the title bar and the main menu items (File, Edit, …). This area is called the control bar. Uncheck View Menu Buttons to remove the control bar from the Dynamic C window. Any undocked toolbars (i.e., toolbars floating off the control bar) will still be visible.
14.2.8 Window Menu Click the menu title or press to display the Window menu. You can choose to minimize, restore or close all open windows or just the open debug window or just the open editor windows. The second group of items is a set of standard Windows commands that allow the application windows to be arranged in an orderly way. The Compiler Messages option is a toggle for displaying that window. This is only available if an error or warning occurred during compilation.
Stdio Select this option to activate or deactivate the Stdio window. The Stdio window displays output from calls to printf(). If the program calls printf(), Dynamic C will activate the Stdio window automatically if it is not already open, unless “Automatic open” is unchecked in the Debug Windows dialog in Options | Environment Options. Starting with Dynamic C 9, the various Find commands available on the Edit menu can be used directly in the Stdio window.
highlighted with the mouse. The total assumes one execution per instruction, so the user must take looping and branching into consideration when evaluating execution times. Use the mouse to select several lines in the Assembly window, and the total cycle time for the instructions that were selected will be displayed to the lower right of the selection. If the total includes an asterisk, that means an instruction with an indeterminate cycle time was selected, such as ldir or ret nz.
Stack (F12) Select this option to activate or deactivate the Stack window. The Stack window displays the top 32 bytes of the run-time stack. It also shows the line and column at which the stack “snapshot” was taken. It is possible to scroll back to see the progression of successive stack snapshots. Dynamic C 9 introduced differences highlighting: each time you single step in C or assembly, changed data can be highlighted in the Stack window. (This is also true for the Memory Dump and Register windows.
Debugger tab of the Project Options dialog, which allows saving the Trace window to a file upon program termination. Stack Trace (Ctrl+T) The Stack Trace window displays the call sequence and the values of function arguments and local variables of the currently running program. The screenshot shown here is the Stack Trace window when Samples/Demo3.c is running.
Table 14-1. Information Window Name of Field Description of Field XMEM code The begin, end and size of the XMEM code area, expressed in physical address format (20-bit). Watch code The begin, end and size of the watch code area, expressed in logical address format (16-bit). Stack The begin, end and size of the run-time stack, expressed in logical address format (16-bit). Root data The begin, end and size of the root data area, expressed in logical address format (16-bit).
14.2.9 Help Menu Click the menu title or press to select the HELP menu. The choices are given below: Online Documentation Opens a browser page and displays a file with links to other manuals. When installing Dynamic C from CD, this menu item points to the hard disk; after a Web upgrade of Dynamic C, this menu item optionally points to the Web. Keywords Opens a browser page and displays an HTML file of Dynamic C keywords, with links to their descriptions in this manual.
If the cursor is on a function when Help | Function Lookup is selected (or when is pressed) then the Library Function Lookup dialog is skipped and the Function Description window appears directly. If you click the Edit button, the Function Description window will close and the library that contains the function that was in the window will open in an editor window. The cursor will be placed at the function description of interest.
Instruction Set Reference Invokes an on-line help system and displays the alphabetical list of instructions for the Rabbit family of microprocessors. I/O Registers Invokes an on-line help system that provides the bit values for all of the Rabbit I/O registers. Keystrokes Invokes an on-line help system and displays the keystrokes page. Although a mouse or other pointing device may be convenient, Dynamic C also supports operation entirely from the keyboard.
digi.
15. COMMAND LINE INTERFACE The Dynamic C command line compiler (dccl_cmp.exe) performs the same compilation and program execution as its GUI counterpart (dcrabxx.exe), but is invoked as a console application from a DOS window. It is called with a single source file program pathname as the first parameter, followed by optional case-insensitive switches that alter the default conditions under which the program is run.
15.3 Saving Output to a File The output consists of all program printf’s as well as all error and warning messages. Output to a file can be accomplished with the -o option dccl_cmp myProgram.c -i myProgramInputs.txt -o myOutputs.txt where myOutputs.txt is overwritten if it exists or is created if it does not exist. If the -oa option is used, myOutputs.txt is appended if it exists or is created if it does not. 15.
-h+ Description: Print program header information. Factory Default: No header information will be printed. GUI Equivalent: None. Example: dccl_cmp samples\demo1.c -h -o myoutputs.txt Header text preceding output of program: ******************************************************** 4/5/01 2:47:16 PM dccl_cmp.exe, Version 7.10P - English samples\demo1.c Options: -h+ -o myoutputs.txt Program outputs: Note: Version information refers to dcwd.exe with the same compiler core.
Description: Generates inline code for WrPortI(), RdPortI(), BitWrPortI() and BitRdPortI() if all arguments are constants. Factory Default: No inline code is generated for these functions. GUI Equivalent: Check “Inline builtin I/O functions” in the Project Options | Compiler dialog box. -lfDescription: Undo Library Directory file specification. Factory Default: No Library Directory file is specified.
-n Description: Null compile for errors and warnings without running the program. The program will be downloaded to the target. Factory Default: Program is run. GUI Equivalent: Select Compile | Compile or use the keyboard shortcut . -r Description: Use compile mode: Compile to attached target. Factory Default: Compile mode: Compile to attached target. GUI Equivalent: Run program (F9) -rb+ Description: Include BIOS when compiling to a file.
-rdDescription: Do not include debug code when compiling to a file. This option is ignored if not compiling to a file. Factory Default: RST 28 instructions are included. GUI Equivalent: This is an advanced setting, viewable by clicking on the “Advanced” radio button at the bottom of the Project Options | Compiler dialog box. Uncheck “Include RST 28 instructions.” -ri+ Description: Enable runtime checking of array indices. Factory Default: Runtime checking of array indices is performed.
-rw+ Description: Restrict watch expressions—may save root code space. Factory Default: Allow any expressions in watch expressions. GUI Equivalent: This is an advanced setting, viewable by clicking on the “Advanced” radio button at the bottom of the Project Options | Compiler dialog box. Check “Restrict watch expressions . . .” -rwDescription: Don’t restrict watch expressions. Factory Default: Allow any expressions in watch expressions.
-tdDescription: Disable type demotion checking. Factory Default: Type demotion checking is performed. GUI Equivalent: Uncheck “Demotion” in the Project Options | Compiler dialog box. -tp+ Description: Enable type checking of pointers. Factory Default: Type checking of pointers is performed. GUI Equivalent: Check “Pointer” in the Project Options | Compiler dialog box. -tpDescription: Disable type checking of pointers. Factory Default: Type checking of pointers is performed.
-vp+ Description: Verify the processor by enabling a DSR check. This should be disabled if a check of the DSR line is incompatible on your system for any reason. Factory Default: Processor verification is enabled. GUI Equivalent: Check “Enable Processor verification” in the Project Options | Communications dialog box. -vpDescription: Assume a valid processor is connected. Factory Default: Processor verification is enabled.
15.4.2 Switches Requiring a Parameter The following switches require one or more parameters. -bf BIOSFilePathname Description: Compile using a BIOS file found in BIOSFilePathname. Factory Default: \Bios\RabbitBios.c GUI Equivalent: This is an advanced setting, viewable by clicking on the “Advanced” radio button at the bottom of the Project Options | Compiler dialog box. Check the box under “User Defined BIOS File” and then fill in the pathname for the new BIOS file. Example: dccl_cmp myProgram.
-d MacroDefinition Description: Define macros and optionally equate to values. The following rules apply and are shown here with examples and equivalent #define form: Separate macros with semicolons. dccl_cmp myProgram.c -d DEF1;DEF2 #define DEF1 #define DEF2 A defined macro may be equated to text by separating the defined macro from the text with an equal sign (=). dccl_cmp myProgram.
-d- MacroToUndefine Description: Undefines a macro that might have been defined in the project file. If a macro is defined in the project file read by the command line compiler and the same macro name is redefined on the command line, the command line definition will generate a warning. A macro previously defined must be undefined with the -d- switch before redefining it. Undefining a macro that has not been defined has no consequence and so is always safe although possibly unnecessary.
-lf LibrariesFilePathname Description: Compile using a file found in LibrariesFilePathname which lists all libraries to be made available to your programs. Factory Default: Lib.dir. GUI Equivalent: This is an advanced setting, viewable by clicking on the “Advanced” radio button at the bottom of the Project Options | Compiler dialog box. Check the box under “User Defined Lib Directory File” and then fill in the pathname for the new Lib.dir. Example dccl_cmp myProgram.c -lf MyPath\MyLibs.
-o OutputFilePathname Description: Write header information (if specified with -h) and all program errors, warnings and outputs to a text file. If the text file does not exist it will be created, otherwise it will be overwritten. Factory Default: None. GUI Equivalent: Go to Option | Environment Options and select the Debug Windows tab. Under “Specific Preferences” select “Stdio” and check “Log to File” under “Options.” Example dccl_cmp myProgram.c -o MyOutput.txt dccl_cmp myProgram.c -o MyOutput.
-pf projectFilePathname Description: Specify a project file to read before the command line switches are read. The environment settings are taken from the project file specified with -pf, or default.dcp if no other project file is specified. Any switches on the command line, regardless of their position relative to the -pf switch, will override the settings from the project file. Factory Default: The project file default.dcp. GUI Equivalent: Select File | Project | Open... Example dccl_cmp myProgram.
-rf RTIFilePathname Description: Compile to a .bin file using targetless compilation parameters found in RTIFilePathname. The resulting compiled file will have the same pathname as the source (.c) file being compiled, but with a .bin extension. Factory Default: None. GUI Equivalent: Example: dccl_cmp myProgram.c -rf MyTCparameters.rti dccl_cmp myProgram.c -rf “My Long Pathname\MyTCparameters.rti” ters.rti” -rti BoardID:CpuID:CrystalSpeed:RAMSize:FlashSize Description: Compile to a .
-s Port:Baud:Stopbits Description: Use serial transmission with parameters defined in a colon separated format of Port:Baud:Stopbits:BackgroundTx. Port: 1, 2, 3, 4, 5, 6, 7, 8 Baud: 110, 150, 300, 600, 1200, 2400, 4800, 9600, 12800, 14400, 19200, 28800, 38400, 57600, 115200, 128000, 230400, 256000 Stopbits: 1, 2 Include all serial parameters in the prescribed format even if only one is being changed. Factory Default: 1:115200:1:0 GUI Equivalent: Select the Communications tab of Project Options.
-t NetAddress:TcpName:TcpPort Description: Use TCP with parameters defined in a contiguous colon separated format of NetAddress:TcpName:TcpPort. Include all parameters even if only one is being changed. netAddress: n.n.n.n tcpName: Text name of TCP port tcpPort: decimal number of TCP port Factory Default: None. GUI Equivalent: Select the Communications tab of Project Options. Select the “Use TCP/IP Connection” radio button. Example: dccl_cmp myProgram.c -t 10.10.6.138:TCPName:4244 15.
Example 3 These examples will compile and run myProgram.c with the current settings in default.dcp but using different defines, displaying up to 50 warnings and capture all output to one file with a header for each run. dccl_cmp myProgram.c -d MAXCOUNT=99 -nw 50 -h -o myOutput.txt dccl_cmp myProgram.c -d MAXCOUNT=15 -nw 50 -h -oa myOutput.txt dccl_cmp myProgram.c -d MAXCOUNT=15 -d DEF1 -nw 50 -h -oa myOutput.txt The first run could have used the -oa option if myOutput.txt were known to not initially exist.
-d Description: Run Ethernet discovery to find RabbitLink or RabbitSys-enabled boards on a local area network (LAN). Don’t load the .bin file. This option is for information gathering and must appear by itself with no other options and no binary image file name. RFU GUI Equivalent: From the Setup | Communications dialog box, click on the “Use TCP/IP Connection” radio button, then on the “Discover” button. Example: clRFU -d -fi Flash.
-s port:baudrate Description: Select the comm port and baud rate for the serial connection. Default: COM1 and 115,200 bps RFU GUI Equivalent: From the Setup | Communications dialog box, choose values from the Baud Rate and Comm Port drop-down menus. Example: clRFU myProgram.bin -s 2:115200 -t ipAddress:tcpPort Description: Select the IP address and port.
-vpDescription: Do not verify the presence of the processor. Default: The processor is verified. RFU GUI Equivalent: From the “Communications Options” dialog box, visible by selecting Setup | Communications, uncheck the “Enable Processor Detection” option. Example: clRFU myProgram.bin -vp- -usb+ Description: Enable use of USB to serial converter. Default: The use of the USB to serial converter is disabled.
16. PROJECT FILES In Dynamic C, a project is an environment that consists of opened source files, a BIOS file, available libraries, and the conditions under which the source files will be compiled. Starting with Dynamic C 9.30, the File Open directory last used will be stored in the project filei. Projects allow different compilation environments to be separately maintained. 16.1 Project File Names A project maintains a compilation environment in a file with the extension .dcp. 16.1.1 Factory.
The active project file name, without path or extension, is always shown in the leftmost panel of the status bar at the bottom of the Dynamic C main window and is prepended to the Dynamic C version in the title bar except when the active project is the default project. Changes made to the compilation environment of Dynamic C are automatically updated to the active project, unless the active project is factory.dcp. 16.2 Updating a Project File Unless the active project is factory.
16.4 Command Line Usage When using the command line compiler, dccl_cmp.exe, a project file is always read. The default project, default.dcp, is used automatically unless the project file switch, -pf, specifies another project file to use. The project settings are read by the command line compiler first even if a -pf switch comes after the use of other switches, and then all other switches used in the command line are read, which may modify any of the settings specified by the project file.
digi.
17. HINTS AND TIPS This chapter offers hints on how to speed up an application and how to store persistent data at run time. 17.1 A User-Defined BIOS Before discussing a user-defined BIOS, we will review the history of the Rabbit BIOS. Dynamic C 9.30 introduced a reorganization of the BIOS. Prior to 9.30, RabbitBIOS.c contained all the BIOS code and a variety of configuration macros. Now, RabbitBIOS.c is a wrapper that permits a choice of which BIOS to compile.
The suggested method to use with Dynamic C 9.30 or later involves editing the file RABBITBIOS.C to include the user-defined BIOS file. To do so, find the “#if __RABBITSYS == 0” statement and modify the code as follows: #if MYBIOS == 1 #use “mybios.c” #elif __RABBITSYS == 0 #use “STDBIOS.C” #elif __RABBITSYS == 1 #use “sysBIOS.C” #else #use”rkBIOS.c” #endif To select the customized BIOS, define “MYBIOS = 1” in the Defines tab of the Options | Project Options dialog box. 17.
If programs are executing on the target controller with the debugging instructions present, but without Dynamic C attached, the call to the function that handles RST 28H instructions in the vector table will be replaced by a simple ret instruction for Rabbit 2000 based targets. For Rabbit 3000 based targets, the RST 28H instruction is treated as a NOP by the processor when in debug mode. The target controller will work, but its performance will not be as good as when the nodebug keyword is used.
• Battery-Backed RAM - Storing data here is as easy as assigning values to global variables or local static variables. The file system can also be configured to use RAM. The life of a battery on a Rabbit board is specified in the user’s manual for that board; some boards have batteries that last several years, most board have batteries that come close to or surpass the shelf-life of the battery.
17.4 Root Memory Reduction Tips Customers with programs that are near the limits of root code and/or root data space usage will be interested in these tips for saving root space. For more help, see Technical Note TN238 “Rabbit Memory Usage Tips.” This document is available at: digi.com, or by choosing Online Documentation from within the Help menu of Dynamic C. 17.4.
• Reduce usage of root constants and string literals Shortening literal strings and reusing them will save root space. The compiler automatically reuses identical string literals. These two statements : printf (“This is a literal string”); sprintf (buf, “This is a literal string”); will share the same literal string space whereas: sprintf (buf, “this is a literal string”); will use its own space since the string is different.
• Place assembly language code into xmem Pure assembly language code functions can go into xmem. #asm foo_root:: [some instructions] ret #endasm The same function in xmem: #asm xmem foo_xmem:: [some instructions] lret ; use lret instead of ret #endasm The correct calls are call foo_root and lcall foo_xmem. If the assembly function modifies the XPC register with LD XPC, A it should not be placed in xmem.
digi.
APPENDIX A. MACROS AND GLOBAL VARIABLES This appendix contains descriptions of macros and global variables available in Dynamic C. This is not an exhaustive list. A.1 Macros Defined by the Compiler The macros in the following table are defined internally. Default values are given where applicable, as well as directions for changing values. Table A-1. Macros Defined by the Compiler Macro Name Definition and Default _BIOSBAUD_ This is the debug baud rate.
Table A-1. Macros Defined by the Compiler Macro Name __DynamicC__ Definition and Default This macro identifies the Dynamic C compiler, e.g: #ifdef __DynamicC__ // conditional code goes here #endif may be used in a portable application to enclose conditional code that applies only to Rabbit targets. DEBUG_RST Go to the Compiler tab of Project Options and click on the “Advanced” button at the bottom of the dialog box. Check “Include RST 28 instructions” to set DEBUG_RST to 1.
Table A-1. Macros Defined by the Compiler Macro Name Definition and Default Boolean value. It defaults to 0. Set it by selecting “Compile defined _TARGETLESS_COMPILE_ target configuration to .bin file” under “Default Compile Mode,” in the Compiler tab of Project Options. __TIME__ Dynamic C User’s Manual The compiler substitutes this macro with the time that the file (BIOS or .c) was compiled. The character string literal is of the form hh:mm:ss. digi.
A.2 Macros Defined in the BIOS or Configuration Libraries This is not a comprehensive list of configuration macros, but rather, a short list of those found to be commonly used by Dynamic C programmers. Most default conditions can be overridden by defining the macro in the “Defines” tab of the “Project Options” dialog. All the configuration macros listed here were defined in RabbitBIOS.c prior to Dynamic C 9.30. Since then many of them have been moved to configuration libraries while RabbitBIOS.
A.3 Global Variables These variables may be read by any Dynamic C application program. dc_timestamp This internally-defined long is the number of seconds that have passed since 00:00:00 January 1, 1980, Greenwich Mean Time (GMT) adjusted by the current time zone and daylight savings of the PC on which the program was compiled. The recorded time indicates when the program finished compiling. The following program will use dc_timestamp to help calculate the date and time.
A.4 Exception Types These macros are defined in errors.
APPENDIX B. MAP FILE GENERATION All symbol information is put into a single file. The map file has three sections: a memory map section, a function section, and a globals section. The map file format is designed to be easy to read, but with parsing in mind for use in program down-loaders and in other possible future utilities (for example, an independent debugger). Also, the memory map, as defined by the #org statements, will be saved into the map file.
digi.
APPENDIX C. SECURITY SOFTWARE & UTILITY PROGRAMS This appendix documents the security software and utility programs available for Rabbit-based systems. The security software is called the Rabbit Embedded Security Pack. It is summarized in Section C.1. There are several Dynamic C utilities, each one described in Section C.2. C.1 Rabbit Embedded Security Pack The Rabbit Embedded Security Pack is composed of AES and SSL functionality. It is available for purchase on the Digi website: www.digi.
C.2 Dynamic C Utilities There are several utilities bundled with Dynamic C. C.2.1 Library File Encryption The Library File Encryption Utility, Encrypt.exe, allows distribution of sensitive runtime library files. The encrypted library files compile normally, but cannot be read with an editor.
C.2.1.2 File Extension Encrypted files will be saved with the same pathname but with the extension supplied. Dynamic C will use encrypted and non-encrypted files seamlessly, so the choice of extension is for one’s own file management. C.2.1.3 Optional Text Area The upper window is a text window of up to 4k bytes in length. Any text entered will appear in all files in the list appearing in the lower window. If two files are to be given unique headers, they should be encrypted separately.
C.2.2.2 File Compression/Decompression API The file compression API consists of 7 functions, 3 of which are of prime importance: OpenInputCompressedFile() - open a compressed file for reading or open an uncompressed #ximport file for compression. CloseInputCompressedFile() - close input file and deallocate memory buffers. ReadCompressedFile() - perform on-the-fly decompression.
The compression utility must reside in the same directory as the Dynamic C compiler executable. Dynamic C expects the program to behave as follows: • Take as input a file name relative to the Dynamic C installation directory or a fully qualified path. • Produce an output file of the same name as the input file with the extension .DCZ at the end. E.g., test.txt becomes test.txt.dcz. • Exit with zero on success, non-zero on failure.
The necessary files are included with Dynamic C. They are: the executable (Rfu.exe), the cold loader, the pilot BIOS, and a file used to determine information about the memory device being used. The default files used for the cold loader, etc., can be seen by selecting “File Locations...” from the Setup menu. Rfu.exe and its ancillary files are freely distributable. The RFU communicates with the target using either a serial or a TCP/IP connection. The serial connection requires a programming cable.
-t ipAddress:tcpPort Description: Select the IP address and port. Default: Serial Connection RFU GUI Equivalent: From the Setup | Communications dialog box, click on “Use TCP/IP Connection,” then type in the IP address and port for the controller that is receiving the .bin file or use the “Discover” radio button. Example: clRFU myProgram.bin -t 10.10.1.100:4244 -v Description: Causes the RFU version number and additional status information to be displayed. Default: Only error messages are displayed.
-fi Flash.ini PathName Description: Select a new file that Dynamic C will use to externally define flash. Default: flash.ini RFU GUI Equivalent: From the “Choose File Locations...” dialog box, visible by selecting the menu option Setup | File Locations, type in a pathname or click on the ellipses radio button to browse for a file. Example: clRFU myProgram.bin -fi myflash.ini -vp+ Description: Verify the presence of the processor by using the DSR line of the PC serial connection.
-usbDescription: Disable use of USB to serial converter. Default: The use of the USB to serial converter is disabled. RFU GUI Equivalent: From the “Communications Options” dialog box, visible by selecting Setup | Communications, uncheck the “Use USB to Servile Converter” option. Example: clRFU myProgram.bin -usb- -d Description: Run Ethernet discovery. Don’t load the .bin file. This option is for information gathering and must appear by itself with no other options and no binary image file name.
digi.
APPENDIX D. ADDITIONAL DOCUMENTATION There is a suite of documentation available for the Dynamic C user. Numerous application notes, technical notes and white papers are available to help the reader learn more about different topics likely to be of interest to embedded systems engineers. Dynamic C documentation is found in two places: 1. Online at the Digi website: www.digi.com. 2. On the software CD that comes with Rabbit-based hardware.
digi.
Index Symbols A _GLOBAL_INIT .................................................. 212 { } curly braces ....................................................... 32 @LENGTH ........................................................... 175 @PC ...................................................................... 175 @RETVAL ................................................... 175, 183 @SP .............................. 175, 179, 182, 183, 184, 192 *.* ..............................................................
BIOS ........................................................................14 _xexit .................................................................119 calling premain() ...............................................113 command line compiler .............................304, 312 compilation environments .................................325 compile option ...................................................338 configuration macros .........................................123 control blocks ..............
#ifdef ................................................................. 225 #ifndef ............................................................... 226 #interleave ......................................................... 226 #makechain ................................................. 44, 226 #memmap .......................................................... 227 options .................................................... 227 #nodebug ...........................................
differences .....................................................12, 44 exit .....................................................................248 support files .........................................................52 Dynamic C modules ..............................................345 dynamic storage allocation ......................................37 E Edit menu ..............................................................249 edit mode .......................................................
anymem ............................................................. 194 debug ................................................................. 199 firsttime ............................................................. 202 interrupt ............................................................. 205 nodebug ............................................................. 209 norst .................................................................. 209 nouseix ....................................................
Stop .........................................................255 Assembly window ..................................293 Toggle Breakpoint ..................................255 Find Next ................................................250 Compile ..................................................253 Trace into ................................................255 Step over .................................................255 Run ..............................................
main function .................................... 33, 46, 208, 331 map file ................................................................. 343 max number of characters read ............................. 147 MBR ..................................................................... 164 memory address space ..................................................... 125 configuration macros ........................................ 132 DATAORG ............................................... 333, 335 dump ........
in assembly ........................................................173 logical operators ................................................239 logical AND (&&) ..................................239 logical NOT (!) .......................................240 logical OR (| |) .........................................239 operator precedence ...........................................244 postfix expressions ............................................240 ( ) parentheses .........................................
static variables ................................................... 127 variable address ................................................. 176 RST 28H ....................................................... 255, 330 run menu .................................................................. 255 mode .......................................................... 251, 255 no polling .......................................................... 255 run-time errors ....................................................
TICK_TIMER ...............................................114, 341 tiling windows .......................................................293 timing loop ............................................................114 toggle breakpoint ..................................................255, 256 toolbar ...................................................................292 trace into ................................................................255 trace macros ...............................................