From a software perspective, reset is almost the same as a general exception, although one from which we're not going to return.
The Central Processing Unit (CPU) responds to reset by entering what's called "bootstrap" mode, starting by fetching instructions from 0xBFC00000. This corresponds (via the MMU) to physical address 0x1FC00000 in the uncached KSEG1 region.
Following this, only enough of the CPUs 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()
PIC32MZ 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 (= 0x9D000000 for PIC32MZ2048ECG100)
- OFFx registers are initialized by start-up code based on defined ISRs in your project
- StatusBEV = 0 (Exception vector entry points changed from the "bootstrap" location to the "normal" location)
- General Exceptions: Ebase (=0x9D000000) + 0x180
- Interrupt Exceptions: Ebase + OFFx
- StatusIE = 0 (Interrupt Exceptions Disabled)
- StatusIPL<2:0> = 0 (CPU running @ priority level 0)
- INTCONMVEC = 0 (Interrupt controller configured for single-vector mode)
- Cache is enabled and configured in write-back with write allocation mode
Configuring for Speed:
Although the L1 cache is configured/enabled by default, you should (at minimum) perform the following additional initialization to get the most work out of your PIC32MZ CPU:
- Flash PM Wait States: MZ Flash runs at 2 wait states @ 200 MHz for PIC32MZ2048EFG100
- PRECONbits.PFMWS = 2;
- Prefetch-cache: Enable prefetch for PFM (any PFM instructions or data)
- PRECONbits.PREFEN = 3;
Other items to consider include peripheral bus clock settings as well as compiler settings.