Keil Logo

Release Notes for C166
C16x/ST10 Development Tool Kits

Download this Update

This file contains release notes and last minute changes that are not found in the printed manuals.

Information in this file, the accompanying manuals, and software is
Copyright © Keil™, An ARM® Company.
All rights reserved.


  1. What's New in C166
  2. Example Programs
  3. Device Database
  4. Peripheral Simulation
  5. Technical Support
  6. Contact Details

What's New in C166

The following sections list the changes instituted in each release of the C166 toolset.

C166 Version 4.23 Release

  • [µVision2]
    Added DaVE support for the new XC161/XC164 devices.
  • [µVision2]
    Added drivers for ULINK (USB-OCDS Adapter for XC16x Devices).
  • [C166 Compiler]
    Corrected the behavior of pragma directives to be compatible with C166 Version 4.20. Version 4.22 added detailed checking for primary controls and created problems with existing source code. Now the behavior is compatible with Version 4.20 except that the ORDER directive must be specified on the command line or at the beginning of a C source file.
  • [L166 Linker]
    Corrected a problem that occurred (due to EC++ segments) when building Monitor-166. EC++ segments are now generated only for projects that contain EC++ modules.
  • [µVision2 Debugger]
    Added debug dialogs (for most C16x and ST10 devices) that display the peripheral status while debugging using Monitor-166 or an Emulator.

C166 Version 4.22 Release

    Added EC++ Compiler. Several tool enhancements were made to support EC++. Details for using the EC++ Compiler can be found in \C166\HLP\EC166.CHM.
    Added support for the new Infineon XC161/XC164 devices.

C166 Version 4.20 Release

  • [L166 Linker]
    Added the NOSORTSIZE (abbreviation NOSO) directive which disables section sorting within the linker. By default, the linker sorts sections by size before locating them. This ensures fewer gaps in the memory space which reduces memory consumption. The NOSORTSIZE directive disables sorting and is compatible with the version 3 linker.

C166 Version 4.12 Release

  • [C166 Compiler]
    Corrected various minor problems.

C166 Version 4.10a Release

  • [C166 Compiler]
    Added the COMMONRET directive (abbreviation CR) which forces the compiler to generate functions that always exit at the same RET instruction. RET instructions will not be inserted in the middle of a function.
  • [C166 Compiler]
    Added the FIXBFLD directive (abbreviation FB) which 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 µVision2, you must enter it in 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.

    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.

  • [L166 Linker]
    Enhanced the INTNO directive by adding two new subcommands.

    INTNO (interrupt_name (FILL)) causes the linker to direct unused interrupts to the specified interrupt_name. For example:
    void interrupt_trap (void) interrupt MYINT
      while (1);

    defines the interrupt service routine MYINT and...

    L166 myfile.obj INTNO (MYINT (FILL))

    instructs the linker to direct all unused interrupts to MYINT.

    INTNO (interrupt_name (NONE)) suppresses generation of the interrupt vector. For example:

    L166 myfile.obj INTNO (MYINT (NONE))

    instructs the linker not to generate an interrupt vector for MYINT. This may be useful if you supply the interrupt vector in an assembly file. For example:

    EXTERN interrupt_trap:NEAR             ; FAR for MEDIUM, LARGE, HLARGE Model
         int_vector4 section code at 4     ; interrupt vector address
         vector4 proc
            jmp FAR interrupt_trap
         vector4 endp
         int_vector4 ends

C166 Version 4.06 Release

  • [C166 Compiler]
    Added the EXTINS directive which causes the compiler to terminate EXTS and EXTP instruction sequences after each source line (typically, the compiler generates code with EXTS and EXTP sequences that are longer than one source line). This directive improves single-stepping during debugging.

C166 Version 4.05 Release

  • [C166 Compiler]
    Added the _pop_ intrinsic function which uses the POP instruction to pop a 16-bit word value from the system stack.
  • [C166 Compiler]
    Added the _push_ intrinsic function which uses the PUSH instruction to push a 16-bit word value onto the system stack.
  • [C166 Compiler]
    Added the _prior_ intrinsic function which uses the PRIOR instruction to calculate the number of left shifts required to normalize a number.
  • [C166 Compiler]
    Added the _priord_ intrinsic function which uses the PRIORD instruction to calculate the number of left shifts required to normalize a number.
  • [C166 Compiler]
    Changed the behavior of hidden string placement. Hidden strings (those declared without an associated name and memory space) are now located in the memory space requested by their associated pointer declaration. For example:
    const char huge  *phc = "const huge memory";  // String located in huge-const
    const char xhuge *pxc = "const xhuge memory"; // String located in xhuge-const
    const char   far *pfc = "const far memory";   // String located in far const
    const char  near *pnc = "near memory";        // String located in near const

