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 ( );
}
示例#2
0
bool _SYS_CLK_PeripheralFrequencySet ( CLK_BUSES_PERIPHERAL peripheralBus,
        uint32_t peripheralClockHz,
        uint32_t *clockClosest )
{
    uint8_t index = 0;
    uint16_t divisorMatch = 0, divisor = 0;
    unsigned long tempFrequency, prevFrequency = 0;

    /* All MX devices have a single peripheral bus at the moment */
    if (peripheralBus != CLK_BUS_PERIPHERAL_1)
    {
        *clockClosest = 0;
        return false;
    }

    for ( index=0; index<4; index++ )
    {
        divisor = 0x01 << index;
        /* Here the code is too specific to PIC32MX. The code may not be so easily
        usable for other controllers. But seems like this is the best way to avoid
        RAM usage for lookup tables */

        tempFrequency = ( clkObject.systemClock / divisor );

        if ( ( abs( peripheralClockHz - tempFrequency ) ) <
            ( abs ( peripheralClockHz - prevFrequency ) ) )
        {
            prevFrequency = tempFrequency;
            divisorMatch = divisor;
        }
    }
    if ( true == SYS_CLK_FrequencyErrorCheck ( peripheralClockHz, prevFrequency ) )
    {
        /* Unlock before you switch */
        SYS_DEVCON_SystemUnlock ( );

        PLIB_OSC_PBClockDivisorSet ( OSC_ID_0, peripheralBus, divisorMatch );

        SYS_DEVCON_SystemLock ( );

        clkObject.peripheralClockStatus[peripheralBus]
                = SYS_CLK_OPERATION_COMPLETE;
    }
    else
    {
        /* Requested frequency is not achievable. Update the error code and closest
        possible frequency */
        clkObject.peripheralClosestClock[peripheralBus] = prevFrequency;

        clkObject.peripheralClockStatus[peripheralBus]
                = SYS_CLK_OPERATION_FAIL_NOT_ACHIEVABLE;

        return false;
    }
    
    *clockClosest = prevFrequency;
    return true;
}
void SYS_CLK_SecondaryOscillatorDisable ( void )
{
    /* Check for secondary oscillator status */
    if (PLIB_OSC_SecondaryIsEnabled(OSC_ID_0))
    {    
        /* Unlock and disable secondary oscillator*/
        SYS_DEVCON_SystemUnlock();
        
        PLIB_OSC_SecondaryDisable(OSC_ID_0);
        
        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 ( );
}
示例#5
0
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;
}
示例#6
0
int8_t SYS_CLK_SystemClockSourceSwitch ( CLK_SOURCES_SYSTEM clockSource,
                                        unsigned char valueToPLLMULT,
                                        unsigned char valueToPLLODIV,
                                        bool waitUntilComplete )
{
    uint32_t delay= 100;
    /* Unlock before you switch */
    SYS_DEVCON_SystemUnlock ( );

    /* Special treatment if the source is a PLL based source. Do not change
     multipliers after switching. Switch to a FRC source first, then alter
     the multiplier values. */
    if ( ( ( clockSource == SYS_CLK_SOURCE_PRIMARY_SYSPLL ) ) ||
            ( clockSource == SYS_CLK_SOURCE_FRC_SYSPLL ) )
    {
        PLIB_OSC_SysClockSelect ( OSC_PLIB_ID, SYS_CLK_SOURCE_FRC );

        /* Ensure that we are not on a PLL based source before switching */

        /* Write the values before switching. Datasheet says so. */
        PLIB_OSC_SysPLLMultiplierSelect ( OSC_PLIB_ID, valueToPLLMULT );
        PLIB_OSC_SysPLLOutputDivisorSet ( OSC_PLIB_ID, valueToPLLODIV );

        /* Switch to a PLL source */
        PLIB_OSC_SysClockSelect ( OSC_PLIB_ID, clockSource );

        delay = SYS_CLK_SYSPLL_LOCK_DELAY_80MHZ;

        /* Wait till the PLL settles down / locked  */
        clkObject.systemClockStatus = SYS_CLK_OPERATION_IN_PROGRESS;

        /* Device expects this delay. We are changing the System clock source here,
        On debugging sometimes the code just stops without this delay. Have to
        understand this further and fine tune this delay. */
        Nop();
        Nop();
        Nop();

        if ( waitUntilComplete == true )
        {
           //while ( PLIB_OSC_PLLIsLocked ( OSC_PLIB_ID, OSC_PLL_SYSTEM ) != true )
           {
                if ( delay-- <= 0 )
                {
                    /* Rarest case. Either the PLL lock failed or the bit is showing
                    the wrong status, A restart needed, an error status update will
                    not help */
                    clkObject.systemClockStatus = SYS_CLK_OPERATION_FAIL_PLL_LOCK_TIMEOUT;

                    //SYS_ASSERT("PLL lock timeout");
                    Nop();
                    /* Reaching here means clock switching is not enabled
                     through configuration bits */
                    return -1;
                }
           }
           clkObject.systemClockStatus = SYS_CLK_OPERATION_COMPLETE;
        }
    }
    else
    {
        /* If the new oscillator is not a PLL source, the one we are running on may
        be. So switch first before setting the divisor */
        PLIB_OSC_SysClockSelect ( OSC_PLIB_ID, clockSource );

        if ( clockSource == SYS_CLK_SOURCE_FRC_BY_DIV )
        {
            PLIB_OSC_FRCDivisorSelect ( OSC_PLIB_ID, valueToPLLMULT );
        }
    }
    /* Lock it before going back */
    SYS_DEVCON_SystemLock ( );

    /* Return something which is not equal to '-1'. Let us return the clock source
    itself */
    return clockSource;
}