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

STARTUP.A51 & INIT.A51 FILE INFO

Hi.
I am using uVersion2 IDE. Here after reset, MPU will execute code from reset vector located in Startup.A51 file and after some initialization, it will jump to label named as ?C_START which is defined in Init.A51, where it does some other initialization. If we dont include the Init.A51 in project, then will it automatically include for project ?

If we dont want to use this Init.A51 file and instead of jumping to ?C_START from Startup.A51, we modify this to jump to Main direclt then will it create any proble ?

Thanks.

  • If we dont want to use this Init.A51 file and instead of jumping to ?C_START from Startup.A51, we modify this to jump to Main direclt then will it create any proble ?
    Of course not. Keil add all kinds of code just to make sure their competitors can make things more efficient and drive them out of business.

    When you buy a car, do you remove some of the bolts before you drive it?

    Erik

  • Eric thanks for the reply.

    If we buy a car and if it has unnecessary bolts as per ones point of view that dont require at all, then one will definately remove them.

    Thanks again.

  • "If we dont include the Init.A51 in project, then will it automatically include for project ?"

    Yes.

    "If we dont want to use this Init.A51 file and instead of jumping to ?C_START from Startup.A51, we modify this to jump to Main direclt then will it create any proble ?"

    I'm not certain, but I suspect it should be ok provided, of course, you don't have any explicitly initialised static data.

  • I build my project without INIT.A51. It works fine.

    Be sure all the project programmers -- including the future ones that might replace you -- know that due to the lack of INIT.A51, source code cannot use static C initializers. It would be even better if you could force lint (or the compiler) to produce an error on encountering initializers.

    (The compiler will compile such, but the code won't run correctly if it expects the variable to initialized. That's what INIT.A51 does, after all.)

  • Hi stefan and davis.
    Thank you very much for providing the information. Here, if we dont have any static variable then there will not be nay problem. But if we dont have then we have to initialize it ? is it ?
    What about global variables initialization which are not static ?

  • Again: Here, if we dont have any static variable then there will not be any problem. But if we have then we have to initialize it if we dont want to use INIT.A51. is it ?

    What about global variables initialization which are not static ?

  • The C standard specifies that any global variable which does not have an initializer is initialized to zero. There are several loops, one for each memory space (idata, pdata, xdata, etc), in the STARTUP.A51 file that zero out all of the memory. This code implements the requirement of the C spec that uninitialized variables are zero.

    The compiler takes all of the explicit static initializers and puts them into the code (ROM) area. INIT.A51 copies this region of initialized data to RAM. INIT.A51 implements the C standard feature for initializing global variables.

    If you omit INIT.A51 from your build, then any program which relies on static initializers will not work correctly. You will have to write code that explicitly initiazes variables the way you want them.

    For example, this code will fail miserably if you omit INIT.A51

    U8 lookup[8] = { 7, 6, 5, 4, 3, 2, 1, 0 };
    
    void main (void)
        {
        ...
        translated = lookup[input];
        ...
        }
    

    You'll find in practice that lookup is all zeros (thanks to STARTUP.A51), and not the lookup values you expect. You can omit INIT.A51, but then you have to write code to make sure the variable gets initialized, like this:

    U8 lookup[8];
    ...
    void LookupInit (void)
        {
        U8 data i;
    
        for (i = 0; i < 8; ++i)
            {
            lookup[i] = 7 - i;
            }
        } // LookupInit
    
    ...
    void main (void)
        {
        LookupInit();
    
        translated = lookup[input]; // works only after call to LookupInit();
        }
    

    At some point it will take more code to initialize everything "manually" than it would have to let INIT.A51 copy it all in one block. On the other hand, you might need to be able to initialize a variable on demand, so that you have to write this code anyway. Also, using the initializer means you really have two copies of the value in your total address space (one in code memory for the source for INIT.A51, and one in data memory where the variable actually lives).

    If you omit the initialization loops in STARTUP.A51, then any program which relies on a variable being initialized to zero will not work correctly. The memory will have whatever random values it powers up with.

    If your program initializes all values before they are used by some other means, then you don't need either the code in INIT.A51 or the initialization loops in STARTUP.A51. You will risk bugs every time someone writes code expecting the system to conform to the full C specification and initialize their variables for them per spec. Programmers notoriously forget to initialize their variables. On the other hand, a default value of zero doesn't mean the program will work right anyway. The specification for all variables being initialized to zero is not a security measure, but just a convenience for the prorammer.

    In my case, INIT.A51 didn't help me much because my system has to be able to re-initialize itself without rebooting. Constants I leave in code space. So there weren't any practical uses for initializers that weren't redundant with other parts of the code.

    Initializing large chunks of RAM to zero, on the other hand, cost me many calls to memset, and so it was cheaper to keep STARTUP.A51's loops for that purpose. (Some variables still have to get reset to zero while operating, and so there are still some memset()s.) But the extra boot time isn't important in my case, and the net code size is smaller.

  • "What about global variables initialization which are not static ?"

    Yes, they need the INIT.A51 code.

  • I just come to think of the following:

    if INIT.A51 is not "needed" will it not be "empty?

    If no variables need initialization, what will INIT.A51 look like? just "jmp main" I guess.

    If the above is correct this whole thread is moot

    Erik

  • If no variables need initialization, what will INIT.A51 look like? just "jmp main" I guess.

    INIT.A51 is not a compiler-generated file, so no, it won't change its shape depending on what the actual program uses, and what it doesn't.

    The startup sequence is:

    STARTUP.A51 --> defines ?C_STARTUP at boot address (usually 0), does all initialization independent of the program; finishes by jumping to ?C_START

    INIT.A51: defines ?C_START, carries out static initializations by going through data in segment ?C_INITSEG; finishes by jumping to MAIN.

    If the project doesn't define ?C_STARTUP in a module of its own (e.g. a modified copy of STARTUP.A51), then a pre-compiled version from the C library is pulled in automatically by the linker. Similarly, if that file references ?C_START, but no object in the project defines it, the linker pulls a pre-compiled INIT.A51 from the library.