C166 Version 4.03 Release

  • [C166 Compiler]
    Corrected various minor problems.

C166 Version 4.02 Release

  • [C166 Compiler]
    Corrected various minor problems.

C166 Version 4.01 Release

  • [C166 Compiler]
    Added the FIXPEC directive which ensures that functions do not begin with JMP instructions. When you use optimizer level 7 (OPTIMIZE(7)) the compiler may generates JMPs to functions (instead of CALLs). If the function begins with a JMP instruction, you may experience problems with the PEC on some chip steppings. The FIXPEC directive solves this potential problem. To use this directive in µVision2, you must enter it in Options-C166-Misc.
  • [A166 Assembler]
    Enhanced the OMF166 object module format to support 32-bit and 64-bit numbers. This OMF format is supported by the L166 Linker Version 4.02 and higher. The absolute OMF format was not changed so existing debugging tools will continue to function without any problems.
  • [A166 Assembler]
    Enhanced expression evaluation to use 64-Bit arithmetic. Previous versions of the A166 Assembler used 16-bit math when calculating expressions. In the following equate:
    Value EQU (8000h + 9000h) / 2

    A166 Version 3 calculates a value of 800h since the result of the addition is 1000h (a 16-bit value). A166 Version 4.12 calculates a value of 8800h since the result of the addition is 110000h (a 64-bit value).

  • [A166 Assembler]
    Added new directives and operators to support 32-bit and 64-bit values.

    The following directives were added to support defining and reserving space for 32-bit and 64-bit objects:
    • DD: Define double-word value.
    • DF32: Define 32-bit floating-point value.
    • DF64: Define 64-bit floating-point value.
    • DSD: Define storage for a double-word value.

    For example:

    [name[:]] DD   init [, init] [,...] /* DWORD */
    [name[:]] DF32 init [, init] [,...] /* 32-bit IEEE float */
    [name[:]] DF64 init [, init] [,...] /* 64-bit IEEE float */
    [name[:]] DSD  expression           /* DWORD */

    The following operators were added to support 32-bit and 64-bit constant manipulations:

    • DATA32: Creates a 32-bit constant value.
    • DATA64: Creates a 64-bit constant value.
    • WORD0, WORD2, WORD4, WORD6: Extracts a word from an expression.
    • BYTE0, BYTE1, BYTE2, ... BYTE7: Extracts a byte from an expression.
  • [A166 Assembler]
    Reserved more symbols and directives to support new features. If your existing assembler modules use names that are the same as those reserved by the assembler, you must change them. For example, the symbol DD is a reserved symbol. It is used to define a double word value. Therefore, your program may not use DD as a label or other name.
  • [A166 Assembler]
    Enhanced the macro processor to behave like the A51 Assembler and A2561 Assembler. The following directives are now available.
    • NOMACRO disables all macro processing.
    • NOMPL disables the MPL Macro processor.
    • MPL enables the MPL Macro processor.
  • [A166 Assembler]
    Added support for all instructions of the STMicroelectronics ST10 MAC unit. MAC instructions are enabled with the EXTMAC directive. For example:

