Startup Without Peripheral Libraries – PIC32MK

Startup without peripheral libraries series

Microchip MPLAB X hides some of the details of starting up the PIC32.  The default startup code and linker scripts are hidden in the compiler directory and included by default.  Generally, they do not need to be touched.  Almost all of the register definitions are included the standard device header file xc.h.  This provides the register values both as a full register variable and as a bit fields.  The bit fields are a really nice touch that Microchip does with all their PIC MCUs.  I also include cp0defs.h to access the defines used to configure CP0.

This example uses the built in 8MHz fast RC internal oscillator and PLL to run at 120MHz.  I then set up Timer1 and enable interrupts.

The startup works as follows:

  1. Set up the proper configuration bits for the clock and features being used.  This populates the clock setting registers with your specified values automatically – MPLAB X contains a gui to help.
  2. Configure the CPU caches – I commented out the pre-fetch enable code since this is covered under some errata for my chip revision
  3. Enable any needed peripheral clocks
  4. Set up peripherals – In this case I set up Timer1 to interrupt every 1ms
  5. Enable interrupts as needed
  6. Call the sysInit function from the main function before the main loop
#include <xc.h>
#include <cp0defs.h>


#pragma config FUSBIDIO2 = OFF
#pragma config FVBUSIO2 = OFF
#pragma config PGL1WAY = OFF
#pragma config PMDL1WAY = OFF
#pragma config IOL1WAY = OFF
#pragma config FUSBIDIO1 = OFF
#pragma config FPLLIDIV = DIV_1
#pragma config FPLLRNG = RANGE_5_10_MHZ
#pragma config FPLLICLK = PLL_FRC
#pragma config FPLLMULT = MUL_60 // 120 MHz
#pragma config FPLLODIV = DIV_4
#pragma config VBATBOREN = OFF
#pragma config DSBOREN = OFF
#pragma config DSWDTEN = OFF
#pragma config BORSEL = HIGH
#pragma config UPLLEN = OFF
#pragma config FNOSC = SPLL
#pragma config FSOSCEN = OFF
#pragma config IESO = OFF
#pragma config POSCMOD = OFF
#pragma config OSCIOFNC = OFF
#pragma config FCKSM = CSECMD
#pragma config DMTCNT = DMT31
#pragma config FWDTEN = OFF
#pragma config FDMTEN = OFF
#pragma config ICESEL = ICS_PGx1

void sysInit (void)
{
   // CPU setup
   __builtin_mtc0(_CP0_CONFIG, 0, 3); // Configure CP0.K0 for cached instruction pre-fetch
   CHECONbits.PERCHEEN = 1; // enable peripheral cache
   CHECONbits.DCHEEN = 1; // enable data cache
   CHECONbits.ICHEEN = 1; // enable instruction cache
   // Comment out due to errata
   //CHECONbits.PREFEN = 1;
   CHECONbits.PFMWS = 3;

   // set up clocks
   PB2DIVbits.ON = 1; // turn on timer1 clock
   PB2DIVbits.PBDIV = 1; // SYSCLK / 2

   // set up timer
   T1CONbits.ON = 0;
   T1CONbits.TECS = 0b10; // use LPRC
   T1CONbits.TCS = 1; // use TECS setting
   T1CONbits.TCKPS = 0; // /1
   TMR1 = 0;
   PR1 = 32;
   IPC1bits.T1IP = 2;
   IFS0bits.T1IF = 0;
   IEC0bits.T1IE = 1;
   T1CONbits.ON = 1;

   // enable ints
   __builtin_enable_interrupts();
}

Leave a Reply

Your email address will not be published. Required fields are marked *