5.15.3 Changing and Linking the Allocated Section
The __section()
specifier allows you to have a object or
function redirected into a user-define psect, or section.
5.15.1 Compiler-Generated Psects lists the default sections the compiler uses to hold objects and code. The default section used by a function or object can be changed if the object has unique linking requirements that cannot be addressed by existing compiler features.
New sections created by the specifier for objects will have no linker
class associated with them. In addition, the compiler will not make assumptions
about the final location of the new section. You can link objects specified with
__section()
into any data bank. However, since the compiler
cannot know where the new section will be placed until the linker has executed,
the code to access the relocated object will be less efficient than the code used
to access the object without the specifier.
Since the new section is linked after other objects have been allocated
memory, you might also receive memory errors when using the
__section()
specifier. If this is the case, you will need to
reserve memory for the new section (see 4.6.1.18 Reserve Option).
New sections created by the specifier for functions will inherit the same flags. However, there are fewer linking restrictions relating to functions and this has minimal impact on the generated code.
The name of the new section you specify must be a valid assembly-domain
identifier. The name must contain only alphabetic, numeric characters, or the
underscore character, _
. It cannot have a name which is the same
as that of an assembler directive, control, or directive flag. If the new section
contains executable code and you wish this code to be optimized by the assembler,
ensure that the section name contains the substring text
, e.g.,
usb_text
. Sections named otherwise will not be modified by
the assembler optimizer.
Objects that use the __section()
specifier will be
cleared or initialized in the usual way by the runtime startup code (see 4.3.2 Startup and Initialization). For the
case of initialized objects, the compiler will automatically allocate an
additional new section (whose name will be the same as the section specified,
prefixed with the letter i
), which will contain the initial
values. This section must be stored in program memory, and you might need to
locate this section explicitly with a linker option.
The following are examples of a object and function allocated to a non-default section.
int __section("myData") foobar;
int __section("myCode") helper(int mode) { /* ... */ }
Typically you locate new sections you create with an explicit linker option. So, for example, if you wanted to place the sections created in the above example, you could use the following driver options:
-Wl,-PmyData=0200h
-Wl,-AMYCODE=50h-3ffh
-Wl,-PmyCode=MYCODE
which will place the section myData
at address 0x200, and
the section myCode
anywhere in the range 0x50 to 0x3ff
represented by the linker class, MYCODE
. See 7.1 Operation for linker
options that can be passed using the -Wl
driver option (4.6.11.8 Wl: Pass Option To The Linker,
Option).
If you are creating a new class for a memory range in program memory and
your target is a Baseline or Mid-range PIC device, then you will need to inform
the linker that this class defines memory that is word addressable. Do this by
using the linker’s -D
option, which indicates a delta value for a
class. For example:
-Wl,-DMYCODE=2
Do not use this option for PIC18 devices, which have byte-addressable program memory.
If you would like to set special flags with the new section, you can do
this by providing a definition of the new section in your source code. For
example, if you wanted the myCode
section to be placed at an
address that is a multiple of 100h, then you can place the following in your
source file:
asm("PSECT mycode,reloc=100h");
int __section("myCode") helper(int mode) { /* ... */ }
The reloc
, size
and
limit
psect flags (see for example 6.1.9.39.16 Reloc Flag) can all be
redefined in this way. Redefinitions might trigger assembler warning messages;
however, these can be ignored in this circumstance.