void SYS_CLK_Initialize( const SYS_CLK_INIT const * clkInit ) { SYS_DEVCON_SystemUnlock ( ); PLIB_OSC_FRCDivisorSelect( OSC_ID_0, OSC_FRC_DIV_2); /* Enable Peripheral Bus 1 */ PLIB_OSC_PBClockDivisorSet (OSC_ID_0, 0, 1 ); /* Disable REFCLKO1*/ PLIB_OSC_ReferenceOscDisable ( OSC_ID_0, 0 ); /* Disable REFCLK1_OE*/ PLIB_OSC_ReferenceOutputDisable ( OSC_ID_0, 0 ); /* Disable REFCLKO2*/ PLIB_OSC_ReferenceOscDisable ( OSC_ID_0, 1 ); /* Disable REFCLK2_OE*/ PLIB_OSC_ReferenceOutputDisable ( OSC_ID_0, 1 ); /* Disable REFCLKO3*/ PLIB_OSC_ReferenceOscDisable ( OSC_ID_0, 2 ); /* Disable REFCLK3_OE*/ PLIB_OSC_ReferenceOutputDisable ( OSC_ID_0, 2 ); /* Disable REFCLKO4*/ PLIB_OSC_ReferenceOscDisable ( OSC_ID_0, 3 ); /* Disable REFCLK4_OE*/ PLIB_OSC_ReferenceOutputDisable ( OSC_ID_0, 3 ); SYS_DEVCON_SystemLock ( ); }
void SYS_CLK_Initialize( const SYS_CLK_INIT const * clkInit ) { SYS_DEVCON_SystemUnlock ( ); PLIB_OSC_FRCDivisorSelect( OSC_ID_0, OSC_FRC_DIV_1); /* Enable Peripheral Bus 1 */ PLIB_OSC_PBClockDivisorSet (OSC_ID_0, 0, 2 ); PLIB_OSC_PBOutputClockEnable (OSC_ID_0, 0 ); /* Enable Peripheral Bus 2 */ PLIB_OSC_PBClockDivisorSet (OSC_ID_0, 1, 2 ); PLIB_OSC_PBOutputClockEnable (OSC_ID_0, 1 ); /* Enable Peripheral Bus 3 */ PLIB_OSC_PBClockDivisorSet (OSC_ID_0, 2, 2 ); PLIB_OSC_PBOutputClockEnable (OSC_ID_0, 2 ); /* Enable Peripheral Bus 4 */ PLIB_OSC_PBClockDivisorSet (OSC_ID_0, 3, 2 ); PLIB_OSC_PBOutputClockEnable (OSC_ID_0, 3 ); /* Enable Peripheral Bus 5 */ PLIB_OSC_PBClockDivisorSet (OSC_ID_0, 4, 2 ); PLIB_OSC_PBOutputClockEnable (OSC_ID_0, 4 ); /* Enable Peripheral Bus 7 */ PLIB_OSC_PBClockDivisorSet (OSC_ID_0, 6, 1 ); PLIB_OSC_PBOutputClockEnable (OSC_ID_0, 6 ); /* Enable Peripheral Bus 8 */ PLIB_OSC_PBClockDivisorSet (OSC_ID_0, 7, 2 ); PLIB_OSC_PBOutputClockEnable (OSC_ID_0, 7 ); /* Disable REFCLKO1*/ PLIB_OSC_ReferenceOscDisable ( OSC_ID_0, OSC_REFERENCE_1 ); /* Disable REFCLK1_OE*/ PLIB_OSC_ReferenceOutputDisable ( OSC_ID_0, OSC_REFERENCE_1 ); /* Disable REFCLKO2*/ PLIB_OSC_ReferenceOscDisable ( OSC_ID_0, OSC_REFERENCE_2 ); /* Disable REFCLK2_OE*/ PLIB_OSC_ReferenceOutputDisable ( OSC_ID_0, OSC_REFERENCE_2 ); /* Disable REFCLKO3*/ PLIB_OSC_ReferenceOscDisable ( OSC_ID_0, OSC_REFERENCE_3 ); /* Disable REFCLK3_OE*/ PLIB_OSC_ReferenceOutputDisable ( OSC_ID_0, OSC_REFERENCE_3 ); /* Disable REFCLKO4*/ PLIB_OSC_ReferenceOscDisable ( OSC_ID_0, OSC_REFERENCE_4 ); /* Disable REFCLK4_OE*/ PLIB_OSC_ReferenceOutputDisable ( OSC_ID_0, OSC_REFERENCE_4 ); SYS_DEVCON_SystemLock ( ); }
bool _SYS_CLK_ReferenceFrequencySet ( CLK_BUSES_REFERENCE referenceBus, CLK_SOURCES_REFERENCE referenceSource, uint32_t targetFreqHz, bool waitUntilComplete, uint32_t *clockClosest ) { unsigned long inputFreq = 0, tempFreq = 0; uint32_t pllMult = 0, pllIDiv = 0; double number = 0.f; unsigned long ipart_number = 0; double fpart_number = 0.f; unsigned long divisor = 0; float trimValue = 0.f; const long scale = 100; CLK_SOURCES_SYSTEM systemSource; if (referenceBus != CLK_BUS_REFERENCE_1) return false; switch ( referenceSource ) { case CLK_SOURCE_REF_SYSTEMCLK: /* The clock source is System clock itself */ inputFreq = clkObject.systemClock; break; case CLK_SOURCE_REF_PBCLK_BUS1: /* The clock source is Peripheral clock */ inputFreq = clkObject.peripheralClock[referenceBus]; break; case CLK_SOURCE_REF_PRIMARY: /* If the System clock is directly using the from the Primary oscillator clock, return the configured primary oscillator frequency */ inputFreq = SYS_CLK_CONFIG_PRIMARY_XTAL; break; case CLK_SOURCE_REF_FRC: /* Source of system clock is internal fast RC. If the System clock is directly using the fast RC clock, return the Fast RC clock */ inputFreq = SYS_CLK_FRC_CLOCK; break; case CLK_SOURCE_REF_LPRC: /* Processor's internal LPRC clock */ inputFreq = SYS_CLK_LPRC_CLOCK; break; case CLK_SOURCE_REF_SECONDARY: inputFreq = SYS_CLK_CONFIG_SECONDARY_XTAL; break; case CLK_SOURCE_REF_USBPLL_OUT: /* Find the closest register value in the hardware */ /* USBPLL_OUT is not directly an input to REFCLOCK. The USBPLL_OUT * is given to REFCLOCK before the SYS_CLK_CONFIG_USBPLL_DIVISOR * (value 2) is applied. */ inputFreq = SYS_CLK_UPLL_BEFORE_DIV2_FREQ; break; case CLK_SOURCE_REF_SYSPLL_OUT: /* Source of system clock is SPLL with divisors */ pllMult = _SYS_CLK_PLLMultiplierRead(); pllIDiv = _SYS_CLK_PLLInputDividerRead(); /* Read the current system clock source from the register */ systemSource = PLIB_OSC_CurrentSysClockGet ( OSC_PLIB_ID ); if (systemSource == SYS_CLK_SOURCE_PRIMARY_SYSPLL) { inputFreq = ( SYS_CLK_CONFIG_PRIMARY_XTAL * pllMult ) / pllIDiv; } else if (systemSource == SYS_CLK_SOURCE_FRC_SYSPLL) { inputFreq = ( SYS_CLK_FRC_CLOCK * pllMult ) / pllIDiv; } else { inputFreq = 0; } break; case CLK_SOURCE_REF_EXTERNAL: /* Source of system clock is internal fast RC with PLL. Find the closest register value in the hardware */ inputFreq = SYS_CLK_CONFIG_EXTERNAL_CLOCK; break; default: break; } /* Failure case if the input is not supported */ if (inputFreq == 0) { *clockClosest = 0; clkObject.systemClockStatus = SYS_CLK_OPERATION_FAIL_NOT_ACHIEVABLE; return false; } /* Find the divisor value, find the equation in the datasheet */ number = inputFreq / ( targetFreqHz * 2.0 ); ipart_number = (unsigned long) number; divisor = ipart_number; fpart_number = number - ipart_number; /* Check whether the divisor is within limit */ if ( ( divisor > 0 ) && ( divisor <= CLK_REFERENCE_DIVISOR_MAX ) ) { //Blocking implementation while(waitUntilComplete && PLIB_OSC_ReferenceOscSourceChangeIsActive ( OSC_PLIB_ID, referenceBus )) { PLIB_OSC_ReferenceOscDisable( OSC_PLIB_ID, referenceBus ); continue; } trimValue = fpart_number*512; if (trimValue > CLK_REFERENCE_TRIM_MAX) { trimValue = CLK_REFERENCE_TRIM_MAX; } else if (trimValue < 0) { //We really should not have -ive trim value trimValue = 0; } if ( !PLIB_OSC_ReferenceOscSourceChangeIsActive ( OSC_PLIB_ID, referenceBus ) ) { /* Unlock before you switch */ SYS_DEVCON_SystemUnlock ( ); /* Switch the Reference clock source */ PLIB_OSC_ReferenceOscBaseClockSelect ( OSC_PLIB_ID, CLK_BUS_REFERENCE_1, referenceSource ); PLIB_OSC_ReferenceOscDivisorValueSet ( OSC_PLIB_ID, referenceBus, divisor ); PLIB_OSC_ReferenceOscTrimSet ( OSC_PLIB_ID, referenceBus, trimValue ); PLIB_OSC_ReferenceOscEnable ( OSC_PLIB_ID, referenceBus ); PLIB_OSC_ReferenceOutputEnable ( OSC_PLIB_ID, referenceBus ); /* Lock it back right after completing all the register related operations */ SYS_DEVCON_SystemLock ( ); tempFreq = inputFreq / ( 2 * ( divisor * scale + ( trimValue * scale / 512 ) ) ) ; *clockClosest = tempFreq * scale; } else { *clockClosest = 0; clkObject.systemClockStatus = SYS_CLK_OPERATION_FAIL_REGISTER_NOT_READY; return false; } } else { clkObject.systemClockStatus = SYS_CLK_OPERATION_FAIL_NOT_ACHIEVABLE; *clockClosest = 0; return false; } /* Control is here, means switching operation is either complete or in progress, not failure */ return true; }