[Icc-avr] Re: Doubts using external memory variables

David Brown david_brown at hotpop.com
Tue Oct 30 07:19:02 PST 2007


Guillermo Megía Palma wrote:
> Hi,
> 
> Thanks Steven for your answer.
> I have told the compiler about the external memory, so I don´t have to
> control the bus (I have set the bit that enables the External SRAM in the
> MCUCR register of the ATMega 128).
> I want to allocate some variables in external memory and others in internal
> one, not all of them in one specific memory (my external memory has a
> back-up battery, so I want to save there some variables to not lose them if
> I turn off my system). Moreover, it isn´t important for me the address
> assigned by the compiler to a variable in external memory. I only want the
> compiler to avoid variables overlaps.
> 
> Regards,
> 
> Guillermo Megía
> 

If you declare your variables normally, then they will be initialised at 
startup whether they are in external memory or internal memory.  Thus 
you will lose all the values that had been held by the battery back-up.

Once you have figured out a way to solve this (I can't remember if 
iccavr has a way to specify global data with no initialisation), you'll 
hit another problem - every time your layout in the external memory 
changes (as might happen with a re-link of the program, and certainly if 
external variables are added or removed), your updated program will see 
a mixture of valid and invalid data in the memory.  You'll also have to 
figure a way to tell if the variables have been initialised to sensible 
default values, or if it is a new and blank ram, random ram data, or 
data from another program version.  Your situation is very similar to 
data in an eeprom.

Clearly, you're going to have to think a little about the consequences 
of using battery-backed memory, and what you really want your code to do.

One way to handle this is to have a dedicated module to handle the 
battery-backed area, looking something like this:

// batmem.h
#ifndef batmem_h__
#define batmem_h__

#include ....

typedef struct {
	uint32_t keyStamp;
	uint16_t dataVersion;

	uint8_t counter;
	uint8_t logger;
	// ... all your external data goes here
} batmemLayout;
typedef batmemLayout *pBatmemLayout;

#define pBatmem ((pBatmemLayout) 0x8000)	// Fixed address

extern void initBatMem(void);

// ------

// batmem.c
#include "batmem.h"

#define currentDataVersion 2		// Increment with each change
#define stamp 0x1948a8c1		// Could be anything

static void resetBatMem(void) {
	pBatMem->counter = 0;		// Initialise all the data
	pBatMem->logger = 0;
	pBatMem->dataVersion = currentDataVersion;
	pBatMem->keyStamp = stamp;
}

static void upgrade0to1(void) {
	// Perhaps this is not worth the effort - use defaults
	resetBatMem();
}

static void upgrade1to2(void) {
	// Perhaps "logger" was added here - ensure it has valid data
	pBatMem->logger = 0;
	pBatMem->dataVersion = 2;
}

void initBatMem(void) {
	if (pBatMem->keyStamp != stamp) {
		resetBatMem();
	} else {
		if (pBatMem->dataVersin == currentVersion) {
			return;		// valid data
		};
		if (pBatMem->dataVersion == 0) {
			upgrade0to1();
		};
		if (pBatMem->dataVersion == 1) {
			upgrade1to2();
		};
		// ... as needed
	}
}



More information about the Icc-avr mailing list