C166 Version 4.00 Release

  • [C166 Compiler]
    Added support for accessing bit-fields with bit instructions when the associated structure is located in the BDATA address space. For example:
    struct test {
      int bit0: 1;
      int bit1: 1;
      int bit2: 1;
      int bit3: 1;
      int bit4: 1;
      int bit5: 1;
    struct test bdata t;
    void main (void)  {
      t.bit0 = 1;
      if (t.bit1) {
        t.bit2 = t.bit0;

    You may use the HOLD directive to locate structures with single-bit bit-fields to the BDATA memory area. The compiler then generates bit instructions to access the bit-fields. For example:

    C166 MYPROG.C HOLD (bdata 2, near 6)

    locates all structures (smaller than 2 bytes) with bit-fields to the BDATA memory.

  • [C166 Compiler]
    Added a new memory type (EBDATA) which allows you to access extended bits in the Special Function Register (SFR) area. The memory classes EBDATA and EBDATA0 are used for bits in EBDATA.

    You may use this bit-addressing mode to access SFR registers of the 166 derivatives by 1) defining all the CPU SFR registers in a C source file, 2) translating the file with the ORDER directive, 3) and locating the section containing the SFR definitions with the SECTIONS linker directive. For example:

  • [C166 Compiler]
    Added the PACK directive which allows you to specify whether objects in structures are aligned on byte (PACK(1)) or word (PACK()) boundaries. By default, the compiler located all structure members so that they begin on 16-bit word boundaries. The following example shows the difference between byte-alignment and word-alignment:
    #pragma pack(1)     // Select byte-alignment
         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()      // Select word-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

    The PACK(1) directive may be useful when exchanging data structures with other systems where no alignment is required. This directive is compatible with the Microsoft C directive.

    Note that the C166 compiler generates considerably more code to access byte-aligned words. For this reason, the PACK(1) directive should be used only when necessary.

  • [C166 Compiler]
    Added the BYTEALIGN directive. By default, the compiler assumes that pointers point to objects that start on word (16-bit) boundaries. The BYTEALIGN directive informs the compiler that struct pointers may point to byte-aligned structures. This directive is required when you use the PACK(1) directive. The following example illustrates this:
    #pragma PACK(1)       // Select byte-alignment
    #pragma BYTEALIGN     // Use pointers to byte-aligned structures
         struct s1  {
           int  i1;       // i1 has offset 0
           char c1;       // c1 has offset 2
           struct s2  {
             int  i2;     // s2.i2 has offset 3
             char c2;     // s2.c2 has offset 5
             int  i3;     // s2.i3 has offset 6
           } s2;
           char z1;       // z1 has offset 8
         } s1;
         struct s2 *s2p;
         void main (void)  {
           s2p = &s1.s2;  // &s1.s2 is a byte-aligned structure
           s2p->i2 = 0;   // s2p->i2 is a byte-aligned int
  • [C166 Compiler]
    Added the PREPRINTONLY directive (abbreviation PPO) which causes the compiler to create a C preprocessor output file and stop after the C preprocessor completes. This directive is similar to the PREPRINT directive except that no object file is created. PREPRINTONLY allows you to optionally specify an output filename (the default filename is basename.I). For example:
  • [C166 Compiler]
    Added the ASMEXPAND directive (abbreviation AE) and the NOASMEXPAND directive (abbreviation NOAE).

    The ASMEXPAND directive is the default setting. It instructs the compiler to expand all symbols used in ASM-ENDASM blocks.

    The NOASMEXPAND directive prevents the the compiler from expanding symbols used in ASM-ENDASM blocks. For example:

    #pragma noasmexpand
    #define  abc  1
    #define  xx0  2
    #define  xx1  3
    #pragma asm
      abc equ 2     ; abc (which is defined above) is not expanded
      xx0 equ 10    ; xx0 (which is defined above) is not expanded
    #ifdef QQQ
      xx1 equ 20    ; xx1 (which is defined above) is not expanded
    #pragma endasm
  • [C166 Compiler]
    Added the USERSTACKDPP3 directive (abbreviation U3) which changes assumptions made by the compiler regarding access to the user stack. By default, the user stack is located in the NDATA memory class and is accessed using R0.

    Use the USERSTACKDPP3 directive to change the memory class of the user stack to IDATA or SDATA (which are accessed using DPP3). To accomplish this you must change the definition of the ?C_USERSTACK section in the STARTUP.A66 or START167.A66 file.

    To this:


    Or this:


    Additionally, you must change the address of the user stack that is loaded into R0.

    From this:


    To this:

  • [C166 Compiler]
    Added the DYNAMICUSRSTK directive (abbreviation DU) which informs the compiler that your program modifies the user stack area. This is useful to developers who create real-time operating systems that change the user stack area. With this directive, it is possible to have a 16KB user stack for each task. Without this control, the entire user stack area must reside in the NDATA memory class which is limited to a maximum of 64 Kbytes.
  • [C166 Compiler]
    Added the NOFRAME directive (abbreviation NOF) which causes the compiler to suppress the prolog and epilog in an interrupt service routine (ISR) that immediately follows the directive specification. This directive is active for only one function. It is useful for interrupt routines that never return (like CPU RESET).

    The following example illustrates the difference in generated code between a standard interrupt and one generated using the NOFRAME directive.

     1          int i1, i2, i3;
     3          void intr_func1 (void)  interrupt 0x21  {
     4   1        i1 = i2 * i3;
     5   1      }
     7          #pragma NOFRAME
     8          void intr_func2 (void)  interrupt 0x22  {
     9   1        i1 = i2 * i3;
    10   1      }
         ; 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)

    The interrupt function built using NOFRAME does not switch context nor save and restore registers.

  • [C166 Compiler]
    Added the SAVESYS directive which instructs the compiler to save temporary results to the system stack. This is the default setting for the compiler. This directive is useful for The system stack is always in the on-chip RAM. It is faster than the user stack but the size is limited. See the SAVEUSR directive description for an example of how this directive is used.
  • [C166 Compiler]
    Added the SAVEUSR directive which instructs the C Compiler to save temporary results and saved-by-callee variables to the user stack. This directive is useful when your stack will exceed the size of the on-chip system stack. Of course, accesses to the user stack are slower than accesses to the system stack. For example:
     1    extern void func (void);
     3    #pragma SAVESYS   // Temporary Saves to SYSTEM STACK (default)
     4    int func1 (int i1, int i2)  {
     5 1    func ();
     6 1    return (i1 + i2);
     7 1  }
    10    #pragma SAVEUSR   // Temporary Saves to USER STACK
    11    int func2 (int i1, int i2)  {
    12 1    func ();
    13 1    return (i1 + i2);
    14 1  }
         ; 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)

    In func1, arguments are passed on the system stack and a PUSH instruction is used to put values onto the stack. In func2, arguments are passed on the user stack (which is accessed using R0) and a MOV instruction is used to put values onto the stack.

  • [C166 Compiler]
    Added optimizer level 7 (OPTIMIZE(7)) common tail merging. When this optimization level is enabled, the compiler analyzes the generated code function-by-function, locates common heads and tails, and merges them if possible. If the compiler detects common code sequences (which commonly occur in switch/case statements) it replaces one code sequence with a jump instruction to the other equivalent code sequence. While analyzing the code, the compiler also replaces instruction sequences with shorter instructions. The default optimizer level is still optimizer level 6. You must enable optimizer level 7 using the OPTIMIZE directive or from the µVision2 Project Options Dialog.
  • [L166 Linker]
    Added the CINITTAB directive which allows you to locate the C166 initialization sections ?C_CLRMEMSEC and ?C_INITTAB to a specific address range. For example:
    L166 myfile.obj CINITTAB (0x10000 - 0x18000)

    locates ?C_CLRMEMSEC and ?C_INITTAB to the address range 0x10000-0x18000. L166 issues a warning if this is not possible.

  • [L166 Linker]
    Added the DISABLEWARNING (abbreviation DW) directive which allows you to selectively disable linker warnings. For example:
    L166 myfile.obj DISABLEWARNING (20, 22)

    disables warnings 20 and 22.

  • [L166 Linker]
    Added Warning 22: CLASS RANGE NOT GIVEN IN INVOCATION LINE. When you use a memory class without defining its address range, the L166 Linker now outputs a warning message. Note that this warning is not generated for the following classes: IDATA, IDATA0, BIT, BIT0, BDATA, and BDATA0.

