GCC and AVR external memory initialisation

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am just designing a system using AtMega 2560 with 32k external RAM. I have read about changing the various section names to allocated variables in the external memory area so I see it is possible.

My question is this:-
If I allocate the initialised data segment to external memory, does cstart actually initialise it ?. It would have to 'know' something of my hardware configuration in order to configure and use the external bus.

Does anyone know if this works 'out of the box' or do I need to customise the cstart code somehow?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No it's your responsibility. The usual idea is to put something into .init3. As you can read in the manual:

http://www.nongnu.org/avr-libc/u...

The even numbered .init sections are used by the library while the odd numbered ones are there for you to intercept startup operation. As it also tells you the .data ad .bss setup code are in .init4 so you want to get in before that if you need to switch some external memory to be visible before it's used for .data or .bss. Hence .init3 being a good choice.

So something like:

__attribute__((section(".init3"))) void set_xmem(void) {
  // setup up XMEM registers
}

however there is a small additional complexity. You effectively want the code to "fall through" this code. So the compiler may provide code in .init2 then you want it to fall into set_xmem(), execute that then fall into .init4. As such you don't want set_xmem() to be CALLd and you don't want it to RET at the end. To achieve this you use "naked" so:

__attribute__((naked, section(".init3"))) void set_xmem(void) {
  // setup up XMEM registers
}

Now the only thing about "naked" is that it does not preserve what it uses (no PUSH/POP), also being in the .init3 position there is no .data or .bss so it cannot make use of globals either. So you basically want it to be restricted to just using registers. The only one it must avoid corrupting is R1 which must still contain 0 when it finishes. It will probably be enough to simply say:

{
  XMEM = 37;
}

or whatever as the body of the function as that will likely become an LDI and OUT (or STS) but check the generated code that this is the case.

A search for "external memory .init3" will probably prove fruitful.

Last Edited: Fri. Mar 15, 2013 - 02:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

excellent reply !. Thanks for all the information and links. I appreciate it !

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Even if you place/relocate some data in your custom section, that does not imply a standard startup code initializes it for you (like with r1, SREG_I, .data or .bss).
But as AVRs are +- the same (with typically only one contiguous .data and one .text section) then a default start-up code is ok for most of the freaks.

In your task this boils down to a problem of a tailored start-up code and custom memory layout. If you would like to know how to maintain multiple sections then I suggest you should review for example ARM Cortex startup code from LPCXpresso. Some ARMs have several RAM sections (like LPC1769) and exactly this problem is solved there so I think a ctrl+c/v with minor tweaks would do.

Then it is enough to:

void foo(void){
__attribute__((section(".external_data")))
static uint16_t static_of_foo=0xabbe;
...
}

and static_of_foo will be assigned a proper value at start-up.
You can also assign variables/code from some specific library or file to some section if you like. Then no need to explicitly __attribute__((section(".external_data"))) every time you declare a variable.

No RSTDISBL, no fun!