23.3.4.8 .vectors Section

Some PIC32 families feature variable offsets for vector spacing. This feature allows the interrupt vector spacing to be configured according to application needs. A specific interrupt vector offset can be set for each vector using its associated OFFxxx register. For details on the interrupt vector-table variable offset feature, refer to the “PIC32 -Family Reference Manual” (DS61108) and also the data sheet for your specific PIC32 MCU.

The application source code is responsible for creating a .vector_n input section for each interrupt vector. The C/C++ compiler creates this section when either the -vector(n) or the at_vector(n) attribute is applied to the interrupt service routine. In assembly code, use the .section directive to create a new named section.

The device-specific linker script creates a single output section named .vectors that groups all of the individual .vector_n input sections from the project. The start of the interrupt-vector table is mapped to the address (_ebase_address + 0x200). The default value of the _ebase_address symbol is also provided in the linker script.

For each vector, the linker script also creates a symbol named __vector_offset_n, whose value is the offset of the vector address from the _ebase_address address.

PROVIDE(_ebase_address = 0x9D000000);
SECTIONS {
 /* Interrupt vector table with vector offsets */ 
 .vectors _ebase_address + 0x200 :
 {
 /* Symbol __vector_offset_n points to .vector_n if it exists, 
  * otherwise points to  the default handler. The
  * vector_offset_init.o module then provides a .data section
  * containing values used to initialize the vector-offset SFRs 
  * in the crt0 startup code.
  */
 __vector_offset_0 = (DEFINED(__vector_dispatch_0) ? (. - _ebase_address) :  __vector_offset_default); KEEP(*(.vector_0))
 __vector_offset_1 = (DEFINED(__vector_dispatch_1) ? (. - _ebase_address) : __vector_offset_default); KEEP(*(.vector_1))
 __vector_offset_2 = (DEFINED(__vector_dispatch_2) ? (. - _ebase_address) : __vector_offset_default); KEEP(*(.vector_2))
 /* ... */
 __vector_offset_190 = (DEFINED(__vector_dispatch_190) ? (. - _ebase_address) :  __vector_offset_default); KEEP(*(.vector_190))
 }
}

The vector-offset initialization module (vector_offset_init.o) uses the __vector_offset_n symbols defined in the default linker script. The value of each symbol is the offset of the vector’s address from the ebase register’s address. The vector-offset initialization module, uses the symbol value to create a .data section using the address of the corresponding OFFxxx special function register. This means that the standard linker-generated data-initialization template contains the values used to initialize the OFFxxx registers.

With these .data sections added to the project and the linker-generated data-initialization template, the standard runtime startup code initializes the OFFxxx special function registers as regular initialized data. No special code is required in the startup code to initialize the OFFxxx registers.