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

Smart Linking

I am trying to make a SW developped with Metrowerks/Hiware on HC05 to work with 8051.
The SW currently needs around 60kb, is very modular and has many options and customizations depending on the customer requirement. In Metrowerks case, the linker has smart linking possibility:

The linker file is *.PRM and list the objects files to link.
If the object file is followed by a "+", all the functions, constant, variables will be placed and mapped in the MCU. (like KEIL)

If there is no "+", the linker will REMOVE automatically functions, rom strings, ram global variables AUTOMATICALLY. The linker tree dependencies can also manage constant function pointers.

Is there a way to do something similar and automatic in KEIL environment?

Otherwise, the cumbersome way is to wrap all C functions like this:

#ifdef My_Function
void My_Function(void)
{
...
}
#endif

And in the header file, comment out the function declaration.... making the source code less readable.

Ideas? Tricks?

Thanks!

  • How about the "Include in Build" in the uVision Project Options?

  • The Keil linker cannot break up a single source file, which becomes a single segment, and remove some but not all of the functions in that file. It's easy enough to include or not include a source file, but not so easy to include part of a file.

    For example, suppose you have two targets which share a hardware access layer. One of them doesn't need all of the function calls the other does. If you implement the abstraction layer in one file, then you have a lot of dead code in one target but not the other, which not only wastes code space but causes problems for the overlay analysis. You can break the file into two pieces in this particular instance, but this is maintenance-intensive during development as one target or another adds and deletes functionality. And breaking up the file into subsets simply doesn't scale with increasing numbers of targets with overlapping requirements.

    The usual suggestion is to put every function into its own file, but this leads to namespace clutter, it forces you expose functions that could be static (and thus wind up with clients you don't expect using the "internal only" functions), and generally destroys the programmer's ability to organize code into modules. Functions are grouped into files for logical, high-level reasons that have to do with application structure and not just correctness or linkage.

    This limitation of the Keil tools is one of the more painful ones for projects that aren't a simple one-to-one mapping from a single executable to one simple board, but involve any sort of shared code, reused hardware, and/or multiple targets.

  • I am building ~27 different versions by using a .bat builder. In various ways it defines program switches and configuration values and selects files to rename (e.g. rename converta or convertb or convertc to convert which is the module the compiler compiles). It works very well. The IDE has a definite shortcoming in this respect.

    Erik

  • it defines program switches

    The original poster was trying to avoid conditional compilation. I'd prefer not to clutter the code with lots of #if's around individual functions to do the linker's job, myself.

    But your suggestion is well taken. That sort of system is indeed the ultimate endpoint when many targets or versions share the same file. Either you break the file into separate .c's to get separate segments, or you put in #if's to selectively omit parts of the one .c file when you compile it.

    Dead code (and variable) elimination is near the top of my wish list for the Keil tools.

    It's always struck me as a bit odd that the linker doesn't make more of an effort in this regard, given how thorough the optimizations usually are, and especially given that 8051 applications are typically extremely resource sensitive.

  • That sort of system is indeed the ultimate endpoint when many targets or versions share the same file. Either you break the file into separate .c's to get separate segments, or you put in #if's to selectively omit parts of the one .c file when you compile it.

    Either...
    The trick, as I see it, is to do both.

    Where a piece of code end up with 471 #ifdefs it is better to make two or more .c files, whereas when a 1000+ line file only has a few #ifdefs, that is the better solution. Another way to unclutter is, when you have a often repeated variance, to make that a macro and example:

    you have two different versions of a board, one with a 1232 type supervisor, the other using the internal supervisor.

    You will then see, all over your code

    #ifdef VER1
    PORT12 = TRUE;
    PORT12 = FALSE;
    #else
    WDSFR = 0xA5;
    WDSFR = 0x5A:
    #endif
    
    Instead, move that to a macro
    #define M_KICK_THE_DOG #ifdef VER1            PORT12 = TRUE;         PORT12 = FALSE;        #else                  WDSFR = 0xA5;          WDSFR = 0x5A:          #endif
    
    and the abibe sequence becomes
    M_KICK_THE_DOG
    no clutter
    

    When the above has been "macronized" your code will become moch less cluttered.

    Erik

  • I had no idea that wirh {pre} used the backslash woulkd be interpreted

    Erik

  • regarding optimizations, do the two different linker versions LX51 and BL51 make any difference?

    the LX51 Enhanced Linker overview page gives various improvements over the "classic" BL51, but it does not say much things about code improvement, apart from the "Linker Code Packing" feature.

    thank you very much in advance,
    Pascal.

  • Linker code packing makes a huge difference. It's well worth using if you're short on code space.

  • There is a (currently undocumented) new directive in LX51: REMOVEUNUSED. It removes unused functions/segments in the generated output file.

    This feature exists in C51 V7.20 and is currently in evaluation/testing. In case that you find problems email to: support.intl@keil.com