Example Programs

Example programs included in the \C166\EXAMPLES folder demonstrate how to use the µVision2 Project Manager and Debugger (see the µVision2 Quick Start Guide for details). Please refer to these if you are new to the tools and want to get started quickly.

Device Database

A unique feature of the Keil µVision2 IDE is the Device Database which contains information about more than 400 supported microcontrollers. When you create a new µVision2 project and select the target chip from the database, µVision2 sets all assembler, compiler, linker, and debugger options for you. The only option you must configure is the memory map.

As new devices become available, they are added to the database along with data sheets and header files. For information about adding your own chips to the database or about creating your own personal databases refer to the following knowledgebase articles.

Peripheral Simulation

The µVision2 Debugger provides complete simulation for the CPU and on-chip peripherals of most embedded devices. To discover which peripherals of a device are supported, in µVision2 select the Simulated Peripherals item from the Help menu. You may also use the web-based Device Database. We are constantly adding new devices and simulation support for on-chip peripherals so be sure to check the Device Database often.

Technical Support

At Keil Software, we are dedicated to providing you with the best development tools and technical support. That's why we offer numerous ways you can get the technical support you need to complete your embedded projects.

  • Technical Support Knowledgebase
    More than 1500 technical support questions and answers are available in the Support Solutions Knowledgebase. When a new question arises, it is added to the knowledgebase which is continuously published to the Web. This enables you to get technical support at times when our support staff is unavailable.
  • Application Notes
    Numerous Application Notes help you decipher complex features and implement robust applications.
  • Example Programs and Files
    Utility programs, example code, and sample projects are regularly added to the Download File section of the web site.
  • Discussion Forum
    Post questions, comments, and suggestions to the Keil Software Discussion Forum and interact with other Keil users around the world.

Many of the features of our Technical Support Knowledgebase and Web Site are the results of your suggestions. If you have any ideas that will improve them, please give us your feedback!

Contact Details

If you experience any problems or have any questions about this product, contact one of our distributors or offices for assistance.

In the USA...

Keil Software, Inc.
1501 10th Street, Suite 110
Plano, TX  75074

800-348-8051 - Sales
972-312-1107 - Support
972-312-1159 - Fax
- Sales E-Mail
- Support E-mail 
In Europe...

Keil Elektronik GmbH
Bretonischer Ring 15
D-85630 Grasbrunn

+49 89 456040-0 - Sales
+49 89 456040-24 - Support
+49 89 468162 - Fax
- Sales E-Mail
- Support E-Mail

Copyright © Keil™, An ARM® Company.
All rights reserved.
Visit our web site at

  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.