DM368开发 -- 再论 UBL
来源:互联网 发布:linux 安装万兆网卡 编辑:程序博客网 时间:2024/06/05 17:06
参看:UBI - Unsorted Block Images
参看:DM36x UBL PLL配置
UBL 前两篇文章中我们有提到过了。
参看:DM368开发 -- 文件烧写
参看:DM368开发 -- Bootloader 开发
简单点来说,UBL 主要功能是实现将 U-boot 代码拷贝到 DDR2 内存中,建立运行环境并引导U-boot。
但是现在我有个问题,我想让 DM368 开发板运行在 432 Mhz,目前它的状态是 AR, 297 Mhz 、DDR 为243Mhz。
具体操作为,修改 /psp/flash-utils/DM36x/Common/Src/device.c 相关的设置。
一、修改内核电源电压
当然,DM368主频大小除了与UBL有关外,还与ARM内核电源电压有关。 当为1.2v时,主频不能达到432Mhz的,只有为1.35v的时候才能达到。所以需要将 ARM 内核电源电压设为1.35v。
The TPS65023 has a 7-bit address:?1001000, other addresses are available upon contact with the factory
则 tps64023的设备地址应为 0x48 ,说明有这个 I2C 设备的。
root@dm368-evm:~# i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f00: -- -- -- -- -- 08 -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- UU -- -- 60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 70: -- -- -- UU -- -- -- --通过i2ctool修改寄存器: 主要有关的寄存器为05和06如下图:
i2cset -f -y 1 0x48 0x05 0x80i2cget -f -y 1 0x48 0x05i2cset -f -y 1 0x48 0x06 0x16i2cget -f -y 1 0x48 0x06OK!!! 有电压1.35v。
二、修改 UBL 源码
How can I modify Leopardboard DM368 running on 432MHz
Timing DDR DM368 MT47H64M16HR-25E IT:H
DM368 (Performance & Power Consumption)
DDR2/mDDR Memory Controller User's Guide
Setting up AM35x SDRC registers
About this Guide
This is reference guide to port UBL for DM368 using DM365 UBL code base. This guide helps to configure PLLs to run ARM@432 and DDR@340 with 24MHz crystal oscillator. Modify PLL1, PLL2 and DDR setup function in DM36x/Common/src/device.c as explained in below sections.
PLL1 Setup
Modify DEVICE_PLL1Init(PLL1_Mult) function for 680MHz by replacing configurations of PLL1 multipliers, pre and post divisors as below
//Program the Multiper and Pre-Divider for PLL1 PLL1->PLLM = 0x55; // VCO will 24*2M/N+1 PLL1->PREDIV = 0x8000|0x5; // Post divider setting for PLL1 PLL1->PLLDIV1 = 0x801B; PLL1->PLLDIV2 = 0x8001; PLL1->PLLDIV3 = 0x8001; // POST DIV 680/2 = 340Mhz -> MJCP and HDVICP bus interface clock PLL1->PLLDIV4 = 0x8003; // POST DIV 680/4 = 170Mhz -> EDMA/Peripheral CFG0(1/2 MJCP/HDVICP bus interface clk) PLL1->PLLDIV5 = 0x8001; // POST DIV 680/2 = 340Mhz -> VPSS PLL1->PLLDIV6 = 0x8008; // POST DIV 680/9 = 75.6 Mhz -> VENC PLL1->PLLDIV7 = 0x8000; // POST DIV 680/1 = 680Mhz -> DDRx2(with internal divider of 2, clock boils down to 340 Mhz) PLL1->PLLDIV8 = 0x8006; // POST DIV 680/7= 97Mhz-> MMC0/SD0 PLL1->PLLDIV9 = 0x801B; // POST DIV 680/28 = 24.3Mhz-> CLKOUT
PLL2 Setup
Modify DEVICE_PLL2Init()function for 432MHz by replacing configurations PLL2 multipliers, pre and post divisor as below
//Program the Multiper and Pre-Divider for PLL2 PLL2->PLLM = 0x9; // VCO will 24*2M/N+1 = 432Mhz PLL2->PREDIV = 0x8000|0x0; // Post divider setting for PLL2 PLL2->PLLDIV1 = 0x8011; PLL2->PLLDIV2 = 0x8000; // POST DIV 432/1=432 Mhz -> ARM926/(HDVICP block) clk PLL2->PLLDIV3 = 0x8001; PLL2->PLLDIV4 = 0x8014; // POST DIV 432/21= 20.5714 Mhz->VOICE Codec clk PLL2->PLLDIV5 = 0x800F; // POST DIV 432/16=27 Mhz -> VENC(For SD modes, requires )
NOTE
- For configuration details of PLL Controllers (PLL1 and PLL2) look into TMS320DM36x ARM Subsystem Reference Guide (literature number SPRUFG5).
- Make sure PLLC1_SYSCLK6 is selected for HD modes and is done by configuring VPSS_CLK_CTRL register(i.e. VPSS_CLK_CTRL = 0x18) in drivers/media/video/davinci/davinci_platform.c. VENC requires clock of 74.25Mhz for HD modes to work properly. HD output is tested on TV with above derived clock of 68Mhz.
- Make sure PLLC2_SYSCLK5 is selected for SD modes and is done by configuring VPSS_CLK_CTRL register(i.e. VPSS_CLK_CTRL = 0x38) in drivers/media/video/davinci/davinci_platform.c. VENC requires clock of 27Mhz for SD modes to work properly.
DDR2 Setup
Modify DEVICE_DDR2Init() for 340MHZ by replacing SDR bank and timing configurations as below
DDR->DDRPHYCR = 0x000000C6; DDR->SDBCR = 0x00D34A32; //Program SDRAM Bank Config Register DDR->SDBCR = 0x0053CA32; DDR->SDTIMR =0x576D7D12; //Program SDRAM Timing Control Register1 DDR->SDTIMR2 =0x422EC742; //Program SDRAM Timing Control Register2 DDR->PBBPR = 0x000000FE; DDR->SDBCR = 0x08534832; //Program SDRAM Bank Config Register DDR->SDRCR = 0xA5C; //Program SDRAM Refresh Control Register
NOTE
The timing configuration done above are specific to DDR part present on the evm's. Please refer DDR device data sheet for information.
Build steps
- Open DM36x/CCS/UBL/UBL.pjt UBL project.
- Make sure you selected BOOT_NAND configuration from active configuration drop down.
- Build the project and new binary at DM36x\CCS\UBL\UBL_DM36x_NAND.bin does the PLL configurations to run ARM@432 and DDR@340.
//Program the Multiper and Pre-Divider for PLL1//cjk add down// PLL1->PLLM = 0x51; // VCO will 24*2M/N+1 = 486Mhz//PLL1->PREDIV = 0x8000|0x7; PLL1->PLLM = 0x55; // VCO will 24*2M/N+1 PLL1->PREDIV = 0x8000|0x5; //cjk add up //cjk add down#if 0 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#endifPLL1->PLLDIV1 = 0x801B; PLL1->PLLDIV2 = 0x8001; PLL1->PLLDIV3 = 0x8001; // POST DIV 680/2 = 340Mhz -> MJCP and HDVICP bus interface clock PLL1->PLLDIV4 = 0x8003; // POST DIV 680/4 = 170Mhz -> EDMA/Peripheral CFG0(1/2 MJCP/HDVICP bus interface clk) PLL1->PLLDIV5 = 0x8001; // POST DIV 680/2 = 340Mhz -> VPSS PLL1->PLLDIV6 = 0x8008; // POST DIV 680/9 = 75.6 Mhz -> VENC PLL1->PLLDIV7 = 0x8000; // POST DIV 680/1 = 680Mhz -> DDRx2(with internal divider of 2, clock boils down to 340 Mhz) PLL1->PLLDIV8 = 0x8006; // POST DIV 680/7= 97Mhz-> MMC0/SD0 PLL1->PLLDIV9 = 0x801B; // POST DIV 680/28 = 24.3Mhz-> CLKOUT//cjk add up//cjk add down //PLL2->PLLM = 0x63; // VCO will 24*2M/N+1 = 594Mhz //PLL2->PREDIV = 0x8000|0x7; PLL2->PLLM = 0x9; // VCO will 24*2M/N+1 = 432Mhz PLL2->PREDIV = 0x8000|0x0; //cjk add up //cjk add down#if 0 PLL2->PLLDIV2 = 0x8001; // 594/2 =297 Mhz -> ARM PLL2->PLLDIV4 = 0x801C; // POST DIV 594/29 = 20.48 -> VOICE PLL2->PLLDIV5 = 0x8007; // POST DIV 594/8 = 74.25 ->VIDEO HD #endif PLL2->PLLDIV1 = 0x8011; PLL2->PLLDIV2 = 0x8000; // POST DIV 432/1=432 Mhz -> ARM926/(HDVICP block) clk PLL2->PLLDIV3 = 0x8001; PLL2->PLLDIV4 = 0x8014; // POST DIV 432/21= 20.5714 Mhz->VOICE Codec clk PLL2->PLLDIV5 = 0x800F; // POST DIV 432/16=27 Mhz -> VENC(For SD modes, requires )//cjk add up //cjk add down #if 0 DDR->DDRPHYCR = 0x000000C5; DDR->SDBCR = 0x08D34832;//Program SDRAM Bank Config RegisterDDR->SDBCR = 0x0853C832; DDR->SDTIMR =0x3C934B51;//Program SDRAM Timing Control Register1DDR->SDTIMR2 =0x4221C72;//Program SDRAM Timing Control Register2DDR->PBBPR = 0x000000FE;DDR->SDBCR = 0x08534832;//Program SDRAM Bank Config RegisterDDR->SDRCR = 0x00000768;//Program SDRAM Refresh Control Register #endif DDR->DDRPHYCR = 0x000000C6; DDR->SDBCR = 0x00D34A32; //Program SDRAM Bank Config Register DDR->SDBCR = 0x0053CA32; DDR->SDTIMR =0x576D7D12; //Program SDRAM Timing Control Register1 DDR->SDTIMR2 =0x422EC742; //Program SDRAM Timing Control Register2 DDR->PBBPR = 0x000000FE; DDR->SDBCR = 0x08534832; //Program SDRAM Bank Config Register DDR->SDRCR = 0xA5C; //Program SDRAM Refresh Control Register //cjk add up
三、UBL 编译
四、UBL源码分析
DM365是的启动方式有两种,通过BOOTSEL[2:0]引脚决定。当其为001时,直接从AEMIF上启 动,比如NOR和OneNAND。除此之外皆是从RBL启动,顺序为RBL-UBL-UBOOT-KERNEL,比如NAND,串口,SD卡等。RBL会 搜寻block1到block24去找UBL,关于RBL启动的详细细节可以参考用户指南关于ARM子系统的那篇文档,很详尽,下面只分析UBL的源码。
// Main entry point
void main(void)
{
// Call to real boot function code
LOCAL_boot();
// Jump to entry point
DEBUG_printString("\r\nJumping to entry point at ");
DEBUG_printHexInt(gEntryPoint);
DEBUG_printString(".\r\n");
APPEntry = (void(*)(void)) gEntryPoint;
(*APPEntry)();
}
main函数主要调用了LOCAL_boot函数来进行实质的引导功能,下面是此函数的内容:
static Uint32 LOCAL_boot(void)
{
DEVICE_BootMode bootMode;
// Read boot mode
bootMode = DEVICE_bootMode();
if (bootMode== DEVICE_BOOTMODE_UART)
{
// Wait until the RBL is done using the UART.
while((UART0->LSR& 0x40)== 0 );
}
// Platform Initialization
if ( DEVICE_init()!= E_PASS)
{
DEBUG_printString(devString);
DEBUG_printString(" initialization failed!\r\n");
asm(" MOV PC, #0");
}
else
{
DEBUG_printString(devString);
DEBUG_printString(" initialization passed!\r\n");
}
// Set RAM pointer to beginning of RAM space
UTIL_setCurrMemPtr(0);
// Send some information to host
DEBUG_printString("TI UBL Version: ");
DEBUG_printString(UBL_VERSION_STRING);
DEBUG_printString("\r\nBooting Catalog Boot Loader\r\nBootMode = ");
// Select Boot Mode
#if defined(UBL_NAND)
{
//Report Bootmode to host
DEBUG_printString("NAND\r\n");
// Copy binary image application from NAND to RAM
if (NANDBOOT_copy()!= E_PASS)
{
DEBUG_printString("NAND Boot failed.\r\n");
LOCAL_bootAbort();
}
}
#elif defined(UBL_NOR)
{
//Report Bootmode to host
DEBUG_printString("NOR \r\n");
// Copy binary application image from NOR to RAM
if (NORBOOT_copy()!= E_PASS)
{
DEBUG_printString("NOR Boot failed.\r\n");
LOCAL_bootAbort();
}
}
#elif defined(UBL_SD_MMC)
{
//Report Bootmode to host
DEBUG_printString("SD/MMC \r\n");
// Copy binary of application image from SD/MMC card to RAM
if (SDMMCBOOT_copy()!= E_PASS)
{
DEBUG_printString("SD/MMC Boot failed.\r\n");
LOCAL_bootAbort();
}
}
#else
{
//Report Bootmode to host
DEBUG_printString("UART\r\n");
UARTBOOT_copy();
}
#endif
DEBUG_printString(" DONE");
UTIL_waitLoop(10000);
DEVICE_TIMER0Stop();
return E_PASS;
}
先通过调用DEVICE_bootMode函数来判断启动方式(通过读取SYS寄存器实现),而后调用了DEVICE_init函数来进行平台的最底层初始化,包括电源域,时钟,DDR,EMIF,UART,I2C,TIMER等,另有专篇分析。
而后通过UTIL_setCurrMemPtr函数对全局变量currMemPtr赋值,以后用到。接着通过判断不同的引导方式,采取不同的处理办法,以 NAND启动为例,将调用NANDBOOT_copy函数,此函数另有专篇分析。此函数将NAND中的某些内容(就是UBOOT)搬移到RAM中,而后 UBL结束,控制权正式交给UBOOT。
书接上回,看看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;
}
继续在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函数了。
下面继续分析,由于后面的代码和函数量相对的多且复杂,所以不再贴上代码,只说流程,只要把程序源码打开对着看很容易就明白了。
五、DM36X 的UBL移植
- DM368开发 -- 再论 UBL
- DAVINCI DM365-DM368开发攻略——U-BOOT-2010.12及UBL的移植
- DAVINCI DM365-DM368开发攻略——U-BOOT-2010.12及UBL的移植
- DAVINCI DM365-DM368开发攻略——U-BOOT-2010.12及UBL的移植
- DAVINCI DM365-DM368开发攻略——U-BOOT-2010.12及UBL的移植
- DAVINCI DM365-DM368开发攻略——U-BOOT-2010.12及UBL的移植
- DAVINCI DM365-DM368开发攻略——U-BOOT-2010.12及UBL的移植
- DAVINCI DM365-DM368开发攻略——U-BOOT-2010.12及UBL的移植
- DAVINCI DM365-DM368开发攻略——U-BOOT-2010.12及UBL的移植
- DAVINCI DM365-DM368开发攻略——U-BOOT-2010.12及UBL的移植
- TI davinci DM368 UBL 编译方法
- DM368 UBL和u-boot的裁剪
- DM368 UBL和u-boot的裁剪 .
- DM368 ubl和uboot的裁剪
- DAVINCI DM365-DM368开发攻略—U-boot-2010.12-rc2-psp03.01.01.39及UBL的移植 .
- DM368开发 -- 硬件认识
- DM368开发 -- 环境搭建
- DM368开发 -- uboot 使用
- Android判断手机是数据连接还是wifi连接
- jquery 文字无缝滚动
- Socket的Connected属性
- Android Calendar获取年月日时分秒毫秒
- 极光推送
- DM368开发 -- 再论 UBL
- Tensorflow安装
- PMP
- 量子计算入门-第二部分
- exit函数和_exit函数之间的区别
- MongoDB一个基于分布式文件存储的数据库(介于关系数据库和非关系数据库之间的数据库)
- 数论——洛谷 P1445 没占到1444的愤怒
- sql语句中select……as的用法
- Struts2框架action传入页面list对象集合,修改对象集合数据后提交给action