These days I try to avoid peripheral libraries too.
My process for this has changed since using the PIC32MZ which pretty much demands Harmony if you want to use anything from the peripheral libraries such as chip setup.
For the basic projects, I don't use MHC or Harmony at all except for a few PLIB resources. Below is my typical boiler plate code for a new project.
o Set up as non-Harmony Project;
o Add "c:\microchip\harmony\v1_09\framework" to the project's include directories;
o Add "c:\microchip\harmony\v1_09\bin\framework\peripheral\PIC32MZnnnnEFxnnn_peripherals.a" as a Library/Object file to the project;
o Create a clean main.c file in the project, deleting all the machine generated shit;
o Add the following example code in main.c;
// DEVCFG0
#pragma config JTAGEN = OFF // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)
/*** DEVCFG1 ***/
#pragma config FNOSC = 0 //FRCDIV, note that setting this to 7 instead of 0 causes a clock failure, and COSC set to BFRC
#pragma config IESO = OFF
#pragma config POSCMOD = EC
#pragma config OSCIOFNC = OFF
#pragma config FCKSM = CSECME
#pragma config FWDTEN = OFF
#pragma config FDMTEN = OFF
#define PLIB_DISABLE_OPTIMIZATION_WARNING
#include "peripheral/peripheral.h"
#include <xc.h>
#include <sys/attribs.h> // Interrupt macros
#include <stdint.h>
#include <stdbool.h>
o Add the following functions and main() to main.c:
static void CPUInit(void)
{
// Note that cache is already configured by startup code
// C:\Program Files\Microchip\xc32\v1.42\pic32-libs\libpic32\stubs\pic32_init_cache.S
// Set up wait states
PLIB_PCACHE_WaitStateSet(PCACHE_ID_0, 2); // Adjust as appropriate for memory and clock
// Set up prefetch
if (PLIB_PCACHE_ExistsPrefetchEnable(PCACHE_ID_0))
{
PLIB_PCACHE_PrefetchEnableSet(PCACHE_ID_0, PLIB_PCACHE_PREFETCH_ENABLE_ALL);
}
// Set up interrupt controller
PLIB_INT_MultiVectorSelect(INT_ID_0);
PLIB_INT_Enable(INT_ID_0);
}
static void OSCInit(void)
{
// Switch to 200MHz PLL sourced from 24MHz EC POSC
PLIB_DEVCON_SystemUnlock ( DEVCON_ID_0 );
PLIB_OSC_SysPLLInputDivisorSet(OSC_ID_0, OSC_SYSPLL_IN_DIV_3); // Generate 8MHz from 24MHz POSC
PLIB_OSC_SysPLLFrequencyRangeSet(OSC_ID_0, OSC_SYSPLL_FREQ_RANGE_5M_TO_10M);
PLIB_OSC_SysPLLInputClockSourceSet(OSC_ID_0, OSC_SYSPLL_IN_CLK_SOURCE_PRIMARY);
PLIB_OSC_SysPLLMultiplierSelect(OSC_ID_0, 50);
PLIB_OSC_SysPLLOutputDivisorSet(OSC_ID_0, OSC_SYSPLL_OUT_DIV_2);
PLIB_OSC_SysClockSelect(OSC_ID_0, OSC_PRIMARY_WITH_PLL);
while (!PLIB_OSC_ClockSwitchingIsComplete(OSC_ID_0))
{
Nop();
}
PLIB_DEVCON_SystemLock ( DEVCON_ID_0 );
}
void main(void)
{
CPUInit();
OSCInit();
// Your code goes here
}
Setting up the CPU and oscillator is almost all I use the PLIBs for, I use bare metal SFR access for almost everything else. It's my intention to move to bare SFR access to set the oscillator in future, but this is a hangover from the time I did actually try to use PLIB but have since decided it's not worth the effort.
If I could be sure the PLIBs were:
(a) correct;
(b) fit for purpose;
(c) able to cover the complete set of peripheral use cases;
(d) not going to be deprecated any time soon;
(e) easy to use and learn;
then I'd be more likely to use them. As it is, within a year or two of release the peripheral library APIs no longer fit the peripherals of newer devices.