ARM Technical Support Knowledge Articles

How do I fill unused ROM with specific content?

Applies to: DS-5

Scenario

In firmware development, some applications require the unused part of a fixed-size ROM to be filled with specified content, for example 0xFFFFFFFF

It is easy to define a ROM region using a scatter file as shown in Example 1. However, it can sometimes be tricky to define a fixed-size ROM. A fixed-size ROM is typically used to store code and/or constant data sections. The size of the code and/or data content might change during development which would also affect the size of the unused memory that needs to be filled. 

Example 1: A typical simple scatter file.

#! armcc –E

#define ROM_ADDRESS 0x00004000
#define ROM_SIZE 0x00001000

LR_ROM ROM_ADDRESS ROM_SIZE ; A ROM region
{
    ER_ROM +0 ROM_SIZE ; A ROOT region
    {
        * (.text_rom) ; Put section “.text_rom” here

        * (.data_rom) ; Put section “.data_rom” here

    }
}

In Example 1, for a given ROM with a fixed size, the memory that stores the content in .text_rom and .data_rom is used memory, and the remaining part is unused memory.

The ROM_SIZE specified in this scatter file only sets the upper limit of the content size for the load region LR_ROM and the execution region ER_ROM. In other words, ROM_SIZE is the maximum size of the ROM. The size of ER_ROM can be smaller than the upper limit, and the linker does not by default fill or pad the remaining part of the ROM. 

Answer

To define a fixed-size ROM and fill the unused part with specified content, use either of the following methods:

Method 1 - Using the FILL execution region attribute

The FILL attribute creates an empty region with a designated size and fills it with a specified value. 

Considering the case in Example 2 below, you must know the actual length of the ER_ROM region to define the correct size for the ER_ROM_UNUSED region.

The ImageLength() function can be used to return the size of a given execution region. To calculate the region size of ER_ROM_UNUSED, the result of ImageLength(ER_ROM) must be subtracted from the ROM size. In Example 2, the macro ROM_FILL_SIZE is defined to improve the readability of the scatter file. 

Example 2: Filling unused ROM using the FILL attribute.

#! armcc –E
#define ROM_ADDRESS 0x00004000
#define ROM_SIZE 0x00001000

#define ROM_FILL_SIZE   (ROM_SIZE - ImageLength(ER_ROM))

LR_ROM ROM_ADDRESS ROM_SIZE ; A ROM region 
{
    ER_ROM +0             ; A ROOT region 
    {

            * (.text_rom)           ; Put section “.text_rom” here

            * (.data_rom)           ; Put section “.data_rom” here

    }

    ; Fill the unused ROM space with 0xFFFFFFFF
    ER_ROM_UNUSED +0 FILL 0xFFFFFFFF ROM_FILL_SIZE
    {}
}

Note: By default, sections within execution regions are aligned to 4 bytes. Padding bytes are added when necessary. Therefore, the result of ImageLength() is always a multiple of 4 in this case. You can use the ALIGN attribute to increase the alignment constraint from 4 to 8 or other specified values. The specified value must be a positive power of 2. For details about the ALIGN attribute, see the ARM Compiler armlink User Guide.

Method 2 - Using the FIXED attribute

In some cases, signatures or CRC checksums must be added to the end of the ROM. It is simple to fill the unused ROM while adding signatures or CRC checksums by using the FIXED attribute. 

To add signatures or CRC checksums to the end of the ROM, define a dedicated ROOT region, like the ER_ROM_SIGN region shown below in Example 3. The FIXED attribute is used here to:

  • Ensure that the execution address and the load address are the same.
  • Inform the linker to add padding between ER_ROM and ER_ROM_SIGN, if necessary, because they are in the same load region. 

In addition, you can specify the padding value using the PADVALUE attribute. 

Example 3: Adding signatures or CRC Checksums while also filling the unused ROM.

#! armcc –E

#define ROM_ADDRESS 0x00004000
#define ROM_SIZE 0x00001000

// Assumes that the size of the signature or CRC checksum is 4
#define ROM_CRC_ADDRESS (ROM_ADDRESS + ROM_SIZE – 4)

LR_ROM ROM_ADDRESS ROM_SIZE ; A ROM region
{
    ER_ROM +0 ; A ROOT region
    {
        * (.text_rom) ; Put section “.text_rom” here

            * (.data_rom) ; Put section “.data_rom” here

    }

    ER_ROM_SIGN ROM_CRC_ADDR FIXED PADVALUE 0xFFFFFFFF UNINIT
    {
    
    * (.rom_sign)

    }
}

As shown below in Example 4, you can put an uninitialized variable such as c_wROMCRC32 in the .rom_sign section, and use this to check ROM integrity and validity.

Example 4: ROM validation with CRC checksums preserved at the end of the ROM.

/* Placeholder of CRC32 for ROM */
__attribute__((section(“.rom_sign”), zero_init))
unsigned int c_wROMCRC32;

/* A function that calculates the crc32 value of the ROM content */
extern unsigned int calculate_rom_crc(void);

int is_rom_valid(void)
{
    /* calculate and compare */
    if (c_wROMCRC != calculate_rom_crc32()) {
    
    return -1;

    }

    return 0;
}

Note: Signatures and CRC checksums are typically calculated or programmed by customer tools and not by compilers. To prevent variables like c_wROMCRC32 from being initialized at link time:

  • Place the variable in its own section by decorating the source code with the section attribute, for example the use __attribute__((section(“.rom_sign”), zero_init)).
  • Place the section named .rom_sign in an execution region marked with the UNINIT attribute.

For details about the FILL, EMPTY, FIXED, and PADVALUE execution region attributes, see the ARM Compiler armlink User Guide.

Related information 

Rate this article

[Bad]
|
|
[Good]
Disagree? Move your mouse over the bar and click

Did you find this article helpful? Yes No

How can we improve this article?

Link to this article
Copyright © 2011 ARM Limited. All rights reserved. External (Open), Non-Confidential