Selective Code Protection in 8-bit PIC® Devices using the MPLAB® XC8 Compiler

Last modified by Microchip on 2023/11/09 09:13

Microchip's 8-bit PIC® code protection configuration bits

These bits allow you to prevent unauthorized access of program memory. Some of these devices allow selective protection of the program memory space and with these devices, you can specify which blocks are protected. There are different sorts of protection too, for example, write protection or protection from external block table reads.

This article looks at how you can arrange for the MPLAB® XC8 compiler to place special code into memory areas that you have protected, and for the remainder of your program to be placed in unprotected memory. There are four main steps to follow.

  1. Place functions to be protected into their own unique section.
  2. Create a linker class that represents the protected memory area.
  3. Link the unique sections in this new linker class.
  4. Reserve the protected area to prevent it from being used by other functions.

Functions can be easily placed into a new section (or psect as they are also called) using the __section() specifier. The following is an example of a function allocated to a section called protected_text rather than its default section:

1
2
3
4
int __section("protected_text”) encode(char * hash, int a)
{
    ...
}

The section name can be any identifier using alphabetic, numeric, and underscore characters. Any section containing code and whose name contains the string text might be optimized if the assembler optimizers are enabled. Choose an alternate section name if you do not want the section contents optimized.

Next, determine the protected memory ranges from your target device's datasheet. For example, PIC18Fx3K20 devices have what is called the boot block spanning 0-1FF and two other blocks spanning 200-FFF, and 1000-1FFF. If, for example, you decide to protect the boot block and place your protected functions anywhere in that block, you can create a suitable linker class with the compiler option -L-APROTECT=0h-1FFh. This is the compiler’s -L- option, which passes the -A linker option (and arguments) directly to the linker application. It requests that PROTECT be made a linker class that consists of one contiguous block of memory ranging from address 0 to 0x1FF.

You can now place your new sections into the memory defined by this class. To do that, use another linker option (-P) passed to the linker via the compiler’s -L- option -L-Pprotected_text=PROTECT.

It is the only convention that dictates you use an upper-case class name and lower-case section name, but note that the linker is case sensitive when it comes to these names.

If you are using MPLAB X IDE, add both of the above options to the XC8 linker > Additional options > Extra Linker Options field, as shown in the accompanying image.

additional linker options

You can prevent ordinary functions from being placed into the protected memory space by reserving this area using the —ROM option. For example, use —ROM=default,-0-1FFh if you are compiling on the command line, or by entering this option argument into the XC8 linker > Memory model > ROM ranges field, as shown:

window showing the range of ROM memory for the selected device

Finally, check the map file to ensure that this all worked as you expected. The following is an extract from the map file, showing that the section created in this example was linked into the boot block memory.

Listing of the Map file to verify the protected range is what we intended

Notice that no other sections were linked in this block. Do not be concerned that the new section is shown under the CODE class in this example, that is the default class assigned to the new section when it was created and this default class is used to arrange sections in the map file.