initializing memory before/after main()

Dear all,

I am using an Analog Devices DSP from the old days (ADSP21020) and the g21k toolset (even though the VisualDSP would do exactly the same in this respect). When using the runtime header, the vendor provides three calls to setup the hardware, the environment and the processor prior to the execution of the main() program. The mechanism is very simple: the reset vector table looks like this:

CALL ___lib_setup_hardware; CALL ___lib_setup_processor; CALL ___lib_setup_environment; JUMP _main (DB);

When using the mem21k utility after linking (you can opt out in case you need to use the loader utility ldr21k which produces a bootloader and takes care of memory initialization), the segment seg_init will contain the necessary information that is needed to configure the memory during the ___lib_setup_processor call.

Since my system has already a boot loader and the way is done is such that to run my main() application it would copy it from flash and then jump to a specific location, I have no way to perform the memory initialization before my main() is called. What I still can do is to call ___lib_setup_processor (and maybe the others as well) as first instruction(s) in my program. This will lead to initializing the memory after the main() is called but before any memory is used. I would like to know if there is any caveat with this approach and if there's something I need to take care about that goes beyond these library calls.

Certainly I may as well take care about memory initialization explicetely, in my program, without any need to care about seg_init.

Any suggestions/ideas are appreciated.

Al

Reply to
alb
Loading thread data ...

As a minimum you must ensure the stack that main() is going to use is setup and configured before main() is called - and then that none of the initialisation functions you explicitly call from main() change the stack configuration - or write over the stack frame that, by that point, will already be in use by main().

Regards, Richard.

  • formatting link
    Designed for Microcontrollers. More than 7000 downloads per month.
Reply to
FreeRTOS info

[...]

At the moment the main is called I believe the stack is configured for the loader which was running before the 'jump to main'. At this point, since there's no need to go back to the loader I believe I can re-initialize the stack from scratch with the lib_setup_environment call which should do the job.

The beginning of my main will look like this then:

void main (void) {

SETUP_HWR(); // setup hardware (cache, irptl and memory banks) SETUP_PRO(); // setup processor (registers, modes and memory) SETUP_ENV(); // setup environment (stacks, errno, heaps, rand, interrupts // exit and arguments)

... }

Where SETUP_HWR/PRO/ENV are defines like:

#define SETUP_HWR() asm("CALL ___lib_setup_hardware;") #define SETUP_PRO() asm("CALL ___lib_setup_processor;") #define SETUP_ENV() asm("CALL ___lib_setup_environment;")

Even though the main is running, the stack should be empty, as well as the heap, the registers and all the rest. Have I understood your concerns correctly?

Reply to
alb

It is a bad idea to do initializations in non-standard way. It could create unforeseen complications. The constructors of static objects must be called before main(). The compiler optimizer might rearrange the beginning of main() in unexpected way. The library initialization can destroy the stack of main itself. The debugger might expect the environment to be set up in a certain way before main(). A programmer could edit out some cryptic calls.

Rewrite the startup code once forever so the initializations would be called in prescribed manner.

Vladimir Vassilevsky DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

That will probably work if main does not define any variables. If it does (even if occurs in the text after all the SETUP_xxx() functions) then when you change the stack pointer those variable locations will be toast. Depending on your optimizations, they may already have something in them, too.

--
Tim Wescott
Control system and signal processing consulting
www.wescottdesign.com
Reply to
Tim Wescott

Vladimir Vassilevsky writes: [...]

I understand that doing initialization in non-standard way is very bad idea and I wouldn't have done it if I had a choice. Unfortunately I don't have any way to change the way the code jumps to the main. This part is written in a protected area of the flash and cannot be changed.

I can say that from the assembly code produced by the compiler the first three calls are as expected, no funny rearrengement and/or optimization. If the static objects need to be constructed before the main is called then I have no choice but avoiding the usage of static objects.

For what concerns the debugger the answer is easy, I don't use one (maybe unwise, but not yet convinced).

Worries about a programmer editing out those details can be solved by documentation and/or comments.

I don't want to defend the approach, my aim is to be aware of what are the consequences and act accordingly.

Well indeed I can think of an additional segment of code which can be located in the place where the main was supposed to be and move the main segment somewhere else. In this way I can call the initialization function before the main is called (how about that).

Reply to
alb

In descending order of desirability/safety:

1: Fix your boot loader so that it either does the requisite setup, or so that it calls a "pre_main" function that you write (in assembly) to do the setup and call main. 2: Write main in assembly to do the "pre_main" function mentioned above. 3: Write main in C, but put _nothing_ into it except for those three function calls you have mentioned. 1 is the right solution. 2 is a kludge. 3 is a really desperate kludge.
--
Tim Wescott
Control system and signal processing consulting
www.wescottdesign.com
Reply to
Tim Wescott

That would be a very good way to do it, IMHO. Just edit the 'standard' startup code so that it's entry point is where the boot code jumps on startup, and go from there.

--
My liberal friends think I'm a conservative kook.
My conservative friends think I'm a liberal kook.
Why am I not happy that they have found common ground?

Tim Wescott, Communications, Control, Circuits & Software
http://www.wescottdesign.com
Reply to
Tim Wescott

Looking at the asm generated by the compiler is the only real way of knowing what the environment expects. For example, ignoring the stack pointer, where is the frame pointer pointing before main() calls another function that is going to attempt to set up its own stack frame? What happens when the compiler implementation changes? Etc.

Also take care about the implementation of your initialisation routines

- do they rely on anything? Some systems will set up a temporary environment for the initialisation code, then scrub it before setting up the environment for main().

All things considered, it might (probably will) work, but you would be better off using functions as they are intended to be used, or writing your own versions of them.

Regards, Richard.

  • formatting link
    Designed for Microcontrollers. More than 7000 downloads per month.
Reply to
FreeRTOS info

I always forget to mention that...

--
Tim Wescott
Control system and signal processing consulting
www.wescottdesign.com
Reply to
Tim Wescott

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.