DM365的UBL源码分析(二)

转自:http://blog.chinaunix.net/space.php?uid=7214824&do=blog&id=160522

书接上回,看看UBL对平台的初始化,主要是调用了DEVICE_init函数,函数内容如下:

Uint32 DEVICE_init()
{
    Uint32 status = E_PASS;
    
    // Mask all interrupts
    AINTC->INTCTL = 0x4;
    AINTC->EABASE = 0x0;
    AINTC->EINT0 = 0x0;
    AINTC->EINT1 = 0x0;        
    
    // Clear all interrupts
    AINTC->FIQ0 = 0xFFFFFFFF;
    AINTC->FIQ1 = 0xFFFFFFFF;
    AINTC->IRQ0 = 0xFFFFFFFF;
    AINTC->IRQ1 = 0xFFFFFFFF;
    
#ifndef SKIP_LOW_LEVEL_INIT
    
    POR_RESET();
    
    // System PSC setup - enable all
    DEVICE_PSCInit();
    
    DEVICE_pinmuxControl(0,0xFFFFFFFF,0x00FD0000); // All Video Inputs

    DEVICE_pinmuxControl(1,0xFFFFFFFF,0x00145555); // All Video Outputs

    DEVICE_pinmuxControl(2,0xFFFFFFFF,0x000000DA); // EMIFA

    DEVICE_pinmuxControl(3,0xFFFFFFFF,0x00180000); // SPI0, SPI1, UART1, I2C, SD0, SD1, McBSP0, CLKOUTs

    DEVICE_pinmuxControl(4,0xFFFFFFFF,0x55555555); // MMC/SD0 instead of MS, SPI0

    
    GPIO->DIR02 &= 0xfeffffff;
    GPIO->CLRDATA02 = 0x01000000;
    
    // System PLL setup
    if (status == E_PASS) status |= DEVICE_PLL1Init(PLL1_Mult);
    
    // DDR PLL setup
    if (status == E_PASS) status |= DEVICE_PLL2Init();
    
    // DDR2 module setup
    if (status == E_PASS) status |= DEVICE_DDR2Init();
#endif
    
    // AEMIF Setup
    if (status == E_PASS) status |= DEVICE_EMIFInit();
    
    // UART0 Setup
    if (status == E_PASS) status |= DEVICE_UART0Init();
    
    // TIMER0 Setup
    if (status == E_PASS) status |= DEVICE_TIMER0Init();
    
    // I2C0 Setup
    if (status == E_PASS) status |= DEVICE_I2C0Init();
    
    return status;
}

      首先屏蔽和清除中断,然后调用DEVICE_PSCInit函数实现对各模块的电源时钟使能,实质是调用PSC电源时钟管理模块的寄存器实现,函数内容如下:

void DEVICE_PSCInit()
{    
    unsigned char i=0;
    unsigned char lpsc_start;
    unsigned char lpsc_end,lpscgroup,lpscmin,lpscmax;
    unsigned int PdNum = 0;
    
    lpscmin =0;
    lpscmax =2;
    
    for(lpscgroup=lpscmin ; lpscgroup <=lpscmax; lpscgroup++) {
        if(lpscgroup==0)
        {
            lpsc_start = 0; // Enabling LPSC 3 to 28 SCR first

            lpsc_end = 28;
        }
        else if (lpscgroup == 1) { /* Skip locked LPSCs [29-37] */
            lpsc_start = 38;
            lpsc_end = 47;
        } else {
            lpsc_start = 50;
            lpsc_end = 51;
        }
        
        //NEXT=0x3, Enable LPSC's
        for(i=lpsc_start; i<=lpsc_end; i++) {
            PSC->MDCTL[i] |= 0x3;
        }
        
        //Program goctl to start transition sequence for LPSCs
        PSC->PTCMD = (1<<PdNum);
        
        //Wait for GOSTAT = NO TRANSITION from PSC for Pdomain 0
        while(! (((PSC->PTSTAT >> PdNum) & 0x00000001) == 0));
        
        //Wait for MODSTAT = ENABLE from LPSC's
        for(i=lpsc_start; i<=lpsc_end; i++) {
            while(!((PSC->MDSTAT[i] & 0x0000001F) == 0x3));             
        }    
    }    
    
}

      然后调用DEVICE_pinmuxControl函数决定复用引脚的功能选择,详见数据手册查看引脚功能。

      接着调用DEVICE_PLL1Init函数实现了PLL1的配置,预分频,倍频,后分频,分频到各个模块,其设置顺序可以参看用户指南ARM子系统文档,有详细的介绍,PLL2类似不再赘述,函数内容如下:

