C166: C166 Introduction

C166 Introduction

The C programming language is a general-purpose programming language that provides code efficiency, elements of structured programming, and a rich set of operators. C is not a big language and is not designed for any one particular area of application. Its generality, combined with its absence of restrictions, makes C a convenient and effective programming solution for a wide variety of software tasks. Many applications can be solved more easily and efficiently with C than with other more specialized languages.

The C166 Optimizing C Compiler is a complete implementation of the American National Standards Institute (ANSI) standard for the C language. The C166 Compiler is not a universal C compiler adapted for the XC16x/C16x/ST10 target. It is a ground-up implementation, dedicated to generating extremely fast and compact code for the C16x microprocessor. The C166 Compiler provides you with the flexibility of programming in C and the code efficiency and speed of assembly language.

The C language on its own is not capable of performing operations (such as input and output) that would normally require intervention from the operating system. Instead, these capabilities are provided as part of the standard library. Because these functions are separate from the language itself, C is especially suited for producing code that is portable across a wide number of platforms.

Since the C166 Compiler is a cross compiler, some aspects of the C programming language and standard libraries are altered or enhanced to address the peculiarities of an embedded target processor. Refer to Language Extensions for more detailed information.

Copyright (c) Keil Software, Inc. and and Keil Elektronik GmbH. All rights reserved.


C166: Books About the C Language

Books About the C Language

There are a number of books that provide an introduction to the C programming language. There are even more books that detail specific tasks using C. The following list is by no means a complete list of books on the subject. The list is provided only as a reference for those who wish more information.

  • The C Programming Language, Second Edition
    Kernighan & Ritchie
    Prentice-Hall, Inc.
    ISBN 0-13-110370-9
  • C: A Reference Manual, Second Edition
    Harbison & Steel
    Prentice-Hall Software Series
    ISBN 0-13-109810-1

More books about the XC16x/C16x/ST10 can be found on the Keil web site.


C166: Instruction Sets

Instruction Sets

The C166 Compiler generates programs using several different instruction sets. The instruction set is chosen by a compiler directive.

  • By default, the C166 Compiler generates programs usiing the original SAB80C166 instruction set. The list of devices supporting this instruction set is short (only the original 80C166 device).
  • The most common instruction set used in the C167 instruction set. It is used when the MOD167 directive is specified. This instruction set is used by the C167, C161, C163, C164, C165, and most ST10 derivatives.
  • The newest instruction set is the C167V2 or XC16x instruction set. It is used when the MODV2 directive is specified. This instruction set is used by the Infineon XC161, XC164, and XC167 and by the ST Microelectronics Super-10 devices.

Since it supports all these instruction sets, the Keil C166 Compiler is said to support the XC16x/C16x/ST10 architectures. You will find reference to these different instruction sets throughout this manual.


C166: Compiling Programs

Compiling Programs

This section explains how to compile C source files and discusses the control directives. These directives allow you to:

  • Direct the C166 Compiler to generate a listing file.
  • Define manifest constants on the command line.
  • Control the amount of information included in the object file.
  • Specify the optimization level and memory model.


C166: Environment Settings

Environment Settings

If you run the C166 Compiler within the µVision IDE, you need no additional settings on your computer. If you want to run the C166 Compiler and utilities from the command prompt, you must manually create the following environment variables.

Variable | Path | Description
PATH | \KEIL\C166\BIN | Path to the C166 executable program.
TMP |  | Path to use for temporary files generated by the compiler. If the specified path does not exist, the compiler generates an error and aborts compilation.
C166INC | \KEIL\C166\INC | Path to the folder for C166 include files.
C166LIB | \KEIL\C166\LIB | Path to the folder for C166 library files.

For Windows NT, Windows 2000, Windows XP, and Windows 2003, environment variables are entered under Control Panel — System — Advanced — Environment Variables.

For Windows 95, Windows 98, and Windows ME, the settings are placed in AUTOEXEC.BAT using the following commands:

PATH=C:\KEIL\C166\BIN;%PATH%
SET TMP=D:\TMP
SET C166INC=C:\KEIL\C166\INC
SET C166LIB=C:\KEIL\C166\LIB


C166: Command Prompt

Command Prompt

To invoke the C166 Compiler, enter C166 at the command prompt. You must include the name of the C source file to be compiled and any required control directives on the command line. The format for the command line is:

C166 sourcefile « directives... »
C166 @commandfile

Where

sourcefile | Is the name of the source program you want to compile.
directives | Are directives that control the operation of the compiler. Refer to Directives for a detailed list of the available directives.
commandfile | Is the name of a command input file that may contain the sourcefile and directives. A commandfile is commonly used when the compiler command line is complex or exceeds the limits of the Windows command prompt.

The following command line example invokes the C166 Compiler, specifies the source file SAMPLE.C, and uses the DEBUG, CODE, and PREPRINT directives.

C166 SAMPLE.C DEBUG CODE PREPRINT

The C166 Compiler displays the following information upon successful compilation.

C166 COMPILATION COMPLETE.  0 WARNING(S),  0 ERROR(S)


C166: ERRORLEVEL

ERRORLEVEL

After compilation, the number of errors and warnings detected is output to the screen. The C166 Compiler then sets the ERRORLEVEL to indicate the status of the compilation. Values are listed in the following table:

ERRORLEVEL | Description
0 | No Errors or Warnings
1 | Warnings Only
2 | Errors and Possibly Warnings
3 | Fatal Errors

You can access the ERRORLEVEL in batch files. Refer to the Windows command reference or to batch commands in the Windows on-line help for more information on ERRORLEVEL or batch files.


C166: Output Files

Output Files

The C166 Compiler generates a number of output files during compilation. By default, each output file shares the same filename as the source file. However, each has a different file extension. The following table lists the files and gives a brief description of each.

File Extension | Description
.LST | Files with this extension are listing files that contain the formatted source text along with any errors detected by the compiler. Listing files may optionally contain the symbols used and the assembly code generated. Refer to the PRINT directive for more information.
.OBJ | Files with this extension are object modules that contain relocatable object code. Object modules may be linked to an absolute object module by the L166 Linker/Locator.
.I | Files with this extension contain the source text as expanded by the preprocessor. All macros are expanded and all comments are deleted in this listing. Refer to the PREPRINT directive for more information.
.SRC | Files with this extension are assembly source files generated from your C source code. These files can be assembled with the A166 Assembler. Refer to the SRC directive for more information.


C166: Listing (LST) File

Listing (LST) File

The compiler listing file contains an abundance of information about the compilation process. It is composed of a number of sections, each of which is described below in the order in which they appear in the file.

Page Header

Each listing page includes a header with the compiler version number, source file name, date, time, and page number.

C166 COMPILER V5.00, MEASURE       01/11/2004 16:16:23 PAGE 1

Command Line

The entire command line that was used to invoke the compiler is included in the listing file. This often helps diagnose problems with the command line.

C166 COMPILER V5.00, COMPILATION OF MODULE MEASURE
OBJECT MODULE PLACED IN .\Object\Measure.obj
COMPILER INVOKED BY: C:\Keil\C166\BIN\C166.EXE Measure.c REGFILE
                     -(.\Object\measure.ORC) BROWSE MOD167 DEBUG
                     -CODE LISTINCLUDE SYMBOLS PRINT(.\Listing\M
                     -easure.lst) PREPRINT(.\Listing\Measure.i)
                     -OBJECT(.\Object\Measure.obj)

Source Code

The source code listing outputs the line number as well as the source code on that line.

You may use the COND directive to include all conditional code (code in #if blocks) in the source code listing. The NOCOND directive may be used to exclude uncompiled conditional code blocks from the listing file.

You may use the LISTINCLUDE directive to include the contents of #include files in the source code listing. By default, include file contents are not output in the listing file.

   46         const char ERROR [] = "\n*** ERROR: %s\n";
   47
   48         #define PERIOD     -2500
   49         #define WRONGINDEX 0xffff
   50
   51
   52         /* The following function is called from */
   53         /* the interrupt service routine. */
   54         /* Save current measurements in save_record */
   55
   56         static void save_measurements (void) {
   57  1        save_record[sindex++] = current;
   58  1        if (sindex == SCNT) sindex = 0;
   59  1        if (sindex == savefirst)  {
   60  2          if (++savefirst == SCNT)  savefirst = 0;
   61  2        }
   62  1      }
   63
   64
   65
   66         /* Timer 0 interrupt service function */
   67         /* executes each 1 msec @ 40 MHz Crystal Clock */
   68
   69         static void timer0(void) interrupt 0x20 using INTREGS {
   70  1      /* Int Vector at 0080H, other Reg Bank */
   71  1
   72  1        unsigned char i;
   73  1
   74  1        if (measurement_interval)  {
   75  2          save_measurements ();
   76  2          measurement_interval = 0;
   77  2        }

Assembly Listing

The assembly listing contains the assembly code generated by the compiler for the C source code. The CODE directive may be used to include the assembly listing output.

             ; FUNCTION save_measurements (BEGIN  RMASK = @0x40D0)
                                           ; SOURCE LINE # 56
                                           ; SOURCE LINE # 57
0000 F2F40A20 R    MOV       R4,sindex
0004 248F0A20 R    SUB       sindex,ONES
0008 5C44          SHL       R4,#04H
000A E6F60A00 R    MOV       R6,#save_record
000E 0064          ADD       R6,R4
0010 E6F40C20 R    MOV       R4,#current
0014 E6F71000      MOV       R7,#010H
0018         ?C0078:
0018 E864          MOV       [R6],[R4+]
001A 0862          ADD       R6,#02H
001C 2872          SUB       R7,#02H
001E 3DFC          JMPR      cc_NZ,?C0078
                                           ; SOURCE LINE # 58
0020 F2F40A20 R    MOV       R4,sindex
0024 46F40002      CMP       R4,#0200H
0028 3D02          JMPR      cc_NZ,?C0001
002A F68E0A20 R    MOV       sindex,ZEROS
002E         ?C0001:
                                           ; SOURCE LINE # 59
002E F2F40400 R    MOV       R4,savefirst
0032 42F40A20 R    CMP       R4,sindex
0036 3D09          JMPR      cc_NZ,?C0002

In the assembly listing, function headers include a comment with a compiler-generated register mask (RMASK = @0x40D0). Function masks are used when global register optimization is enabled by the REGFILE directive. The register mask is a 16-bit number that indicates which registers are used by a function. Each bit in the mask refers to one register. The encoding for the register mask is as follows:

Bit Position
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
-- | DPP3 | MDx | R12 | R11 | R10 | R9 | R8 | R7 | R6 | R5 | R4 | R3 | R2 | R1 | DPP0

Two special values of the register mask specify all registers or no registers:

  • 0x0000 specifies that the function uses all registers.
  • 0x8000 specifies that the function uses no registers.

For example, a register mask value of 0x40D0 indicates that the function uses DPP3, R7, R6, and R4.

Symbol Listing

The symbol listing contains symbolic information about program symbols in the compiled source file. Included are symbol name, classification (SFR, structure, typedef, static, public, auto, extern), memory space, data type, offset, and size in bytes. The SYMBOLS directive may be used to include symbol listing output.

NAME                            CLASS    SPACE  TYPE   OFFSET   SIZE
--------------------------------------------------------------------
wchar_t. . . . . . . . . . . .  typedef         char   -----    1
interval . . . . . . . . . . .  --tag--         struct -----    4
  min. . . . . . . . . . . . .  member          uchar     0H    1
  sec. . . . . . . . . . . . .  member          uchar     1H    1
  msec . . . . . . . . . . . .  member          uint      2H    2
PSW. . . . . . . . . . . . . .  sfr             uint   FF10H    2
S0RIR. . . . . . . . . . . . .  absbit          bit    FF6EH.7  1
T8REL. . . . . . . . . . . . .  sfr             uint   F056H    2
T7REL. . . . . . . . . . . . .  sfr             uint   F054H    2
WDT. . . . . . . . . . . . . .  sfr             uint   FEAEH    2
IEN. . . . . . . . . . . . . .  absbit          bit    FF10H.11 1
sscanf . . . . . . . . . . . .  extern   NCODE  funct  -----
toupper. . . . . . . . . . . .  extern   NCODE  funct  -----
printf . . . . . . . . . . . .  extern   NCODE  funct  -----
set_interval . . . . . . . . .  extern   NCODE  funct  -----
measure_display. . . . . . . .  extern   NCODE  funct  -----
set_time . . . . . . . . . . .  extern   NCODE  funct  -----
getline. . . . . . . . . . . .  extern   NCODE  funct  -----
_getkey. . . . . . . . . . . .  extern   NCODE  funct  -----
clear_records. . . . . . . . .  static   NCODE  funct  -----
  idx. . . . . . . . . . . . .  --reg--         uint   -----    2
timer0 . . . . . . . . . . . .  static   NCODE  funct  -----
  i. . . . . . . . . . . . . .  --reg--         uchar  -----    1
save_measurements. . . . . . .  static   NCODE  funct  -----
main . . . . . . . . . . . . .  public   NCODE  funct  -----
  cmdbuf . . . . . . . . . . .  static   NDATA0 array  201CH    15
  i. . . . . . . . . . . . . .  --reg--         uchar  -----    1
  idx. . . . . . . . . . . . .  --reg--         uint   -----    2
read_index . . . . . . . . . .  static   NCODE  funct  -----
  buffer . . . . . . . . . . .  --reg--         ptr    -----    2
  index. . . . . . . . . . . .  auto            int       0H    2
  args . . . . . . . . . . . .  --reg--         int    -----    2
ERROR. . . . . . . . . . . . .  public   NCONST array     0H    16
menu . . . . . . . . . . . . .  static   NCONST array    7AH    847
interval . . . . . . . . . . .  public   NDATA0 struct    0H    4
savefirst. . . . . . . . . . .  static   NDATA0 uint      4H    2
setinterval. . . . . . . . . .  public   NDATA0 struct    6H    4
save_record. . . . . . . . . .  static   NDATA0 array     AH    8192
sindex . . . . . . . . . . . .  static   NDATA0 uint   200AH    2
current. . . . . . . . . . . .  public   NDATA0 struct 200CH    16
cmdbuf . . . . . . . . . . . .  static   NDATA0 array  201CH    15
measurement_interval . . . . .  static   BIT0   bit       0H    1
mdisplay . . . . . . . . . . .  static   BIT0   bit       1H    1
startflag. . . . . . . . . . .  static   BIT0   bit       2H    1

Module Information

The module information provides the size of initialized and uninitialized memory areas defined by the source file.

MODULE INFORMATION:   INITIALIZED  UNINITIALIZED
  CODE SIZE        =         910     --------
  NEAR-CONST SIZE  =        1062     --------
  FAR-CONST SIZE   =    --------     --------
  HUGE-CONST SIZE  =    --------     --------
  XHUGE-CONST SIZE =    --------     --------
  NEAR-DATA SIZE   =        8235     --------
  FAR-DATA SIZE    =    --------     --------
  XHUGE-DATA SIZE  =    --------     --------
  IDATA-DATA SIZE  =    --------     --------
  SDATA-DATA SIZE  =    --------     --------
  BDATA-DATA SIZE  =    --------     --------
  HUGE-DATA SIZE   =    --------     --------
  BIT SIZE         =           3     --------
  INIT'L SIZE      =    --------     --------
END OF MODULE INFORMATION.

Warnings and Errors

Problems encountered while compiling may cause errors and/or warnings that are output to the screen and to the listing file. Refer to the Error Messages chapter for details about error and warning messages.


C166: Preprocessor (I) File

Preprocessor (I) File

The preprocessor output file is created when the PREPRINT directive is specified. This file includes the preprocessor output for the specified source file.

The most obvious use for a preprocessor output file is to verify the operation of macros and conditional preprocessor directives.

For example, for the following C source file:

#define defIt(x)  char x[] = #x

void main (void)
{
defIt(asdf);
}

the C compiler generates the following preprocessor output file:

#line 1 "main.c" /0

 void main (void)
 {
  char asdf[] = "asdf";
 }

Note

  • The preprocessor output file is a valid C source file which may be compiled by the C Compiler.


C166: Object (OBJ) File

Object (OBJ) File

The C166 Compiler produces object (.OBJ) files in the Infineon object format in response to various C language statements and other directives. The OBJECT directive specifies the name for the object file while the NOOBJECT directive inhibits object file output.

The object file is not simply a binary representation of the assembly generated for your C source code. It is a specially formatted file with data records for symbolic information, object code, debugging information, library references, and so on. Following are just a few of the details that are stored in the object file.

  • Reserved memory for global variables.
  • Public symbol (variable and function) names.
  • External symbol (variable and function) references.
  • Library files with which to link.
  • Debugging information to help synchronize source lines with object code.

Most of the object code stored in the object file is not absolute. It may be located by the linker at any appropriate address. References to external variables and functions are set to address 0 by the compiler. The linker fixes-up all references. For these reasons, the object code generated by the compiler is not executable as-is. It must be linked before it can be executed.

The level of detail stored in the object file makes it possible for simulators (like the Keil µVision Simulator), debuggers (like the Keil µVision Target Debugger), and emulators to load your program and provide complete symbolic, source-level debugging capabilities.

  • The object file provides references to line numbers within the original source code. It does not include the original source code. Source-level debugging requires that the debugger have access to the original source code.


C166: Source (SRC) File

Source (SRC) File

The compiler can generate an assembler source file (.SRC) from a valid C source file. Refer to the SRC directive for information on how this directive is used.

There are several reasons to create an assembly source file:

  • You have used the ASM and ENDASM directives to add inline assembly to a C function.
  • You need to hand optimize the assembler output from the compiler.
  • You are writing a routine in assembly code and want to prototype the function and arguments in C.

No matter what your reason for creating a source file, the steps required are always the same:

  1. Create a C source file.
  2. Add any required inline assembly instructions.
  3. Compile using the SRC directive.
  4. Rename the .SRC file so that it is not overwritten by subsequent compilations of the original C source (if required).
  5. Make changes to the created assembler source file.
  6. Assemble using the assembler.

Note

  • When the SRC directive is used, the compiler outputs an assembler source (.SRC) file. No object (.OBJ) file is output.
  • C symbolic and source-level debugging is not available once a C source file is converted to an assembler source file.


C166: Directives

Directives

The C166 Compiler provides a number of directives you may use to control source file compilation. Directives are composed of one or more letters or digits and, unless otherwise specified, may be specified after the filename on the command line or within the source file using #pragma. For example:

C166 testfile.c SYMBOLS CODE DEBUG

or

#pragma SYMBOLS CODE DEBUG

The source file to compile is testfile.c and SYMBOLS, CODE, and DEBUG are the directives.

Control directives may be divided into three groups:

  • Source controls define macros on the command line and determine the name of the file to be compiled.
  • Object controls affect the form and content of the generated object module (*.OBJ). These directives allow you to specify the optimizing level or include debugging information in the object file.
  • Listing controls govern various aspects of the listing file (*.LST), in particular its format and specific content.

Note

  • The syntax is the same for the command line and #pragma. Multiple options, however, may be specified on the #pragma line.
  • Some directives may be specified only once at the beginning of a source file. If one of these directives is specified more than once, the compiler generates a fatal error and aborts compilation.

The following table is an alphabetical list of the control directives available in the C166 Compiler.

Directive | Group | Description
ASM2 | Source | Marks the beginning of an inline assembly block.
ASMEXPAND | Source | Enables preprocessor expansion of symbols used in ASM/ENDASM blocks.
BROWSE1 | Object | Enables source browser information.
BYTEALIGN | Object | Enables pointers to byte-aligned objects.
CODE1 | Listing | Includes generated assembly in the listing file.
COMMONRET | Object | Generates a single exit point for functions.
COMPACT1 | Object | Selects the COMPACT memory model.
COND | Listing | Includes (in the listing file) conditional source lines skipped by the preprocessor.
DEBUG1 | Object | Includes debugging information in the object file.
DEFINE3 | Source | Defines preprocessor names on the command line.
DISABLE2 | Object | Disables interrupts for the duration of a single function.
DYNAMICUSRSTK1 | Object | Specifies that the program modifies the user stack pointer.
EJECT2 | Listing | Inserts a form feed character into the listing file.
ENDASM2 | Source | Marks the end of an inline assembly block.
EXTINS | Object | Terminates EXTS and EXTP instructions at the end of each source line.
FIX166 | Object | Resolves problem A17 of 80C166 CA step and GOLD devices.
FIX167 | Object | Resolves problem CPU.3 of C167 and C165 devices.
FIXBFLD | Object | Resolves problem CPU.21 of C16x devices.
FIXPEC | Object | Resolves problems with JMPs to JMPs and the PEC.
FLOAT64 | Object | Enables 64-bit floating-point math support.
HCOMPACT1 | Object | Selects the HCOMPACT memory model.
HLARGE1 | Object | Selects the HLARGE memory model.
HOLD | Object | Specifies the default memory space for small objects.
INCDIR1 | Source | Sets additional include file paths.
INIT2 | Object | Signals variables that should be initialized at startup.
LARGE1 | Object | Selects the LARGE memory model.
LISTINCLUDE | Listing | Adds contents of include files into the listing file.
MAC | Object | Enables extensions for the XC16x and Suprt10 MAC unit.
MEDIUM1 | Object | Selects the MEDIUM memory model.
MOD167 | Object | Enables use of the enhanced C167 instruction set.
MODV2 | Object | Enables use of the enhanced XC167 instruction set.
NOALIAS1 | Object | Ignores write operations through pointers when optimizing.
NOAMAKE1 | Object | Excludes build information from the object file.
NOASMEXPAND | Object | Disables preprocessor expansion of symbols used in ASM/ENDASM blocks.
NOCOND | Listing | Excludes (from the listing file) conditional source lines skipped by the preprocessor.
NODPPSAVE1 | Object | Disables saving DPP registers in interrupts.
NOEXTEND1 | Source | Disables Cx51 extensions to ANSI C.
NOFIXDPP1 | Object | Generates code independent of DPP register contents.
NOFRAME | Object | Disables entry and exit code that saves registers in interrupts.
NOINIT2 | Object | Signals variables that should not be initialized at startup.
NOOBJECT1 | Object | Disables object file generation.
NOPRINT1 | Listing | Disables listing file generation.
NOSAVEMAC | Object | Disables saving of MAC co-processor registers during interrupt functions.
OBJECT1 | Object | Specifies the name for the object file.
OPTIMIZE | Object | Specifies the level of optimization performed by the compiler.
ORDER1 | Object | Allocates storage for variables in the order in which they are declared.
PACK | Object | Specifies the boundary for structure packing.
PAGELENGTH1 | Listing | Specifies the number of lines on a page in the listing file.
PAGEWIDTH1 | Listing | Specifies the number of characters on a line in the listing file.
PECDEF1 | Object | Reserves memory for PEC source and destination registers.
PREPRINT1 | Listing | Produces a preprocessor listing file with expanded macros.
PREPRINTONLY1 | Listing | Produces a preprocessor listing file with expanded macros and halts.
PRINT1 | Listing | Specifies the name for the listing file.
REENTRANT | Object | Generates reentrant functions (automatics are stored on the user stack).
REGFILE1 | Object | Uses the register definition file for global register optimization.
RENAMECLASS | Object | Changes the name of a pre-defined memory class.
REORDER | Object | Reorders instructions to minimize pipeline effects.
RESTORE2 | Object | Restores settings for the OPTIMIZE directive.
SAVE2 | Object | Saves settings for the OPTIMIZE directive.
SAVEMAC | Object | Saves MAC co-processor registers during interrupt functions.
SAVESYS | Object | Saves temporary results on the system stack.
SAVEUSR | Object | Saves temporary results on the user stack.
SMALL1 | Object | Selects the SMALL memory model.
SRC1 | Object | Creates an assembler source file instead of an object file.
STATIC | Object | Use static memory locations for automatic variables.
SYMBOLS1 | Listing | Includes a symbol list in the listing file.
TABS1 | Listing | Specifies the tab character expansion width for the listing file.
TINY1 | Object | Selects the TINY memory model.
UNSIGNED_CHAR1 | Object | Defaults all char types to unsigned.
USERSTACKDPP31 | Object | Specifies that DPP3 is used for accesses to the user stack.
WARNING2 | Listing | Changes the level of a warning.
WARNINGLEVEL1 | Listing | Selects the level of warning detection.
XLARGE1 | Object | Selects the XLARGE memory model.

Note

  1. These directives apply to the entire source file and may be specified only once on the command line or at the beginning of the source file using the #pragma statement. They may not be used more than once in a source file.
  2. These directives may not be specified on the command line. They may only be specified in the source file.
  3. Directives and arguments, with the exception of arguments specified with the DEFINE directive, are not case sensitive.


C166: Reference

Reference

The following pages describe the C166 Compiler directives. Directives are listed in alphabetical order and each is divided into several sections:

Abbreviation | Gives any abbreviations that may be substituted for the directive name.
Arguments | Describes and lists optional and required directive arguments.
Default | Shows the directive's default setting.
µVision | Lists how to specify the directive in the µVision IDE.
Description | Provides a detailed description of the directive and how to use it.
See Also | Lists related directives.
Example | Shows an example of how to use and sometimes the effects of the directive.


C166: ASM Compiler Directive

ASM Compiler Directive

Abbreviation | None.
Arguments | None.
Default | None.
µVision | This directive may not be specified on the command line.
Description

The ASM directive signals the beginning of a block of assembler source text to merge into the .SRC file generated using the SRC directive.

The ENDASM directive signals the end of the source text block.

This source text can be thought of as in-line assembly. However, it is output to the source file generated only when using the SRC directive. The source text is not assembled and output to the object file.

In µVision you may set a file specific option for C source files that contain ASM/ENDASM sections as follows:

  1. Right click on the file in the Project Window — Files tab
  2. Choose Options for... to open Options — Properties page
  3. Enable Generate Assembler SRC file
  4. Enable Assemble SRC file.

µVision generates an assembler source file (.SRC) and translates this file with the Assembler which generates an object file (.OBJ). The linker links this object file with other object files from the project and creates the target application program.

Note

  • The ASM and ENDASM directives may occur only in the source file as part of a #pragma.
See Also | ENDASM, SRC
Example
extern void test ();

void main (void)  {
  test ();

#pragma asm
  JMP   $  ; endless loop
#pragma endasm
}


C166: ASMEXPAND Compiler Directive

ASMEXPAND Compiler Directive

Abbreviation | AE
Arguments | None.
Default | ASMEXPAND
µVision | Options — C166 — Misc Controls.
Description

The ASMEXPAND directive instructs the compiler preprocessor to expand all symbols used in ASM/ENDASM blocks. This is the default compiler setting.
Example
#pragma noasmexpand

#define  abc  1
#define  xx0  2
#define  xx1  3

#pragma asm
  abc equ 2     ; above 'abc' not expanded
  xx0 equ 10    ; above 'xx0' not expanded
#ifdef QQQ
  xx1 equ 20
#endif

#pragma endasm


C166: BROWSE Compiler Directive

BROWSE Compiler Directive

Abbreviation | BR
Arguments | None.
Default | No browse information is created.
µVision | Options — Output — Browse Information.
Description

The BROWSE directive causes the compiler to include source browser information in the generated object module. Browser information includes identifiers (including preprocessor symbols), their memory space, type, definition, and reference lists.

Source browser information may be displayed in µVision using the Source Browser item from the View menu.
Example
C166 SAMPLE.C BROWSE

#pragma browse


C166: BYTEALIGN Compiler Directive

BYTEALIGN Compiler Directive

Abbreviation | None.
Arguments | None.
Default | Structure pointers point to word-aligned structures.
µVision | Options — C166 — Misc Controls.
Description

The BYTEALIGN directive generates code that supports pointers to structure members that may start on byte boundaries. This directive is required when you use the PACK(1) directive.
See Also | PACK
Example
#pragma pack(1)     /* byte alignment */
#pragma BYTEALIGN

struct s1  {
  int  i1;       // i1 has offset 0
  char c1;       // c1 has offset 2
  struct s2  {
    int  i2;     // i2 has offset 3
    char c2;     // c2 has offset 5
    int  i3;     // i3 has offset 6
  }s2;
  char z1;       // z1 has offset 8
} s1;

struct s2 *s2p;

void main (void)  {
  s2p = &s1.s2;   // pointer to byte-aligned struct
  s2p->i2 = 0;    // access to byte-aligned int
}


C166: CODE Compiler Directive

CODE Compiler Directive

Abbreviation | CD
Arguments | None.
Default | No assembly code listing is generated.
µVision | Options — Listing — C Compiler Listing — Assembly Code.
Description

The CODE directive appends an assembly mnemonics list to the listing file. The assembler code is represented for each function contained in the source program. By default, no assembly code listing is included in the listing file.

Refer to the Listing File for an assembly listing example.
Example
C166 SAMPLE.C CD

#pragma code


C166: COMMONRET Compiler Directive

COMMONRET Compiler Directive

Abbreviation | CR
Arguments | None.
Default | None.
µVision | Options — C166 — Misc Controls.
Description

The COMMONRET directive causes the compiler to generate function code so that each function has exactly one exit point. The effect is that the compiler no longer inserts RET instructions in the middle of a function. This may be useful with third party debugging tools for performance or code coverage analysis.
Example
C166 mycode.c COMMONRET

#pragma COMMONRET


C166: COMPACT Compiler Directive

COMPACT Compiler Directive

Abbreviation | CP
Arguments | None.
Default | SMALL
µVision | Options — Target — Memory Model.
Description

The COMPACT directive selects the compact memory model. The memory model affects the code generated by the compiler. In this memory model variables are accessed using far addresses and functions are accessed using near addresses.
See Also | HCOMPACT, HLARGE, HOLD, LARGE, MEDIUM, SMALL, TINY, XLARGE
Example
C166 SAMPLE.C COMPACT

#pragma compact


C166: COND Compiler Directive

COND Compiler Directive

Abbreviation | CO
Arguments | None.
Default | COND
µVision | Options — Listing — C Compiler Listing — Conditional.
Description

The COND directive includes lines omitted from compilation in the listing file. Line numbers and nesting levels are not output for lines excluded from the compilation.

The effect of this directive takes place one line after the preprocessor detects it.
See Also | NOCOND
Example

The following example shows the listing file for a source file compiled with the COND directive:

.
.
.
stmt level  source
   1        extern unsigned char  a, b;
   2               unsigned char     c;
   3
   4        main()
   5        {
   6   1    #if defined (VAX)
              c = 13;
            #elif defined (_ _TIME_ _)
   9   1      b = 14;
  10   1      a = 15;
  11   1    #endif
  12   1    }
.
.
.


C166: DEBUG Compiler Directive

DEBUG Compiler Directive

Abbreviation | DB
Arguments | None.
Default | No Debug information is generated.
µVision | Options — Output — Debug Information.
Description

The DEBUG directive instructs the compiler to include debugging information in the object file. By default, debugging information is excluded from the generated object file.

Debug information is necessary for the symbolic testing of programs. It contains global and local variable definitions and their addresses, function names and addresses, and line number information for source code. Debug information contained in each object module remains valid through the Link/Locate process and may be used by the µVision debugger or by an emulator.
Example
C166 SAMPLE.C DEBUG

#pragma db


C166: DEFINE Compiler Directive

DEFINE Compiler Directive

Abbreviation | DF
Arguments | One or more names (in accordance with the naming conventions of the C language) separated by commas. An optional value may be assigned to each name.
Default | None.
µVision | Options — C166 — Define.
Description

The DEFINE directive defines preprocessor symbols on the compiler command line. This is equivalent to using the #define directive in your program source code. You may use the #if, #ifdef, and #ifndef preprocessor directives to query names defined with the DEFINE directive.

Defined names are copied exactly as they are entered and are case-sensitive. Each name may be assigned a value.

Note

  • The DEFINE directive may be specified only on the command line. Use the C preprocessor #define directive to define symbols inside a C source file.
  • The DEFINE directive may not be used to define preprocessor macros.
Example
C166 SAMPLE.C DEFINE (check, NoExtRam)

C166 MYPROG.C DF (X1="1+5",iofunc="getkey ()")


C166: DISABLE Compiler Directive

DISABLE Compiler Directive

Abbreviation | None.
Arguments | None.
Default | None.
µVision | This directive may not be specified on the command line.
Description

The DISABLE directive instructs the compiler to generate code that disables all interrupts for the duration of a function. This directive must be specified with #pragma immediately before the function declaration. The DISABLE directive applies to one function only and must be re-specified for each new function.

Note

  • The DISABLE directive must be specified using #pragma only and may not be specified on the command line.
  • The DISABLE directive may be specified more than once in a source file but must be specified for each function that is to execute with interrupts disabled.
  • A function with disabled interrupts may not have a return type of bit.
Example
stmt level    source
   1          #pragma DISABLE
   2
   3          int function (int a, int b)  {
   4   1        return (a * b);
   5   1      }

ASSEMBLY LISTING OF GENERATED OBJECT CODE

        ; SOURCE LINE # 3
0000 1A88F0F0      BFLDH   PSW,#0F0H,#0F0H

0004 CC00          NOP
0006 CC00          NOP
;---- Variable 'b' assigned to Register 'R9' ----
;---- Variable 'a' assigned to Register 'R8' ----
        ; SOURCE LINE # 4
0008 0B89          MUL     R8,R9
000A F2F40EFE      MOV     R4,MDL
        ; SOURCE LINE # 5
000E 1A8800F0      BFLDH   PSW,#0F0H,#00H
0012 CB00          RET


C166: DYNAMICUSRSTK Compiler Directive

DYNAMICUSRSTK Compiler Directive

Abbreviation | DU
Arguments | None.
Default | The user stack resides in the NDATA memory class.
µVision | Options — C166 — Misc Controls.
Description

The DYNAMICUSRSTK directive informs the C166 Compiler that your program modifies the user stack area. This directive is useful for developers who create real-time operating systems that change the user stack area.

This directive makes it possible to have a 16K user stack for each task. Without this directive, the entire user stack must reside in the NDATA memory class which is limited to a maximum of 64K.
Example
#pragma dynamicusrstk


C166: EJECT Compiler Directive

EJECT Compiler Directive

Abbreviation | EJ
Arguments | None.
Default | None.
µVision | This directive may not be specified on the command line.
Description

The EJECT directive inserts a form feed character into the listing file.

Note

  • The EJECT directive may be specified only in the source file as part of a #pragma. It may not be specified on the command line.
Example
#pragma eject


C166: ENDASM Compiler Directive

ENDASM Compiler Directive

Abbreviation | None.
Arguments | None.
Default | None.
µVision | This directive may not be specified on the command line.
Description

The ENDASM directive signals the end of a block of assembler source text to merge into the .SRC file generated using the SRC directive.

Note

  • The ASM and ENDASM directives may occur only in the source file as part of a #pragma.
See Also | ASM, SRC
Example
extern void test ();

void main (void)  {
  test ();

#pragma asm
  JMP   $  ; endless loop
#pragma endasm
}


C166: EXTINS Compiler Directive

EXTINS Compiler Directive

Abbreviation | None.
Arguments | None.
Default | None.
µVision | Options — C166 — Misc Controls.
Description

The EXTINS directive causes the C166 Compiler to terminate EXTS and EXTP instruction sequences at the end of each source line. By default, these instruction sequences may extend one or more source lines.

Using the EXTINS directive makes debugging easier because single-steps execute a line at a time (rather than the extent of the whole EXT sequence).
Example
#pragma EXTINS


C166: FIX166 Compiler Directive

FIX166 Compiler Directive

Abbreviation | None.
Arguments | None.
Default | None.
µVision | Options — C166 — Misc Controls.
Description

The FIX166 directive is required to resolve problem A17 of the 80C166 CA step (typically the bond-out version of the 80C166) or the GOLD chip based on this chip version.

When the FIX166 directive is used, the following instructions are inserted before each RETI instruction:

BFLDH PSW, #0F0h, #0F0h
NOP
NOP
See Also | FIX167, FIXBFLD, FIXPEC
Example
#pragma FIX166


C166: FIX167 Compiler Directive

FIX167 Compiler Directive

Abbreviation | None.
Arguments | None.
Default | None.
µVision | Options — C166 — Misc Controls.
Description

The FIX167 directive resolves the problem CPU.3 of the C167 derivative. This problem is no longer present in currently shipping C167/C165 chip versions. Check the latest chip errata sheet to see if this directive is required.

When the FIX167 directive is specified the C166 Compiler will not generate a MOV Rn,[Rm+#d16] instruction at the end of an EXTS/EXTP sequence.
See Also | FIX166, FIXBFLD, FIXPEC
Example
#pragma FIX167


C166: FIXBFLD Compiler Directive

FIXBFLD Compiler Directive

Abbreviation | FB
Arguments | None.
Default | None.
µVision | Options — C166 — Misc Controls.
Description

The FIXBFLD directive ensures that the compiler encloses BFLDL and BFLDH instructions within ATOMIC sequences. This is required to avoid problems documented by Infineon in CPU.21 problem description. To use this directive in µVision, you must enter it under Options — C166 — Misc.

The FIXBFLD directive causes the compiler to insert ATOMIC #1 instructions before each BFLDL and BFLDH instruction. If the BFLD instruction is used to access ESFR registers, the EXTR sequence is not combined with other EXTR sequences. An exception to this occurs when accessing the SYSCON1, SYSCON2, and SYSCON3 SFR's since this is required by the hardware for UNLOCK sequences.

The compiler does not modify the use of the _bfld_ intrinsic function within _atomic_/_endatomic_ blocks. You must check such code blocks carefully and insert NOP's if required (using the _nop_ intrinsic function) before the _bfld_() intrinsic call.

Note

  • If you use RTX166 Tiny you must enable the FIXBFLD option in RTX166T.A66 and rebuild the RTX166 Tiny library. This corrects the CPU.21 problems in the kernel.
See Also | FIX166, FIX167, FIXPEC
Example
#pragma FB


C166: FIXPEC Compiler Directive

FIXPEC Compiler Directive

Abbreviation | None.
Arguments | None.
Default | None.
µVision | Options — C166 — Misc Controls.
Description

The FIXPEC directive causes the C166 Compiler to avoid potential problems with JMP to JMP instructions.

When using optimizer level 7 the compiler may generate JMPs to functions instead of CALLs. If the function begins with a JMP instruction, you may experience a problem with the PEC (on some chip steps) that has to do with JMP to JMP instruction sequences. The FIXPEC directive avoid this problem.
See Also | FIX166, FIX167, FIXBFLD
Example
#pragma FIXPEC


C166: FLOAT64 Compiler Directive

FLOAT64 Compiler Directive

Abbreviation | F64
Arguments | None.
Default | 32-bit floating-point math is used.
µVision | Options — C166 — Double-precision Floating-point.
Description

The FLOAT64 directive enables 64-bit (double-precision) floating-point math for double variable types in your C programs. Variables of type float continue to use 32-bit floating-point math.

By default, all floating-point math is performed using 32-bits (even when the double type is specified.) The FLOAT64 directive must be specified to use 64-bit floating-point math.
Example
C166 SAMPLE.C FLOT64

#pragma float64


C166: HCOMPACT Compiler Directive

HCOMPACT Compiler Directive

Abbreviation | HCP
Arguments | None.
Default | SMALL
µVision | Options — Target — Memory Model.
Description

The HCOMPACT directive selects the hcompact memory model. The memory model affects the code generated by the compiler. In this memory model variables are accessed using huge addresses and functions are accessed using near addresses.

Note

  • This memory model is not supported by the orignal 80C166 microntroller and is only available with the enhanced C16x/ST10 instruction set. Using this memory model automatically sets the MOD167 directive.
See Also | COMPACT, HLARGE, HOLD, LARGE, MEDIUM, MOD167, SMALL, TINY, XLARGE
Example
C166 SAMPLE.C HCOMPACT

#pragma hcompact


C166: HLARGE Compiler Directive

HLARGE Compiler Directive

Abbreviation | HLA
Arguments | None.
Default | SMALL
µVision | Options — Target — Memory Model.
Description

The HLARGE directive selects the hlarge memory model. The memory model affects the code generated by the compiler. In this memory model variables are accessed using huge addresses and functions are accessed using far addresses.

Note

  • This memory model is not supported by the orignal 80C166 microntroller and is only available with the enhanced C16x/ST10 instruction set. Using this memory model automatically sets the MOD167 directive.
See Also | COMPACT, HCOMPACT, HOLD, LARGE, MEDIUM, MOD167, SMALL, TINY, XLARGE
Example
C166 SAMPLE.C HLA

#pragma hlarge


C166: HOLD Compiler Directive

HOLD Compiler Directive

Abbreviation | HL
Arguments A memory type (near, idata, sdata, or bdata)
and a size between 0 and 16384.
Default | HOLD (near 6)
µVision | Options — Target — Data.
Description

The HOLD directive allows you to locate smaller data objects in the near, idata, sdata, or bdata memory areas instead of the default memory space associated with the memory model. These memory areas are accessed more efficiently than the far or huge memory areas.

By default, objects are located in the memory space specified by the selected memory model. Objects that are 6 bytes or smaller in size are located in the NEAR memory space. Objects that require more than 6 bytes of memory are located in the far or huge memory areas (in the LARGE, HLARGE, XLARGE COMPACT, or HCOMPACT memory models).
See Also | COMPACT, HCOMPACT, HLARGE, LARGE, MEDIUM, SMALL, XLARGE
Example
C166 SAMPLE.C HOLD (idata 2, near 6)

#pragma HL (sdata 10)


C166: INCDIR Compiler Directive

INCDIR Compiler Directive

Abbreviation | None.
Arguments | Path specifications for include files enclosed in parentheses.
Default | None.
µVision | Options — C166 — Include Paths.
Description

The INCDIR directive specifies the location of the compiler include files. The compiler accepts a maximum of 512 path declarations. If more than one path declaration is specified the path names must be separated by semicolons.

Include files enclosed within double quote characters ('"') are searched for in the following folders in order:

  • The current folder.
  • The source file folder.
  • Paths specified by the INCDIR directive.
  • Paths specified by the C166INC environment variable.

Include files enclosed within angle bracket characters ('<>') are searched for in the following folders in order:

  • Paths specified by the INCDIR directive.
  • Paths specified by the C166INC environment variable.
Example
C166 SAMPLE.C INCDIR(C:\MYINC;C:\CHIP_DIR)


C166: INIT Compiler Directive

INIT Compiler Directive

Abbreviation | IN
Arguments | None.
Default | INIT
µVision | This directive may not be specified on the command line.
Description

The INIT directive specifies that declared variables are initialized with zero (0) at the startup (reset) of the program. This is the default for the C Programming Language.

Embedded systems with non-volatile memory may require that variables are not cleared to zero at startup. The INIT directive may be used with the NOINIT directive to switch back and forth between variables which should be initialized and those which should not.
See Also | NOINIT
Example
#pragma NOINIT
char states[100];     /* Uninitialized Variable */

#pragma INIT
char array[100];      /* Initialized Variable */


C166: LARGE Compiler Directive

LARGE Compiler Directive

Abbreviation | LA
Arguments | None.
Default | SMALL
µVision | Options — Target — Memory Model.
Description

The LARGE directive selects the large memory model. The memory model affects the code generated by the compiler. In this memory model variables are accessed using far addresses and functions are accessed using far addresses.
See Also | COMPACT, HCOMPACT, HLARGE, HOLD, MEDIUM, SMALL, TINY, XLARGE
Example
#C166 SAMPLE.C LARGE


C166: LISTINCLUDE Compiler Directive

LISTINCLUDE Compiler Directive

Abbreviation | LC
Arguments | None.
Default | NOLISTINCLUDE
µVision | Options — Listing — C Compiler Listing — #include Files.
Description

The LISTINCLUDE directive displays the contents of include files in the listing file. By default, include files are not listed in the listing file.
Example
C166 SAMPLE.C LISTINCLUDE

#pragma listinclude


C166: MAC Compiler Directive

MAC Compiler Directive

Abbreviation | None.
Arguments | None.
Default | MAC extensions are disabled.
µVision | Options — C166 — Misc Controls.
Description

The MAC directive enables compiler extensions for the MAC unit available on the XC16x and Super10 devices. You may use the MAC in your programs to obtain increased performance of multiplication, multiply and accumulate, and memory move operations.
See Also | MOD167, MODV2
Example
C166 MACCODE.C MAC

#pragma MAC


C166: MEDIUM Compiler Directive

MEDIUM Compiler Directive

Abbreviation | ME
Arguments | None.
Default | SMALL
µVision | Options — Target — Memory Model.
Description

The MEDIUM directive selects the medium memory model. The memory model affects the code generated by the compiler. In this memory model variables are accessed using near addresses and functions are accessed using far addresses.
See Also | COMPACT, HCOMPACT, HLARGE, HOLD, LARGE, SMALL, TINY, XLARGE
Example
#pragma ME


C166: MOD167 Compiler Directive

MOD167 Compiler Directive

Abbreviation | M167
Arguments | None.
Default | The C166 Compiler uses the original C166 (80C166) instruction set.
µVision | Options — C166 — Misc Controls.
Description

The MOD167 directive instructs the compiler to generate code using the enhanced C167 instruction set. Among other things, this instruction set has new instructions that more efficiently allow access to far and huge objects. For this reason, the COMPACT and LARGE memory models are best suited for C166 (80C166) microcontrollers while the HCOMPACT, HLARGE, and XLARGE memory models are better suited for C167 and compatible devices.
See Also | COMPACT, HCOMPACT, HLARGE, LARGE, MODV2, XLARGE
Example
C166 SAMPL1667.C MOD167

#pragma MOD167


C166: MODV2 Compiler Directive

MODV2 Compiler Directive

Abbreviation | None.
Arguments | None.
Default | The C166 Compiler uses the original C166 (80C166) instruction set.
µVision | Options — C166 — Misc Controls.
Description

The MODV2 directive instructs the compiler to generate code using the enhanced XC16x/Super10 instruction set. The XC16x and Super10 devices support a new MAC unit that may be used to get increased performance of multiplication, multiply and accumulate, and memory move operations.
See Also | MOD167
Example
C166 XCSAMPLE.C MODV2

#pragma MODV2


C166: NOALIAS Compiler Directive

NOALIAS Compiler Directive

Abbreviation | NOAL
Arguments | None.
Default | All write operations via pointer are destructive. The compiler does not reuse the contents of registers when variables are accessed through pointers.
µVision | Options — C166 — Alias Checking on Pointer Accesses.
Description

It is common practice for the compiler to copy a variable's value into a register for fast, temporary access. However, when the value is changed through a pointer to the variable, the contents of the register must be re-synchronized. The technique which does this is known as alias checking. It is enabled by default.

The NOALIAS directive instructs the compiler to ignore pointer write operations during the optimization phase. If a register holds a variable, the variable is reused, even when access through a pointer might have modified that variable.

If you are confident that certain functions in your program do not modify variables through pointers, the NOALIAS directive may be used to reduce program size.
Example
C166 SAMPLE.C NOALIAS

#pragma NOAL

The following example:

 stmt lvl     source
    1         struct { int  i1; int  i2; } *p_struct;
    2         int val;
    3
    4         void func1 (int *p_val)  {
    5  1        p_struct->i1 = val;
    6  1        *p_val = 0;
    7  1        p_struct->i2 = val;
    8  1      }
    9
   10         void func2 (void)  {
   11  1        func1 (&val);
   12  1      }

demonstrates code generated using the NOALIAS directive:

Code Generated
Without NOALIAS
; FUNCTION func1 (BEGIN  RMASK = @0x4030)
                   ; SOURCE LINE # 4
;---- 'p_val' assigned to 'R8' ----
                   ; SOURCE LINE # 5
0000 F2F40000 R    MOV       R4,p_struct
0004 84040200 R    MOV       [R4],val

                   ; SOURCE LINE # 6
0008 E005          MOV       R5,#00H
000A B858          MOV       [R8],R5
                   ; SOURCE LINE # 7
000C F2F50200 R    MOV       R5,val
0010 F2F40000 R    MOV       R4,p_struct
0014 C4540200      MOV       [R4+#02H],R5
                   ; SOURCE LINE # 8
0018 CB00          RET
; FUNCTION func1 (END    RMASK = @0x4030)

; FUNCTION func2 (BEGIN  RMASK = @0x0130)
                   ; SOURCE LINE # 10
                   ; SOURCE LINE # 11
001A E6F80200 R    MOV       R8,#val
001E BBF0          CALLR     func1
                   ; SOURCE LINE # 12
0020 CB00          RET
; FUNCTION func2 (END    RMASK = @0x0130)
CODE SIZE: 34 Bytes
Code Generated
With NOALIAS
; FUNCTION func1 (BEGIN  RMASK = @0x4070)
                   ; SOURCE LINE # 4
;---- 'p_val' assigned to 'R8' ----
                   ; SOURCE LINE # 5
0000 F2F40200 R    MOV       R4,val
0004 F2F60000 R    MOV       R6,p_struct
0008 B846          MOV       [R6],R4
                   ; SOURCE LINE # 6
000A E005          MOV       R5,#00H
000C B858          MOV       [R8],R5
                   ; SOURCE LINE # 7

000E C4460200      MOV       [R6+#02H],R4
                   ; SOURCE LINE # 8
0012 CB00          RET
; FUNCTION func1 (END    RMASK = @0x4070)

; FUNCTION func2 (BEGIN  RMASK = @0x0170)
                   ; SOURCE LINE # 10
                   ; SOURCE LINE # 11
0014 E6F80200 R    MOV       R8,#val
0018 BBF3          CALLR     func1
                   ; SOURCE LINE # 12
001A CB00          RET
; FUNCTION func2 (END    RMASK = @0x0170)
CODE SIZE: 28 Bytes

When the NOALIAS directive is used, the compiler does not reload p_struct or val, even though the *p_val = 0 statement destroys val.


C166: NOAMAKE Compiler Directive

NOAMAKE Compiler Directive

Abbreviation | NOAM
Arguments | None.
Default | AutoMAKE information is generated.
µVision | This directive may not be used with µVision.
Description

The NOAMAKE directive disables AutoMAKE project information records produced by the Compiler. Use this directive to generate object files to use with older versions of the development tool chain and emulators that do not support all of the Keil object module extensions.

Note

  • The NOAMAKE directive excludes certain information from the object module that is required for global register optimization. When this directive is used, global register optimization is not possible.
See Also | REGFILE
Example
C166 SAMPLE.C  NOAMAKE

#pragma NOAM


C166: NOASMEXPAND Compiler Directive

NOASMEXPAND Compiler Directive

Abbreviation | NOAE
Arguments | None.
Default | ASMEXPAND
µVision | Options — C166 — Misc Controls.
Description

The NOASMEXPAND directive prevents the compiler from expanding symbols used in ASM/ENDASM blocks. Instead, text between ASM and ENDASM is copied verbatim without any preprocessor expansion. Use this directive when symbols in your in-line assembly have the same names as defined macros.
See Also | ASMEXPAND
Example
#pragma noasmexpand

#define  abc  1
#define  xx0  2
#define  xx1  3

#pragma asm
  abc equ 2     ; above 'abc' not expanded
  xx0 equ 10    ; above 'xx0' not expanded
#ifdef QQQ
  xx1 equ 20
#endif

#pragma endasm


C166: NOCOND Compiler Directive

NOCOND Compiler Directive

Abbreviation | NOCO
Arguments | None.
Default | COND
µVision | Options — Listing — C Compiler Listing — Conditional.
Description

The NOCOND directive excludes lines omitted from compilation from the listing file.
See Also | COND
Example

The following example shows the listing file for a source file compiled with the NOCOND directive:

.
.
.
stmt level  source
   1        extern unsigned char  a, b;
   2               unsigned char     c;
   3
   4        main()
   5        {
   6   1    #if defined (VAX)
   9   1      b = 14;
  10   1      a = 15;
  11   1    #endif
  12   1    }
.
.
.


C166: NODPPSAVE Compiler Directive

NODPPSAVE Compiler Directive

Abbreviation | NODS
Arguments | None.
Default | The DPP0 and DPP3 registers are saved on interrupt entries.
µVision | Options — C166 — Save DPP on Interrupt Entry.
Description

The NODPPSAVE directive instructs the compiler not to preserve the DPP0 and DPP3 registers inside interrupt functions. This control is useful when writing applications for the C167 microcontroller using the MOD167 directive. It may be used when you are certain the DPP0 and DPP3 registers are not altered in assembly subroutines and when all C modules are compiled using the MOD167 directive.

Note

  • The C run-time libraries for the C16x/ST10 microcontroller family do not alter the contents of the DPP0 and DPP3 registers.
See Also | MOD167
Example
C166 SAMPLE.C NODPPSAVE

#pragma NODPPSAVE

The following example:

stmt lvl  source

   1      extern void efunc (void);
   2
   3      void func (void) interrupt 0x21
   4                       using     ireg1
   5      {
   6   1    efunc ();
   7   1  }

demonstrates code generated using the NODPPSAVE directive:

Code Generated
Normally
    ; FUNCTION func (BEGIN)
    ; SOURCE LINE # 3
0000 C6030300      SCXT    DPP3,#03H
0004 CC00          NOP
0006 F6F00000 R    MOV     ireg1,R0
000A C60800C0 R    SCXT    CP,#ireg1
000E CC00          NOP
0010 EC00          PUSH    DPP0
0012 C6871000      SCXT    MDC,#010H
0016 EC06          PUSH    MDH
0018 EC07          PUSH    MDL

    ; SOURCE LINE # 6
001A CA000000 E    CALLA   cc_UC,efunc

    ; SOURCE LINE # 7
001E FC07          POP     MDL
0020 FC06          POP     MDH
0022 FC87          POP     MDC
0024 FC00          POP     DPP0
0026 FC08          POP     CP
0028 FC03          POP     DPP3
002A FB88          RETI
    ; FUNCTION func (END)
CODE SIZE: 44 Bytes
Code Generated
With NODPPSAVE
    ; FUNCTION func (BEGIN)
    ; SOURCE LINE # 3

0000 F6F00000 R    MOV     ireg1,R0
0004 C60800C0 R    SCXT    CP,#ireg1
0008 CC00          NOP

000A C6871000      SCXT    MDC,#010H
000E EC06          PUSH    MDH
0010 EC07          PUSH    MDL

    ; SOURCE LINE # 6
0012 CA000000 E    CALLA   cc_UC,efunc

    ; SOURCE LINE # 7
0016 FC07          POP     MDL
0018 FC06          POP     MDH
001A FC87          POP     MDC

001C FC08          POP     CP

001E FB88          RETI
    ; FUNCTION func (END)
CODE SIZE: 32 Bytes


C166: NOEXTEND Compiler Directive

NOEXTEND Compiler Directive

Abbreviation | None.
Arguments | None.
Default | All language extensions are enabled.
µVision | Options — C166 — Misc Controls.
Description

The NOEXTEND directive instructs the compiler to process only ANSI C language constructs. All C166 language extensions are disabled. Compiler-specific keywords are not recognized and cause compiler errors or warnings if used.
Example
C166 SAMPLE.C NOEXTEND

#pragma NOEXTEND


C166: NOFIXDPP Compiler Directive

NOFIXDPP Compiler Directive

Abbreviation | NOFD
Arguments | None.
Default | The C166 Compiler assumes the user stack is accessed with the DPP2 register.
µVision | Options — C166 — Misc Controls.
Description

By default, the C166 Compiler assumes the DPP2 register is used for all user stack accesses. The NOFIXDPP directive must be used when the DPPUSE L166 Linker Directive is used to reassign DPP registers. The NOFIXDPP directive instructs the compiler to generate code independent of DPP register contents.

Refer to DPPUSE in the L166 User's Guide for more information about DPPUSE.

Note

  • The NOFIXDPP control is only relevant if you convert the address of a user stack-based object to a far pointer.
Example
C166 SAMPLE.C NOFIXDPP

#pragma NOFD

The following example:

stmt lvl  source
   1      char far *p;
   2
   3      void func (void)  {
   4   1    char array[10];
   5   1
   6   1    p = &array[0];
   7   1  }

demonstrates code generated using the NOFIXDPP directive.

Code Generated
Normally
    ; FUNCTION func (BEGIN)
    ; SOURCE LINE # 3
0000 06F0F6FF      ADD     R0,#0FFF6H

    ; SOURCE LINE # 6
0004 F040          MOV     R4,R0
0006 66F4FF3F      AND     R4,#03FFFH
000A F2F504FE      MOV     R5,DPP2

000E F6F40000 R    MOV     p,R4
0012 F6F50200 R    MOV     p+02H,R5

    ; SOURCE LINE # 7
0016 06F00A00      ADD     R0,#0AH
001A CB00          RET
    ; FUNCTION func (END)
CODE SIZE: 28 Bytes
Code Generated
With NOFIXDPP
    ; FUNCTION func (BEGIN)
    ; SOURCE LINE # 3
0000 06F0F6FF      ADD     R0,#0FFF6H

    ; SOURCE LINE # 6
0004 F040          MOV     R4,R0
0006 E005          MOV     R5,#00H
0008 06F40000 E    ADD     R4,#SOF(?C_NDATABASE)
000C 16F50000 E    ADDC    R5,#?C_NDATABASESEG
0010 0044          ADD     R4,R4
0012 1055          ADDC    R5,R5
0014 0044          ADD     R4,R4
0016 1055          ADDC    R5,R5
0018 7C24          SHR     R4,#02H
001A F6F40000 R    MOV     p,R4
001E F6F50200 R    MOV     p+02H,R5

    ; SOURCE LINE # 7
0022 06F00A00      ADD     R0,#0AH
0026 CB00          RET
    ; FUNCTION func (END)
CODE SIZE: 40 Bytes


C166: NOFRAME Compiler Directive

NOFRAME Compiler Directive

Abbreviation | NOF
Arguments | None.
Default | Interrupt routines are created with prolog and epilog.
µVision | This directive cannot be entered at command line level.
Description

The NOFRAME directive suppresses the prolog and epilog for an Interrupt Service Routine (ISR). By default, the C166 Compiler adds a prolog and epilog that save and restore used register to interrupt functions.

The NOFRAME directive is useful with interrupt functions that never return as is the case with an interrupt that resets the MCU.

Note

  • The NOFRAME directive is active for one function only. It is therefore not possible to use it at command line level.
Example

The following example illustrates the difference between a standard interrupt frame and one created with the NOFRAME directive.

  1          int i1, i2, i3;
  2
  3          void intr_func1 (void)  interrupt 0x21  {
  4   1        i1 = i2 * i3;
  5   1      }
  6
  7          #pragma NOFRAME
  8          void intr_func2 (void)  interrupt 0x22  {
  9   1        i1 = i2 * i3;
 10   1      }

 ASSEMBLY LISTING OF GENERATED OBJECT CODE

 ; FUNCTION intr_func1 (BEGIN  RMASK = @0x2030)
                 ; SOURCE LINE # 3
 0000 C6871000      SCXT    MDC,#010H
 0004 EC06          PUSH    MDH
 0006 EC07          PUSH    MDL
 0008 ECF4          PUSH    R4
 000A ECF5          PUSH    R5
                 ; SOURCE LINE # 4
 000C F2F50000 R    MOV     R5,i3
 0010 F2F40200 R    MOV     R4,i2
 0014 0B45          MUL     R4,R5
 0016 F2F40EFE      MOV     R4,MDL
 001A F6070400 R    MOV     i1,MDL
                 ; SOURCE LINE # 5
001E FCF5          POP     R5
0020 FCF4          POP     R4
0022 FC07          POP     MDL
0024 FC06          POP     MDH
0026 FC87          POP     MDC
0028 FB88          RETI
; FUNCTION intr_func1 (END    RMASK = @0x2030)

; FUNCTION intr_func2 (BEGIN  RMASK = @0x2030)
                ; SOURCE LINE # 8
                ; SOURCE LINE # 9
002A F2F50000 R    MOV     R5,i3
002E F2F40200 R    MOV     R4,i2
0032 0B45          MUL     R4,R5
0034 F2F40EFE      MOV     R4,MDL
0038 F6070400 R    MOV     i1,MDL
                ; SOURCE LINE # 10
003C FB88          RETI
; FUNCTION intr_func2 (END    RMASK = @0x2030)


C166: NOINIT Compiler Directive

NOINIT Compiler Directive

Abbreviation | NOIN
Arguments | None.
Default | INIT
µVision | This directive may not be specified on the command line.
Description

The NOINIT directive specifies that declared variables are not initialized to zero (0) at the startup (reset) of the program. This directive does not disable explicit variable initializations at source level. It affects only the implicit zero initialization of the variables.

Embedded systems with non-volatile memory may require that variables are not cleared to zero at startup. The INIT directive may be used with the NOINIT directive to switch back and forth between variables which should be initialized and those which should not.
See Also | INIT
Example
#pragma NOINIT
char states[100];     /* Uninitialized Variable */

#pragma INIT
char array[100];      /* Initialized Variable */


C166: NOOBJECT Compiler Directive

NOOBJECT Compiler Directive

Abbreviation | NOOJ
Arguments | None.
Default | OBJECT (filename.OBJ)
µVision | None.
Description

The NOOBJECT directive prevents the compiler from creating an object file.
See Also | OBJECT
Example
C166 SAMPLE.C NOOBJECT

#pragma nooj


C166: NOPRINT Compiler Directive

NOPRINT Compiler Directive

Abbreviation | NOPR
Arguments | None.
Default | PRINT (filename.LST)
µVision | Options — Listing — C Compiler Listing.
Description

The NOPRINT directive prevents the compiler from generating a listing file.
See Also | PRINT
Example
C166 SAMPLE.C NOPRINT

#pragma nopr


C166: NOREORDER Compiler Directive

NOREORDER Compiler Directive

Abbreviation | NORO
Arguments | None.
Default | Instructions are not reordered.
µVision | Options — C166 — Reorder Instructions to Minimize Pipeline Effects.
Description

The NOREORDER directive disables instruction reordering that was previously enabled with the REORDER directive.
See Also | REORDER
Example
C166 EXAMPLE.C NOREORDER

#pragma noreorder


C166: NOSAVEMAC Compiler Directive

NOSAVEMAC Compiler Directive

Abbreviation | NOSM
Arguments | None.
Default | The C166 Compiler does not save MAC registers for interrupt functions.
µVision | Options — C166 — Misc Controls.
Description | The NOSAVEMAC directive directs the C166 Compiler not to save the MAC co-processor registers during interrupt functions.
See Also | MAC, SAVEMAC
Example | None.


C166: OBJECT Compiler Directive

OBJECT Compiler Directive

Abbreviation | OJ
Arguments | An optional filename enclosed in parentheses.
Default | OBJECT (filename.OBJ)
µVision | Options — Output — Select Folder for Objects.
Description

The OBJECT directive specifies the filename of the object file. By default, the object file created is named using the source file name and the .OBJ file extension.
See Also | NOOBJECT
Example
C166 SAMPLE.C OBJECT(sample1.obj)

#pragma oj(sample_1.obj)


C166: OPTIMIZE Compiler Directive

OPTIMIZE Compiler Directive

Abbreviation | OT
Arguments | A decimal number between 0 and 8 enclosed in parentheses optionally followed by SIZE or SPEED to specify code size or execution speed emphasis.
Default | OPTIMIZE (6, SPEED)
µVision | Options — C166 — Code Optimization.
Description

The OPTIMIZE directive sets the optimization level and emphasis the C166 Compiler uses when generating object code.

Level | Description
0 | Constant Folding: The compiler performs calculations that reduce expressions to numeric constants, where possible. This includes calculations of run-time addresses. Jump Optimizing: The compiler always extends jumps to the final target. Jumps to jumps are eliminated.
1 | Dead Code Elimination: Unused code fragments and artifacts are eliminated. Jump Negation: Conditional jumps are closely examined to see if they can be streamlined or eliminated by the inversion of the test logic.
2 | Access Optimizing: Variables accesses are directly included in operations. Intermediate registers are frequently unnecessary.
3 | Unreachable Code Analysis: Code that cannot be reached because of constant conditional expressions or unreferenced labels is removed. Register Variables: Automatic variables and function arguments are located in registers when possible. Reservation of data memory for these variables is omitted.
4 | Local Common Subexpression Elimination: The compiler detects multiple uses of the same expression or subexpression. The result of the first expression is saved and reused when possible. Superfluous expression calculations are eliminated from the code. Global Common Subexpression Elimination: Identical subexpressions within a function are calculated only once when possible. The intermediate result is stored in a register and reused. Case/Switch Optimizing: Code involving switch and case statements is optimized using jump tables or jump strings.
5 | Life Variable Analysis: Redundant store operations are replaced with the use of automatic variables.
6 | Constant Propagation: The values of expressions are tracked and, when possible, constant values are inserted instead of variable accesses. Peephole Optimizing: Redundant MOV instructions are removed. This includes unnecessary loading of objects from the memory as well as load operations with constants. Complex operations are replaced by simple operations when memory space or execution time can be saved.
7 | Common Tail Merging: When there are multiple calls to a single function, some of the setup code can be reused, thereby reducing program size.
8 | Register Variable Lifetime Analysis: Register variables are relocated in CPU registers to improve execution speed and code density.

Note

  • Each higher optimization level contains all of the characteristics of the preceding lower optimization level. For example, OPTIMIZE level 7 includes all optimizations of levels 0 to 6.
Example
C166 SAMPLE.C OPTIMIZE (4)

C166 SAMPLE.C OPTIMIZE (0)

#pragma ot(6, SIZE)

#pragma ot(size)


C166: ORDER Compiler Directive

ORDER Compiler Directive

Abbreviation | OR
Arguments | None.
Default | The variables are not ordered.
µVision | Options — C166 — Keep Variables in Order.
Description

The ORDER directive instructs the compiler to order all variables in memory according to their order of definition in the C source file. This directive disables the hash algorithm used by the C compiler when adding symbols to the symbol table and may result in longer compile times.
Example
C166 SAMPLE.C ORDER

#pragma OR


C166: PACK Compiler Directive

PACK Compiler Directive

Abbreviation | None.
Arguments | A decimal number (1, 2, or 4), enclosed in parentheses.
Default | PACK(2)
µVision | Options — C166 — Misc Controls.
Description

The PACK directive causes the compiler to generate byte-aligned structures with word elements. This is useful when exchanging data with other systems where no alignment is required.

Note

  • The compiler generates considerably more code to access byte-aligned words. For this reason, PACK(1) should be used only when necessary.
  • By default, the compiler assumes that structure members are aligned on word boundaries. If you use PACK(1) some structure members may be aligned on byte boundaries. The BYTEALIGN directive supports pointers to structure members that are aligned on byte boundaries.
See Also | BYTEALIGN
Example
#pragma pack(1)     /* byte alignment */
#pragma bytealign   /* ptrs to byte-aligned objects */

struct s1  {
  int  i1;     // i1 has offset 0
  char c1;     // c1 has offset 2
  int  i2;     // i2 has offset 3
  char c2;     // c2 has offset 5
  int  i3;     // i3 has offset 6
  char z1;     // z1 has offset 8
};

#pragma pack()    /* reset to default alignment */

struct s2  {
  int  i1;     // i1 has offset 0
  char c1;     // c1 has offset 2
  int  i2;     // i2 has offset 4
  char c2;     // c2 has offset 6
  int  i3;     // i3 has offset 8
  char z1;     // z1 has offset 10
};


C166: PAGELENGTH Compiler Directive

PAGELENGTH Compiler Directive

Abbreviation | PL
Arguments | A decimal number up to 65535 enclosed in parentheses.
Default | PAGELENGTH (60)
µVision | Options — Listing — Page Length.
Description

The PAGELENGTH directive specifies the number of lines printed per page in the listing file.
See Also | PAGEWIDTH
Example
C166 SAMPLE.C PAGELENGTH (70)

#pragma pl (70)


C166: PAGEWIDTH Compiler Directive

PAGEWIDTH Compiler Directive

Abbreviation | PW
Arguments | A decimal number from 78 to 132 enclosed in parentheses.
Default | PAGEWIDTH (132)
µVision | Options — Listing — Page Width.
Description

The PAGEWIDTH directive specifies the number of characters printed per line in the listing file. Lines with more characters are split into multiple lines.
See Also | PAGELENGTH
Example
C166 SAMPLE.C PAGEWIDTH(79)

#pragma pw(79)


C166: PECDEF Compiler Directive

PECDEF Compiler Directive

Abbreviation | PD
Arguments | PEC channel numbers from 0-7. Numbers must be separated by commas if more than one is specified. Channel ranges may be specified using a dash between the numbers.
Default | None.
µVision | Options — C166 — Misc Controls.
Description

The PECDEF directive reserves memory space required by the PEC source and destination pointers for the specified channels. The PEC source and destination pointers are used for PEC transfers and are located in internal RAM at address 0FDE0h-0FDFFh. By default, this memory is available to the application program.
Example
C166 SAMPLE.C PECDEF (0, 2, 4)

// Reserve memory for PEC channel 6
#pragma PD (6)

// Reserve memory for PEC channels 1-7
#pragma PD (1, 2, 3, 4, 5, 6, 7)

// Reserve memory for PEC channels 1-3 and 5-7
#pragma PD (1 - 3, 5 - 7)


C166: PREPRINT Compiler Directive

PREPRINT Compiler Directive

Abbreviation | PP
Arguments | An optional filename enclosed in parentheses.
Default | No preprocessor listing is generated.
µVision | Options — C166 — C Preprocessor Listing.
Description

The PREPRINT directive instructs the compiler to produce a preprocessor listing. Macro calls are expanded and comments are deleted. If PREPRINT is used without an argument, the source filename with the extension .I is used. By default, the compiler does not generate a preprocessor output file.

The PREPRINT directive causes the compiler to produce a preprocessor listing file. Macro calls are expanded and comments are deleted and an object file is created.

If no argument is specified for PREPRINT, the preprocessor listing file is named basename.I where basename is the name of the source file.

If an argument is specified for PREPRINT, the preprocessor listing file is created with that name.

By default, the compiler does not create a preprocessor listing file.

Note

  • The PREPRINT directive may be specified only on the command line. It may not be specified in the C source file by means of the #pragma directive.
See Also | NOPRINT, PREPRINTONLY, PRINT
Example
C166 SAMPLE.C PREPRINT

C166 SAMPLE.C PP (PREPRO.LST)


C166: PREPRINTONLY Compiler Directive

PREPRINTONLY Compiler Directive

Abbreviation | PPO
Arguments | An optional filename enclosed in parentheses.
Default | No preprocessor listing is generated.
µVision | Options — C166 — Misc Controls.
Description

The PREPRINTONLY directive causes the compiler to produce a preprocessor listing file and halt further processing. Macro calls are expanded and comments are deleted but no object file is created.

If no argument is specified for PREPRINTONLY, the preprocessor listing file is named basename.I where basename is the name of the source file.

If an argument is specified for PREPRINTONLY, the preprocessor listing file is created with that name.

By default, the compiler does not create a preprocessor listing file.

Note

  • The PREPRINTONLY directive may be specified only on the command line. It may not be specified in the C source file using the #pragma directive.
See Also | PREPRINT
Example
C166 SAMPLE.C PREPRINTONLY

C166 SAMPLE.C PPO (PREPRO.LST)


C166: PRINT Compiler Directive

PRINT Compiler Directive

Abbreviation | PR
Arguments | An optional filename enclosed in parentheses.
Default | PRINT (filename.LST)
µVision | Options — Listing — Select Folder for List Files.
Description

The PRINT directive specifies the filename of the listing file. By default, the listing file created is named using the source file name and the .LST file extension.

For an example of the listing file output, refer to the Listing File description.
See Also | NOPRINT, TABS
Example
C166 SAMPLE.C PRINT(CON:)

#pragma pr (\usr\list\sample.lst)


C166: REENTRANT Compiler Directive

REENTRANT Compiler Directive

Abbreviation | None.
Arguments | None.
Default | REENTRANT
µVision | Options — C166 — Use Static Memory for Non—register Automatics.
Description

The REENTRANT directive instructs the C166 Compiler to store automatic variables that cannot be allocated to a CPU register on the user stack. The generated code is fully reentrant.

The C166 Compiler uses the MOV Rn,[R0+#d16] and MOV [R0+#d16],Rn instructions to access stack-based variables.
See Also | STATIC
Example
stmt level    source

   1          #pragma reentrant
   2
   3          int rfunc (int i, int j)  {
   4   1        int array[10];
   5   1
   6   1        array[i] = j;
   7   1        return (array[j]);
   8   1      }
   9
  10          #pragma static
  11
  12          int sfunc (int i, int j)  {
  13   1        int array[10];
  14   1
  15   1        array[i] = j;
  16   1        return (array[j]);
  17   1      }

ASSEMBLY LISTING OF GENERATED OBJECT CODE
    ; FUNCTION rfunc (BEGIN  RMASK = @0x4070)
        ; SOURCE LINE # 3
;---- Variable ‘j’ assigned to Register ‘R9’ ----
;---- Variable ‘i’ assigned to Register ‘R8’ ----
0000 06F0ECFF      ADD     R0,#0FFECH
        ; SOURCE LINE # 6
0004 F058          MOV     R5,R8
0006 5C15          SHL     R5,#01H
0008 F060          MOV     R6,R0
000A F046          MOV     R4,R6
000C 0045          ADD     R4,R5
000E B894          MOV     [R4],R9
        ; SOURCE LINE # 7
0010 F049          MOV     R4,R9
0012 5C14          SHL     R4,#01H
0014 0064          ADD     R6,R4
0016 A846          MOV     R4,[R6]
        ; SOURCE LINE # 8
0018 06F01400      ADD     R0,#014H
001C CB00          RET
    ; FUNCTION rfunc (END    RMASK = @0x4070)

    ; FUNCTION sfunc (BEGIN  RMASK = @0x4010)
        ; SOURCE LINE # 12
;---- Variable ‘j’ assigned to Register ‘R9’ ----
;---- Variable ‘i’ assigned to Register ‘R8’ ----
        ; SOURCE LINE # 15
001E F048          MOV     R4,R8
0020 5C14          SHL     R4,#01H
0022 C4940000      MOV     [R4+#array],R9
        ; SOURCE LINE # 16
0026 F049          MOV     R4,R9
0028 5C14          SHL     R4,#01H
002A D4440000      MOV     R4,[R4+#array]
        ; SOURCE LINE # 17
002E CB00          RET
    ; FUNCTION sfunc (END    RMASK = @0x4010)


C166: REGFILE Compiler Directive

REGFILE Compiler Directive

Abbreviation | RF
Arguments | A file name enclosed in parentheses.
Default | None.
µVision | Options — C166 — Global Register Coloring.
Description

The REGFILE directive instructs the compiler to use a register definition file for global register optimization. The register definition file specifies the registers used by external functions. Using this information, the compiler can optimize the use of the general purpose registers. This feature enables global program-wide register optimization.
Example
C166 SAMPLE.C REGFILE(sample.reg)

#pragma REGFILE(sample.reg)


C166: RENAMECLASS Compiler Directive

RENAMECLASS Compiler Directive

Abbreviation | RC
Arguments | RENAMECLASS (class = userclass)
Default | None.
µVision | Options — C166 — Misc Controls.
Description

The RENAMECLASS directive changes the name of the predefined memory class to the userclass name specified. This directive is typically used when parts of your project must be located to memory areas that differ from the predefined memroy classes.

Note

  • Class names may be changed only for a complete module.
  • The memory model must be defined before a CODE section is renamed. Therefore, the memory model must be specified before the RENAMECLASS directive is used.
Example
C166 SAMPLE.C LARGE RENAMECLASS (FCODE=FLASH_FCODE)

#pragma HLARGE
#pragma RENAMECLASS (FCODE=BOOT_FCODE)


C166: REORDER Compiler Directive

REORDER Compiler Directive

Abbreviation | RO
Arguments | None.
Default | Instructions are not reordered.
µVision | Options — C166 — Reorder Instructions to Minimize Pipeline Effects.
Description

The REORDER directive enables the compiler to reorder instructions to minimize wait states and pipeline stalls. REORDER is only useful for XC16x and Super-10 devices where the following instructions may cause stalls (wait states) when the register used in the instruction are set in the prior instruction.

  • MOV Rn,[Rm]
  • MOV Rn,[Rm+data16]
  • MOV xxx,MDL
  • MOV xxx,MDH

The following example:

stmt lvl  source
  1       unsigned int *p;
  2       unsigned int v;
  3
  4       unsigned int func (void)  {
  5   1     unsigned int i1, i2;
  6   1
  7   1     i1 = v * 4;
  8   1     i2 = *p << i1;
  9   1     return (i2);
 10   1   }

demonstrates code generated using the REORDER directive:

Code Generated
Normally
; FUNCTION func (BEGIN)
                  ; SOURCE LINE # 4
                  ; SOURCE LINE # 7

0000 F2F50000 R    MOV       R5,v
0004 5C25          SHL       R5,#02H
;---- 'i1' assigned to 'R5' ----
                  ; SOURCE LINE # 8
0006 F2F10200 R    MOV       R1,p
000A A841          MOV       R4,[R1]
000C 4C45          SHL       R4,R5
;---- 'i2' assigned to 'R4' ----
                  ; SOURCE LINE # 9
                  ; SOURCE LINE # 10
000E CB00          RET
; FUNCTION func (END)
Code Generated
with REORDER
; FUNCTION func (BEGIN)
                  ; SOURCE LINE # 4
                  ; SOURCE LINE # 7
0000 F2F10200 R    MOV       R1,p
0004 F2F50000 R    MOV       R5,v
0008 5C25          SHL       R5,#02H
;---- 'i1' assigned to 'R5' ----
                  ; SOURCE LINE # 8

000A A841          MOV       R4,[R1]
000C 4C45          SHL       R4,R5
;---- 'i2' assigned to 'R4' ----
                  ; SOURCE LINE # 9
                  ; SOURCE LINE # 10
000E CB00          RET
; FUNCTION func (END)
See Also | NOREORDER
Example
C166 EXAMPLE.C REORDER

#pragma reorder


C166: RESTORE Compiler Directive

RESTORE Compiler Directive

Abbreviation | None.
Arguments | None.
Default | None.
µVision | This directive may not be specified on the command line.
Description

The RESTORE directive restores the settings (from the save stack) that were previously saved using the SAVE directive.

Note

  • SAVE and RESTORE may be specified only as an argument of a #pragma. You may not specify these directives on the command line.
See Also | SAVE
Example
#pragma save
#pragma optimize (1)

void func (void)
{
.
.
.
}

#pragma restore


C166: SAVE Compiler Directive

SAVE Compiler Directive

Abbreviation | None.
Arguments | None.
Default | None.
µVision | This directive may not be specified on the command line.
Description

The SAVE directive stores the current settings of the OPTIMIZE directive onto a save stack. Settings may be restored using the RESTORE directive.

Settings may be saved before an #include directive, so that the included file doesn't affect settings for the current file, and restored afterwards using RESTORE.

The maximum nesting depth for SAVE directives is eight levels.

Note

  • SAVE and RESTORE may be specified only as an argument of a #pragma. You may not specify these directives on the command line.
See Also | OPTIMIZE, RESTORE
Example
#pragma save
#pragma optimize (1)

void func (void)
{
.
.
.
}

#pragma restore


C166: SAVEMAC Compiler Directive

SAVEMAC Compiler Directive

Abbreviation | SM
Arguments | None.
Default | The C166 Compiler does not save MAC registers for interrupt functions.
µVision | Options — C166 — Misc Controls.
Description | The SAVEMAC directive directs the C166 Compiler to save all MAC co-processor registers during interrupt functions.
See Also | MAC, NOSAVEMAC
Example
    1         #pragma SAVEMAC
    2
    3         void irq_func1 (void) interrupt 1 {
    4  1        ;
    5  1      }
    6
    7         #pragma NOSAVEMAC
    8
    9         void irq_func2 (void) interrupt 2  {
   10  1        ;
   11  1      }

             ; FUNCTION irq_func1
             3:  void irq_func1 (void) interrupt 1 {
0002 EC2E          PUSH      MAL
0004 EC2F          PUSH      MAH
0006 C6ED0000      SCXT      MRW,#00H
000A EC84          PUSH      IDX0
000C EC85          PUSH      IDX1
000E EC02          PUSH      QR0
0010 EC03          PUSH      QR1
0012 EC00          PUSH      QX0
0014 EC01          PUSH      QX1
0016 ECEE          PUSH      MCW
              4:    ;
0018 FCEE          POP       MCW
001A FC01          POP       QX1
001C FC00          POP       QX0
001E FC03          POP       QR1
0020 FC02          POP       QR0
0022 FC85          POP       IDX1
0024 FC84          POP       IDX0
0026 FCED          POP       MRW
0028 FC2F          POP       MAH
002A FC2E          POP       MAL
002C FCEF          POP       MSW
002E FB88          RETI
              5:  }

 ; FUNCTION irq_func2 (BEGIN RMASK = @0x8000)
              9:  void irq_func1 (void) interrupt 1 {
             10:    ;
0030 FB88          RETI
             11:  }


C166: SAVESYS Compiler Directive

SAVESYS Compiler Directive

Abbreviation | None.
Arguments | None.
Default | SAVESYS
µVision | Options — C166 — Save Temporary Variables on User Stack.
Description

The SAVESYS directive instructs the C166 Compiler to save temporary results on the system stack. This is the default operation of the C166 Compiler.
See Also | SAVEUSR
Example
  1    extern void func (void);
  2
  3    #pragma SAVESYS // Save to SYS STACK (default)
  4    int func1 (int i1, int i2)  {
  5 1    func ();
  6 1    return (i1 + i2);
  7 1  }
  8
  9
 10    #pragma SAVEUSR // Save to USER STACK
 11    int func2 (int i1, int i2)  {
 12 1    func ();
 13 1    return (i1 + i2);
 14 1  }

ASSEMBLY LISTING OF GENERATED OBJECT CODE
    ; FUNCTION func1 (BEGIN  RMASK = @0x7FFF)
            ; SOURCE LINE # 4
0000 ECFD          PUSH    R13
0002 ECFE          PUSH    R14
0004 F0D9          MOV     R13,R9
;---- Variable 'i2' assigned to Register 'R13' ----
0006 F0E8          MOV     R14,R8
;---- Variable 'i1' assigned to Register 'R14' ----
        ; SOURCE LINE # 5
0008 CA000000 E    CALLA   cc_UC,func
        ; SOURCE LINE # 6
000C F04E          MOV     R4,R14
000E 004D          ADD     R4,R13
        ; SOURCE LINE # 7
0010 FCFE          POP     R14
0012 FCFD          POP     R13
0014 CB00          RET
    ; FUNCTION func1 (END    RMASK = @0x7FFF)

    ; FUNCTION func2 (BEGIN  RMASK = @0x7FFF)
        ; SOURCE LINE # 11
0016 88D0          MOV     [-R0],R13
0018 88E0          MOV     [-R0],R14
001A F0D9          MOV     R13,R9
;---- Variable 'i2' assigned to Register 'R13' ----
001C F0E8          MOV     R14,R8
;---- Variable 'i1' assigned to Register 'R14' ----
        ; SOURCE LINE # 12
001E CA000000 E    CALLA   cc_UC,func
        ; SOURCE LINE # 13
0022 F04E          MOV     R4,R14
0024 004D          ADD     R4,R13
        ; SOURCE LINE # 14
0026 98E0          MOV     R14,[R0+]
0028 98D0          MOV     R13,[R0+]
002A CB00          RET
    ; FUNCTION func2 (END    RMASK = @0x7FFF)


C166: SAVEUSR Compiler Directive

SAVEUSR Compiler Directive

Abbreviation | None.
Arguments | None.
Default | SAVESYS
µVision | Options — C166 — Save Temporary Variables on User Stack.
Description

The SAVEUSR directive instructs the C166 Compiler to save temporary results and saved-by-callee variables on the user stack. This option may be necessary if you run out of system stack space. The system stack is always located in on-chip RAM, which is faster than external RAM but is limited in size.
See Also | SAVESYS
Example
  1    extern void func (void);
  2
  3    #pragma SAVESYS // Save to SYS STACK (default)
  4    int func1 (int i1, int i2)  {
  5 1    func ();
  6 1    return (i1 + i2);
  7 1  }
  8
  9
 10    #pragma SAVEUSR // Save to USER STACK
 11    int func2 (int i1, int i2)  {
 12 1    func ();
 13 1    return (i1 + i2);
 14 1  }

ASSEMBLY LISTING OF GENERATED OBJECT CODE
    ; FUNCTION func1 (BEGIN  RMASK = @0x7FFF)
            ; SOURCE LINE # 4
0000 ECFD          PUSH    R13
0002 ECFE          PUSH    R14
0004 F0D9          MOV     R13,R9
;---- Variable 'i2' assigned to Register 'R13' ----
0006 F0E8          MOV     R14,R8
;---- Variable 'i1' assigned to Register 'R14' ----
        ; SOURCE LINE # 5
0008 CA000000 E    CALLA   cc_UC,func
        ; SOURCE LINE # 6
000C F04E          MOV     R4,R14
000E 004D          ADD     R4,R13
        ; SOURCE LINE # 7
0010 FCFE          POP     R14
0012 FCFD          POP     R13
0014 CB00          RET
    ; FUNCTION func1 (END    RMASK = @0x7FFF)

    ; FUNCTION func2 (BEGIN  RMASK = @0x7FFF)
        ; SOURCE LINE # 11
0016 88D0          MOV     [-R0],R13
0018 88E0          MOV     [-R0],R14
001A F0D9          MOV     R13,R9
;---- Variable 'i2' assigned to Register 'R13' ----
001C F0E8          MOV     R14,R8
;---- Variable 'i1' assigned to Register 'R14' ----
        ; SOURCE LINE # 12
001E CA000000 E    CALLA   cc_UC,func
        ; SOURCE LINE # 13
0022 F04E          MOV     R4,R14
0024 004D          ADD     R4,R13
        ; SOURCE LINE # 14
0026 98E0          MOV     R14,[R0+]
0028 98D0          MOV     R13,[R0+]
002A CB00          RET
    ; FUNCTION func2 (END    RMASK = @0x7FFF)


C166: SMALL Compiler Directive

SMALL Compiler Directive

Abbreviation | SM
Arguments | None.
Default | SMALL
µVision | Options — Target — Memory Model.
Description

The SMALL directive selects the small memory model. The memory model affects the code generated by the compiler. In this memory model variables are accessed using near addresses and functions are accessed using near addresses.
See Also | COMPACT, HCOMPACT, HLARGE, HOLD, LARGE, MEDIUM, TINY, XLARGE
Example
C166 SAMPLE.C SM

#pragma small


C166: SRC Compiler Directive

SRC Compiler Directive

Abbreviation | None.
Arguments | SRC « (filename) »
Default | None.
µVision
  1. Right click on the file in the Project Window — Files tab
  2. Choose Options for... to open Options — Properties page
  3. Enable Generate Assembler SRC file
  4. Enable Assemble SRC file.
Description

The SRC directive creates an assembler source (.SRC) file instead of an object (.OBJ) file. The source file may be assembled with the assembler. Refer to Source (SRC) File for more information regarding assembler source files.

The source file is saved as filename if specified. Otherwise, the source file is saved as the path and base name of the C source file with a .SRC extension.

Note

  • The compiler cannot simultaneously produce a source file and an object file.
See Also | ASM, ENDASM
Example
C166 SAMPLE.C SRC

C166 SAMPLE.C SRC(SML.ASM)

#pragma src


C166: STATIC Compiler Directive

STATIC Compiler Directive

Abbreviation | None.
Arguments | None.
Default | REENTRANT
µVision | Options — C166 — Use Static Memory for Non—register Automatics.
Description

The STATIC directive instructs the C166 Compiler to use static memory locations for automatic variables (not parameters) that cannot be allocated to a CPU register. The generated code is not reentrant but code size is reduced and execution speed is improved.

The C16x/ST10 microcontroller can access static variables directly in operations like ADD, AND, CMP, OR, SUB, and XOR. The MOV instruction accesses direct memory faster than stack-based memory.
See Also | REENTRANT
Example
stmt level    source

   1          #pragma reentrant
   2
   3          int rfunc (int i, int j)  {
   4   1        int array[10];
   5   1
   6   1        array[i] = j;
   7   1        return (array[j]);
   8   1      }
   9
  10          #pragma static
  11
  12          int sfunc (int i, int j)  {
  13   1        int array[10];
  14   1
  15   1        array[i] = j;
  16   1        return (array[j]);
  17   1      }

ASSEMBLY LISTING OF GENERATED OBJECT CODE
    ; FUNCTION rfunc (BEGIN  RMASK = @0x4070)
        ; SOURCE LINE # 3
;---- Variable 'j' assigned to Register 'R9' ----
;---- Variable 'i' assigned to Register 'R8' ----
0000 06F0ECFF      ADD     R0,#0FFECH
        ; SOURCE LINE # 6
0004 F058          MOV     R5,R8
0006 5C15          SHL     R5,#01H
0008 F060          MOV     R6,R0
000A F046          MOV     R4,R6
000C 0045          ADD     R4,R5
000E B894          MOV     [R4],R9
        ; SOURCE LINE # 7
0010 F049          MOV     R4,R9
0012 5C14          SHL     R4,#01H
0014 0064          ADD     R6,R4
0016 A846          MOV     R4,[R6]
        ; SOURCE LINE # 8
0018 06F01400      ADD     R0,#014H
001C CB00          RET
    ; FUNCTION rfunc (END    RMASK = @0x4070)

    ; FUNCTION sfunc (BEGIN  RMASK = @0x4010)
        ; SOURCE LINE # 12
;---- Variable 'j' assigned to Register 'R9' ----
;---- Variable 'i' assigned to Register 'R8' ----
        ; SOURCE LINE # 15
001E F048          MOV     R4,R8
0020 5C14          SHL     R4,#01H
0022 C4940000      MOV     [R4+#array],R9
        ; SOURCE LINE # 16
0026 F049          MOV     R4,R9
0028 5C14          SHL     R4,#01H
002A D4440000      MOV     R4,[R4+#array]
        ; SOURCE LINE # 17
002E CB00          RET
    ; FUNCTION sfunc (END    RMASK = @0x4010)


C166: SYMBOLS Compiler Directive

SYMBOLS Compiler Directive

Abbreviation | SB
Arguments | None.
Default | No list of symbols is generated.
µVision | Options — Listing — C Compiler Listing — Symbols.
Description

The SYMBOLS directive directs the compiler to generate a list of all symbols used in and by the program module being compiled. The symbol list is included in the listing file. The memory category, memory type, offset, and size are listed for each symbolic object.

Refer to the Listing File for a symbol listing example.
Example
C166 SAMPLE.C SYMBOLS

#pragma SYMBOLS


C166: TABS Compiler Directive

TABS Compiler Directive

Abbreviation | TA
Arguments | None.
Default | TABS (4)
µVision | Edit — Configuration — Editor — C/C++ Files — Tab Size.
Description

The TABS directive specifies the tabulator stops used when editing the source files. The tab characters (0x09) are expanded into space characters in the listing file.

For an example of the listing file output, refer to the Listing File description.
See Also | PRINT
Example
C166 SAMPLE.C TABS(2)


C166: TINY Compiler Directive

TINY Compiler Directive

Abbreviation | TI
Arguments | None.
Default | SMALL
µVision | Options — Target — Memory Model.
Description

The TINY directive selects the tiny memory model. The memory model affects the code generated by the compiler. In this memory model the non-segmented mode of the C16x/ST10 is used. This mode uses 16-bit addressing for all memory objects.
See Also | COMPACT, HCOMPACT, HLARGE, HOLD, LARGE, MEDIUM, SMALL, XLARGE
Example
C166 SAMPLE.C TINY


C166: UNSIGNED_CHAR Compiler Directive

UNSIGNED_CHAR Compiler Directive

Abbreviation | UCH
Arguments | None.
Default | Variables of type char are signed.
µVision | Options — C166 — Treat 'char' as 'unsigned char'.
Description

The UNSIGNED_CHAR directive instructs the compiler to treat all variables declared with char as unsigned char variables.
Example
C166 SAMPLE.C UNSIGNED_CHAR

#pragma UCH

The following example:

 stmt lvl     source
    1         char  ch1;
    2         unsigned char uch2;   /* always unsigned */
    3         signed char sch3;     /* always signed   */
    4
    5         int i;
    6
    7         void test (void)  {
    8  1        if (ch1  > 0) i = ch1;
    9  1        if (uch2 > 0) i = uch2;
   10  1        if (sch3 > 0) i = sch3;
   11  1      }

demonstrates code generated using the SIGNED_CHAR directive:

Code Generated
Without UNSIGNED_CHAR
; FUNCTION uchar (BEGIN  RMASK = @0x0030)
                   ; SOURCE LINE # 7
                   ; SOURCE LINE # 8
0000 F3FA0200 R    MOVB      RL5,ch1
0004 49A0          CMPB      RL5,#00H
0006 BD03          JMPR      cc_SLE,?C0001
0008 D0A4          MOVBS     R4,RL5
000A F6F40000 R    MOV       i,R4
000E         ?C0001:
                   ; SOURCE LINE # 9
000E F3FA0300 R    MOVB      RL5,uch2
0012 49A0          CMPB      RL5,#00H
0014 FD03          JMPR      cc_ULE,?C0002
0016 C0A4          MOVBZ     R4,RL5
0018 F6F40000 R    MOV       i,R4
001C         ?C0002:
                   ; SOURCE LINE # 10
001C F3FA0400 R    MOVB      RL5,sch3
0020 49A0          CMPB      RL5,#00H
0022 BD03          JMPR      cc_SLE,?C0003
0024 D0A4          MOVBS     R4,RL5
0026 F6F40000 R    MOV       i,R4
002A         ?C0003:
                   ; SOURCE LINE # 11
002A CB00          RET
; FUNCTION uchar (END    RMASK = @0x0030)
CODE SIZE: 44 Bytes
Code Generated
With UNSIGNED_CHAR
; FUNCTION uchar (BEGIN  RMASK = @0x0030)
                   ; SOURCE LINE # 7
                   ; SOURCE LINE # 8
0000 F3FA0200 R    MOVB      RL5,ch1
0004 49A0          CMPB      RL5,#00H
0006 FD03          JMPR      cc_ULE,?C0001
0008 C0A4          MOVBZ     R4,RL5
000A F6F40000 R    MOV       i,R4
000E         ?C0001:
                   ; SOURCE LINE # 9
000E F3FA0300 R    MOVB      RL5,uch2
0012 49A0          CMPB      RL5,#00H
0014 FD03          JMPR      cc_ULE,?C0002
0016 C0A4          MOVBZ     R4,RL5
0018 F6F40000 R    MOV       i,R4
001C         ?C0002:
                   ; SOURCE LINE # 10
001C F3FA0400 R    MOVB      RL5,sch3
0020 49A0          CMPB      RL5,#00H
0022 BD03          JMPR      cc_SLE,?C0003
0024 D0A4          MOVBS     R4,RL5
0026 F6F40000 R    MOV       i,R4
002A         ?C0003:
                   ; SOURCE LINE # 11
002A CB00          RET
; FUNCTION uchar (END    RMASK = @0x0030)
CODE SIZE: 44 Bytes


C166: USERSTACKDPP3 Compiler Directive

USERSTACKDPP3 Compiler Directive

Abbreviation | U3
Arguments | None.
Default | None.
µVision | Options — C166 — Misc Controls.
Description

The USERSTACKDPP3 directive changes compiler assumptions about accesses to the user stack area and affects the address generation of far, huge, and xhuge pointers. By default, the user stack is located in the NDATA memory class and is accessed using DPP2.

The USERSTACKDPP3 directive allows you to locate the user stack in the IDATA or SDATA memory classes which are accessed using DPP3. When relocating the user stack, some changes must be made to the definition of the ?C_USERSTACK section in the startup code (STARTUP.A66 or START167.A66) as follows.

?C_USERSTACK   SECTION   DATA PUBLIC 'IDATA'

or

?C_USERSTACK   SECTION   DATA PUBLIC 'SDATA'

In addition, you must change the following line:

MOV     R0,#DPP2:?C_USERSTKTOP

to:

MOV     R0,#DPP3:?C_USERSTKTOP
Example
C166 myfile.c USERSTACKDPP3


C166: WARNING Compiler Directive

WARNING Compiler Directive

Abbreviation | WA
Arguments | A level and a numeric list of warning messages.
Default | None.
µVision | This directive may not be specified on the command line.
Description

The WARNING directive changes the level of individual compiler warnings. You may disable a selected warning, list it only once, or treat the warning message as an error. The WARNING directive also allows you to change the warning level in which the message is listed. Refer to Error Messages for a complete list of compiler warnings.

The WARNING directive has the following format:

WARNING level = warning « , warning »

where

level | is the level to which the warning is switched or a command that determines subsequent compiler action for the warning(s).
warning | is the number of the warning message to modify.

Following are valid values for level:

Level | Description
0 | Changes the warning level to 0.
1 | Changes the warning level to 1.
2 | Changes the warning level to 2.
3 | Changes the warning level to 3.
disable | Disables the warning.
error | Converts the warning to an error.
once | Lists only the first occurrence of the warning.
See Also | WARNINGLEVEL
Example
#pragma warning error = 95
   /* changes warning 95 to an error */

#pragma warning once = 56, 57
   /* report only the first occurrence */
   /* of warning 56 & 57 */


C166: WARNINGLEVEL Compiler Directive

WARNINGLEVEL Compiler Directive

Abbreviation | WL
Arguments | A number from 0-3.
Default | WARNINGLEVEL (2)
µVision | Options — C166 — Warnings.
Description

The WARNINGLEVEL directive suppresses certain compiler warnings based on the level of the warning. Refer to Error Messages for a complete list of compiler warnings.

Warning Level | Description
0 | Disables most compiler warnings.
1 | Lists only those warnings which may generate incorrect code.
2 (Default) | Lists all warnings about unused variables, expressions, or labels but excludes XC16x/C16x/ST10-specific warnings.
3 | Lists all warnings including XC16x/C16x/ST10-specific warnings.
See Also | WARNING
Example
C166 SAMPLE.C WL (1)

#pragma WARNINGLEVEL (0)


C166: XLARGE Compiler Directive

XLARGE Compiler Directive

Abbreviation | XLA
Arguments | None.
Default | SMALL
µVision | Options — Target — Memory Model.
Description

The XLARGE directive selects the xlarge memory model. The memory model affects the code generated by the compiler. In this memory model variables are accessed using xhuge addresses and functions are accessed using far addresses.

Note

  • This memory model is not supported by the orignal 80C166 microntroller and is only available with the enhanced C16x/ST10 instruction set. Using this memory model automatically sets the MOD167 directive.
See Also | COMPACT, HCOMPACT, HLARGE, HOLD, LARGE, MEDIUM, MOD167, SMALL, TINY
Example
C166 SAMPLE.C XLARGE

#pragma xlarge


C166: Language Extensions

Language Extensions

The C166 Compiler provides several extensions to ANSI Standard C to support the elements of the C16x/XC16x/ST10 architecture. These include extensions for:

  • Memory Types
  • Memory Models
  • Data Types
  • Bit Variables and Bit-Addressable Objects
  • Special Function Registers
  • Function Attributes


C166: Keywords

Keywords

To facilitate many of the features of the C16x, ST10, and XC16x devices, the C166 Compiler adds a number of new keywords to the scope of the C language:

__asm
bdata
bit
ebdata
far
huge 		idata
interrupt
__inline
near
_priority_
sbit 		sdata
sfr
_task_
using
xhuge

You may disable these extensions using the NOEXTEND directive. Refer to Compiling Programs for more information.


C166: Memory Models

Memory Models

The memory model determines the default memory type to use for variables and functions. The C166 Compiler provides seven memory models as shown in the following table:

Directive | Memory Model | Variable Addresses | Function Addresses
TINY | Tiny Model | near | near Up to 64K Code Size
SMALL | Small Model | near | near Up to 64K Code Size
MEDIUM | Medium Model | near | far Unlimited Code Size
COMPACT | Compact Model | far | near Up to 64K Code Size
LARGE | Large Model | far | far Unlimited Code Size
HCOMPACT | HCompact Model | huge | near Up to 64K Code Size
HLARGE | HLarge Model | huge | far Unlimited Code Size
XLARGE | XLarge Model | xhuge | far Unlimited Code Size

Note

  • You may override the default memory type imposed by the memory model by explicitly declaring a variable or function with a memory type specifier.


C166: Tiny Model

Tiny Model

The tiny memory model (selected with the TINY directive) uses the non-segmented mode of the C16x/ST10/XC16x microcontroller. In this memory model:

  • Variables are stored in near memory.
  • Functions are stored in near memory and are accessed using near calls.

This memory model generates efficient 16-bit linear addresses by limiting code and data space to 64K. The far, huge, and xhuge memory types are not allowed in this memory model.

This memory model is the best choice for programs that have small code and small data requirements and do not require access to additional address space.


C166: Small Model

Small Model

The small memory model (selected with the SMALL directive) uses the segmented mode of the C16x/ST10/XC16x microcontroller. This is the default memory model if no model is specified. In this memory model:

  • Variables are stored in near memory.
  • Functions are stored in near memory and are accessed using near calls.

This memory model provides the same efficient code as the Tiny Memory Model but code and data are not limited to 64K. You may locate variables and use functions with far, huge, and xhuge memory types which permit full use of the C16x/ST10 address capabilities.

This memory model is the best choice for programs that have small code and small data requirements but require access to more than 64K of address space.


C166: Medium Model

Medium Model

The medium memory model (selected with the MEDIUM directive) uses the segmented mode of the C16x/ST10/XC16x microcontroller. In this memory model:

  • Variables are stored in near memory.
  • Functions are stored in far memory and are accessed using far calls.

This memory model is the best choice for programs that have large code and small data requirements.


C166: Compact Model

Compact Model

The compact memory model (selected with the COMPACT directive) uses the segmented mode of the C16x/ST10/XC16x microcontroller. In this memory model:

  • Variables are stored in far memory when they require more space than defined by the HOLD directive.
  • Functions are stored in near memory and are accessed using near calls.

This memory model is the best choice for programs that have small code and large data requirements.


C166: Large Model

Large Model

The large memory model (selected with the LARGE directive) uses the segmented mode of the C16x/ST10/XC16x microcontroller. In this memory model:

  • Variables are stored in far memory when they require more space than defined by the HOLD directive.
  • Functions are stored in far memory and are accessed using far calls.

This memory model is the best choice for 80C166 programs that have large code and data requirements.


C166: HCompact Model

HCompact Model

The hcompact memory model (selected with the HCOMPACT directive) uses the segmented mode of the C16x/ST10/XC16x microcontroller. In this memory model:

  • Variables are stored in huge memory when they require more space than defined by the HOLD directive.
  • Functions are stored in near memory and are accessed using near calls.

This memory model is the best choice for C16x/ST10/XC16x programs that have small code and large data requirements.

Note

  • The HCOMPACT memory model is not available for 80C166 microcontrollers.


C166: HLarge Model

HLarge Model

The hlarge memory model (selected with the HLARGE directive) uses the segmented mode of the C16x/ST10/XC16x microcontroller. In this memory model:

  • Variables are stored in huge memory when they require more space than defined by the HOLD directive.
  • Functions are stored in far memory and are accessed using far calls.

This memory model is the best choice for C16x/ST10/XC16x programs that have large code and data requirements.

Note

  • The HLARGE memory model is not available for 80C166 microcontrollers.


C166: XLarge Model

XLarge Model

The xlarge memory model (selected with the XLARGE directive) uses the segmented mode of the C16x/ST10/XC16x microcontroller. In this memory model:

  • Variables are stored in xhuge memory when they require more space than defined by the HOLD directive.
  • Functions are stored in far memory and are accessed using far calls.

This memory model is the best choice for C16x/ST10/XC16x programs that have large code and data requirements.

Note

  • The XLARGE memory model is not available for 80C166 microcontrollers.


C166: Memory Types

Memory Types

The memory type of an object specifies into which memory area the object is stored. Some memory areas have fast access times but limited in the amount of space available while other memory areas are large but slow to access.

High-performance applications benefit from locating frequently-used variables in fast memory areas (like on-chip RAM). Large buffers and tables are typically located in larger memory areas (like external RAM or ROM). Refer to the HOLD directive for information on how to automatically locate variables based on size.

A number of memory types are available. Some memory types are selected by default for certain Memory Models. Other memory types are available for explicit variable declarations and are not tied to a specific memory model.

Type | Description
near Supports 16-bit pointers, 16-bit address calculation, and access to:
  • up to 16 KB for variables in the NDATA group,
  • up to 16 KB for constants in the NCONST group,
  • up to 16 KB for the system area in the SDATA group.

The DPPUSE linker directive allows up to 64 KB in the NDATA and NCONST groups.

If near is applied to a function, a 16-bit call instruction (CALLA or CALLR) is generated to call the function.

bdata | Bit-addressable on-chip RAM that supports mixed bit and byte accesses but is limited to 256 bytes.
idata | On-chip RAM that provides the fastest access to variables.
sdata | On-chip system area (address space 0C000h-0FFFFh) that may be used for Special Function Registers (SFRs) and PEC-addressable objects.
far | Supports 32-bit pointers, 16-bit address calculations, and access to the entire address space. The size of a single object (array or structure) is limited to 16 KB. If far is applied to a function, a segmented call instruction (CALLS) is generated when calling the function. far is the best memory type to use on the 80C166 microcontroller for accessing the 256KB address space.
huge | Supports 32-bit pointers, 16-bit address calculations, and access to the entire address space. The size of a single object (array or structure) is limited to 64 KB. huge is the best memory type on the C167/C165 microcontroller for accessing the 16MB address space.
xhuge | Supports 32-bit pointers, 32-bit address calculations, and access to the entire address space. The size of a single object (array or structure) is limited to 16MB. This memory model performs more slowly than the others.

The following examples show how to use memory types in variable declarations:

char idata var1;
static unsigned long far array [100];
extern float near x, huge y;
extern unsigned int huge vector[1000][10];
unsigned char sdata pec_buffer [100];
char bdata flags; sbit flag0 = flags^0;

The following example shows how to use a memory type in a function definition:

/*************************************************/
/* function with 'NEAR' CALL and RET instruction */
/*************************************************/
void near func1 (char *p)  {
*p = 1;
}

Note

  • The near memory type may be applied to static functions in the MEDIUM or LARGE memory models to speed up calls to the function and save stack space.


C166: near

near

The near memory type may be used for variables, constants, and functions. This memory is accessed using 16-bit addresses and may be on-chip or external.

  • For variables, near memory is limited to 16K, objects are limited to 16K, and objects may not cross a 64K boundary. Variables declared near are located in the NDATA group.
  • For constants (ROM variables), near memory is limited to 16K, objects are limited to 16K, and objects may not cross a 64K boundary. Constant variables declared near are located in the NCONST group.
  • For program code (functions), near memory is limited to 64K. Program code declared near is stored in the NCODE group. Functions are invoked with the CALLA or CALLR instruction.

Note

  • The DPPUSE linker directive may be used to extend the amount of memory available to the NDATA and NCONST groups to a total of 64K.

Declare near objects as follows:

unsigned char near near_variable;

unsigned char const near near_const_variable;

unsigned int near near_func (void)
{
return (0);
}


C166: far

far

The far memory type may be used for variables, constants, and functions. This memory is accessed using 32-bit addresses and may be on-chip or external.

  • For variables, far memory is limited to 16M, objects are limited to 16K, and objects may not cross a 64K boundary. Variables declared far are located in the FDATA group.
  • For constants (ROM variables), far memory is limited to 16M, objects are limited to 16K, and objects may not cross a 64K boundary. Constant variables declared far are located in the FCONST group.
  • For program code (functions), far memory is limited to 16M. Program code declared far is stored in the FCODE group. Functions are invoked with the CALLS instruction.

Declare far objects as follows:

unsigned char far far_variable;

unsigned char const far far_const_variable;

unsigned int far far_func (void)
{
return (0);
}


C166: bdata

bdata

The bdata memory type may be used to declare variables only. You may not declare bdata functions. This memory is accessed using 16-bit addresses and is the on-chip bit-addressable memory of the C16x/ST10/XC16x. This memory (which is limited to 512 bytes) may be accessed as bytes or as bits.

Variables declared bdata are located in the SDATA group.

Declare bdata variables as follows:

unsigned int bdata ba_var;

Declare bits within a bdata variable as follows:

sbit ba_bit_0 = ba_var ^ 0;    /* Bit 0 of ba_var */
sbit ba_bit_8 = ba_var ^ 8;    /* Bit 8 of ba_var */


C166: ebdata

ebdata

The ebdata memory type may be used to declare variables only. You may not declare ebdata functions. This memory is accessed using 16-bit addresses and is the on-chip extended bit-addressable memory of the C16x/ST10/XC16x. This memory (which is limited to 512 bytes) may be accessed as bytes or as bits.

Variables declared ebdata are located in the SDATA group.

Declare ebdata variables as follows:

unsigned int ebdata eb_var;

Declare bits within an ebdata variable as follows:

struct s  {
  unsigned int b0:1;
  unsigned int b1:1;
  unsigned int b2:1;
  unsigned int b3:1;
  unsigned int b4:1;
  unsigned int b5:1;
  unsigned int b6:1;
  unsigned int b7:1;
};

struct s ebdata  v;

void main (void)  {
  if (v.b1)  {
    v.b0 = 1;
  }
}

You may use ebdata variables to access extended SFRs by:

  1. Defining the SFRs in a C source file,
  2. Compiling the file using the ORDER directive,
  3. and Using the SECTIONS linker directive to locate the SFR definitions to the appropriate address. For example:
    L166 ... SECTIONS(?EB?SFRBIT%EBDATA(0F100H), ?BD?SFRBIT%BDATA(0FF00H))

    4. Note

    • All SFRs (including extended SFRs) are defined in the SFR Definitions Files for each supported microcontroller. While it is possible to do, there is no need to use the ebdata type to define SFRs.


C166: idata

idata

The idata memory type may be used to declare variables only. You may not declare idata functions. This memory is accessed using 16-bit addresses and is on-chip RAM of the C16x/ST10/XC16x. It has the shortest (fastest) access time but the amount of idata is limited in size.

Variables declared idata are located in the SDATA group.

Declare idata variables as follows:

unsigned char idata fast_variable;


C166: sdata

sdata

The sdata memory type may be used to declare variables only. You may not declare sdata functions. This memory is accessed using 16-bit addresses and is on-chip system memory of the C16x/ST10/XC16x. It is typically composed of SFRs and PEC-addressable objects.

Variables declared sdata are located in the SDATA group.

Declare sdata variables as follows:

unsigned char sdata pec_var;


C166: huge

huge

The huge memory type may be used for variables, constants, and functions. This memory is accessed using 32-bit addresses and may be on-chip or external.

  • For variables, huge memory is limited to 16M, objects are limited to 64K, and objects may not cross a 64K boundary. Variables declared huge are located in the HDATA group.
  • For constants (ROM variables), huge memory is limited to 16M, objects are limited to 64K, and objects may not cross a 64K boundary. Constant variables declared huge are located in the HCONST group.
  • For program code (functions), huge memory is limited to 16M. Program code declared huge is stored in the FCODE group. Functions are invoked with the CALLS instruction.

Declare huge objects as follows:

unsigned char huge huge_variable;

unsigned char const huge huge_const_variable;

unsigned int huge huge_func (void)
{
return (0);
}


C166: xhuge

xhuge

The xhuge memory type may be used for variables, constants, and functions. This memory is accessed using 32-bit addresses and may be on-chip or external.

  • For variables, xhuge memory is limited to 16M as are xhuge objects. Variables declared xhuge are located in the XDATA group.
  • For constants (ROM variables), xhuge memory is limited to 16M as are xhuge objects. Constant variables declared xhuge are located in the XCONST group.
  • For program code (functions), xhuge memory is limited to 16M. Program code declared xhuge is stored in the FCODE group. Functions are invoked with the CALLS instruction.

Declare xhuge objects as follows:

unsigned char xhuge xhuge_variable;

unsigned char const xhuge xhuge_const_variable;

unsigned int xhuge xhuge_func (void)
{
return (0);
}


C166: Memory Type Comparison

Memory Type Comparison

When accessing near (bdata, ebdata, idata, and sdata), far, huge, and xhuge variables, the C166 Compiler either generates instructions or calls library routines depending on the device and size of object accessed. Library routines are called when there are no memory type-specific instructions available.

Memory Type | 80C166 Access | C16x/XC16x Access
near All Objects | Instructions | Instructions
far All Objects | Instructions | Instructions
huge All Objects | Library Routines | Instructions
xhuge Byte/Word Objects | Library Routines | Instructions
xhuge DWord and Larger Objects | Library Routines | Library Routines

The following examples show the code generated for different memory type accesses on the 80C166 and C16x/XC16x devices. The comparisons show the effects of different memory types on 80C166 and C16x/XC16x instructions and help you estimate the size of the code generated.

near Memory Access

unsigned int j;
unsigned int ui;
unsigned int near near_uiarray [10];

i = near_array [j];
80C166 Code C16x/XC16x Code
MOV R4,j
SHL R4,#01H
MOV R4,[R4+#near_uiarray]
MOV ui,R4

MOV R4,j
SHL R4,#01H
MOV R4,[R4+#near_uiarray]
MOV ui,R4

far Memory Access

unsigned int j;
unsigned int ui;
unsigned int far far_uiarray [10];

i = far_array [j];
80C166 Code C16x/XC16x Code
MOV R4,j
SHL R4,#01H
MOV DPP0,#PAG (far_uiarray)
NOP       ; pipeline effect
MOV R4,[R4+#far_uiarray]

MOV ui,R4

MOV  R4,j
SHL  R4,#01H
EXTP #PAG (far_uiarray),#01H

MOV  R4,[R4+#POF(far_uiarray)]
MOV  ui,R4

huge Memory Access

unsigned int j;
unsigned int ui;
unsigned int huge huge_uiarray [10];

i = huge_array [j];
80C166 Code C16x/XC16x Code
MOV   R4,j
SHL   R4,#01H
MOV   R2,#SOF (huge_uiarray)
MOV   R3,#SEG (huge_uiarray)
ADD   R2,R4
CALLA cc_UC,?C_HLOADI

MOV   ui,R4

MOV  R4,j
SHL  R4,#01H

EXTS #SEG (huge_uiarray),#01H
MOV  R4,[R4+#SOF(huge_uiarray)]
MOV  ui,R4

xhuge Memory Access
Byte/Word Objects

unsigned int j;
unsigned int ui;
unsigned int xhuge xhuge_uiarray [10];

i = xhuge_array [j];
80C166 Code C16x/XC16x Code
MOV   R4,j
MOV   R5,#00H
ADD   R4,R4
ADDC  R5,R5
MOV   R2,#SOF (xhuge_uiarray)
MOV   R3,#SEG (xhuge_uiarray)
ADD   R2,R4
ADDC  R3,R5
CALLA cc_UC,?C_HLOADI

MOV   ui,R4

MOV  R4,j
MOV  R5,#00H
ADD  R4,R4
ADDC R5,R5

MOV  R6,R4
MOV  R7,R5
MOV  R4,#SOF (xhuge_uiarray)
MOV  R5,#SEG (xhuge_uiarray)
ADD  R4,R6
ADDC R5,R7
EXTS R5,#01H
MOV  R4,[R4]
MOV  ui,R4

xhuge Memory Access
DWord and Larger Objects

unsigned int j;
unsigned long ul;
unsigned long xhuge xhuge_ularray [10];

i = xhuge_larray [j];
80C166 Code C16x/XC16x Code
MOV   R5,#00H
ADD   R4,R4
ADDC  R5,R5
ADD   R4,R4
ADDC  R5,R5
MOV   R2,#SOF (xhuge_ularray)
MOV   R3,#SEG (xhuge_ularray)
ADD   R2,R4
ADDC  R3,R5
CALLA cc_UC,?C_HLOADL
MOV   ul,R4
MOV   ul+02H,R5

MOV   R5,#00H
ADD   R4,R4
ADDC  R5,R5
ADD   R4,R4
ADDC  R5,R5
MOV   R2,#SOF (xhuge_ularray)
MOV   R3,#SEG (xhuge_ularray)
ADD   R2,R4
ADDC  R3,R5
CALLA cc_UC,?C_HLOADL
MOV   ul,R4
MOV   ul+02H,R5


C166: Pointers with Memory Types

Pointers with Memory Types

Memory types may used in pointer declarations to define the memory area of the object referenced or even the memory area where the pointer is located. In general, pointers should be declared according to the following rules:

Variable Declaration | Pointer Size | Pointer Declaration
char c; 16/32-bit char *ptr;
(Pointer size depends on the memory model in use)
int near nc; | 16-bit | int near *np;
float sdata nf; 16-bit float sdata *sp;

or

float near *sp;
long bdata x; 16-bit long bdata *xp;

or

long near *xp;
char idata index; 16-bit char idata *ip;

or

char near *ip;
const char near n = 5; 16-bit char near *cp;
(const may be ignored)
unsigned long far l; | 32-bit | long far *lp;
char huge hc; | 32-bit | char huge *hc_ptr;
long xhuge xl; | 32-bit | char xhuge *hl_ptr;
void near func1 (void); | 16-bit | void (near *fp1) (void);
int far func2 (void); | 32-bit | int (far *fp2) (void);

NOTE:

  • Pointers to sdata, idata, or bdata objects may so be declared with the near memory type because a near pointer can hold the DPP for all objects that have a logical 16-bit address.
  • In the TINY model, the memory type for pointer declarations are unnecessary because each object is accessed via a 16-bit address.
  • near objects can be addressed with a far, huge, or xhuge pointer. The far, huge, or xhuge pointer access always yields DPP load or EXTS/EXTP instructions.
  • A near pointer access uses the pre-loaded DPP registers and cannot be used to address a far, huge, or xhuge object.

The following examples illustrate several different declaration types:

char near *px

This example declares a pointer that refers to a char type object in near memory. The pointer is stored in the default memory area. The *px pointer has a size of 2 bytes.

char near *idata pdx

This example is similar to the char near *px except the pointer is placed into the internal data memory (idata) regardless of the memory model used.

struct time  { char hour; char min; char sec; struct time near *pxtime; }

This example contains a pointer, pxtime, that refers to another structure that must be located in the near memory type (near, idata, sdata, or bdata). The pxtime pointer has a size of 2 bytes.

struct time far *ptime

This example defines a pointer stored in the default memory type and refers to a structure time located in the far memory type. The ptime pointer has a size of 4 bytes.

ptime->pxtime->hour = 12

This example uses the prior two declarations; however, the pxtime pointer is indirectly loaded from the structure. The pxtime pointer refers to the structure time, which is located in the near memory type. The value 12 is assigned to the member hour in this structure.


C166: Implicit Memory Types

Implicit Memory Types

Variables declared without a memory type specifier are stored in the default or implicit memory area. Function arguments and automatic variables that cannot be allocated to MCU registers are also stored in the default memory area.

The default memory type is determined by the memory model selected. For global variables, the HOLD directive allows you to specify size limits and alternative implicit memory spaces.


C166: Type Qualifiers

Type Qualifiers

The C166 Compiler supports two type qualifiers: const and volatile.

  • The const type qualifier declares an object that is not changed at run-time.
  • The volatile type qualifier declares an object whose value may be changed by something external to the code in which it appears. In an embedded system this would typically be hardware.


C166: const

const

In ANSI C, the const type qualifier is used to define and access objects that are constant and that may not be changed. A variable that is declared with const may not be assigned to in the program.

The C166 Compiler extends the ANSI definition of const objects to mean that they are stored in read-only or ROM memory. Objects you want to locate in ROM must be declared with the const type qualifier. For example:

const char test[] = "This is a text string";

Constant objects are typically initialized when they are defined (in your source files). They are placed into a CONST class which is typically located in ROM space by the linker.

The const type qualifier may be combined with the memory types near, far, and huge to specify three different CONST areas:

  • NCONST (for near constants),
  • FCONST (for far constants),
  • and HCONST (for huge constants).

The following variable definitions show different ways to create constant objects:

/* table is stored in the default memory type const class */
const int table[2][2] =
  { 0, 2, 4, 8 };

/* pi is stored in the FCONST class */
const float far pi = 3.1415927;

/* vectors is stored in the HCONST class */
const long xhuge vectors[10000] =
  { 1, 67890 };

/* mask is stored in the NCONST class */
const unsigned char near mask [] =
  { 0x01, 0x02, 0x04, 0x08 };

When using pointers to const objects, you may exclude the const type qualifier in the pointer definition. For example:

const unsigned char near mask [] =
  { 0x01, 0x02, 0x04, 0x08 };

const unsigned char near *cp = mask;
      unsigned char near  *p = mask;  /* same as cp */

.
.
.

*p = 'a';    // This has no effec.
             // It causes no error or warning

*cp = 'a';   // This causes an error

As shown, it is possible to assign the address of a const object (mask) to a non-const pointer (p) and subsequently use the pointer to change the const object. In this case, the compiler does generate code to write to the const object. The effects of this code is undefined and may or may not work as expected.

It is not possible to use a const pointer to change the const object it points to. Attempts to do so will cause a compiler error.

An interesting use of const is to define a pointer that may not be changed. For example:

char near text [] = "This is a string.";
char *const near textp = text;
.
.
.
*textp = 'A';    // This is OK (it changes text[0])
textp++;         // This causes an error (textp is const)
textp[2] = 'B';  // This is OK (it changes text[2])

In this case, the C166 Compiler locates text in the NEAR class and textp in the NCONST class. When the pointer is declared this way, it may not be changed.


C166: volatile

volatile

The volatile type qualifier is used to restrict assumptions the compiler makes about object values. For example:

unsigned char reg1;   // Hardware Register #1
unsigned char reg2;   // Hardware Register #2

void func (void)
{
while (reg1 & 0x01)   // Repeat while bit 0 is set
  {
  reg2 = 0x00;        // Toggle bit 7
  reg2 = 0x80;
  }
}

This program uses two variables (reg1 and reg2) to access hardware registers. In most cases, the compiler loads reg1 into a register and does not re-read it between loop iterations (even though the hardware register may be changing). In addition, the three assignments to reg2 may simply be optimized to the final assignment (no code is generated for the first two assignments).

These effects are caused by the optimizer and are not bugs generated by the compiler. In fact, these are the types of optimizations the compiler should make. However, in this case they are certainly undesirable.

The volatile type qualifier was introduced to solve these types of problems. For example:

volatile unsigned char reg1;   // Hardware Register #1
volatile unsigned char reg2;   // Hardware Register #2

void func (void)
{
while (reg1 & 0x01)   // Repeat while bit 0 is set
  {
  reg2 = 0x00;        // Toggle bit 7
  reg2 = 0x80;
  }
}

By defining reg1 and reg2 as volatile, the compiler now knows that accesses to these variables may not be optimized out. The resulting code executes as desired.


C166: Data Types

Data Types

The C166 Compiler provides several basic data types you may use in your C programs. The compiler supports the standard C data types as well as several data types that are unique to the C16x/ST10/XC16x platform.

Data Type | Bits | Bytes | Value Range
bit | 1 |  | 0 or 1
signed char | 8 | 1 | -128 to +127
unsigned char | 8 | 1 | 0 to 255
enum | 8 / 16 | 1 or 2 | -128 to +127 or -32768 to +32767
signed short | 16 | 2 | -32768 to +32767
unsigned short | 16 | 2 | 0 to 65535
signed int | 16 | 2 | -32768 to +32767
unsigned int | 16 | 2 | 0 to 65535
signed long | 32 | 4 | -2147483648 to +2147483647
unsigned long | 32 | 4 | 0 to 4294967295
float | 32 | 4 | ±1.175494E-38 to ±3.402823E+38
double | 64 | 8 | ±1.7E-308 to ±1.7E+308
sbit | 1 |  | 0 or 1
sfr | 16 | 2 | 0 to 65535

Note

  • The bit, sbit, and sfr data types are not provided in ANSI C and are specific to the C166 Compiler.


C166: Special Function Registers

Special Function Registers

The C16x/ST10/XC16x families of microcontrollers provide distinct memory areas for accessing Special Function Registers (SFRs). SFRs are used in your program to control on-chip peripherals like timers, counters, and I/O ports.

SFRs reside from address 0xFE00-0xFFDE and 0xF000-0xF1DE. They may be accessed as bits, bytes, and words. Within the C16x/ST10/XC16x microcontroller families, the number and type of SFRs vary widely. For more information about SFRs refer to the data book for the device you use.

The C166 Compiler provides a number of include files for various C16x/ST10/XC16x derivatives. Each file contains declarations for the SFRs available on that device. Refer to SFR Definitions for more information about the available include files.

The C166 Compiler provides access to SFRs with the sfr and sbit data types.

Note

  • No SFR names are predefined by the C166 Compiler.


C166: sfr Types

sfr Types

SFRs are declared in the same fashion as other C variables. The only difference is that the data type specified is sfr rather than char or int. For example:

sfr P0 = 0xFF00;    /* Port-0, address FF00h */
sfr P1 = 0xFF04;    /* Port-1, address FF04h */

Names for sfr types are defined using the same method as other C variables. In the above example, P0 and P1 are the SFR name declarations. Any symbolic name may be used in an sfr declaration.

The address specification after the equal sign ('=') must be a numeric constant. Expressions with operators are not allowed. This constant must lie in the SFR address range 0xFE00-0xFFDE or in the extended SFR address range 0xF000-0xF1DE (for C167 family devices).


C166: sbit Types

sbit Types

The sbit keyword allows you to define objects that access individual bits of bit-addressable SFRs and bit-addressable objects. For example:

sbit IEN = PSW ^ 11;

defines IEN as an SFR bit at bit 11 of the PSW. On the C16x/ST10 microcontroller, this is the global interrupt enable bit in the PSW register.

Any symbolic name may be used in an sbit declaration. The expression to the right of the equal sign ('=') specifies an absolute bit address for the symbolic name. Two variations of this definition are possible:

Variant 1

sbit name = sfr-name ^ bit-position;

The previously declared SFR (sfr-name) is the base address for the sbit. The bit-position (which must be a number from 0-15) follows the carat symbol ('^') and specifies the bit position to access. For example:

sfr  PSW   = 0xFF10;
sbit USR0  = PSW ^ 6;
sfr  ADCON = 0xFFA0;
sbit ADBSY = ADCON ^ 8;

Variant 2

sbit name = sfr-address ^ bit-position;

An integer constant (sfr-address) specifies the base address for the sbit. The bit-position (which must be a number from 0-15) follows the carat symbol ('^') and specifies the bit position to access. For example:

sbit ADBSY = 0xFFA0 ^ 8;
sbit USR0  = 0xFF10 ^ 6;

Note

  • Special function bits represent an independent declaration class that is not interchangeable with other bit declarations or bit fields.
  • The sbit data type declaration may be used to access individual bits of variables declared with the bdata memory type specifier. Refer to Bit-Addressable Objects for more information.


C166: bit Types

bit Types

The C166 Compiler provides a bit data type that may be used for variable declarations, argument lists, and function return values. A bit variable is declared just as other C data types are declared. For example:

static bit done_flag = 0;    /* bit variable */

bit testfunc (               /* bit function */
  bit flag1,                 /* bit arguments */
  bit flag2)
{
.
.
.
  return (0);                /* bit return value */
}

All bit variables are stored in a bit segment located in the bit memory area of the C16x/ST10. This area is only 256 bytes long, so, a maximum of 2048 bit variables may be declared within any one scope.

Automatic bit variables are stored in register R14 and R15 and limited to a maximum of 32 automatic bits inside a function.

Note

  • Functions that disable interrupts (using #pragma disable) and functions that that use explicit register banks (with the using function attribute) may not return a bit value. The C166 Compiler generates an error if functions of this type attempt to return a bit.
  • A bit may not be declared as a pointer. For example:
    bit *ptr;          /* invalid */
  • An array of type bit is invalid. For example:
    bit ware [5];      /* invalid */


C166: Bit-Addressable Objects

Bit-Addressable Objects

Bit-addressable objects are objects that can be addressed as words or as bits. Only data objects that occupy the bit-addressable area (bdata) of the C16x/ST10 internal memory fall into this category.

The C166 Compiler places variables declared with the bdata memory type into the on-chip bit-addressable area. Variables declared with the bdata type must be global. You may declare these variables as follows:

int bdata ibase;        /* Bit-addressable int */

char bdata bary [4];    /* Bit-addressable array */

The variables ibase and bary are bit-addressable and the individual bits of these variables can be directly accessed and modified. Use the sbit keyword to declare new variables that access the bits of variables declared using bdata.

The following example shows declarations, not assignments, to the bits of the ibase and bary variables.

sbit mybit0 = ibase ^ 0;      /* bit 0 of ibase */
sbit mybit15 = ibase ^ 15;    /* bit 15 of ibase */

sbit Ary07 = bary[0] ^ 7;     /* bit 7 of bary[0] */
sbit Ary37 = bary[3] ^ 7;     /* bit 7 of bary[3] */

The expression following the carat symbol ('^') in the example, specifies the position of the bit to access with this declaration. The expression must be a constant value. The range depends on the type of the base variable included in the declaration. The range is 0-7 for char and unsigned char, 0-15 for int, unsigned int, short, and unsigned short, and 0-31 for long and unsigned long.

You may provide external variable declarations for the sbit type to access these types in other modules. For example:

extern bit mybit0;      /* bit 0 of ibase */
extern bit mybit15;     /* bit 15 of ibase */

extern bit Ary07;       /* bit 7 of bary[0] */
extern bit Ary37;       /* bit 7 of bary[3] */

Declarations involving the sbit type require that the base object is declared with the bdata memory type. The only exceptions are the special function register bits. Refer to sfr Types for more information.

The following example shows how to change the ibase and bary bits using the above declarations.

Ary37 = 0;        /* clear bit 7 in bary[3] */
bary[3] = 'a';    /* Byte addressing */
ibase = -1;       /* Word addressing */
mybit15 = 1;      /* set bit 15 in ibase */

The bdata memory type is handled like the idata memory type except that variables declared with bdata reside in the bit-addressable portion of the on-chip data memory. Note that the total size of this area of memory cannot exceed 256 bytes.

In addition to declaring sbit variables for scalar types, you may also declare sbit variables for structures and unions. For example:

union lft
  {
  float mf;
  long ml;
  };

bdata struct bad
  {
  char m1;
  union lft u;
  } tcp;

sbit tcpf31 = tcp.u.ml ^ 31;        /* bit 31 of float */
sbit tcpm10 = tcp.m1 ^ 0;
sbit tcpm17 = tcp.m1 ^ 7;

Note

  • You may not specify bit variables for the bit positions of floating-point variable types. However, you may include floating-point types and integer types in a union and declare bit variables to access the bits in the integer part of the union.


C166: Function Declarations

Function Declarations

The C166 Compiler provides a number of extensions for standard C function declarations. These extensions allow you to:

  • Declare a function as an interrupt procedure.
  • Choose the register bank used.
  • Select the memory area where the function is stored.
  • Declare a function as a real-time task function.

You may include these extensions or attributes (many of which may be combined) in the function declaration. Use the following standard format for your C166 Compiler function declarations.

« type » funcname (« args ») « interrupt vector » « using bankname »

Where

type | is the type of the value returned from the function. If no type is specified, int is assumed.
funcname | is the name of the function.
args | is the argument list for the function.
interrupt | indicates that the function is an interrupt function.
vector | is the interrupt vector name or trap number.
using | specifies which register bank the function uses.
bankname | is the register bank name.

Descriptions of these attributes and other features are described in detail in the following sections.


C166: Return Values

Return Values

C functions (which are declared as follows) may return a single value with a specified type.

« type » funcname (« args »)

where:

type | is the type of the value returned from the function. If no type is specified, int is assumed.
funcname | is the name of the function.
args | is the argument list for the function.

Return values are always returned in registers depending on the return value type. The following table lists return types and the registers used for each.

Return Type | Register(s) | Description
bit | R4.0 |
signed char unsigned char | RL4 |
signed int unsigned int | R4 |
signed long unsigned long | R4-R5 | LSB in R4, MSB in R5.
float | R4-R5 | 32-bit IEEE format, exponent and sign in R5.
double | R4-R7 | 64-bit IEEE format, exponent and sign in R7.
near (2-byte) pointer | R4 |
far (4-byte) pointer huge (4-byte) pointer | R4-R5 | Offset in R4, selector in R5.


C166: Register Bank

Register Bank

The C16x/ST10/XC16x microcontroller families support multiple register banks that must be located in on-chip RAM. The C166 Compiler allows you to define up to 128 register banks of 16 registers (R0-R15). The base address of the currently active register bank is specified in the context pointer (CP) SFR.

If a function is declared with the using attribute, a new register bank is selected on entry to the function and the previous register bank is restored when the function exits. The compiler generates the code necessary to change and restore the register bank.

There are several advantages to using more than one register bank. Using multiple register banks enhances the performance of interrupt procedures and real-time programs. If the active register bank is exchanged when an interrupt or context switch occurs, only the Context Pointer must be saved. Otherwise, the whole register bank must be saved before the interrupt procedure or task can execute.

The using function attribute is used to specify which register bank a function uses. For example:

« type » funcname (« args ») using bankname

Where

type | is the type of the value returned from the function. If no type is specified, int is assumed.
funcname | is the name of the function.
args | is the argument list for the function.
using | specifies which register bank the function uses.
bankname | is the register bank name.

You may use the same register bank in more than one function. It is common practice to use the same register bank name for interrupt procedures defined with the same interrupt priority level. It is possible to use the same name because interrupt functions with the same priority level cannot interrupt each other. Therefore, the register bank is not in use when the interrupt occurs. For example:

void rb_func (void) using my_rbank  {
.
.
.
}

In the above example, using my_rbank specifies that my_rbank is the name of the active register bank during the execution of the function rb_func. There are no restrictions or required naming conventions for the register bank name. Memory for the register bank is automatically allocated and located by the linker.

The using attribute affects the generated object code as follows:

  1. The current CP is saved on the stack when the function is entered.
  2. The CP is set to point to the specified register bank.
  3. When the function exits the saved CP value is restored.

The following listing shows the code generated for the using attribute:

stmt level    source
   1
   2          extern bit alarm;
   3          int alarm_count;
   4          extern void alfunc (bit b0);
   5
   6          void falarm (void) using f_registers  {
   7   1        alarm_count++;
   8   1        alfunc (alarm = 1);
   9   1      }

ASSEMBLY LISTING OF GENERATED OBJECT CODE
             ; FUNCTION falarm (BEGIN  RMASK = @0x3FFF)
0000 F6F00000 R    MOV     f_registers,R0
0004 C6090000 R    SCXT    CP,#f_registers
0008 CC00          NOP
                                           ; SOURCE LINE # 6
                                           ; SOURCE LINE # 7
000A 248F0000 R    SUB     alarm_count,ONES
                                           ; SOURCE LINE # 8
000E 0F00     E    BSET    alarm
0010 CA000000 E    CALLA   cc_UC,alfunc
                                           ; SOURCE LINE # 9
0014 FC09          POP     CP
0016 CB00          RET
             ; FUNCTION falarm (END    RMASK = @0x3FFF)

Note

  • The using attribute is not allowed when declaring or prototypeing external functions. For example, the following function prototype is invalid:
    extern int func (void) using my_regbank;


C166: Register Mask

Register Mask

The C166 Compiler supports register masks for function prototypes and external function declarations. The register mask specifies which registers are modified by the function. The register mask is used by the compiler to optimize registers used in the code generated.

The following example shows the definition of a register mask:

« extern » « type » funcname (« args ») @mask

The reg_mask is a 16-bit number that specifies the register modified by this function. Each bit in the reg_mask refers to one C16x/ST10 register. The encoding is as follows:

Bit Position
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
-- | DPP3 | MDx | R12 | R11 | R10 | R9 | R8 | R7 | R6 | R5 | R4 | R3 | R2 | R1 | DPP0

  • DPP3 is the DPP3 register used in copy and compare functions for memory images and strings.
  • MDx is the MDL, MDH, and MDC register which is used for multiplication and division.
  • R1-R12 are the registers R1-R12. R13, R14, and R15 are saved by the called function and the saved contents are never altered for the caller.
  • DPP0 is the DPP0 register that is used for far, huge, and xhuge accesses.

Two special values of the register mask specify all register or no registers:

  • 0 (zero) specifies that the function uses all registers. This is the default if the function prototype does not specify a register mask.
  • 0x8000 specifies that the function uses no registers. This value is useful for functions like exit that never return to the caller.

The C166 Compiler displays the register mask for each function in the assembly listing (generated by the CODE directive) included in the listing file. The register mask (RMASK) is printed at the beginning and at the end of the function.

Note

  • Register mask specifications assist the compiler in generating code with calls to external functions or with forward calls to functions. They are only included for backwards compatibility with C166 Version 1 programs and should not be used for new projects.
  • Register masks are provided for compatibility with C166 Version 1 programs. Use the REGFILE compiler directive and REGFILE linker directive to enable global register optimization which automatically creates register masks definitions.


C166: Interrupt Functions

Interrupt Functions

The C166 Compiler allows you to write interrupt function in the C language which eliminates the need for assembly language interrupt routine. For example:

void funcname (void) interrupt vector « using bankname »

Where

funcname | is the name of the function.
interrupt | indicates that the function is an interrupt function.
vector | is the interrupt vector name or trap number.
using | specifies which register bank the function uses.
bankname | is the register bank name.

The interrupt attribute requires an interrupt vector argument. You may specify an arbitrary interrupt name (whose trap number is specified by the linker INTNO directive), a trap number, or both for the vector. For example:

  • trap_number
  • interrupt_name
  • interrupt_name = trap_number

Where

trap_number is the interrupt vector address divided by 4.

The interrupt attribute affects the object code of the function as follows:

  • On function entry the contents of the SFRs MDC, MDL and MDH (when required) are saved on the stack.
  • If a register bank is specified by the using attribute, the context pointer is saved and the new register bank is selected. Otherwise, all the working registers (Rnn) used during the interrupt function are saved on the stack.
  • When exiting the function all register contents saved on the stack are restored.
  • The RETI instruction (return from interrupt) terminates the function.

The following sample program shows how to use the interrupt attribute and displays the code sequences detailing the prologue and epilogue for this example function. A using attribute is also specified in the example. The generated code switches register banks using the CP register. For example:

stmt level    source

   1          extern bit alarm;
   2          int alarm_count;
   3          extern void alfunc (bit b0);
   4
   5          void falarm (void) interrupt 0x21 using f_regs  {
   6   1        alarm_count++;
   7   1        alfunc (alarm = 1);
   8   1      }

ASSEMBLY LISTING OF GENERATED OBJECT CODE

             ; FUNCTION falarm (BEGIN  RMASK = @0x7FFF)
                                           ; SOURCE LINE # 5
0000 C6030300      SCXT    DPP3,#03H
0004 CC00          NOP
0006 F6F00000 R    MOV     f_regs,R0
000A C60800C0 R    SCXT    CP,#f_regs
000E CC00          NOP
0010 EC00          PUSH    DPP0
0012 C6871000      SCXT    MDC,#010H
0016 EC06          PUSH    MDH
0018 EC07          PUSH    MDL
                                           ; SOURCE LINE # 6
001A 248F0000 R    SUB     alarm_count,ONES
                                           ; SOURCE LINE # 7
001E 0FFF          BSET    R15.0
0020 4AFF0000 E    BMOV    alarm,R15.0
0024 CA000000 E    CALLA   cc_UC,alfunc
                                           ; SOURCE LINE # 8
0028 FC07          POP     MDL
002A FC06          POP     MDH
002C FC87          POP     MDC
002E FC00          POP     DPP0
0030 FC08          POP     CP
0032 FC03          POP     DPP3
0034 FB88          RETI
             ; FUNCTION falarm (END    RMASK = @0x7FFF)

Note

  • The interrupt attribute is not allowed when declaring or prototyping external functions. For example, the following function prototype is invalid:
    extern void func (void) interrupt 12;
  • Passing parameters to an interrupt function is not possible. Any attempt to define an interrupt function with arguments generates an error message.
  • Interrupt function declarations may not include a return value. They must be declared with a void return type. The compiler generates an error message if an attempt to define a return value for the interrupt function is made.
  • Your program may not directly invoke an interrupt function. If your program must invoke an interrupt you may use the _trap_ library routine. The _trap_ routine is required to avoid hardware side-effects caused by the RETI instruction that terminates the interrupt function.
  • Interrupt vectors are generated by the linker if a trap number is specified in the interrupt definition. The interrupt vector contains a jump to the interrupt function. You may suppress linker generation of vectors with the NOVECTAB linker directive.
  • All C166 library routines (except serial I/O and memory allocation) are fully reentrant and impose no restrictions on interrupt routines.
  • The C166 Compiler places automatic variables on the stack. Subsequently, C functions that use only automatic variables are reentrant.
  • The compiler never generates absolute addresses for register accesses. Each function is independent of the register bank in use. Therefore, interrupt functions may call any standard C function without restriction.

Note

  • If your interrupt functions are fairly small, it is often more efficient to avoid the using attribute and allow the C166 Compiler to PUSH and POP the registers that are actually used. You may use the CODE compiler directive to compare the code generated with and without the using attribute.


C166: Fast Interrupts

Fast Interrupts

In addition to standard interrupts, XC16x and Super10 devices provide high-speed interrupts which offer:

  • Cached interrupt vectors that require no JMPS instruction in the interrupt vector table.
  • Fast register bank switching (either by setting the PSW.BANK field or by using the BNKSELx SFR registers).

Note

  • Both cached interrupt vector and fast register bank switching may be used on the same interrupt service routine.


C166: Cached Vectors

Cached Vectors

The C166 Compiler allows you to create cached interrupts in C. These interrupts execute more quickly than standard interrupts and are declared as follows:

void funcname (void) interrupt name=CACHED « using bankname »

Where

funcname | is the name of the function.
interrupt | indicates that the function is an interrupt function.
name | may be any name you choose for the interrupt vector.
CACHED | specifies that the interrupt is a fast interrupt.
using | specifies which register bank the function uses.
bankname | is the register bank name.

When you define a fast interrupt using the CACHED keyword, you must use the FINTxCSP and FINTxADDR SFRs to specify the interrupt routine to the MCU. For example:

/* Macros to get the function segment and offset */
#define SEG(func) (unsigned int)(((unsigned long)((void (far *) (void))func)>> 16))
#define SOF(func) (unsigned int)(((void (far *) (void))func))

/* The fast interrupt service routine */
void serial_TX_irq (void) interrupt S0TINT=CACHED
{
ASC0_TBUF = 'A';
}
.
.
.
/* Configure the FINT0... SFRs to use serial_TX_irq */
FINT0CSP = 0x8800 | SEG(serial_TX_irq);
FINT0ADDR = SOF(serial_TX_irq);


C166: Fast Register Banks

Fast Register Banks

Fast register bank switching may be used by interrupt service routines that must execute quickly. When enabled, register banks are switched using the PSW or BNKSELx SFR. Use the using keyword to specify fast register bank switching. For example:

void funcname (void) interrupt vector « using fastbank »

Where

funcname | is the name of the function.
interrupt | indicates that the function is an interrupt function.
vector | is the interrupt vector name or trap number.
using | specifies which register bank the function uses.
fastbank specifies the type of fast bank switching using the following options:
  • _FAST_BANK1_: PSW.BANK is used to select fast bank 1.
  • _FAST_BANK2_: PSW.BANK is used to select fast bank 2.
  • _FAST_ABANK1_: BNKSELx is used to select fast bank 1.
  • _FAST_ABANK2_: BNKSELx is used to select fast bank 2.

For example:

void my_isr (void) interrupt my_interrupt using _FAST_ABANK1_  {
  /* interrupt code goes here */
}


C166: Inline Functions

Inline Functions

The C166 Compiler supports inline functions using the __inline keyword. For example:

__inline « type » funcname (« args »)

Where

__inline | specifies that the function is an inline function.
type | is the type of the value returned from the function. If no type is specified, int is assumed.
funcname | is the name of the function.
args | is the argument list for the function. Functions with variable argument lists cannot be expanded as inline code.

Code generated for inline functions is expanded in-line inside the calling function. This has the benefit of reduced call overhead at the expense of increased code size.

There are several rules that apply to inline functions. These rules become especially important to consider when inline functions call other inline functions.

  1. Function in-lining is performed on an expression statement boundary where the right side operator is a function call. For example:
    z = iFunc (z1, z2);       // in-lined:
                          //   first operation is a call
z = iFunc (z1, z2) * 11;  // not in-lined:
                          //   first operation is a multiply
z = iFunc (z1, z2) + 2;   // not in-lined:
                          //   first operation is an add
  2. Expressions with for statements are never in-lined. For example:
    for (z = iFunc (z1, z2) ; z != 0 ; )   // iFunc is not in-lined
{ ... }
  3. Inline functions that call no other functions and inline functions that call only inline functions are in-lined as long as the above rules are fulfilled.
    static __inline int yFunc (int n)  {
  return (n + 10);
}

static int zFunc (int n)  {
  return (n + 10);
}

static __inline int iFunc (int i, int y)  {
  i += y;
  i += yFunc (y);
  i *= zFunc (i);

// Note: i += y + yFunc * zFunc (i): is not in-lined

  return (i);
}

static int z, z1, z2;

void main (void)  {
  z = iFunc (z1, z2);           // in-lined
  z = z2 + iFunc (z1, z2);      // not in-lined
  z = iFunc (z1, z2) * 11;      // not in-lined
}

Note

  • When you create an inline function, the compiler generates callable function code unless you declare the function with file scope using the static keyword. For example:
    static __inline int func (void) ...

    For static __inline functions, the compiler generates a callable function if the inline function is called in a way that violates the above rules.

    Functions with global scope may be invoked by other external functions. Since the compiler only compiles one file at a time, an inline function with global scope is assumed to be called from a function in another source module and object code is generated.

  • When using the SRC directive to generate an assembler source file, the C166 Compiler does not perform function inlining.
  • Function inlining depends on the complexity of a function. The C166 Compiler does not issue any warning messages in case that a function with the __inline attribute is not expaneded as inline code.


C166: Real-Time Function Tasks

Real-Time Function Tasks

The C166 Compiler provides support for the AR166 Advanced RTOS, the RTX166 Full, and RTX166 Tiny real-time multitasking operating systems. Through use of the _task_ keyword, you may define a function as a real-time task. For example:

void func (void) _task_ task_num

Where

task_num is a task ID number in the range 0-255 for RTX166 Full or 0-31 for RTX166 Tiny.

Task functions must be declared with a void return type and a void argument list.


C166: Inline Assembly

Inline Assembly

Inline assembly is assembly code that you can insert into your C programs. The Keil C166 C Compiler supports two different methods of inline assembly.

  • Traditional Inline Assembly:
    Traditional inline assembly requires that you place your assembly instructions between ASM and ENDASM directives and that you compile your C source file into a .SRC file using the SRC directive which you must assemble with the Keil A166 Assembler.
  • Extended Inline Assembly:
    Integrated inline assembly inserts the assembly code directly into the object file output by the compiler and requires no further processing by the assembler. Inline assembly source blocks are marked by the __asm keyword.

The following table compares the inline assembler methods.

Inline Assembly Comparison | Traditional | Integrated
Direct to Object | NO | YES
Access to C Variables | NO | YES
Source-Level Debugging | NO | YES
C166 Instructions | YES | YES
C167 Instructions | YES | YES
XC16x Instructions | YES | YES
ST10 Instructions | YES | YES
MAC Instructions | YES | YES


C166: Traditional Inline Assembly

Traditional Inline Assembly

The traditional inline assembler merges assembly instructions with the code generated by the compiler and creates assembly source files that you assemble with the A166 Assembler.

The ASM and ENDASM directives enclose the assembly source code and the SRC directive directs the compiler to generate an assembler source file. For example:

#pragma SRC
#pragma SMALL

unsigned int asmfunc1 (
  unsigned int arg)
{
#pragma ASM
INC   R8
#pragma ENDASM

return (arg);
}

For this example, the compiler generates the following SRC file.

$NOMACRO
$SEGMENTED CASE MOD167
;
; '.\asmfunc1.SRC' GENERATED FROM INPUT FILE 'asmfunc1.c'
; COMPILER INVOKED BY:
;	C:\Keil\C166\BIN\C166.EXE asmfunc1.c BROWSE
;        MOD167 DEBUG SRC(.\asmfunc1.SRC)
;
$MODINF (43)
NAME ASMFUNC1
NCODE  CGROUP  ?PR?ASMFUNC1
ASSUME  DPP3 : SYSTEM
REGDEF   R0 - R15

?PR?ASMFUNC1  SECTION  CODE WORD 'NCODE'
; line 1: #pragma SRC
; line 2: #pragma SMALL
; line 3:
; line 4: unsigned int asmfunc1 (

         asmfunc1  PROC  NEAR
         PUBLIC  asmfunc1
; FUNCTION asmfunc1 (BEGIN  RMASK = @0x0010)
;---- Variable 'arg' assigned to Register 'R8' ----
; line 4:   unsigned int arg)
; line 5: {
; line 6: #pragma asm
; line 7: ADD R8,#1
    ADD R8,#1
; line 8: #pragma endasm
; line 9:
; line 10: return (arg);
    MOV	R4,R8
; line 11: }
    RET
; FUNCTION asmfunc1 (END    RMASK = @0x0010)
         asmfunc1  ENDP
?PR?ASMFUNC1  ENDS

END

Note

  • SRC files created using the ASM and ENDASM directives must be compiled using the SRC directive and must be assembled with the A166 Assembler.
  • Source-level information is not available for C files for which a SRC file was generated, assembled, and linked into the project. You may debug the generated assembler code but not the origninal C source code. If this is a requirement, consider using Extended Inline Assembly.


C166: Extended Inline Assembly

Extended Inline Assembly

The extended inline assembler merges assembly instructions with the assembly code generated by the compiler and creates an object file. There is nothing to assemble with the A166 Assembler (unlike Traditional Inline Assembly).

Extended inline assembler blocks begin with the __asm keyword. For example:

__asm { instruction ; comment }

__asm {               ; open inline-assembly block
       instruction    ; comment
       .
       .
       .
      }               // close inline-assembly block

Where

instruction | Is an instruction opcode.
comment | Is a program comment.

For example:

int AddUp (
  int n,
  int near *pTab)
{
  __asm  {            ; open inline-assembly block
    mov   r2,pTab     ; R2:=start of table
    mov   r3,n
    cmp   r3,#0
    jmp   cc_sle,stop ;
    shl   r3,#1       ; n * 2
    add   r3,r2       ; R3 := (n*2)+pTab, end of table + 2
    mov   r4,#0x00    ; clear result

lM: add   r4,[r2+]    ; add up next value
    cmp   r2,r3       ; end of table ?
    jmp   cc_nz,lM    ; loop if not eot
    ret               ; need result in R4
  }

stop:
  __asm { nop    ; single line assembly }
  __asm { nop    ; another nop          }
  return (0);
}

Note

  • __asm blocks may not be nested.
  • __asm blocks may not be used outside a function definition.
  • Labels may be defined in an __asm block and may be referenced by assembler JMP instructions or the C goto statement. An assembler label defined within an __asm block is equivalent to a C label defined in a C function. C labels may be referenced by JMP instructions in __asm blocks.


C166: Register Use

Register Use

There are several rules for registers used in extended inline assembly blocks.

  • Inline assembler instructions may not have expressions with forward references. The only exception to this are local labels and registerbanks (defined with the using keyword).
  • Function return value may be assigned to CPU registers. Refer to Return Values for information about the registers used for different return types.
  • It is not possible for the C166 Compiler to verify and validate the return value of inline assembly blocks. Moreover, checks for missing return values are relaxed for functions that include inline assembly. Therefore, great care is required to properly set the appropriate registers based on the function's return type.
  • Use RET instructions carefully. You must ascertain whether or not the C function code (generated by the compiler) executes PUSH/POP instructions or makes user stack adjustments. If this is the case, you should add a common exit label to your C code and use it in the inline assembler block.
  • You must save and restore the R0 register (which contains the user stack pointer) if your inline assembly code modifies it. For example:
    __asm  {
    PUSH  R0               ; save R0
    .
    .
    .
    POP   R0               ; restore R0
}
  • Registers R1-R7 are preferred for inline assembly instructions. You may use these register in your inline assembly routines without saving and restoring them.
  • By default, registers R8-R15 are used to hold function arguments. If your inline assembly code modifies them, the C166 Compiler may be forced to save parameters and/or local variables to the user stack and reduce the number of register variables in the compiler-generated assembly code.
  • You must save and restore R13, R14, and R15 (which contain saved-by-callee registers) if your inline assembly code modifies them.
  • You must save and restore the DPP0-DPP3 Registers (which contain the Data Page Pointers) if your inline assembly code modifies them. For example:
    __asm  {
    PUSH  DPP2               ; save DPP2
    .
    .
    .
    POP   DPP2               ; restore DPP2
}


C166: Use in Macro Definitions

Use in Macro Definitions

C macros provide a convenient way to insert extended inline assembly code into your C source code. Macros demand extra care because they expand in a single logical line. Follow these rules to create trouble-free macros:

  • Enclose the __asm block in braces ('{}').
  • Put the __asm keyword in front of each assembly instruction.
  • Use only traditional C comment delimiters ('/*') and ('*/'). Assembly-style comment delimiters (';') and single-line C comment delimiters ('//') are not possible.

For example:

#define ABLOCK __asm  {  /* comment */          \
                       __asm       mov R5,#0x10 \
                       __asm   l1: mov rl4,#'}' \
                       __asm       mov R6,R5    \
                       __asm       jnbs R6.2,l1 \
                      }

The __asm keywords (highlighted in red) seem superfluous. However, they are required because C macros are expanded in a single line.

The preprocessor's handling of '#' within macro definitions that begin with the __asm keyword is relaxed (since # is used for immediate values in assembly language). In standard C, an assembly immediate value like #0x10 would cause an error in the preprocessor phase because it violates the C preprocessor rules.

The following example demonstrates how to define and use an extended inline assembly block in a macro.

#define ABLOCK __asm  {  /* comment */          \
                       __asm       mov R5,#0x10 \
                       __asm   l1: mov rl4,#'}' \
                       __asm       mov R6,R5    \
                       __asm       bset R6.3    \
                       __asm       jnbs R6.2,l1 \
                      }

int  i;

void main (void)  {
  i = 1;
  ABLOCK        // expand inline assembly macro
  i = 2;
}


C166: Preprocessor

Preprocessor

The preprocessor built into the C166 Compiler processes the source text of a source file before it is actually compiled into machine language and object code. Preprocessing is the first thing the compiler does. The purpose of the preprocessor is to replace or insert additional text into the source file just prior to compilation.

Most of the obvious functions of the preprocessor require activation (by including preprocessor directives) in your source code. However, there are several things the preprocessor always does:

  • Each C comment is replaced by a single space.
  • Line continuations (indicated by a backslash ('\') at the end of a line) are removed and the lines they break apart are joined for compilation.
  • Predefined macro names are replaced with their predefined text.

In addition to these operations, the preprocessor in the C166 Compiler supports the more obvious preprocessor operations:

  • Header Files,
  • Macros,
  • Conditional Compilation.

If you encounter preprocessor problems, you may direct the compiler to generate a Preprocessor File that shows the exact output from the preprocessor.


C166: Header Files

Header Files

Header files or include files are included and processed by the preprocessor. They provide you with a convenient way to publish global variables, function prototypes, manifest constants, and macro definitions that are used throughout a large development effort.

The #include directive specifies the name of the header file to include.


C166: How #include Works

How #include Works

The #include directive tells the C preprocessor to include the contents of the file specified in the input stream to the compiler and then continue with the rest of the original file.

For example, the header file, file.h contains the following:

char *func (void);

The program file, myprog.c includes this header file:

#include "file.h"

void main (void)
{
while (1)
  {
  printf (func());
  }
}

The output generated by the proprocessor is:

char *func (void);

void main (void)
{
while (1)
  {
  printf (func());
  }
}

Header files typically contain variable and function declarations along with macro definitions. But, they are not limited to only those. A header file may contain any valid C program fragment. However, this practice is error-prone, very confusing, and not at all recommended.


C166: Including Files Once Only

Including Files Once Only

Header files often contain #include directives for other header files. This common practice can result in certain header files that are included more than once. If the header file defines structures or typedefs or if it defines program code or variables, the compiler may generate errors or warnings. Even if there are no erroneous side-effects, including a header file more than once is wasteful.

The standard technique to avoid header files from being included more than once is to enclose the contents of the header file in a preprocessor conditional. For example:

#ifndef FILENAME_INCLUDED
#define FILENAME_INCLUDED

/* Header File Contents */

#endif

FILENAME_INCLUDED, when defined, indicates the header file FILENAME has been included.

Convention dictates that the macro name begins with '__' for system header files and should not begin with '_' for user header files. The macro name should contain the name of the header file and some additional text.


C166: Macros

Macros

Perhaps the most useful aspect of the C preprocessor is the ability to create and use macros. Macros enable you to assign short names to source code blocks. When you use the macro name in your source file, the preprocessor replaces it with the source code block specified in the macro definition.

A macro definition includes the name of the macro, the macro body, and may include macro arguments.

  • Simple Macros require no arguments and are the simplest macros to define.
  • Complex Macros accept one or more arguments and may be used like functions.
  • Macro Operators lists special macro operators that may be used in macro definitions.
  • Predefined Macros lists macros that are defined by the compiler at compile-time.

There are a few caveats of macros that deserve further scrutiny.


C166: Simple Macros

Simple Macros

A simple macro is merely an abbreviation for a fragment of code. It is often called a manifest constant because it defines a name for a constant value.

Macros must be defined using the #define directive before they can be used. For example:

#define LEN 128

defines a macro named LEN. When LEN is used in your program (or in preprocessor directives) it is replaced with the text 128. So, a C statement like

char buffer[LEN];

is expanded by the preprocessor into

char buffer[128];

and is subsequently compiled by the compiler.

Note

  • Macro definitions must be a single line. You may use the backslash character ('\') followed by a new-line to continue a macro on a subsequent line (refer to Preprocessor Directives for more information).
  • By convention, macro names are uppercase. If you maintain that convention in your applications, it is easy to tell at a glance if an object is a variable, a function, or a macro.


C166: Complex Macros

Complex Macros

A complex macro accepts arguments and generates a fragment of code using the values of those arguments. Macros that accept arguments appear to be functions. However, arguments are not typed as in a C function. They are merely replaced by the text passed to the macro when expanded.

Macros with arguments must be defined using the #define directive before they can be used. The argument list is enclosed in parentheses and must immediately follow the macro name. Spaces are not allowed between and macro name and open parenthesis. For example:

#define MAX(x,y) ((x) > (y) ? (x) : (y))

defines a macro named MAX that takes two arguments (x and y). When MAX is used in your program (or in preprocessor directives) it is replaced with the text ((x) > (y) ? (x) : (y)). If x and y are numeric constants, the preprocessor can determine the result of the macro and substitute the greater value.

A C statement like

int a = MAX(15,20);

is expanded by the preprocessor into

int a = 20;

While a C statement like

int a = MAX(myvar,20);

is expanded by the preprocessor into

int a = ((myvar) > (20) ? (myvar) : (20));
  • The number of arguments passed to a macro must match the number of arguments specified in the macro definition.
  • It is common practice to surround arguments used in a macro definition with parentheses. This is done so that compound expressions, when passed to a macro, do not cause unwanted side-effects. For example:
    #define MAX(x,y) ((x) > (y) ? (x) : (y))

int a = MAX(x-5,10);

    expands as

    int a = ((x-5) > (10) ? (x-5) : (10));

    Without the additional parentheses,

    #define MAX(x,y) x > y ? x : y

int a = MAX(x-5,10);

    expands as

    int a = x-5 > 10 ? x-5 : 10;

    with a potentially different meaning.

  • Macros that use arguments more than once can introduce undesired side-effects into your program. For example:
    #define MAX(x,y) ((x) > (y) ? (x) : (y))

maxval = MAX(a+b, func(c));

    expands as

    maxval = ((a+b) > (func(c)) ? (a+b) : (func(c)));

    The function func appears to be invoked only once in the program, but because of the macro definition, it is actually called twice. Each call may return a different value and the result of MAX may be incorrect.

  • Macros may be defined with a null or empty argument list. For example:
    #define MYMACRO() (func();)

    To call such a macro, you must specify the macro name along with an empty argument list. For example:

    MYMACRO()
  • To pass an empty argument to a macro, you must include at least one whitespace character in the place of that argument.


C166: Macro Operators

Macro Operators

Three preprocessor operators may be used in #define or #if and #elif preprocessor directives.

  • Stringize Operator (#)
  • Token-Pasting Operator (##)
  • Defined Operator


C166: Stringize (#)

Stringize (#)

The stringize or number-sign operator ('#'), when used within a macro definition, converts a macro parameter into a string constant. This operator may be used only in a macro that has a specified argument or parameter list.

When the stringize operator immediately precedes the name of one of the macro parameters, the parameter passed to the macro is enclosed within quotation marks and is treated as a string literal. For example:

#define stringizer(x)  printf (#x "\n")

stringizer(text)

This example results in the following actual output from the preprocessor:

printf ("text\n")

The expansion shows that the parameter is converted literally as if it were a string. When the preprocessor stringizes the x parameter, the resulting line is:

printf ("text" "\n")

Because strings separated by whitespace are concatenated at compile time, these two strings are combined into "text\n".

If the string passed as a parameter contains characters that should normally be literalized or escaped (for example, " and \), the required \ character is added automatically.


C166: Token Pasting (##)

Token Pasting (##)

The token-pasting operator (##) within a macro definition combines two arguments. It permits two separate tokens in the macro definition to be joined into a single token.

If the name of a macro parameter used in the macro definition is immediately preceded or followed by the token-pasting operator, the macro parameter and the token-pasting operator are replaced by the value of the passed parameter. Text that is adjacent to the token-pasting operator that is not the name of a macro parameter is not affected. For example:

#define tokenpaster(n) printf ("token" #n " = %d", token##n)

tokenpaster(34);

This example results in the following actual output from the preprocessor:

printf ("token34 = %d", token34);

This example shows the concatenation of token##n into token34. Both the stringize and the token-pasting operators are used in this example.


C166: Defined

Defined

The preprocessor defined operator is used in constant expressions to determine if an identifier has been defined (by the #define preprocessor directive). If the specified identifieris defined, the value is true (non-zero). If the symbol is not defined, the value is false (zero). The defined operator is specified as follows:

defined (identifier)

or

defined identifier

The defined operator may be used in #if or #elif directives only.


C166: Predefined Macros

Predefined Macros

The C166 Compiler provides you with predefined constants to use in preprocessor directives and C code for more portable programs. The following table lists and describes each one.

Constant | Description
__C166__ | Version number of the compiler (for example, 501 for version 5.01).
__DATE__ | Date when the compilation was started in ANSI format (month dd yyyy).
__DATE2__ | Date when the compilation was started in short form (mm/dd/yy).
__DUS__ | Defined to 1 to indicate that the DYNAMICUSRSTK directive is active.
__FILE__ | Name of the file being compiled.
__FLOAT64__ | Defined to 1 to indicate that the FLOAT64 directive is active.
__LINE__ | Current line number in the file being compiled.
__MAC__ | Defined to 1 to indicate that the MAC directive is active.
__MOD167__ | Defined to 1 to indicate that the MOD167 directive is active.
__MODEL__ Memory model selected:
  • 0 for TINY,
  • 1 for SMALL,
  • 2 for COMPACT,
  • 3 for MEDIUM,
  • 4 for LARGE,
  • 5 for HCOMPACT,
  • 6 for HLARGE,
  • 7 for XLARGE.
__MODV2__ | Defined to 1 to indicate that the MODV2 directive is active.
__SAVEMAC__ | Defined to 1 to indicate that the SAVEMAC directive is active.
__STDC__ | Defined to 1 to indicate full conformance with the ANSI C Standard.
__TIME__ | Time when the compilation was started.

Note

  • There are two (2) leading and trailing underscore characters ('_') used for the predefined constants.


C166: Undefining and Redefining

Undefining and Redefining

Macros are defined using the #define directive. Undefining or canceling a defined macro is done using the #undef directive. For example:

#define VALUE 123
int v1 = VALUE;
#undef VALUE
int v2 = VALUE;

expands into

int v1 = 123;

int v2 = VALUE;

Redefining a macro is simply using the #define directive to provide a new macro body for an existing macro definition. If the redefinition is identical to the original definition, the compiler goes on without emitting any type of diagnostic message. If, however, the redefinition is different, the compiler generates a warning since this may not be desired. To avoid the warning and redefine the macro, undefine the macro (using #undef) first.


C166: Macro Caveats

Macro Caveats

  • Macro definitions are not stored in the object file. They are only active for the duration of a single source file starting when they are defined and ending when they are undefined (using #undef), redefined, or when the end of the source file is found.
  • Macro definitions you wish to use in multiple source files may be defined in an include file which may be included in each source file where the macros are required.
  • When a macro with arguments is invoked, the macro processor substitutes the arguments into the macro body and then processes the results again for additional macro calls. This makes it possible, but confusing, to piece together a macro call from the macro body and from the macro arguments.
  • Most experienced C programmers enclose macro arguments in parentheses when they are used in the macro body. This technique prevents undesired grouping of compound expressions used as arguments and helps avoid operator precedence rules overriding the intended meaning of a macro.
  • While a macro may contain references to other macros, references to itself are not expanded. Self-referencing macros are a special feature of ANSI Standard C in that the self-reference is not interpreted as a macro call. This special rule also applies to indirectly self-referencing macros (or macros that reference themselves through another macro).


C166: Conditional Compilation

Conditional Compilation

Conditional compilation directives allow you to designate parts of the program for the compiler to ignore. These parts are not compiled and no object code is generated for them. Conditional directives resemble the C if statement and may be used to test defined macros or arithmetic expressions. The test performed by a conditional directive is done at compile-time by the compiler. Depending on the result of the test, source code is either included or excluded from the compilation.

There are several reasons to use conditional compilation in your program.

  • Your program may require different code depending on which device or architecture you use. In some cases, library routines may exist in one configuration that do not exist in another. Conditional compilation allows you to handle such a situation by substituting alternate functions with the unavailable library routines.
  • Many complex functions require comprehensive test code to verify or validate I/O and proper operation. Intermediate values may be tested and output as well. After verification, you may wish to retain the test cases for future reference. You can include them in conditional blocks you control with a macro. For example:
    #define DEBUG 0

    The following test case compiles only when DEBUG is defined to a value other than 0.

    #if DEBUG   /*** Test Case ***/
.
.
.
#endif
  • Often, it is necessary to replace or rewrite certain sections of a working program. Conditionals allow you to retain old code in the source file by placing it in a conditional block. For example:
    #if 0   /*** Old code from 1999 ***/
.
.
.
#endif

Following is a list of the available conditional compilation directives.

Directive | Description
#elif | Initiates an alternative branch of the if condition, when the previous #if, #ifdef, #ifndef, or #elif branch was not taken.
#else | Initiates an alternative branch when the previous #if, #ifdef, or #ifndef branch was not taken.
#endif | Ends a #if, #ifdef, #ifndef, #elif, or #else block.
#ifdef | Evaluates an expression for conditional compilation. The argument to be evaluated is the name of a definition.
#ifndef | Same as #ifdef but the evaluation succeeds if the definition is not defined.
#if | Evaluates an expression for conditional compilation.


C166: Preprocessor Directives

Preprocessor Directives

Preprocessor directives must be the first non-whitespace text specified on a line. All directives are prefixed with the pound or number-sign character ('#'). For example:

#pragma PRINT
#include <stdio.h>
#define DEBUG 1

Whitespace is allowed before and after the number-sign ('#'). A number-sign ('#') that appears alone on a line is interpreted as a null preprocessor directive. For example:

# define myfavnum 45
#
   #    include

The entire proprocessor directive must be contained in a single source line. Line continuations, backslash ('\') followed by a new-line character, may be used in preprocessor directives since these are removed by the preprocessor. For example:

#define mycode                      \
        {                           \
        volatile unsigned char i;   \
        for (i=0; i<100; i++);      \
        }

The number-sign ('#') and the preprocessor directive must be explicitly specified and may not come from a macro expansion. For example:

#define mydef #define otherdef 16

mydef

In this case, mydef is expanded to define otherdef 16 since # is interpreted as a stringize operator. This expansion is processed by the compiler and a syntax error is generated.

The following table lists the preprocessor directives and gives a brief description of each.

Directive | Description
#define | Defines a preprocessor macro or constant.
#elif | Initiates an alternative branch of the if condition, when the previous #if, #ifdef, #ifndef, or #elif branch was not taken.
#else | Initiates an alternative branch when the previous #if, #ifdef, or #ifndef branch was not taken.
#endif | Ends a #if, #ifdef, #ifndef, #elif, or #else block.
#error | Outputs an error message defined by the user.
#ifdef | Evaluates an expression for conditional compilation. The argument to be evaluated is the name of a definition.
#ifndef | Same as #ifdef but the evaluation succeeds if the definition is not defined.
#if | Evaluates an expression for conditional compilation.
#include | Reads source text from an external file. The notation sequence determines the search sequence of the included files. The compiler searches for include files specified with less-than/greater-than symbols ('<', '>') in the include file directory. Include files specified with double-quotes (" ") are searched for in the current directory.
#line | Specifies a line number and an optional filename. This specification is used in error messages to identify the error position.
#message | Outputs a information message defined by the user.
#pragma | Allows you to specify directives that may be included on the compiler command line. Pragmas may contain the same directives that are specified on the command line.
#undef | Deletes a preprocessor macro or constant definition.
#warning | Outputs a warning message defined by the user.


C166: #pragma

#pragma

The #pragma directive specifies compiler directives that may change during program compilation.

#pragma directive « directive ... »

Basically, you place pragmas in your program source code where you want the directive(s) to take effect. Refer to the C166 Compiler Directives for a complete list of directives you may specify using #pragma.

Note

  • Not all directives may be specified using #pragma.
  • Some directives may be specified only once (at the top of the file) and some may be specified multiple times without the source code.
  • Some directives may be specified on the command line and overridden with #pragma.


C166: #include

#include

The #include directive causes the C preprocessor to include the contents of the specified file in the compilation before continuing with the rest of the current file. The #include directive may be used to specify two different types of header (or include) files: system header files and user header files.

System header files are included as follows:

#include <filename>

These include files are installed in the \INC\ folder. They are a part of the Keil development tools release and should not be modified. When a system header file is specified, the compiler searches for the file in the following folders in order:

  • Paths specified by the INCDIR directive.
  • Paths specified by the C166INC environment variable.

User header files are included as follows:

#include "filename"

These include files are user-created and may reside anywhere on your computer. When a user header file is specified, the compiler searches for the file in the following folders in order:

  • The current folder.
  • The source file folder.
  • Paths specified by the INCDIR directive.
  • Paths specified by the C166INC environment variable.

Note

  • Include files usually have an extension of .H indicating they are Header files. We recommend you use this standard for your user header files.
  • Typically, include files contain only variable declarations (not definitions), macro definitions, and definitions for Special Function Registers.
  • Include files may contain variable definitions. However, you must make certain that the such a header file is only included in one C file in your project. Otherwise, multiple variables with the same name may be defined resulting in linker errors. We recommended that you do not define variables or functions in include files.
  • It is possible to begin or end a function in an include file. It is also possible to put function and variable definitions in include files. While these kinds of things are possible, they are very confusing and are not good coding habits to get into. Therefore, we do not recommend that you do them.

Refer to Header Files for a complete description of how to use include files in your C programs.


C166: #define

#define

The #define directive defines a preprocessor macro.

#define macro-name « (arg« , arg ... ») » replacement-text

You may use #define to create function-like macros with or without arguments. Macros are syntactically similar to function calls. When a defined macro is encountered in the source file, the macro-name and any arguments are replaced by the replacement-text. For example:

#define my_macro(a,b,c) a+b+c

int func (int x, int y, int z)
{
return(my_macro(x,y,z));
}

appears as follows after macro expansion:

int func (int x, int y, int z)
{
return(x+y+z);
}

Refer to Macros for a complete description of how to define and use macros in your C programs.


C166: #undef

#undef

The #undef directive un-defines a macro name.

#undef macro-name

#undef causes the previously defined macro macro-name to no longer be defined as a macro. If macro-name is not defined, #undef is ignored. Predefined macros are not affected by #undef.


C166: #if

#if

The #if directive tests an expression and if the result is true (non-zero) allows the compiler to process subsequent text (until the next #else, #elif, or #endif directive). If the result is false (zero), subsequent text is not processed by the compiler.

#if expression
.
.
.
#endif


C166: #ifdef

#ifdef

The #ifdef directive is a special case of the #if directive that tests a name to determine if it is defined.

#ifdef name

This directive is equivalent to:

#if defined(name)


C166: #ifndef

#ifndef

The #ifndef directive is a special case of the #if directive that tests a name to determine if it is not defined.

#ifndef name

This directive is equivalent to:

#if !defined(name)


C166: #elif

#elif

The #elif directive tests an expression and if the result is true (non-zero) allows the compiler to process subsequent text (until the next #else, #elif, or #endif directive). If the result is false (zero), subsequent text is not processed by the compiler. The #elif directive may be used only after a #if directive has been specified.

#if expression
.
.
.
#elif expression
.
.
.
#elif expression
.
.
.
#else
.
.
.
#endif


C166: #else

#else

The #else directive specifies an alternative text block to the block following a #if or #elif directive. If the result of the preceding #if or #elif is false, the text following the #else is processed by the compiler.

#if expression
.
.
.
#else
.
.
.
#endif


C166: #endif

#endif

The #endif directive marks the end of a #if block. All #if directives must have an accompanying #endif.

#if expression
.
.
.
#endif

Copyright (c) Keil Software, Inc. and and Keil Elektronik GmbH. All rights reserved.


C166: #line

#line

The #line directive specifies a line-number and optional filename for the next line in the source file.

#line line-number « filename »

C source code may come from more than one source file if the #include directive is used. The proprocessor tracks the line number and file name so that the C compiler can accurately reference lines causing errors or warnings. Additionally, accurate file name and line number details are necessary to support source-level debugging.

Third-party tools exist that may be used to generate C source code from a high-level specification language. A common use for the #line directive is to sets the source line-number and filename, in the generated source, to the actual line number and file name of the specification language file. When errors are output, the line number and file referenced will be the original specification rather than the actual C source file.


C166: #error

#error

The #error directive causes the preprocessor to emit an error message. The rest of the line is the error message.

#error "message"

You may use #error inside a condition that detects an error condition. For example, the following outputs an error message if __KEIL__ is not defined.

#ifndef __KEIL__
#error "This code will not work without the Keil Compiler."
#endif


C166: #warning

#warning

The #warning directive causes the preprocessor to emit a warning. The rest of the line is the warning message.

#warning "message"

You may use #warning inside a condition that detects an error condition. For example, the following outputs a warning message if __KEIL__ is not defined.

#ifndef __KEIL__
#warning "This code probably will not work without the Keil Compiler."
#endif


C166: #message

#message

The #message directive causes the preprocessor to emit a message in the listing file. The rest of the line is the message.

#message "message"

You may use #message inside a condition that detects a condition you wish to annotate. For example, the following outputs a message if MYCODE is not defined.

#ifndef MYCODE
#message "This code will not work without the Keil Compiler."
#endif


C166: Advanced Programming

Advanced Programming

This section describes advanced programming information that experienced software engineers will find invaluable. Knowledge of most of these topics is not necessary to successfully create an embedded C16x/ST10 target program using the C166 Compiler. However, the following sections provide insight into how many non-standard procedures can be accomplished.

This section discusses the following topics:

  • Files you may alter to customize the startup procedures.
  • Files you may alter to customize run-time execution of several library routines.
  • The conventions the C166 Compiler uses to name code and data segments.
  • How to Interface the C166 functions to assembly routines.
  • Data storage formats for different C166 data types.
  • Different optimizing features of the C166 optimizing compiler.


C166: Sections, Classes, and Groups

Sections, Classes, and Groups

A section is a contiguous area of memory generated from code or data defined in a source module. Each section has a type, class, group, and a name. Sections are usually related to the hardware configuration. Therefore, portions of programs stored in ROM are in separate sections from the portions stored in RAM. Sections generated by the Keil C166 Compiler are given names which are composed of a prefix and the name of the source module.

A class is an arbitrarily ordered collection of sections that share a common attribute. The purpose of a class is to allow manipulation of a number of sections using only the class name. For instance, the near data objects from all modules in a program are combined into the NDATA class while the far constant objects are combined into the FCONST class.

A group is a shorthand which is used to reference a collection of sections that all reside within one data page (for data groups) or segment (for code groups). Groups define address-range limits for their references sections. Two group types are supported: CGROUP (code groups) and DGROUP (data groups). Groups are used by the linker to guarantee that classes within the group fit into the appropriate address range (16K for DATA or 64K for CODE) and that DPP register assignments are correctly performed in the startup code. The DPPUSE linker directive may be used to extend the address space possible for DATA groups.

Objects that the C166 Compiler generates (such as program code, program data, and constant data) are stored in sections that may be absolute or relocatable. The only exception is automatic variables that are stored on the USER STACK that is addressed by the R0 register. The compiler creates a separate section for each memory type used in the C source.

Section names created by the C166 Compiler are converted to and stored in uppercase and include a class-code and a module-name formatted as follows:

?class-code?module-name

Where

class-code | is an abbreviation for the class type.
module-name | is the name of the source file in which the object is declared.

The following table shows all possible section names with their associated class and group names. The class and group names are used by the linker to simplify address assignments and to ensure that objects from different modules are placed in valid address ranges.

Section Name | Group Name | Class Name | Section Contents
?PR?module-name | NCODE | NCODE | near function code
?PR?module-name | — | FCODE | far function code
?NC?module-name | NCONST | NCONST | const near objects
?FC?module-name | — | FCONST | const far objects
?HC?module-name | — | HCONST | const huge objects
?ND?module-name | NDATA | NDATA | near objects with #pragma NOINIT
?ND0?module-name | NDATA | NDATA0 | near objects with #pragma INIT
?SD?module-name | SDATA | SDATA | sdata objects with #pragma NOINIT
?SD0?module-name | SDATA | SDATA0 | sdata objects with #pragma INIT
?ID?module-name | SDATA | IDATA | idata objects with #pragma NOINIT
?ID0?module-name | SDATA | IDATA0 | idata objects with #pragma INIT
?BD?module-name | SDATA | BDATA | bdata objects with #pragma NOINIT
?BD0?module-name | SDATA | BDATA0 | bdata objects with #pragma INIT
?BI?module-name | — | BIT | bit objects with #pragma NOINIT
?BI0?module-name | — | BIT0 | bit objects with #pragma INIT
?FD?module-name | — | FDATA | far objects with #pragma NOINIT
?FD0?module-name | — | FDATA0 | far objects with #pragma INIT
?HD?module-name | — | HDATA | huge objects with #pragma NOINIT
?HD0?module-name | — | HDATA0 | huge objects with #pragma INIT
?XD?module-name | — | XDATA | xhuge objects with #pragma NOINIT
?XD0?module-name | — | XDATA0 | xhuge objects with #pragma INIT
?C_INITSEC | — | — | Variable-initialization information
?C_MEMCLRSEC | — | — | RAM zero-initialization information
?C_STARTUP_CODE | — | ICODE | Startup code for the C main function

Note

  • If the TINY memory model is used, no group names are assigned to the section names.


C166: Special Sections

Special Sections

There are several special features of some sections:

  • Sections that contain a 0 in the section name prefix or class name are cleared to zero by the startup code.
  • The ?C_MEMCLRSEC section is generated by the L166 Linker. It contains the address ranges of the memory that is cleared to zero.
  • The ?C_INITSEC section contains initialization data for global and static objects that are initialized to a value other than zero.
  • The ?C_STARTUP_CODE section contains the startup code that initializes the MCU. This code is executed before the main C function is called. If you use on-chip ROM, the startup code must be located there and must be assigned the ICODE class.


C166: Locating Sections

Locating Sections

There are two linker directives you may use to locate sections and classes to physical addresses.

  • The CLASSES directive provides a way to assign all sections in a class to a specified address range.
  • The SECTIONS directive provides a way to assign one or more sections to a specified address range.

Sections should be located to memory according to the following rules:

Class Names | Location
NCODE | ROM or EPROM space for near code; must fit into one 64KByte segment.
NCONST | ROM or EPROM space for const near variables; must fit into one 16 KByte page. You may use the DPPUSE linker directive to enlarge address range for this class.
FCONST | ROM or EPROM space for const far variables.
HCONST | ROM or EPROM space for const huge variables.
XCONST | ROM or EPROM space for const xhuge variables.
FCODE | ROM or EPROM space for far code.
NDATA, NDATA0 | RAM space for near variables; both classes combined must fit into one 16 KByte page. You may use the DPPUSE linker directive to enlarge address range for these class.
SDATA, SDATA0 | RAM space for sdata variables; address range 0C000h-0FFFFh (Page 3).
IDATA, IDATA0 On-chip RAM for idata variables:
  • 80C166 address range: 0xFA00-0xFDFF.
  • C16x/XC16x address range: 0xF800-0xFDFF.
BIT, BIT0 | Bit-addressable RAM for bit variables; address range 0FD00h-0FDFFh.
BDATA, BDATA0 | Bit-addressable RAM for bdata variables; address range 0FD00h-0FDFFh.
FDATA, FDATA0 | RAM space for far variables.
HDATA, HDATA0 | RAM space for huge variables.
XDATA, XDATA0 | RAM space for xhuge variables.
ICODE | ROM or EPROM space; located in on-chip code memory.


C166: Customization Files

Customization Files

The C166 Compiler provides a number of source files you may modify to adapt your target program to a specific hardware platform. These files contain:

  • Code that executes upon reset
    (STARTUP.A66, START167.A66, and START_V2.A66).
  • Code that performs low-level stream I/O.
  • Code for memory allocation.

The code contained in these files is already compiled or assembled and included in the C library. When you link your program, the code from the library is automatically included.

You may customize these files to adjust them to your requirements. If you use the µVision IDE, we recommend that you copy the customization file into your project folder to make modifications. The modified version of the file may be added to your project.

When you use the command-line tools, you must include the object files generated from the modified customization files on the linker command line. The following example shows you how to include custom replacement files for STARTUP.A66 and PUTCHAR.C:

L166 MYMODUL1.OBJ, MYMODUL2.OBJ, STARTUP.OBJ, PUTCHAR.OBJ


C166: Startup Code

Startup Code

Startup Code is the program code that executes immediately after reset. The startup code includes:

  • The reset vector.
  • Code to setup SYSCON and BUSCON SFRs.
  • Code to clear memory.
  • Code to initialize global variables.

There are several different startup files available.

  • STARTUP.A66 contains the startup code for 80C166-compatible devices.
  • START167.A66 contains the startup code for C161, C163, C164, C165, and C167 devices.
  • START_V2.A66 contains the startup code for the XC16x devices.

All startup files are located in the /KEIL/C166/LIB folder. You should include a copy of the appropriate startup file in your project.


C166: STARTUP.A66

STARTUP.A66

The STARTUP.A66 file contains the startup code for a C166 target program. Use this file for the C166 and GOLD derivatives of the C166 microcontroller family.

The startup code is executed immediately upon reset of the target system and performs the following operations in order:

  • Initializes the SYSCON SFRs.
  • Initializes the ADDRSELx/BUSCONx SFRs (if configured).
  • Reserves and initializes the hardware stack and stack overflow/underflow registers.
  • Sets DPP0-DPP3 and CP for memory and register bank accesses.
  • Reserves and initializes the user stack area and user stack pointer (R0).
  • Clears data memory.
  • Initializes explicitly initialized variables.
  • Transfers control to the main C function.

STARTUP.A66 contains definitions that are used to configure the hardware of the 80C166 and to setup the C runtime system.

The functions of the individual EQU statements are described below.

Name | Definition
_ALECTL0 | ALE Lengthening Control Bit; see the C167 data sheet for description.
_BTYP0 or BYTP | Defines the external bus configuration the CPU uses. The bus configuration is used only if BTYP_ENABLE is set to 1.
_BUSACT0 or BUSACT | Bus Active Control Bit. Default: 1 to enable the external bus.
_BYTDIS | Byte High Enable pin control bit initialization value. Default: 0 for enabled. (This is the reset value of the CPU). To disable the BHE# output, set _BYTDIS to 1.
_CLREN | System Clock Output Enable bit initialization value. Default: 0 to disable the CLKOUT output (this is also the reset value of the CPU.) To enable the CLKOUT output set _CLKEN to 1.
_MCTC0 or _MCTC | Memory Cycle Time initialization value. Default: 1 for one memory wait state (MCTC = 0EH). Reset value of the CPU is 15 for 15 additional state times.
_MCTCn-_CSWENn | Defines the bus characteristics for the address range specified with ADDRESSn and RANGEn. These values are used to set the BUSCON1-BUSCON4 registers.
_MTTC0 or MTTC | Memory Tri-State Time initialization value. Default: 0 for 0.5 states; this is also the reset value of the CPU. To select 0 states for the Tri-State time, set _MTTC to 1.
_RDY_AS | Synchronous / Asynchronous READY# input selection. Default: 0 for synchronous READY# input.
_RDYEN0 or RDYEN | READY# Input Enable Control Bit. Default: 0 to disable the READY# input.
_ROMEN | The Internal ROM Access Enable bit is read-only. Do not change this value.
_ROMS1 | On-Chip ROM Segment-Mapping Control Bit. Default: 0 for on-chip ROM mapped to segment 0 (address range 0x0000-0xFFFF). Seg _ROMS1 to 1 for segment 1 (address range 0x10000-0x1FFFF).
_RWDC0 or RWDC | Read/Write Signal Delay initialization value. Default: 1 for no delay (this is the typical value in most systems). Reset value of the CPU is 0 for 0.5 states delay time.
_SGTDIS | Segmentation Disable Control Bit initialization value. The segmentation is disabled for the TINY memory model; in all other memory models it is enabled. Do not change the definition of _SGTDIS.
_WRCFG | Write Configuration Control Bit. Default: 0 for normal configuration of WR# and BHE# outputs.
_XRAMEN | XRAM Enable Control Bit. Default: 0 to disable access to XRAM area. External bus accesses are generated in the XRAM area.
ADDRESS1-ADDRESS4 | Define the start address of the Chip Select 1-4 output (CS1#-CS4#). This value is used to set the ADDRSEL1-ADDRSEL4 register.
BTYP_ENABLE | Allow software to modify BTYP and change the bus mode. By default, this is disabled and the bus type is set by the hardware pins of the C16x/ST10. To enable the external bus configuration, set BTYP_ENABLE = 1.
BUSCON1-BUSCON4 | Initialization for BUSCON1/ADDRSEL1-BUSCON4/ADDRSEL4 registers. Set BUSCON1 = 1 to initialize BUSCON1/ADDRSEL1.
CLR_MEMORY | Memory Zero Initialization of RAM areas. Default: enable the memory zero initialization of RAM area. To disable the memory zero initialization, set CLR_MEMORY = 1. This reduces the startup code size.
DPPUSE | Allow re-assignment of DPP registers. Default: 1 to support the L166 DPPUSE directive. To disable the DPP re-assignment, set DPPUSE = 0. This reduces the startup code size.
EXT_RAM | External RAM Write-Access Enable (P3.13 = WR-Pin) initialization value. The default value enables the external RAM access. To disable external RAM, remove the statement $SET (EXT_RAM).
INIT_VARS | Variable Initialization of explicitly initialized variables (variables are to be defined as static or declared at file level). Default: initialize variables. To disable the variable initialization, set INIT_VARS = 0. This reduces the startup code size.
RANGE1-RANGE4 | Define the address range of the Chip Select 1-4 output (CS1#-CS4#). This value is used to set the ADDRSEL1-ADDRSEL4 register.
SSTSZ | Set the system stack space, if you selected 7 for the STK_SIZE.
STK_SIZE | STK_SIZE: Maximum System Stack Size selection initialization value. Default value is 0 for 256-word stack size. Set STK_SIZE to the following values for other stack sizes: 0 for 256-word system stack 1 for 128-word system stack 2 for 64-word system stack 3 for 32-word system stack 4 for 512-word system stack (not for C166) 7 for user-defined system-stack size If you select 7, the system-stack size is defined with the SSTSZ variable.
USTSZ | Set the user stack space. The user stack is used for automatic variables.
WATCHDOG | Hardware Watchdog control. Default: disable the hardware watchdog. To enable the watchdog set WATCHDOG = 1.


C166: START167.A66

START167.A66

The START167.A66 file contains the startup code for the C161, C163, C164, C165, and C167 microcontrollers.

The startup code is executed immediately upon reset of the target system and performs the following operations in order:

  • Initializes the SYSCON SFRs including BUSCON0.
  • Initializes the ADDRSELx/BUSCONx SFRs (if configured).
  • Reserves and initializes the hardware stack and stack overflow/underflow registers.
  • Sets DPP0-DPP3 and CP for memory and register bank accesses.
  • Reserves and initializes the user stack area and user stack pointer (R0).
  • Clears data memory.
  • Initializes explicitly initialized variables.
  • Transfers control to the main C function.

START167.A66 contains definitions that are used to configure the hardware of the C16x and to setup the C runtime system.

The functions of the individual EQU statements are described below.

Name | Definition
_ALECTL0 | ALE Lengthening Control Bit; see the C167 data sheet for description.
_BTYP0 or BYTP | Defines the external bus configuration the CPU uses. The bus configuration is used only if BTYP_ENABLE is set to 1.
_BUSACT0 or BUSACT | Bus Active Control Bit. Default: 1 to enable the external bus.
_BYTDIS | Byte High Enable pin control bit initialization value. Default: 0 for enabled. (This is the reset value of the CPU). To disable the BHE# output, set _BYTDIS to 1.
_CLREN | System Clock Output Enable bit initialization value. Default: 0 to disable the CLKOUT output (this is also the reset value of the CPU.) To enable the CLKOUT output set _CLKEN to 1.
_MCTC0 or _MCTC | Memory Cycle Time initialization value. Default: 1 for one memory wait state (MCTC = 0EH). Reset value of the CPU is 15 for 15 additional state times.
_MCTCn-_CSWENn | Defines the bus characteristics for the address range specified with ADDRESSn and RANGEn. These values are used to set the BUSCON1-BUSCON4 registers.
_MTTC0 or MTTC | Memory Tri-State Time initialization value. Default: 0 for 0.5 states; this is also the reset value of the CPU. To select 0 states for the Tri-State time, set _MTTC to 1.
_RDY_AS | Synchronous / Asynchronous READY# input selection. Default: 0 for synchronous READY# input.
_RDYEN0 or RDYEN | READY# Input Enable Control Bit. Default: 0 to disable the READY# input.
_ROMEN | The Internal ROM Access Enable bit is read-only. Do not change this value.
_ROMS1 | On-Chip ROM Segment-Mapping Control Bit. Default: 0 for on-chip ROM mapped to segment 0 (address range 0x0000-0xFFFF). Seg _ROMS1 to 1 for segment 1 (address range 0x10000-0x1FFFF).
_RWDC0 or RWDC | Read/Write Signal Delay initialization value. Default: 1 for no delay (this is the typical value in most systems). Reset value of the CPU is 0 for 0.5 states delay time.
_SGTDIS | Segmentation Disable Control Bit initialization value. The segmentation is disabled for the TINY memory model; in all other memory models it is enabled. Do not change the definition of _SGTDIS.
_WRCFG | Write Configuration Control Bit. Default: 0 for normal configuration of WR# and BHE# outputs.
_XRAMEN | XRAM Enable Control Bit. Default: 0 to disable access to XRAM area. External bus accesses are generated in the XRAM area.
ADDRESS1-ADDRESS4 | Define the start address of the Chip Select 1-4 output (CS1#-CS4#). This value is used to set the ADDRSEL1-ADDRSEL4 register.
BTYP_ENABLE | Allow software to modify BTYP and change the bus mode. By default, this is disabled and the bus type is set by the hardware pins of the C16x/ST10. To enable the external bus configuration, set BTYP_ENABLE = 1.
BUSCON1-BUSCON4 | Initialization for BUSCON1/ADDRSEL1-BUSCON4/ADDRSEL4 registers. Set BUSCON1 = 1 to initialize BUSCON1/ADDRSEL1.
CLR_MEMORY | Memory Zero Initialization of RAM areas. Default: enable the memory zero initialization of RAM area. To disable the memory zero initialization, set CLR_MEMORY = 1. This reduces the startup code size.
DPPUSE | Allow re-assignment of DPP registers. Default: 1 to support the L166 DPPUSE directive. To disable the DPP re-assignment, set DPPUSE = 0. This reduces the startup code size.
EXT_RAM | External RAM Write-Access Enable (P3.13 = WR-Pin) initialization value. The default value enables the external RAM access. To disable external RAM, remove the statement $SET (EXT_RAM).
INIT_VARS | Variable Initialization of explicitly initialized variables (variables are to be defined as static or declared at file level). Default: initialize variables. To disable the variable initialization, set INIT_VARS = 0. This reduces the startup code size.
RANGE1-RANGE4 | Define the address range of the Chip Select 1-4 output (CS1#-CS4#). This value is used to set the ADDRSEL1-ADDRSEL4 register.
SSTSZ | Set the system stack space, if you selected 7 for the STK_SIZE.
STK_SIZE | STK_SIZE: Maximum System Stack Size selection initialization value. Default value is 0 for 256-word stack size. Set STK_SIZE to the following values for other stack sizes: 0 for 256-word system stack 1 for 128-word system stack 2 for 64-word system stack 3 for 32-word system stack 4 for 512-word system stack (not for C166) 7 for user-defined system-stack size If you select 7, the system-stack size is defined with the SSTSZ variable.
USTSZ | Set the user stack space. The user stack is used for automatic variables.
WATCHDOG | Hardware Watchdog control. Default: disable the hardware watchdog. To enable the watchdog set WATCHDOG = 1.


C166: Basic I/O

Basic I/O

The following files contain the source code for the low-level stream I/O routines. When you use µVision IDE, you can simply add the modified versions to the project.

C Source File | Description
PUTCHAR.C | Used by all stream routines that output characters. You may adapt this routine to your individual hardware (for example, LCD or LED displays). The default version outputs characters via the serial interface. An XON/XOFF protocol is used for flow control. Line feed characters ('\n') are converted into carriage return/line feed sequences ('\r\n').
GETKEY.C | Used by all stream routines that input characters. You may adapt this routine to your individual hardware (for example, matrix keyboards). The default version reads a character via the serial interface. No data conversions are performed.


C166: Memory Allocation

Memory Allocation

The following files contain the source code for the memory allocation routines.

C Source File | Description
CALLOC.C | This file contains the source code for the calloc library routine. This routine allocates memory for an array from the memory pool.
FREE.C | This file contains the source code for the free library routine. This routine returns a previously allocated memory block to the memory pool.
INIT_MEM.C | This file contains the source code for the init_mempool library routine. This routine allows you to specify the location and size of a memory pool from which memory may be allocated using the malloc, calloc, and realloc routines.
MALLOC.C | This file contains the source code for the malloc library routine. This routine allocates memory from the memory pool.
REALLOC.C | This file contains the source code for the realloc library routine. This routine resizes a previously allocated memory block.
XCALLOC.C | This file contains the source code for the xcalloc library routine. This routine allocates memory for an array from an xhuge memory pool.
XFREE.C | This file contains the source code for the xfree library routine. This routine returns a previously allocated memory block to the xhuge memory pool.
XINIT_MEM.C | This file contains the source code for the xinit_mempool library routine. This routine allows you to specify the location and size of an xhuge memory pool that memory may be allocated using the xmalloc, xcalloc, and xrealloc routines.
XMALLOC.C | This file contains the source code for the xmalloc library routine. This routine allocates memory from an xhuge memory pool.
XREALLOC.C | This file contains the source code for the xrealloc library routine. This routine resizes a previously allocated xhuge memory block.


C166: TRAPS.C

TRAPS.C

This file contains definitions of hardware trap routines for error conditions that may occur during run-time. This module may be included in a project during the debug phase to detect hardware problems. The TRAPS.C source file may be customized to provide error detection and correction for your applications.


C166: Optimizer

Optimizer

The C166 Compiler optimizes programs so that the generated code is as efficient (small and/or fast) as possible. There are several optimizations that are applied depending on device and various compiler options you select.

  • Optimizer Options
  • General Optimizations
  • 80C166-Specific Optimizations
  • XC16X-Specific Optimizations

Refer to the OPTIMIZE directive for more information on the various optimization levels that are available.


C166: Optimizer Options

Optimizer Options

  • NOALIAS
    Disables alias checking for pointer accesses. The C166 Compiler ignores pointer-write optimizations during the optimization phase. If a register holds a variable, the variable is reused, even when a pointer could modify that variable.
  • NODPPSAVE
    Does not save DPP registers in interrupt function. This directive may be used when the application does not modify the contents of DPP0 and DPP3. In 167 Mode (MOD167 directive), these DPP register are not modified.
  • NOFIXDPP
    Reassigns the DPP registers to allow as much as 64 KBytes space for near variables. Without this directive, the compiler assumes DPP2 is used for user-stack accesses.
  • OPTIMIZE(SIZE)
    Reduces program code by replacing common C operations (such as shift long) with subprograms.
  • STATIC
    Allocates automatic variables in static memory rather than on the user stack. The code is no longer reentrant, but the code size and execution speed improve.


C166: General Optimizations

General Optimizations

  • Common Tail Merging (Level 7)
    When there are multiple calls to a single function, some of the setup code can be reused, thereby reducing program size.
  • Constant Propagation (Level 6)
    The values of expressions are tracked and, when possible, constant values are inserted instead of variable accesses.
  • Constant Folding (Level 0)
    The compiler performs calculations that reduce expressions to numeric constants, where possible. This includes calculations of run-time addresses.
  • Dead Code Elimination (Level 1)
    Unused code fragments and artifacts are eliminated.
  • Global Common Subexpression Elimination (Level 4)
    Identical subexpressions within a function are calculated only once when possible. The intermediate result is stored in a register and reused.
  • Jump Negation (Level 1)
    Conditional jumps are closely examined to see if they can be streamlined or eliminated by the inversion of the test logic.
  • Jump Optimizing (Level 0)
    The compiler always extends jumps to the final target. Jumps to jumps are eliminated.
  • Life Variable Analysis (Level 5)
    Redundant store operations are replaced with the use of automatic variables.
  • Local Common Subexpression Elimination (Level 4)
    The compiler detects multiple uses of the same expression or subexpression. The result of the first expression is saved and reused when possible. Superfluous expression calculations are eliminated from the code.
  • Register Variable Lifetime Analysis (Level 8)
    Register variables are relocated in CPU registers to improve execution speed and code density.
  • Register Variables (Level 3)
    Automatic variables and function arguments are located in registers when possible. Reservation of data memory for these variables is omitted.
  • Unreachable Code Analysis (Level 3)
    Code that cannot be reached because of constant conditional expressions or unreferenced labels is removed.


C166: 80C166-Specific Optimizations

80C166-Specific Optimizations

  • Access Optimizing (Level 2)
    Variables accesses are directly included in operations. Intermediate registers are frequently unnecessary.
  • Case/Switch Optimizing (Level 4)
    Code involving switch and case statements is optimized using jump tables or jump strings.
  • Peephole Optimizing (Level 6)
    Redundant MOV instructions are removed. This includes unnecessary loading of objects from the memory as well as load operations with constants. Complex operations are replaced by simple operations when memory space or execution time can be saved.


C166: DPP Registers

DPP Registers

DPP Registers are assigned different values depending on the mode of the MCU.

  • In the NON-SEGMENTED mode of the XC16x, C16x, and ST10, the C166 Compiler assigns the values 0-3 to DPP0-DPP3 respectively. NON-SEGMENTED mode is used for the TINY memory model.
  • In the SEGMENTED mode of the XC16x, C16x, and ST10, the C166 Compiler allocates the DPP1-DPP3 registers to allow 16-bit (near) memory areas. SEGMENTED mode is used for the SMALL, COMPACT, MEDIUM, and LARGE memory models.

The following table shows how DPP registers are used in SEGMENTED mode:

Register | Description
DPP0 | Used to access far, huge, and xhuge objects when generating code for C166-compatible devices.
DPP1 | Used to access the NCONST group which includes variables defined with const near.
DPP2 | Used to access the NDATA group which includes variables defined with near.
DPP3 | Used to access the SDATA or SYSTEM group which includes variables defined with sdata, idata or bdata.

You may use the DPPUSE L166 Linker directive to reassign how DPP registers are used.

Note

  • The DPP3 register is used when generating C166-compatible code to speed up copy and compare functions that access two far or huge objects.
  • The MOD167 C166 Compiler directive prevents the compiler and run-time library from changing the DPP register contents.


C166: Stacks

Stacks

Two different stacks are available to C16x programs.

  • The System Stack, which contains return address (for CALL instructions). Return addresses are retrieved from the stack by the RET instructions. Additionally, the PUSH and POP instructions may be used to save and retrieve data from the system stack.
  • The User Stack, which contains the stack frame used for function variables.


C166: System Stack

System Stack

The system stack stores return addresses and registers used for local register variables. For interrupt functions, the system stack saves the PSW, CP, and status of the MUL/DIV unit. The size of the system stack area is defined and initialized in the startup code which is executed before the C main function is called. The startup code also sets the values for the STKOV (stack overflow) and STKUN (stack underflow) registers.

The default value of the system stack is 256 words which is typically enough for most complex applications. However, if the system stack overflows, a stack overflow trap (interrupt 4) is generated. This signals that the system stack is too small.

Note

  • Programs may swap the system stack area to external memory in the event of a stack overflow or underflow. However, the interrupt reaction time becomes unpredictable when this feature is used. In addition, you may encounter problems saving and restoring the MDL/MDH registers. Therefore, we recommend that you do not incorporate stack swapping features in your applications.


C166: User Stack

User Stack

The C16x architecture supports stack-relative addressing using the MOV [Ri+#displacement] and MOV [Ri-] instructions.

The Keil C166 Compiler uses the R0 register to maintain a user stack for parameter passing and for automatic (local) variables. The stack grows down from the top of memory. The size of the user-stack area and the user-stack pointer are defined and initialized in the startup code.

When passing arguments to a called function, the compiler stored them on the user stack in reverse order while decrementing the user stack pointer (R0) before each argument is "pushed" onto the stack. When a function with local variables is entered, it decrements the user stack pointer to make space for those local variables. For example:

Example Program
void func (char a, long b, int c)
{
char  x1, x2;
int   y;
float z;
.
.
.
}

Argument/Variable | Stack Position
int c | R0 + 14
long b | R0 + 10
GAP | R0 + 9
char a | R0 + 8
float z | R0 + 4
int y | R0 + 2
char x2 | R0 + 1
char x1 | R0 + 0

Note

  • The C166 Compiler optimizes some arguments and local variables into registers, which improves program performance and reduces the amount of stack space required. Optimizer level 0 disables this optimization and forces all arguments and local variables onto the stack. Refer to the OPTIMIZE directive for more information.
  • Single-byte variables (char and unsigned char) are passed as words on the user stack. The C166 Compiler inserts memory gaps to ensure the objects on the user stack are word-aligned. Word alignment of 16-bit, 32-bit, and 64-bit objects is required by the C16x architecture. Memory gaps are minimized as much as possible.


C166: Stack Sizes

Stack Sizes

The C166 Compiler cannot calculate the exact stack usage of your application program because it does not detect the actual program flow and can not know about the interrupt capabilities of your target system.

The default settings 512 bytes for the system stack and 4096 bytes for the user stack are typically enough for most applications.


C166: System Stack Size

System Stack Size

To determine the required size of the system stack, you may:

  1. Halt program execution at the main entry point and fill the memory area allocated to the system stack with a constant value (such as 0xA5).
  2. Execute all functions and interrupts in your application. Try to be as complete as possible. You may use the code coverage analysis in the µVision Debugger to make sure you have executed all functions.
  3. Calculate the number of bytes that were changed (from your constant value). This indicates the number of bytes of the stack that were used.

Note

  • The C16x architecture provides system stack overflow and underflow traps. You may add the TRAPS.C file (located in the \KEIL\C166\LIB\ folder) to your project to detect these interrupts.
  • The system stack must be large enough to execute the most complex interrupts in your system and have at least 40 bytes (20 words) of space remaining.


C166: User Stack Size

User Stack Size

To determine the required size of the user stack, you may:

  1. Halt program execution at the entery to the main C function and fill the memory area allocated to the user stack with a constant value (such as 0xA5). The address range of the user stack (the ?C_USERSTACK section) is listed in the linker map file (*.M66) under MEMORY MAP OF MODULE heading.
  2. Execute all functions and interrupts in your application. Try to be as complete as possible. You may use the code coverage analysis in the µVision Debugger to make sure you have executed all functions.
  3. Calculate the number of bytes that were changed (from your constant value). This indicates the number of bytes of the user stack that were used.
  4. Calculate the number of bytes of the stack that were changed (from your constant value). This indicates the number of bytes that were used. We recommend that you have at least 100 bytes (50 words) of additional stack space.

Note

  • We recommend that you have at least 100 bytes (50 words) of user stack space beyond the maximum calculated requirements.
  • If your application behaves strangely, try increasing the size of the user stack.


C166: XBUS Memory and Peripherals

XBUS Memory and Peripherals

The XBUS is the internal bus used to access external, off-chip devices (memory or peripherals). Access to the XBUS is slower then other on-chip hardware. Some C16x/XC16x derivatives have on-chip memory or peripherals that are connected to the XBUS.

  • On-chip XRAM is on-chip memory that is connected to the XBUS. This memory may be used for program variables or buffers.
  • XBUS Peripherals are on-chip peripherals that are connected to the XBUS instead of SFR memory.


C166: On-chip XRAM

On-chip XRAM

Some C16x/XC16x derivatives have additional on-chip XRAM. This memory is physically located on-chip but is accessed using the external data bus. This memory is subject to the same limitations as external memory (including timing).

You may declare XRAM variables using the sdata memory type. You may also use sdata pointers to access XRAM memory.

Note

  • Access to on-chip XRAM must be enabled with the _XRAMEN configuration variable in the startup code (START167.A66 or STARTV2.A66).
  • It is not possible to locate the system stack or register banks in the XRAM memory area (XRAM appears as external memory).


C166: XBUS Peripherals

XBUS Peripherals

XBUS peripherals are located in sdata memory. However, the memory they occupy may not be used as general purpose RAM. To use an XBUS peripheral you must allocate the memory with the RESERVE linker directive. You must also declare XBUS peripheral objects with the volatile keyword to prevent the compiler from optimizing XBUS peripheral accesses.

The following example shows how on-chip peripherals located in XRAM are accessed by the compiler.

stmt level    source
   1          /* Synchronous Serial Port (SSP), connected via XBUS */
   2          #define SSPCON0  (*((unsigned int volatile sdata *)  0xEF00))
   3
   4
   5          unsigned int test (void)  {
   6   1        SSPCON0 = 0x0004;
   7   1        while (SSPCON0 & 0x8000);   /* wait */
   8   1        return (SSPCON0);
   9   1      }
ASSEMBLY LISTING OF GENERATED OBJECT CODE
             ; FUNCTION test (BEGIN  RMASK = @0x4010)
                                           ; SOURCE LINE # 5
                                           ; SOURCE LINE # 6
0000 E044          MOV     R4,#04H
0002 F6F400EF      MOV     0EF00H,R4
                                           ; SOURCE LINE # 7
0006         ?C0001:
0006 F2F400EF      MOV     R4,0EF00H
000A 66F40080      AND     R4,#08000H
000E 3DFB          JMPR    cc_NZ,?C0001
0010         ?C0002:
                                           ; SOURCE LINE # 8
0010 F2F400EF      MOV     R4,0EF00H
                                           ; SOURCE LINE # 9
0014 CB00          RET
             ; FUNCTION test (END    RMASK = @0x4010)

Using XBUS CAN Registers

The CAN controller, integrated into some C167x derivatives, is an XBUS peripheral. The C166 Compiler provides a header file (CAN167.H) that defines all the CAN-related registers (in sdata memory) and several status information masks.

SFR Name | Address | Description
CAN_CTL_STAT | 0xEF00 | Control/Status Register
CAN_INTID | 0xEF02 | Interrupt Register
CAN_BIT_TIMING | 0xEF04 | Bit-Timing Register
CAN_MASK_SHORT | 0xEF06 | Global Mask Short
CAN_UMASK_LONG | 0xEF08 | Upper Global Mask Long
CAN_LMASK_LONG | 0xEF0A | Lower Global Mask Long
CAN_UMASK_LAST | 0xEF0C | Upper Mask of Last Message
CAN_LMASK_LAST | 0xEF0E | Lower Mask of Last Message
CAN_OBJ[15] | 0xEF10 | Message Object: Each of the 15 possible message objects uses 16 bytes defined by the can_obj structure.
/* Structure for a single CAN message object */
/* A total of 15 such object structures exists (starting at EF10H) */
struct can_obj {
  unsigned int  msg_ctl;   /* Message Control       */
  unsigned long arbitr;    /* Arbitration           */
  unsigned char msg_cfg;   /* Message Configuration */
  unsigned char msg[8];    /* Message Data 0-7      */
  unsigned char dummy;     /* Reserved Byte         */
};

The following program example shows how to use the CAN message object to setup various CAN registers.

#include <can167.h>

void test_can (void)  {
  /* init CAN controller */
  CAN_CTL_STAT = 1;
  /* init arbitration register for object 0 */
  CAN_OBJ[0].arbitr = 0xE0000000L;
  /* write to message buffer for object 0 */
  CAN_OBJ[0].msg[0] = 0;
  CAN_OBJ[0].msg[1] = 1;
  CAN_OBJ[0].msg[2] = 2;
  /* write to message configuration for object 0 */
  CAN_OBJ[0].msg_cfg = 0x38;

  /* init arbitration register for object 1 */
  CAN_OBJ[1].arbitr = 0xE0010000L;
}


C166: Interfacing C to Assembler

Interfacing C to Assembler

You can easily interface your C programs to routines written in XC16x/C16x/ST10 assembly language. The A166 Assembler is a macro assembler that emits object modules in OMF166 format. By following a few programming rules, you can call assembly routines from C and vice versa. Public variables declared in the assembly module are available to your C programs.

There are several reasons to call an assembly routine from your C program.

  • You have assembly code already written that you wish to use.
  • You need to improve the speed of a particular function.
  • You want to manipulate SFRs or memory-mapped I/O devices directly from assembly.

This section describes how to write assembly routines that can be directly interfaced to C programs.

For an assembly routine to be called from C, it must be aware of the parameter passing and return value conventions used in C functions. For all practical purposes, the assembly routine must appear to be a C function.


C166: Function Parameters

Function Parameters

C functions pass up to five parameters in registers (R8-R12). Bit parameters are passed in R15. Parameters that do not fit into R8-R12 are passed on the user stack and are accessed using [R0+#disp] instructions.

The following examples demonstrate the C166 parameter passing conventions:

void func1 (
  char a)	       /* 1st parameter passed in R8 */

The above function has one argument that easily fits into a single 16-bit register (R8).

void func2 (
  int b,        /* 1st parameter passed in R8  */
  int c,        /* 2nd parameter passed in R9  */
  int near *d,  /* 3rd parameter passed in R10 */
  char e,       /* 4th parameter passed in R11 */
  char f)       /* 5th parameter passed in R12 */

The above function has five arguments. All fit into R8-R12.

void func3 (
  long g,       /* 1st parameter passed in R8/R9   */
  int far *h,   /* 2nd parameter passed in R10/R11 */
  int i,        /* 3rd parameter passed in R12     */
  long j)       /* 4th parameter cannot be located in registers */

The above function has four arguments. The first three use all available registers. The fourth argument must be passed on the user stack.

void func4 (
  double k,     /* 1st parameter passed in R8/R9/R10/R11 */
  long j)       /* 2nd parameter LSW passed in R12 */
                /* MSW passed on the user stack */

The above function has two arguments. The first argument uses four of the five registers. The LSW of the second argument is passed in R12 and the MSW is passed on the user stack.

void func5 (
  bit m,	       /* 1st parameter passed in R15.0 */
  bit n)	       /* 2nd parameter passed in R15.1 */

The above function has two bit arguments that passed in R15.

void func6 (
  char o,       /* 1st parameter passed in R8    */
  bit p,	       /* 2nd parameter passed in R15.0 */
  char q,       /* 3rd parameter passed in R9    */
  bit r)	       /* 4th parameter passed in R15.1 */

The above function has four arguments (two are bits) that are passed in registers and in R15 (for the bits).


C166: Function Return Values

Function Return Values

Function return values are always passed using MCU registers. The following table lists the possible return values and the registers used for each.

Return Type | Register | Description
bit | R4.0 | Single bit returned in R4.0.
char, unsigned char | RL4 | Single byte type returned in RL4.
int, unsigned int, near pointer | R4 | Two byte (16-bit) type returned in R4.
long, unsigned long, far pointer, huge pointer | R4 & R5 | LSB in R4, MSB in R5.
float | R4 & R5 | 32-Bit IEEE format.
double | R4-R7 | 64-Bit IEEE format.


C166: Using the SRC Directive

Using the SRC Directive

The C166 Compiler can create assembly source files that you assemble with the A166 Assembler. These SRC files can help you determine the argument passing conventions between C and assembly.

To create an assembly source file, you must use the SRC directive with the C166 Compiler. For example:

#pragma SRC
#pragma SMALL

unsigned int asmfunc1 (
  unsigned int arg)
{
return (1 + arg);
}

For this example, the compiler generates the following SRC file.

$NOMACRO
$SEGMENTED CASE NOMOD166
;
; 'ASM1.SRC' GENERATED FROM INPUT FILE 'ASM1.C'
; COMPILER INVOKED BY:
;       C166.EXE ASM1.C CODE SRC
;
$MODINF (11)
        NAME ASM1

        NCODE   CGROUP  ?PR?ASM1
        ASSUME  DPP3: SYSTEM
        REGDEF  R0 - R15

        ?PR?ASM1  SECTION  CODE WORD 'NCODE'
; line 1: #pragma SRC
; line 2: #pragma SMALL
; line 3:
; line 4: unsigned int asmfunc1 (unsigned int arg)  {

        asmfunc1  PROC  NEAR
        PUBLIC  asmfunc1
; FUNCTION asmfunc1 (BEGIN  RMASK = @0x0010)
;---- Variable 'arg' assigned to Register 'R8' ----
; line 5:   return (1 + arg);
        MOV     R4,R8
        ADD     R4,#1
; line 6: }
        RET

; FUNCTION asmfunc1 (END    RMASK = @0x0010)
        asmfunc1  ENDP
        ?PR?T  ENDS

        END


C166: Register Usage

Register Usage

Assembler functions may destroy the contents of R1-R12, PSW, MDL, MDH, MDC, and DPP0. When invoking a C function from assembly, assume that these registers are destroyed.

When using the mac directive the compiler uses in addition the mac registers msw, mal, mah, mrw, and idx0. when code is generated with the MAC directive, these registers are used by C functions (in addition to the register listed above). When invoking a C function form assembly you need therefore to assume that these registers are destroyed too.

The following registers have special meaning and must be preserved by the assembler subroutine.

Register | Description
R0 | R0 is the user stack pointer. At the end of the assembler subroutine the value of R0 must be the same as at the start of the routine.
R13 | This register may be used but its contents must be saved (on entry) and restored (before returning).
R14 | This register may be used but its contents must be saved (on entry) and restored (before returning).
R15 | This register may be used but its contents must be saved (on entry) and restored (before returning).
DPP1 | This DPP register may not be modified by assembler subroutines. It contains the memory class page and may be used in an interrupt service routine that interrupts the assembler subroutine.
DPP2 | This DPP register may not be modified by assembler subroutines. It contains the memory class page and may be used in an interrupt service routine that interrupts the assembler subroutine.
DPP3 | If DPP3 is modified in the assembler subroutine, it must be reset to 3 (SYSTEM PAGE) before returning.

Note

  • DPP0 is used only when the MOD167 C166 Compiler directive is not specified.
  • If your assembler programs alter DPP0, the DPPUSE L166 Linker directive may not be used to assign DPP0 to the near memory area.
  • If your assembler programs alter DPP0 or DPP3, the NODPPSAVE C166 Compiler directive may not be used to bypass saving and restoring DPP0 and DPP3 in interrupts.


C166: Example Routines

Example Routines

The following program examples show you how to pass parameters to and from assembly routines. The equivalent C source for the assembler program is included in the comments.

  • Tiny Model Example
  • Small Model Example
  • Compact Model Example
  • Medium Model Example
  • Large Model Example


C166: TINY Model

TINY Model

LOC  OBJ       LINE     SOURCE
                  1     ; A166 must be CASE sensitive for interfacing with C166.
                  2     $CASE
                  3     ; TINY model works in NON-SEGMENTED mode of the 80C166.
                  4     $NONSEGMENTED
                  5
                  6                     NAME    A166_modul
                  7
                  8     ;  /***********************************/
                  9     ;  /* Sample Assembler to C Interface */
                 10     ;  /***********************************/
                 11     ;
                 12     ;  extern int func1 (int a1, int a2, bit b);
                 13     ;
                 14     ;  extern bit flag;
                 15     ;  extern int near val;
                 16     ;
                 17     ;  int func2 (int *x1, int *x2)  {
                 18     ;    int y;
                 19     ;
                 20     ;    y = func1 (*x1, *x2, flag);
                 21     ;    val += y;
                 22     ;    return (y);
                 23     ;  }
                 24
                 25     EXTRN   func1 : NEAR
                 26     EXTRN   val   : WORD
                 27     EXTRN   flag  : BIT
                 28
                 29     ?PR?A166_modul  SECTION CODE 'NCODE'
                 30
                 31     PUBLIC          func2           ; entry point for func2
                 32
                 33     func2           PROC    NEAR
                 34     ;---- Variable 'x2' is passed in Register 'R9'
                 35     ;---- Variable 'x1' is passed in Register 'R8'
0000 ECFF        36                     PUSH    R15     ; Save R15 because of Bit Parameter
0002 A899        37                     MOV     R9,[R9]
0004 A888        38                     MOV     R8,[R8]
0006 4A??FF?0 E  39                     BMOV    R15.0,flag
000A CA00???? E  40                     CALLA   cc_UC,func1
                 41     ;---- The function value of 'func1' is returned in Register 'R4'
                 42     ;---- temporary Variable 'y' is saved in Register 'R5'
000E 04F4???? E  43                     ADD     val,R4  ; TINY requires no DPP
                 44
0012 FCFF        45                     POP     R15     ; restore R15
                 46     ;---- The function value 'y' is placed in 'R4'
0014 CB00        47                     RET
                 48     func2           ENDP
                 49
                 50     ?PR?A166_modul  ENDS
                 51
                 52                     END


C166: SMALL Model

SMALL Model

LOC  OBJ       LINE     SOURCE
                  1     ; A166 must be CASE sensitive for interfacing with C166.
                  2     $CASE
                  3     ; SMALL model works in SEGMENTED mode of the 80C166.
                  4     $SEGMENTED
                  5
                  6                     NAME    A166_modul
                  7     ;  /***********************************/
                  8     ;  /* Sample Assembler to C Interface */
                  9     ;  /***********************************/
                 10     ;
                 11     ;  extern int func1 (int a1, int a2, bit b);
                 12     ;
                 13     ;  extern bit flag;
                 14     ;  extern int near val;
                 15     ;
                 16     ;  int func2 (int *x1, int *x2)  {
                 17     ;    int y;
                 18     ;
                 19     ;    y = func1 (*x1, *x2, flag);
                 20     ;    val += y;
                 21     ;    return (y);
                 22     ;  }
                 23
                 24     EXTRN   func1 : NEAR
                 25     EXTRN   val   : WORD        ; near value based DPP2
                 26     EXTRN   flag  : BIT
                 27
                 28     ?PR?A166_modul  SECTION CODE 'NCODE'
                 29     NCODE           CGROUP  ?PR?A166_modul
                 30
                 31     PUBLIC          func2           ; entry point for func2
                 32
                 33     func2           PROC    NEAR
                 34     ;---- Variable 'x2' is passed in Register 'R9'.
                 35     ;---- Variable 'x1' is passed in Register 'R8'.
0000 ECFF        36                     PUSH    R15     ; Save R15 because of Bit Parameter
0002 A899        37                     MOV     R9,[R9]
0004 A888        38                     MOV     R8,[R8]
0006 4A??FF?0 E  39                     BMOV    R15.0,flag
000A CA00???? E  40                     CALLA   cc_UC,func1
                 41     ;---- The function value of 'func1' is returned in Register 'R4'.
                 42     ;---- temporary Variable 'y' is saved in Register 'R5'.
000E 04F4???? E  43                     ADD     DPP2:val,R4   ; NEAR variable requires DPP2
                 44
0012 FCFF        45                     POP     R15     ; restore R15
                 46     ;---- The function value 'y' is placed in 'R4'
0014 CB00        47                     RET
                 48     func2           ENDP
                 49
                 50     ?PR?A166_modul  ENDS
                 51
                 52                     END


C166: COMPACT Model

COMPACT Model

LOC  OBJ       LINE     SOURCE
                  1     ; A166 must be CASE sensitive for interfacing with C166.
                  2     $CASE
                  3     ; COMPACT model works in SEGMENTED mode of the 80C166.
                  4     $SEGMENTED
                  5
                  6                     NAME    A166_modul
                  7     ;  /***********************************/
                  8     ;  /* Sample Assembler to C Interface */
                  9     ;  /***********************************/
                 10     ;
                 11     ;  extern int func1 (int a1, int a2, bit b);
                 12     ;
                 13     ;  extern bit flag;
                 14     ;  extern int near val;
                 15     ;
                 16     ;  int func2 (int *x1, int *x2)  {
                 17     ;    int y;
                 18     ;
                 19     ;    y = func1 (*x1, *x2, flag);
                 20     ;    val += y;
                 21     ;    return (y);
                 22     ;  }
                 23
                 24     EXTRN   func1 : NEAR
                 25     EXTRN   val   : WORD        ; near value based DPP2
                 26     EXTRN   flag  : BIT
                 27
                 28     ?PR?A166_modul  SECTION CODE 'NCODE'
                 29     NCODE           CGROUP  ?PR?A166_modul
                 30
                 31     PUBLIC          func2           ; entry point for func2
                 32
                 33     ASSUME  DPP3:SYSTEM             ; required for SFR accesses
                 34
                 35     func2           PROC    NEAR
                 36     ;---- Variable 'x2' is a far * and passed in Register 'R10, R11'.
                 37     ;---- Variable 'x1' is a far * and passed in Register 'R8, R9'.
0000 ECFF        38                     PUSH    R15     ; Save R15 because of Bit Parameter
0002 F6F900FE    39                     MOV     DPP0,R9
0006 CC00        40                     NOP
0008 A888        41                     MOV     R8,[R8]
000A F6FB00FE    42                     MOV     DPP0,R11
000E CC00        43                     NOP
0010 A89A        44                     MOV     R9,[R10]
0012 4A??FF?0 E  45                     BMOV    R15.0,flag
0016 CA00???? E  46                     CALLA   cc_UC,func1
                 47     ;---- The function value of 'func1' is returned in Register 'R4'
                 48     ;---- temporary Variable 'y' is saved in Register 'R5'.
001A 04F4???? E  49                     ADD     DPP2:val,R4   ; NEAR variable requires DPP2
                 50
001E FCFF        51                     POP     R15     ; restore R15
                 52     ;---- The function value 'y' is placed in 'R4'
0020 CB00        53                     RET
                 54     func2           ENDP
                 55
                 56     ?PR?A166_modul  ENDS
                 57
                 58                     END


C166: MEDIUM Model

MEDIUM Model

LOC  OBJ       LINE     SOURCE
                  1     ; A166 must be CASE sensitive for interfacing with C166.
                  2     $CASE
                  3     ; MEDIUM model works in SEGMENTED mode of the 80C166.
                  4     $SEGMENTED
                  5
                  6                     NAME    A166_modul
                  7     ;  /***********************************/
                  8     ;  /* Sample Assembler to C Interface */
                  9     ;  /***********************************/
                 10     ;
                 11     ;  extern int func1 (int a1, int a2, bit b);
                 12     ;
                 13     ;  extern bit flag;
                 14     ;  extern int near val;
                 15     ;
                 16     ;  int func2 (int *x1, int *x2)  {
                 17     ;    int y;
                 18     ;
                 19     ;    y = func1 (*x1, *x2, flag);
                 20     ;    val += y;
                 21     ;    return (y);
                 22     ;  }
                 23
                 24     EXTRN   func1 : FAR
                 25     EXTRN   val   : WORD       ; near value based DPP2
                 26     EXTRN   flag  : BIT
                 27
                 28     ?PR?A166_modul  SECTION CODE 'NCODE'
                 29
                 30     PUBLIC          func2           ; entry point for func2
                 31
                 32     func2           PROC    FAR
                 33     ;---- Variable 'x2' is passed in Register 'R9'.
                 34     ;---- Variable 'x1' is passed in Register 'R8'.
0000 ECFF        35                     PUSH    R15     ; Save R15 because of Bit Parameter
0002 A899        36                     MOV     R9,[R9]
0004 A888        37                     MOV     R8,[R8]
0006 4A??FF?0 E  38                     BMOV    R15.0,flag
000A DA?????? E  39                     CALLS   SEG (func1), func1
                 40     ;---- The function value of 'func1' is returned in Register 'R4'.
                 41     ;---- temporary Variable 'y' is saved in Register 'R5'.
000E 04F4???? E  42                     ADD     DPP2:val,R4   ; NEAR variable requires DPP2
                 43
0012 FCFF        44                     POP     R15     ; restore R15
                 45     ;---- The function value 'y' is placed in 'R4'
0014 DB00        46                     RETS
                 47
                 48     func2           ENDP
                 49
                 50     ?PR?A166_modul  ENDS
                 51
                 52                     END


C166: LARGE Model

LARGE Model

LOC  OBJ       LINE     SOURCE
                  1     ; A166 must be CASE sensitive for interfacing with C166.
                  2     $CASE
                  3     ; LARGE model works in SEGMENTED mode of the 80C166.
                  4     $SEGMENTED
                  5
                  6                     NAME    A166_modul
                  7     ;  /***********************************/
                  8     ;  /* Sample Assembler to C Interface */
                  9     ;  /***********************************/
                 10     ;
                 11     ;  extern int func1 (int a1, int a2, bit b);
                 12     ;
                 13     ;  extern bit flag;
                 14     ;  extern int near val;
                 15     ;
                 16     ;  int func2 (int *x1, int *x2)  {
                 17     ;    int y;
                 18     ;
                 19     ;    y = func1 (*x1, *x2, flag);
                 20     ;    val += y;
                 21     ;    return (y);
                 22     ;  }
                 23
                 24     EXTRN   func1 : FAR
                 25     EXTRN   val   : WORD       ; near value based DPP2
                 26     EXTRN   flag  : BIT
                 27
                 28     ?PR?A166_modul  SECTION CODE 'NCODE'
                 29
                 30     PUBLIC          func2           ; entry point for func2
                 31
                 32     ASSUME  DPP3:SYSTEM             ; required for SFR accesses
                 33
                 34     func2           PROC    FAR
                 35     ;---- Variable 'x2' is a far * and passed in Register 'R10, R11'.
                 36     ;---- Variable 'x1' is a far * and passed in Register 'R8, R9'.
0000 ECFF        37                     PUSH    R15     ; Save R15 because of Bit Parameter
0002 F6F900FE    38                     MOV     DPP0,R9
0006 CC00        39                     NOP
0008 A888        40                     MOV     R8,[R8]
000A F6FB00FE    41                     MOV     DPP0,R11
000E CC00        42                     NOP
0010 A89A        43                     MOV     R9,[R10]
0012 4A??FF?0 E  44                     BMOV    R15.0,flag
0016 DA?????? E  45                     CALLS   SEG (func1), func1
                 46     ;---- The function value of 'func1' is returned in Register 'R4'.
                 47     ;---- temporary Variable 'y' is saved in Register 'R5'.
001A 04F4???? E  48                     ADD     DPP2:val,R4   ; NEAR variable requires DPP2
                 49
001E FCFF        50                     POP     R15     ; restore R15
                 51     ;---- The function value 'y' is placed in 'R4'
0020 DB00        52                     RETS
                 53
                 54     func2           ENDP
                 55
                 56     ?PR?A166_modul  ENDS
                 57
                 58                     END


C166: Data Storage Formats

Data Storage Formats

The C166 Compiler offers a number of data types you may use in your C programs. The following table lists these types along with size requirements and value ranges.

Data Type | Bits | Bytes | Value Range
bit | 1 | - | 0 to 1
signed char | 8 | 1 | -128 to + 127
unsigned char | 8 | 1 | 0 to 255
enum | 16 | 2 | -32768 to +32767
signed int | 16 | 2 | -32768 to +32767
unsigned int | 16 | 2 | 0 to 65535
signed short | 16 | 2 | -32768 to +32767
unsigned short | 16 | 2 | 0 to 65535
signed long | 32 | 4 | -2147483648 to 2147483647
unsigned long | 32 | 4 | 0 to 4294967295
float | 32 | 4 | ±1.175494E-38 to ± 3.402823E+38
double | 64 | 8 | ±1.7E-308 to ±1.7E+308
near pointer | 16 | 2 | 16-bit near address
far pointer | 32 | 4 | 32-bit far address
huge pointer | 32 | 4 | 32-bit huge address
xhuge pointer | 32 | 4 | 32-bit xhuge address

Other data types, such as structures and unions, may contain scalars from this table. Furthermore, because of the 16-bit architecture of the C16x/ST10 family, each variable (except signed/unsigned char) must be word-aligned. For example, in structures, a one-byte gap is necessary between a char and an int member.


C166: Bit Variables

Bit Variables

Scalars of type bit are stored using a single bit. Pointers to bits and arrays of bits are not allowed. Bit objects are always located in the bit-addressable on-chip memory of the C16x/ST10/XC16x.


C166: 1-byte Scalars

1-byte Scalars

Scalars of type signed char and unsigned char are stored in a single byte (8-bits).


C166: 2-byte Scalars

2-byte Scalars

Scalars of type signed int, unsigned int, signed short, unsigned short, and enum are stored using two bytes (16 bits). The bytes are stored little endian or low to high order. For example, the integer value 0x1234 is stored in memory as follows:

 | Address+0 | Address+1
Contents | 0x34 | 0x12


C166: 4-byte Scalars

4-byte Scalars

Scalars of type signed long and unsigned long are stored using four bytes (32 bits). The bytes are stored little endian or low to high order. For example, the long value 0x12345678 is stored in memory as follows:

 | Address+0 | Address+1 | Address+2 | Address+3
Contents | 0x78 | 0x56 | 0x34 | 0x12


C166: float Scalars

float Scalars

Scalars of type float are stored using four bytes (32-bits). The format used follows the IEEE-754 standard and is stored little endian or LSB first.

A floating-point number is expressed as the product of two parts: the mantissa and a power of two. For example:

±mantissa × 2exponent

The mantissa represents the actual binary digits of the floating-point number.

The power of two is represented by the exponent. The stored form of the exponent is an 8-bit value from 0 to 255. The actual value of the exponent is calculated by subtracting 127 from the stored value (0 to 255) giving a range of –127 to +128.

The mantissa is a 24-bit value (representing about seven decimal digits) whose most significant bit (MSB) is always 1 and is, therefore, not stored. There is also a sign bit that indicates whether the floating-point number is positive or negative.

Floating-point numbers are stored on word boundaries in the following format:

 | Address+0 | Address+1 | Address+2 | Address+3
Contents | MMMM MMMM | MMMM MMMM | EMMM MMMM | SEEE EEEE

Where

S | represents the sign bit where 1 is negative and 0 is positive.
E | is the exponent with an offset of 127.
M | is the 24-bit mantissa (stored in 23 bits).

Zero is a special value denoted with an exponent field of 0 and a mantissa of 0.

Using the above format, the floating-point number -12.5 is stored as a hexadecimal value of 0xC1480000. In memory, this value appears as follows:

 | Address+0 | Address+1 | Address+2 | Address+3
Contents | 0x00 | 0x00 | 0x48 | 0xC1

It is fairly simple to convert floating-point numbers to and from their hexadecimal storage equivalents. The following example demonstrates how this is done for the value -12.5 shown above.

The floating-point storage representation is not an intuitive format. To convert this to a floating-point number, the bits must be separated as specified in the floating-point number storage format table shown above. For example:

 | Address+0 | Address+1 | Address+2 | Address+3
Format | MMMMMMMM | MMMMMMMM | EMMMMMMM | SEEEEEEE
Binary | 00000000 | 00000000 | 01001000 | 11000001
Hex | 00 | 00 | 48 | C1

From this illustration, you can determine the following:

  • The sign bit is 1, indicating a negative number.
  • The exponent value is 10000010 binary or 130 decimal. Subtracting 127 from 130 leaves 3, which is the actual exponent.
  • The mantissa appears as the following binary number:
    10010000000000000000000

There is an understood binary point at the left of the mantissa that is always preceded by a 1. This digit is omitted from the stored form of the floating-point number. Adding 1 and the binary point to the beginning of the mantissa gives the following value:

1.10010000000000000000000

To adjust the mantissa for the exponent, move the decimal point to the left for negative exponent values or right for positive exponent values. Since the exponent is three, the mantissa is adjusted as follows:

1100.10000000000000000000

The result is a binary floating-point number. Binary digits to the left of the decimal point represent the power of two corresponding to their position. For example, 1100 represents (1 × 23) + (1 × 22) + (0 × 21) + (0 × 20), which is 12.

Binary digits to the right of the decimal point also represent the power of two corresponding to their position. However, the powers are negative. For example, .100... represents (1 × 2-1) + (0 × 2-2) + (0 × 2-3) + ... which equals .5.

The sum of these values is 12.5. Because the sign bit was set, this number should be negative.

So, the hexadecimal value 0xC1480000 is -12.5.


C166: float Errors

float Errors

The C16x/ST10/XC16x does not contain an interrupt vector to trap floating-point errors. Therefore, your software must appropriately respond to these error conditions.

In addition to the normal floating-point values, a float number may contain a binary error value. These values are defined as a part of the IEEE standard and are used whenever an error occurs during normal processing of floating-point operations. Your code should check for possible arithmetic errors at the end of each floating-point operation.

Name | Value | Meaning
NaN | 0xFFFFFFF | Not a number
+INF | 0x7F80000 | Positive infinity (positive overflow)
-INF | 0xFF80000 | Negative infinity (negative overflow)

Note

  • The C166 library function _chkfloat_ allows you to quickly check the floating-point status of float numbers.


C166: double Scalars

double Scalars

Scalars of type double are stored using eight bytes (64 bits). The format used corresponds to that of the IEEE-754 standard and is stored little endian or LSB first.

A double precision floating-point number is expressed as the product of two parts: the mantissa and a power of two. For example:

±mantissa × 2exponent

The mantissa represents the actual binary digits of the floating-point number.

The power of two is represented by the exponent. The stored form of the exponent is an 11-bit value from 0 to 2047. The actual value of the exponent is calculated by subtracting 1023 from the stored value (0 to 2047) giving a range of –1023 to +1024.

The mantissa is a 53-bit value (representing about thirteen decimal digits) whose most significant bit (MSB) is always 1 and is, therefore, not stored. There is also a sign bit that indicates whether the floating-point number is positive or negative.

Double precision floating-point numbers are stored on word boundaries in the following format:

 | Address+0 | Address+1 | Address+2 | Address+3
Contents | MMMM MMMM | MMMM MMMM | MMMM MMMM | MMMM MMMM

 | Address+4 | Address+5 | Address+6 | Address+7
Contents | MMMM MMMM | MMMM MMMM | EEEE MMMM | SEEE EEEE

Where

S | represents the sign bit where 1 is negative and 0 is positive.
E | is the exponent with an offset of 1023.
M | is the 53-bit mantissa (stored in 52 bits).

Zero is a special value denoted with an exponent field of 0 and a mantissa of 0.

Using the above format, the floating-point number -12.5 is stored as a hexadecimal value of 0xC029000000000000. In memory, this value appears as follows:

 | Address+0 | Address+1 | Address+2 | Address+3
Contents | 0x00 | 0x00 | 0x00 | 0x00

 | Address+4 | Address+5 | Address+6 | Address+7
Contents | 0x00 | 0x00 | 0x29 | 0xC0

It is fairly simple to convert floating-point numbers to and from their hexadecimal storage equivalents. The following example demonstrates how this is done for the value -12.5 shown above.

The floating-point storage representation is not an intuitive format. To convert this to a floating-point number, the bits must be separated as specified in the floating-point number storage format table shown above. For example:

 | Address+0 | Address+1 | Address+2 | Address+3
Format | MMMMMMMM | MMMMMMMM | MMMMMMMM | MMMMMMMM
Binary | 00000000 | 00000000 | 00000000 | 00000000
Hex | 00 | 00 | 00 | 00

 | Address+4 | Address+5 | Address+6 | Address+7
Format | MMMMMMMM | MMMMMMMM | EEEEMMMM | SEEEEEEE
Binary | 00000000 | 00000000 | 00101001 | 11000000
Hex | 00 | 00 | 29 | C0

From this illustration, you can determine the following:

  • The sign bit is 1, indicating a negative number.
  • The exponent value is 100 0000 0010 binary or 1026 decimal. Subtracting 1023 from 1026 leaves 3, which is the actual exponent.
  • The mantissa appears as the following binary number:
    1001 00000000 00000000 00000000 00000000 00000000 00000000

There is an understood binary point at the left of the mantissa that is always preceded by a 1. This digit is omitted from the stored form of the floating-point number. Adding 1 and the binary point to the beginning of the mantissa gives the following value:

1.1001000000000000000000000000000000000000000000000000

To adjust the mantissa for the exponent, move the decimal point to the left for negative exponent values or right for positive exponent values. Since the exponent is three, the mantissa is adjusted as follows:

1100.1000000000000000000000000000000000000000000000000

The result is a binary floating-point number. Binary digits to the left of the decimal point represent the power of two corresponding to their position. For example, 1100 represents (1 × 23) + (1 × 22) + (0 × 21) + (0 × 20), which is 12.

Binary digits to the right of the decimal point also represent the power of two corresponding to their position. However, the powers are negative. For example, .100... represents (1 × 2-1) + (0 × 2-2) + (0 × 2-3) + ... which equals .5.

The sum of these values is 12.5. Because the sign bit was set, this number should be negative.

So, the hexadecimal value 0xC029000000000000 is -12.5.


C166: double Errors

double Errors

The C16x/ST10/XC16x does not contain an interrupt vector to trap floating-point errors. Therefore, your software must be prepared to respond to these error conditions.

In addition to the normal floating-point values, a double number can contain a binary error value. Binary error values are defined as a part of the IEEE standard and used whenever an error occurs during normal processing of floating-point operations. Your code should check for possible arithmetic errors at the end of each floating-point operation.

Name | Value | Meaning
NaN | 0xFFFFFFF FFFFFFFF | Not a number
+INF | 0x7FF0000 00000000 | Positive infinity (positive overflow)
-INF | 0xFFF0000 00000000 | Negative infinity (negative overflow)

Note

  • The C166 library function _chkdouble_ allows you to quickly check the floating-point status of double numbers.


C166: near Pointers

near Pointers

Pointers to near objects are stored using two bytes (16 bits). The bytes are stored little endian or low to high order. In the tiny memory model, near pointers contain a 16-bit memory address. In all other memory models, near pointers contain a 14-bit offset in bits 0-13 and a 2-bit DPP selector in bits 14 and 15.

A near pointer is stored in memory at a word boundary as follows:

 | Address+0 | Address+1
Contents | Offset (LSB) | Offset (MSB)

The 2-bit DPP selector allows access to the following memory types:

DPP Selector Value | Memory Type
0 | Unused in C166 near pointers.
1 | NCONST group (objects defined with const near).
2 | NDATA group (objects defined with near).
3 | SDATA or SYSTEM group (objects defined with sdata, idata, or bdata).

You may use the L166 Linker DPPUSE directive to manually configure the DPP register assignments.


C166: far Pointers

far Pointers

Pointers to far objects are stored using four bytes (32 bits). The bytes are stored little endian or low to high order. The first word contains the 14-bit memory offset (bits 14 and 15 are always 0). The second word contains the page number (or segment number for function pointers). The memory address is calculated as follows:

Variable Address = (Page * 0x4000L) + Offset

Function Address = (Segment * 0x10000L) + Offset

A far pointer is stored in memory at a word boundary as follows:

 | Address+0 | Address+1 | Address+2 | Address+3
Contents | Offset (LSB) | Offset (MSB) | Page (LSB) or Segment (LSB) | Page (MSB) or Segment (MSB)

A far pointer can access objects up to 16K in size in any memory area. Objects larger than 16K must be accessed using huge or xhuge pointers.


C166: huge Pointers

huge Pointers

Pointers to huge objects are stored using four bytes (32 bits). The bytes are stored little endian or low to high order. The first word contains the 16-bit memory offset. The second word contains the segment number. The memory address is calculated as follows:

Address = (Segment * 0x10000L) + Offset

A huge pointer is stored in memory at a word boundary as follows:

 | Address+0 | Address+1 | Address+2 | Address+3
Contents | Offset (LSB) | Offset (MSB) | Segment (LSB) | Segment (MSB)

A huge pointer can access objects up to 64K in size in any memory area. Objects larger than 64K must be accessed using xhuge pointers.


C166: xhuge Pointers

xhuge Pointers

Pointers to xhuge objects are stored using four bytes (32 bits). The bytes are stored little endian or low to high order. The first word contains the 16-bit memory offset. The second word contains the segment number. The memory address is calculated as follows:

Address = (Segment * 0x10000L) + Offset

An xhuge pointer is stored in memory at a word boundary as follows:

 | Address+0 | Address+1 | Address+2 | Address+3
Contents | Offset (LSB) | Offset (MSB) | Segment (LSB) | Segment (MSB)

An xhuge pointer can access objects of any size in any memory area.


C166: Absolute Memory Access

Absolute Memory Access

The C programming language does not support a method of explicitly specifying the memory location of a static or global variable. You must do that manually using one of the following methods:

  • Absolute access macros.
  • Linker location controls.


C166: Absolute Access Macros

Absolute Access Macros

The absolute memory access macros allow you to directly access the various memory areas of the C16x/ST10/XC16x. These macros require that you specify the address you wish to read or write.

HARRAY
HVAR 		MARRAY
MVAR 		XARRAY
XVAR


C166: Linker Location Controls

Linker Location Controls

Another method of referencing explicit memory locations is to declare the variables in a stand-alone C module and use the linker location directives to locate them at an absolute memory address.

In the following example, the alarm_control structure is defined containint the variables to locate.

.
.
.
struct alarm_st  {
  unsigned int alarm_number;
  unsigned char enable flag;
  unsigned int time_delay;
  unsigned char status;
 };

struct alarm_st far alarm_control;
.
.
.

The C166 Compiler generates an object file for ALMCTRL.C and includes a section for variables in the far memory area. Since alarm_control is the only variable declared in this module, it is the only variable in far section. The name of the section is ?FD0?ALMCTRL. If the NOINIT directive was used the section is named ?FD?ALMCTRL.

The L166 Linker can locate a section at any address. The following example shows how to locate the ?FD0?ALMCTRL section starting at address 128000h.

L166 ... almctrl.obj SECTIONS(?FD0?ALMCTRL%FDATA0(128000h)) ...

The SECTIONS linker directive instructs the linker to locate the section named ?FD0?ALMCTRL in the FDATA0 class at address 128000h. Refer to the L166 Linker User's Guide for more information.


C166: Debugging

Debugging

The C166 Compiler uses the Siemens Object Format (OMF-166) for object files. Complete symbol information is written to the generated object file. This allows any C16x/ST10 emulator to be used for program debugging.

The DEBUG directive embeds debugging information in the object file. When this directive is used, symbolic information, line numbers, and variable type information that allows type-specific display of variables and structures are included in the object file.


C166: Error Messages

Error Messages

This section lists the fatal errors, errors, and warnings you may encounter when using the C166 C Compiler. Errors and warnings are listed in numerical order and are divided into several sections:

Summary | Briefly describes the error or warning.
Description | Provides a detailed description of message and why it was generated.
Cause | Describes the cause of the error.
Resolution | Provides hints and suggestions for correcting the problem.
Example | Provides an example, where possible, of the error condition.
See Also | Provides useful references to additional material.

Some errors include an exception that provides more information about the exact nature of the error. These exceptions are generated by the operating system and indicate a failure at that level.

Exception | Description
0021h | Path or File Not Found The specified path or filename is missing.
0026h | Illegal File Access An attempt was made to delete or write to a write-protected file.
0029h | Access to File Denied The specified file is a directory.
002Ah | I/O Error The drive is either full or the drive was not ready.
0101h | Illegal Context An attempt was made to access a file in an illegal context. This happens if you try to read from LPT1 or delete COM1.


C166: Fatal Errors

Fatal Errors

Fatal errors cause immediate termination of the compilation. These errors normally occur as the result of invalid options specified on the command line or when the compiler cannot access a specified file.

Fatal error messages conform to one of the following formats:

C166 FATAL-ERROR -
    ACTION: Action
    LINE: LineNumber
    ERROR: Message
C166 TERMINATED.

or

C166 FATAL-ERROR -
    ACTION: Action
    FILE: Filename
    ERROR: Message
C166 TERMINATED.

Where

Action | Is the operation that was being performed when the error occurred.
LineNumber | Is the line number where the error was detected.
Filename | Is the name of the file in which the error was detected.
Message | Is a short summary of the error.


C166: Actions

Actions

  • Allocating Memory
    The compiler could not allocate enough memory to compile the specified source file.
  • Creating List-File/Object-File/Work-File
    The compiler could not create the list file, object file, or work file. This error may occur if the disk is full or write-protected or if the file already exists and is marked read only. For temporary work files check the TMP environment variable setting to be sure it refers to an existing drive and/or directory.
  • Generating Intermediate Code
    The source file contains a function that is too large to be translated into pseudo-code by the compiler. Break the function into smaller functions and re-compile.
  • Opening Input-File
    The compiler failed to find or open the selected source or include file.
  • Parsing Invoke-/#pragma-Line
    An error was detected while evaluating arguments on the command line or while evaluating parameters in a #pragma statement.
  • Parsing Source-File/Analyzing Declarations
    The source file violates a compiler limit.
  • Writing to File
    An error was encountered while writing to the list file, object file, or work file.


C166: Messages

Messages

  • '(' After Control Expected
    Some control parameters need an argument enclosed in parentheses. This message is displayed when the left parenthesis is missing.
  • ')' After Parameter Expected
    This message indicates that the right parenthesis of the enclosed argument is missing.
  • '=' Expected
    This message indicates a syntax error with the specified WARNING directive or pragma.
  • Bad Digit In Number
    The numerical argument of a control parameter contains invalid characters. Only decimal digits are acceptable.
  • Can't Create File
    The filename defined on the FILE line cannot be created.
  • Can't Have General Control In Invocation Line
    General controls like EJECT cannot be included on the command line. Place these controls in the source file using the #pragma statement.
  • File Does Not Exist
    The filename defined on the FILE line, cannot be found.
  • File Write-Error
    An error occurred while writing to the list, preprint, work, or object file because of insufficient disk space.
  • Identifier Expected
    This message is generated when the DEFINE directive has no arguments. The DEFINE directive requires an identifier as its argument. This is the same convention as in the C language.
  • Line Too Long
    The maximum length of the command line may not exceed 500 characters. The same limit also applies to the contents of a command file (@cmdfile).
  • Memory Space Exhausted
    The compiler could not allocate enough memory to compile the specified source file. If you receive this message consistently, you should split the source file into two or more smaller files and re-compile.
  • More Than 100 Errors in Source-File
    During the compilation more than 100 errors were detected. This causes the termination of the compiler.
  • Non-Null Argument Expected
    The selected control parameter needs an argument (for example, a filename or a number) enclosed in parentheses.
  • Numeric Value Out Of Range
    The numerical argument of a control parameter is out of range. For instance, the OPTIMIZE directive allows only certain numbers. A value of 25 would generate this error message.
  • Parse Stack Overflow/Statements Are Too Nested
    The parse stack has overflowed. This can occur if the source program contains extremely complex expressions or if blocks are nested more than 31 levels deep.
  • Preprocessor: Line Too Long (32K)
    An intermediate expansion exceeded 32K characters in length.
  • Preprocessor: Macros Too Nested
    During macro expansion, the stack consumption of the preprocessor grew too large to continue. This message usually indicates a recursive macro definition, but can also indicate a macro with too many levels of nesting.
  • Respecified Or Conflicting Control
    A command-line parameter was specified twice or conflicting command-line parameters were specified.
  • Source Must Come From A Disk-File
    The source and include files must exist on either a hard disk or diskette. The console CON:, :CI:, or similar devices are not allowed as input files.
  • Unknown Class Name
    The first parameter specified using the RENAMECLASS directive must be one of the following predefined classes: BIT, BDATA, FCODE, FCONST, FDATA, HCONST, HDATA, IDATA, NCODE, NCONST, NDATA, SDATA, XCONST, or XDATA.
  • Unknown Control
    The selected control parameter is not recognized by the compiler.


C166: Errors and Warnings

Errors and Warnings

Syntax and semantic errors typically occur in the source program. They identify actual programming errors. When an error is encountered, the compiler attempts to recover from the error and continue processing the source file. As more errors are encountered, the compiler outputs additional error messages. No object file is produced once an error is encountered.

Warnings produce information about potential problems which may occur during program execution. Warnings do not hinder compilation of the source file.

Errors and warnings are formatted as follows:

*** ERROR number IN LINE line OF file: message

*** WARNING number IN LINE line OF file: message

Where

number | is the error number.
line | is the line number where the error was detected.
file | is the source or include file in which the error was detected.
message | is a brief description of the error or warning.


C166: Reference

Reference

The following pages describe the errors and warnings generated by the C166 Compiler. Messages are listed in numerical order and each is divided into several sections:

Summary | Briefly describes the error or warning.
Description | Provides a detailed description of the problem encountered.
Cause | Describes typical causes of the problem.
Resolution | Describes ways you may solve the problem.
Example | Gives a function or program fragment that causes the error or warning.
See Also | Provides related information.


C166: Warning C1 (Misplaced Primary Directive, Line Ignored)

Warning C1
Misplaced Primary Directive, Line Ignored

Summary
*** Warning C1
    Misplaced Primary Directive, Line Ignored
Description | A primary directive was found in the middle of a source file. Primary controls may be located only on the command line or in the source file before any #include directives or declarations are specified. The compiler will ignore the specified line and directive.
Resolution | Remove the directive or move it to the beginning of the source file.


C166: Error C2 (Unknown #pragma Directive, Line Ignored)

Error C2
Unknown #pragma Directive, Line Ignored

Summary
*** Error C2
    Unknown #pragma Directive, Line Ignored
Description | An unrecognized compiler directive was encountered. The compiler ignores the control along with the rest of the pragma line.
Resolution | Remove the unknown directive.


C166: Warning C3 (ASM/ENDASM Not Allowed in Include File)

Warning C3
ASM/ENDASM Not Allowed in Include File

Summary
*** Warning C3
    ASM/ENDASM Not Allowed in Include File
Description | The asm and/or endasm directives were found in an include file. These directives may not be specified in an include file. Additionally, executable code should not be placed in include files since source-level debugging information is not generated for included files.
Resolution | Move the asm/endasm code into a C file.


C166: Warning C4 (SAVE/RESTORE: Save-Stack Overflow/Underflow)

Warning C4
SAVE/RESTORE: Save-Stack Overflow/Underflow

Summary
*** Warning C4
    SAVE/RESTORE: Save-Stack Overflow/Underflow
Description The maximum nesting depth of #pragma save is eight levels. The pragmas save and restore work with a stack according to the LIFO (last in, first out) principle.


C166: Warning C5 (ASM Requires SRC Directive)

Warning C5
ASM Requires SRC Directive

Summary
*** Warning C5
    ASM Requires SRC Directive
Description | You source file specifies the asm and endasm directives which enclose in-line assembler code. However, no src directive is specified. Source files with in-line assembler code must be compiled with the src directive so the compiler can create a .src file.
Resolution | Specify the src directive on the command line or at the top of your source file.


C166: Error C9 (Function Pointer: huge Changed to far)

Error C9
Function Pointer: huge Changed to far

Summary
*** Error C9
    Function Pointer: huge Changed to far
Description A function pointer with a huge or xhuge specifier, such as int (huge *xpi) (void), is changed to int (far *xpi) (void) because huge and xhuge apply to data pointers, not to function pointers. Function pointers should use near or far if explicit override


C166: Error C10 (Conversion: type operator type)

Error C10
Conversion: type operator type

Summary
*** Error C10
    Conversion: type operator type
Description This message warns about pointer conversions and type conversions in assignment expressions, such as unsigned short = pointer. In case of pointer conversions, the message indicates that a pointer is truncated or enlarged.


C166: Warning C11 (Internal Error: message)

Warning C11
Internal Error: message

Summary
*** Warning C11
    Internal Error: message
Description | This message indicates an internal compiler error.
Resolution | Contact Keil Software technical support and be prepared to provide an example that causes this error.


C166: Error C12 ('=' type Converted to Pointer)

Error C12
'=' type Converted to Pointer

Summary
*** Error C12
    '=' type Converted to Pointer
Description A type other than int/uint has been converted to a pointer type in an assignment expression. Because the C166/C167 architecture has special constraints on pointer types, you should verify if this conversion is really what you want to do.


C166: Error C13 (Unsafe Conversion: type Truncated to Short Pointer)

Error C13
Unsafe Conversion: type Truncated to Short Pointer

Summary
*** Error C13
    Unsafe Conversion: type Truncated to Short Pointer
Description A type such as long or unsigned long has been converted to a short pointer. Such an operation truncates the long value to an int value. A conversion of the short pointer back to a long value can yield a different result.


C166: Error C14 (operator: Unsafe Conversion - Boolean to Pointer)

Error C14
operator: Unsafe Conversion - Boolean to Pointer

Summary
*** Error C14
    operator: Unsafe Conversion - Boolean to Pointer
Description The result of a Boolean expression such as ==, >=, ||, && has been converted to a pointer. Because the result could be 1, the resulting pointer can be invalid because the segment or page part of the pointer may be invalid.


C166: Warning C15 (Floating-Point Error)

Warning C15
Floating-Point Error

Summary
*** Warning C15
    Floating-Point Error
Description This error occurs when a floating-point argument lies outside of the valid range for 32-bit or 64-bit floating values.


C166: Warning C16 (Unprintable Character 0xnn Skipped)

Warning C16
Unprintable Character 0xnn Skipped

Summary
*** Warning C16
    Unprintable Character 0xnn Skipped
Description An illegal character was found in the source file. (Note that characters inside a comment are not checked.)


C166: Warning C17 (Unclosed String)

Warning C17
Unclosed String

Summary
*** Warning C17
    Unclosed String
Description A string is not terminated with a quotation mark (").


C166: Warning C18 (String Too Long)

Warning C18
String Too Long

Summary
*** Warning C18
    String Too Long
Description A string cannot contain more than 4096 characters.


C166: Warning C19 ('\c': Invalid Character Constant)

Warning C19
'\c': Invalid Character Constant

Summary
*** Warning C19
    '\c': Invalid Character Constant
Description A character constant has an invalid format. The notation '\c' is valid only when c is any printable ASCII character.


C166: Warning C20 ('\esc': Value Exceeds 255)

Warning C20
'\esc': Value Exceeds 255

Summary
*** Warning C20
    '\esc': Value Exceeds 255
Description A character constant has a value greater than 0xFF.


C166: Warning C21 ('c': Illegal Octal Digit)

Warning C21
'c': Illegal Octal Digit

Summary
*** Warning C21
    'c': Illegal Octal Digit
Description The specified character is not a valid octal digit.


C166: Warning C22 (Constant Too Big)

Warning C22
Constant Too Big

Summary
*** Warning C22
    Constant Too Big
Description The value of the specified constant cannot be represented because the specified character is not a valid octal digit.


C166: Warning C23 (Bad Syntax in Floating-Point Number)

Warning C23
Bad Syntax in Floating-Point Number

Summary
*** Warning C23
    Bad Syntax in Floating-Point Number
Description The fractional part of the specified floating-point number should start with a digit.


C166: Warning C24 (Hex Constants Must Have At Least One Hex Digit)

Warning C24
Hex Constants Must Have At Least One Hex Digit

Summary
*** Warning C24
    Hex Constants Must Have At Least One Hex Digit
Description A hex constant with no hex digits after the 0x prefix was detected.


C166: Warning C25 (Syntax Error Near token)

Warning C25
Syntax Error Near token

Summary
*** Warning C25
    Syntax Error Near token
Description The token as seen by the compiler is wrong. This error usually results from missing semicolons or misspelled keywords.


C166: Warning C26 (Expression Too Complex, Simplify)

Warning C26
Expression Too Complex, Simplify

Summary
*** Warning C26
    Expression Too Complex, Simplify
Description The specified expression should be divided into two or more simpler expressions.


C166: Warning C27 (Illegal Type Specifier)

Warning C27
Illegal Type Specifier

Summary
*** Warning C27
    Illegal Type Specifier
Description The type specifier is illegal, for example, signed struct x or unsigned float.


C166: Warning C28 (More Than One Storage Class)

Warning C28
More Than One Storage Class

Summary
*** Warning C28
    More Than One Storage Class
Description A declaration cannot have more than one storage class.


C166: Warning C29 (Formal Parameter Has Illegal Storage Class)

Warning C29
Formal Parameter Has Illegal Storage Class

Summary
*** Warning C29
    Formal Parameter Has Illegal Storage Class
Description Formal parameters of a function type must not have a storage class other than register.


C166: Warning C30 (Same Type Qualifier Used More Than Once)

Warning C30
Same Type Qualifier Used More Than Once

Summary
*** Warning C30
    Same Type Qualifier Used More Than Once
Description A type qualifier (const or volatile) is specified more than once in one type of declaration.


C166: Warning C31 (Declarator Too Complex (20))

Warning C31
Declarator Too Complex (20)

Summary
*** Warning C31
    Declarator Too Complex (20)
Description The declaration of an object contains up to 20 kinds of modifiers, such as nested array, pointer, or function types.


C166: Warning C32 (Type-Stack Underflow)

Warning C32
Type-Stack Underflow

Summary
*** Warning C32
    Type-Stack Underflow
Description The type declaration stack has underflowed. This error is usually a side effect of error 31.


C166: Warning C33 (identifier: Invalid Storage Class)

Warning C33
identifier: Invalid Storage Class

Summary
*** Warning C33
    identifier: Invalid Storage Class
Description The storage class for the specified identifier is invalid. An example for this error would be storage class static or extern specified for a member of a structure or union.


C166: Error C34 (Missing Declaration Specifiers)

Error C34
Missing Declaration Specifiers

Summary
*** Error C34
    Missing Declaration Specifiers
Description A declaration of an identifier with no type and storage class information causes this type of warning.


C166: Error C35 (identifier: Uses Old-Style Declarator)

Error C35
identifier: Uses Old-Style Declarator

Summary
*** Error C35
    identifier: Uses Old-Style Declarator
Description The function definition uses the old-style declarator format where the return type is omitted. The return type defaults to type int, possibly causing runtime problems if far or huge pointers are returned because of pointer truncation.


C166: Warning C36 (Missing Declarator)

Warning C36
Missing Declarator

Summary
*** Warning C36
    Missing Declarator
Description A type is declared but has no identifier. For example:


C166: Error C38 (Empty Translation Unit)

Error C38
Empty Translation Unit

Summary
*** Error C38
    Empty Translation Unit
Description The specified source file is empty: it contains no external or file-level declarations.


C166: Warning C39 (identifier: Typedef May Not be Used for Function Definition)

Warning C39
identifier: Typedef May Not be Used for Function Definition

Summary
*** Warning C39
    identifier: Typedef May Not be Used for Function Definition
Description A function definition cannot be initiated by a typedef function type.


C166: Error C40 (type Converted to memory-space Pointer)

Error C40
type Converted to memory-space Pointer

Summary
*** Error C40
    type Converted to memory-space Pointer
Description A non-pointer value has been converted to a pointer value of type near, far, huge or xhuge. If an int is converted to a far or huge pointer, then the page or segment part of the pointer will be zero, which is probably not what you want.


C166: Warning C41 (Duplicate Function-Parameter)

Warning C41
Duplicate Function-Parameter

Summary
*** Warning C41
    Duplicate Function-Parameter
Description A formal parameter name exists more than once within the list of the function parameters. The formal parameter names must be unique.


C166: Warning C42 (Not in Formal Parameter List)

Warning C42
Not in Formal Parameter List

Summary
*** Warning C42
    Not in Formal Parameter List
Description The parameter declarations inside a function use a name not present in the parameter name list. For example:


C166: Warning C44 (Illegal Use of memory-space Specifier)

Warning C44
Illegal Use of memory-space Specifier

Summary
*** Warning C44
    Illegal Use of memory-space Specifier
Description A mspace specifier cannot be used for the members of a structure or union type. It can be used to direct a structure or union (or any other type) to a specified memory space.


C166: Warning C45 (Memory Attribute Ignored)

Warning C45
Memory Attribute Ignored

Summary
*** Warning C45
    Memory Attribute Ignored
Description A memory attribute (mspace) was specified for a non-static object within a function. You may not specify a memory attribute for local variables because they are always stored on the run-time stack.


C166: Error C46 (Storage Class class Ignored)

Error C46
Storage Class class Ignored

Summary
*** Error C46
    Storage Class class Ignored
Description The compiler has ignored the specified storage class. An example would be register struct x1; defined within a function. Because compound types are never placed in registers, the compiler ignores the storage class register.


C166: Error C47 (identifier: Unreferenced Item)

Error C47
identifier: Unreferenced Item

Summary
*** Error C47
    identifier: Unreferenced Item
Description An unreferenced label, local variable, or parameter has been detected.


C166: Warning C48 (identifier: struct/union Type Redefinition)

Warning C48
identifier: struct/union Type Redefinition

Summary
*** Warning C48
    identifier: struct/union Type Redefinition
Description A structure or union type has been redefined.


C166: Warning C49 (tag-name: Not a union Tag)

Warning C49
tag-name: Not a union Tag

Summary
*** Warning C49
    tag-name: Not a union Tag
Description The tag name specified in the union type does not specify a union-type tag.


C166: Warning C50 (tag-name: Not a struct Tag)

Warning C50
tag-name: Not a struct Tag

Summary
*** Warning C50
    tag-name: Not a struct Tag
Description The tag name specified in the struct type does not specify a structure-type tag.


C166: Warning C51 (tag-name: Not an enum Tag)

Warning C51
tag-name: Not an enum Tag

Summary
*** Warning C51
    tag-name: Not an enum Tag
Description The tag name specified in the enum type does not specify an enumeration-type tag.


C166: Error C52 (Use of Undefined Type tag-name)

Error C52
Use of Undefined Type tag-name

Summary
*** Error C52
    Use of Undefined Type tag-name
Description An undefined struct or union type has been used. Depending on context, this message can be issued as an error or a warning.


C166: Warning C53 (Redefinition of identifier)

Warning C53
Redefinition of identifier

Summary
*** Warning C53
    Redefinition of identifier
Description Because the identifier's type has been redefined, it does not conform to the type specified in an earlier declaration.


C166: Warning C54 (identifier: Duplicate Label)

Warning C54
identifier: Duplicate Label

Summary
*** Warning C54
    identifier: Duplicate Label
Description Definitions of labels within a function must use unique names.


C166: Warning C55 (identifier: Undefined Label)

Warning C55
identifier: Undefined Label

Summary
*** Warning C55
    identifier: Undefined Label
Description The specified label name referred to by a goto statement is undefined within the current function.


C166: Warning C56 ('{', Scope Stack Overflow (31))

Warning C56
'{', Scope Stack Overflow (31)

Summary
*** Warning C56
    '{', Scope Stack Overflow (31)
Description The maximum of 31 nested blocks has been exceeded. Additional levels of nested blocks are ignored.


C166: Error C57 (Parameter number: Different From Declaration)

Error C57
Parameter number: Different From Declaration

Summary
*** Error C57
    Parameter number: Different From Declaration
Description The parameter with number has been defined with a type that is not compatible with an earlier function prototype.


C166: Warning C60 (identifier: Duplicate Member)

Warning C60
identifier: Duplicate Member

Summary
*** Warning C60
    identifier: Duplicate Member
Description The specified identifier is already a member of some struct or union type.


C166: Warning C61 (Duplicate Parameter)

Warning C61
Duplicate Parameter

Summary
*** Warning C61
    Duplicate Parameter
Description The specified identifier is already defined in the list of function parameters.


C166: Warning C64 (identifier: static Function Declared But Not Defined)

Warning C64
identifier: static Function Declared But Not Defined

Summary
*** Warning C64
    identifier: static Function Declared But Not Defined
Description A static function was declared but not defined. Because a static function must be defined somewhere in the source module, this error signals a function that was not defined.


C166: Warning C65 (Illegal Use of near/far/huge)

Warning C65
Illegal Use of near/far/huge

Summary
*** Warning C65
    Illegal Use of near/far/huge
Description The language extension keywords near, far, huge and xhuge are not allowed in the TINY memory model because of the non-segmented mode of CPU operation.


C166: Warning C66 (Invalid Dereference)

Warning C66
Invalid Dereference

Summary
*** Warning C66
    Invalid Dereference
Description An invalid dereference has been encountered. This error can be issued when the type of an object is unknown or invalid.


C166: Warning C67 (identifier: Undefined Identifier)

Warning C67
identifier: Undefined Identifier

Summary
*** Warning C67
    identifier: Undefined Identifier
Description The identifier used in an expression is undefined.


C166: Warning C68 (Left Side of -> Requires struct/union Pointer)

Warning C68
Left Side of -> Requires struct/union Pointer

Summary
*** Warning C68
    Left Side of -> Requires struct/union Pointer
Description The left side of a member-selection expression must be a pointer to a struct or union type.


C166: Warning C69 (Left Side of . Requires struct/union)

Warning C69
Left Side of . Requires struct/union

Summary
*** Warning C69
    Left Side of . Requires struct/union
Description The left side of a member-selection expression must be a struct or union type.


C166: Warning C70 (identifier: Undefined Member)

Warning C70
identifier: Undefined Member

Summary
*** Warning C70
    identifier: Undefined Member
Description The right side of a member-selection expression must be the name of a member of the left side's struct or union type.


C166: Warning C71 (Subscript Requires Array or Pointer Type)

Warning C71
Subscript Requires Array or Pointer Type

Summary
*** Warning C71
    Subscript Requires Array or Pointer Type
Description The left side of an array-access expression array[x] does not represent an array or pointer type. In the latter case, the pointer must not be of type void *p.


C166: Error C72 (sizeof Returns Zero)

Error C72
sizeof Returns Zero

Summary
*** Error C72
    sizeof Returns Zero
Description The calculation of an object size yields zero, for example, if sizeof (*vp) is specified where vp represents a void pointer.


C166: Warning C73 (sizeof Illegal Operand Taken)

Warning C73
sizeof Illegal Operand Taken

Summary
*** Warning C73
    sizeof Illegal Operand Taken
Description This error occurs if sizeof is applied to a function type. Such operations are illegal.


C166: Warning C74 (Type Follows void)

Warning C74
Type Follows void

Summary
*** Warning C74
    Type Follows void
Description Prototype declarations of functions can contain a void parameter list, for example, int func (void). This notation cannot contain further type definitions after the void keyword.


C166: Warning C75 (void Follows Other Types)

Warning C75
void Follows Other Types

Summary
*** Warning C75
    void Follows Other Types
Description Type void cannot follow other types in a function parameter list.


C166: Warning C76 (Formal Parameter Ignored)

Warning C76
Formal Parameter Ignored

Summary
*** Warning C76
    Formal Parameter Ignored
Description This error is caused by a nested function prototype where at least one parameter is specified in an identifier list as shown:


C166: Warning C77 (identifier: Invalid or Conflicting Memory Space)

Warning C77
identifier: Invalid or Conflicting Memory Space

Summary
*** Warning C77
    identifier: Invalid or Conflicting Memory Space
Description An invalid or conflicting memory space was detected, such as a function with a memory space other than near or far, or a conflict between two memory spaces, one in the declaration and another introduced by a spaced typedef type, as shown below:


C166: Warning C79 ('*' Indirection to Object of Unknown Size)

Warning C79
'*' Indirection to Object of Unknown Size

Summary
*** Warning C79
    '*' Indirection to Object of Unknown Size
Description The indirection operator * cannot be used with void pointers because the object size, to which the pointer refers, is unknown.


C166: Warning C80 ('*' Illegal Indirection)

Warning C80
'*' Illegal Indirection

Summary
*** Warning C80
    '*' Illegal Indirection
Description The * operator cannot be applied on non-pointer arguments.


C166: Warning C81 (Call Not to a Function)

Warning C81
Call Not to a Function

Summary
*** Warning C81
    Call Not to a Function
Description The term of a function call does not evaluate to a function type or to a pointer-to-function type.


C166: Warning C82 ('+': Two Pointers)

Warning C82
'+': Two Pointers

Summary
*** Warning C82
    '+': Two Pointers
Description The sum of two pointers is not a legal C operation.


C166: Warning C83 (operator: Incompatible Types)

Warning C83
operator: Incompatible Types

Summary
*** Warning C83
    operator: Incompatible Types
Description An expression with operands of incompatible types has been detected. An example for such an operation is *p = s1, where p1 is of type int * and s1 is a structure.


C166: Warning C84 (Illegal Type Conversion)

Warning C84
Illegal Type Conversion

Summary
*** Warning C84
    Illegal Type Conversion
Description An expression causes an invalid type conversion such as float-to-pointer or bit-to-pointer, or if the target of the conversion is a function type.


C166: Warning C85 (void Illegal With All Types)

Warning C85
void Illegal With All Types

Summary
*** Warning C85
    void Illegal With All Types
Description A type conversion cannot have void as the target type. An exception to this rule is (void) test (1,2), where the return value of the function test is discarded without a type conversion actually having been performed.


C166: Warning C86 (operator: void Illegal With All Types)

Warning C86
operator: void Illegal With All Types

Summary
*** Warning C86
    operator: void Illegal With All Types
Description The expression with the specified operator has at least one void type operand that is invalid.


C166: Warning C87 (Illegal Type Conversion on struct/union Type)

Warning C87
Illegal Type Conversion on struct/union Type

Summary
*** Warning C87
    Illegal Type Conversion on struct/union Type
Description A struct or union type cannot be converted to any type.


C166: Warning C88 (operator: Invalid Left/Right Operand Type)

Warning C88
operator: Invalid Left/Right Operand Type

Summary
*** Warning C88
    operator: Invalid Left/Right Operand Type
Description The specified expression operator has an invalid left or right operand type.


C166: Error C89 (operator: Different Levels of Indirection)

Error C89
operator: Different Levels of Indirection

Summary
*** Error C89
    operator: Different Levels of Indirection
Description A pointer initialization uses a pointer with a different level as an initializer, such as a pointer level or a pointer-to-pointer level. See the example below:


C166: Warning C90 (operator: Different struct/union Types)

Warning C90
operator: Different struct/union Types

Summary
*** Warning C90
    operator: Different struct/union Types
Description Structure assignment must use the same struct or union type on both sides of the specified operator. This rule also applies when a structure is passed to a function by value.


C166: Error C91 (operator: Pointer to Different Objects)

Error C91
operator: Pointer to Different Objects

Summary
*** Error C91
    operator: Pointer to Different Objects
Description The operands of the specified operator are pointers to different objects, such as in this example: pi = pl where pi is int * and pl is long * will give warning 91.


C166: Warning C92 (operator: Requires L-Value)

Warning C92
operator: Requires L-Value

Summary
*** Warning C92
    operator: Requires L-Value
Description The left side of an assignment must evaluate to an address that represents an object that can be modified.


C166: Warning C93 (operator: bit or Bit Field Not Allowed)

Warning C93
operator: bit or Bit Field Not Allowed

Summary
*** Warning C93
    operator: bit or Bit Field Not Allowed
Description An expression tried to take the address of a bit or bit field, this action is illegal in C.


C166: Warning C94 (identifier: Declared With void Parameter List)

Warning C94
identifier: Declared With void Parameter List

Summary
*** Warning C94
    identifier: Declared With void Parameter List
Description A function declared with a void parameter list must not be activated with parameters.


C166: Error C95 (identifier: Too Many Actual Parameters)

Error C95
identifier: Too Many Actual Parameters

Summary
*** Error C95
    identifier: Too Many Actual Parameters
Description A function call expression with too many parameters has been detected.


C166: Error C96 (identifier: Too Few Actual Parameters)

Error C96
identifier: Too Few Actual Parameters

Summary
*** Error C96
    identifier: Too Few Actual Parameters
Description A function call expression with too few parameters has been detected.


C166: Warning C97 (Parameter number: Incompatible Types)

Warning C97
Parameter number: Incompatible Types

Summary
*** Warning C97
    Parameter number: Incompatible Types
Description A parameter uses a type not compatible with an earlier function prototype or function definition, for example, a structure is passed when another typed value is expected.


C166: Error C98 (Parameter number: Pointer to Different Objects)

Error C98
Parameter number: Pointer to Different Objects

Summary
*** Error C98
    Parameter number: Pointer to Different Objects
Description A parameter uses a pointer to an object that is different from an earlier function prototype or function definition. An example would be passing a pointer to int where a pointer to long is expected.


C166: Warning C99 (operator: L-Value Specifies a const Object)

Warning C99
operator: L-Value Specifies a const Object

Summary
*** Warning C99
    operator: L-Value Specifies a const Object
Description Objects declared with the const type qualifier cannot be modified.


C166: Warning C100 (operator: Left/Right Operand Must be an L-Value)

Warning C100
operator: Left/Right Operand Must be an L-Value

Summary
*** Warning C100
    operator: Left/Right Operand Must be an L-Value
Description The specified operand must evaluate to an address that represents an object that can be modified.


C166: Error C101 (L-Value Specifies a const/code Object)

Error C101
L-Value Specifies a const/code Object

Summary
*** Error C101
    L-Value Specifies a const/code Object
Description An l-value with memory type code cannot represent the address of an object that can be modified.


C166: Error C102 (operator: Different const/volatile Qualifiers)

Error C102
operator: Different const/volatile Qualifiers

Summary
*** Error C102
    operator: Different const/volatile Qualifiers
Description The pointer operands use different qualifiers. For example:


C166: Warning C103 (Illegal Function Definition (Missing ';'))

Warning C103
Illegal Function Definition (Missing ';')

Summary
*** Warning C103
    Illegal Function Definition (Missing ';')
Description An illegal function definition was detected. This error is usually caused by forgotten semicolons that can change the meaning of declarations.


C166: Warning C104 (Different Function Types)

Warning C104
Different Function Types

Summary
*** Warning C104
    Different Function Types
Description A conditional expression (e1 ? e2 : e3) specifies different function types for expressions e2 and e3.


C166: Error C105 (Unnamed Type Definition in Parentheses)

Error C105
Unnamed Type Definition in Parentheses

Summary
*** Error C105
    Unnamed Type Definition in Parentheses
Description A declaration of an unnamed type within a parameter list has been detected. Unnamed types are those declared without a tag name, such as an enumeration tag, as shown below:


C166: Warning C106 ('&' on Constant)

Warning C106
'&' on Constant

Summary
*** Warning C106
    '&' on Constant
Description The system will not let you take the address of a constant.


C166: Error C107 (Address of Automatic: Dangling Reference)

Error C107
Address of Automatic: Dangling Reference

Summary
*** Error C107
    Address of Automatic: Dangling Reference
Description A function returns the address of an automatic object. This reference could be dangling because the value, accessed later via pointer, is undefined.


C166: Warning C109 (Illegal Constant Expression)

Warning C109
Illegal Constant Expression

Summary
*** Warning C109
    Illegal Constant Expression
Description An invalid constant expression has been found. Constant expressions must not have float or double type, for example, when used for specification of a using or interrupt number.


C166: Warning C110 (Non-Constant Array Dimension or case Expression)

Warning C110
Non-Constant Array Dimension or case Expression

Summary
*** Warning C110
    Non-Constant Array Dimension or case Expression
Description A constant expression is required for case values and dimension values for arrays. Such an expression must not have components other than constants.


C166: Error C111 (Division by Zero)

Error C111
Division by Zero

Summary
*** Error C111
    Division by Zero
Description A division by zero was detected while evaluating a constant expression.


C166: Error C112 (Modulo by Zero)

Error C112
Modulo by Zero

Summary
*** Error C112
    Modulo by Zero
Description A modulus by zero was detected while evaluating a constant expression.


C166: Error C113 (Nonstandard Extension: Cast on L-Value Was Used)

Error C113
Nonstandard Extension: Cast on L-Value Was Used

Summary
*** Error C113
    Nonstandard Extension: Cast on L-Value Was Used
Description Casting the left side of an assignment is a nonstandard operation. The compiler allows this operation for historical reasons, as long as the size of the left value is not changed, as shown below:


C166: Error C114 (operator: Integral Constant Overflow)

Error C114
operator: Integral Constant Overflow

Summary
*** Error C114
    operator: Integral Constant Overflow
Description A constant overflow was detected while evaluating a constant expression.


C166: Error C115 (operator: Applied to Unsigned Type, Result Still Unsigned)

Error C115
operator: Applied to Unsigned Type, Result Still Unsigned

Summary
*** Error C115
    operator: Applied to Unsigned Type, Result Still Unsigned
Description The unary plus or minus operator has been applied to an unsigned type. The result of such an expression is still unsigned.


C166: Warning C116 (Negative Subscript)

Warning C116
Negative Subscript

Summary
*** Warning C116
    Negative Subscript
Description The constant value specifying a dimension size of an array must not be negative.


C166: Warning C117 (Constant Expression: Value Out of Range)

Warning C117
Constant Expression: Value Out of Range

Summary
*** Warning C117
    Constant Expression: Value Out of Range
Description The constant value is out of range. This error can happen, for example, when a bit field size uses a value greater than 16 or an address constant is not within the 16MB address range. Depending on context, E117 will appear as an error or a warning.


C166: Error C118 (enum Constant: Signed Value Out of Range)

Error C118
enum Constant: Signed Value Out of Range

Summary
*** Error C118
    enum Constant: Signed Value Out of Range
Description This warning is issued on an enumeration declaration where an enumerator has a different signed value.


C166: Warning C119 (identifier: Bit-Field Type Too Small for Number of Bits)

Warning C119
identifier: Bit-Field Type Too Small for Number of Bits

Summary
*** Warning C119
    identifier: Bit-Field Type Too Small for Number of Bits
Description A bit field with a width greater than the width (in bits) of the base scalar was specified, as shown below:


C166: Warning C120 (identifier: Named Bit-Field Cannot Have 0 Width)

Warning C120
identifier: Named Bit-Field Cannot Have 0 Width

Summary
*** Warning C120
    identifier: Named Bit-Field Cannot Have 0 Width
Description A named bit field must not have a width of zero bits.


C166: Warning C121 (identifier: char/int Type Required for Bit Fields)

Warning C121
identifier: char/int Type Required for Bit Fields

Summary
*** Warning C121
    identifier: char/int Type Required for Bit Fields
Description The compiler supports bit fields based on signed and unsigned char, and int and short int types.


C166: Warning C122 (identifier: Unknown Size)

Warning C122
identifier: Unknown Size

Summary
*** Warning C122
    identifier: Unknown Size
Description The size of the specified object is unknown. For example, this error can occur if an array declared within a function does not specify a dimension size.


C166: Warning C123 (identifier: Allocation Exceeds 64K)

Warning C123
identifier: Allocation Exceeds 64K

Summary
*** Warning C123
    identifier: Allocation Exceeds 64K
Description An object declared near, far or huge must not have a size greater than 64K. If you require a bigger object, you should use the xhuge specifier.


C166: Error C124 (identifier: Illegal Pointer: bit *)

Error C124
identifier: Illegal Pointer: bit *

Summary
*** Error C124
    identifier: Illegal Pointer: bit *
Description A pointer cannot refer to a bit scalar because the CPU architecture does not support this kind of addressing.


C166: Warning C125 (identifier: Array of Invalid Type)

Warning C125
identifier: Array of Invalid Type

Summary
*** Warning C125
    identifier: Array of Invalid Type
Description An array of void or function types is not valid in C.


C166: Warning C126 (identifier: Function Returning Invalid Type)

Warning C126
identifier: Function Returning Invalid Type

Summary
*** Warning C126
    identifier: Function Returning Invalid Type
Description A function cannot return a function type or change the declaration to return a pointer to a function.


C166: Warning C127 (identifier: Member Has Invalid Type)

Warning C127
identifier: Member Has Invalid Type

Summary
*** Warning C127
    identifier: Member Has Invalid Type
Description A member of a structure or union cannot have type bit, function or void.


C166: Warning C128 (identifier: Self Relative struct/union)

Warning C128
identifier: Self Relative struct/union

Summary
*** Warning C128
    identifier: Self Relative struct/union
Description A structure or union cannot have an instance of itself as a member.


C166: Warning C129 (identifier: Uses Undefined struct/union tag-name)

Warning C129
identifier: Uses Undefined struct/union tag-name

Summary
*** Warning C129
    identifier: Uses Undefined struct/union tag-name
Description The type tag name designates an undefined structure or union type.


C166: Warning C130 (break/continue: Missing Enclosing Loop)

Warning C130
break/continue: Missing Enclosing Loop

Summary
*** Warning C130
    break/continue: Missing Enclosing Loop
Description A break or continue statement must be placed within a for, while, or do statement.


C166: Warning C131 (case/default: Missing Enclosing switch)

Warning C131
case/default: Missing Enclosing switch

Summary
*** Warning C131
    case/default: Missing Enclosing switch
Description A case or default statement requires an enclosing switch statement.


C166: Warning C132 (case Value number Already Used)

Warning C132
case Value number Already Used

Summary
*** Warning C132
    case Value number Already Used
Description The case values in a switch statement must be unique.


C166: Warning C133 (More Than One default)

Warning C133
More Than One default

Summary
*** Warning C133
    More Than One default
Description A switch statement cannot have more than one default statement.


C166: Warning C134 (Can't Return huge/xhuge struct/union)

Warning C134
Can't Return huge/xhuge struct/union

Summary
*** Warning C134
    Can't Return huge/xhuge struct/union
Description A function cannot return a union or structure with a size greater than 16K.


C166: Error C135 (function-name: No Return Value)

Error C135
function-name: No Return Value

Summary
*** Error C135
    function-name: No Return Value
Description The specified function does not return a value at all. This error can cause runtime problems because the caller will use random values.


C166: Warning C136 (Return Value on void Function)

Warning C136
Return Value on void Function

Summary
*** Warning C136
    Return Value on void Function
Description A function declared with a void return value could not return a value.


C166: Error C137 (Constant in Condition Expression)

Error C137
Constant in Condition Expression

Summary
*** Error C137
    Constant in Condition Expression
Description This message warns about a possibly misspelled operator, such as if (i = 5) where if (i == 5) was intended.


C166: Error C138 (Expression With Possibly No Effect)

Error C138
Expression With Possibly No Effect

Summary
*** Error C138
    Expression With Possibly No Effect
Description A dead expression such as i << 4 was detected. Because the result of such an expression is not used anywhere, the compiler will remove the expression. This message is usually the result of a wrong operator, for example, << where <<= was intended.


C166: Warning C139 (Expression Has Illegal Type)

Warning C139
Expression Has Illegal Type

Summary
*** Warning C139
    Expression Has Illegal Type
Description The type of a condition expression must not have struct, union, or function type.


C166: Error C140 (identifier Undefined; Assuming extern int identifier())

Error C140
identifier Undefined; Assuming extern int identifier()

Summary
*** Error C140
    identifier Undefined; Assuming extern int identifier()
Description A function call to a function with no currently existing prototype has been found. The compiler assumes the function is external and returns an int value. The parameters, if any, will be promoted using the default promotion rules.


C166: Warning C141 (identifier: Too Many Initializers)

Warning C141
identifier: Too Many Initializers

Summary
*** Warning C141
    identifier: Too Many Initializers
Description An initialization statement provides more initializers than required, for example, char array[5] = { 1,2,3,4,5,6, };


C166: Warning C142 (Illegal Initialization)

Warning C142
Illegal Initialization

Summary
*** Warning C142
    Illegal Initialization
Description An attempt was made to initialize a symbol that represents a typedef name or a function parameter.


C166: Warning C143 (identifier: Initializer Is Not a Constant)

Warning C143
identifier: Initializer Is Not a Constant

Summary
*** Warning C143
    identifier: Initializer Is Not a Constant
Description Initializer expressions for file-level objects must be constant expressions. Such an expression can use constants and addresses of objects.


C166: Warning C144 (identifier: Initialization Needs Curly Braces)

Warning C144
identifier: Initialization Needs Curly Braces

Summary
*** Warning C144
    identifier: Initialization Needs Curly Braces
Description Initialization of an array or a structure needs curly braces around the initializers. An exception to this rule is the initialization of an automatic structure or union, where another structure or union without curly braces can be specified for the initi


C166: Error C145 (Non-L-Value struct Converted to Pointer)

Error C145
Non-L-Value struct Converted to Pointer

Summary
*** Error C145
    Non-L-Value struct Converted to Pointer
Description A member of a structure or union directly returned by some function has been accessed. Because the returned structure or union is stored in a temporary location, the compiler converts the struct.member access type to a ptr->member access type.


C166: Error C146 (identifier: Slightly Different Types)

Error C146
identifier: Slightly Different Types

Summary
*** Error C146
    identifier: Slightly Different Types
Description The type of the initializer expression does not match the type of the object being initialized.


C166: Warning C148 (Initializer Uses An Auto-Address)

Warning C148
Initializer Uses An Auto-Address

Summary
*** Warning C148
    Initializer Uses An Auto-Address
Description A function local static object must not be initialized with a stack-based address in a reentrant function.


C166: Error C149 (Potential Pointer Truncation)

Error C149
Potential Pointer Truncation

Summary
*** Error C149
    Potential Pointer Truncation
Description An expression causes a pointer to be converted to a pointer with smaller size. Because of truncation, the result may be an invalid pointer.


C166: Error C150 (memory-space Pointer Converted to memory-space Pointer)

Error C150
memory-space Pointer Converted to memory-space Pointer

Summary
*** Error C150
    memory-space Pointer Converted to memory-space Pointer
Description A pointer with memory space 1 (near, far, huge, ...) has been converted to a pointer with a different memory space. Depending on the memory spaces, a pointer can be truncated.


C166: Error C151 (Pointer Truncation memory-space to memory-space)

Error C151
Pointer Truncation memory-space to memory-space

Summary
*** Error C151
    Pointer Truncation memory-space to memory-space
Description A pointer has been truncated.


C166: Warning C152 (Bad Type Conversion: type to type)

Warning C152
Bad Type Conversion: type to type

Summary
*** Warning C152
    Bad Type Conversion: type to type
Description It is not possible to convert a float or double-type constant to a pointer.


C166: Error C153 (operator: Different Spaced Pointer (memory-space, memory-space))

Error C153
operator: Different Spaced Pointer (memory-space, memory-space)

Summary
*** Error C153
    operator: Different Spaced Pointer (memory-space, memory-space)
Description A comparison of pointers with different memory spaces was attempted. In general, it makes no sense to compare pointers with different memory spaces because these spaces could refer to different segments or pages.


C166: Warning C154 (Cannot Allocate An Array of Constant Size 0)

Warning C154
Cannot Allocate An Array of Constant Size 0

Summary
*** Warning C154
    Cannot Allocate An Array of Constant Size 0
Description An array must not have a zero size.


C166: Warning C155 (Invalid Base Address)

Warning C155
Invalid Base Address

Summary
*** Warning C155
    Invalid Base Address
Description The base address of a SFR or sbit declaration does not specify the address of a special function register


C166: Warning C156 (Invalid sbit Declaration)

Warning C156
Invalid sbit Declaration

Summary
*** Warning C156
    Invalid sbit Declaration
Description An sbit declaration must use the address of a sfr or a bdata object and a bit position in range 0-15. If a bdata-based sbit is declared, the bit position range depends on the base scalar. For example, if the base scalar is a long value, then the bit pos


C166: Error C161 (memory-space Pointer Truncated to memory-space Pointer)

Error C161
memory-space Pointer Truncated to memory-space Pointer

Summary
*** Error C161
    memory-space Pointer Truncated to memory-space Pointer
Description A pointer has been truncated.


C166: Warning C162 (far/huge/xhuge Not Allowed in Tiny Model)

Warning C162
far/huge/xhuge Not Allowed in Tiny Model

Summary
*** Warning C162
    far/huge/xhuge Not Allowed in Tiny Model
Description It is not possible to use far, huge, and xhuge pointers and arrays in tiny model, because the CPU is operated in non-segmented mode, in which the code and data must reside within the first 64K segment.


C166: Error C163 (Data/Function Pointer Converted to Function/Data Pointer)

Error C163
Data/Function Pointer Converted to Function/Data Pointer

Summary
*** Error C163
    Data/Function Pointer Converted to Function/Data Pointer
Description A data pointer has been converted to function pointer or vice versa. Care should be taken when data/function pointer conversions take place. Whereas a data pointer represents a page and an offset, a function pointer represents a segment and an offset.


C166: Warning C164 (More Than 128 regbanks/vectors)

Warning C164
More Than 128 regbanks/vectors

Summary
*** Warning C164
    More Than 128 regbanks/vectors
Description A single module must not specify more than 128 register banks or interrupt procedures since the hardware architecture imposes this limit.


C166: Warning C165 (Interrupt Vector Redefinition)

Warning C165
Interrupt Vector Redefinition

Summary
*** Warning C165
    Interrupt Vector Redefinition
Description An interrupt vector specified for a function can be used only once. That is, you cannot have two or more functions tied to a single interrupt vector.


C166: Warning C166 (Interrupt Vector number: Already in Use)

Warning C166
Interrupt Vector number: Already in Use

Summary
*** Warning C166
    Interrupt Vector number: Already in Use
Description The numeric interrupt vector number can be assigned only once.


C166: Warning C167 (Intrinsic function-name: Declaration or Activation Error)

Warning C167
Intrinsic function-name: Declaration or Activation Error

Summary
*** Warning C167
    Intrinsic function-name: Declaration or Activation Error
Description Either an intrinsic function has an invalid declaration, or the activation of an intrinsic function uses invalid parameters. You should include the INTRINS.H file in your source file to provide consistent declaration of the intrinsic functions. You can


C166: Warning C169 (Illegal Task Definition (Task ID/Priority))

Warning C169
Illegal Task Definition (Task ID/Priority)

Summary
*** Warning C169
    Illegal Task Definition (Task ID/Priority)
Description The task definition uses out-of-range numeric parameters. The taskid must be in range 0-0xFF, where the range for priority is 0-0x7F.


C166: Warning C170 (Constant Value Not in Range range)

Warning C170
Constant Value Not in Range range

Summary
*** Warning C170
    Constant Value Not in Range range
Description The constant value is not within the specified range.


C166: Warning C171 (Interrupt/Using: Can’t Receive or Return Values)

Warning C171
Interrupt/Using: Can’t Receive or Return Values

Summary
*** Warning C171
    Interrupt/Using: Can’t Receive or Return Values
Description A function declared with the using register bank attribute or an interrupt function cannot receive parameters or return a value to the caller.


C166: Warning C172 (segment/group Length Exceeded: Act=actvalue, Max=maxvalue)

Warning C172
segment/group Length Exceeded: Act=actvalue, Max=maxvalue

Summary
*** Warning C172
    segment/group Length Exceeded: Act=actvalue, Max=maxvalue
Description Some segment or page or a group of pages or segments violates the maximum size given by maxvalue. For example, the total size of all huge data objects within one source module cannot exceed 64K. With far data objects, the maximum size is 16K.


C166: Error C173 (operator: Signed/Unsigned Type Mismatch)

Error C173
operator: Signed/Unsigned Type Mismatch

Summary
*** Error C173
    operator: Signed/Unsigned Type Mismatch
Description The arguments for a comparison operator have different signs.


C166: Error C174 (identifier: Unreferenced static Function)

Error C174
identifier: Unreferenced static Function

Summary
*** Error C174
    identifier: Unreferenced static Function
Description An unreferenced static functions have been detected. Because static functions cannot be activated from outside the module, you can remove the function.


C166: Warning C175 (identifier: More Than 32 Local Bits)

Warning C175
identifier: More Than 32 Local Bits

Summary
*** Warning C175
    identifier: More Than 32 Local Bits
Description A single function cannot have more than 32 local bit declarations. Local bits are assigned to registers. The compiler allows a maximum of two word registers to hold bits.


C166: Warning C176 (identifier: Automatics Require More than 16,384 Bytes)

Warning C176
identifier: Automatics Require More than 16,384 Bytes

Summary
*** Warning C176
    identifier: Automatics Require More than 16,384 Bytes
Description The maximum size for automatic objects per functions is 16K.


C166: Error C177 (Unreachable Code)

Error C177
Unreachable Code

Summary
*** Error C177
    Unreachable Code
Description The optimizer has detected one or more paths that cannot be reached from the regular control flow within a function. This message usually results from condition expressions with constant assignments


C166: Warning C178 (atomic/endatomic: Available in 167 Mode Only)

Warning C178
atomic/endatomic: Available in 167 Mode Only

Summary
*** Warning C178
    atomic/endatomic: Available in 167 Mode Only
Description The intrinsic functions atomic and endatomic are not available in C166 mode.


C166: Error C179 (function-name: Out of Memory While Optimizing Function)

Error C179
function-name: Out of Memory While Optimizing Function

Summary
*** Error C179
    function-name: Out of Memory While Optimizing Function
Description The compiler could not allocate enough memory for optimization of the specified function. The generated code remains correct, although it may be less efficient because one or more optimizer stages could not be executed.


C166: Error C180 (function-name: Not Every Path Returns a Value)

Error C180
function-name: Not Every Path Returns a Value

Summary
*** Error C180
    function-name: Not Every Path Returns a Value
Description Control-flow analysis yields one or more exit paths that do not provide a return value. This example shows a situation where the warning would be issued:


C166: Warning C181 (identifier: Unknown Size)

Warning C181
identifier: Unknown Size

Summary
*** Warning C181
    identifier: Unknown Size
Description A static file-level object with undefined size has been detected. This object type is not allowed because no BSS segment collects such definitions.


C166: Error C182 (identifier: Unknown Size, Assumed to be extern)

Error C182
identifier: Unknown Size, Assumed to be extern

Summary
*** Error C182
    identifier: Unknown Size, Assumed to be extern
Description A non-static, file-level object with an undefined size has been detected. The object is assumed to be defined in another source module.


C166: Error C183 (Dead Assignment Eliminated)

Error C183
Dead Assignment Eliminated

Summary
*** Error C183
    Dead Assignment Eliminated
Description The optimizer has removed a dead assignment, which is an assignment to a local variable whose value is not used anywhere. Note that such assignments can result from the different optimizer stages:


C166: Error C184 (Value of identifier Possibly Undefined)

Error C184
Value of identifier Possibly Undefined

Summary
*** Error C184
    Value of identifier Possibly Undefined
Description Data flow analysis shows an access to a local variable that may be undefined. This is the case if no definition of the variable reaches its use.


C166: Warning C185 (Atomic #number: Out of Range)

Warning C185
Atomic #number: Out of Range

Summary
*** Warning C185
    Atomic #number: Out of Range
Description The automatic calculation of the number of atomic instructions is not within range 1-4.


C166: Error C186 (expression Meaningless Use of an Expression)

Error C186
expression Meaningless Use of an Expression

Summary
*** Error C186
    expression Meaningless Use of an Expression
Description An function address is used in an expression or relational operators such as >=, < have been applied to unsigned types.


C166: Error C187 (Address Not Aligned)

Error C187
Address Not Aligned

Summary
*** Error C187
    Address Not Aligned
Description An int or long address refers to an odd address.


C166: Error C188 (expression: Address of R-Value Taken)

Error C188
expression: Address of R-Value Taken

Summary
*** Error C188
    expression: Address of R-Value Taken
Description You cannot derrive the address of an struct member that is returned by a function call.


C166: Error C189 (variable: Storage Class Changed to static)

Error C189
variable: Storage Class Changed to static

Summary
*** Error C189
    variable: Storage Class Changed to static
Description An explicit memory type used for an automatic variable implies that the variable will be not allocated on user stack. Therefore the variable behaves the same was as a static variable.


C166: Error C190 (identifier: Not Mapped to Register)

Error C190
identifier: Not Mapped to Register

Summary
*** Error C190
    identifier: Not Mapped to Register
Description The assembler instruction that you are using implies that the symbol must be assigned to an register. However, the compiler did not assign the symbol to an register.


C166: Error C191 (identifier: Incomplete Type)

Error C191
identifier: Incomplete Type

Summary
*** Error C191
    identifier: Incomplete Type
Description It is impossible to initialize a struct that is not fully declared. A struct initialization requires a complete struct definition.


C166: Error C192 (expression: Value Truncation)

Error C192
expression: Value Truncation

Summary
*** Error C192
    expression: Value Truncation
Description You have assigned a value to a smaller data type (for example a long value to an int variable). The value gets trunctated in such assignments.


C166: Error C193 (function-name: More than 256 Parameters)

Error C193
function-name: More than 256 Parameters

Summary
*** Error C193
    function-name: More than 256 Parameters
Description It is not possible to use more than 256 parameters in a function definition.


C166: Error C194 (directive: Requires MODV2 Control)

Error C194
directive: Requires MODV2 Control

Summary
*** Error C194
    directive: Requires MODV2 Control
Description The specified directive is only available for Infineon XC16x or ST Super10 devices and requires therefore the MODV2 compiler control.


C166: Error C195 (Inline Assembly Error: instruction)

Error C195
Inline Assembly Error: instruction

Summary
*** Error C195
    Inline Assembly Error: instruction
Description The is not a legal assembler instruction.


C166: Error C196 (__asm: Cannot be Used with SRC Mode)

Error C196
__asm: Cannot be Used with SRC Mode

Summary
*** Error C196
    __asm: Cannot be Used with SRC Mode
Description __asm { } statements require that C166 generates directly the object file. Such statements cannot be used when you generate an assembler (SRC) output file.


C166: Warning C197 (function-name: Function Not Inlined)

Warning C197
function-name: Function Not Inlined

Summary
*** Warning C197
    function-name: Function Not Inlined
Description The function 'name' has been defined with the __inline specifier. The compiler decided not to inline this function and therefore gives this warning.


C166: Warning C300 (Unterminated Comment)

Warning C300
Unterminated Comment

Summary
*** Warning C300
    Unterminated Comment
Description This message occurs when a comment does not have a closing delimiter (*/).


C166: Warning C301 (identifier Expected)

Warning C301
identifier Expected

Summary
*** Warning C301
    identifier Expected
Description The syntax of a preprocessor directive expects an identifier.


C166: Warning C302 (Misused # Operator)

Warning C302
Misused # Operator

Summary
*** Warning C302
    Misused # Operator
Description This message occurs if an identifier does not follow the stringize operator ('#').


C166: Warning C303 (Formal Argument Expected)

Warning C303
Formal Argument Expected

Summary
*** Warning C303
    Formal Argument Expected
Description This message occurs if the stringize operator ('#') is not followed by an identifier representing a formal parameter name of the macro currently being defined.


C166: Warning C304 (Bad Macro Parameter List)

Warning C304
Bad Macro Parameter List

Summary
*** Warning C304
    Bad Macro Parameter List
Description The macro parameter list is not a brace-enclosed, comma-separated list of identifiers.


C166: Warning C305 (Unterminated String/char Constant)

Warning C305
Unterminated String/char Constant

Summary
*** Warning C305
    Unterminated String/char Constant
Description A string or character constant is invalid. Typically, this error is encountered if the closing quote is missing.


C166: Warning C306 (Unterminated Macro Call)

Warning C306
Unterminated Macro Call

Summary
*** Warning C306
    Unterminated Macro Call
Description The end of the input file was reached while the preprocessor was collecting and expanding macro-call parameters.


C166: Warning C307 (Macro macro-name: Parameter Count Mismatch)

Warning C307
Macro macro-name: Parameter Count Mismatch

Summary
*** Warning C307
    Macro macro-name:  Parameter Count Mismatch
Description The number of parameters in a macro call does not match the number of parameters of the macro definition. If too few parameters were specified, then message 307 appears as an error. If too many parameters were specified, then message 307 appears as a w


C166: Warning C308 (Invalid Integer Constant Expression)

Warning C308
Invalid Integer Constant Expression

Summary
*** Warning C308
    Invalid Integer Constant Expression
Description The numerical expression of an if/elif directive contains a syntax error.


C166: Warning C309 (Bad or Missing File Name)

Warning C309
Bad or Missing File Name

Summary
*** Warning C309
    Bad or Missing File Name
Description The filename argument in an include directive is invalid or missing.


C166: Warning C310 (Conditionals Too Nested (20))

Warning C310
Conditionals Too Nested (20)

Summary
*** Warning C310
    Conditionals Too Nested (20)
Description The source file contains too many nested directives for conditional compilation. The maximum nesting level allowed is 20.


C166: Warning C311 (Misplaced elif/else Control)

Warning C311
Misplaced elif/else Control

Summary
*** Warning C311
    Misplaced elif/else Control
Description The directives elif, else, and endif are legal only within an if, ifdef, or ifndef directive.


C166: Warning C312 (Misplaced endif Control)

Warning C312
Misplaced endif Control

Summary
*** Warning C312
    Misplaced endif Control
Description The directives elif, else, and endif are legal only within an if, ifdef, or ifndef directive.


C166: Warning C313 (Can’t Remove Predefined Macro macro-name)

Warning C313
Can’t Remove Predefined Macro macro-name

Summary
*** Warning C313
    Can’t Remove Predefined Macro macro-name
Description An attempt was made to remove a predefined macro. Existing macros can be deleted using the #undef directive. Predefined macros cannot be removed. The compiler recognizes the following predefined macros:


C166: Warning C314 (Bad # Directive Syntax)

Warning C314
Bad # Directive Syntax

Summary
*** Warning C314
    Bad # Directive Syntax
Description In a preprocessor directive, the character ('#') must be followed by either a newline character or the name of a preprocessor command (for example, if/define/ifdef, ...).


C166: Warning C315 (Unknown # Directive identifier)

Warning C315
Unknown # Directive identifier

Summary
*** Warning C315
    Unknown # Directive identifier
Description The compiler does not know the name of the preprocessor directive.


C166: Warning C316 (Unterminated Conditionals)

Warning C316
Unterminated Conditionals

Summary
*** Warning C316
    Unterminated Conditionals
Description The number of endifs does not match the number of if or ifdefs after the end of the input file.


C166: Error C317 (Redefinition of Macro macro-name)

Error C317
Redefinition of Macro macro-name

Summary
*** Error C317
    Redefinition of Macro macro-name
Description The macro with the specified name is already defined with different parameter and/or macro body.


C166: Warning C318 (Can’t Open File file-name)

Warning C318
Can’t Open File file-name

Summary
*** Warning C318
    Can’t Open File file-name
Description The specified file could not be opened.


C166: Warning C319 (file-name: Not a Disk File)

Warning C319
file-name: Not a Disk File

Summary
*** Warning C319
    file-name: Not a Disk File
Description The specified file is not a disk file. Files other than disk files are not acceptable for compilation.


C166: Warning C320 (User_error_ Text)

Warning C320
User_error_ Text

Summary
*** Warning C320
    User_error_ Text
Description This error number is reserved for errors introduced with the #error directive of the preprocessor. Error 320 prevents the compiler from generating code.


C166: Warning C321 (Missing character)

Warning C321
Missing character

Summary
*** Warning C321
    Missing character
Description | A character that was expected was not found.
Cause This message is generated when the specified character is missing. This typically occurs when a closing character is missing in the filename argument of an include directive. For example:
#include <stdio.h
Resolution | Insert the missing character.


C166: Error C322 (Unknown identifier)

Error C322
Unknown identifier

Summary
*** Error C322
    Unknown identifier
Description The integer constant expression uses an undefined identifier.


C166: Error C323 (New-line Expected, Extra Character Found)

Error C323
New-line Expected, Extra Character Found

Summary
*** Error C323
    New-line Expected, Extra Character Found
Description A preprocessor directive is terminated by one or more extra characters, which are not interpreted. The directive should be terminated by a newline character.


C166: Error C324 (Preprocessor Token Expected)

Error C324
Preprocessor Token Expected

Summary
*** Error C324
    Preprocessor Token Expected
Description A preprocessor token was expected but a newline character was found.


C166: Warning C325 (Duplicate Formal Parameter identifier)

Warning C325
Duplicate Formal Parameter identifier

Summary
*** Warning C325
    Duplicate Formal Parameter identifier
Description The names of the formal parameters of a macro must be unique.


C166: Warning C326 (Macro Body Cannot Start or End With ##)

Warning C326
Macro Body Cannot Start or End With ##

Summary
*** Warning C326
    Macro Body Cannot Start or End With ##
Description The concatenation operator (##) cannot be the first or last token of a macro body.


C166: Warning C327 (Macro macro-name: More Than 50 Parameters)

Warning C327
Macro macro-name: More Than 50 Parameters

Summary
*** Warning C327
    Macro macro-name: More Than 50 Parameters
Description The number of parameters per macro is limited to 50.


C166: Warning C328 (Misplaced ASM/ENDASM)

Warning C328
Misplaced ASM/ENDASM

Summary
*** Warning C328
    Misplaced ASM/ENDASM
Description The preprocessor found nested asm directives. Asm and endasm must not be nested.


C166: Library Reference

Library Reference

The C166 run-time library provides more than 100 predefined functions and macros you may use in your C16x/ST10/XC16x C programs. The library makes embedded software development easier by providing routines that perform common programming tasks such as string and buffer manipulation, data conversion, and floating-point math operations.

The routines in this library conform to the ANSI C Standard. However, some functions differ slightly in order to take advantage of the features of the C16x/ST10/XC16x architecture. Where possible, function return types and argument types are adjusted to use the smallest data type possible. In addition, unsigned data types are favored over signed types. These changes to the standard library provide a maximum of performance while reducing program size.

All routines in this library are implemented to be independent of any register bank.


C166: Library Files

Library Files

The C166 library includes numerous compile-time libraries which are optimized for various functional requirements. These libraries support most of the ANSI C function calls.

Filename | Device | Model | Floating-Point
C166T.LIB | 80C166 | Tiny |
C166S.LIB | 80C166 | Small |
C166M.LIB | 80C166 | Medium |
C166C.LIB | 80C166 | Compact |
C166L.LIB | 80C166 | Large |
C166FPT.LIB | 80C166 | Tiny | Single-Precision
C166FPS.LIB | 80C166 | Small | Single-Precision
C166FPM.LIB | 80C166 | Medium | Single-Precision
C166FPC.LIB | 80C166 | Compact | Single-Precision
C166FPL.LIB | 80C166 | Large | Single-Precision
C166DPT.LIB | 80C166 | Tiny | Double-Precision
C166DPS.LIB | 80C166 | Small | Double-Precision
C166DPM.LIB | 80C166 | Medium | Double-Precision
C166DPC.LIB | 80C166 | Compact | Double-Precision
C166DPL.LIB | 80C166 | Large | Double-Precision
C167T.LIB | C16x/ST10/XC16x | Tiny |
C167S.LIB | C16x/ST10/XC16x | Small |
C167M.LIB | C16x/ST10/XC16x | Medium |
C167C.LIB | C16x/ST10/XC16x | Compact |
C167L.LIB | C16x/ST10/XC16x | Large |
C167HC.LIB | C16x/ST10/XC16x | HCompact |
C167HL.LIB | C16x/ST10/XC16x | HLarge |
C167XL.LIB | C16x/ST10/XC16x | XLarge |
C167FPT.LIB | C16x/ST10/XC16x | Tiny | Single-Precision
C167FPS.LIB | C16x/ST10/XC16x | Small | Single-Precision
C167FPM.LIB | C16x/ST10/XC16x | Medium | Single-Precision
C167FPC.LIB | C16x/ST10/XC16x | Compact | Single-Precision
C167FPL.LIB | C16x/ST10/XC16x | Large | Single-Precision
C167FPHC.LIB | C16x/ST10/XC16x | HCompact | Single-Precision
C167FPHL.LIB | C16x/ST10/XC16x | HLarge | Single-Precision
C167FPXL.LIB | C16x/ST10/XC16x | XLarge | Single-Precision
C167DPT.LIB | C16x/ST10/XC16x | Tiny | Double-Precision
C167DPS.LIB | C16x/ST10/XC16x | Small | Double-Precision
C167DPM.LIB | C16x/ST10/XC16x | Medium | Double-Precision
C167DPC.LIB | C16x/ST10/XC16x | Compact | Double-Precision
C167DPL.LIB | C16x/ST10/XC16x | Large | Double-Precision
C167DPHC.LIB | C16x/ST10/XC16x | HCompact | Double-Precision
C167DPHL.LIB | C16x/ST10/XC16x | HLarge | Double-Precision
C167DPXL.LIB | C16x/ST10/XC16x | XLarge | Double-Precision

Note

  • Normally, you do not need to manually specify libraries for the library routines you use. The compiler includes special references to the library in the generated object file. Of course, you may specify the NODEFAULTLIBRARY directive to the linker to disable automatic linkage with the default libraries.


C166: Source Code

Source Code

Source code is provided (in the \KEIL\C166\LIB folder) for the following library routines:

Library Routine | Filename | Description
calloc | calloc.c | Allocates memory for an array of elements.
free | free.c | Releases memory allocated with calloc, malloc, or realloc.
_getkey | getkey.c | Waits for a character to be received from the serial port.
init_mempool | init_mem.c | Initializes the memory pool used by the calloc, free, malloc, and realloc routines.
malloc | malloc.c | Allocates a memory block from the memory pool.
putchar | putchar.c | Transmits a character using the serial port.
realloc | realloc.c | Changes the size of a previously allocated memory block.
xcalloc | xcalloc.c | Allocates xhuge memory for an array of elements.
xfree | xfree.c | Releases memory allocated with calloc, malloc, or realloc.
xinit_mempool | xinitmem.c | Initializes the xhuge memory pool used by the calloc, free, malloc, and realloc routines.
xmalloc | xmalloc.c | Allocates a memory block from the xhuge memory pool.
xrealloc | xrealloc.c | Changes the size of a previously allocated xhuge memory block.

You may modify these routines and substitute them for the default routines stored in the library.

An additional source module, traps.c defines trap interrupts for NMI, Stack Overflow, and Stack Underflow.


C166: Standard Types

Standard Types

The C166 standard library contains definitions for a number of standard types which may be used by the library routines. They are declared in include files which you may access from your C programs.


C166: jmp_buf

jmp_buf

The jmp_buf type is defined in setjmp.h. It specifies the buffer used by the setjmp and longjmp routines to save and restore the program environment. The jmp_buf type is defined as:

typedef char jmp_buf[_JBLEN];

and is used as shown in the following example:

#include <setjmp.h>

jmp_buf env;     /* jump environment (must be global) */
bit error_flag;

void trigger (void) {
  .
  .
  .
  /* processing code here */
  .
  .
  .
  if (error_flag != 0) {
    longjmp (env, 1);   /* return 1 to setjmp */
  }
  .
  .
  .
}

Note

  • The value of _JBLEN depends on the memory model selected.


C166: ptrdiff_t

ptrdiff_t

The prtdiff_t type is defined in stddef.h. This type specifies the signed integer result of subtracting two pointers. It is defined as:

typedef int ptrdiff_t;

and is used as shown in the following example:

#include <stddef.h>

void pfunc (void *p1, void *p2) {
  ptrdiff_t pdiff;

  pdiff = p1 -p2;
}


C166: size_t

size_t

The size_t type is defined in stdio.h, stddef.h, stdlib.h, and string.h. This type is used for defining the sizes of strings and memory blocks. It is defined as:

typedef unsigned int size_t;

and is used as shown in the following example:

#include <string.h>

void lfunc (char *string) {
  size_t string_length;

  string_length = strlen(string);
}


C166: va_list

va_list

The va_list array type is defined in stdarg.h. This type holds data required by the va_arg and va_end routines. The va_list type is defined as:

typedef char *va_list;

and is used as shown in the following example:

#include <stdarg.h>

int varfunc (char *buf, int id, ...) {
  va_list tag;

  va_start (tag, id);

  if (id == 0) {
    int arg1;
    char *arg2;
    long arg3;

    arg1 = va_arg (tag, int);
    arg2 = va_arg (tag, char *);
    arg3 = va_arg (tag, long);
  }

  else {
    char *arg1;
    char *arg2;
    long arg3;

    arg1 = va_arg (tag, char *);
    arg2 = va_arg (tag, char *);
    arg3 = va_arg (tag, long);
  }

  va_end (tag);
}


C166: wchar_t

wchar_t

The wchar_t type is defined in stdlib.h. This type defines a wide-character variable. It is defined as:

typedef signed char wchar_t;

Note

  • The Keil C166 C Compiler does not support wide characters. The wchar_t type is provided only for ANSI syntax compatibility.


C166: Macros

Macros

The C166 library includes definitions for a number of macros you may use in your programs.


C166: HARRAY

HARRAY

The HARRAY macro accesses an array of a specified type in the huge memory area. You may use this macro in your programs as follows:

#include <absacc.h>    /* Include Macro Definitions */
.
.
.
int i;
long l;

l = HARRAY (long, 0x8000)[i];
HARRAY (long, 0x8000)[10] = 0x12345678;

#define DualPortRam HARRAY (int, 0x24000)
DualPortRam [i] = 0x1234;
.
.
.

This macro scales the index by the size of the specified type and adds the result to specified address. The result is the memory address used.

Note

  • Objects accessed using this macro may not cross a 64KB segment boundary. For example, you cannot access a long array that starts at address 0x12FFFE.


C166: HVAR

HVAR

The HVAR macro accesses absolute memory addresses in the huge memory area. You may use this macro in your programs as follows:

#include <absacc.h>    /* Include Macro Definitions */
.
.
.
#define IOVAL HVAR (long, 0x14FFE) /* long at 0x14FFE */

var = IOVAL;                       /* read */
IOVAL = 0x10;                      /* write */

var = HVAR (int, 0x24002)          /* read int from 0x24002 */
.
.
.

Note

  • Objects accessed using this macro may not cross a 64KB segment boundary. For example, you cannot access a long variable at address 0x12FFFE.


C166: MARRAY

MARRAY

The MARRAY macro accesses an array of a specified type in the far memory area (in segmented mode) or in the standard near memory area (in Tiny model or non-segmented mode). You may use this macro in your programs as follows:

#include <absacc.h>    /* Include Macro Definitions */
.
.
.
int i;
long l;

l = MARRAY (long, 0x8000)[i];
MARRAY (long, 0x8000)[10] = 0x12345678;

#define DualPortRam MARRAY (int, 0x24000)
DualPortRam [i] = 0x1234;
.
.
.

This macro scales the index by the size of the specified type and adds the result to specified address. The result is the memory address used.

Note

  • Objects accessed using this macro may not cross a 64KB segment boundary. For example, you cannot access a long array that starts at address 0x12FFFE.


C166: MVAR

MVAR

The MVAR macro accesses absolute memory addresses in the far memory area (in segmented mode) or in the standard near memory area (in Tiny model or non-segmented mode). You may use this macro in your programs as follows:

#include <absacc.h>    /* Include Macro Definitions */
.
.
.
#define IOVAL MVAR (long, 0x4FFE)  /* long at 0x4FFE */

var = IOVAL;                       /* read */
IOVAL = 0x10;                      /* write */

var = MVAR (int, 0x4002)           /* read int from 0x4002 */
.
.
.

Note

  • Objects accessed using this macro may not cross a 64KB segment boundary. For example, you cannot access a long variable at address 0x00FFFE.


C166: XARRAY

XARRAY

The XARRAY macro accesses an array of a specified type in the xhuge memory area. You may use this macro in your programs as follows:

#include <absacc.h>    /* Include Macro Definitions */
.
.
.
int i;
long l;

l = XARRAY (long, 0x8000)[i];
XARRAY (long, 0x8000)[10] = 0x12345678;

#define DualPortRam XARRAY (int, 0x24000)
DualPortRam [i] = 0x1234;
.
.
.

This macro scales the index by the size of the specified type and adds the result to specified address. The result is the memory address used.

Note

  • Objects accessed using this macro may cross a 64KB segment boundary.


C166: XVAR

XVAR

The XVAR macro accesses absolute memory addresses in the xhuge memory area. You may use this macro in your programs as follows:

#include <absacc.h>    /* Include Macro Definitions */
.
.
.
#define IOVAL XVAR (long, 0x14FFE) /* long at 0x14FFE */

var = IOVAL;                       /* read */
IOVAL = 0x10;                      /* write */

var = XVAR (int, 0x24002)          /* read int from 0x24002 */
.
.
.

Note

  • Objects accessed using this macro may cross a 64KB segment boundary.


C166: Routines By Category

Routines By Category

This section gives a brief overview of the major categories of library routines that are available in the C166 standard library.

Note

  • Many of the routines in the C166 standard library are reentrant and/or intrinsic. These specifications are listed in the following tables. Unless otherwise noted, routines are non-reentrant and non-intrinsic.


C166: Buffer Manipulation Routines

Buffer Manipulation Routines

Routine | Attributes | Description
memccpy | reentrant | Copies data bytes from one buffer to another until a specified character or specified number of characters has been copied.
memchr | reentrant | Returns a pointer to the first occurrence of a specified character in a buffer.
memcmp | reentrant | Compares a given number of characters from two different buffers.
memcpy | reentrant | Copies a specified number of data bytes from one buffer to another.
memmove | reentrant | Copies a specified number of data bytes from one buffer to another. This routine is typically used when the two buffers may overlap.
memset | reentrant | Initializes a specified number of data bytes in a buffer to a specified character value.

The buffer manipulation routines work on memory buffers on a character-by-character basis. A buffer is an array of characters like a string, however, a buffer is usually not terminated with a null character ('\0'). For this reason, these routines require a buffer length or count argument.

All of these routines are implemented as functions. Function prototypes are included in the string.h include file.


C166: Character Routines

Character Routines

Routine | Attributes | Description
isalnum | reentrant | Tests for an alphanumeric character.
isalpha | reentrant | Tests for an alphabetic character.
iscntrl | reentrant | Tests for a Control character.
isdigit | reentrant | Tests for a decimal digit.
isgraph | reentrant | Tests for a printable character with the exception of space.
islower | reentrant | Tests for a lowercase alphabetic character.
isprint | reentrant | Tests for a printable character.
ispunct | reentrant | Tests for a punctuation character.
isspace | reentrant | Tests for a whitespace character.
isupper | reentrant | Tests for an uppercase alphabetic character.
isxdigit | reentrant | Tests for a hexadecimal digit.
toascii | reentrant | Converts a character to an ASCII code.
toint | reentrant | Converts a hexadecimal digit to a decimal value.
tolower | reentrant | Tests a character and converts it to lowercase if it is uppercase.
_tolower | reentrant | Unconditionally converts a character to lowercase.
toupper | reentrant | Tests a character and converts it to uppercase if it is lowercase.
_toupper | reentrant | Unconditionally converts a character to uppercase.

The character routines allow you to test individual characters for a variety of attributes and convert characters to different formats.

The _tolower, _toupper, and toascii routines are implemented as macros. All other routines are implemented as functions. All macro definitions and function prototypes are found in the ctype.h include file.


C166: Data Conversion Routines

Data Conversion Routines

Routine | Attributes | Description
abs | reentrant | Generates the absolute value of an integer type.
atof | reentrant | Converts a string to a float.
atoi | reentrant | Converts a string to an int.
atol | reentrant | Converts a string to a long.
labs | reentrant | Generates the absolute value of a long type.
strtod | reentrant | Converts a string to a float.
strtol | reentrant | Converts a string to a long.
strtoul | reentrant | Converts a string to an unsigned long.

The data conversion routines convert strings of ASCII characters to numbers. All of these routines are implemented as functions and most are prototyped in stdlib.h. The abs labs functions are prototyped in math.h.


C166: Intrinsic Routines

Intrinsic Routines

Routine | Attributes | Description
_atomic_ | intrinsic, reentrant | Inserts an ATOMIC assembler instruction.
_bfld_ | intrinsic, reentrant | Inserts a BFLDL and/or BFLDH assembler instruction.
_chkdouble_ | intrinsic, reentrant | Checks the status of a 64-bit floating-point number.
_chkfloat_ | intrinsic, reentrant | Checks the status of a 32-bit floating-point number.
_crol_ | intrinsic, reentrant | Rotates an unsigned char left a specified number of bits.
_cror_ | intrinsic, reentrant | Rotates an unsigned char right a specified number of bits.
_einit_ | intrinsic, reentrant | Inserts an EINIT assembler instruction.
_endatomic_ | intrinsic, reentrant | Checks the range of the ATOMIC instruction.
_idle_ | intrinsic, reentrant | Inserts an IDLE assembler instruction.
_irol_ | intrinsic, reentrant | Rotates an unsigned int left a specified number of bits.
_iror_ | intrinsic, reentrant | Rotates an unsigned int right a specified number of bits.
_lrol_ | intrinsic, reentrant | Rotates an unsigned long left a specified number of bits.
_lror_ | intrinsic, reentrant | Rotates an unsigned long right a specified number of bits.
_nop_ | intrinsic, reentrant | Inserts a NOP assembler instruction.
_pop_ | intrinsic, reentrant | Pops and returns a 16-bit value from the system stack using the POP assembler instruction.
_prior_ | intrinsic, reentrant | Uses the PRIOR instruction to calculate the number of single bit shifts required to normalize a 16-bit value.
_priord_ | intrinsic, reentrant | Uses the PRIOR instruction to calculate the number of single bit shifts required to normalize a 32-bit value.
_pwrdn_ | intrinsic, reentrant | Inserts a PWRDN assembler instruction.
_push_ | intrinsic, reentrant | Pushes a 16-bit value onto the system stack using the PUSH assembler instruction.
_sof_ | intrinsic, reentrant | Generates the segment-offset value of an address for PEC transfers.
_srvwdt_ | intrinsic, reentrant | Inserts a SRVWDT assembler instruction which services the watchdog timer.
_testclear_ | intrinsic, reentrant | Inserts a JBC instruction to test the value of a bit for 1 and clear it to 0 in a single, atomic instruction.
_testset_ | intrinsic, reentrant | Inserts a JNBS instruction to test the value of a bit for 0 and set it to 1 in a single, atomic instruction.
_trap_ | intrinsic, reentrant | Inserts a TRAP or SRST assembler instruction.

The C166 Compiler supports a number of intrinsic library routines all of which are defined in the intrins.h include file. Code is generated inline for most intrinsic routines, however, some routines are implemented as functions to save code space.


C166: Math Routines

Math Routines

Routine | Attributes | Description
acos | reentrant | Calculates the arc cosine of a specified number.
asin | reentrant | Calculates the arc sine of a specified number.
atan | reentrant | Calculates the arc tangent of a specified number.
atan2 | reentrant | Calculates the arc tangent of a fraction.
ceil | reentrant | Finds the integer ceiling of a specified number.
cos | reentrant | Calculates the cosine of a specified number.
cosh | reentrant | Calculates the hyperbolic cosine of a specified number.
exp | reentrant | Calculates the exponential function of a specified number.
fabs | reentrant | Finds the absolute value of a specified number.
floor | reentrant | Finds the largest integer less than or equal to a specified number.
fmod | reentrant | Calculates the floating-point remainder.
log | reentrant | Calculates the natural logarithm of a specified number.
log10 | reentrant | Calculates the common logarithm of a specified number.
modf | reentrant | Generates integer and fractional components of a specified number.
pow | reentrant | Calculates a value raised to a power.
rand | reentrant | Generates a pseudo random number.
sin | reentrant | Calculates the sine of a specified number.
sinh | reentrant | Calculates the hyperbolic sine of a specified number.
srand | reentrant | Initializes the pseudo random number generator.
sqrt | reentrant | Calculates the square root of a specified number.
tan | reentrant | Calculates the tangent of a specified number.
tanh | reentrant | Calculates the hyperbolic tangent of a specified number.
_chkdouble_ | intrinsic, reentrant | Checks the status of a floating-point number of type double.
_chkfloat_ | intrinsic, reentrant | Checks the status of a floating-point number of type float.
_crol_ | intrinsic, reentrnt | Rotates an unsigned char left a specified number of bits.
_cror_ | intrinsic, reentrant | Rotates an unsigned char right a specified number of bits.
_irol_ | intrinsic, reentrant | Rotates an unsigned int left a specified number of bits.
_iror_ | intrinsic, reentrant | Rotates an unsigned int right a specified number of bits.
_lrol_ | intrinsic, reentrant | Rotates an unsigned long left a specified number of bits.
_lror_ | intrinsic, reentrant | Rotates an unsigned long right a specified number of bits.

The math routines perform common mathematical calculations. Most of these routines work with floating-point values and include the floating-point libraries and support routines.

All of these routines are implemented as functions. Most are prototyped in the math.h include file. The rand and srand functions are prototyped in the stdlib.h include file.

The _crol_, _cror_, _irol_, _iror_, _lrol_, and _lror_ functions are prototyped in the intrins.h include file.


C166: Memory Allocation Routines

Memory Allocation Routines

Routine | Attributes | Description
_alloc_boxf | reentrant | Allocates a fixed size far block from the specified memory pool.
_calloc_boxh | reentrant | Allocates a fixed size huge block from the specified memory pool.
_alloc_boxn | reentrant | Allocates a fixed size near block from the specified memory pool.
_calloc_boxf | reentrant | Allocates a fixed size far block from the specified memory pool.
_calloc_boxh | reentrant | Releases a fixed size block from the specified huge memory pool.
_calloc_boxn | reentrant | Allocates a fixed size near block from the specified memory pool.
_free_boxf | reentrant | Frees a fixed size block that was allocated using _alloc_boxf or _calloc_boxf.
_free_boxh | reentrant | Frees a fixed size block that was allocated using _alloc_boxh or _calloc_boxh.
_free_boxn | reentrant | Frees a fixed size block that was allocated using _alloc_boxn or _calloc_boxn.
_init_boxf | reentrant | Initializes the location and size of a far fixed block memory pool.
_init_boxh | reentrant | Initializes the location and size of a huge fixed block memory pool.
_init_boxn | reentrant | Initializes the location and size of a near fixed block memory pool.
calloc |  | Allocates storage for an array from the memory pool.
calloc_b |  | Allocates storage for an array from the xhuge memory pool.
free |  | Frees a memory block that was allocated using calloc, malloc, or realloc.
free_b |  | Frees a memory block that was allocated using calloc_b, malloc_b, or realloc_b.
init_mempool |  | Initializes the memory location and size of the memory pool.
init_mempool_b |  | Initializes the memory location and size of the xhuge memory pool.
malloc |  | Allocates a block from the memory pool.
malloc_b |  | Allocates a block from the xhuge memory pool.
realloc |  | Reallocates a block from the memory pool.
realloc_b |  | Reallocates a block from the xhuge memory pool.

The memory allocation functions provide you with a means to specify, allocate, and free blocks of memory from a memory pool. Standard memory allocation functions are implemented as functions and are prototyped in the stdlib.h include file. Fixed block size memory allocation routines are prototyped in membox.h.

Before using any of these functions to allocate memory, you must first specify the size and location of the memory pool using the init_mempool routine or the size, location, and block size using the _init_box? routines. All memory requests are satisfied from the specified memory block.

The calloc, malloc, _alloc_box?, and _calloc_box? routines allocate blocks of memory from the pool. The calloc routine allocates an array with a specified number of elements of a given size and initializes the array to 0. The malloc routine allocates a specified number of bytes. The _alloc_box? and _calloc_box? routines allocate a single fixed-size block from the memory pool.

The realloc routine changes the size of an allocated block. The free and _free_box? routines return a previously allocated memory block to the memory pool.


C166: Stream I/O Routines

Stream I/O Routines

Routine | Attributes | Description
getchar |  | Reads and echoes a character using the _getkey and putchar routines.
_getkey |  | Reads a character using the serial interface.
gets |  | Reads and echoes a character string using the getchar routine.
printf |  | Writes formatted data using the putchar routine.
putchar |  | Writes a character using the serial interface.
puts | reentrant | Writes a character string and newline ('\n') character using the putchar routine.
scanf |  | Reads formatted data using the getchar routine.
sprintf | reentrant | Writes formatted data to a string.
sscanf | reentrant | Reads formatted data from a string.
ungetchar |  | Places a character back into the getchar input buffer.
vprintf |  | Writes formatted data using the putchar function.
vsprintf | reentrant | Writes formatted data to a string.

The stream I/O routines are implemented as functions and are prototyped in the stdio.h include file.

The stream input and output routines allow you to read and write data to and from a user-defined I/O interface. Characters are read using the _getkey routine and are written using the putchar routine. The default _getkey and putchar functions in the library read and write characters using the C16x serial interface.

The source code for _getkey and putchar is available in the \KEIL\C166\LIB folder. You may modify these files and substitute them for the default library routines. The stream functions then perform input and output using your modified _getkey and putchar routines.

To use the existing _getkey and putchar routines, you must first initialize the serial port. If the serial port is not properly initialized, the default stream functions do not function. Initializing the serial port requires manipulating several special function registers (SFRs).


C166: String Routines

String Routines

Routine | Attributes | Description
strcat | reentrant | Concatenates two strings.
strchr | reentrant | Returns a pointer to the first occurrence of a specified character in a string.
strcmp | reentrant | Compares two strings.
strcpy | reentrant | Copies one string to another.
strcspn | reentrant | Returns the index of the first character in a string that matches any character in a second string.
strlen | reentrant | Returns the length of a string.
strncat | reentrant | Concatenates up to a specified number of characters from one string to another.
strncmp | reentrant | Compares two strings up to a specified number of characters.
strncpy | reentrant | Copies up to a specified number of characters from one string to another.
strpbrk | reentrant | Returns a pointer to the first character in a string that matches any character in a second string.
strpos | reentrant | Returns the index of the first occurrence of a specified character in a string.
strrchr | reentrant | Returns a pointer to the last occurrence of a specified character in a string.
strrpbrk | reentrant | Returns a pointer to the last character in a string that matches any character in a second string.
strrpos | reentrant | Returns the index of the last occurrence of a specified character in a string.
strspn | reentrant | Returns the index of the first character in a string that does not match any character in a second string.
strstr | reentrant | Returns a pointer in a string that is identical to a second sub-string.

The string routines are implemented as functions and are prototyped in the string.h include file. They perform the following operations:

  • Copying strings
  • Appending one string to the end of another
  • Comparing two strings
  • Locating one or more characters from a specified set in a string

All string functions operate on null-terminated character strings. Use the buffer manipulation routines to work on non-terminated strings.


C166: Variable Length Argument Routines

Variable Length Argument Routines

Routine | Attributes | Description
va_arg | reentrant | Retrieves an argument from an argument list.
va_end | reentrant | Resets an argument pointer.
va_start | reentrant | Sets a pointer to the beginning of an argument list.

The variable-length argument list routines are implemented as macros and are defined in the stdarg.h include file. These routines provide a portable method of accessing arguments in functions that take a variable number of arguments. These macros conform to the ANSI C Standard for variable-length argument lists.


C166: Miscellaneous Routines

Miscellaneous Routines

Routine | Attributes | Description
setjmp | reentrant | Saves the current stack condition and program address.
longjmp | reentrant | Restores the stack condition and program address.

Routines found in the miscellaneous category do not fit easily into any other library routine category. The setjmp and longjmp routines are implemented as functions and are prototyped in the setjmp.h include file.


C166: Include Files

Include Files

The include files provided with the C166 standard library are found in the \KEIL\C166\INC folder. These files contain constant and macro definitions, type definitions, and function prototypes. The following sections describe the use and contents of each include file.


C166: SFR Definitions

SFR Definitions

The C166 Compiler provides a number of include files that contain sfr and sbit definitions for the special function registers of various C16x/ST10/XC16x devices. These files are found in the \KEIL\C166\INC folder and subfolders.

Typically, SFR definition files begin with the prefix reg. For example, the SFR definitions for the Infineon C163 device are defined in reg163.h.


C166: absacc.h

absacc.h

The absacc.h include file contains definitions for macros that allow you to directly access different memory areas.

HARRAY
HVAR 		MARRAY
MVAR 		XARRAY
XVAR


C166: assert.h

assert.h

The assert.h include file defines the assert macro you may use to create test conditions in your programs.


C166: ctype.h

ctype.h

The ctype.h include file contains definitions and prototypes for routines which classify ASCII characters and routines which perform character conversions. The following is a list of these routines:

isalnum
isalpha
iscntrl
isdigit
isgraph
islower 		isprint
ispunct
isspace
isupper
isxdigit
toascii 		toint
tolower
_tolower
toupper
_toupper


C166: float.h

float.h

The float.h include file defines manifest constants that represent implementation-defined properties of floating-point numbers.

Defined Constant | Description
DBL_DIG | The precision in decimal digits for type double.
DBL_EPSILON | The smallest n of type double such that 1.0 + n != 1.0.
DBL_MANT_DIG | The number of mantissa digits, base DBL_RADIX, for type double.
DBL_MAX | The largest finite representable value of type double.
DBL_MAX_10_EXP | The maximum integer n, such that 10n is a finite representable value of type double.
DBL_MAX_EXP | The maximum integer n, such that DBL_RADIXn-1 is a finite representable value of type double.
DBL_MIN | The smallest normalized, finite representable value of type double.
DBL_MIN_10_EXP | The minimum integer n such that 10n is a normalized, finite representable value of type double.
DBL_MIN_EXP | The minimum integer n such that DBL_RADIXn-1 is a normalized, finite representable value of type double.
DBL_RADIX | The radix of all double types.
DBL_ROUNDS A value that describes the current rounding mode for double operations.
  • -1 if the mode is indeterminate,
  • 0 if rounding is toward zero,
  • 1 if rounding is to nearest representable value (this is the default for the C166 Compiler),
  • 2 if rounding is toward +infinity,
  • 3 if rounding is toward -infinity.
FLT_DIG | The precision in decimal digits for type float.
FLT_EPSILON | The smallest n of type float such that 1.0 + n != 1.0.
FLT_MANT_DIG | The number of mantissa digits, base FLT_RADIX, for type float.
FLT_MAX | The largest finite representable value of type float.
FLT_MAX_10_EXP | The maximum integer n, such that 10n is a finite representable value of type float.
FLT_MAX_EXP | The maximum integer n, such that FLT_RADIXn-1 is a finite representable value of type float.
FLT_MIN | The smallest normalized, finite representable value of type float.
FLT_MIN_10_EXP | The minimum integer n, such that 10n is a normalized, finite representable value of type float.
FLT_MIN_EXP | The minimum integer n, such that FLT_RADIXn-1 is a normalized, finite representable value of type float.
FLT_RADIX | The radix of all float types.
FLT_ROUNDS A value that describes the current rounding mode for float operations.
  • -1 if the mode is indeterminate,
  • 0 if rounding is toward zero,
  • 1 if rounding is to nearest representable value (this is the default for the C166 Compiler),
  • 2 if rounding is toward +infinity,
  • 3 if rounding is toward -infinity.
LDBL_DIG | The precision in decimal digits for type long double.
LDBL_EPSILON | The smallest n of type long double such that 1.0 + n != 1.0.
LDBL_MANT_DIG | The number of mantissa digits, base LDBL_RADIX, for type long double.
LDBL_MAX | The largest finite representable value of type long double.
LDBL_MAX_10_EXP | The maximum integer n, such that 10n is a finite representable value of type long double.
LDBL_MAX_EXP | The maximum integer n, such that LDBL_RADIXn-1 is a finite representable value of type long double.
LDBL_MIN | The smallest normalized, finite representable value of type long double.
LDBL_MIN_10_EXP | The minimum integer n, such that 10n is a normalized, finite representable value of type long double.
LDBL_MIN_EXP | The minimum integer n, such that LDBL_RADIXn-1 is a normalized, finite representable value of type long double.
LDBL_RADIX | The radix of all long double types.
LDBL_ROUNDS A value that describes the current rounding mode for long double operations.
  • -1 if the mode is indeterminate,
  • 0 if rounding is toward zero,
  • 1 if rounding is to nearest representable value (this is the default for the C166 Compiler),
  • 2 if rounding is toward +infinity,
  • 3 if rounding is toward -infinity.


C166: intrins.h

intrins.h

The intrins.h include file contains prototypes for routines that instruct the compiler to generate intrinsic code.

_atomic_
_bfld_
_chkdouble_
_chkfloat_
_crol_
_cror_
_diswdt_
_einit_
_endatomic_ 		_idle_
_irol_
_iror_
_lrol_
_lror_
_nop_
_pop_
_prior_ 		_priord_
_push_
_pwrdn_
_sof_
_srvwdt_
_testclear_
_testset_
_trap_

Note

  • Code for most of these functions is inserted inline. However, some intrinsic routines may call library routines.


C166: limits.h

limits.h

The limits.h include file defines manifest constants that represent implementation-defined limits on values stored in various data types.

Defined Constant | Description
CHAR_BIT | Number of bits in any char type.
CHAR_MAX | Maximum char value.
CHAR_MIN | Minimum char value.
SCHAR_MAX | Maximum signed char value.
SCHAR_MIN | Minimum signed char value.
UCHAR_MAX | Maximum unsigned char value.
SHRT_MAX | Maximum short value.
SHRT_MIN | Minimum short value.
USHRT_MAX | Maximum unsigned short value.
INT_MAX | Maximum int value.
INT_MIN | Minimum int value.
UINT_MAX | Maximum unsigned int value.
LONG_MAX | Maximum long value.
LONG_MIN | Minimum long value.
ULONG_MAX | Maximum unsigned long value.


C166: math.h

math.h

The math.h include file contains prototypes and definitions for all routines that perform floating-point math calculations. Other math functions are also included in this file. All of the math function routines are listed below:

_chkfloat_
_chkdouble_
abs
acos
asin
atan
atan2
ceil 		cos
cosh
exp
fabs
floor
fmod
labs
log 		log10
modf
pow
sin
sinh
sqrt
tan
tanh


C166: membox.h

membox.h

The membox.h include file contains prototypes and definitions for memory pool management of fixed size allocation blocks. Functions are provided for near, far, and huge memory types:

_alloc_boxf
_calloc_boxf
_free_boxf
_init_boxf 		_alloc_boxh
_calloc_boxh
_free_boxh
_init_boxh 		_alloc_boxn
_calloc_boxn
_free_boxn
_init_boxn


C166: setjmp.h

setjmp.h

The setjmp.h include file defines the jmp_buf type and prototypes the setjmp and longjmp routines which use it.


C166: stdarg.h

stdarg.h

The stdarg.h include file defines macros that access arguments in functions with variable-length argument lists. The macros include:

va_arg va_end va_start

In addition, the va_list type is defined in this file.


C166: stddef.h

stddef.h

The stddef.h include file defines the offsetof macro which you may use to determine the offset of members of a structure.

The stddef.h include file also defines the NULL manifest constant.


C166: stdio.h

stdio.h

The stdio.h include file contains prototypes and definitions for stream I/O routines. They are:

_getkey
getchar
gets
printf 		putchar
puts
scanf
sprintf 		sscanf
ungetchar
vprintf
vsprintf

The stdio.h include file also defines the EOF and NULL manifest constants.


C166: stdlib.h

stdlib.h

The stdlib.h include file contains prototypes and definitions for the type conversion and memory allocation routines listed below:

abs
atof
atoi
atol
calloc
calloc_b
free
free_b
init_mempool 		init_mempool_b
labs
malloc
malloc_b
rand
realloc
realloc_b
srand
strtod 		strtol
strtoul
xcalloc
xfree
xinit_mempool
xmalloc
xrealloc

The stdlib.h include file also defines the NULL and RAND_MAX manifest constants and the size_t and wchar_t types.


C166: string.h

string.h

The string.h include file contains prototypes for the following string and buffer manipulation routines:

fmemccpy
fmemchr
fmemcmp
fmemcpy
fmemmove
fmemset
fstrcat
fstrchr
fstrcmp
fstrcpy
fstrcspn
fstrlen
fstrncat
fstrncmp
fstrncpy
fstrpbrk
fstrpos
fstrrchr
fstrrpbrk 		fstrrpos
fstrspn
hmemcmp
hmemcpy
hstrcmp
hstrcpy
memccpy
memchr
memcmp
memcpy
memmove
memset
strcat
strchr
strcmp
strcpy
strcspn
strlen
strncat 		strncmp
strncpy
strpbrk
strpos
strrchr
strrpbrk
strrpos
strspn
strstr
xmemccpy
xmemchr
xmemcmp
xmemcpy
xmemmove
xmemset
xstrcmp
xstrcpy
xstrlen
xstrncpy

The string.h include file also defines the NULL manifest constant and the size_t type.


C166: Reference

Reference

The following pages describe the routines in the C166 Standard Library. Routines are listed in alphabetical order and each is divided into several sections:

Summary | Briefly describes the routine's effect, lists include file(s) containing its declaration and prototype, illustrates the syntax, and describes any arguments.
Description | Provides a detailed description of the routine and how it is used.
Return Value | Describes the value returned by the routine.
See Also | Names related routines.
Example | Gives a function or program fragment demonstrating proper use of the function.


C166: _alloc_boxf

_alloc_boxf

Summary
#include <membox.h>

void far *_alloc_boxf (
  void far *box_mem);        /* pool address */
Description The _alloc_boxf routine allocates a block from the far memory pool box_mem. The memory pool must have been previously initialized using the _init_boxf library routine.

Note

  • This routine is reentrant and thread-safe. It may be called from the main function and an interrupt with no restrictions.
Return Value | The _alloc_boxf routine returns a far pointer to the allocated block (if available) or a NULL pointer if no block is available.
See Also | _calloc_boxf, _free_boxf, _init_boxf


C166: _alloc_boxh

_alloc_boxh

Summary
#include <membox.h>

void huge *_alloc_boxh (
  void huge *box_mem);        /* pool address */
Description The _alloc_boxh routine allocates a block from the huge memory pool box_mem. The memory pool must have been previously initialized using the _init_boxh library routine.

Note

  • This routine is reentrant and thread-safe. It may be called from the main function and an interrupt with no restrictions.
Return Value | The _alloc_boxh routine returns a huge pointer to the allocated block (if available) or a NULL pointer if no block is available.
See Also | _calloc_boxh, _free_boxh, _init_boxh


C166: _alloc_boxn

_alloc_boxn

Summary
#include <membox.h>

void near *_alloc_boxn (
  void near *box_mem);        /* pool address */
Description The _alloc_boxn routine allocates a block from the near memory pool box_mem. The memory pool must have been previously initialized using the _init_boxn library routine.

Note

  • This routine is reentrant and thread-safe. It may be called from the main function and an interrupt with no restrictions.
Return Value | The _alloc_boxn routine returns a near pointer to the allocated block (if available) or a NULL pointer if no block is available.
See Also | _calloc_boxn, _free_boxn, _init_boxn


C166: _atomic_

_atomic_

Summary
#include <intrins.h>

void _atomic_ (
  unsigned int n);      /* number of instructions to protect */
Description

The _atomic_ routine allows you to protect a number of instructions from hardware interrupts. When you use this function, the C166 Compiler inserts an ATOMIC instruction into your program. The argument n specifies the number of instructions to protect (1-4).

If a value of 0 is used for n, the _endatomic_ function must be used to terminate the atomic sequence. The compiler automatically calculates the number of instructions protected from interrupts.

Note

  • Typically, you should use _atomic_(0) to begin an atomic sequence and _endatomic_() to terminate the sequence. This process automatically generates the correct atomic length.
  • The _atomic_ and _endatomic_ routines may be used only when the MOD167 control is specified because the ATOMIC instruction is available only in the C167 instruction set.
Return Value | None.
See Also | _endatomic_
Example
 1    #pragma MOD167
 2    #include <intrins.h>
 3
 4    int  i;
 5
 6    void main (void)  {
 7      _atomic_(0);   /* compiler calculates 'n' */
 8      i = i + 10;
 9      _endatomic_(); /* terminate _atomic_(0) */
10    }ASSEMBLY LISTING OF GENERATED OBJECT CODE

             ; FUNCTION main (BEGIN  RMASK = @0x0010)
                                    ; SOURCE LINE # 6
                                    ; SOURCE LINE # 7
0000 D110          ATOMIC  #02H
                                    ; SOURCE LINE # 8
0002 E0A4          MOV     R4,#0AH
0004 04F40000 R    ADD     i,R4
                                    ; SOURCE LINE # 9
                                    ; SOURCE LINE # 10
0008 CB00          RET
             ; FUNCTION main (END    RMASK = @0x0010)


C166: _bfld_

_bfld_

Summary
#include <intrins.h>

void _bfld_ (
  unsigned int sfr,	/* the SFR name */
  int mask,		/* the data bits mask */
  int data);		/* the data value */
Description | The _bfld_ function generates a BFLDL instruction, a BFLDH instruction, or both on sfr depending on the value of the mask and data parameters. This routine is implemented as an intrinsic function. The code required is generated inline rather than being a function call.
Return Value | None.
Example
1    #include <intrins.h>
2    #include <reg166.h>
3
4    void main (void)  {
5      _bfld_ (P0, 0xFFFF, 0x0101);
6      _bfld_ (P1, 0x00F0, 0x0010);
7      _bfld_ (P0, 0xF000, 0x2000);
8    }

ASSEMBLY LISTING OF GENERATED OBJECT CODE

             ; FUNCTION main (BEGIN  RMASK = @0x4000)
                                     ; SOURCE LINE # 4
                                     ; SOURCE LINE # 5
0000 1A8001FF      BFLDH   P0,#0FFH,#01H
0004 0A80FF01      BFLDL   P0,#0FFH,#01H
                                     ; SOURCE LINE # 6
0008 0A82F010      BFLDL   P1,#0F0H,#010H
                                     ; SOURCE LINE # 7
000C 1A8020F0      BFLDH   P0,#0F0H,#020H
                                     ; SOURCE LINE # 8
0010 CB00          RET
             ; FUNCTION main (END    RMASK = @0x4000)


C166: _calloc_boxf

_calloc_boxf

Summary
#include <membox.h>

void far *_calloc_boxf (
  void far *box_mem);        /* pool address */
Description The _calloc_boxf routine allocates a block from the far memory pool box_mem and initializes it to 0. The memory pool must have been previously initialized using the _init_boxf library routine.

Note

  • This routine is reentrant and thread-safe. It may be called from the main function and an interrupt with no restrictions.
See Also _alloc_boxf, _free_boxf, _init_boxf


C166: _calloc_boxh

_calloc_boxh

Summary
#include <membox.h>

void huge *_calloc_boxh (
  void huge *box_mem);        /* pool address */
Description The _calloc_boxh routine allocates a block from the huge memory pool box_mem and initializes it to 0. The memory pool must have been previously initialized using the _init_boxh library routine.

Note

  • This routine is reentrant and thread-safe. It may be called from the main function and an interrupt with no restrictions.
See Also _alloc_boxh, _free_boxh, _init_boxh


C166: _calloc_boxn

_calloc_boxn

Summary
#include <membox.h>

void near *_calloc_boxn (
  void near *box_mem);        /* pool address */
Description The _calloc_boxn routine allocates a block from the near memory pool box_mem and initializes it to 0. The memory pool must have been previously initialized using the _init_boxn library routine.

Note

  • This routine is reentrant and thread-safe. It may be called from the main function and an interrupt with no restrictions.
See Also _alloc_boxn, _free_boxn, _init_boxn


C166: _chkdouble_

_chkdouble_

Summary
#include <intrins.h>
/* or */
#include <math.h>

unsigned int _chkdouble_ (
  double val);       /* number to check */
Description | The _chkdouble_ function checks the status of the floating-point number val.
Return Value

The _chkdouble_ function returns the status of the floating-point number val:

Return Value | Meaning
0 | Standard floating-point number.
1 | Floating-point value 0.
2 | +INF (positive overflow).
3 | -INF (negative overflow).
4 | NaN (Not a Number) error status.
See Also | _chkfloat_
Example
#include <intrins.h>
#include <stdio.h> /* for printf */

float f1, f2, f3;

void tst_chkdouble (void) {
  f1 = f2 * f3;

  switch (_chkdouble_ (f1)) {
    case 0:
      printf ("result is a number\n"); break;
    case 1:
      printf ("result is zero\n"); break;
    case 2:
      printf ("result is +INF\n"); break;
    case 3:
      printf ("result is -INF\n"); break;
    case 4:
      printf ("result is NaN\n"); break;
  }
}


C166: _chkfloat_

_chkfloat_

Summary
#include <intrins.h>
/* or */
#include <math.h>

unsigned int _chkfloat_ (
  float val);       /* number to check */
Description | The _chkfloat_ function checks the status of the floating-point number val.
Return Value

The _chkfloat_ function returns the status of the floating-point number val:

Return Value | Meaning
0 | Standard floating-point number.
1 | Floating-point value 0.
2 | +INF (positive overflow).
3 | -INF (negative overflow).
4 | NaN (Not a Number) error status.
See Also | _chkdouble_
Example
#include <intrins.h>
#include <stdio.h> /* for printf */

float f1, f2, f3;

void test_chkfloat (void) {
  f1 = f2 * f3;

  switch (_chkfloat_ (f1)) {
    case 0:
      printf ("result is a number\n"); break;
    case 1:
      printf ("result is zero\n"); break;
    case 2:
      printf ("result is +INF\n"); break;
    case 3:
      printf ("result is -INF\n"); break;
    case 4:
      printf ("result is NaN\n"); break;
  }
}


C166: _crol_

_crol_

Summary
#include <intrins.h>

unsigned char _crol_ (
  unsigned char c,        /* character to rotate left */
  unsigned char b);       /* bit positions to rotate */
Description | The _crol_ routine rotates the bit pattern for the character c left b bits. This routine is implemented as an intrinsic function.
Return Value | The _crol_ routine returns the rotated value of c.
See Also | _cror_, _irol_, _iror_, _lrol_, _lror_
Example
#include <intrins.h>

void test_crol (void) {
  char a;
  char b;

  a = 0xA5;
  b = _crol_(a,3); /* b now is 0x2D */
}


C166: _cror_

_cror_

Summary
#include <intrins.h>

unsigned char _cror_ (
  unsigned char c,        /* character to rotate left */
  unsigned char b);       /* bit positions to rotate */
Description | The _cror_ routine rotates the bit pattern for the character c right b bits. This routine is implemented as an intrinsic function.
Return Value | The _cror_ routine returns the rotated value of c.
See Also | _crol_, _irol_, _iror_, _lrol_, _lror_
Example
#include <intrins.h>

void test_cror (void) {
  char a;
  char b;

  a = 0xA5;
  b = _crol_(a,1);   /* b now is 0xD2 */
}


C166: _diswdt_

_diswdt_

Summary
#include <intrins.h>

void _diswdt_ (void);
Description | The _diswdt_ function inserts a DISWDT instruction (which disables the watchdog timer) into the program. This routine is implemented as an intrinsic function. The code required is generated inline rather than being a function call.
Return Value | None.
See Also | _srvwdt_
Example
#include <intrins.h>

int  i;
void tst_diswdt (void)  {

  i = 1;
  _diswdt_();             /* disable watchdog timer */
  i = 0;
}


C166: _einit_

_einit_

Summary
#include <intrins.h>

void _einit_ (void);
Description | The _einit_ routine inserts an EINIT instruction into the program. This instruction signals the CPU that the initialization sequence is finished. This routine is implemented as an intrinsic function. The code required is included inline rather than being called.
Return Value | None.
Example
#include <intrins.h>

int  i;
void tst_einit (void) {
  i = 1;
  _einit_();        /* signal end of initialization */
  i = 0;
}


C166: _endatomic_

_endatomic_

Summary
#include <intrins.h>

void _endatomic_ (void);
Description | The _endatomic_ routine terminates an atomic sequence that began with a call to _atomic_(0).
Return Value | None.
See Also | _atomic_
Example
 1    #pragma MOD167
 2    #include <intrins.h>
 3
 4    int  i;
 5
 6    void main (void)  {
 7      _atomic_(0);   /* compiler calculates 'n' */
 8      i = i + 10;
 9      _endatomic_(); /* terminate _atomic_(0) */
10    }ASSEMBLY LISTING OF GENERATED OBJECT CODE

             ; FUNCTION main (BEGIN  RMASK = @0x0010)
                                    ; SOURCE LINE # 6
                                    ; SOURCE LINE # 7
0000 D110          ATOMIC  #02H
                                    ; SOURCE LINE # 8
0002 E0A4          MOV     R4,#0AH
0004 04F40000 R    ADD     i,R4
                                    ; SOURCE LINE # 9
                                    ; SOURCE LINE # 10
0008 CB00          RET
             ; FUNCTION main (END    RMASK = @0x0010)


C166: _free_boxf

_free_boxf

Summary
#include <membox.h>

int _free_boxf (
  void far *box_mem,         /* pool address */
  void far *box);            /* block address */
Description The _free_boxf routine returns a block box, that was previously allocated using _alloc_boxf or _calloc_boxf, to the memory pool specified by box_mem.

Note

  • This routine is reentrant and thread-safe. It may be called from the main function and an interrupt with no restrictions.
Return Value | The _free_boxf routine returns a value of 1 if the box was successfully returned to the memory pool or a value of 0 if there was an error freeing the block.
See Also | _alloc_boxf, _calloc_boxf, _init_boxf


C166: _free_boxh

_free_boxh

Summary
#include <membox.h>

int _free_boxh (
  void huge *box_mem,         /* pool address */
  void huge *box);            /* block address */
Description The _free_boxh routine returns a block box, that was previously allocated using _alloc_boxh or _calloc_boxh, to the memory pool specified by box_mem.

Note

  • This routine is reentrant and thread-safe. It may be called from the main function and an interrupt with no restrictions.
Return Value | The _free_boxh routine returns a value of 1 if the box was successfully returned to the memory pool or a value of 0 if there was an error freeing the block.
See Also | _alloc_boxh, _calloc_boxh, _init_boxh


C166: _free_boxn

_free_boxn

Summary
#include <membox.h>

int _free_boxn (
  void near *box_mem,         /* pool address */
  void near *box);            /* block address */
Description The _free_boxn routine returns a block box, that was previously allocated using _alloc_boxn or _calloc_boxn, to the memory pool specified by box_mem.

Note

  • This routine is reentrant and thread-safe. It may be called from the main function and an interrupt with no restrictions.
Return Value | The _free_boxn routine returns a value of 1 if the box was successfully returned to the memory pool or a value of 0 if there was an error freeing the block.
See Also | _alloc_boxn, _calloc_boxn, _init_boxn


C166: _getkey

_getkey

Summary
#include <stdio.h>

char _getkey (void);
Description

The _getkey function waits for a character to be received from the serial port.

Note

  • This routine is implementation-specific and its function may deviate from that described above. Source code is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
Return Value | The _getkey routine returns the received character.
See Also | getchar, putchar, ungetchar
Example
#include <stdio.h>

void test_getkey (void) {
  char c;

  while ((c = _getkey ()) != 0x1B) {
    printf ("key = %c %bu %bx\n", c, c, c);
  }
}


C166: _idle_

_idle_

Summary
#include <intrins.h>

void _idle_ (void);
Description | The _idle_ routine inserts an IDLE instruction into the program, causing the microcontroller to enter idle mode. This routine is implemented as an intrinsic function. The code required is included inline rather than being called.
Return Value | None.
See Also | _pwrdn_
Example
#include <intrins.h>

int  i;
void tst_idle (void) {
  i = 1;
  _idle_();          /* enter idle mode */
  i = 2;
}


C166: _init_boxf

_init_boxf

Summary
#include <membox.h>

int _init_boxf (
  void far *box_mem,          /* pool address */
  unsigned int box_mem_size,  /* pool size */
  unsigned int box_size);     /* block size */
Description The _init_boxf routine initializes a fixed block size memory pool. The box_mem argument specifies the starting address of the pool and the box_mem_size argument specifies the size of the pool (in bytes). The box_size argument specifies the size of each block (in bytes).

Note

  • This routine is reentrant and thread-safe. It may be called from the main function and an interrupt with no restrictions.
Return Value | The _init_boxf routine returns a value of 1 if the memory box was initialized with no problems or a value of 0 to indicate an initialization error.
See Also | _alloc_boxf, _calloc_boxf, _free_boxf


C166: _init_boxh

_init_boxh

Summary
#include <membox.h>

int _init_boxh (
  void huge *box_mem,         /* pool address */
  unsigned int box_mem_size,  /* pool size */
  unsigned int box_size);     /* block size */
Description The _init_boxh routine initializes a fixed block size memory pool. The box_mem argument specifies the starting address of the pool and the box_mem_size argument specifies the size of the pool (in bytes). The box_size argument specifies the size of each block (in bytes).

Note

  • This routine is reentrant and thread-safe. It may be called from the main function and an interrupt with no restrictions.
Return Value | The _init_boxh routine returns a value of 1 if the memory box was initialized with no problems or a value of 0 to indicate an initialization error.
See Also | _alloc_boxh, _calloc_boxh, _free_boxh


C166: _init_boxn

_init_boxn

Summary
#include <membox.h>

int _init_boxn (
  void near *box_mem,         /* pool address */
  unsigned int box_mem_size,  /* pool size */
  unsigned int box_size);     /* block size */
Description The _init_boxn routine initializes a fixed block size memory pool. The box_mem argument specifies the starting address of the pool and the box_mem_size argument specifies the size of the pool (in bytes). The box_size argument specifies the size of each block (in bytes).

Note

  • This routine is reentrant and thread-safe. It may be called from the main function and an interrupt with no restrictions.
Return Value | The _init_boxn routine returns a value of 1 if the memory box was initialized with no problems or a value of 0 to indicate an initialization error.
See Also | _alloc_boxn, _calloc_boxn, _free_boxn


C166: _irol_

_irol_

Summary
#include <intrins.h>

unsigned int _irol_ (
  unsigned int i,        /* integer to rotate left */
  unsigned char b);      /* bit positions to rotate */
Description | The _irol_ routine rotates the bit pattern for the integer i left b bits. This routine is implemented as an intrinsic function.
Return Value | The _irol_ routine returns the rotated value of i.
See Also | _crol_, _cror_, _iror_, _lrol_, _lror_
Example
#include <intrins.h>

void test_irol (void) {
  int a;
  int b;

  a = 0xA5A5;
  b = _irol_(a,3);     /* b now is 0x2D2D */
}


C166: _iror_

_iror_

Summary
#include <intrins.h>

unsigned int _iror_ (
  unsigned int i,        /* integer to rotate right */
  unsigned char b);      /* bit positions to rotate */
Description | The _iror_ routine rotates the bit pattern for the integer i right b bits. This routine is implemented as an intrinsic function.
Return Value | The _iror_ routine returns the rotated value of i.
See Also | _crol_, _cror_, _irol_, _lrol_, _lror_
Example
#include <intrins.h>

void test_iror (void) {
  int a;
  int b;

  a = 0xA5A5;
  b = _irol_(a,1);      /* b now is 0xD2D2 */
}


C166: _lrol_

_lrol_

Summary
#include <intrins.h>

unsigned long _lrol_ (
  unsigned long l,       /* 32-bit integer to rotate left */
  unsigned char b);      /* bit positions to rotate */
Description | The _lrol_ routine rotates the bit pattern for the long integer l left b bits. This routine is implemented as an intrinsic function.
Return Value | The _lrol_ routine returns the rotated value of l.
See Also | _crol_, _cror_, _irol_, _iror_, _lror_
Example
#include <intrins.h>

void test_lrol (void) {
  long a;
  long b;

  a = 0xA5A5A5A5;
  b = _lrol_(a,3); /* b now is 0x2D2D2D2D */
}


C166: _lror_

_lror_

Summary
#include <intrins.h>

unsigned long _lror_ (
  unsigned long l,       /* 32-bit integer to rotate right */
  unsigned char b);      /* bit positions to rotate */
Description | The _lror_ routine rotates the bit pattern for the long integer l right b bits. This routine is implemented as an intrinsic function.
Return Value | The _lror_ routine returns the rotated value of l.
See Also | _crol_, _cror_, _irol_, _iror_, _lrol_
Example
#include <intrins.h>

void test_lror (void) {
  long a;
  long b;

  a = 0xA5A5A5A5;
  b = _lror_(a,1); /* b now is 0xD2D2D2D2 */
}


C166: _nop_

_nop_

Summary
#include <intrins.h>

void _nop_ (void);
Description | The _nop_ routine inserts a NOP instruction into the program. This routine can be used to pause for 1 CPU cycle. This routine is implemented as an intrinsic function. The NOP instruction is included inline.
Return Value | None.
Example
#include <intrins.h>

void test_nop (void) {
  P1 = 0xFF;

  _nop_ (); /* delay for hardware */
  _nop_ ();
  _nop_ ();

  P1 = 0x00;
}


C166: _pop_

_pop_

Summary
#include <intrins.h>

int _pop_ (void);
Description | The _pop_ routine inserts a POP instruction into the program which pops the next word from the system stack.
Return Value | The _pop_ routine returns the 16-bit value poped from the system stack.
See Also | _push_
Example
#include <intrins.h>

void test_pop (void) {
  volatile unsigned temp;

  _push_ (temp);
  temp = _pop_ ();
}


C166: _prior_

_prior_

Summary
#include <intrins.h>

int _prior_ (
  int value);    /* value to normalize */
Description | The _prior_ routine uses the PRIOR instruction to count the number of shifts required to normalize value. The value returned is a number from 0 to 15 which indicates how many times value must be shifted left before the MSB is set.
Return Value | The _prior_ function returns the number of shifts required to normalize value.
See Also | _priord_
Example
#include <intrins.h>

void testprior (int val) {
  volatile int temp;

  temp = _prior_ (val);
}


C166: _priord_

_priord_

Summary
#include <intrins.h>

int _prior_ (
  long value);    /* value to normalize */
Description | The _priord_ routine uses the PRIOR instruction to count the number of shifts required to normalize value. The value returned is a number from 0 to 31 which indicates how many times value must be shifted left before the MSB is set.
Return Value | The _priord_ function returns the number of shifts required to normalize value.
See Also | _prior_
Example
#include <intrins.h>

void testprior (long val) {
  volatile int temp;

  temp = _priord_ (val);
}


C166: _push_

_push_

Summary
#include <intrins.h>

void _push_ (
  int value);   /* value to push */
Description | The _push_ function inserts a PUSH instruction into the program which pushes value onto the system stack.
Return Value | None.
See Also | _pop_
Example
#include <intrins.h>

void test_pop (void) {
  volatile unsigned temp;

  _push_ (temp);
  temp = _pop_ ();
}


C166: _pwrdn_

_pwrdn_

Summary
#include <intrins.h>

void _pwrdn_ (void);
Description | The _pwrdn_ function inserts a PWRDN instruction into the program causing the CPU to enter power down mode. This routine is implemented as an intrinsic function. The code is generated inline rather than being called.
Return Value | None.
See Also | _idle_
Example
#include <intrins.h>

void testpwrdn (void) {
  P1 = 0xFF;
  _pwrdn_();     /* enter power down mode */
  P1 = 0x00;
}


C166: _sof_

_sof_

Summary
#include <intrins.h>

unsigned int _sof_ (
  void *ptr);          /* Tiny Model */

or

unsigned int _sof_ (
  void huge *ptr);     /* Other Models */
Description

The _sof_ routine converts ptr to a segment offset for segment 0. The result of _sof_ is valid only if the pointer refers to segment 0 in the C16x address space (0000h-0FFFFh).

The _sof_ routine is typically used to initialize source and destination pointers for PEC transfers. The offset value is calculated inline without a call to a library function.
Return Value The _sof_ routine returns the offset of ptr in the 0 segment.
Example
 1     #include <intrins.h>
 2     #include <reg166.h>
 3
 4     int idata buf [5];
 5
 6     void main (void)  {
 7       DSTP0 = _sof_ (buf);  /* dest pointer */
 8       SRCP0 = &ADDAT;       /* source pointer */
 9       PECC0 = 0x0205;       /* transfer 5 words */
10     }

ASSEMBLY LISTING OF GENERATED OBJECT CODE

             ; FUNCTION main (BEGIN  RMASK = @0x4010)
                                    ; SOURCE LINE # 6
                                    ; SOURCE LINE # 7
0000 E6F40000 R    MOV     R4,#SOF (buf)
0004 F6F4E2FD      MOV     0FDE2H,R4
                                    ; SOURCE LINE # 8
0008 E6F4A0FE      MOV     R4,#0FEA0H ; ADDAT
000C F6F4E0FD      MOV     0FDE0H,R4
                                    ; SOURCE LINE # 9
0010 E6600502      MOV     PECC0,#0205H
                                    ; SOURCE LINE # 10
0014 CB00          RET
             ; FUNCTION main (END    RMASK = @0x4010)


C166: _srvwdt_

_srvwdt_

Summary
#include <intrins.h>

void _srvwdt_ (void);
Description | The _srvwdt_ routine inserts a SRVWDT instruction (which services the watchdog timer) into the program. This routine is implemented as an intrinsic function. The code is generated inline rather than being called.
Return Value | None.
See Also | _diswdt_
Example
#include <intrins.h>

int  i;
void test_srvwdt (void)  {

  i = 1;
  _srvwdt_();        /* service watchdog timer */
  i = 0;
}


C166: _testclear_

_testclear_

Summary
#include <intrins.h>

bit _testclear_ (
  bit b);          /* bit to test and clear */
Description | The _testclear_ routine generates a JBC instruction in the generated program code to simultaneously test the bit and clear it to 0. This routine can be used only on directly addressable bit variables and is invalid on any other type of expression. This routine is implemented as an intrinsic function. The code generated is inline rather than being called.
Return Value | The _testclear_ routine returns the value of the bit.
See Also | _testset_
Example
#include <intrins.h>
#include <stdio.h>                    /* for printf */

void tst_testbit (void) {
  bit test_flag;

  if (_testclear_ (test_flag))
    printf ("Bit was set\n");
  else
    printf ("Bit was clear\n");
}


C166: _testset_

_testset_

Summary
#include <intrins.h>

bit _testset_ (
  bit b);          /* bit to test and set */
Description | The _testset_ routine generates a JNBS instruction in the generated program code to simultaneously test the bit and set it to 1. This routine can be used only on directly addressable bit variables and is invalid on any other type of expression. This routine is implemented as an intrinsic function. The code required is included inline rather than being called.
Return Value | The _testset_ routine returns 1 if the bit was clear and 0 otherwise.
See Also | _testclear_
Example
#include <intrins.h>
#include <stdio.h>                    /* for printf */

void tst_testset (void) {
  bit test_flag;

  if (_testset_ (test_flag))
    printf ("Bit was clear\n");
  else
    printf ("Bit was set\n");
}


C166: _tolower

_tolower

Summary
#include <ctype.h>

int _tolower (
  int c);      /* character to convert */
Description | The _tolower routine is a macro version of tolower that may be used when c is known to be an uppercase character.
Return Value | The _tolower macro returns a lowercase character.
See Also | _toupper, tolower, toupper
Example
#include <ctype.h>

void test__tolower (char k) {
  if (isupper (k)) k = _tolower (k);
}


C166: _toupper

_toupper

Summary
#include <ctype.h>

int _toupper (
  int c);      /* character to convert */
Description | The _toupper routine is a macro version of toupper that may be used when c is known to be a lowercase character.
Return Value | The _toupper macro returns an uppercase character.
See Also | _tolower, tolower, toupper
Example
#include <ctype.h>

void test__toupper (char k) {
  if (islower (k)) k = _toupper (k);
}


C166: _trap_

_trap_

Summary
#include <intrins.h>

void _trap_ (
  unsigned int trapno);     /* trap number to insert */
Description | The _trap_ routine allows you to invoke a trap (interrupt) function or generate a software reset. This routine inserts a TRAP or an SRST instruction into the program. If trapno is zero, a SRST (software reset) instruction is generated. If trapno is non-zero, a TRAP instruction is generated. This routine is implemented as an intrinsic function. The code is generated inline rather than being called.
Return Value | None.
Example
1       #include <intrins.h>
2       #include <reg166.h>
3
4       void main (void)  {
5         _trap_ (0x10);  /* generates TRAP */
6         _trap_ (0x01);  /* generates TRAP */
7         _trap_ (0x00);  /* generates SRST */
8       }

ASSEMBLY LISTING OF GENERATED OBJECT CODE

             ; FUNCTION main (BEGIN  RMASK = @0x8000)
                                     ; SOURCE LINE # 4
                                     ; SOURCE LINE # 5
0000 9B20          TRAP    #010H
                                     ; SOURCE LINE # 6
0002 9B02          TRAP    #01H
                                     ; SOURCE LINE # 7
0004 B748B7B7      SRST
                                     ; SOURCE LINE # 8
0008 CB00          RET
             ; FUNCTION main (END    RMASK = @0x8000)


C166: abs

abs

Summary
#include <math.h>
/* or */
#include <stdlib.h>

int abs (
  int val);     /* number to take absolute value of */
Description | The abs function determines the absolute value of the integer val.
Return Value | The abs function returns the absolute value of val.
See Also | fabs, labs
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_abs (void) {
  int x;
  int y;

  x = -42;
  y = abs (x);

  printf ("ABS(%d) = %d\n", x, y);
}


C166: acos

acos

Summary
#include <math.h>

double acos (
  double x);   /* number to calculate arc cosine of */
Description | The acos function calculates the arc cosine of the floating-point number x whose value must be between -1 and 1. The floating-point value returned by acos is a number in the range 0-pi.
Return Value | The acos function returns the arc cosine of x.
See Also | asin, atan, atan2
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_acos (void) {
  float x;
  float y;

  for (x = -1.0; x <= 1.0; x += 0.1) {
    y = acos (x);
    printf ("ACOS(%f) = %f\n", x, y);
  }
}


C166: asin

asin

Summary
#include <math.h>

double asin (
  double x);   /* number to calculate arc sine of */
Description | The asin function calculates the arc sine of the floating-point number x. The value of x must be in the range -1 to 1. The floating-point value returned by asin is a number in the -pi/2 to pi/2 range.
Return Value | The asin function returns the arc sine of x.
See Also | acos, atan, atan2
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_asin (void) {
  float x;
  float y;

  for (x = -1.0; x <= 1.0; x += 0.1) {
    y = asin (x);
    printf ("ASIN(%f) = %f\n", x, y);
  }
}


C166: assert

assert

Summary
#include <assert.h>

void assert (
  expression);      /* expression to test */
Description | The assert macro tests expression and prints a diagnostic message using the printf library routine if expression is false.
Return Value | None.
Example
#include <assert.h>
#include <stdio.h>       /* required for printf */

void check_parms (
  char *string)
{
  assert (string != NULL);     /* check for NULL ptr */
  printf ("String %s is OK\n", string);
}


C166: atan

atan

Summary
#include <math.h>

double atan (
  double x);   /* number to calculate arc tangent of */
Description | The atan function calculates the arc tangent of the floating-point number x. The floating-point value returned by atan is a number in the -pi/2 to pi/2 range.
Return Value | The atan function returns the arc tangent of x.
See Also | acos, asin, atan2
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_atan (void) {
  float x;
  float y;

  for (x = -10.0; x <= 10.0; x += 0.1) {
    y = atan (x);
    printf ("ATAN(%f) = %f\n", x, y);
  }
}


C166: atan2

atan2

Summary
#include <math.h>

double atan2 (
  double y,    /* denominator for arc tangent */
  double x);   /* numerator for arc tangent */
Description | The atan2 function calculates the arc tangent of the floating-point ratio y / x. This function uses the signs of both x and y to determine the quadrant of the return value. The floating-point value returned by atan2 is a number in the range -pi to pi.
Return Value | The atan2 function returns the arc tangent of y / x.
See Also | acos, asin, atan
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_atan2 (void) {
  float x;
  float y;
  float z;

  x = -1.0;

  for (y = -10.0; y < 10.0; y += 0.1) {
    z = atan2 (y,x);
    printf ("ATAN2(%f/%f) = %f\n", y, x, z);
  }

/* z approaches -pi as y goes from -10 to 0 */
/* z approaches +pi as y goes from +10 to 0 */
}


C166: atof

atof

Summary
#include <stdlib.h>

double atof (
  void *string);   /* string to convert */
Description

The atof function converts string into a floating-point value. The input string must be a sequence of characters that can be interpreted as a floating-point number. This function stops processing characters from string at the first one it cannot recognize as part of the number.

The string passed to atof must have the following format:

« {+|-} » digits.digits « {e|E} « {+|-} » digits »

Where

digits

 May be one or more decimal digits (0-9).
Return Value | The atof function returns the floating-point value produced by interpreting the characters in string as a number.
See Also | atoi, atol, strtod, strtol, strtoul
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_atof (void) {
  float f;
  char s [] = "1.23";

  f = atof (s);
  printf ("ATOF(%s) = %f\n", s, f);
}


C166: atoi

atoi

Summary
#include <stdlib.h>

int atoi (
  void *string);   /* string to convert */
Description

The atoi function converts string into an integer value. The input string must be a sequence of characters that can be interpreted as an integer. This function stops processing characters from string at the first one it cannot recognize as part of the number.

The string passed to atoi must have the following format:

« whitespace » « {+|-} » digits

Where

whitespace | May be any number of space(' '), tab ('\t'), newline ('\n'), or carriage return ('\r') characters.
digits | May be one or more decimal digits.
Return Value | The atoi function returns the integer value that is produced by interpreting the characters in string as a number.
See Also | atof, atol, strtod, strtol, strtoul
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_atoi (void) {
  int i;
  char s [] = "12345";

  i = atoi (s);
  printf ("ATOI(%s) = %d\n", s, i);
}


C166: atol

atol

Summary
#include <stdlib.h>

long atol (
  void *string);   /* string to convert */
Description

The atol function converts string into a long integer value. The input string must be a sequence of characters that can be interpreted as a long integer. This function stops processing characters from string at the first one it cannot recognize as part of the number.

The string passed to atol must have the following format:

« whitespace » « {+|-} » digits

Where

whitespace | May be any number of space(' '), tab ('\t'), newline ('\n'), or carriage return ('\r') characters.
digits | May be one or more decimal digits.
Return Value | The atol function returns the long integer value that is produced by interpreting the characters in string as a number.
See Also | atof, atoi, strtod, strtol, strtoul
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_atol (void) {
  long l;
  char s [] = "8003488051";

  l = atol (s);
  printf ("ATOL(%s) = %ld\n", s, l);
}


C166: calloc

calloc

Summary
#include <stdlib.h>

void far *calloc (
  size_t num,    /* number of items */
  size_t len);   /* length of each item */

or

void huge *calloc (
  size_t num,    /* number of items */
  size_t len);   /* length of each item */

or

void xhuge *calloc (
  size_t num,    /* number of items */
  size_t len);   /* length of each item */
Description

The calloc function allocates memory for an array of num elements. Each element in the array occupies len bytes and is initialized to 0. The total number of bytes of memory allocated is num * len.

Note

  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • Pointer arguments and return values are far in Small, Medium, Compact, and Large Memory Models; huge in HCompact and HLarge Memory Models; and xhuge in the XLarge Memory Model. This function is not supported in the Tiny Memory Model.
Return Value | The calloc function returns a pointer to the allocated memory or a null pointer if the memory allocation request cannot be satisfied.
See Also | free, init_mempool, malloc, realloc
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_calloc (void) {
  int far *p; /* ptr to array of 100 ints */

  p = calloc (100, sizeof (int));

  if (p == NULL)
    printf ("Error allocating array\n");
  else
    printf ("Array address is %p\n", (void *) p);
}


C166: calloc_b

calloc_b

Summary
#include <stdlib.h>

void far *calloc_b (
  size_t num,           /* number of items */
  size_t len);          /* length of each item */

or

void huge *calloc_b (
  size_t num,           /* number of items */
  size_t len);          /* length of each item */
Description

The calloc_b function allocates memory for an array of num elements. Each element in the array occupies len bytes and is initialized to 0. The total number of bytes of memory allocated is num * len.

Note

  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • Pointer return values are far in Small, Medium, Compact, and Large Memory Models and huge in HCompact, HLarge, and XLarge Memory Models. This function is not supported in the Tiny Memory Model.
Return Value | The calloc_b function returns a pointer to the allocated memory or a null pointer if the memory allocation request cannot be satisfied.
See Also | free_b, init_mempool_b, malloc_b, realloc_b
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_calloc_b (void) {
  int far *p; /* ptr to array of 100 ints */

  p = calloc_b (100, sizeof (int));

  if (p == NULL)
    printf ("Error allocating array\n");
  else
    printf ("Array address is %p\n", (void *) p);
}


C166: ceil

ceil

Summary
#include <math.h>

double ceil (
  double val);   /* number to calculate ceiling for */
Description | The ceil function calculates the smallest integer value that is greater than or equal to val.
Return Value | The ceil function returns a float that contains the smallest integer value that is not less than val.
See Also | floor
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_ceil (void) {
  float x;
  float y;

  x = 45.998;
  y = ceil (x);

  printf ("CEIL(%f) = %f\n", x, y);

  /* output is "CEIL(45.998) = 46" */
}


C166: cos

cos

Summary
#include <math.h>

double cos (
  double x);   /* number to calculate cosine for */
Description | The cos function calculates the cosine of the floating-point value x. The value of x must be between -65535 and 65535. Values outside this range result in an NaN error.
Return Value | The cos function returns the cosine for the value x.
See Also | sin, tan
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_cos (void) {
  float x;
  float y;

  for (x = 0; x < (2 * 3.1415); x += 0.1) {
    y = cos (x);

    printf ("COS(%f) = %f\n", x, y);
  }
}


C166: cosh

cosh

Summary
#include <math.h>

double cosh (
  double x);   /* value for hyperbolic cos function */
Description | The cosh function calculates the hyperbolic cosine of the floating-point value x.
Return Value | The cosh function returns the hyperbolic cosine for the value x.
See Also | sinh, tanh
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_cosh (void) {
  float x;
  float y;

  for (x = 0; x < (2 * 3.1415); x += 0.1) {
    y = cosh (x);

    printf ("COSH(%f) = %f\n", x, y);
  }
}


C166: exp

exp

Summary
#include <math.h>

double exp (
  double x);   /* power to use for ex function */
Description | The exp function calculates the exponential function for the floating-point value x.
Return Value | The exp function returns the floating-point value ex.
See Also | log, log10
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_exp (void) {
  float x;
  float y;

  x = 4.605170186;
  y = exp (x); /* y = 100 */

  printf ("EXP(%f) = %f\n", x, y);
}


C166: fabs

fabs

Summary
#include <math.h>

double fabs (
  double val);   /* number to take absolute value of */
Description | The fabs function determines the absolute value of the floating-point number val.
Return Value | The fabs function returns the absolute value of val.
See Also | abs, labs
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_fabs (void) {
  float x;
  float y;

  x = 10.2;
  y = fabs (x);
  printf ("FABS(%f) = %f\n", x, y);

  x = -3.6;
  y = fabs (x);
  printf ("FABS(%f) = %f\n", x, y);
}


C166: floor

floor

Summary
#include <math.h>

double floor (
  double val);   /* number to calculate floor for */
Description | The floor function calculates the largest integer value that is less than or equal to val.
Return Value | The floor function returns a float that contains the largest integer value that is not greater than val.
See Also | ceil
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_floor (void) {
  float x;
  float y;

  x = 45.998;
  y = floor (x);

  printf ("FLOOR(%f) = %f\n", x, y);   /* prints 45 */
}


C166: fmemccpy

fmemccpy

Summary
#include <string.h>

void *fmemccpy (
  void far *dest,        /* destination buffer */
  const void far *src,   /* source buffer */
  char c,                /* character which ends copy */
  unsigned int len);     /* maximum bytes to copy */
Description

The fmemccpy function copies 0 or more characters from src to dest. Characters are copied until the character c is copied or until len bytes have been copied, whichever comes first.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fmemccpy function returns a pointer to the byte in dest that follows the last character copied or a null pointer if the last character copied was c.
See Also | fmemchr, fmemcmp, fmemcpy, fmemmove, fmemset, hmemcmp, memcmp, xmemcmp
Example
#include <string.h<
#include <stdio.h> /* for printf */

void tst_memccpy (char far *src1) {
  static char dst1 [100];
  void *c;

  c = fmemccpy (dst1, src1, 'g', sizeof (dst1));

  if (c == NULL)
    printf ("'g' was not found in the src buffer\n");
  else
    printf ("characters copied up to 'g'\n");
}


C166: fmemchr

fmemchr

Summary
#include <string.h>

void far *fmemchr (
  const void far *buf,   /* buffer to search */
  char c,                /* byte to find */
  unsigned int len);     /* maximum buffer length */
Description

The fmemchr function scans buf for the character c in the first len bytes of the buffer.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fmemchr function returns a pointer to the character c in buf or a null pointer if the character was not found.
See Also | fmemccpy, fmemcmp, fmemcpy, fmemmove, fmemset, memchr, xmemchr
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memchr (char far *src1, unsigned int len) {
  void *c;

  c = fmemchr (src1, 'g', len);

  if (c == NULL)
    printf ("'g' was not found in the buffer\n");
  else
    printf ("found 'g' in the buffer\n");
}


C166: fmemcmp

fmemcmp

Summary
#include <string.h>

int fmemcmp (
  const void far *buf1,   /* first buffer */
  const void far *buf2,   /* second buffer */
  unsigned int len);      /* bytes to compare */
Description

The fmemcmp function compares the first len bytes from buf1 and buf2 and returns a value indicating their relationship as follows:

Value | Description
< 0 | buf1 less than buf2
= 0 | buf1 equal to buf2
> 0 | buf1 greater than buf2

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fmemcmp function returns a positive, negative, or zero value indicating the relationship of buf1 and buf2.
See Also | fmemccpy, fmemchr, fmemcpy, fmemmove, fmemset, hmemcmp, memcmp, xmemcmp
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memcmp (
  char far *buf1,
  char far *buf2,
  unsigned int len)
{
char i;

  i = fmemcmp (buf1, buf2, len);

  if (i < 0)
    printf ("buf1 < buf2\n");
  else if (i > 0)
    printf ("buf1 > buf2\n");
  else
    printf ("buf1 == buf2\n");
}


C166: fmemcpy

fmemcpy

Summary
#include <string.h>

void far *fmemcpy (
  void far *dest,        /* destination buffer */
  const void far *src,   /* source buffer */
  unsigned int len);     /* bytes to copy */
Description

The fmemcpy function copies len bytes from src to dest. If these memory buffers overlap, the fmemcpy function cannot guarantee that bytes in src are copied to dest before being overwritten. If these buffers do overlap, use the fmemmove function.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fmemcpy function returns dest.
See Also | fmemccpy, fmemchr, fmemcmp, fmemmove, fmemset, hmemcpy, memcpy, xmemcpy
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memcpy (char far *src1)
{
char dst1 [101];
char *p;

  p = fmemcpy (dst1, src1, sizeof (dst1));
  printf ("dst = \"%s\"\n", p);
}


C166: fmemmove

fmemmove

Summary
#include <string.h>

void far *fmemmove (
  void far *dest,        /* destination buffer */
  const void far *src,   /* source buffer */
  unsigned intlen);      /* bytes to move */
Description

The fmemmove function copies len bytes from src to dest. If these memory buffers overlap, the fmemmove function ensures that bytes in src are copied to dest before being overwritten.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fmemmove function returns dest.
See Also | fmemccpy, fmemchr, fmemcmp, fmemcpy, fmemset, memmove, xmemmove
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memmove (void) {
  static char buf [] = "This is line 1 "
                       "This is line 2 "
                       "This is line 3 ";

  printf ("buf before = %s\n", buf);
  fmemmove (&buf [0], &buf [16], 32);
  printf ("buf after = %s\n", buf);
}


C166: fmemset

fmemset

Summary
#include <string.h>

void far *fmemset (
  void far *buf,      /* buffer to initialize */
  const char c,       /* byte value to set */
  unsigned intlen);   /* buffer length */
Description

The fmemset function sets the first len bytes in buf to c.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fmemset function returns dest.
See Also | fmemccpy, fmemchr, fmemcmp, fmemcpy, fmemmove, memset, xmemset
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memset (void) {
  char buf [10];

  fmemset (buf, '\0', sizeof (buf));
  /* fill buffer with null characters */
}


C166: fmod

fmod

Summary
#include <math.h>

double fmod (
  double x,    /* value to calculate modulo for */
  double y);   /* integer portion of modulo */
Description

The fmod function returns a value f such that f has the same sign as x, the absolute value of f is less than the absolute value of y, and there exists an integer k such that:

k * y + f = x

If the quotient x / y cannot be represented, the result is undefined.
Return Value The fmod function returns the floating-point remainder of x / y.
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_fmod (void) {
  float f;

  f = fmod (15.0, 4.0);
  printf ("fmod (15.0, 4.0) = %f\n", f);
}


C166: free

free

Summary
#include <stdlib.h>

void free (
  void far *p);      /* block to free */

or

void free (
  void huge *p);     /* block to free */

or

void free (
  void xhuge *p);    /* block to free */
Description

The free function returns a memory block to the memory pool. The p argument points to a memory block that was previously allocated with the calloc, malloc, or realloc functions. Once it has been returned to the memory pool by the free function, the block is available for subsequent allocation.

If p is a null pointer, it is ignored.

Note

  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • Pointer arguments and return values are far in Small, Medium, Compact, and Large Memory Models; huge in HCompact and HLarge Memory Models; and xhuge in the XLarge Memory Model. This function is not supported in the Tiny Memory Model.
Return Value | None.
See Also | calloc, init_mempool, malloc, realloc
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_free (void) {
  void far *mbuf;

  printf ("Allocating memory\n");
  mbuf = malloc (1000);

  if (mbuf == NULL) {
    printf ("Unable to allocate memory\n");
  }

  else {
    free (mbuf);
    printf ("Memory free\n");
  }
}


C166: free_b

free_b

Summary
#include <stdlib.h>

void free_b (
  void far *p);      /* block to free */

or

void free_b (
  void huge *p);     /* block to free */
Description

The free_b function returns a memory block to the memory pool. The p argument points to a memory block that was previously allocated with the calloc_b, malloc_b, or realloc_b functions. Once it has been returned to the memory pool by the free_b function, the block is available for subsequent allocation.

If p is a null pointer, it is ignored.

Note

  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • Pointer arguments and return values are far in Small, Medium, Compact, and Large Memory Models and huge in HCompact, HLarge, and XLarge Memory Models. This function is not supported in the Tiny Memory Model.
Return Value | None.
See Also | calloc_b, init_mempool_b, malloc_b, realloc_b
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_free_b (void) {
  void far *mbuf;

  printf ("Allocating memory\n");
  mbuf = malloc_b (1000);

  if (mbuf == NULL) {
    printf ("Unable to allocate memory\n");
  }

  else {
    free_b (mbuf);
    printf ("Memory free\n");
  }
}


C166: fstrcat

fstrcat

Summary
#include <string.h>

char far *fstrcat (
  char far *dst,          /* destination string */
  const char far *src);   /* source string */
Description

The fstrcat function concatenates or appends src to dst and terminates dst with a null character.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fstrcat function returns dst.
See Also | fstrchr, fstrcmp, fstrcpy, fstrcspn, fstrlen, fstrncat, fstrncmp, fstrncpy, fstrpbrk, fstrpos, fstrrchr, fstrrpbrk, fstrrpos, fstrspn
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strcat (char far* fstr) {
  char buf [21];

  fstrcpy (buf, fstr);
  fstrcat (buf, " #2");

  printf ("new string is %s\n", buf);
}


C166: fstrchr

fstrchr

Summary
#include <string.h>

char far *fstrchr (
  const char far *string,   /* string to search */
  char c);
Description

The fstrchr function searches string for the first occurrence of c. The null character terminating string is included in the search.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fstrchr function returns a pointer to the first occurrence of character c in string or a null pointer if no matching character is found.
See Also | fstrcat, fstrcmp, fstrcpy, fstrcspn, fstrlen, fstrncat, fstrncmp, fstrncpy, fstrpbrk, fstrpos, fstrrchr, fstrrpbrk, fstrrpos, fstrspn
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strchr (char far *buf) {
  char *s;

  s = fstrchr (buf, 't');

  if (s == NULL)
    printf ("No t's in buf.\n");
}


C166: fstrcmp

fstrcmp

Summary
#include <string.h>
int fstrcmp (
  const char far *string1,    /* first string */
  const char far *string2);   /* second string */
Description

The fstrcmp function compares the contents of string1 and string2 and returns a value indicating their relationship.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value

The fstrcmp function returns the following values to indicate the relationship of string1 to string2:

Value | Description
< 0 | string1 is less than string2
= 0 | string1 is equal to string2
> 0 | string1 is greater than string2
See Also fstrcat, fstrchr, fstrcpy, fstrcspn, fstrlen, fstrncat, fstrncmp, fstrncpy, fstrpbrk, fstrpos, fstrrchr, fstrrpbrk, fstrrpos, fstrspn, hstrcmp, strcmp, xstrcmp
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strcmp (char far *buf1, char far *buf2) {
  char i;

  i = fstrcmp (buf1, buf2);

  if (i < 0)
    printf ("buf1 < buf2\n");
  else if (i > 0)
    printf ("buf1 > buf2\n");
  else
    printf ("buf1 == buf2\n");
}


C166: fstrcpy

fstrcpy

Summary
#include <string.h>

char far *fstrcpy (
  char far *dst,          /* destination string */
  const char far *src);   /* source string */
Description

The fstrcpy function copies src to dst and appends a null character to the end of dst.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fstrcpy function returns dst.
See Also | fstrcat, fstrchr, fstrcmp, fstrcspn, fstrlen, fstrncat, fstrncmp, fstrncpy, fstrpbrk, fstrpos, fstrrchr, fstrrpbrk, fstrrpos, fstrspn, hstrcpy, strcpy, xstrcpy
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strcpy (char far *s) {
  char buf [21];

  fstrcpy (buf, s);
  fstrcat (buf, " #2");

  printf ("new string is %s\n", buf);
}


C166: fstrcspn

fstrcspn

Summary
#include <string.h>

int fstrcspn (
  const char far *src,    /* source string */
  const char far *set);   /* characters to find */
Description

The fstrcspn function searches the src string for any of the characters in the set string.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fstrcspn function returns the index of the first character located in src that matches a character in set. If the first character in src matches a character in set, a value of 0 is returned. If there are no matching characters in src, the length of the src is returned.
See Also | fstrcat, fstrchr, fstrcmp, fstrcpy, fstrlen, fstrncat, fstrncmp, fstrncpy, fstrpbrk, fstrpos, fstrrchr, fstrrpbrk, fstrrpos, fstrspn
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strcspn (char far *buf) {
  int i;

  i = fstrcspn (buf, ".,");

  if (buf [i] != '\0')
    printf ("Found a %c.\n", (char) buf [i]);
}


C166: fstrlen

fstrlen

Summary
#include <string.h>

size_t fstrlen (
  char far *src);      /* source string */
Description

The fstrlen function calculates the length, in bytes, of src. This calculation does not include the null terminating character.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fstrlen function returns the length of src.
See Also | fstrcat, fstrchr, fstrcmp, fstrcpy, fstrcspn, fstrncat, fstrncmp, fstrncpy, fstrpbrk, fstrpos, fstrrchr, fstrrpbrk, fstrrpos, fstrspn
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strlen (char far *buf) {
  int len;

  len = fstrlen (buf);
  printf ("string length is %d\n", len);
}


C166: fstrncat

fstrncat

Summary
#include <string.h>

char far *fstrncat (
  char far *dst,         /* destination string */
  const char far *src,   /* source string */
  unsigned int len);     /* max. chars to concatenate */
Description

The fstrncat function appends at most len characters from src to dst and terminates dst with a null character. If src has fewer than len characters, src is copied up to and including the null terminating character.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fstrncat function returns dst.
See Also | fstrcat, fstrchr, fstrcmp, fstrcpy, fstrcspn, fstrlen, fstrncmp, fstrncpy, fstrpbrk, fstrpos, fstrrchr, fstrrpbrk, fstrrpos, fstrspn
Example
#include <string.h>

void tst_strncat (char far *fstr) {
  char buf [21];

  strcpy (buf, "Test ");
  fstrncat (buf, fstr, sizeof (buf) - strlen (buf));
}


C166: fstrncmp

fstrncmp

Summary
#include <string.h>

int fstrncmp (
  const char far *string1,   /* first string */
  const char far *string2,   /* second string */
  unsigned int len);         /* max characters to compare */
Description

The fstrncmp function compares the first len bytes of string1 and string2 and returns a value indicating their relationship.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value

The fstrncmp function returns the following values to indicate the relationship of the first len bytes of string1 to string2:

Value | Description
< 0 | string1 is less than string2
= 0 | string1 is equal to string2
> 0 | string1 is greater than string2
See Also fstrcat, fstrchr, fstrcmp, fstrcpy, fstrcspn, fstrlen, fstrncat, fstrncpy, fstrpbrk, fstrpos, fstrrchr, fstrrpbrk, fstrrpos, fstrspn
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strncmp (char far *str1, char far *str2) {
  char i;

  i = fstrncmp (str1, str2, 15);

  if (i < 0)       printf ("str1 < str2\n");
  else if (i > 0)  printf ("str1 > str2\n");
  else             printf ("str1 == str2\n");
}


C166: fstrncpy

fstrncpy

Summary
#include <string.h>

char far *fstrncpy (
  char far *dst,         /* destination string */
  const char far *src,   /* source string */
  unsigned int len);     /* max characters to copy */
Description

The fstrncpy function copies at most len characters from src to dst.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fstrncpy function returns dst.
See Also | fstrcat, fstrchr, fstrcmp, fstrcpy, fstrcspn, fstrlen, fstrncat, fstrncmp, fstrpbrk, fstrpos, fstrrchr, fstrrpbrk, fstrrpos, fstrspn
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strncpy (char far *s) {
  char buf [21];

  fstrncpy (buf, s, sizeof (buf));
  buf [sizeof (buf)] = '\0';
}


C166: fstrpbrk

fstrpbrk

Summary
#include <string.h>

char far *fstrpbrk (
  const char far *string,   /* string to search */
  const char far *set);     /* characters to find */
Description

The fstrpbrk function searches string for the first occurrence of any character from set. The null terminator is not included in the search.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fstrpbrk function returns a pointer to the matching character in string. If string contains no characters from set, a null pointer is returned.
See Also | fstrcat, fstrchr, fstrcmp, fstrcpy, fstrcspn, fstrlen, fstrncat, fstrncmp, fstrncpy, fstrpos, fstrrchr, fstrrpbrk, fstrrpos, fstrspn
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strpbrk (char far *text) {
  char vowels [] ="AEIOUaeiou";
  char far *p;

  p = fstrpbrk (text, vowels);

  if (p == NULL)
    printf ("No vowels found in text.\n");
}


C166: fstrpos

fstrpos

Summary
#include <string.h>

int fstrpos (
  const char far *string,  /* string to search */
  char c);                 /* character to find */
Description

The fstrpos function searches string for the first occurrence of c. The null character terminating string is included in the search.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fstrpos function returns the index of the character matching c in string or a value of -1 if no matching character was found. The index of the first character in string is 0.
See Also | fstrcat, fstrchr, fstrcmp, fstrcpy, fstrcspn, fstrlen, fstrncat, fstrncmp, fstrncpy, fstrpbrk, fstrrchr, fstrrpbrk, fstrrpos, fstrspn
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strpos (char far *text) {
  int i;

  i = fstrpos (text, ' ');

  if (i == -1)
    printf ("No spaces found in text.\n");
  else
    printf ("Found a space at offset %d\n", i);
}


C166: fstrrchr

fstrrchr

Summary
#include <string.h>

char far *fstrrchr (
  const char far *string,  /* string to search */
  char c);                 /* character to find */
Description

The fstrrchr function searches string for the last occurrence of c. The null character terminating string is included in the search.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fstrrchr function returns a pointer to the last character c found in string or a null pointer if no matching character was found.
See Also | fstrcat, fstrchr, fstrcmp, fstrcpy, fstrcspn, fstrlen, fstrncat, fstrncmp, fstrncpy, fstrpbrk, fstrpos, fstrrpbrk, fstrrpos, fstrspn
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strrchr (char far *buf) {
  char far *s;

  s = fstrrchr (buf, 't');

  if (s == NULL)
    printf ("No t's were found.\n");
}


C166: fstrrpbrk

fstrrpbrk

Summary
#include <string.h>

char far *fstrrpbrk (
  const char far *string,   /* string to search */
  const char far *set);     /* characters to find */
Description

The fstrrpbrk function searches string for the last occurrence of any character from set. The null terminator is not included in the search.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fstrrpbrk function returns a pointer to the last matching character in string. If string contains no characters from set, a null pointer is returned.
See Also | fstrcat, fstrchr, fstrcmp, fstrcpy, fstrcspn, fstrlen, fstrncat, fstrncmp, fstrncpy, fstrpbrk, fstrpos, fstrrchr, fstrrpos, fstrspn
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strrpbrk (char far *text) {
  char vowels [] ="AEIOUaeiou";
  char far *p;

  p = fstrpbrk (text, vowels);

  if (p == NULL)
    printf ("No vowels found in %s\n", text);
}


C166: fstrrpos

fstrrpos

Summary
#include <string.h>

int fstrrpos (
  const char far *string,  /* string to search */
  char c);                 /* character to find */
Description

The fstrrpos function searches string for the last occurrence of c. The null character terminating string is included in the search.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fstrrpos function returns the index of the last character matching c in string or a value of -1 if no matching character was found. The index of the first character in string is 0.
See Also | fstrcat, fstrchr, fstrcmp, fstrcpy, fstrcspn, fstrlen, fstrncat, fstrncmp, fstrncpy, fstrpbrk, fstrpos, fstrrchr, fstrrpbrk, fstrspn
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strrpos (char far *s) {
  int i;

  i = fstrrpos (s, ' ');

  if (i == -1)
    printf ("No spaces found in %s\n", s);
  else
    printf ("Last space in %s is at offset %d\n", s, i);
}


C166: fstrspn

fstrspn

Summary
#include <string.h>

int fstrspn (
  const char far *string,   /* string to search */
  const char far *set);     /* characters to allow */
Description

The fstrspn function searches string for characters not found in the set string.

Note

  • This function uses far pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The fstrspn function returns the index of the first character located in string that does not match a character in set. If the first character in string does not match a character in set, a value of 0 is returned. If all characters in string are found in set, the length of string is returned.
See Also | fstrcat, fstrchr, fstrcmp, fstrcpy, fstrcspn, fstrlen, fstrncat, fstrncmp, fstrncpy, fstrpbrk, fstrpos, fstrrchr, fstrrpbrk, fstrrpos
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strspn (char far *digit_str) {
  char octd [] = "01234567";
  int i;

  i = fstrspn (digit_str, octd);

  if (digit_str [i] != '\0')
    printf ("%c is not an octal digit\n", digit_str [i]);
}


C166: getchar

getchar

Summary
#include <stdio.h>

char getchar (void);
Description

The getchar function reads a single character from the input stream using the _getkey function. The character read is then passed to the putchar function to be echoed.

Note

  • This function is implementation-specific and is based on the operation of the _getkey and putchar functions. These functions, as provided in the standard library, read and write characters using the microcontroller's serial port. Custom functions may use other I/O devices.
Return Value | The getchar function returns the character read.
See Also | _getkey, putchar, ungetchar
Example
#include <stdio.h>

void tst_getchar (void) {
  char c;

  while ((c = getchar ()) != 0x1B) {
    printf ("character = %c %bu %bx\n", c, c, c);
  }
}


C166: gets

gets

Summary
#include <stdio.h>

char *gets (
  char *string,        /* string to read */
  unsigned int len);   /* max characters to read */
Description

The gets function calls the getchar function to read a line of characters into string. The line consists of all characters up to and including the first newline character ('\n'). The newline character is replaced by a null character ('\0') in string.

The len argument specifies the maximum number of characters that may be read. If len characters are read before a newline is encountered, the gets function terminates string with a null character and returns.

Note

  • This function is implementation-specific and is based on the operation of the _getkey and putchar functions. These functions, as provided in the standard library, read and write characters using the microcontroller's serial port. Custom functions may use other I/O devices.
Return Value | The gets function returns string.
See Also | printf, puts, scanf
Example
#include <stdio.h>

void tst_gets (void) {
  char buf [21];

  do {
    gets (buf, sizeof(buf)-1);
    printf ("Input string \"%s\"", buf);
  } while (buf [0] != '\0');
}


C166: hmemcmp

hmemcmp

Summary
#include <string.h>

int hmemcmp (
  const void huge *buf1,   /* first buffer */
  const void huge *buf2,   /* second buffer */
  unsigned int len);       /* bytes to compare */
Description

The hmemcmp function compares the first len bytes from buf1 and buf2 and returns a value indicating their relationship as follows:

Value | Description
< 0 | buf1 less than buf2
= 0 | buf1 equal to buf2
> 0 | buf1 greater than buf2

Note

  • This function uses huge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The hmemcmp function returns a positive, negative, or zero value indicating the relationship of buf1 and buf2.
See Also | fmemcmp, hmemcpy, memcmp, xmemcmp
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memcmp (
  char huge *buf1,
  char huge *buf2,
  unsigned int len)
{
char i;

  i = hmemcmp (buf1, buf2, len);

  if (i < 0)
    printf ("buf1 < buf2\n");
  else if (i > 0)
    printf ("buf1 > buf2\n");
  else
    printf ("buf1 == buf2\n");
}


C166: hmemcpy

hmemcpy

Summary
#include <string.h>

void huge *hmemcpy (
  void huge *dest,        /* destination buffer */
  const void huge *src,   /* source buffer */
  unsigned int len);      /* bytes to copy */
Description

The hmemcpy function copies len bytes from src to dest. If these memory buffers overlap, the hmemcpy function cannot guarantee that bytes in src are copied to dest before being overwritten. If these buffers do overlap, use the xmemmove function.

Note

  • This function uses huge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The hmemcpy function returns dest.
See Also | fmemcpy, hmemcmp, memcpy, xmemcpy
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memcpy (char huge *src1)
{
char dst1 [101];
char *p;

  p = hmemcpy (dst1, src1, sizeof (dst1));
  printf ("dst = \"%s\"\n", p);
}


C166: hstrcmp

hstrcmp

Summary
#include <string.h>
int hstrcmp (
  const char huge *string1,    /* first string */
  const char huge *string2);   /* second string */
Description

The hstrcmp function compares the contents of string1 and string2 and returns a value indicating their relationship.

Note

  • This function uses huge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value

The hstrcmp function returns the following values to indicate the relationship of string1 to string2:

Value | Description
< 0 | string1 is less than string2
= 0 | string1 is equal to string2
> 0 | string1 is greater than string2
See Also fstrcmp, hstrcpy, strcmp, xstrcmp
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strcmp (char huge *buf1, char huge *buf2) {
  char i;

  i = hstrcmp (buf1, buf2);

  if (i < 0)
    printf ("buf1 < buf2\n");
  else if (i > 0)
    printf ("buf1 > buf2\n");
  else
    printf ("buf1 == buf2\n");
}


C166: hstrcpy

hstrcpy

Summary
#include <string.h>

char huge *hstrcpy (
  char huge *dst,          /* destination string */
  const char huge *src);   /* source string */
Description

The hstrcpy function copies src to dst and appends a null character to the end of dst.

Note

  • This function uses huge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The hstrcpy function returns dst.
See Also | fstrcpy, hstrcmp, strcpy, xstrcpy
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strcpy (char huge *s) {
  char buf [21];

  hstrcpy (buf, s);

  printf ("new string is %s\n", buf);
}


C166: init_mempool

init_mempool

Summary
#include <stdlib.h>

void init_mempool (
  void far *p,    /* start of memory pool */
  size_t size);   /* length of memory pool */

or

void init_mempool (
  void huge *p,   /* start of memory pool */
  size_t size);   /* length of memory pool */

or

void init_mempool (
  void xhuge *p,  /* start of memory pool */
  size_t size);   /* length of memory pool */
Description

The init_mempool function initializes the memory management routines and provides the starting address and size of the memory pool. The p argument points to a memory area in xdata which is managed using the calloc, free, malloc, and realloc library functions. The size argument specifies the number of bytes to use for the memory pool.

Note

  • This function must be used to setup the memory pool before any other memory management functions (calloc, free, malloc, realloc) can be called. Call the init_mempool function only once at the beginning of your program.
  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • Pointer arguments and return values are far in Small, Medium, Compact, and Large Memory Models; huge in HCompact and HLarge Memory Models; and xhuge in the XLarge Memory Model. This function is not supported in the Tiny Memory Model.
Return Value | None.
See Also | calloc, free, malloc, realloc
Example
#include <stdlib.h>

unsigned char xdata malloc_mempool [0x1000];

void tst_init_mempool (void) {
  int i;
  void far *p;

  init_mempool (&malloc_mempool, sizeof(malloc_mempool));

  p = malloc (100);

  for (i = 0; i < 100; i++)
    ((char *) p)[i] = i;

  free (p);
}


C166: init_mempool_b

init_mempool_b

Summary
#include <stdlib.h>

void init_mempool_b (
  void xhuge *p,       /* start of memory pool */
  unsigned long size); /* length of memory pool */
Description

The init_mempool_b function initializes the memory management routines and provides the starting address and size of the memory pool. The p argument points to a memory area which is managed using the calloc_b, free_b, malloc_b, and realloc_bb library functions. The size argument specifies the number of bytes to use for the memory pool.

Note

  • This function must be used to setup the memory pool before any other memory management functions (calloc_b, free_b, malloc_b, realloc_b) can be called. Call the init_mempool_b function only once at the beginning of your program.
  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • Pointer arguments are xhuge in all memory models. This function is not supported in the Tiny Memory Model.
Return Value | None.
See Also | calloc_b, free_b, malloc_b, realloc_b
Example
#include <stdlib.h>

char memory_pool [0x1000];

void tst_init_mempool_b (void) {
  void far *p;
  int i;

/* initialize memory pool */
  init_mempool_b (memory_pool, sizeof(memory_pool));

  p = malloc_b (100);

  for (i = 0; i < 100; i++)
    ((char *) p)[i] = i;

  free_b (p);
}


C166: isalnum

isalnum

Summary
#include <ctype.h>

int isalnum (
  int c);   /* character to test */
Description | The isalnum function tests c to determine if it is an alphanumeric character ('A'-'Z', 'a'-'z', or '0'-'9').
Return Value | The isalnum function returns a value of 1 if c is an alphanumeric character or a value of 0 if it is not.
See Also | isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, isxdigit
Example
#include <ctype.h>
#include <stdio.h> /* for printf */

void tst_isalnum (void) {
  unsigned char i;
  char *p;

  for (i = 0; i < 128; i++) {
    p = (isalnum (i) ? "YES" : "NO");

    printf ("isalnum (%c) %s\n", i, p);
  }
}


C166: isalpha

isalpha

Summary
#include <ctype.h>

int isalpha (
  int c);   /* character to test */
Description | The isalpha function tests c to determine if it is an alphabetic character ('A'-'Z' or 'a'-'z').
Return Value | The isalpha function returns a value of 1 if c is an alphabetic character or a value of 0 if it is not.
See Also | isalnum, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, isxdigit
Example
#include <ctype.h>
#include <stdio.h> /* for printf */

void tst_isalpha (void) {
  unsigned char i;
  char *p;

  for (i = 0; i < 128; i++) {
    p = (isalpha (i) ? "YES" : "NO");

    printf ("isalpha (%c) %s\n", i, p);
  }
}


C166: iscntrl

iscntrl

Summary
#include <ctype.h>

int iscntrl (
  int c);   /* character to test */
Description | The iscntrl function tests c to determine if it is a control character (0x00-0x1F or 0x7F).
Return Value | The iscntrl function returns a value of 1 if c is a control character or a value of 0 if it is not.
See Also | isalnum, isalpha, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, isxdigit
Example
#include <ctype.h>
#include <stdio.h> /* for printf */

void tst_iscntrl (void) {
  unsigned char i;
  char *p;

  for (i = 0; i < 128; i++) {
    p = (iscntrl (i) ? "YES" : "NO");

    printf ("iscntrl (%c) %s\n", i, p);
  }
}


C166: isdigit

isdigit

Summary
#include <ctype.h>

int isdigit (
  int c);   /* character to test */
Description | The isdigit function tests c to determine if it is a decimal digit ('0'-'9').
Return Value | The isdigit function returns a value of 1 if c is a decimal digit or a value of 0 if it is not.
See Also | isalnum, isalpha, iscntrl, isgraph, islower, isprint, ispunct, isspace, isupper, isxdigit
Example
#include <ctype.h>
#include <stdio.h> /* for printf */

void tst_isdigit (void) {
  unsigned char i;
  char *p;

  for (i = 0; i < 128; i++) {
    p = (isdigit (i) ? "YES" : "NO");

    printf ("isdigit (%c) %s\n", i, p);
  }
}


C166: isgraph

isgraph

Summary
#include <ctype.h>

int isgraph (
  int c);   /* character to test */
Description | The isgraph function tests c to determine if it is a printable character (0x21-0x7E) not including space (' ').
Return Value | The isgraph function returns a value of 1 if c is a printable character or a value of 0 if it is not.
See Also | isalnum, isalpha, iscntrl, isdigit, islower, isprint, ispunct, isspace, isupper, isxdigit
Example
#include <ctype.h>
#include <stdio.h> /* for printf */

void tst_isgraph (void) {
  unsigned char i;
  char *p;

  for (i = 0; i < 128; i++) {
    p = (isgraph (i) ? "YES" : "NO");

    printf ("isgraph (%c) %s\n", i, p);
  }
}


C166: islower

islower

Summary
#include <ctype.h>

int islower (
  int c);   /* character to test */
Description | The islower function tests c to determine if it is a lowercase alphabetic character ('a'-'z').
Return Value | The islower function returns a value of 1 if c is a lowercase alphabetic character or a value of 0 if it is not.
See Also | isalnum, isalpha, iscntrl, isdigit, isgraph, isprint, ispunct, isspace, isupper, isxdigit
Example
#include <ctype.h>
#include <stdio.h> /* for printf */

void tst_islower (void) {
  unsigned char i;
  char *p;

  for (i = 0; i < 128; i++) {
    p = (islower (i) ? "YES" : "NO");

    printf ("islower (%c) %s\n", i, p);
  }
}


C166: isprint

isprint

Summary
#include <ctype.h>

int isprint (
  int c);   /* character to test */
Description | The isprint function tests c to determine if it is a printable character (0x20-0x7E).
Return Value | The isprint function returns a value of 1 if c is a printable character or a value of 0 if it is not.
See Also | isalnum, isalpha, iscntrl, isdigit, isgraph, islower, ispunct, isspace, isupper, isxdigit
Example
#include <ctype.h>
#include <stdio.h> /* for printf */

void tst_isprint (void) {
  unsigned char i;
  char *p;

  for (i = 0; i < 128; i++) {
    p = (isprint (i) ? "YES" : "NO");

    printf ("isprint (%c) %s\n", i, p);
  }
}


C166: ispunct

ispunct

Summary
#include <ctype.h>

int ispunct (
  int c);   /* character to test */
Description

The ispunct function tests c to determine if it is a punctuation character. Following is a list of all punctuation characters:

!
"
#
$ 		%
&
'
( 		)
*
+
, 		-
.
/
: 		;
<
=
> 		?
@
[
 ]
^
_
` 		{
|
}
~
Return Value | The ispunct function returns a value of 1 if c is a punctuation character or a value of 0 if it is not.
See Also | isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, isspace, isupper, isxdigit
Example
#include <ctype.h>
#include <stdio.h> /* for printf */

void tst_ispunct (void) {
  unsigned char i;
  char *p;

  for (i = 0; i < 128; i++) {
    p = (ispunct (i) ? "YES" : "NO");

    printf ("ispunct (%c) %s\n", i, p);
  }
}


C166: isspace

isspace

Summary
#include <ctype.h>

int isspace (
  int c);   /* character to test */
Description | The isspace function tests c to determine if it is a whitespace character (0x09-0x0D or 0x20).
Return Value | The isspace function returns a value of 1 if c is a whitespace character or a value of 0 if it is not.
See Also | isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isupper, isxdigit
Example
#include <ctype.h>
#include <stdio.h> /* for printf */

void tst_isspace (void) {
  unsigned char i;
  char *p;

  for (i = 0; i < 128; i++) {
    p = (isspace (i) ? "YES" : "NO");

    printf ("isspace (%c) %s\n", i, p);
  }
}


C166: isupper

isupper

Summary
#include <ctype.h>

int isupper (
  int c);   /* character to test */
Description | The isupper function tests c to determine if it is an uppercase alphabetic character ('A'-'Z').
Return Value | The isupper function returns a value of 1 if c is an uppercase alphabetic character or a value of 0 if it is not.
See Also | isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isxdigit
Example
#include <ctype.h>
#include <stdio.h> /* for printf */

void tst_isupper (void) {
  unsigned char i;
  char *p;

  for (i = 0; i < 128; i++) {
    p = (isupper (i) ? "YES" : "NO");

    printf ("isupper (%c) %s\n", i, p);
  }
}


C166: isxdigit

isxdigit

Summary
#include <ctype.h>

int isxdigit (
  int c);   /* character to test */
Description | The isxdigit function tests c to determine if it is a hexadecimal digit ('A'-'F', 'a'-'f', or '0'-'9').
Return Value | The isxdigit function returns a value of 1 if c is a hexadecimal digit or a value of 0 if it is not.
See Also | isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper
Example
#include <ctype.h>
#include <stdio.h> /* for printf */

void tst_isxdigit (void) {
  unsigned char i;
  char *p;

  for (i = 0; i < 128; i++) {
    p = (isxdigit (i) ? "YES" : "NO");

    printf ("isxdigit (%c) %s\n", i, p);
  }
}


C166: labs

labs

Summary
#include <math.h>
/* or */
#include <stdlib.h>

long labs (
  long val);     /* number to take absolute value of */
Description | The labs function determines the absolute value of the long integer val.
Return Value | The labs function returns the absolute value of val.
See Also | abs, fabs
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_labs (void) {
  long x;
  long y;

  x = -1234567L;
  y = labs (x);

  printf ("LABS(%ld) = %ld\n", x, y);
}


C166: log

log

Summary
#include <math.h>

double log (
  double val);   /* value to take natural logarithm of */
Description | The log function calculates the natural logarithm for the floating-point number val. The natural logarithm uses the base e or 2.718282...
Return Value | The log function returns the floating-point natural logarithm of val.
See Also | exp, log10
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_log (void) {
  float x;
  float y;

  x = 2.718282;
  x *= x;

  y = log (x); /* y = 2 */

  printf ("LOG(%f) = %f\n", x, y);
}


C166: log10

log10

Summary
#include <math.h>

double log10 (
  double val);   /* value to take common logarithm of */
Description | The log10 function calculates the common logarithm for the floating-point number val. The common logarithm uses base 10.
Return Value | The log10 function returns the floating-point common logarithm of val.
See Also | exp, log
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_log10 (void) {
  float x;
  float y;

  x = 2.718282;
  x *= x;

  y = log10 (x); /* y = 2 */

  printf ("LOG10(%f) = %f\n", x, y);
}


C166: longjmp

longjmp

Summary
#include <setjmp.h>

void longjmp (
  jmp_buf env,      /* environment to restore */
  int retval);      /* return value */
Description

The longjmp function restores the state which was previously stored in env by the setjmp function. The retval argument specifies the value to return from the setjmp function.

The longjmp and setjmp functions may be used to execute a non-local goto. They are usually utilized to pass control to an error recovery routine.

Local variables and function arguments are restored only if declared with the volatile attribute.
Return Value | None.
See Also | setjmp
Example
#include <setjmp.h>
#include <stdio.h> /* for printf */

jmp_buf env; /* jump environment (must be global) */
bit error_flag;

void trigger (void) {
  .
  .
  .
  /* processing code here */
  .
  .
  .
  if (error_flag != 0) {
    longjmp (env, 1);   /* return 1 to setjmp */
  }
  .
  .
  .
}

void recover (void) {
  /* recovery code here */
}

void tst_longjmp (void) {
  .
  .
  .
  if (setjmp (env) != 0) {     /* setjmp returns a 0 */
    printf ("LONGJMP called\n");
    recover ();
  }

  else {
    printf ("SETJMP called\n");

    error_flag = 1;            /* force an error */

    trigger ();
  }
}


C166: malloc

malloc

Summary
#include <stdlib.h>

void far *malloc (
  size_t size);   /* block size to allocate */

or

void huge *malloc (
  size_t size);   /* block size to allocate */

or

void xhuge *malloc (
  size_t size);    /* block size to allocate */
Description

The malloc function allocates a memory block from the memory pool of size bytes in length.

Note

  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • Pointer arguments and return values are far in Small, Medium, Compact, and Large Memory Models; huge in HCompact and HLarge Memory Models; and xhuge in the XLarge Memory Model. This function is not supported in the Tiny Memory Model.
Return Value | The malloc function returns a pointer to the allocated block or a null pointer if there is not enough memory to satisfy the allocation request.
See Also | calloc, free, init_mempool, realloc
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_malloc (void) {
  unsigned char far *p;

  p = malloc (1000); /* allocate 1000 bytes */

  if (p == NULL)
    printf ("Not enough memory space\n");
  else
    printf ("Memory allocated\n");
}


C166: malloc_b

malloc_b

Summary
#include <stdlib.h>

void far *malloc_b (
  size_t size);      /* block size to allocate */

or

void huge *malloc_b (
  size_t size);      /* block size to allocate */
Description

The malloc_b function allocates a memory block from the memory pool of size bytes in length.

Note

  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • Pointer return values are far in Small, Medium, Compact, and Large Memory Models and huge in HCompact, HLarge, and XLarge Memory Models. This function is not supported in the Tiny Memory Model.
Return Value | The malloc_b function returns a pointer to the allocated block or a null pointer if there is not enough memory to satisfy the allocation request.
See Also | calloc_b, free_b, init_mempool_b, realloc_b
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_malloc_b (void) {
  unsigned char far *p;

  p = malloc_b (1000); /* allocate 1000 bytes */

  if (p == NULL)
    printf ("Not enough memory space\n");
  else
    printf ("Memory allocated\n");
}


C166: memccpy

memccpy

Summary
#include <string.h>

void *memccpy (
  void *dest,          /* destination buffer */
  const void *src,     /* source buffer */
  char c,              /* character which ends copy */
  unsigned int len);   /* maximum bytes to copy */
Description | The memccpy function copies 0 or more characters from src to dest. Characters are copied until the character c is copied or until len bytes have been copied, whichever comes first.
Return Value | The memccpy function returns a pointer to the byte in dest that follows the last character copied or a null pointer if the last character copied was c.
See Also | memchr, memcmp, memcpy, memmove, memset
Example
#include <string.h<
#include <stdio.h> /* for printf */

void tst_memccpy (void) {
  char src1 [100] = "Copy this string to dst1";
  char dst1 [100];
  void *c;

  c = memccpy (dst1, src1, 'g', sizeof (dst1));

  if (c == NULL)
    printf ("'g' was not found in the src buffer\n");
  else
    printf ("characters copied up to 'g'\n");
}


C166: memchr

memchr

Summary
#include <string.h>

void *memchr (
  const void *buf,     /* buffer to search */
  char c,              /* byte to find */
  unsigned int len);   /* maximum buffer length */
Description | The memchr function scans buf for the character c in the first len bytes of the buffer.
Return Value | The memchr function returns a pointer to the character c in buf or a null pointer if the character was not found.
See Also | memccpy, memcmp, memcpy, memmove, memset
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memchr (void) {
  static char src1 [100] = "Search this string from the start";
  void *c;

  c = memchr (src1, 'g', sizeof (src1));

  if (c == NULL)
    printf ("'g' was not found in the buffer\n");
  else
    printf ("found 'g' in the buffer\n");
}


C166: memcmp

memcmp

Summary
#include <string.h>

int memcmp (
  const void *buf1,    /* first buffer */
  const void *buf2,    /* second buffer */
  unsigned int len);   /* bytes to compare */
Description

The memcmp function compares the first len bytes from buf1 and buf2 and returns a value indicating their relationship as follows:

Value | Description
< 0 | buf1 less than buf2
= 0 | buf1 equal to buf2
> 0 | buf1 greater than buf2
Return Value | The memcmp function returns a positive, negative, or zero value indicating the relationship of buf1 and buf2.
See Also | memccpy, memchr, memcpy, memmove, memset
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memcmp (void) {
  char hexchars [] = "0123456789ABCDEF";
  char hexchars2 [] = "0123456789abcdef";
  char i;

  i = memcmp (hexchars, hexchars2, 16);

  if (i < 0)
    printf ("hexchars < hexchars2\n");
  else if (i > 0)
    printf ("hexchars > hexchars2\n");
  else
    printf ("hexchars == hexchars2\n");
}


C166: memcpy

memcpy

Summary
#include <string.h>

void *memcpy (
  void *dest,          /* destination buffer */
  const void *src,     /* source buffer */
  unsigned int len);   /* bytes to copy */
Description | The memcpy function copies len bytes from src to dest. If these memory buffers overlap, the memcpy function cannot guarantee that bytes in src are copied to dest before being overwritten. If these buffers do overlap, use the memmove function.
Return Value | The memcpy function returns dest.
See Also | fmemcpy, memccpy, memchr, memcmp, memmove, memset, xmemcpy
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memcpy (void) {
  char src1 [100] = "Copy this string to dst1";
  char dst1 [100];
  char *p;

  p = memcpy (dst1, src1, sizeof (dst1));
  printf ("dst = \"%s\"\n", p);
}


C166: memmove

memmove

Summary
#include <string.h>

void *memmove (
  void *dest,          /* destination buffer */
  const void *src,     /* source buffer */
  unsigned int len);   /* bytes to move */
Description | The memmove function copies len bytes from src to dest. If these memory buffers overlap, the memmove function ensures that bytes in src are copied to dest before being overwritten.
Return Value | The memmove function returns dest.
See Also | memccpy, memchr, memcmp, memcpy, memset
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memmove (void) {
  static char buf [] = "This is line 1 "
                       "This is line 2 "
                       "This is line 3 ";

  printf ("buf before = %s\n", buf);
  memmove (&buf [0], &buf [16], 32);
  printf ("buf after = %s\n", buf);
}


C166: memset

memset

Summary
#include <string.h>

void *memset (
  void *buf,           /* buffer to initialize */
  const char c,        /* byte value to set */
  unsigned int len);   /* buffer length */
Description | The memset function sets the first len bytes in buf to c.
Return Value | The memset function returns dest.
See Also | fmemset, memccpy, memchr, memcmp, memcpy, memmove, xmemset
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memset (void) {
  char buf [10];

  memset (buf, '\0', sizeof (buf));
  /* fill buffer with null characters */
}


C166: modf

modf

Summary
#include <math.h>

double modf (
  double val,    /* value to calculate modulo for */
  double *ip);   /* integer portion of modulo */
Description | The modf function splits the floating-point number val into integer and fractional components. The fractional part of val is returned as a signed floating-point number. The integer part is stored as a floating-point number at ip.
Return Value | The modf function returns the signed fractional part of val.
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_modf (void) {
  float x;
  float int_part, frc_part;

  x = 123.456;

  frc_part = modf (x, &int_part);

  printf ("%f = %f + %f\n", x, int_part,frc_part);
}


C166: offsetof

offsetof

Summary
#include <stddef.h>

int offsetof (
  structure,      /* structure to use */
  member);        /* member to get offset for */
Description | The offsetof macro calculates the offset of the member structure element from the beginning of the structure. The structure argument must specify the name of a structure. The member argument must specify the name of a member of the structure.
Return Value | The offsetof macro returns the offset, in bytes, of the member element from the beginning of struct structure.
Example
#include <stddef.h>

struct index_st
  {
  unsigned char type;
  unsigned long num;
  unsigned ing len;
  };

typedef struct index_st index_t;

void main (void) {
  int x, y;

  x = offsetof (struct index_st, len);  /* x = 5 */
  y = offsetof (index_t, num);          /* y = 1 */
}


C166: pow

pow

Summary
#include <math.h>

double pow (
  double x,    /* value to use for base */
  double y);   /* value to use for exponent */
Description | The pow function calculates x raised to the yth power.
Return Value The pow function returns the value xy.
  • If x != 0 and y = 0, pow returns a value of 1.
  • If x = 0 and y <= 0, pow returns NaN.
  • If x < 0 and y is not an integer, pow returns NaN.
See Also | sqrt
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_pow (void) {
  float base;
  float power;
  float y;

  base = 2.0;
  power = 8.0;

  y = pow (base, power); /* y = 256 */

  printf ("%f ^ %f = %f\n", base, power, y);
}


C166: printf

printf

Summary
#include <stdio.h>

int printf (
  const char *fmtstr     /* format string */
  « , arguments »...);   /* additional arguments */
Description

The printf function formats a series of strings and numeric values and builds a string to write to the output stream using the putchar function. The fmtstr argument is a format string that may be composed of characters, escape sequences, and format specifications.

Ordinary characters and escape sequences are copied to the stream in the order in which they are interpreted. Format specifications always begin with a percent sign ('%') and require that additional arguments are included in the printf function call.

The format string is read from left to right. The first format specification encountered references the first argument after fmtstr and converts and outputs it using the format specification. The second format specification accesses the second argument after fmtstr, and so on. If there are more arguments than format specifications, extra arguments are ignored. Results are unpredictable if there are not enough arguments for the format specifications or if the argument types do not match those specified by fmtstr.

Format specifications have the following general format:

% « flags » « width » « .precision » « {l|L} » type

Each field in the format specification may be a single character or a number which specifies a particular format option.

The type field is a single character that specifies whether the argument is interpreted as a character, string, number, or pointer, as shown in the following table.

Type | Argument Type | Input Format
d | int | Signed decimal number.
u | unsigned int | Unsigned decimal number.
o | unsigned int | Unsigned octal number.
x | unsigned int | Unsigned hexadecimal number using "0123456789abcedf".
X | unsigned int | Unsigned hexadecimal number using "0123456789ABCDEF".
f | float | Floating-point number formatted as « - »dddd.dddd.
e | float | Floating-point number formatted as « - »d.dddde« - »dd.
E | float | Floating-point number formatted as « - »d.ddddE« - »dd.
g | float | Floating-point number using either the e or f format, whichever is more compact for the specified value and precision.
G | float | Floating-point number using either the E or f format, whichever is more compact for the specified value and precision.
c | char | A single character.
s | * | A string of characters terminated by a null character ('\0').
p | * | A generic pointer formatted as a linear address.

The optional characters l or L may immediately precede the type character to respectively specify long versions of the integer types d, i, u, o, x, and X.

Characters following a percent sign that are not recognized as a format specification are treated as ordinary characters. For example, "%%" writes a single percent sign to the output stream.

The flags field is a single character used to justify the output and to print +/- signs and blanks, decimal points, and octal and hexadecimal prefixes, as shown in the following table.

Flag | Description
- | Left justify the output in the specified field width.
+ | Prefix the output value with a + or - sign if the output is a signed type.
blank (' ') | Prefix the output value with a blank if it is a signed positive value. Otherwise, no blank is prefixed.
# | Prefixes a non-zero output value with 0, 0x, or 0X when used with o, x, and X field types, respectively. When used with the e, E, f, g, and G field types, the # flag forces the output value to include a decimal point. The # flag is ignored in all other cases.

The width field is a non-negative number that specifies the minimum number of characters printed. If the number of characters in the output value is less than width, blanks are added on the left (by default) or right (when the - flag is specified) to pad to the minimum width. If width is prefixed with a '0', zeros are padded instead of blanks. The width field never truncates the output. If the length of the output value exceeds the specified width, all characters are output.

The width field may be an asterisk ('*'), in which case an int argument from the argument list provides the width value. Specifying a 'b' in front of the asterisk specifies that the argument is an unsigned char.

The precision field is a non-negative number that specifies the number of characters to print, the number of significant digits, or the number of decimal places. The precision field can cause truncation or rounding of the output value in the case of a floating-point number as specified in the following table.

Type | Precision Field Meaning
d,u,o,x,X | The precision field specifies the minimum number of digits that are included in the output value. Digits are not truncated if the number of digits in the argument exceeds that defined in the precision field. If the number of digits in the argument is less than the precision field, the output value is padded on the left with zeros.
f | The precision field specifies the number of digits to the right of the decimal point. The last digit is rounded.
e,E | The precision field specifies the number of digits to the right of the decimal point. The last digit is rounded.
g,G | The precision field specifies the maximum number of significant digits in the output value.
s | The precision field specifies the maximum number of characters in the output value. Excess characters are not output.
c,p | The precision field has no effect on these field types.

The precision field may be an asterisk ('*'), in which case an int argument from the argument list provides the value. Specifying a 'b' in front of the asterisk specifies that the argument is an unsigned char.

Note

  • You must ensure that the argument type matches that of the format specification. You may use type casts to ensure that the proper type is passed to printf.
  • This function is implementation-specific and is based on the operation of the _getkey and putchar functions. These functions, as provided in the standard library, read and write characters using the microcontroller's serial port. Custom functions may use other I/O devices.
Return Value | The printf function returns the number of characters actually written to the output stream.
See Also | gets, puts, scanf, sprintf, sscanf, vprintf, vsprintf
Example
#include <stdio.h>

void tst_printf (void) {
  char a = 1;
  int b  = 12365;
  long c = 0x7FFFFFFF;

  unsigned char x = 'A';
  unsigned int y  = 54321;
  unsigned long z = 0x4A6F6E00;

  float f = 10.0;
  float g = 22.95;

  char buf [] = "Test String";
  char *p = buf;

  printf ("char %d int %d long %ld\n",a,b,c);
  printf ("Uchar %u Uint %u Ulong %lu\n",x,y,z);
  printf ("xchar %x xint %x xlong %lx\n",x,y,z);
  printf ("String %s is at address %p\n",buf,p);
  printf ("%f != %g\n", f, g);
  printf ("%*f != %*g\n", 8, f, 8, g);
}


C166: putchar

putchar

Summary
#include <stdio.h>

char putchar (
  char c);   /* character to output */
Description

The putchar function transmits the character c using the serial port.

Note

  • This routine is implementation-specific and its function may deviate from that described above. Source code is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
Return Value | The putchar routine returns the character output, c.
See Also | _getkey, getchar, ungetchar
Example
#include <stdio.h>

void tst_putchar (void) {
  char i;

  for (i = 0x20; i < 0x7F; i++)
    putchar (i);
}


C166: puts

puts

Summary
#include <stdio.h>

int puts (
  const char *string);   /* string to output */
Description

The puts function writes string followed by a newline character ('\n') to the output stream using the putchar function.

Note

  • This function is implementation-specific and is based on the operation of the putchar function. This function, as provided in the standard library, writes characters using the microcontroller's serial port. Custom functions may use other I/O devices.
Return Value | The puts function returns EOF if an error occurred and a value of 0 if no errors were encountered.
See Also | gets, printf, scanf
Example
#include <stdio.h>

void tst_puts (void) {
  puts ("Line #1");
  puts ("Line #2");
  puts ("Line #3");
}


C166: rand

rand

Summary
#include <stdlib.h>

int rand (void);
Description | The rand function generates a pseudo-random number between 0 and 32767.
Return Value | The rand function returns a pseudo-random number.
See Also | srand
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_rand (void) {
  int i;
  int r;

  for (i = 0; i < 10; i++) {
    printf ("I = %d, RAND = %d\n", i, rand ());
  }
}


C166: realloc

realloc

Summary
#include <stdlib.h>

void far *realloc (
  void far *p,     /* previously allocated block */
  size_t size);    /* new size for block */

or

void huge *realloc (
  void huge *p,    /* previously allocated block */
  size_t size);    /* new size for block */

or

void xhuge *realloc (
  void xhuge *p,   /* previously allocated block */
  size_t size);    /* new size for block */
Description

The realloc function changes the size of a previously allocated memory block. The p argument points to the allocated block and size specifies the new size for the block. The contents of the existing block are copied to the new block. Any additional area in the new block, due to a larger block size, is not initialized.

Note

  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • Pointer arguments and return values are far in Small, Medium, Compact, and Large Memory Models; huge in HCompact and HLarge Memory Models; and xhuge in the XLarge Memory Model. This function is not supported in the Tiny Memory Model.
Return Value | The realloc function returns a pointer to the new block. If there is not enough memory in the memory pool to satisfy the memory request, a null pointer is returned and the original memory block is not affected.
See Also | calloc, free, init_mempool, malloc
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_realloc (void) {
  void far *p;
  void far *new_p;

  p = malloc (100);

  if (p != NULL) {
    new_p = realloc (p, 200);

    if (new_p != NULL)
      p = new_p;
    else
      printf ("Reallocation failed\n");
  }
}


C166: realloc_b

realloc_b

Summary
#include <stdlib.h>

void far *realloc_b (
  void far *p,       /* previously allocated block */
  size_t size);      /* new size for block */

or

void huge *realloc_b (
  void huge *p,      /* previously allocated block */
  size_t size);      /* new size for block */
Description

The realloc_b function changes the size of a previously allocated memory block. The p argument points to the allocated block and size specifies the new size for the block. The contents of the existing block are copied to the new block. Any additional area in the new block, due to a larger block size, is not initialized.

Note

  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • Pointer arguments and return values are far in Small, Medium, Compact, and Large Memory Models and huge in HCompact, HLarge, and XLarge Memory Models. This function is not supported in the Tiny Memory Model.
Return Value | The realloc_b function returns a pointer to the new block. If there is not enough memory in the memory pool to satisfy the memory request, a null pointer is returned and the original memory block is not affected.
See Also | calloc_b, free_b, init_mempool_b, malloc_b
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_realloc_b (void) {
  void far *p;
  void far *new_p;

  p = malloc_b (100);

  if (p != NULL) {
    new_p = realloc_b (p, 200);

    if (new_p != NULL)
      p = new_p;
    else
      printf ("Reallocation failed\n");
  }
}


C166: scanf

scanf

Summary
#include <stdio.h>

int scanf (
  const char *fmtstr    /* format string */
  « , argument »...);   /* additional arguments */
Description

The scanf function reads data from the input stream using the getchar routine. Data input are stored in the locations specified by argument according to the format string fmtstr. Each argument must be a pointer to a variable that corresponds to the type defined in fmtstr. The type controls the interpretation of the input data. The fmtstr may be composed of one or more whitespace characters, non-whitespace characters, and format specifications.

  • Whitespace characters, blank (' '), tab ('\t'), or newline ('\n'), cause scanf to skip whitespace characters in the input stream. A single whitespace character in the format string matches 0 or more whitespace characters in the input stream.
  • Non-whitespace characters, with the exception of the percent sign ('%'), cause scanf to read but not store a matching character from the input stream. The scanf function terminates if the next character in the input stream does not match the specified non-whitespace character.
  • Format specifications begin with a percent sign ('%') and cause scanf to read and convert characters from the input stream to the specified type values. The converted value is stored to an argument from the parameter list. Characters following a percent sign that are not recognized as a format specification are treated as ordinary characters. For example, %% matches a single percent sign in the input stream.

The format string is read from left to right. Characters that are not part of the format specifications must match characters in the input stream. These characters are read from the input stream but are discarded and not stored. If a character in the input stream conflicts with the format string, scanf terminates. Any conflicting characters remain in the input stream.

The first format specification encountered in the format string references the first argument after fmtstr. The scanf function converts input characters and stores the value using the format specification. The second format specification accesses the second argument after fmtstr, and so on. If there are more arguments than format specifications, the extra arguments are ignored. Results are unpredictable if there are not enough arguments for the format specifications.

Values in the input stream are called input fields and are delimited by whitespace characters. When converting input fields, scanf ends a conversion for an argument when a whitespace character or another unrecognized character is encountered.

Format specifications have the following format:

% « * » « width » « {b|h|l} » type

Each field in the format specification can be a single character or a number which specifies a particular format option.

The type field is where a single character specifies whether input characters are interpreted as a character, string, or number. This field can be any one of the characters in the following table.

Character | Argument Type | Input Format
d | int * | Signed decimal number.
i | int * | Signed decimal, hexadecimal, or octal integer.
u | unsigned int * | Unsigned decimal number.
o | unsigned int * | Unsigned octal number.
x | unsigned int * | Unsigned hexadecimal number.
e | float * | Floating-point number.
f | float * | Floating-point number.
g | float * | Floating-point number.
c | char * | A single character.
s | char * | A string of characters terminated by whitespace.

An asterisk ('*') as the first character of a format specification causes the input field to be scanned but not stored. The asterisk suppresses assignment of the format specification.

The width field is a non-negative number that specifies the maximum number of characters read from the input stream. No more than width characters are read and converted for the corresponding argument. However, fewer than width characters may be read if a whitespace or other unrecognized character is encountered first.

The optional characters b, h, and l may immediately precede the type character to respectively specify char, short, or long versions of the integer types d, i, u, o, and x. If l is applied to the floating-point types f, e, and g, a pointer to a double is required as an argument.

Note

  • This function is implementation-specific and is based on the operation of the _getkey and putchar functions. These functions, as provided in the standard library, read and write characters using the microcontroller's serial port. Custom functions may use other I/O devices.
Return Value | The scanf function returns the number of input fields that were successfully converted. An EOF is returned if an error is encountered.
See Also | gets, printf, putchar, puts, sprintf, vprintf, vsprintf
Example
#include <stdio.h>

void tst_scanf (void) {
  char a;
  int b;
  long c;

  unsigned char x;
  unsigned int y;
  unsigned long z;

  float f,g;
  char d, buf [10];
  int argsread;

  printf ("Enter a signed byte, int, and long\n");
  argsread = scanf ("%bd %d %ld", &a, &b, &c);
  printf ("%d arguments read\n", argsread);

  printf ("Enter an unsigned byte, int, and long\n");
  argsread = scanf ("%bu %u %lu", &x, &y, &z);
  printf ("%d arguments read\n", argsread);

  printf ("Enter a character and a string\n");
  argsread = scanf ("%c %9s", &d, buf);
  printf ("%d arguments read\n", argsread);

  printf ("Enter two floating-point numbers\n");
  argsread = scanf ("%f %f", &f, &g);
  printf ("%d arguments read\n", argsread);
}


C166: setjmp

setjmp

Summary
#include <setjmp.h>

int setjmp (
  jmp_buf env);      /* current environment */
Description

The setjmp function saves the current state of the CPU in env. The state may be restored by a subsequent call to the longjmp function. When used together, the setjmp and longjmp functions provide you with a way to execute a non-local goto.

A call to the setjmp function saves the current instruction address as well as other CPU registers. A subsequent call to the longjmp function restores the instruction pointer and registers, and execution resumes at the point just after the setjmp call.

Local variables and function arguments are restored only if declared with the volatile attribute.
Return Value | The setjmp function returns a value of 0 when the current state of the CPU has been copied to env. A non-zero value indicates that the longjmp function was executed to return to the setjmp function call. In such a case, the return value is the value passed to the longjmp function.
See Also | longjmp
Example
#include <setjmp.h>
#include <stdio.h> /* for printf */

jmp_buf env; /* jump environment (must be global) */
bit error_flag;

void trigger (void) {
  .
  .
  .
  /* processing code here */
  .
  .
  .
  if (error_flag != 0) {
    longjmp (env, 1);   /* return 1 to setjmp */
  }
  .
  .
  .
}

void recover (void) {
  /* recovery code here */
}

void tst_longjmp (void) {
  .
  .
  .
  if (setjmp (env) != 0) {     /* setjmp returns a 0 */
    printf ("LONGJMP called\n");
    recover ();
  }

  else {
    printf ("SETJMP called\n");

    error_flag = 1;            /* force an error */

    trigger ();
  }
}


C166: sin

sin

Summary
#include <math.h>

double sin (
  double x);   /* value to calculate sine for */
Description | The sin function calculates the sine of the floating-point value x. The value of x must be in the -65535 to +65535 range or an NaN error value is generated.
Return Value | The sin function returns the sine of x.
See Also | cos, tan
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_sin (void) {
  float x;
  float y;

  for (x = 0; x < (2 * 3.1415); x += 0.1) {
    y = sin (x);
    printf ("SIN(%f) = %f\n", x, y);
  }
}


C166: sinh

sinh

Summary
#include <math.h>

double sinh (
  double x);   /* value to calc hyperbolic sine for */
Description | The sinh function calculates the hyperbolic sine of the floating-point value x. An NaN error value is generated if the value of x is not in the range -65535 to +65535.
Return Value | The sinh function returns the hyperbolic sine of x.
See Also | cosh, tanh
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_sinh (void) {
  float x;
  float y;

  for (x = 0; x < (2 * 3.1415); x += 0.1) {
    y = sinh (x);
    printf ("SINH(%f) = %f\n", x, y);
  }
}


C166: sprintf

sprintf

Summary
#include <stdio.h>

int sprintf (
  char *buffer,          /* storage buffer */
  const char *fmtstr     /* format string */
  « , argument » ...);   /* additional arguments */
Description The sprintf function formats a series of strings and numeric values and stores the resulting string in buffer. This function is similar to the printf routine, but it stores the formatted output in buffer rather than sending it to the output stream.

The fmtstr argument is a pointer to a format string which has the same form and function as the printf function's format string. The list of arguments that are converted and output according to the corresponding format specifications in fmtstr.
Return Value | The sprintf function returns the number of characters actually written to buffer.
See Also | gets, printf, puts, vprintf, vsprintf
Example
#include <stdio.h>

void tst_sprintf (void) {
  char buf [100];
  int n;
  int a,b;
  float pi;

  a = 123;
  b = 456;
  pi = 3.14159;

  n = sprintf (buf, "%f\n", 1.1);
  n += sprintf (buf+n, "%d\n", a);
  n += sprintf (buf+n, "%d %s %g", b, "---", pi);

  puts (buf);
}


C166: sqrt

sqrt

Summary
#include <math.h>

double sqrt (
  double x);  /* value to calculate square root of */
Description | The sqrt function calculates the square root of x.
Return Value | The sqrt function returns the positive square root of x.
See Also | pow
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_sqrt (void) {
  float x;
  float y;

  x = 25.0;
  y = sqrt (x); /* y = 5 */

  printf ("SQRT(%f) = %f\n", x, y);
}


C166: srand

srand

Summary
#include <stdlib.h>

void srand (
  unsigned int seed);   /* random number generator seed */
Description | The srand function sets the starting value, seed, used by the pseudo-random number generator in the rand function. The random number generator produces the same sequence of pseudo-random numbers for any given value of seed.
Return Value | None.
See Also | rand
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_srand (void) {
  int i;
  int r;

  srand (56);

  for (i = 0; i < 10; i++) {
    printf ("I = %d, RAND = %d\n", i, rand ());
  }
}


C166: sscanf

sscanf

Summary
#include <stdio.h>

int sscanf (
  char *buffer,         /* scanf input buffer */
  const char *fmtstr    /* format string */
  « , argument »...);   /* additional arguments */
Description

The sscanf function reads data from the string buffer. Data input are stored in the locations specified by argument according to the format string fmtstr. Each argument must be a pointer to a variable that corresponds to the type defined in fmtstr. The type specified in fmtstr controls the interpretation of the input data. The fmtstr may be composed of one or more whitespace characters, non-whitespace characters, and format specifications, as defined in the scanf function description.
Return Value | The sscanf function returns the number of input fields that were successfully converted. An EOF is returned if an error is encountered.
See Also | gets, printf, puts, scanf, sprintf, vprintf, vsprintf
Example
#include <stdio.h>

void tst_sscanf (void) {
  char a;
  int b;
  long c;

  unsigned char x;
  unsigned int y;
  unsigned long z;

  float f,g;

  char d, buf [10];

  int argsread;

  printf ("Reading a signed byte, int,and long\n");
  argsread = sscanf ("1 -234 567890", "%bd %d %ld", &a, &b, &c);
  printf ("%d arguments read\n", argsread);

  printf ("Reading an unsigned byte, int, and long\n");
  argsread = sscanf ("2 44 98765432", "%bu %u %lu", &x, &y, &z);
  printf ("%d arguments read\n", argsread);

  printf ("Reading a character and a string\n");
  argsread = sscanf ("a abcdefg", "%c %9s", &d, buf);
  printf ("%d arguments read\n", argsread);

  printf ("Reading two floating-point numbers\n");
  argsread = sscanf ("12.5 25.0", "%f %f", &f, &g);
  printf ("%d arguments read\n", argsread);
}


C166: strcat

strcat

Summary
#include <string.h>

signed char *strcat (
  signed char *dst,          /* destination string */
  const signed char *src);   /* source string */
Description | The strcat function concatenates or appends src to dst and terminates dst with a null character.
Return Value | The strcat function returns dst.
See Also | strcpy, strlen, strncat, strncpy
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strcat (void) {
  char buf [21];
  char s [] = "Test String";

  strcpy (buf, s);
  strcat (buf, " #2");

  printf ("new string is %s\n", buf);
}


C166: strchr

strchr

Summary
#include <string.h>

signed char *strchr (
  const signed char *string,   /* string to search */
  signed char c);              /* character to find */
Description | The strchr function searches string for the first occurrence of c. The null character terminating string is included in the search.
Return Value | The strchr function returns a pointer to the first occurrence of character c in string or a null pointer if no matching character is found.
See Also | strcspn, strpbrk, strpos, strrchr, strrpbrk, strrpos, strspn, strstr
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strchr (void) {
  char *s;
  char buf [] = "This is a test";

  s = strchr (buf, 't');

  if (s != NULL)
    printf ("found a 't' at %s\n", s);
}


C166: strcmp

strcmp

Summary
#include <string.h>

int strcmp (
  const signed char *string1,    /* first string */
  const signed char *string2);   /* second string */
Description | The strcmp function compares the contents of string1 and string2 and returns a value indicating their relationship.
Return Value

The strcmp function returns the following values to indicate the relationship of string1 to string2:

Value | Description
< 0 | string1 is less than string2
= 0 | string1 is equal to string2
> 0 | string1 is greater than string2
See Also | fstrcmp, hstrcmp, memcmp, strncmp, xstrcmp
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strcmp (void) {
  char buf1 [] = "Bill Smith";
  char buf2 [] = "Bill Smithy";
  int i;

  i = strcmp (buf1, buf2);

  if (i < 0)
    printf ("buf1 < buf2\n");
  else if (i > 0)
    printf ("buf1 > buf2\n");
  else
    printf ("buf1 == buf2\n");
}


C166: strcpy

strcpy

Summary
#include <string.h>

signed char *strcpy (
  signed char *dst,          /* destination string */
  const signed char *src);   /* source string */
Description | The strcpy function copies src to dst and appends a null character to the end of dst.
Return Value | The strcpy function returns dst.
See Also | fstrcpy, hstrcpy, strcat, strlen, strncat, strncpy, xstrcpy
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strcpy (void) {
  char buf [21];
  char s [] = "Test String";

  strcpy (buf, s);
  strcat (buf, " #2");

  printf ("new string is %s\n", buf);
}


C166: strcspn

strcspn

Summary
#include <string.h>

int strcspn (
  const signed char *src,    /* source string */
  const signed char *set);   /* characters to find */
Description | The strcspn function searches the src string for any of the characters in the set string.
Return Value | The strcspn function returns the index of the first character located in src that matches a character in set. If the first character in src matches a character in set, a value of 0 is returned. If there are no matching characters in src, the length of the src is returned.
See Also | strchr, strpbrk, strpos, strrchr, strrpbrk, strrpos, strspn, strstr
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strcspn (void) {
  char buf [] = "13254.7980";
  int i;

  i = strcspn (buf, ".,");

  if (buf [i] != '\0')
    printf ("%c was found in %s\n",
            (char) buf [i],
            buf);
}


C166: strlen

strlen

Summary
#include <string.h>

size_t strlen (
  const signed char *src);   /* source string */
Description | The strlen function calculates the length, in bytes, of src. This calculation does not include the null terminating character.
Return Value | The strlen function returns the length of src.
See Also | strcat, strncat, strncpy
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strlen (void) {
  char buf [] = "Find the length of this string";
  int len;

  len = strlen (buf);
  printf ("string length is %d\n", len);
}


C166: strncat

strncat

Summary
#include <string.h>

signed char *strncat (
  signed char *dst,           /* destination string */
  const signed char *src,     /* source string */
  unsigned int len);   /* max. chars to concatenate */
Description | The strncat function appends at most len characters from src to dst and terminates dst with a null character. If src has fewer than len characters, src is copied up to and including the null terminating character.
Return Value | The strncat function returns dst.
See Also | strcat, strcpy, strlen, strncpy
Example
#include <string.h>

void tst_strncat (void) {
  char buf [21];

  strcpy (buf, "test #");
  strncat (buf, "three", sizeof (buf) - strlen (buf));
}


C166: strncmp

strncmp

Summary
#include <string.h>

int strncmp (
  const signed char *string1,   /* first string */
  const signed char *string2,   /* second string */
  unsigned int len);     /* max characters to compare */
Description | The strncmp function compares the first len bytes of string1 and string2 and returns a value indicating their relationship.
Return Value

The strncmp function returns the following values to indicate the relationship of the first len bytes of string1 to string2:

Value | Description
< 0 | string1 is less than string2
= 0 | string1 is equal to string2
> 0 | string1 is greater than string2
See Also | memcmp, strcmp
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strncmp (void) {
  char str1 [] = "Wrodanahan T.J.";
  char str2 [] = "Wrodanaugh J.W.";
  char i;

  i = strncmp (str1, str2, 15);

  if (i < 0)       printf ("str1 < str2\n");
  else if (i > 0)  printf ("str1 > str2\n");
  else             printf ("str1 == str2\n");
}


C166: strncpy

strncpy

Summary
#include <string.h>

signed char *strncpy (
  signed char *dst,           /* destination string */
  const signed char *src,     /* source string */
  unsigned int len);   /* max characters to copy */
Description | The strncpy function copies at most len characters from src to dst. Characters are copied until a null character ('\0') is copied or until len characters have been copied. If the length of src is less than len the remaining bytes in dst are padded with null characters ('\0').
Return Value | The strncpy function returns dst.
See Also | strcat, strcpy, strlen, strncat
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strncpy (char *s) {
  char buf [21];

  strncpy (buf, s, sizeof (buf));
  buf [sizeof (buf) -1] = '\0';
}


C166: strpbrk

strpbrk

Summary
#include <string.h>

signed char *strpbrk (
  const signed char *string,   /* string to search */
  const signed char *set);     /* characters to find */
Description | The strpbrk function searches string for the first occurrence of any character from set. The null terminator is not included in the search.
Return Value | The strpbrk function returns a pointer to the matching character in string. If string contains no characters from set, a null pointer is returned.
See Also | strchr, strcspn, strpos, strrchr, strrpbrk, strrpos, strspn, strstr
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strpbrk (void)
{
char vowels [] ="AEIOUaeiou";
char text [] = "Seven years ago...";
char *p;

p = strpbrk (text, vowels);

if (p == NULL)
  printf ("No vowels found in %s\n", text);
else
  printf ("Found a vowel at %s\n", p);
}


C166: strpos

strpos

Summary
#include <string.h>

int strpos (
  const signed char *string,   /* string to search */
  signed char c);              /* character to find */
Description | The strpos function searches string for the first occurrence of c. The null character terminating string is included in the search.
Return Value | The strpos function returns the index of the character matching c in string or a value of -1 if no matching character was found. The index of the first character in string is 0.
See Also | strchr, strcspn, strpbrk, strrchr, strrpbrk, strrpos, strspn, strstr
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strpos (void) {
  char text [] = "Search this string for blanks";
  int i;

  i = strpos (text, ' ');

  if (i == -1)
    printf ("No spaces found in %s\n", text);
  else
    printf ("Found a space at offset %d\n", i);
}


C166: strrchr

strrchr

Summary
#include <string.h>

signed char *strrchr (
  const signed char *string,   /* string to search */
  signed char c);              /* character to find */
Description | The strrchr function searches string for the last occurrence of c. The null character terminating string is included in the search.
Return Value | The strrchr function returns a pointer to the last character c found in string or a null pointer if no matching character was found.
See Also | strchr, strcspn, strpbrk, strpos, strrpbrk, strrpos, strspn, strstr
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strrchr (void) {
  char *s;
  char buf [] = "This is a test";

  s = strrchr (buf, 't');

  if (s != NULL)
    printf ("found the last 't' at %s\n", s);
}


C166: strrpbrk

strrpbrk

Summary
#include <string.h>

signed char *strrpbrk (
  const signed char *string,   /* string to search */
  const signed char *set);     /* characters to find */
Description | The strrpbrk function searches string for the last occurrence of any character from set. The null terminator is not included in the search.
Return Value | The strrpbrk function returns a pointer to the last matching character in string. If string contains no characters from set, a null pointer is returned.
See Also | strchr, strcspn, strpbrk, strpos, strrchr, strrpos, strspn, strstr
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strrpbrk (void) {
  char vowels [] ="AEIOUaeiou";
  char text [] = "American National Standards Institute";
  char *p;

  p = strpbrk (text, vowels);

  if (p == NULL)
    printf ("No vowels found in %s\n", text);
  else
    printf ("Last vowel is at %s\n", p);
}


C166: strrpos

strrpos

Summary
#include <string.h>

int strrpos (
  const signed char *string,   /* string to search */
  signed char c);              /* character to find */
Description | The strrpos function searches string for the last occurrence of c. The null character terminating string is included in the search.
Return Value | The strrpos function returns the index of the last character matching c in string or a value of -1 if no matching character was found. The index of the first character in string is 0.
See Also | strchr, strcspn, strpbrk, strpos, strrchr, strrpbrk, strspn, strstr
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strrpos (const char *s) {
  int i;

  i = strrpos (s, ' ');

  if (i == -1)
    printf ("No spaces found in %s\n", s);
  else
    printf ("Last space in %s is at offset %d\n", s, i);
}


C166: strspn

strspn

Summary
#include <string.h>

int strspn (
  const signed char *string,   /* string to search */
  const signed char *set);     /* characters to allow */
Description | The strspn function searches string for characters not found in the set string.
Return Value | The strspn function returns the index of the first character located in string that does not match a character in set. If the first character in string does not match a character in set, a value of 0 is returned. If all characters in string are found in set, the length of string is returned.
See Also | strchr, strcspn, strpbrk, strpos, strrchr, strrpbrk, strrpos, strstr
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strspn (const char *digit_str) {
  char octd [] = "01234567";
  int i;

  i = strspn (digit_str, octd);

  if (digit_str [i] != '\0')
    printf ("%c is not an octal digit\n", digit_str [i]);
}


C166: strstr

strstr

Summary
#include <string.h>

signed char *strstr (
  const signed char *src,    /* string to search */
  const signed char *sub);   /* sub string to search */
Description | The strstr function locates the first occurrence of the string sub in the string src and returns a pointer to the beginning of the first occurrence.
Return Value | The strstr function returns a pointer within src that points to a string identical to sub. If no such sub string exists in src a null pointer is returned.
See Also | strchr, strcspn, strpbrk, strpos, strrchr, strrpbrk, strrpos, strspn
Example
#include <string.h>
#include <stdio.h> /* for printf */

char s1 [] = "My House is small";
char s2 [] = "My Car is green";

void tst_strstr (void) {
  char *s;

  s = strstr (s1, "House");
  printf ("substr (s1, \"House\") returns %s\n", s);
}


C166: strtod

strtod

Summary
#include <stdlib.h>

double strtod (
  const char *string,   /* string to convert */
  char **ptr);          /* ptr to subsequent characters */
Description

The strtod function converts string into a floating-point value. The input string is a sequence of characters that can be interpreted as a floating-point number. Whitespace characters at the beginning of string are skipped.

The value of *ptr is set to point to the first character in string immediately following the converted part of string. If ptr is NULL, no value is assigned to *ptr. If no conversion is possible, *ptr is set to the value of string and the value 0 is returned by the strtod function.

The strtod function requires string to have the following format:

« {+|-} » digits « .digits » « {e|E} « {+|-} » digits »

Where

digits May be one or more decimal digits (0-9).
Return Value | The strtod function returns the floating-point value that is produced by interpreting the characters in the string as a floating-point number.
See Also | atof, atoi, atol, strtol, strtoul
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_strtod (void) {
  float f;
  char s [] = "1.23 other";
  char *p;

  f = strtod (s, &p);
  printf ("strtod(%s) = %f\n", s, f);

/* p points to " other" */
}


C166: strtol

strtol

Summary
#include <stdlib.h>

long strtol (
  const char *string,   /* string to convert */
  char **ptr,           /* ptr to subsequent characters */
  int base);            /* number base for conversion */
Description

The strtol function converts string into a signed long value. The input string is a sequence of characters that can be interpreted as an integer number. Whitespace characters at the beginning of string are skipped. An optional sign may precede the number.

The value of *ptr is set to point to the first character in string immediately following the converted part of string. If ptr is NULL, no value is assigned to *ptr. If no conversion is possible, *ptr is set to the value of string and the value 0 is returned by the strtol function.

If the base is zero, the number should have the format of a decimal-constant, octal-constant or hexadecimal-constant. The radix of the number is deduced from its format. If the value of base is in the range 2-36, the number in string must consist of a non-zero sequence of letters and digits representing an integer in the specified base. The letters a-z (or A-Z) represent the values 10-36. Only those letters representing values less than the base are permitted. If the base is 16, the number may begin with 0x or 0X, which is ignored.

The strtol function requires string to have the following format:

« whitespace » « {+|-} » digits

Where

whitespace | May be any whitespace characters.
digits | May be one or more decimal digits (0-9).
Return Value | The strtol function returns the integer value that is produced by interpreting the characters in string as a number. The value LONG_MIN or LONG_MAX is returned to indicate an overflow or underflow.
See Also | atof, atoi, atol, strtod, strtoul
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_strtol (void) {
  long l;
  char s [] = "-123456789 stuff";
  char *p;

  l = strtol (s, &p, 10);
  printf ("strtol(%s) = %ld\n", s, l);

/* p points to " stuff" */
}


C166: strtoul

strtoul

Summary
#include <stdlib.h>

unsigned long strtoul (
  const char *string,   /* string to convert */
  char **ptr,           /* ptr to subsequent characters */
  intbase);             /* number base for conversion */
Description

The strtoul function converts string into an unsigned long value. The input string is a sequence of characters that can be interpreted as an integer number. Whitespace characters at the beginning of string are skipped. An optional sign may precede the number.

The value of *ptr is set to point to the first character in string immediately following the converted part of string. If ptr is NULL, no value is assigned to *ptr. If no conversion is possible, *ptr is set to the value of string and the value 0 is returned by the strtol function.

If the base is zero, the number should have the format of a decimal-constant, octal-constant or hexadecimal-constant. The radix of the number is deduced from its format. If the value of base is in the range 2-36, the number in string must consist of a non-zero sequence of letters and digits representing an integer in the specified base. The letters a-z (or A-Z) represent the values 10-36. Only those letters representing values less than the base are permitted. If the base is 16, the number may begin with 0x or 0X, which is ignored.

The strtol function requires string to have the following format:

« whitespace » « {+|-} » digits

Where

whitespace | May be any whitespace characters.
digits | May be one or more decimal digits (0-9).
Return Value | The strtoul function returns the integer value that is produced by interpreting the characters in string as a number. The value ULONG_MAX is returned in case of overflow.
See Also | atof, atoi, atol, strtod, strtol
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_strtoul (void) {
  unsigned long ul;
  char s [] = "12345AB next";
  char *p;

  ul = strtoul (s, &p, 16);
  printf ("strtoul(%s) = %lx\n", s, ul);

/* p points to " next" */
}


C166: tan

tan

Summary
#include <math.h>

double tan (
  double x);   /* value to calculate tangent of */
Description | The tan function calculates the tangent of the floating-point value x. This function returns an NaN error value if x is not in the range -65535 to +65535 range.
Return Value | The tan function returns the tangent of x.
See Also | cos, sin
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_tan (void) {
  float x;
  float y;
  float pi;

  pi = 3.14159;

  for (x = -(pi/4); x < (pi/4); x += 0.1) {
    y = tan (x);
    printf ("TAN(%f) = %f\n", x, y);
  }
}


C166: tanh

tanh

Summary
#include <math.h>

double tanh (
  double x);   /* value to calc hyperbolic tangent for */
Description | The tanh function calculates the hyperbolic tangent for the floating-point value x.
Return Value | The tanh function returns the hyperbolic tangent of x.
See Also | cosh, sinh
Example
#include <math.h>
#include <stdio.h> /* for printf */

void tst_tanh (void) {
  float x;
  float y;
  float pi;

  pi = 3.14159;

  for (x = -(pi/4); x < (pi/4); x += 0.1) {
    y = tanh (x);
    printf ("TANH(%f) = %f\n", x, y);
  }
}


C166: toascii

toascii

Summary
#include <ctype.h>

int toascii (
  int c);      /* character to convert */
Description | The toascii macro converts c to a 7-bit ASCII character. This macro clears all but the lower 7 bits of c.
Return Value | The toascii macro returns the 7-bit ASCII character for c.
See Also | toint
Example
#include <ctype.h>
#include <stdio.h> /* for printf */

void tst_toascii ( char c) {
  char k;

  k = toascii (c);
  printf ("%c is an ASCII character\n", k);
}


C166: toint

toint

Summary
#include <ctype.h>

int toint (
  int c);   /* digit to convert */
Description | The toint function interprets c as a hexadecimal value. ASCII characters '0'-'9' generate values 0-9. ASCII characters 'A'-'F' and 'a'-'f' generate values 10-15. If the value of c is not a hexadecimal digit, the function returns –1.
Return Value | The toint function returns the value of the ASCII hexadecimal character c.
See Also | toascii
Example
#include <ctype.h>
#include <stdio.h> /* for getchar */

void tst_toint (void) {
  unsigned long l;
  char k;

  for (l = 0; isdigit (k = getchar ()); l *= 10) {
    l += toint (k);
  }
}


C166: tolower

tolower

Summary
#include <ctype.h>

int tolower (
  int c);   /* character to convert */
Description | The tolower function converts c to a lowercase character. If c is not an alphabetic letter, the tolower function has no effect.
Return Value | The tolower function returns the lowercase equivalent of c.
See Also | _tolower, _toupper, toupper
Example
#include <ctype.h>
#include <stdio.h> /* for printf */

void tst_tolower (void) {
  unsigned char i;

  for (i = 0x20; i < 0x7F; i++) {
    printf ("tolower(%c) = %c\n", i, tolower(i));
  }
}


C166: toupper

toupper

Summary
#include <ctype.h>

int toupper (
  int c);   /* character to convert */
Description | The toupper function converts c to an uppercase character. If c is not an alphabetic letter, the toupper function has no effect.
Return Value | The toupper function returns the uppercase equivalent of c.
See Also | _tolower, _toupper, tolower
Example
#include <ctype.h>
#include <stdio.h> /* for printf */

void tst_toupper (void) {
  unsigned char i;

  for (i = 0x20; i < 0x7F; i++) {
    printf ("toupper(%c) = %c\n", i, toupper(i));
  }
}


C166: ungetchar

ungetchar

Summary
#include <stdio.h>

char ungetchar (
  char c);   /* character to unget */
Description | The ungetchar function stores the character c back into the input stream. The next call to getchar or any other stream input function returns c. Only one character may be passed to unget between calls to getchar.
Return Value | The ungetchar function returns the character c if successful. If ungetchar is called more than once between function calls that read from the input stream, EOF is returned indicating an error condition.
See Also | _getkey, getchar, putchar
Example
#include <stdio.h>
#include <ctype.h>  /* for isdigit */

void tst_ungetchar (void) {
  char k;

  while (isdigit (k = getchar ())) {
    /* stay in the loop as long as k is a digit */
  }

  ungetchar (k);
}


C166: va_arg

va_arg

Summary
#include <stdarg.h>

type va_arg (
  argptr,      /* optional argument list */
  type);       /* type of next argument */
Description

The va_arg macro is used to extract subsequent arguments from a variable-length argument list referenced by argptr. The type argument specifies the data type of the argument to extract. This macro may be called only once for each argument and must be called in the order of the parameters in the argument list.

The first call to va_arg returns the first argument after the prevparm argument specified in the va_start macro. Subsequent calls to va_arg return the remaining arguments in succession.
Return Value | The va_arg macro returns the value for the specified argument type.
See Also | va_end, va_start
Example
#include <stdarg.h>
#include <stdio.h> /* for printf */

int varfunc (char *buf, int id, ...) {
  va_list tag;

  va_start (tag, id);

  if (id == 0) {
    int arg1;
    char *arg2;
    long arg3;

    arg1 = va_arg (tag, int);
    arg2 = va_arg (tag, char *);
    arg3 = va_arg (tag, long);
  }

  else {
    char *arg1;
    char *arg2;
    long arg3;

    arg1 = va_arg (tag, char *);
    arg2 = va_arg (tag, char *);
    arg3 = va_arg (tag, long);
  }

  va_end (tag);
}

void caller (void) {
  char tmp_buffer [10];

  varfunc (tmp_buffer, 0, 27, "Test Code", 100L);
  varfunc (tmp_buffer, 1, "Test", "Code", 348L);
}


C166: va_end

va_end

Summary
#include <stdarg.h>

void va_end (
  argptr);      /* optional argument list */
Description | The va_end macro is used to terminate use of the variable-length argument list pointer argptr that was initialized using the va_start macro.
Return Value | None.
See Also | va_arg, va_start
Example
#include <stdarg.h>
#include <stdio.h> /* for printf */

int varfunc (char *buf, int id, ...) {
  va_list tag;

  va_start (tag, id);

  if (id == 0) {
    int arg1;
    char *arg2;
    long arg3;

    arg1 = va_arg (tag, int);
    arg2 = va_arg (tag, char *);
    arg3 = va_arg (tag, long);
  }

  else {
    char *arg1;
    char *arg2;
    long arg3;

    arg1 = va_arg (tag, char *);
    arg2 = va_arg (tag, char *);
    arg3 = va_arg (tag, long);
  }

  va_end (tag);
}

void caller (void) {
  char tmp_buffer [10];

  varfunc (tmp_buffer, 0, 27, "Test Code", 100L);
  varfunc (tmp_buffer, 1, "Test", "Code", 348L);
}


C166: va_start

va_start

Summary
#include <stdarg.h>

void va_start (
  argptr,         /* optional argument list */
  prevparm);      /* arg preceding optional args */
Description | The va_start macro, when used in a function with a variable-length argument list, initializes argptr for subsequent use by the va_arg and va_end macros. The prevparm argument must be the name of the function argument immediately preceding the optional arguments specified by ellipses ('...'). This routine must be called to initialize a variable-length argument list pointer before any access using the va_arg macro is made.
Return Value | None.
See Also | va_arg, va_end
Example
#include <stdarg.h>
#include <stdio.h> /* for printf */

int varfunc (char *buf, int id, ...) {
  va_list tag;

  va_start (tag, id);

  if (id == 0) {
    int arg1;
    char *arg2;
    long arg3;

    arg1 = va_arg (tag, int);
    arg2 = va_arg (tag, char *);
    arg3 = va_arg (tag, long);
  }

  else {
    char *arg1;
    char *arg2;
    long arg3;

    arg1 = va_arg (tag, char *);
    arg2 = va_arg (tag, char *);
    arg3 = va_arg (tag, long);
  }

  va_end (tag);
}

void caller (void) {
  char tmp_buffer [10];

  varfunc (tmp_buffer, 0, 27, "Test Code", 100L);
  varfunc (tmp_buffer, 1, "Test", "Code", 348L);
}


C166: vprintf

vprintf

Summary
#include <stdio.h>

void vprintf (
  const char *fmtstr,   /* pointer to format string */
  char *argptr);        /* pointer to argument list */
Description

The vprintf function formats a series of strings and numeric values and builds a string to write to the output stream using the putchar function. This function is similar to the printf routine, but it accepts a pointer to a list of arguments instead of an argument list.

The fmtstr argument is a pointer to a format string which has the same form and function as the printf function's format string. The argptr argument points to a list of arguments that are converted and output according to the corresponding format specifications in fmtstr.

Note

  • This function is implementation-specific and is based on the operation of the putchar function. This function, as provided in the standard library, writes characters using the microcontroller's serial port. Custom functions may use other I/O devices.
Return Value | The vprintf function returns the number of characters actually written to the output stream.
See Also | gets, printf, puts, scanf, sprintf, sscanf, vsprintf
Example
#include <stdio.h>
#include <stdarg.h>

void error (char *fmt, ...) {
  va_list arg_ptr;
  va_start (arg_ptr, fmt); /* format string */
  vprintf (fmt, arg_ptr);
  va_end (arg_ptr);
}

void tst_vprintf (void) {
  int i;

  i = 1000;

  /* call error with one parameter */
  error ("Error: '%d' number too large\n", i);

  /* call error with just a format string */
  error ("Syntax Error\n");
}


C166: vsprintf

vsprintf

Summary
#include <stdio.h>

void vsprintf (
  char *buffer,         /* pointer to storage buffer */
  const char *fmtstr,   /* pointer to format string */
  char *argptr);        /* pointer to argument list */
Description

The vsprintf function formats a series of strings and numeric values and stores the resulting string in buffer. This function is similar to the sprintf routine, but it accepts a pointer to a list of arguments instead of an argument list.

The fmtstr argument is a pointer to a format string which has the same form and function as the printf function's format string. The argptr argument points to a list of arguments that are converted and output according to the corresponding format specifications in fmtstr.
Return Value | The vsprintf function returns the number of characters actually written to buffer.
See Also | gets, printf, puts, sscanf, vprintf
Example
#include <stdio.h>
#include <stdarg.h>

char etxt[30]; /* text buffer */

void error (char *fmt, ...) {
  va_list arg_ptr;
  va_start (arg_ptr, fmt); /* format string */
  vsprintf (etxt, fmt, arg_ptr);
  va_end (arg_ptr);
}

void tst_vsprintf (void) {
  int i;

  i = 1000;

  /* call error with one parameter */
  error ("Error: '%d' number too large\n", i);

  /* call error with just a format string */
  error ("Syntax Error\n");
}


C166: xcalloc

xcalloc

Summary
#include <stdlib.h>

void xhuge *calloc (
  unsigned long num,           /* number of items */
  unsigned long len);          /* length of each item */
Description

The xcalloc function allocates memory for an array of numelements. Each element in the array occupies len bytes and is initialized to 0. The total number of bytes of memory allocated is num * len.

Note

  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The xcalloc function returns a pointer to the allocated memory or a null pointer if the memory allocation request cannot be satisfied.
See Also | xfree, xinit_mempool, xmalloc, xrealloc
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_calloc (void) {
  int xhuge *p; /* ptr to array of 100 ints */

  p = xcalloc (100, sizeof (int));

  if (p == NULL)
    printf ("Error allocating array\n");
  else
    printf ("Array address is %p\n", (void *) p);
}


C166: xfree

xfree

Summary
#include <stdlib.h>

void xfree (
  void xhuge *p);      /* block to free */
Description

The xfree function returns a memory block to the memory pool. The p argument points to a memory block that was previously allocated with the xcalloc, xmalloc, or xrealloc functions. Once it has been returned to the memory pool by the free function, the block is available for subsequent allocation.

If p is a null pointer, it is ignored.

Note

  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | None.
See Also | xcalloc, xinit_mempool, xmalloc, xrealloc
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_free (void) {
  void xhuge *mbuf;

  printf ("Allocating memory\n");
  mbuf = xmalloc (1000);

  if (mbuf == NULL) {
    printf ("Unable to allocate memory\n");
  }

  else {
    xfree (mbuf);
    printf ("Memory free\n");
  }
}


C166: xinit_mempool

xinit_mempool

Summary
#include <stdlib.h>

void xinit_mempool (
  void xhuge *p,           /* start of memory pool */
  unsigned long size);     /* length of memory pool */
Description

The xinit_mempool function initializes the memory management routines and provides the starting address and size of the memory pool. The p argument points to a memory area in xdata which is managed using the xcalloc, xfree, xmalloc, and xrealloc library functions. The size argument specifies the number of bytes to use for the memory pool.

Note

  • This function must be used to setup the memory pool before any other memory management functions (xcalloc, xfree, xmalloc, xrealloc) can be called. Call the xinit_mempool function only once at the beginning of your program.
  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | None.
See Also | xcalloc, xfree, xmalloc, xrealloc
Example
#include <stdlib.h>

void tst_init_mempool (void) {
  xdata void *p;
  int i;

/* initialize memory pool at xdata 0x2000 for 4096 bytes */
  xinit_mempool (&XBYTE [0x2000], 0x1000);

  p = xmalloc (100);

  for (i = 0; i < 100; i++)
    ((char *) p)[i] = i;

  xfree (p);
}


C166: xmalloc

xmalloc

Summary
#include <stdlib.h>

void xhuge *xmalloc (
  unsigned long size);      /* block size to allocate */
Description

The xmalloc function allocates a memory block from the memory pool of size bytes in length.

Note

  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The xmalloc function returns a pointer to the allocated block or a null pointer if there is not enough memory to satisfy the allocation request.
See Also | xcalloc, xfree, xinit_mempool, xrealloc
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_malloc (void) {
  void xhuge *p;

  p = xmalloc (1000); /* allocate 1000 bytes */

  if (p == NULL)
    printf ("Not enough memory space\n");
  else
    printf ("Memory allocated\n");
}


C166: xmemccpy

xmemccpy

Summary
#include <string.h>

void xhuge *xmemccpy (
  void xhuge *dest,        /* destination buffer */
  const void xhuge *src,   /* source buffer */
  char c,                  /* character which ends copy */
  unsigned long len);      /* maximum bytes to copy */
Description

The xmemccpy function copies 0 or more characters from src to dest. Characters are copied until the character c is copied or until len bytes have been copied, whichever comes first.

Note

  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The xmemccpy function returns a pointer to the byte in dest that follows the last character copied or a null pointer if the last character copied was c.
See Also | xmemchr, xmemcmp, xmemcpy, xmemmove, xmemset
Example
#include <string.h<
#include <stdio.h> /* for printf */

void tst_memccpy (char xhuge *src1) {
  static char dst1 [100];
  void *c;

  c = xmemccpy (dst1, src1, 'g', sizeof (dst1));

  if (c == NULL)
    printf ("'g' was not found in the src buffer\n");
  else
    printf ("characters copied up to 'g'\n");
}


C166: xmemchr

xmemchr

Summary
#include <string.h>

void xhuge *xmemchr (
  void xhuge *buf,     /* buffer to search */
  char c,              /* byte to find */
  unsigned long len);  /* maximum buffer length */
Description

The xmemchr function scans buf for the character c in the first len bytes of the buffer.

Note

  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The xmemchr function returns a pointer to the character c in buf or a null pointer if the character was not found.
See Also | xmemccpy, xmemcmp, xmemcpy, xmemmove, xmemset
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memchr (
  char xhuge *src1,
  unsigned long len)
{
void *c;

  c = xmemchr (src1, 'g', len);

  if (c == NULL)
    printf ("'g' was not found in the buffer\n");
  else
    printf ("found 'g' in the buffer\n");
}


C166: xmemcmp

xmemcmp

Summary
#include <string.h>

int xmemcmp (
  const void xhuge *buf1,   /* first buffer */
  const void xhuge *buf2,   /* second buffer */
  unsigned long len);       /* bytes to compare */
Description

The xmemcmp function compares the first len bytes from buf1 and buf2 and returns a value indicating their relationship as follows:

Value | Description
< 0 | buf1 less than buf2
= 0 | buf1 equal to buf2
> 0 | buf1 greater than buf2

Note

  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The xmemcmp function returns a positive, negative, or zero value indicating the relationship of buf1 and buf2.
See Also | xmemccpy, xmemchr, xmemcpy, xmemmove, xmemset
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memcmp (
  char xhuge *buf1,
  char xhuge *buf2,
  unsigned long len)
{
char i;

  i = xmemcmp (buf1, buf2, len);

  if (i < 0)
    printf ("buf1 < buf2\n");
  else if (i > 0)
    printf ("buf1 > buf2\n");
  else
    printf ("buf1 == buf2\n");
}


C166: xmemcpy

xmemcpy

Summary
#include <string.h>

void xhuge *xmemcpy (
  void xhuge *dest,        /* destination buffer */
  const void xhuge *src,   /* source buffer */
  unsigned long len);      /* bytes to copy */
Description

The xmemcpy function copies len bytes from src to dest. If these memory buffers overlap, the xmemcpy function cannot guarantee that bytes in src are copied to dest before being overwritten. If these buffers do overlap, use the xmemmove function.

Note

  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The xmemcpy function returns dest.
See Also | fmemcpy, memcpy, xmemccpy, xmemchr, xmemcmp, xmemmove, xmemset
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memcpy (char xhuge *src1)
{
char dst1 [101];
char *p;

  p = xmemcpy (dst1, src1, sizeof (dst1));
  printf ("dst = \"%s\"\n", p);
}


C166: xmemmove

xmemmove

Summary
#include <string.h>

void xhuge *xmemmove (
  void xhuge *dest,        /* destination buffer */
  const void xhuge *src,   /* source buffer */
  unsigned long len);      /* bytes to move */
Description

The xmemmove function copies len bytes from src to dest. If these memory buffers overlap, the xmemmove function ensures that bytes in src are copied to dest before being overwritten.

Note

  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The xmemmove function returns dest.
See Also | xmemccpy, xmemchr, xmemcmp, xmemcpy, xmemset
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memmove (void) {
  static char buf [] = "This is line 1 "
                       "This is line 2 "
                       "This is line 3 ";

  printf ("buf before = %s\n", buf);
  xmemmove (&buf [0], &buf [16], 32);
  printf ("buf after = %s\n", buf);
}


C166: xmemset

xmemset

Summary
#include <string.h>

void xhuge *xmemset (
  void xhuge *buf,      /* buffer to initialize */
  char c,               /* byte value to set */
  unsigned long len);   /* buffer length */
Description

The xmemset function sets the first len bytes in buf to c.

Note

  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The xmemset function returns dest.
See Also | fmemset, memset, xmemccpy, xmemchr, xmemcmp, xmemcpy, xmemmove
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_memset (void) {
  char buf [10];

  xmemset (buf, '\0', sizeof (buf));
  /* fill buffer with null characters */
}


C166: xrealloc

xrealloc

Summary
#include <stdlib.h>

void xhuge *realloc (
  void xhuge *p,           /* previously allocated block */
  unsigned long size);     /* new size for block */
Description

The xrealloc function changes the size of a previously allocated memory block. The p argument points to the allocated block and size specifies the new size for the block. The contents of the existing block are copied to the new block. Any additional area in the new block, due to a larger block size, is not initialized.

Note

  • Source code for this routine is provide in the LIB folder. You may modify the source to customize this function for your particular hardware environment.
  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The xrealloc function returns a pointer to the new block. If there is not enough memory in the memory pool to satisfy the memory request, a null pointer is returned and the original memory block is not affected.
See Also | xcalloc, xfree, xinit_mempool, xmalloc
Example
#include <stdlib.h>
#include <stdio.h> /* for printf */

void tst_realloc (void) {
  void xhuge *p;
  void xhuge *new_p;

  p = xmalloc (100);

  if (p != NULL) {
    new_p = xrealloc (p, 200);

    if (new_p != NULL)
      p = new_p;
    else
      printf ("Reallocation failed\n");
  }
}


C166: xstrcmp

xstrcmp

Summary
#include <string.h>
int xstrcmp (
  const char xhuge *string1,    /* first string */
  const char xhuge *string2);   /* second string */
Description

The xstrcmp function compares the contents of string1 and string2 and returns a value indicating their relationship.

Note

  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value

The xstrcmp function returns the following values to indicate the relationship of string1 to string2:

Value | Description
< 0 | string1 is less than string2
= 0 | string1 is equal to string2
> 0 | string1 is greater than string2
See Also fstrcmp, hstrcmp, strcmp, xstrcpy, xstrlen, xstrncpy
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strcmp (char xhuge *buf1, char xhuge *buf2) {
  char i;

  i = xstrcmp (buf1, buf2);

  if (i < 0)
    printf ("buf1 < buf2\n");
  else if (i > 0)
    printf ("buf1 > buf2\n");
  else
    printf ("buf1 == buf2\n");
}


C166: xstrcpy

xstrcpy

Summary
#include <string.h>

char xhuge *xstrcpy (
  char xhuge *dst,       /* destination string */
  char xhuge *src);      /* source string */
Description

The xstrcpy function copies src to dst and appends a null character to the end of dst.

Note

  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The xstrcpy function returns dst.
See Also | fstrcpy, hstrcpy, strcpy, xstrcmp, xstrlen, xstrncpy
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strcpy (char xhuge *s) {
  char buf [21];

  xstrcpy (buf, s);

  printf ("new string is %s\n", buf);
}


C166: xstrlen

xstrlen

Summary
#include <string.h>

unsigned int strlen (
  const char xhuge *src);   /* source string */
Description The xstrlen function calculates the length, in bytes, of src. This calculation does not include the null terminating character.

Note

  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The xstrlen function returns the length of src.
See Also | xstrcmp, xstrcpy, xstrncpy
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_xstrlen (void) {
  char buf [] = "Find the length of this string";
  unsigned int len;

  len = xstrlen (buf);
  printf ("string length is %d\n", len);
}


C166: xstrncpy

xstrncpy

Summary
#include <string.h>

char *strncpy (
  char *dst,         /* destination string */
  const char *src,   /* source string */
  int len);          /* max characters to copy */
Description

The xstrncpy function copies at most len characters from src to dst. Characters are copied until a null character ('\0') is copied or until len characters have been copied. If the length of src is less than len the remaining bytes in dst are padded with null characters ('\0').

Note

  • This function uses xhuge pointers to objects and may be used in any memory model other than Tiny Model.
Return Value | The xstrncpy function returns dst.
See Also | xstrcmp, xstrcpy, xstrlen
Example
#include <string.h>
#include <stdio.h> /* for printf */

void tst_strncpy (char xhuge *s) {
  char buf [21];

  xstrncpy (buf, s, sizeof (buf));
  buf [sizeof (buf)] = '\0';
}


C166: Appendix

Appendix

This appendix provides numerous details about the Keil C166 Compiler including:

  • Differences from ANSI C
  • Version Differences
  • Writing Optimum Code
  • Compiler Limits
  • Byte Ordering
  • Hints, Tips, and Techniques


C166: A. Differences from ANSI C

A. Differences from ANSI C

The C166 Compiler differs in only a few aspects from the ANSI C Standard. These differences can be grouped into compiler-related differences and library-related differences.

  • Compiler-related Differences
  • Library-related Differences


C166: Compiler-Related

Compiler-Related

  • Wide Characters
    Wide 16-bit characters are not supported by the C166 Compiler. ANSI provides wide characters for support of an international character sets.


C166: Library-Related

Library-Related

The ANSI C Standard Library includes a vast number of routines, most of which are included in the C166 Library. Many, however, are not applicable to an embedded application and are excluded from the C166 Library.

The C166 library includes these ANSI Standard Library routines:

abs
acos
asin
atan
atan2
atof
atoi
atol
calloc
ceil
cos
cosh
exp
fabs
floor
free
getchar
gets
isalnum
isalpha 		iscntrl
isdigit
isgraph
islower
isprint
ispunct
isspace
isupper
isxdigit
labs
log
log10
longjmp
malloc
memchr
memcmp
memcpy
memmove
memset
modf 		pow
printf
putchar
puts
rand
realloc
scanf
setjmp
sin
sinh
sprintf
sqrt
srand
sscanf
strcat
strchr
strcmp
strcpy
strcspn
strlen 		strncat
strncmp
strncpy
strpbrk
strrchr
strspn
strstr
strtod
strtol
strtoul
tan
tanh
tolower
toupper
va_arg
va_end
va_start
vprintf
vsprintf

The following ANSI Standard library routines are not included in the C166 library:

abort
asctime
atexit
bsearch
clearerr
clock
ctime
difftime
div
exit
fclose
feof
ferror
fflush
fgetc
fgetpos
fgets 		fmod
fopen
fprintf
fputc
fputs
fread
freopen
frexp
fscanf
fseek
fsetpos
ftell
fwrite
getc
getenv
gmtime
ldexp 		ldiv
localeconv
localtime
mblen
mbstowcs
mbtowc
mktime
perror
putc
qsort
raise
remove
rename
rewind
setbuf
setlocale
setvbuf 		signal
strcoll
strerror
strftime
strtok
strxfrm
system
time
tmpfile
tmpnam
ungetc
vfprintf
wcstombs
wctomb

The following routines are not found in the ANSI Standard Library but are included in the C166 library:

_atomic_
_bfld_
_chkfloat_
_chkdouble_
_crol_
_cror_
_diswdt_
_einit_
_endatomic_
_getkey
_idle_
_irol_
_iror_
_lrol_
_lror_
_nop_
_pop_
_prior_
_priord_ 		_push_
_pwrdn_
_sof_
_srvwdt_
_testclear_
_testset_
_tolower
_toupper
_trap_
fmemccpy
fmemchr
fmemcmp
fmemcpy
fmemmove
fmemset
fstrcat
fstrchr
fstrcmp
fstrcpy 		fstrcspn
fstrlen
fstrncat
fstrncmp
fstrncpy
fstrpbrk
fstrpos
fstrrchr
fstrpbrk
fstrrpos
fstrspn
hmemcmp
hmemcpy
hstrcmp
hstrcpy
init_mempool
memccpy
strpos
strrpbrk 		strrpos
toascii
toint
ungetchar
xcalloc
xfree
xinit_mempool
xmalloc
xmemccpy
xmemchr
xmemcmp
xmemcpy
xmemmove
xmemset
xrealloc
xstrcmp
xstrcpy


C166: B. Version Differences

B. Version Differences

This appendix lists an overview of major product enhancements and differences between the current version of the C166 Compiler and previous versions. The current version contains all enhancements listed.

  • Version 4.0 Differences
  • Version 3.0 Differences
  • Version 2.6 Differences
  • Version 2.0 Differences
  • Version 1.0 Differences


C166: Version 4.0 Differences

Version 4.0 Differences

  • XLarge Memory Model
    The C166 Compiler now supports the XLarge memory model for the C167 CPU. This memory model increases the available address space for near objects and improves the generated code's performance.


C166: Version 3.0 Differences

Version 3.0 Differences

  • Startup Code
    The startup code supports more features and greater flexibility. When upgrading existing applications, be sure to use the new startup code.
  • Optimizer Level 7
    The C166 Compiler supports Optimizer Level 7 (OPTIMIZE(7)) which adds Common Tail Merging. Refer to OPTIMIZE for more information.
  • _pop_ Intrinsic Library Routine
    The _pop_ library routine pops words off of the system stack.
  • _prior_ Intrinsic Library Routine
    The _prior_ library routine calculates the number of shifts required to normalize a word.
  • _priord_ Intrinsic Library Routine
    The _priord_ library routine calculates the number of shifts required to normalize a 32-bit value.
  • _push_ Intrinsic Library Routine
    The _push_ library routine pushes words onto the system stack.
  • strtod Library Routine
    The strtod library routine converts a string to a double.
  • strtol Library Routine
    The strtol library routine converts a string to a long.
  • strtoul Library Routine
    The strtoul library routine converts a string to an unsigned long.
  • ASMEXPAND and NOASMEXPAND Directives
    The ASMEXPAND and NOASMEXPAND directives select whether or not the C preprocessor expands symbols in ASM/ENDASM blocks.
  • BYTEALIGN Directive
    The BYTEALIGN directive enables compiler support for pointers to byte-aligned structures.
  • DYNAMICUSRSTK Directive
    The DYNAMICUSRSTK directive allows you to specify that the user stack is dynamic. This is required for custom real-time kernels that change the stack for each task.
  • EXTINS Directive
    The EXTINS directive causes the compiler to terminate EXT sequences on a line-by-line basis. This eases debugging and makes it easier to follow program execution because single-steps execute a single line at a time.
  • FIXPEC Directive
    The FIXPEC directive prevents the compiler from generating JMP-to-JMP constructs that may cause problems with the PEC on some C16x/ST10 devices.
  • NOFRAME Directive
    The NOFRAME directive specifies that interrupt service routines are created without prolog or epilog code.
  • PACK Directive
    The PACK directive allows you to specify the alignment the compiler uses when packing structures.
  • PREPRINTONLY Directive
    The PREPRINTONLY directive allows the compiler to generate a preprocessor listing file without creating an object file.


C166: Version 2.6 Differences

Version 2.6 Differences

  • Optimizer Level 6
    The C166 Compiler now supports Optimizer Level 6 (OPTIMIZE(6)) which adds the following new optimizations:
    • Global constant propagation.
    • Enhanced peephole optimization.
    • Enhanced access to huge and xhuge objects.
    • Loop rotation generates code that is faster and more efficient.
    • Conversion of MUL and DIV operations with constant numbers into shift operations.
    • Faster long-shift operations with constant shift factors.
  • Global Common Subexpressions Elimination
    The global common subexpressions optimization is improved.
  • Enhanced C167 Instruction Set Code Generation
    • The code generated for the C167 microcontroller is improved. Library routines are no longer used to access huge and xhuge variables.
  • Enhanced Startup Code
    The startup files (STARTUP.A66 and START167.A66) are rewritten to include initialization of ADDRSEL and BUSCON registers and flexible assignment of DPP registers with the linker's DPPUSE directive.
  • HCompact Memory Model
    The C166 Compiler now supports the HCompact memory model for the C167 CPU. This memory model increases the available address space for near objects and improves the generated code's performance. Furthermore, the linear memory programming model is much easier to understand.
  • HLarge Memory Model
    The C166 Compiler now supports the HLarge memory model for the C167 CPU. This memory model increases the available address space for near objects and improves the generated code's performance. Furthermore, the linear memory programming model is much easier to understand.
  • New Library Routines Support xhuge Objects
    Many new library routines now support the xhuge memory type.
  • _chkfloat_ Library Routine
    The _chkfloat_ library routine supports rapid floating-point number error checking.
  • _chkdouble_ Library Routine
    The _chkdouble_ library routine supports rapid floating-point number error checking.
  • NODPPSAVE Directive
    The NODPPSAVE directive instructs the compiler not to preserve the DPP0 and DPP3 registers inside interrupt functions.
  • NOFIXDPP Directive
    The NOFIXDPP directive instructs the compiler to generate code independent of DPP register contents.
  • REENTRANT Directive
    The REENTRANT directive instructs the compiler to store automatic variables that cannot be allocated to a CPU register on the user stack.
  • STATIC Directive
    The STATIC directive instructs the compiler to use static memory locations for automatic variables that cannot be allocated to a CPU register.
  • UNSIGNED_CHAR Directive
    The UNSIGNED_CHAR directive instructs the compiler to treat all variables declared with char as unsigned char variables.
  • INCDIR Directive
    The INCDIR directive specifies the location of the compiler include files.
  • NOALIAS Directive
    The NOALIAS directive instructs the compiler to ignore pointer write operations during the optimization phase.
  • L166 DPPUSE Directive
    The DPPUSE directive allows reassignment of the DPP registers to support up to 64K of NDATA and NCONST memory.


C166: Version 2.0 Differences

Version 2.0 Differences

  • _atomic_ Intrinsic Library Routine
    The _atomic_ library routine signals the beginning of an ATOMIC instruction sequence and inserts an ATOMIC instruction into your program.
  • _diswdt_ Intrinsic Library Routine
    The _diswdt_ library routine inserts a DISWDT instruction (which disables the watch dog timer) into your program.
  • _einit_ Intrinsic Library Routine
    The _einit_ library routine signals the end of the initialization section and inserts an EINIT instruction into your program.
  • _endatomic_ Intrinsic Library Routine
    The _endatomic_ library routine signals the end of an ATOMIC instruction sequence.
  • vprintf Library Routine
    The vprintf library routine outputs formatted information to the output stream using putchar.
  • vsprintf Library Routine
    The vsprintf library routine outputs formatted information to a buffer.
  • ORDER Directive
    The ORDER directive stored variables in memory in the same order in which they were defined.
  • XHuge Memory Type
    The xhuge memory type was added to support data objects larger than 64K.


C166: Version 1.0 Differences

Version 1.0 Differences

  • C167 and Derivative Support
    The C166 Compiler now supports code generation for the C167 and its derivatives. The MOD167 directive causes the compiler to generate C167 instructions instead of C166 (80C166) instructions. Code generated for the C167 may contain EXTP, EXTR, and EXTS instruction sequences for accessing far and huge memory and extended registers.
  • Additional Warnings
    The C166 Compiler now checks for unused local variables, labels, and expressions.
  • Incremental Linkage
    The L166 Linker now supports incremental linkage which allows you to link your program without locating sections to their final addresses. This feature is enabled by the LINKONLY directive.
  • FIX166 Directive
    The FIX166 directive resolves the A17 problem of the 80C166.
  • FIX167 Directive
    The FIX167 directive resolves the CPU.3 problem of the C167 derivative.
  • MOD167 Directive
    The MOD167 directive instructs the compiler to generate C167 instructions.
  • NOAMAKE Directive
    The NOAMAKE directive excludes AutoMAKE information from the generated object file.
  • REGFILE Directive
    The REGFILE directive specifies the name of the register definitions file to use for global register optimization.
  • RENAMECLASS Directive
    The RENAMECLASS directive allows you to rename a memory class within your C program.
  • WARNINGLEVEL Directive
    The WARNINGLEVEL directive allows you to suppress compiler warnings based on level.
  • L166 LINKONLY Directive
    The LINKONLY directive suppresses the linker's locate process.
  • L166 PUBLICSONLY control
    The PUBLICSONLY directive includes only public symbol information from an input file in the linkage.
  • L166 REGBANK Directive
    The REGBANK directive defines the base address, a memory address, or the order of register banks.
  • L166 VECTAB Directive
    The VECTAB directive specifies the starting address for the interrupt vector table.


C166: C. Writing Optimum Code

C. Writing Optimum Code

This section lists a number of ways you can use to improve the efficiency (i.e., smaller code and faster execution) of the code generated by the C166 Compiler. The following is by no means a complete list of things to try. In most cases, these suggestions improve the speed and reduce the code size of your program.

  • Memory Model
  • Variable Location
  • Variable Size
  • Automatic Variables
  • Avoid far/huge Pointer Cast
  • Optimum Code for C167
  • Other Sources


C166: Memory Model

Memory Model

The most significant impact on code size and execution speed is the selected memory model. Compiling in the small model always generates the smallest, fastest code possible.

The SMALL directive instructs the compiler to use the small memory model. In this memory model, all variables are stored in near memory (unless they are explicitly located elsewhere) and are accessed using short, 16-bit near addresses. Programs with more than 64K of code may use medium model (which still stores variables in near memory).

If you must use the large or compact memory model and if you use a C167-compatible device, you should consider the xlarge, hlarge, or hcompact models. These memory models generate better code for C167 devices.


C166: Variable Location

Variable Location

Frequently accessed data objects should be located in the on-chip memory of the C16x/ST10. Accessing the on-chip memory is much more efficient than accessing external data memory. The on-chip data RAM is shared among register banks, the bit data area, the stack, and other user-defined variables with the idata or bdata memory type.

Because of the limited amount of on-chip RAM, all your program variables may not fit into this memory area and some must be located in other memory areas. There are several ways to do this.

One way is to change the memory model and let the compiler to all the work. This is the simplest method, but it is also the most costly in terms of the amount os generated code and system performance. Refer to Memory Model for more information.

Another way to locate variables in other memory areas is to manually select the variables that are not required to be in on-chip memory and to declare them using the far, huge, or xhuge memory specifiers. Usually, string buffers and other large arrays can be located off-chip without a significant degradation in performance or increase in code size.

The HOLD directive may be used in combination with an appropriate memory model to specify thresholds for variable size and certain memory areas. This allows you to automatically locate large buffers and variables in memory areas based entirely on size.

In general, near variables are the most efficient followed by far, huge, and xhuge in that order. Bit variables are always located in on-chip RAM. So, you should use a bit whenever yes/no information is adequate.


C166: Variable Size

Variable Size

Members of the C16x/ST10 family are all 16-bit CPUs. Operations that use 16-bit types (like int and unsigned int) are much more efficient than operations that use char or long types. For this reason, use the int or unsigned int data types when possible and when RAM size is not critical.


C166: Automatic Variables

Automatic Variables

The C166 Compiler attempts to maintain automatic variables in CPU registers. Since the C16x/ST10 microcontroller has 16 registers, several automatic variables can be located in registers. When determining which automatic variables to store in registers, the optimizer in the C166 Compiler gives priority to index variables used in for and while loops. The best results are achieved by using int or unsigned int variables.


C166: Avoid far/huge Pointer Cast

Avoid far/huge Pointer Cast

Avoid pointer type casts betweek far and huge. These kinds of type casts generate many instructions to convert from one pointer type to the other. You will achieve the best reqults by declaring the pointer with the memory type actually needed.

On C167-compatible devices, huge pointers are more efficient and generate less code than far pointers. In general, you should avoid the far memory type in C167 applications.


C166: Optimum C16x Code

Optimum C16x Code

The default settings of the C166 Compiler generate optimum code for 80C166 devices. If you use devices with the extended C16x or XC16x instruction sets, the following suggestions will help you create smaller, faster programs.

  • If you are writing a program for C16x derivatives, make sure you use the MOD167 directive to enable the C16x instruction set.
  • If you are writing a program for XC16x derivatives, make sure you use the MODV2 directive to enable the XC16x instruction set.
  • If your application has large data-memory requirements use the XLARGE, HLARGE, or HCOMPACT memory models instead of LARGE or COMPACT. The XLARGE, HLARGE, and HCOMPACT memory models are more efficient and generate better code than LARGE or COMPACT. Using HLARGE or HCOMPACT simplifies debugging since 14-bit far pointers are not used in these memory models.
  • You can improve interrupt functions by using the NODPPSAVE compiler directive. Use this directive only if you do not change the DPP registers in your code. The C166 Compiler and the run-time libraries for the C167 do not change these registers.
  • Make certain that assembler code or libraries you use do not change the DPP registers. Refer to the NODPPSAVE compiler directive for more information.
  • You may extend the space for near objects (NDATA and NCONST) up to 64KB by using the NOFIXDPP compiler directive with the DPPUSE linker directive.


C166: Other Sources

Other Sources

The quality of the compiler-generated code is more often than not directly influenced by the algorithms implemented in the program. Sometimes, you can improve the performance or reduce the code size simply by using a different algorithm. For example, a heap sort algorithm always outperforms a bubble sort algorithm.

For more information on how to write efficient programs, refer to the following books:

The Elements of Programming Style, Second Edition
Kernighan & Plauger
McGraw-Hill
ISBN 0-07-034207-5

Writing Efficient Programs
Jon Louis Bentley
Prentice-Hall Software Series
ISBN 0-13-970244-X

Algorithms in C
Robert Sedgewick
Addison Wesley
ISBN 0-201-51425-7

Data Structures, Algorithms & Software Principles in C
Thomas A. Standish
Addison Wesley
ISBN 0-201-59118-9


C166: D. Compiler Limits

D. Compiler Limits

The C166 Compiler embodies some known limitations. For the most part, there are no limits placed on the compiler with respect to components of the C programming language. For example, you may specify an unlimited number of symbols or number of case statements in a switch block. If there is enough address space, several thousand symbols could be defined.


C166: Compiler Limitations

Compiler Limitations

Following is a list of the limitations of the Keil C166 C Compiler.

  • The C166 Compiler supports a maximum of 20 levels of indirection (access modifiers) to any standard data type. This includes array descriptors, indirection operators, and function descriptors.
  • Preprocessor symbols may be up to 255 characters long. All 255 characters are significant. Preprocessor symbols are case sensitive.
  • Names may be up to 255 characters long. However, only the first 128 characters are significant. The C language provides for case sensitivity for function and variable names.
  • There is no limit to the number of case statements in a switch block.
  • The maximum number of nested function calls in an invocation parameter list is 10.
  • The maximum code size of a single module is 64K.
  • The maximum number of nested include files is 9. This value is independent of list files, preprocessor files, or whether or not an object file is to be generated.
  • The maximum depth of directives for conditional compilation is 20. This is a preprocessor limitation.
  • Instruction blocks ({...}) may be nested up to 255 levels deep.
  • Macros may be nested up to 8 levels deep.
  • A maximum of 32 parameters may be passed in a macro or function call.
  • The maximum length of a line or a macro definition is 65,535 characters. Even after a macro expansion, the result must not exceed 65,535 characters.


C166: OMF Limitations

OMF Limitations

Following is a list of the limitations of the OMF166 object module format.

  • The maximum number of sections in an object file is 32,767. Each compilation unit generates one code section (if it contains at least one function) and a variable number of other sections (typically 1 to 8), depending on the memory types used in variable declarations.
  • The maximum number of global (public) identifiers is 32,767. All file-level data and function definitions that are not explicitly declared with the static storage class are public identifiers.
  • The maximum number of external identifiers is 32,767.
  • The maximum number of interrupt procedures is 128. This limit is imposed by the C16x/ST10 architecture.


C166: E. Byte Ordering

E. Byte Ordering

Most microprocessors have a memory architecture composed of 8-bit address locations known as bytes. Many data items (addresses, numbers, and strings) are too long to be stored using a single byte and must be stored in a series of consecutive bytes.

When using data stored in multiple bytes, byte ordering becomes an issue. Unfortunately, there is not just one standard for the order in which bytes in multi-byte data are stored. There are two popular methods of byte ordering currently in widespread use.

The first method is called little endian and is often referred to as Intel order. In little endian, the least significant, or low-order, byte is stored first. For example, a 16-bit integer value of 0x1234 (4660 decimal) would be stored using the little endian method in two consecutive bytes as follows:

Address | +0 | +1
Contents | 0x34 | 0x12

A 32-bit integer value of 0x57415244 (1463898692 decimal) would be stored using the little endian method as follows:

Address | +0 | +1 | +2 | +3
Contents | 0x44 | 0x52 | 0x41 | 0x57

A second method of accessing multi-byte data is called big endian and is often referred to as Motorola order. In big endian, the most significant, or high-order, byte is stored first and the least significant, or low-order, byte is stored last. For example, a 16-bit integer value of 0x1234 would be stored using the big endian method in two consecutive bytes as follows:

Address | +0 | +1
Contents | 0x12 | 0x34

A 32-bit integer value of 0x004A4F4E would be stored using the big endian method as follows:

Address | +0 | +1 | +2 | +3
Contents | 0x00 | 0x4A | 0x4F | 0x4E

The C16x/ST10 is a 16-bit machine and has no instructions to directly manipulate data objects larger than 16-bits. Multi-byte data are stored according to the following rules:

  • The C16x/ST10 architecture uses the little endian format.
  • Floating-point numbers are stored according to the IEEE-754 format and are stored in little endian format. Refer to Floating-point Numbers for more information.

If your C16x/ST10 embedded application performs data communications with other microprocessors, it may be necessary to know the byte ordering method used by the other CPU. This knowledge is required when transmitting raw binary data.


C166: F. Hints, Tips, and Techniques

F. Hints, Tips, and Techniques

This section lists a number of illustrations and tips which commonly require further explanation. Items in this section are listed in no particular order and are merely intended to be referenced if you experience similar problems.


C166: Using Interrupts

Using Interrupts

To enable an interrupt source you must set the following registers:

  • The PSW contains the IEN bit which enables all interrupts. The IEN bit must be set to 1. Otherwise, the chip does not accept any interrupts.
  • Each interrupt source is controlled through an Interrupt Control Register (xxIC) which contains a group level (GLVL), an interrupt level (ILVL), and an interrupt enable bit (xxIE). To enable the interrupt source, set the xxIE bit to 1.
  • ILVL determines the priority of the interrupt. If ILVL is set to 0, the interrupt is not serviced. You must set the ILVL field to 1 or higher to service the interrupt.
  • If several interrupts have the same ILVL value, the group level (GLVL) must be different. The C16x/ST10 microcontroller does not allow the same ILVL and GLVL value for more than one interrupt.
  • Interrupt functions with the same ILVL value can share a register bank minimizing the memory space required.

Use the following methods to disable interrupts for a C statement or a C function:

  • Use #pragma disable to disable interrupts for the duration of a C function. Refer to the DISABLE directive for more information.
  • C167-compatible devices have an ATOMIC instruction which may be used to prevent interrupts for up to 4 instructions. Refer to the _atomic_ and _endatomic_ routines for more information.
  • For longer sequences on XC16x devices clear the IEN bit in the PSW. On classic 80C166, C16x, and ST10 devices this method is not recommended since it may cause an disabled interrupt system for a very long time (see note below).
  • On classic 80C166, C16x, and ST10 you can set the ILVL value in the PSW to 0xF. Since no interrupts can have a higher ILVL essentially, they will all be disabled. Changes to the PSW require two instructions cycles before they take effect. Therefore, you must add two NOP instructions after PSW changes to avoid any pipeline effects.

The following example program shows the C statements required to disable interrupts:

stmt level    source

   1          #include <reg167.h>
   2          #include <intrins.h>
   3
   4          long l;
   5
   6          void test (void)  {
   7   1        _bfld_ (PSW, 0xF000, 0xF000); /* disable interrupts */
   8   1        _nop_ ();                     /* avoid pipeline effect */
   9   1        _nop_ ();
  10   1        l = 0;
  11   1        _bfld_ (PSW, 0xF000, 0x0000); /* enable interrupts */
  12   1
  13   1        _atomic_ (0);                 /* disable interrupts */
  14   1        l = 1;
  15   1        _endatomic_ ();               /* enable interrupts */
  16   1      }
  17
  18

ASSEMBLY LISTING OF GENERATED OBJECT CODE

             ; FUNCTION test (BEGIN  RMASK = @0x4010)
                                           ; SOURCE LINE # 6
                                           ; SOURCE LINE # 7
0000 1A88F0F0      BFLDH   PSW,#0F0H,#0F0H
                                           ; SOURCE LINE # 8
0004 CC00          NOP
                                           ; SOURCE LINE # 9
0006 CC00          NOP
                                           ; SOURCE LINE # 10
0008 F68E0000 R    MOV     l,ZEROS
000C F68E0200 R    MOV     l+02H,ZEROS
                                           ; SOURCE LINE # 11
0010 1A8800F0      BFLDH   PSW,#0F0H,#00H
                                           ; SOURCE LINE # 13
0014 D120          ATOMIC  #03H
                                           ; SOURCE LINE # 14
0016 E014          MOV     R4,#01H
0018 F6F40000 R    MOV     l,R4
001C F68E0200 R    MOV     l+02H,ZEROS
                                           ; SOURCE LINE # 15
0020 CB00          RET
             ; FUNCTION test (END    RMASK = @0x4010)

Note

  • On classic 80C166, C16x and ST10 devices, do not use the IEN bit in the PSW to disable interrupt. If you set IEN to 0, the PSW gets updated two instruction later. During this time, if an interrupt occurs, the interrupt system is blocked for the entire interrupt function and not just for the C statements you are trying to protect.


C166: Program Execution

Program Execution

Certain problems commonly occur due to the complexity of the C16x/ST10 microcontroller architecture. Check the following if your program hangs up or behaves strangely:

  • If your program runs in the µVision Simulator but not on your target hardware you may have problems with the initialization of the SYSCON and BUSCON registers in the STARTUP code. Carefully check to be certain that all parameters in the STARTUP code match your target hardware. In most cases, the hardware is not correctly configured.

    Run a simple program on your target hardware before you try a complex application. Start with the HELLO program example provided in the \KEIL\C166\EXAMPLES\HELLO folder.
  • If your program runs in the µVision Simulator but not on your target hardware the linker memory classes for your ROM and RAM may not match your target system. Check the areas listed under MEMORY MAP in the linker/locator MAP file (*.M66) and verify that they match the memory configuration of your target hardware.
  • Make certain your code is not allocated to on-chip RAM (register or SFR area). Code allocated to on-chip RAM will not work in your target hardware. Select proper areas for the FCODE memory class with the linker's CLASSES directive. For example:
    FCODE (0 - 0xEFFF, 0x10000 - 0x3FFFF)


C166: Using the PEC

Using the PEC

The Peripheral Event Controller (PEC) of the C16x/ST10 only works with source and destination addresses from segment 0 (address range 0x0000-0xFFFF). If you use the sdata memory type for these buffers, the L166 Linker ensures they are located page 3 (address range 0xC000-0xFFFF). If you use any other memory type, you must ensure that the buffers are located in the proper address range.

For more information about using the PEC, refer to the _sof_ library routine.


C166: Stack Problems

Stack Problems

If your program hangs for no apparent reason, you may be running out of stack space. Since embedded applications often use interrupts, it can be very difficult to calculate stack requirements. Try one of the following suggestions if you think your application has problems with the available stack space.

  • Execute your program with a debugger or emulator. Stop after the memory initialization at the beginning of the main function. Fill the memory space of the system stack and the user stack with a constant value (such as 0xA5 or "STACK...") and execute all functions of the application. Use the debugger to see if there is enough stack space to execute your most complex interrupt procedure. The location of the user stack and system stack is listed in the MEMORY MAP of the linker/locator listing file (*.M66).
  • If you cannot work with a debugger in your target system, increase the stack space and see if this resolves the problems you are experiencing.


C166: Using Monitor-166

Using Monitor-166

If you want to test a C program using MON166, and if MON166 is installed at code address 0000h, consider the following rules:

  • When you build the monitor, you must correctly specify the redirected reset and interrupt vector address to the monitor by editing the INT_ADR_SEG and INT_ADR_OFF definitions in the INSTALL.A66 or INST167.A66 monitor configuration files.
  • You must use the linker's VECTAB directive to locate the interrupt and reset vectors for the target program to the correct starting address.
  • When using MON166, you must protect the monitor's memory area from being used by your target program. You may use the linker's RESERVE directive to do that. For example:
    L166 ... RESERVE  (8h-0Bh, 88h-8Bh, 0B8h-0BBh,   /* Monitor Traps */
                   3E900h-3FFFFh)                /* Monitor Code & Data */


C166: Using the bdata Type

Using the bdata Type

Some users have reported difficulties in using the bdata memory type. Using bdata is similar to using the sfr modifier. The most common error is encountered when referencing a bdata variable defined in another module. For example:

extern char bdata xyz_flag;

sbit xyz_bit1 = xyz_flag^1;

In order to generate the appropriate instructions, the compiler must have the absolute value of the reference to be generated. In the above example, this cannot be done, as the address of xyz_flag is not known until after the linking phase has been completed. Follow the rules below to avoid this problem.

  • A bdata variable (defined and used in the same way as an sfr) must be defined in global space and not within the scope of a procedure.
  • A bdata bit variable (defined and used in the same way as an sbit) must also be defined in global space and cannot be located within the scope of a procedure.
  • The definition of the bdata variable and the creation of its sbits must be accomplished within a single source module.

For example, declare the bdata variable and the bit component in the same source module:

char bdata xyz_flag;
sbit xyz_bit1 = xyz_flag^1;

Then, declare the bit component external:

extern bit xyz_bit1;

As with any other declared and named C variable that reserves space, simply define your bdata variable and its component sbits in a module. Then, use the extern bit specifier to reference it as the need arises.


C166: Using TRAPS.C

Using TRAPS.C

The C16x/ST10 microcontroller generates several hardware traps (interrupts) for hardware or software failures. The source code of TRAPS.C (found in the \KEIL\C166\LIB\ folder) is listed below:

/***********************************************************************/
/*  This file is part of the C166 Compiler package                     */
/***********************************************************************/
/*                                                                     */
/*  TRAPS.C:  TRAP Handler for 166/167 hardware traps                  */
/*                                                                     */
/*  To translate this file use C166 with the following invocation:     */
/*                                                                     */
/*     C166 TRAPS.C                                                    */
/*                                                                     */
/*  To link the modified TRAPS.OBJ file to your application use the    */
/*  following L166 invocation:                                         */
/*                                                                     */
/*     L166 <your object file list>, TRAPS.OBJ <controls>              */
/*                                                                     */
/***********************************************************************/

/*
 * Non-Maskable Interrupt
 */
void NMI_trap (void) interrupt 0x02  {
  /* add your code here */
  while (1);                 /* end-less loop */
}

/*
 * Stack Overflow Interrupt
 */
void STKOF_trap (void) interrupt 0x04  {
  /* add your code here */
  while (1);                 /* end-less loop */
}

/*
 * Stack Underflow Interrupt
 */
void STKUF_trap (void) interrupt 0x06  {
  /* add your code here */
  while (1);                 /* end-less loop */
}
/*
 * Class B Hardware Trap:
 *   ->  Undefined Opcode
 *   ->  Protected Instruction Fault
 *   ->  Illegal Word Operand Access
 *   ->  Illegal Instruction Access
 *   ->  Illegal External Bus Access
 */
void Class_B_trap (void) interrupt 0x0A  {
  /* add your code here */
  while (1);                 /* end-less loop */
}

You may add this module to your project to detect hardware and software failures of your application. If you run your program with a debugger or emulator, you may set break points on the entry addresses of the interrupt functions. The location that caused the problem can be determined by using TRACE information or the stack contents.


C166: C166 User's Guide

C166 User's Guide

 Keil Software

The C166 Compiler User's Guide contains information about how to use the Keil C166 Compiler. The C166 Compiler creates object modules from the C files you write and compile. Object modules created may be added into a library (using the LIB166 Library Manager) or may be linked with other object modules and libraries to form a program (using the L166 Linker/Locator).

This manual contains the following chapters.

  • Introduction provides a brief introduction to the Keil C166 Compiler.
  • Compiling Programs specifies how to run the compiler and generate object files. This chapter discusses the directives that are available.
  • Language Extensions discusses the extensions to the ANSI C Language that are implemented by the C166 Compiler.
  • Preprocessor describes some of the capabilities of the C language preprocessor.
  • Advanced Programming discusses advanced programming options including startup code, customization files, interfacing C programs to assembler, and data storage formats.
  • Error Messages lists all error and warning messages that are generated by the compiler.
  • Library Reference lists all library routines that are available in the standard C166 library.
  • The Appendix provides numerous details about the compiler including differences from ANSI C, version details, compiler limitations, how to write optimum code, and other hints and tips.
Revision History
  • January 2004: Initial revision in CHM format.