9.1.5 Tip #5 Constants in Program Space

Many applications run out of SRAM, in which to store data, before they run out of Flash. Constant global variables, tables or arrays which never change, should usually be allocated to a read-only section (Flash or EEPROM on 8-bit AVR). By this way we can save precious SRAM space.

In this example we don’t use C keyword "const". Declaring an object "const" announces that its value will not be changed. "const" is used to tell the compiler that the data is to be "read-only" and increases opportunities for optimization. It does not identify where the data should be stored.

To allocate data into program space (read-only) and retrieve them from program space, AVR-Libc provides a simple macro "PROGMEM" and a macro "pgm_read_byte". The "PROGMEM" macro and "pgm_read_byte" macro are defined in the <avr/pgmspace.h> system header file.

The table below shows how we save SRAM by moving the global string into program space.

Table 9-6. Example of Constants in Program Space
Constants in Data SpaceConstants in Program Space
C source code
#include <avr/io.h>
uint8_t string[12] = {"hello world!"};
int main(void)
{
UDR0 = string[10];
}
#include <avr/io.h>
#include <avr/pgmspace.h>
uint8_t string[12] PROGMEM = {"hello world!"};
int main(void)
{
UDR0 = pgm_read_byte(&string[10]);
}
AVR Memory Usage

Program: 122 bytes (1.5% Full)

(.text + .data + .bootloader)

Data: 12 bytes (1.2% Full)

(.data + .bss + .noinit)

Program: 102 bytes (1.2% Full)

(.text + .data + .bootloader)

Data: 0 bytes (0.0% Full)

(.data + .bss + .noinit)

Compiler optimization level-Os (Optimize for size)-Os (Optimize for size)

After we allocate the constants into program space, we see that the program space and data space are both reduced. However, there is a slight overhead when reading back the data, because the function execution will be slower than reading data from SRAM directly.

If the data stored in Flash are used multiple times in the code, size is reduced by using a temporary variable instead of using the "pgm_read_byte" macro directly several times.

There are more macros and functions in the <avr/pgmspace.h> system header file for storing and retrieving different types of data to/from program space. Refer to the AVR-Libc User Manual for more details.