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).