[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