• Global Initializers

    From bill rowe@21:1/5 to All on Mon Nov 2 12:38:21 2020
    My 1802 target for LCC just defines and initializes globals in the static assembly so that, for example, if you restart it, the original initializers are not refreshed. Is that standard C?

    I'm working now on a target that splits the code off for ROM and I need a way to initialize RAM globals.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Keith Thompson@21:1/5 to bill rowe on Mon Nov 2 13:29:07 2020
    bill rowe <bill.rowe.ottawa@gmail.com> writes:
    My 1802 target for LCC just defines and initializes globals in the
    static assembly so that, for example, if you restart it, the original initializers are not refreshed. Is that standard C?

    I'm working now on a target that splits the code off for ROM and I
    need a way to initialize RAM globals.

    I'm not certain what behavior you're describing.

    This program:

    #include <stdio.h>
    int global = 10;
    int main(void) {
    printf("%d ", global);
    global = 20;
    printf("%d\n", global);
    }

    must print "10 20" every time it's executed. If it prints "10 20"
    the first time and "20 20" the second time, the implementation is
    not conforming. (Replace printf by some other mechanism if the
    target doesn't support stdio.)

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    Working, but not speaking, for Philips Healthcare
    void Void(void) { Void(); } /* The recursive call of the void */

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bill rowe@21:1/5 to Keith Thompson on Tue Nov 3 04:17:37 2020
    On Monday, November 2, 2020 at 4:29:09 PM UTC-5, Keith Thompson wrote:
    bill rowe <bill.row...@gmail.com> writes:
    My 1802 target for LCC just defines and initializes globals in the
    static assembly so that, for example, if you restart it, the original initializers are not refreshed. Is that standard C?

    I'm working now on a target that splits the code off for ROM and I
    need a way to initialize RAM globals.
    I'm not certain what behavior you're describing.

    This program:

    #include <stdio.h>
    int global = 10;
    int main(void) {
    printf("%d ", global);
    global = 20;
    printf("%d\n", global);
    }

    must print "10 20" every time it's executed. If it prints "10 20"
    the first time and "20 20" the second time, the implementation is
    not conforming. (Replace printf by some other mechanism if the
    target doesn't support stdio.)

    --
    Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
    Working, but not speaking, for Philips Healthcare
    void Void(void) { Void(); } /* The recursive call of the void */

    well, for some definition of "every time it's executed" ;-) In a small computer where there's no operating system, the C program gets loaded by itself and the loaded binary has the initialized variables in it. If, after it has run and printf'd, you
    reset the computer to run it again without reloading the binary, it will print 20 twice.

    That's fine if you know about it, the real kicker is if the code has to go in ROM and the data in RAM so it's only *ever* loaded once. I need a mechanism to get my LCC generated program to copy init values to the RAM "*every* time it's executed" or
    restarted. I can work around it by init'ing the globals at the top of main but i'm hoping someone has a more integrated approach.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Keith Thompson@21:1/5 to bill rowe on Tue Nov 3 14:48:29 2020
    bill rowe <bill.rowe.ottawa@gmail.com> writes:
    On Monday, November 2, 2020 at 4:29:09 PM UTC-5, Keith Thompson wrote:
    bill rowe <bill.row...@gmail.com> writes:
    My 1802 target for LCC just defines and initializes globals in the
    static assembly so that, for example, if you restart it, the original
    initializers are not refreshed. Is that standard C?

    I'm working now on a target that splits the code off for ROM and I
    need a way to initialize RAM globals.
    I'm not certain what behavior you're describing.

    This program:

    #include <stdio.h>
    int global = 10;
    int main(void) {
    printf("%d ", global);
    global = 20;
    printf("%d\n", global);
    }

    must print "10 20" every time it's executed. If it prints "10 20"
    the first time and "20 20" the second time, the implementation is
    not conforming. (Replace printf by some other mechanism if the
    target doesn't support stdio.)

    well, for some definition of "every time it's executed" ;-) In a small computer where there's no operating system, the C program gets loaded
    by itself and the loaded binary has the initialized variables in it.
    If, after it has run and printf'd, you reset the computer to run it
    again without reloading the binary, it will print 20 twice.

    That's fine if you know about it, the real kicker is if the code has
    to go in ROM and the data in RAM so it's only *ever* loaded once. I
    need a mechanism to get my LCC generated program to copy init values
    to the RAM "*every* time it's executed" or restarted. I can work
    around it by init'ing the globals at the top of main but i'm hoping
    someone has a more integrated approach.

    Hmm. I've never worked with that kind of bare-metal implementation.

    Here's what the C standard says about program startup for freestanding implementations:

    In a freestanding environment (in which C program execution
    may take place without any benefit of an operating system),
    the name and type of the function called at program startup are
    implementation-defined. Any library facilities available to a
    freestanding program, other than the minimal set required by
    clause 4, are implementation-defined.

    The effect of program termination in a freestanding environment
    is implementation- defined.

    (The "function called at program startup" is "main" in a hosted implementation.)

    Objects with static storage duration ("globals") are initialized
    during program startup. If "program startup" effectively happens
    only once, then yes, that's a problem. It would be nice if there
    were some implementation-specific method to reload everything as
    if the program were starting up again. If not, you'll probably
    just have to reinitialize stuff manually.

    Does "restarting" the application execute an entry point function, corresponding to "main" in a hosted environment? If so, I'd normally
    expect globals to be initialized before that function begins.
    If it doesn't, I'd argue that the implementation is non-conforming. Unfortunately, knowing that doesn't do you much good.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    Working, but not speaking, for Philips Healthcare
    void Void(void) { Void(); } /* The recursive call of the void */

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Fred J. Scipione@21:1/5 to All on Wed Nov 4 02:57:29 2020
    In article <be843f93-e097-4513-a6b6-d005f808d442n@googlegroups.com>, bill.rowe.ottawa@gmail.com says...

    My 1802 target for LCC just defines and initializes globals in the
    static assembly so that, for example, if you restart it, the
    original initializers are not refreshed. Is that standard C?

    I'm working now on a target that splits the code off for ROM and I
    need a way to initialize RAM globals.

    For a stand-alone system it is not so much that the compiler does this,
    as it is that you need to coordinate the compiler generated modules
    with the linker and (custom?) libraries to get things where you want
    them in ROM and RAM. You may need a 'program-launcher' routine (for
    C run-time start-off / _crtso_()) like the following illustration -

    ---------------------------8>< snip here ---------------------------
    #include "ROM_DEFS.h" // where ram_init_image blob is in ROM
    #include "RAM_DEFS.h" // RAM init and zeroed bases & lengths

    extern void main(void); // for stand-alone

    void _crtso_(void) {
    sys_start:
    // power-up/reset comes here w/o stack call, frame, etc.

    // may need to use assembly code to init stack pointer here

    // here, all args are compile/link time constants -
    memcopy(&init_ram_base, &ram_init_image, RAM_INIT_LENGTH);
    memset(&zero_ram_base, 0, RAM_ZERO_LENGTH);

    main(void); // perhaps sets-up interrupts
    exit(void); // does not return

    // never reached, so no return
    }

    void exit(void) {
    while(1) ; // interrupts still running forever?

    // never reached, so does not return
    }
    ---------------------------8>< snip here ---------------------------

    You need to put all your initiaized (RAM) globals into one (separate)
    module, and compile/link it into a binary blob image to be placed
    into ROM. Putting all your default-zeroed globals into their own
    module helps make them into a contigious RAM block for memset().
    You have to cover your own globals, and any in libraries too.
    Code and read-only globals might be linked into ROM.

    LCC needs you to do this manualy. Other compilers like SDCC try to
    help you to specify them in the program source.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)