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

继续在DEVICE_init函数中,下面是调用DEVICE_DDR2Init函数来配置DDR控制器,这是 UBL中重要的一部分,如果硬件电路需要更换内存芯片的话,需要在UBL中修改这个函数,即按照芯片手册来配置DDR控制寄存器中的相关参数,比如时 序,BANK数,页大小等。这个函数主要是操作SYS模块和DDR模块的相关寄存器来配置内存,函数中调用的DEVICE_LPSCTransition 函数用来实现模块的电源时钟状态的改变,函数内容如下:

Uint32 DEVICE_DDR2Init()
{
    DEVICE_LPSCTransition(LPSC_DDR2,0,PSC_ENABLE);
    
    SYSTEM->VTPIOCR = (SYSTEM->VTPIOCR) & 0xFFFF9F3F;
    
    // Set bit CLRZ (bit 13)
    SYSTEM->VTPIOCR = (SYSTEM->VTPIOCR) | 0x00002000;
    
    // Check VTP READY Status
    while( !(SYSTEM->VTPIOCR & 0x8000));
    
    // Set bit VTP_IOPWRDWN bit 14 for DDR input buffers)
    //SYSTEM->VTPIOCR = SYSTEM->VTPIOCR | 0x00004000; 

    // Set bit LOCK(bit7) and PWRSAVE (bit8)
    SYSTEM->VTPIOCR = SYSTEM->VTPIOCR | 0x00000080;
    
    // Powerdown VTP as it is locked (bit 6)
    // Set bit VTP_IOPWRDWN bit 14 for DDR input buffers)
    SYSTEM->VTPIOCR = SYSTEM->VTPIOCR | 0x00004040;
    
    // Wait for calibration to complete 
    UTIL_waitLoop( 150 );
    
    // Set the DDR2 to synreset, then enable it again
    DEVICE_LPSCTransition(LPSC_DDR2,0,PSC_SYNCRESET);
    DEVICE_LPSCTransition(LPSC_DDR2,0,PSC_ENABLE);
    
    DDR->DDRPHYCR = 0x000000C5;   
    DDR->SDBCR = 0x08D34832;        //Program SDRAM Bank Config Register
    DDR->SDBCR = 0x0853C832;    
    DDR->SDTIMR =0x3C934B51;        //Program SDRAM Timing Control Register1
    DDR->SDTIMR2 =0x4221C72;        //Program SDRAM Timing Control Register2
    DDR->PBBPR = 0x000000FE;   
    DDR->SDBCR = 0x08534832;        //Program SDRAM Bank Config Register   
    DDR->SDRCR = 0x00000768;        //Program SDRAM Refresh Control Register
 
    DEVICE_LPSCTransition(LPSC_DDR2,0,PSC_SYNCRESET);
    DEVICE_LPSCTransition(LPSC_DDR2,0,PSC_ENABLE);
    
    return E_PASS;
}

void DEVICE_LPSCTransition(Uint8 module, Uint8 domain, Uint8 state)
{
    // Wait for any outstanding transition to complete
    while ( (PSC->PTSTAT) & (0x00000001 << domain) );
    
    // If we are already in that state, just return
    if (((PSC->MDSTAT[module]) & 0x1F) == state) return;
    
    // Perform transition
    PSC->MDCTL[module] = ((PSC->MDCTL[module]) & (0xFFFFFFE0)) | (state);
    PSC->PTCMD |= (0x00000001 << domain);
    
    // Wait for transition to complete
    while ( (PSC->PTSTAT) & (0x00000001 << domain) );
    
    // Wait and verify the state
    while (((PSC->MDSTAT[module]) & 0x1F) != state);    
}

      而后调用DEVICE_EMIFInit函数来配置EMIF模块,这个模块用来接外存,比如NAND,NOR等。DM365有两个片选空间,如果某一空间配置成NAND,则需要在寄存器中设置,其函数内容如下:

Uint32 DEVICE_EMIFInit()
{    
    AEMIF->AWCCR = 0xff;   
    AEMIF->A1CR = 0x40400204;  
    AEMIF->NANDFCR |= 1;  
    AEMIF->A2CR = 0x00a00505;
    
    return E_PASS;   
}

      而后调用DEVICE_UART0Init函数来配置串口0,调用DEVICE_TIMER0Init函数来配置TIMER0,调用 DEVICE_I2C0Init函数来配置I2C控制器,都是操作某一模块的控制寄存器实现,具体如何设置可以参考相关模块的手册,这三个函数的内容如 下:

Uint32 DEVICE_UART0Init()
{    
    UART0->PWREMU_MGNT = 0; // Reset UART TX & RX components

    UTIL_waitLoop( 100 );
    
    UART0->MDR = 0x0;
    UART0->DLL = 0xd; // Set baud rate    
    UART0->DLH = 0;
     
    UART0->FCR = 0x0007; // Clear UART TX & RX FIFOs
    UART0->FCR = 0x0000; // Non-FIFO mode
    UART0->IER = 0x0007; // Enable interrupts

    UART0->LCR = 0x0003; // 8-bit words
    // 1 STOP bit generated,
    // No Parity, No Stick paritiy,
    // No Break control
 
    UART0->MCR = 0x0000; // RTS & CTS disabled,
    // Loopback mode disabled,
    // Autoflow disabled
 
    UART0->PWREMU_MGNT = 0xE001; // Enable TX & RX componenets
 
    return E_PASS;
}

Uint32 DEVICE_I2C0Init()
{
    I2C0->ICMDR = 0; // Reset I2C
    I2C0->ICPSC = 26; // Config prescaler for 27MHz
    I2C0->ICCLKL = 20; // Config clk LOW for 20kHz
    I2C0->ICCLKH = 20; // Config clk HIGH for 20kHz
    I2C0->ICMDR |= I2C_ICMDR_IRS; // Release I2C from reset
    
    return E_PASS;
}

Uint32 DEVICE_TIMER0Init()
{
    // Put timer into reset
    TIMER0->EMUMGT_CLKSPD = 0x00000003;
    TIMER0->TCR = 0x00000000;
    
    // Enable TINT0, TINT1 interrupt
    TIMER0->INTCTL_STAT = 0x00000001;
    
    // Set to 64-bit GP Timer mode, enable TIMER12 & TIMER34
    TIMER0->TGCR = 0x00000003;
    
    // Reset timers to zero 
    TIMER0->TIM12 = 0x00000000;
    TIMER0->TIM34 = 0x00000000;
    
    // Set timer period (5 second timeout = (24000000 * 5) cycles = 0x07270E00) 
    TIMER0->PRD34 = 0x00000000;
    TIMER0->PRD12 = 0x07270E00;
    
    return E_PASS;
}

      至此,DEVICE_init函数结束,程序返回至LOCAL_boot函数中,接着就调用NANDBOOT_copy函数了。