This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Using target's settings in the program code

Hello, Keil uVision world! :)

Keil uVision project file contains some target's settings, stored as e.g. Device (C8051F340) or DevID (3997). How to use these values in the source text (e.g. for conditionally translation)?

For example:

#if DevID==3997
...
#endif

or

$if (DevID==3997)
...
$endif

Parents
  • Since the Keil tool doesn't have a predefined constant (per Andy statement and not my own research---but Andy is a good authority) that represents the current processor setting, you can create it yourself.

    Each compile configuration uses a target profile, so you can use this as a mechanism to define the processor ID and then use it within the code as needed. Since you would change this profile anyway to use a different micro-controller, this does make sense.

    Each target profile is managed in the "Components, Environments and books" using the "Project Components" tab. Here you can define Project Targets, Groups, and the files for your project. You can have several different target groups using different target processors.

    Under the Keil's IDE Options for Target "C51" Tab you can predefine constants.

    You can, under your target configuration setting, define the "DEVICE_ID 3997" (no quotes) and then test for it within the source code. (or "C8051F340 1" then #ifdef C8051F340)

    Watch the lower part of the tab area under "Compiler control string" and see that what you are typing in, is auto inserted using the compiler directive DEFINE( , ).

    As a general rule though, I don't like IDE specific settings and prefer to control the build process as much as I can within the "controlled source [code]" itself. By having an include file that specifies the processor target, you can define it there as you would normally do anyway.

    If you have source code that depends upon your specific IDE like (Keil's tool suite), then you are limiting yourself and code when/if your company changes over to IAR's tools, or BSO Tasking, etc.

    I do like the fact that Keil has features like:

    /*
    
    The XL51 has some built-in features that are handy to use.
    [Only] the LX51 allocates them if they are used in the final code
    (BL51 doesn't have this feature)
    
    A list class names
    
    bit
    code
    const
    data
    ecode
    hconst
    hdata
    idata
    srom
    xdata
    
    _class-name_S_  The starting address of the class.
    _class-name_B_  The code bank in which the class is stored.
    _class-name_L_  The length of the class in bytes.
    _class-name_E_  The ending address of the class.
    _class-name_T_  The target (execution) address of the class.
    
    */
    // examples of using these pre-defined Keil IDE data allocation information
    // LX51 pre-defines these data-stores (only upon use of it)
    extern unsigned char _code_B_;  //
    extern unsigned char _code_S_;  //
    extern unsigned char _code_E_;  // Ending address of code space
    extern unsigned char _code_T_;  //
    extern unsigned char _code_L_;  //
    
    extern unsigned char _bit_L_;   //
    extern unsigned char _const_L_; //
    extern unsigned char _data_L_;  //
    extern unsigned char _idata_L_; //
    extern unsigned char _xdata_L_; // Length of xdata space
    extern unsigned char _ecode_L_; //
    extern unsigned char _srom_L_;  //
    extern unsigned char _hconst_L_;
    extern unsigned char _hdata_L_; //
    
    extern unsigned char _idata_E_; //
    
    u16 code_length = (u16) &(_code_L_);
    u16 code_bank   = (u16) &(_code_B_);
    u16 code_start  = (u16) &(_code_S_);
    u16 code_end    = (u16) &(_code_E_);
    u16 code_target = (u16) &(_code_T_);
    
    u8 idata_end    = (u8) &(_idata_E_);
    
    u16 bit_length   = (u16) &(_bit_L_  );
    u16 const_length = (u16) &(_const_L_);
    u16 data_length  = (u16) &(_data_L_ );
    u16 idata_length = (u16) &(_idata_L_);
    u16 xdata_target = (u16) &(_xdata_L_);
    u16 ecode_length = (u16) &(_ecode_L_);
    u16 srom_target  = (u16) &(_srom_L_);
    u16 hconst_target= (u16) &(_hconst_L_);
    u16 hdata_length = (u16) &(_hdata_L_);
    


    Other handy Keil specific features are


    // There are two (2) leading and trailing underscore characters ('_')
    // used for the predefined constants. __C51__ // Version number of the compiler (for example, 701 for version 7.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).
    __TIME__ // Time when the compilation was started. (Format: hh:mm:ss)
    __FILE__ // Name of the file being compiled.
    __LINE__ // Current line number in the file being compiled.
    __MODEL__ // Memory model selected: // * 1 for SMALL, // * 2 for COMPACT, // * 3 for LARGE.
    __STDC__ // Defined to 1 to indicate full conformance with the ANSI C Standard.
    __KEIL__ // Defined if Keil is used // example from the 'book'
    char code Compile_date[] = "Compile Date = " __DATE__;
    char code Compile_time[] = "Compile Time = " __TIME__;


    Example of their use:

    #ifndef __KEIL__
        #error    "This source code is highly dependant upon the Keil IDE toolset"
        #message  "NOTE: "
        #message  "Please refer to the Compiler.H file to see how this source code"
        #message  "depends way too heavily on a specific tool suite."
    #endif
    
    #ifdef __KEIL__ // So if the compiler IS Keil, then make sure its the right one
    
    #if (__C51__ < 700) || (__C51__ > 799)      // example right out of the 'book'
        #error "Requires C51 Compiler V7.xx"    // example right out of the 'book'
    #endif
    
    #if (__MODEL__ < 3)
        #warning "This code will not work on any environment that is not set for LARGE"
        #message " NOTE: "
        #message "The code contains a look up table that that is 16K x 8.  Without that"
        #message "table, the code can fit in SMALL: We lost the arguement for run-time"
        #message "calculation versus code size using the LUT... yell at Joe if the"
        #message "CPU oscillator changed from 11.0592MHz to 24MHz as that is the"
        #message "threashold speed needed to convert this code to run-time calcs,"
        #message "and allow the removal of the external memory stores."
    #endif
    
    #endif // end of the "If it was KEIL" conditional
    

    --Cpt. Vince Foster
    2nd Cannon Place
    Fort Marcy Park, VA

Reply
  • Since the Keil tool doesn't have a predefined constant (per Andy statement and not my own research---but Andy is a good authority) that represents the current processor setting, you can create it yourself.

    Each compile configuration uses a target profile, so you can use this as a mechanism to define the processor ID and then use it within the code as needed. Since you would change this profile anyway to use a different micro-controller, this does make sense.

    Each target profile is managed in the "Components, Environments and books" using the "Project Components" tab. Here you can define Project Targets, Groups, and the files for your project. You can have several different target groups using different target processors.

    Under the Keil's IDE Options for Target "C51" Tab you can predefine constants.

    You can, under your target configuration setting, define the "DEVICE_ID 3997" (no quotes) and then test for it within the source code. (or "C8051F340 1" then #ifdef C8051F340)

    Watch the lower part of the tab area under "Compiler control string" and see that what you are typing in, is auto inserted using the compiler directive DEFINE( , ).

    As a general rule though, I don't like IDE specific settings and prefer to control the build process as much as I can within the "controlled source [code]" itself. By having an include file that specifies the processor target, you can define it there as you would normally do anyway.

    If you have source code that depends upon your specific IDE like (Keil's tool suite), then you are limiting yourself and code when/if your company changes over to IAR's tools, or BSO Tasking, etc.

    I do like the fact that Keil has features like:

    /*
    
    The XL51 has some built-in features that are handy to use.
    [Only] the LX51 allocates them if they are used in the final code
    (BL51 doesn't have this feature)
    
    A list class names
    
    bit
    code
    const
    data
    ecode
    hconst
    hdata
    idata
    srom
    xdata
    
    _class-name_S_  The starting address of the class.
    _class-name_B_  The code bank in which the class is stored.
    _class-name_L_  The length of the class in bytes.
    _class-name_E_  The ending address of the class.
    _class-name_T_  The target (execution) address of the class.
    
    */
    // examples of using these pre-defined Keil IDE data allocation information
    // LX51 pre-defines these data-stores (only upon use of it)
    extern unsigned char _code_B_;  //
    extern unsigned char _code_S_;  //
    extern unsigned char _code_E_;  // Ending address of code space
    extern unsigned char _code_T_;  //
    extern unsigned char _code_L_;  //
    
    extern unsigned char _bit_L_;   //
    extern unsigned char _const_L_; //
    extern unsigned char _data_L_;  //
    extern unsigned char _idata_L_; //
    extern unsigned char _xdata_L_; // Length of xdata space
    extern unsigned char _ecode_L_; //
    extern unsigned char _srom_L_;  //
    extern unsigned char _hconst_L_;
    extern unsigned char _hdata_L_; //
    
    extern unsigned char _idata_E_; //
    
    u16 code_length = (u16) &(_code_L_);
    u16 code_bank   = (u16) &(_code_B_);
    u16 code_start  = (u16) &(_code_S_);
    u16 code_end    = (u16) &(_code_E_);
    u16 code_target = (u16) &(_code_T_);
    
    u8 idata_end    = (u8) &(_idata_E_);
    
    u16 bit_length   = (u16) &(_bit_L_  );
    u16 const_length = (u16) &(_const_L_);
    u16 data_length  = (u16) &(_data_L_ );
    u16 idata_length = (u16) &(_idata_L_);
    u16 xdata_target = (u16) &(_xdata_L_);
    u16 ecode_length = (u16) &(_ecode_L_);
    u16 srom_target  = (u16) &(_srom_L_);
    u16 hconst_target= (u16) &(_hconst_L_);
    u16 hdata_length = (u16) &(_hdata_L_);
    


    Other handy Keil specific features are


    // There are two (2) leading and trailing underscore characters ('_')
    // used for the predefined constants. __C51__ // Version number of the compiler (for example, 701 for version 7.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).
    __TIME__ // Time when the compilation was started. (Format: hh:mm:ss)
    __FILE__ // Name of the file being compiled.
    __LINE__ // Current line number in the file being compiled.
    __MODEL__ // Memory model selected: // * 1 for SMALL, // * 2 for COMPACT, // * 3 for LARGE.
    __STDC__ // Defined to 1 to indicate full conformance with the ANSI C Standard.
    __KEIL__ // Defined if Keil is used // example from the 'book'
    char code Compile_date[] = "Compile Date = " __DATE__;
    char code Compile_time[] = "Compile Time = " __TIME__;


    Example of their use:

    #ifndef __KEIL__
        #error    "This source code is highly dependant upon the Keil IDE toolset"
        #message  "NOTE: "
        #message  "Please refer to the Compiler.H file to see how this source code"
        #message  "depends way too heavily on a specific tool suite."
    #endif
    
    #ifdef __KEIL__ // So if the compiler IS Keil, then make sure its the right one
    
    #if (__C51__ < 700) || (__C51__ > 799)      // example right out of the 'book'
        #error "Requires C51 Compiler V7.xx"    // example right out of the 'book'
    #endif
    
    #if (__MODEL__ < 3)
        #warning "This code will not work on any environment that is not set for LARGE"
        #message " NOTE: "
        #message "The code contains a look up table that that is 16K x 8.  Without that"
        #message "table, the code can fit in SMALL: We lost the arguement for run-time"
        #message "calculation versus code size using the LUT... yell at Joe if the"
        #message "CPU oscillator changed from 11.0592MHz to 24MHz as that is the"
        #message "threashold speed needed to convert this code to run-time calcs,"
        #message "and allow the removal of the external memory stores."
    #endif
    
    #endif // end of the "If it was KEIL" conditional
    

    --Cpt. Vince Foster
    2nd Cannon Place
    Fort Marcy Park, VA

Children
  • Cpt. Vince, thank you for detailed info.

    Cpt. Vince wrote:
    Since the Keil tool doesn't have a predefined constant ... you can create it yourself.
    ...
    Each compile configuration uses a target profile...

    Here you can define Project Targets, Groups, and the files for your project. You can have several different target groups using different target processors...

    I use target setings in all my projects. ;)

    Cpt. Vince wrote:
    Under the Keil's IDE Options for Target "C51" Tab you can predefine constants...

    Beacuse of developpment and support many similar projects (in fact, they are "derived" from a few of "roots") differing on miscellaneous functions, I found inconvenient to introduce and check a lot of settings (the same for C and ASM!). Especial for libraries developpment. Therefore my projects have now only one constant defined via IDE: CPU type. :)

    Using of the Keil Configuration Wizard - like "GUI settings dialog" - is more comfortable. IMHO.

    Cpt. Vince wrote:
    As a general rule though, I don't like IDE specific settings and prefer to control the build process as much as I can within the "controlled source [code]" itself. By having an include file that specifies the processor target, you can define it there as you would normally do anyway...

    CPU type is already defined via Keil IDE - why don't use this?

    Cpt. Vince wrote:
    If you have source code that depends upon your specific IDE like (Keil's tool suite), then you are limiting yourself and code when/if your company changes over to IAR's tools, or BSO Tasking, etc.
    ...

    Sure. But I can define "manually" the same constants, #defines etc. by using other tools too - without loss of compatibility. Or nearly without...

    Language extensions (e.g., using C-Preprocessor directives in ASM source code) could cause more problems by code porting. But these extensions are comfortable! Schould one not use they and stay in 197..? ;)

    So every developper find own way, own style etc. IMHO.

    P.S. Sorry for my english...

  • The answer from Keil:

    currently this information cannot be directly accessed by the Compiler/Assembler. It is indented to be used by programming utilities and the help systems (by querying the environment variables).