⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.c

📁 Ports_for_CF5213.zip 接口程序;接口程序;
💻 C
字号:
/*
 * File:    clock.c
 * Purpose: Driver for the on-chip Clock module
 *
 * Notes:       
 */

#include "common.h"
#include "clock.h"

/********************************************************************/
/* Initialize the PLL
 * 
 * Parameters:
 *  fref    PLL reference clock frequency in KHz
 *  fsys    Desired PLL output frequency in KHz
 *  flags   Operating parameters
 *
 * Return Value:
 *  The resulting output system frequency
 */
int
clock_pll (int fref, int fsys, int flags)
{
    int syncr, mfd_max, mfd_min, rfd_max;
    int i, temp, fout, mfd, rfd, done;
    
    /* Check for the disable flag */
    if (flags & PLL_DISABLE)
    {
        MCF_CLOCK_SYNCR &= ~MCF_CLOCK_SYNCR_PLLEN;
        return fref;
    }
    
    /* Check bounds of reference clock */
    if((fref >= MAX_FREF) || (fref <= MIN_FREF))
        return fref;
        
    if (fsys == 0)
    {
        /* Return current PLL output */
        if ((MCF_CLOCK_SYNCR & MCF_CLOCK_SYNCR_CLKSRC) &&
            (MCF_CLOCK_SYNCR & MCF_CLOCK_SYNCR_PLLEN))
        {
            mfd = (MCF_CLOCK_SYNCR & 0x7000) >> 12;
            mfd = MIN_MFD + (mfd * 2);
            rfd = (MCF_CLOCK_SYNCR & 0x0700) >> 8;
            rfd = 1 << rfd;
            return (fref * mfd / rfd);
        }
        else
            return fref;            
    }
    
    /* Check bounds of requested system clock */
    if (fsys > MAX_FSYS)
        fsys = MAX_FSYS;

    /* Determine maximum possible multiplier (must be even) */
    mfd_max = MAX_FVCO / fref;
    mfd_max &= ~1;
    if (mfd_max > MAX_MFD)
        mfd_max = MAX_MFD;
    
    /* Determine maximum possible output based on max multiplier */
    fout = fref * mfd_max;

    /* Determine target output based on fsys and max possible */ 
    if (fout > fsys)
        fout = fsys;
    
    /* Determine the minimum multiplier */
    for (mfd_min = mfd_max; 
         mfd_min > MIN_MFD && fout < (fref * mfd_min); 
         mfd_min-=2);
         
    /* Set preliminary divider maximum */         
    rfd_max = MAX_RFD;

    /*
     * Loop across the valid MFD and RFD settings starting with
     * the max MFD and min RFD and find the closest match less-than
     * or equal-to the desired output frequency
     */
    done = FALSE;
    for (mfd = mfd_max; mfd >= mfd_min; mfd-=2)
    {
        for (rfd = MIN_RFD; rfd < rfd_max; rfd <<= 1)
        {
            temp = fref * mfd / rfd;
            
            if (fout == temp)
            {
                /* exact match */
                done = TRUE;
                break;
            }
            if (fout > temp)
            {
                /* new upper bound for the rfd */
                rfd_max = rfd;
                /* is this the nearest match? */
                if ((rfd != 1) && ((fout - temp) < (fref / (rfd>>1))))
                    done = TRUE;
                break;
            }
        }
        if (done)
            break;
     }
    if (!done)
    {
        /* 
         * Fell out of loop before finding an exact match or getting 
         * as close as possible. Adjust mfd to nearest match.
         */
        mfd += 2;
    }
    
    fout = fref * mfd / rfd;

    /* Encode MFD and RFD settings */
    mfd = (mfd - MIN_MFD) / 2;
    for (i = 0; rfd > MIN_RFD; rfd >>= 1, i++) {};
    rfd = i;

    /*
     * Temp fix for PLL bug on Rev 0
     */
    if ((MCF_CIM_CIR & 0x003F) == 0)
        (*(vuint8 *)(&__IPSBAR[0x120006])) |= 0x04;

    if (!(flags & PLL_PRETEND))
    {
        /* 
         * Initialize the PLL to generate the new system clock frequency 
         * A higher divider is used first with the desired MFD.  Once 
         * locked, the desired RFD is applied
         */
        syncr = MCF_CLOCK_SYNCR & ~(0x7700);
        temp = (MCF_CLOCK_SYNCR & 0x7000) >> 12;
        MCF_CLOCK_SYNCR = syncr 
            | MCF_CLOCK_SYNCR_RFD(rfd + 1)
            | MCF_CLOCK_SYNCR_MFD(temp)
            | MCF_CLOCK_SYNCR_PLLEN;
        MCF_CLOCK_SYNCR = syncr 
            | MCF_CLOCK_SYNCR_RFD(rfd + 1)
            | MCF_CLOCK_SYNCR_MFD(mfd)
            | MCF_CLOCK_SYNCR_PLLEN;
            
       	/* Wait for the PLL to lock */	
    	while (!(MCF_CLOCK_SYNSR & MCF_CLOCK_SYNSR_LOCK)) {};

        /* Finish off the initialization */
        MCF_CLOCK_SYNCR = syncr
            | MCF_CLOCK_SYNCR_RFD(rfd)
            | MCF_CLOCK_SYNCR_MFD(mfd)
            | MCF_CLOCK_SYNCR_CLKSRC
            | MCF_CLOCK_SYNCR_PLLEN;
    }

    return fout;
}
/********************************************************************/
/*
 * Initialize the Low Power Divider circuit
 * 
 * Parameters:
 *  div     Desired system frequency divider
 *
 * Return Value:
 *  The divider value applied
 *  -1 if divider was out of valid bounds
 */
int
clock_lpd (int div)
{
    int i, j;

    /* Check bounds of divider */
    if ((div < MIN_LPD) || (div > MAX_LPD))
        return (1 << (MCF_CLOCK_LPCR & 0x0F));

    /* Round divider down to nearest power of two */
    for (i = 0, j = div; j != 1; j >>= 1, i++) 
    {};
    
    /* Apply the divider to the system clock */
    MCF_CLOCK_LPCR = MCF_CLOCK_LPCR_LPD(i);

    return (1 << i);
}
/********************************************************************/
/*
 * These functions control the PSTCLK/CLKOUT signal. Disabling the 
 * CLKOUT signal reduces power and EMI. However, some BDM interface
 * cables will rely on the PSTCLK/CLKOUT signal to clock the logic
 * that interfaces to the DSCLK, DSI, and DSO signals.
 */
void
clock_clkout_disable(void)
{
    MCF_CLOCK_SYNCR |= MCF_CLOCK_SYNCR_DISCLK;
}

void
clock_clkout_enable(void)
{
    MCF_CLOCK_SYNCR &= ~MCF_CLOCK_SYNCR_DISCLK;
}
/********************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -