1,TMS320F28069 学习--------InitSysCtrl();

建工程的时候用到一个GPIO的例程

其中调用的第一个函数就是InitSysCtrl(); 今天详细了解一下这个函数都干了什么事情

void
InitSysCtrl(void)
{
    //
    // Disable the watchdog
    //
    DisableDog();

    //
    // *IMPORTANT*
    // The Device_cal function, which copies the ADC & oscillator calibration 
    // values from TI reserved OTP into the appropriate trim registers, occurs 
    // automatically in the Boot ROM. If the boot ROM code is bypassed during 
    // the debug process, the following function MUST be called for the ADC and
    // oscillators to function according to specification. The clocks to the 
    // ADC MUST be enabled before calling this function.
    // See the device data manual and/or the ADC Reference
    // Manual for more information.
    //
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1; // Enable ADC peripheral clock
    (*Device_cal)();
    SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 0; // Return ADC clock to original state
    EDIS;

    //
    // Select Internal Oscillator 1 as Clock Source (default), and turn off all
    // unused clocks to conserve power.
    //
    IntOsc1Sel();

    //
    // Initialize the PLL control: PLLCR and CLKINDIV
    // DSP28_PLLCR and DSP28_CLKINDIV are defined in F2806x_Examples.h
    //
    InitPll(DSP28_PLLCR,DSP28_DIVSEL);

    //
    // Initialize the peripheral clocks
    //
    InitPeripheralClocks();
}

先是调用了下面这个函数

void
DisableDog(void)
{
    EALLOW;
    SysCtrlRegs.WDCR= 0x0068;
    EDIS;
}

#define  EALLOW __asm(" EALLOW")   -->猜测是EN ALLOW 的缩写   使能允许位,就是把EALLOW Bit 置1 ,去保护
#define  EDIS   __asm(" EDIS")  -->猜测是 EN DISABLE的缩写  使能禁用位,就是把EALLOW Bit置0,写保护

器件仿真寄存器、FLASH寄存器、CSM寄存器、PIE 矢量表、系统控制寄存器、GPIO MUX 寄存器、在操作这些寄存器之前需要去保护,操作完需要写保护 

SysCtrlRegs.WDCR= 0x0068;

WDPS        000  WDCLK = OSCCLK/512/1 (default)

WDCHK     101  You must ALWAYS write 1,0,1

WDDIS       1      Disables the watchdog module.

WDFLAG    0

接下来这段

    EALLOW;   
    SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1; // Enable ADC peripheral clock
    (*Device_cal)();
    SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 0; // Return ADC clock to original state
    EDIS;

SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;   

SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 0; 

 开启ADC的时钟   很奇怪啊 为什么要把ADC的时钟打开软后又关了

仔细看,上面有段话  标注  important 

仔细看了一下 大概的意思是   Device_cal  函数存在TI的预留存储中用来校准ADC和振荡器的

追踪一下这个函数 #define Device_cal (void   (*)(void))0x3D7C80  是一个函数指针 位置是0x3D7C80 

好 接下来

IntOsc1Sel(); 初始化振荡器 

void
IntOsc1Sel(void)
{
    EALLOW;
    SysCtrlRegs.CLKCTL.bit.INTOSC1OFF = 0;
    SysCtrlRegs.CLKCTL.bit.OSCCLKSRCSEL=0;  // Clk Src = INTOSC1
    SysCtrlRegs.CLKCTL.bit.XCLKINOFF=1;     // Turn off XCLKIN
    SysCtrlRegs.CLKCTL.bit.XTALOSCOFF=1;    // Turn off XTALOSC
    SysCtrlRegs.CLKCTL.bit.INTOSC2OFF=1;    // Turn off INTOSC2
    EDIS;
}

现在内部时钟已经到了锁相环的入口处(PLL)   果然下一句就是配置PLL的

InitPll(DSP28_PLLCR,DSP28_DIVSEL);

