PIC32MX Exceptions: Processor Initialization

Last modified by Microchip on 2023/11/10 11:07

Starting Up

From a software perspective, Reset is almost the same as a general exception, although it is one from which we're not going to return.

The CPU responds to Reset by entering what's called "bootstrap" mode, starting by fetching instructions from 0xBFC00000. This corresponds (via the MMU) to the physical address 0x1FC00000 in the uncached KSEG1 region.

Following this, only enough of the CPU's control register state (CP0 registers) is defined so that the CPU can execute uncached instructions.

"Enough state" is interpreted minimally, i.e. only 3 things are guaranteed in the CP0 Status register:

  • The CPU is in Kernel Mode (StatusEXL=1)
  • Interrupt exceptions are disabled (StatusIE=0)
  • Bootstrap exceptions (i.e. exceptions occurring during reset) will vector through uncached entry points (StatusBEV=1)

Furthermore, the caches will be in a random, unusable state, as will the memory management unit (MMU).

MPLAB® XC32 Start-Up Code

The job of modifying this initial CPU state to a state that will run your main() code falls to a small assembly language code stub that is automatically inserted by the MPLAB® XC32 compiler.

crt0.S - C Run-time Startup Code

Initializes objects and CPU state to prepare to run the main() function, then calls main() itself:

  • Jump to NMI Handler (_nmi_handler), if an NMI occurred.
  • Initialize the stack pointer.
  • Initialize the Global Pointer in all register sets available on the selected target device.
  • Call the "on reset" procedure (_on_reset).
  • Call the _pic32_init_cache procedure to initialize the L1 cache on target devices that feature an L1 cache.
  • Call the _pic32_tlb_init_ebi_sqi procedure to initialize the TLB on target devices that use pre-mapped EBI and SQI external memory regions.
  • Clear uninitialized small bss sections.
  • Initialize data using the linker-generated data-initialization template.
  • If the target device that features a bus matrix and the application uses a RAM function, initialize the bus matrix for execution from data memory.
  • Initialize the CP0 registers.
  • Enable the DSPr2 engine on target devices that feature it.
  • Call the "On Bootstrap" procedure (_on_bootstrap).
  • Change the location of exception vectors.
  • For C++, call the C++ initialization code to invoke all constructors for file-scope static storage objects.
  • Call main().

Review chapter 14.3 of the MPLAB XC32 Users Guide for full details on each step.

On Windows® PCs, crt0.S is located in C:\Program Files\Microchip\xc32\<version>\pic32-libs\libpic32\startup

CPU State on Entry to main()

PIC32MX CP0 and Interrupt Controller registers are initialized by hardware and MPLAB XC32 Compiler start-up code placing the CPU in the following state upon entry to your main() function:

  • Ebase = _ebase_address (= 0x9FC01000 for PIC32MX795F512L)
  • IntCtlVS<4:0> = 0x01 (Vector spacing is initialized to 32 (0x20) bytes (8 words) between entry points)
  • StatusBEV = 0 (Exception vector entry points changed from the "bootstrap" location to the "normal" location)
    • General Exceptions: Ebase (= 0x9FC01000) + 0x180
    • Interrupt Exceptions: Ebase + 0x200 + (VectNumber * IntCtlVS)
  • StatusIE = 0 (Interrupt Exceptions Disabled)
  • StatusIPL<2:0> = 0 (CPU running @ priority level 0)
  • INTCONMVEC = 0 (Interrupt controller configured for single-vector mode)
  • Prefetch Cache is disabled
  • KSEG0 cacheability is disabled
  • PFM Wait States = 7 (max. setting)
  • Data Ram Wait States = 1 (max. setting)
Configuring for Speed:

You should (at minimum) perform the following initialization to get the most work out of your PIC32MX CPU:

  • Data Memory SRAM wait states: Default Setting = 1; set it to 0 (Data Memory SRAM on PIC32MX795F512L runs at 0 wait states @ 80MHz)


  • Flash PM Wait States: MX Flash runs at 2 wait states @ 80 MHz for PIC32MX795F512L


  • Prefetch-cache: Enable prefetch for cacheable PFM instructions


  • KSEG0 Cacheability: Enable caching of KSEG0 program memory accesses

unsigned int val;
val = _builtin_mfc0(_CP0_CONFIG, _CP0_CONFIG_SELECT);
val |= 0x00000003;
_builtin_mtc0(_CP0_CONFIG, _CP0_CONFIG_SELECT, val);

Other items to consider include:

  • peripheral bus clock setting
  • compiler setting