9.1 Routine Entry Points
The example code shown above looks similar to that appropriate for a Mid-range device,
except for the psect used to hold the increment
routine. This psect is
associated with a special class that ensures it will be linked in such a way that calls
to the label(s) at the start of the psect will work as expected on Baseline devices.
This is explained below.
When a call
instruction is executed by a PIC Baseline device, bits 0
through 7 of the PC register are loaded from the instruction operand, bits 9 and 10 are
loaded from the PA bits in the STATUS register but, importantly, bit location 8 is
unconditionally cleared. This implies that call
instructions on
Baseline devices can only reach addresses that fall in the first 256 locations of any
program memory page. In other words, any entry points to callable routines must be
located in the first 256 program memory locations of a page. This is also true of any
instruction that modifies the PCL register.
Note that this restriction does not affects jumps (goto
instructions),
which can reach any address. Also note that this restriction does not prevent a routine
from consuming the entire program memory page; it merely means that the routine's
entry points must be in the lower portion of the page if the routine is
called or reached via an instruction that modifies the PCL register. Once code in a
routine has been reached, sequential execution of the remainder of the code in that
routine can proceed all the way to the end of the page.
-AMYCLASS=00h-01FFh
which defines a class
called MYCLASS
with the address range 0 through to 0x1FF. If a routine
was linked into this class, the linker could placed it anywhere in this range. But
classes can be defined using an additional hyphen-separated address field, for
example:-AMYCLASS=00h-0FFh-01FFh
which tells the linker that when
linking any psect into this range, the start of the psect must fall in first specified
address range (0 through to 0xFF), but that the remainder of the psect can extend all
the way up to the end address, in this case 0x1FF.ENTRY
and you can see this class being used for the psect that
holds the increment
routine in the example, which is repeated below.
Note that this class was not used by the psect that holds the code associated with
main
. As this example program contains no instructions that
call the main
label (one instruction jumps to it)
this routine can be linked anywhere in program memory and can continue to use the
code
psect (which is defined by the assembler to use the
CODE
class).PSECT entryCode,class=ENTRY,delta=2
increment:
movwf loc
incf loc,w
return
...
-Mmain.map -E1 --acfsm=1493 -ACODE=00h-01FFhx4 -ASTRCODE=00h-07FFh \
-AENTRY=00h-0FFh-01FFh,0200h-02FFh-03FFh,0400h-04FFh-05FFh,0600h-06FFh-07FFh \
...
TOTAL Name Link Load Length Space
CLASS CODE
resetVec 0 0 5 0
code 1F6 1F6 A 0
CLASS ENTRY
entryCode 5 5 3 0
You can see in the linker options at the top that the CODE
class consists of four blocks of memory, each being an entire page in size (0x1FF). The
ENTRY
class consists of four blocks, where each block spans an
entire page but with an entry range defined over the first 0xFF bytes of each page.Down further, you can see that the code
psect happened to be linked
within the top half of a memory page (at address 0x1F6), but the
entryCode
psect was linked within one of the entry ranges of the
ENTRY
class (at address 0x5), as was requested.
The linker will find it more difficult to position psects into a class such as
ENTRY
due to the additional restrictions imposed by that class, but
linking them with these restrictions is necessary for correct program operation. If
routines do not have entry points that are called or reached via an instruction that
modifies the PCL register, consider placing them in a psect that is linked into the
regular CODE
class (such as the code
psect), to
utilize the potentially unused upper portions of program memory pages.