[url=][/url]
static void init_autorun_timer(int sec){U32 val = (PCLK>>4)/100-1;autorun_10ms = sec*100;pISR_TIMER4 = (U32)autorun_proc;rTCFG0 &= ~(0xff<<8);rTCFG0 |= 3<<8; //prescaler 1 = 3+1 ,for Timer 2,3,4rTCFG1 &= ~(0xf<<16);rTCFG1 |= 1<<16; //mux = 1/4 ,for Timer 4rTCNTB4 = val; //val = (PCLK>>4)/100-1rTCON &= ~(0xf<<20);rTCON |= 7<<20; //interval, inv-off, update TCNTB4&TCMPB4[占空比], start timer 4rTCON &= ~(2<<20); //clear manual update bitEnableIrq(BIT_TIMER4); //清0对应位,使能对应中断}static __irq void autorun_proc(void){ClearPending(BIT_TIMER4);if(autorun_ds) //自动运行标识位,为1时禁止自动运行;系统启动时有按键按下时为1 DisableIrq(BIT_TIMER4); //禁能对应中断autorun_10ms--;if(!autorun_10ms) //当中断一百次时执行下面的程序{ DisableIrq(BIT_TIMER4); //CLR_IF(); //in irq service routine, irq is disabled //autorun_trig = 1; //masked by lqm! //NandLoadRun(); //NandLoadRun_wince();//added by lqm,2008-06-29 ?????????不能加载????????? EnRunWINCE=1;}}[url=][/url]
中断程序中有个变量EnRunWINCE,默认为0.当autorun_10ms值减到0后,即定时的时间已到,
这时EnRunWINCE=1,后面的程序通过该变量判断时间到了,然后执行自动加载NK的代码。
具体代码如下:
if(EnRunWINCE){ NandLoadRun_wince();}
三:LCD设置
bootloader运行时可以附加显示开机图片,这就需要对LCD控制器的相关寄存器进行设置。
由于寄存器较多,这里不一一列举,仅给LCD显示的函数如下:
[url=][/url]
void LCD_Play(){U32 i,j,k;U32* palette;Lcd_Init();LcdBkLtSet( 70 ) ;//背光PWM设置Lcd_PowerEnable(0, 1); Lcd_EnvidOnOff(1); //turn on vedio for(k=0,j=0;j<LCD_YSIZE_TFT_320240;j++) for(i=0;i<LCD_XSIZE_TFT_320240;i++) { PutPixel(i,j,ackj[k++]); }}[url=][/url]
四:USB,MMU,ISR,DMA等寄存器的设置
这里尤其是USB和DMA的寄存器设置,由于下载BIN文件是通过USB走的DMA下载的,因此设置这些寄存器至关重要。相关寄存器实在太多,这里不一一列举。
五:EBOOT
核心代码如下:
while(1){ if(menuUsed==1)Menu(); WaitDownload();}
前面各寄存器初始化完成后,进入这个死循环,默认menuUsed=0,这时将执行函数WaitDownload()。
在WaitDownload()中,如果没有点击DNW的下载,这时没有检测到下载的BIN文件的大小,此时
downloadFileSize=0,这时执行下面的代码:
[url=][/url]
while(downloadFileSize==0){ //检测到USB连上后打印下面连接上的信息。 if(first==1 && isUsbdSetConfiguration!=0) { Uart_Printf("USB host is connected. Waiting a download.\n");//unmasked by lqm! first=0; } //在没有按DNW下载时一个LED闪 if(j%0x100000==0)Led_Display(0x8); if(j%0x100000==0x80000)Led_Display(0x0); j++; key=Uart_GetKey(); /* if(autorun_trig) //Timer4倒计时到后autorun_trig置1,执行下面的函数。 AutoNandLoadRun(); //run it in svc mode */ /**************************************************** ; 注意这里面的autorun_ds标识变量! ; 当系统启动后没有键按下时,autorun_ds=0; ; 此时timer4中断使能,通过中断自动运行系统; ; 如果按下键后,则运行Menu()函数,显示具体 ; 的菜单供用户选择。 ; 这时autorun_ds=1,timer4中断禁能; ; 系统不再自动加载。 ****************************************************/ if(key!=0) { autorun_ds = 1; //printf("disable autorun\n"); Menu(); first=1; //To display the message,"USB host ...." //在串口下载返回后downloadFileSize不为0,因此不能再执行USB下载! } //在这里添加自动加载NK的程序!added by lqm,2009-06-29 if(EnRunWINCE) { NandLoadRun_wince(); } }[url=][/url]
通过程序可以看到,此时LED会不停闪烁。
一旦通过DNW下载点击后,downloadFileSize将被赋值为下载的BIN文件或nb0文件的大小,不再为0,这个while循环将结束,程序继续往后运行,USB通过DMA将PC上的BIN或nb0文件下载到DRAM中。
在下载BIN或nb0文件时,开启定时器,用于计算下载整个文件所花的时间,并打印出来。
开始下载时,执行如下两个函数:
Timer_InitEx(); Timer_StartEx();
下载完后,执行如下函数:
time=Timer_StopEx();
下载一次所花的时间被保存在变量time中,并通过串口打印出来。
下载完后将执行数据校验,确保数据无误。
校验无误后,将根据前面是否选择下载并运行,如果下载时选择的下载并运行,这时将运行下载的程序。这里指下载到DRAM中才有这种功能。具体代码如下:
[url=][/url]
if(download_run==1){ register void(*run)(void); //使用寄存器变量以防止禁止DCACHE后数据不一致!!! rINTMSK=BIT_ALLMSK; run=(void (*)(void))downloadAddress; //使用DCACHE且RW区也在CACHE区间downloadAddress会在cache中 { MMU_DisableDCache(); //download program must be in MMU_DisableICache(); //non-cache area MMU_InvalidateDCache(); //使所有DCACHE失效,本程序的MMU_Init中将会刷新DCACHE到存储器, //为使应用此MMU_Init方式的程序能被正确运行必须先使DCACHE失效!!! MMU_DisableMMU(); //call_linux(0, 193, downloadAddress); //或不用上面3个函数而直接使用call_linux }run();}[url=][/url]
如果选择的下载到NAND,bootloader先将下载的BIN文件下载进DRAM,再将DRAM的数据拷到NAND中。拷备完后,执行引导系统的程序。
具体程序如何拷到NAND,再如何引导系统,代码做了非常详尽的注释,这里不多说了。
bootloader生成的BIN文件: |