I need to place a chunk of data in its own page in flash memory, so I can erase and
reprogram that page without erasing anything else. How can I do that?
This is a typical requirement for an application with large calibration tables.
There are two ways to deal with this. You can use a custom linker script, or special
command line arguments to the linker. In either case you will want to tag the items to
be placed in your special area, so the linker can identify them. the following illustrates
how to do this:
#define __special_area__ __attribute__((section(".specialarea")))
void __special_area__ special_routine(int x, float y);
const __special_area__ int my_const = MY_VALUE;
|
The attribute "__special_area__" may be used with any other attributes in defining routines and
data. At link time, the linker will associate all these with the section ".specialarea".
Either your custom linker file, or command line parameters must define this section.
The easiest way to make a custom linker script is to start from the standard one
for the device you are using. You can adjust the boundaries of the existing sections, and
add new ones to lay out your code and data any way you want in memory. The linker
script language is defined in the documentation for binutils. A compiler command such as:
$ msp430-gcc -Wl,--section-start -Wl,-T linker_script.x [other options and files]
|
Specifies that the customer linker script "linker_script.x" should be used in place of the
default one.
For the simple definition of one special section, it may be easier to just define that
section on the command line with a command such as:
$ msp430-gcc -Wl,--section-start -Wl,.newsection=0xd400 [other options and files]
|
which will place .newsection at address 0xd4000. Although this will place objects where you
want them, it may not reliably fulfill your requirement. it will not ensure that nothing else
goes in the relevant page of the flash memory, which would cause trouble if you need to erase
that page. Defining your data to be the exact size of one or more flash memory pages, and
forcing that data to start at the required page boundary will be reliable. The following
example uses a union to ensure the overall size of your data block is well known:
#define __special_area__ __attribute__((section(".specialarea")))
const __special_area__ union
{
char force[512];
struct
{
int a;
int b;
char c[10];
float d;
};
} my_erasable_data_area;
|
Bear in mind that startup code (if linked) will start from the ROM's first address. Its
size is 0x40 (including _reset_vector__(), _unexpected_() and _unexpected_1_(), providing
last two are not redefined in your code).