Search code examples
microchippic32system-clock

PIC32MX System clock half of expected Value/Harmony


I recently started in a fresh company where the programer that did the PIC32 programming is now gone and I do need to troubleshoot his uC-Code.

He disliked the Microchip Harmony Configurator/Framework and thus he is only using the Peripheral Library of the Harmony Framework to do coding (That means he used alot of PLIB_*-functions in his code, taken from examples). For this he extraced the sys_devcon.c and sys_devcon.h files from framework/system/devcon/src and copied that file to the project's source.

Now my Problem: Below you see the device.cfg. The Pins OSC1 and OSC2 are connected to the primary oscillator (4MHz). We already confirmed that the oscillator is working correctly by testing it with a LeCroy Teledyne (shows 4MHz). With the Config given by the file the SystemClock (SYSCLK) is derived by the SYSPLL. Since my IDIV is 1, my MULT is 18 and my ODIV is 1, I expect the SYSCLK to run at 72MHz (4/1*18/1=72). The PBDIV is set to DIV_2 (so PBCLK=SYSCLK/2 -> 36MHz). The REFCLK is expected to run at 6.4MHz.

HOWEVER: The measured PBCLK shows 18MHz, the measured REFCLK(SYSPLL as F_REFIN, shows 3.2MHz which means the SYSCLK only runs 36MHz (not expected 72MHz). But taken the config into account everthing should run twice as fast. Im unable to locate the problem why the SYSCLK runs at half speed.

I troubleshooted every single PLIB_OSC*(including PLIB_OSC_SLEW*) function inside the code and havent found a single issue (only 5 lines to use some sort of PLIB_OSC* functions). Maybe someone got some ideas/hints to troubleshoot. It's also not clear if the SYSCLK is actually halved or if there is some divider after the SYSPLL (in between REFCLK and PBCLK). Is there a way i can measure the SYSCLK?

uC: PIC32MX174F256B XC-Version: V2.10 Harmony: V2.05.01 (only PLIB is used) MPLAB X IDE: v4.20

#ifndef PIC32MX174F256B_CONFIG_HEADER

#define PIC32MX174F256B_CONFIG_HEADER


#ifdef __cplusplus
extern "C" {
#endif

/* PIC32MX174F256B Configuration Bit Settings */


// DEVCFG3
// USERID = No Setting

// Alternate I/O Select for I2C1 (I2C1 uses the SDA1/SCL1 pins)
#pragma config AI2C1 = OFF

// Alternate I/O Select for I2C2 (I2C2 uses the SDA2/SCL2 pins)  
#pragma config AI2C2 = OFF              
#pragma config PMDL1WAY = OFF            // Peripheral Module Enable Configuration
#pragma config IOL1WAY = OFF             // Peripheral Pin Select Configuration (Allow reconfigurations)

// DEVCFG2
#pragma config FPLLIDIV = DIV_1         // PLL Input Divider (1x Divider)
#pragma config FPLLMUL = MUL_18         // PLL Multiplier (18x Multiplier)
#pragma config FPLLICLK = PLL_POSC      // System PLL Input Clock Selection (POSC is input to the System PLL)
#pragma config FPLLODIV = DIV_1         // System PLL Output Clock Divider (PLL Divide by 1)
#pragma config BOREN = ON               // Brown-Out Reset (BOR) Enable (Enable BOR)
#pragma config DSBOREN = ON             // Deep Sleep BOR Enable (Enable ZPBOR during Deep Sleep Mode)
#pragma config DSWDTPS = DSPS7         // Deep Sleep Watchdog Timer Postscaler (1:2^11)
#pragma config DSWDTOSC = LPRC          // Deep Sleep WDT Reference Clock Selection (Select LPRC as
                                        // DSWDT Reference clock)
#pragma config DSWDTEN = OFF            // Deep Sleep Watchdog Timer Enable (Disable DSWDT during
                                        // Deep Sleep Mode)
#pragma config FDSEN = ON               // Deep Sleep Enable (Enable DSEN bit in DSCON)

// DEVCFG1
#pragma config FNOSC = SPLL             // Oscillator Selection Bits (Primary Osc (HS,EC, XT))
#pragma config FSOSCEN = OFF            // Secondary Oscillator Enable (Disabled)
#pragma config IESO = OFF                // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = XT             // Primary Oscillator Configuration (XT osc mode)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)

// value can also be adjusted in module sys_system from libpic32mx174f256b
#pragma config FPBDIV = DIV_2           // Peripheral Clock Divisor

#pragma config FCKSM = CSDCMD           // Clock Switching and Monitor Selection (Clock Switch
                                        // Disable, FSCM Disabled)
#pragma config WDTPS = PS1              // Watchdog Timer Postscaler (1:1)
#pragma config WDTSPGM = ON             // Watchdog Timer Stop During Flash Programming (Watchdog
                                        // Timer stops during Flash programming)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
#pragma config FWDTWINSZ = WINSZ_25     // Watchdog Timer Window Size (Window Size is 25%)

// DEVCFG0
#pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx2        // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)
#pragma config PWP = OFF                // Program Flash Write Protect (Disable)
#pragma config SMCLR = MCLR_NORM        // Soft Master Clear Enable (MCLR pin generates a normal system Reset)
#pragma config BWP = OFF                // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF                 // Code Protect (Protection Disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

Solution

  • I finally solved the issue by myself.

    It was simply my lack of knowledge. I found the crucial information in 2 seperate data sheets.

    One was the "PIC32MX1XX/2XX 28/44-PIN XLP FAMILY Data Sheet" on page 318, which states that the maximum SPICLK must not exceed 25MHz (I believe .

    The second crucial information was the calculation of the BaudRate. I thought that the BaudRate equals the selected PBCLK (so when I have a SYSCLK of 72MHz and the PBCLK is SYSCLK=PBCLK/2 => 36MHz, the BaudRate is also set at 36MHz). But at page 23-29 at "PIC32 FRM Section 23. Serial Peripheral Interface (SPI)" there is the formula F_SCK = F_PB / ( 2 ⋅ ( SPIxBRG + 1 ))