​
void
InitPll(Uint16 val, Uint16 divsel)
{
    volatile Uint16 iVol;

    // Make sure the PLL is not running in limp mode
    if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0)
    {
    EALLOW;
    // OSCCLKSRC1 failure detected. PLL running in limp mode.
    // Re-enable missing clock logic.
    SysCtrlRegs.PLLSTS.bit.MCLKCLR = 1;
    EDIS;
    // Replace this line with a call to an appropriate
    // SystemShutdown(); function.
    __asm("        ESTOP0");     // Uncomment for debugging purposes
    }

    // DIVSEL MUST be 0 before PLLCR can be changed from
    // 0x0000. It is set to 0 by an external reset XRSn
    // This puts us in 1/4
    if (SysCtrlRegs.PLLSTS.bit.DIVSEL != 0)
    {
    EALLOW;
    SysCtrlRegs.PLLSTS.bit.DIVSEL = 0;
    EDIS;
    }

    //
    // Change the PLLCR
    //
    if (SysCtrlRegs.PLLCR.bit.DIV != val)
    {
        EALLOW;
        
        //
        // Before setting PLLCR turn off missing clock detect logic
        //
        SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;
        SysCtrlRegs.PLLCR.bit.DIV = val;
        EDIS;
        
        //
        // Optional: Wait for PLL to lock.
        // During this time the CPU will switch to OSCCLK/2 until
        // the PLL is stable.  Once the PLL is stable the CPU will
        // switch to the new PLL value.
        //
        // This time-to-lock is monitored by a PLL lock counter.
        //
        // Code is not required to sit and wait for the PLL to lock.
        // However, if the code does anything that is timing critical,
        // and requires the correct clock be locked, then it is best to
        // wait until this switching has completed.
        //

        //
        // Wait for the PLL lock bit to be set.
        //

        //
        // The watchdog should be disabled before this loop, or fed within
        // the loop via ServiceDog().
        //
        
        //
        // Uncomment to disable the watchdog
        //
        DisableDog();

        while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1)
        {
            //
            // Uncomment to service the watchdog
            //
            //ServiceDog();
        }

        EALLOW;
        SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0;
        EDIS;
    }

    //
    // If switching to 1/2
    //
    if((divsel == 1)||(divsel == 2))
    {
        EALLOW;
        SysCtrlRegs.PLLSTS.bit.DIVSEL = divsel;
        EDIS;
    }

    //
    // If switching to 1/1
    // * First go to 1/2 and let the power settle
    //   The time required will depend on the system, this is only an example
    // * Then switch to 1/1
    //
    if(divsel == 3)
    {
        EALLOW;
        SysCtrlRegs.PLLSTS.bit.DIVSEL = 2;
        DELAY_US(50L);
        SysCtrlRegs.PLLSTS.bit.DIVSEL = 3;
        EDIS;
    }
}

​

val = DSP28_PLLCR    divsel =  DSP28_DIVSEL   2

#define DSP28_PLLCR   18 
#define DSP28_DIVSEL   2

 if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0)  //确保PLL不工作在limp mode下,也就是有时钟输入到PLL,前面已经讲过
    {
    EALLOW;
    SysCtrlRegs.PLLSTS.bit.MCLKCLR = 1;    //如果时钟丢失就执行 ,清除标注位,再进行检测
    EDIS;                                                           //程序注释,如果时钟丢失可以在这里添加停机函数,我目前没用到
    __asm("        ESTOP0"); 
    }
 

    if (SysCtrlRegs.PLLSTS.bit.DIVSEL != 0)  //不管分频是多少 都归零
    {
    EALLOW;
    SysCtrlRegs.PLLSTS.bit.DIVSEL = 0;
    EDIS;
    }

    if (SysCtrlRegs.PLLCR.bit.DIV != val)      设置倍频系数
    {
        EALLOW;

        SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;    //先关掉故障检测模块
        SysCtrlRegs.PLLCR.bit.DIV = val;
        EDIS;

        DisableDog();

        while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1)
        {

            //ServiceDog();
        }

        EALLOW;
        SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0;
        EDIS;
    }

接下来设置分频

    if((divsel == 1)||(divsel == 2))
    {
        EALLOW;
        SysCtrlRegs.PLLSTS.bit.DIVSEL = divsel;
        EDIS;
    }

    //
    // If switching to 1/1
    // * First go to 1/2 and let the power settle
    //   The time required will depend on the system, this is only an example
    // * Then switch to 1/1
    //
    if(divsel == 3)
    {
        EALLOW;
        SysCtrlRegs.PLLSTS.bit.DIVSEL = 2;
        DELAY_US(50L);
        SysCtrlRegs.PLLSTS.bit.DIVSEL = 3;
        EDIS;
    }

PLL的框图

主频90MHz 就是这样配出来的

90 MHz devices [90 MHz = (10MHz * 18)/2]

接下来就是设置各个外设的时钟是否开启了,根据自己的需要自己配置即可,

InitPeripheralClocks();

GPIO的时钟在下面这个图中标出了 是从SYSCLKOUT过去的

好了 今天就写到这里吧   

2020.02.15

发布了6 篇原创文章 · 获赞 0 · 访问量 1046

猜你喜欢

转载自blog.csdn.net/Rocky_Zou/article/details/104328695