11.7 Read-only Data
Read-only data sections are located in program memory, but are defined and accessed just like data memory. They are useful for storing constant tables that are too large for available data memory. The C compiler creates a read-only section named .const
when the -mconst-in-code
option is specified.
Access to read-only data sections is provided by means of the PSV window, or the EDS window. In either case, a reference to the read-only data is resolved to a data address within the PSV or EDS window.
C programmers can use the space
attribute to allocate variables in read-only data sections. Access to such variables can be
managed automatically by the compiler, or by explicit application code. For additional
information on using read-only variables in C, refer to MPLAB® XC-DSC C
Compiler User’s Guide (DS-50003589), section 11.3.4 “Changing Program Memory
Variable Allocation.”
The psv
section attribute is used to designate read-only data sections in assembly language. The contents of read-only data sections may be specified with data directives, as shown in the following assembly source example:
.section rdonly,psv
L1: .byte 1
L2: .byte 2
In this example, section rdonly
will be allocated in program memory. Both byte constants will be located in the same program memory word, followed by a pad byte. Unlike other sections in program memory, read-only sections are byte addressable. Each label is resolved to a unique address that lies with the PSV or EDS address range.
The linker allocates read-only sections such that they do not cross a page boundary. Therefore, a single setting of the page register will access the entire section. A maximum length restriction is implied; the linker will issue an error message if any read-only data section exceeds 32 Kbytes. Only the least significant 16 bits of each instruction word are available for data storage (bits 16-23). The upper byte of each program word is filled with 0x0 or another value specified with the --fill-upper
option. None of the p-variant assembler directives (including .pbyte
and .pword
) are permitted in read-only data sections.
The following examples illustrate how bytes in read-only sections may be accessed:
; example 1
mov #psvpage(L1),w0
mov w0,PSVPAG ; set page register
mov #psvoffset(L1),w0
mov #psvoffset(L2),w1
mov.b [w0],w2 ; load the byte at L1
mov.b [w1],w3 ; load the byte at L2
; example 2
mov #edspage(L1),w0
mov w0,DSRPAG ; set page register
mov #edsoffset(L1),w0
mov #edsoffset(L2),w1
mov.b [w0],w2 ; load the byte at L1
mov.b [w1],w3 ; load the byte at L2
User-defined read-only sections do not require a custom linker script. Based on the psv
section attribute, the linker will locate the section in program memory and map its labels into the PSV or EDS window. If the programmer wishes to declare a read-only section in a custom linker script, the following syntax may be used:
/*
** User-Defined Constants in Program Memory
**
** This section is identified as a read-only section
** by use of the psv section attribute. It will be
** loaded into program memory and mapped into data
** memory using the PSV or EDS window.
*/
userconstants ADDR : AT (LOADADDR)
{
*(userconstants);
} >program
In this example, LOADADDR
specifies the load address in program memory.
It is not generally recommended to define read-only data sections in the linker script. This is because sections that appear in the linker script are allocated sequentially, and read-only data sections have significant page alignment restrictions. Because of these alignment restrictions, sequential allocation can fragment memory and result in less efficient memory utilization.
Likewise, it is not recommended to specify an absolute address for read-only data sections using attributes in source code. Absolute sections also fragment memory and can result in less efficient memory utilization.