转自: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函数了。
转载于:https://blog.51cto.com/ttsky138/655404