Uint32 DEVICE_PLL1Init(Uint32 PLLMult)
{
    unsigned int CLKSRC=0x0;             
    unsigned int j;
    
    /*Power up the PLL*/
    PLL1->PLLCTL &= 0xFFFFFFFD;        
    
    PLL1->PLLCTL &= 0xFFFFFEFF;             
    PLL1->PLLCTL |= CLKSRC<<8;
    
    /*Set PLLENSRC '0', PLL Enable(PLLEN) selection is controlled through MMR*/
    PLL1->PLLCTL &= 0xFFFFFFDF;    
    
    /*Set PLLEN=0 => PLL BYPASS MODE*/
    PLL1->PLLCTL &= 0xFFFFFFFE;
    
    UTIL_waitLoop(150);                 
    
    // PLLRST=1(reset assert)
    PLL1->PLLCTL |= 0x00000008; 
    
    UTIL_waitLoop(300);
    
    /*Bring PLL out of Reset*/
    PLL1->PLLCTL &= 0xFFFFFFF7;
    
    //Program the Multiper and Pre-Divider for PLL1
    PLL1->PLLM = 0x51; // VCO will 24*2M/N+1 = 486Mhz

    PLL1->PREDIV = 0x8000|0x7;
    
    PLL1->SECCTL = 0x00470000; // Assert TENABLE = 1, TENABLEDIV = 1, TINITZ = 1 
    PLL1->SECCTL = 0x00460000; // Assert TENABLE = 1, TENABLEDIV = 1, TINITZ = 0 
    PLL1->SECCTL = 0x00400000; // Assert TENABLE = 0, TENABLEDIV = 0, TINITZ = 0 
    PLL1->SECCTL = 0x00410000; // Assert TENABLE = 0, TENABLEDIV = 0, TINITZ = 1    
  
    //Program the PostDiv for PLL1
    PLL1->POSTDIV = 0x8000;
    
    // Post divider setting for PLL1     
    PLL1->PLLDIV2 = 0x8001;
    PLL1->PLLDIV3 = 0x8001; // POST DIV 486/2 -> MJCP/HDVICP
    PLL1->PLLDIV4 = 0x8003; // POST DIV 486/4 -> EDMA/EDMA CFG
    PLL1->PLLDIV5 = 0x8001; // POST DIV 486/2 -> VPSS
    PLL1->PLLDIV6 = 0x8011; // 27Mhz POST DIV 486/18 -> VENC
    PLL1->PLLDIV7 = 0x8000; // POST DIV 486/2 -> DDR
    PLL1->PLLDIV8 = 0x8003; // POST DIV 486/4 -> MMC0/SD0
    PLL1->PLLDIV9 = 0x8001; // POST DIV 486/2 -> CLKOUT

    UTIL_waitLoop(300);
    
    /*Set the GOSET bit */
    PLL1->PLLCMD = 0x00000001; // Go

    UTIL_waitLoop(300);
        
    /*Wait for PLL to LOCK */
    while(! (((SYSTEM->PLL0_CONFIG) & 0x07000000) == 0x07000000));    
    
    /*Enable the PLL Bit of PLLCTL*/
    PLL1->PLLCTL |= 0x00000001; // PLLEN=0
  
    return E_PASS;
}

 

你可能感兴趣的:(职场,分析,休闲,UBL)