BootLoader —— S3C2440

发布者:technology1最新更新时间:2019-12-26 来源: eefocus关键字:BootLoader  S3C2440 手机看文章 扫描二维码
随时随地手机看文章

先来看看扬创的bootloader的实现方法:


首先:在汇编中初始化堆栈,中断向量表,MMU,时钟,串口等,然后跳到C语言的Main函数。这部分代码小于4K,放在block0。这个Main函数用来将第二段代码拷备到DRAM中并执行。


其次:进入第二段代码。第二段代码也是先在汇编中初始化堆栈,中断向量表等,然后跳到C语言的Main函数。这部分代码就不用有4K限制了,具体大小由第一段代码决定,因为它本身由第一段代码来搬运。这个Main函数用来显示开机图片以及进度条。然后视串口接收信息运行带有USB下载NK的Eboot或是读取NK映像,启动WINCE系统。


最后:进入第三段代码。这段代码用于通过USB将PC上的NK.nb0或NK.bin文件下载进NANDFLASH并运行。


可见,扬创公司光bootloader就分成了三个部分,即3个bin文件组成。然后分别将这三段二进制代码下载进分别从 block0,block2,block8(block12)开始的三块。具体烧写手段采用老掉牙的giveio烧写,就是曾经大名鼎鼎的SJF2440 了,相信不少嵌入式高手都用过,哈哈。如果不小心将bootloader弄丢了,再重烧一片,得等上好几分钟,足够你到外面跑上几千米再回来这么长了。尽管如此,我们的扬创公司仍然拿他们的代码当宝,死活不肯开源。要知道对于买你们板子的人,都是来学习的呀!学习嵌入式系统,bootloader是最基础也是进入嵌入式行业的敲门砖,没有了代码,无疑给学习添加了很大的麻烦,而扬创官方回答却是:用户开发产品用不着修改bootloader.我看扬创没开发过东西,不了解行情。


不说这么多废话了,说多了无益,让我们一起来揭开bootloader的神秘的面纱吧!


先说下我移植的bootloader的功能,以及烧录时间,和扬创的做下对比。


第一次下载bootloader到NANDFLASH的方法:


方法一:通过扬创的老掉牙的方法,先在ADS1.2里面生成bootloader.bin文件,然后用SJF2440烧写工具,配合giveio将BIN文件烧写进从block0开始的块。大概要花上十分钟左右的样子吧!BIN文件有点大。


方法二:在ADS1.2环境下,通过AXD将程序映像到DRAM的地址并运行,然后通过运行着的bootloader将本身bootloader的BIN 文件下载至NANDFLASH。很神奇吗?哈哈!本身bootloader运行的地方是ADS可配的,视文件大小可以选配在SRAM,SDRAM下运行,运行之后就可以拿程序本身来烧写代码至NAND了,弄懂原理了也就不足为奇了。这里暂时通过并口 + H-JTAG + WIGGLER的方式。


方法三:采用multiICE等仿真器下载BIN文件到NAND。


方法四:将ADS1.2的代码移植到MDK,通过ULINK2仿真,让程序运行在DRAM,然后通过bootloader程序将BIN文件烧写进NAND。


方法五:还有更多的方法留着你去做呢,哈哈.................


对比扬创的bootloader,至少有如下好处大家是看得到的吧:


其一:下载速度至少是扬创的50倍以上。大概以扬创下载整个文件需要3分钟计算,实际用USB下载bootloader仅需1秒,那就是180倍。


其二:如果手上没有USB的仿真器,那么也仅仅是用并口烧写过一次bootloader就不用了,除非NAND的bootloader被格掉了。如果手上有USB的仿真器,那就彻底不用并口了,这不正是广大笔记本开发者头痛之处么?


其三:整个bootloader文件只需一个工程文件,即只用一个BIN文件,而且是直接烧写至以block0开始的块。继续神奇?哈哈,2440手册上不是说第一段代码不能大于4K吗?这不是与手册冲突了?再觉得神奇就看代码吧!


先将整个bootloader的流程图放上来:


先从全局对整个工程有个大体的了解很重要,这样局部一条条的看更容易懂。


由于程序实在太长,这里分几个部分逐步说明。


一:串口配置。


整个bootloader的交互环境全部是通过串口显示的,那么怎么样才能准确无误的显示出想要的字符呢?


首先要知道的是:串口的CLK是挂在PCLK上的。波特率与PCLK有着密切的关系,因此正确设置PCLK,是和正确设置波特率有着千丝万缕的联系的。


S3C2440内置两个PLL电路,即MPLL和UPLL。MPLL给FCLK,HCLK,PCLK提供时钟,UPLL给USB提供时钟。


MPLL=FCLK=(2*m*Fin)/(p*2^s);

m=M+8;

p=P+2;

M,P由寄存器MPLLCON设置。

确定了FCLK后,HCLK和PCLK由寄存器CLKDIVN确定。

详细设置请参考S3C2440的SPEC。

这里设置mdiv=92,pdiv=1,s=1,计算得FCLK=400MHz.

相应的设置CLKDIVN,使得FCLK:HCLK:PCLK=1:4:8,

这样PCLK=400/8=50MHz.

再通过PCLK设置波特率为115200,这样串口配置就完成了。


二:TIMER4的设置

从上面的流程图可以看出,TIMER4用于倒计时,当在规定时间内没有响应键盘后,自动装载系统并运行。


TIMER4的时钟也是以PCLK为基准的。具体输入的时钟频率为:

Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}

其中prescaler value由寄存器rTCFG0确定,divider value由寄存器rTCFG1确定。

这里设置输入的频率Fin=PCLK/(3+1)/4=312500Hz.

然后设置定时器装载的初始值,由寄存器rTCNTB4确定。

这里设置rTCNTB4=3125.

由此可以算出,定时器产生一次中断所花的时间为:T=N/F=3125/312500=0.01S。

具体代码如下:


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,4

rTCFG1 &= ~(0xf<<16);

rTCFG1 |= 1<<16; //mux = 1/4 ,for Timer 4


rTCNTB4 = val; //val = (PCLK>>4)/100-1

rTCON &= ~(0xf<<20);

rTCON |= 7<<20; //interval, inv-off, update TCNTB4&TCMPB4[占空比], start timer 4

rTCON &= ~(2<<20); //clear manual update bit

EnableIrq(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;

}

}


中断程序中有个变量EnRunWINCE,默认为0.当autorun_10ms值减到0后,即定时的时间已到,

这时EnRunWINCE=1,后面的程序通过该变量判断时间到了,然后执行自动加载NK的代码。

具体代码如下:


if(EnRunWINCE)

{

  NandLoadRun_wince();

}


三:LCD设置


bootloader运行时可以附加显示开机图片,这就需要对LCD控制器的相关寄存器进行设置。

由于寄存器较多,这里不一一列举,仅给LCD显示的函数如下:


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  for(i=0;i  {   

  PutPixel(i,j,ackj[k++]);   

  }

}


四: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,这时执行下面的代码:


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 autorunn");

  Menu();

  first=1;

  //To display the message,"USB host ...."

  //在串口下载返回后downloadFileSize不为0,因此不能再执行USB下载!

  }

  //在这里添加自动加载NK的程序!added by lqm,2009-06-29

  if(EnRunWINCE)

  {

  NandLoadRun_wince();

  }   

}


通过程序可以看到,此时LED会不停闪烁。


一旦通过DNW下载点击后,downloadFileSize将被赋值为下载的BIN文件或nb0文件的大小,不再为0,这个while循环将结束,程序继续往后运行,USB通过DMA将PC上的BIN或nb0文件下载到DRAM中。


在下载BIN或nb0文件时,开启定时器,用于计算下载整个文件所花的时间,并打印出来。


开始下载时,执行如下两个函数:


Timer_InitEx();   

Timer_StartEx();

下载完后,执行如下函数:


time=Timer_StopEx();


下载一次所花的时间被保存在变量time中,并通过串口打印出来。


下载完后将执行数据校验,确保数据无误。


校验无误后,将根据前面是否选择下载并运行,如果下载时选择的下载并运行,这时将运行下载的程序。这里指下载到DRAM中才有这种功能。具体代码如下:


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();

}


如果选择的下载到NAND,bootloader先将下载的BIN文件下载进DRAM,再将DRAM的数据拷到NAND中。拷备完后,执行引导系统的程序。


具体程序如何拷到NAND,再如何引导系统,代码做了非常详尽的注释,这里不多说了。


bootloader生成的BIN文件:


无法上传,sorry]

注:应该可以通过扬创提供的giveio烧到block0开始的块,之后就不用这么麻烦用giveio烧写了.

关键字:BootLoader  S3C2440 引用地址:BootLoader —— S3C2440

上一篇:ARM状态和THUMB状态
下一篇:ARM命名规则

推荐阅读最新更新时间:2024-11-12 12:22

S3C2440外接SDRAM
CPU提供了一组用于SDRAM的信号: SDRAM时钟有效信号SCKE; SDRAM时钟信号SCLK0/SCLK1; 数据掩码信号DQM0/DQM1/DQM2/DQM3; SDRAM片选信号nSCS0(它与nGCS6是同一引脚的两个功能); SDRAM行地址选通脉冲信号nSRAS; SDRAM列地址选通脉冲信号nSCAS; 写允许信号nWE(它不是专用于SDRAM的). SDRAM内部就是一个存储阵列,先确定一个行,然后确定一个列; SDRAM一般有4个L-Bank. 可以想象SDRA
[单片机]
<font color='red'>S3C2440</font>外接SDRAM
S3C2440内部中断和外部中断
1.中断分两大类:内部中断和外部中断。 2.外部中断。24个外部中断占用GPF0-GPF7(EINT0-EINT7),GPG0-GPG15(EINT8-EINT23)。用这些脚做中断输入,则必须配置引脚为中断,并且不要上拉。具体参考datesheet数据手册。 寄存器:EXTINT0-EXTINT2:三个寄存器设定EINT0-EINT23的触发方式。 EINTFLT0-EINTFLT3:控制滤波时钟和滤波宽度。 EINTPEND:这个是中断挂起寄存器,清除时要写1,后面还有几个是写1清除。当一个外部中断(EINT4-EINT23)发生后,那么相应的位会被置1。为什么没有EINT0-EINT3,呵呵,看看SRCPND就知道了
[单片机]
S3C2440 GPIO (使用miniARM 2440)
S3C2440 GPIO (使用miniARM 2440): #ifndef LDE_H #define LED_H #include 2440addr.h //GPB 有 PIN0 到 PIN10 共11个引脚 //rGPBCON 寄存器的每两个位控制一个IO的输入输出方向 //其中00表示输入 // 01表示输出 // 10为使用第二功能 // 11为出厂保留 //*************************************************** //功能:流水灯 //接口: GPB5 - LED1 低 灯亮
[单片机]
S3C2440裸机实验之clock(时钟设置)
快要毕业了,毕业之前再重新把这些实验从头到尾的练习一遍,先开始裸机的吧,这些都是以前搞过的东西,现在应该会比较快。。 开始吧! 时钟对于电子设备来说都是非常重要的,它是传输数据的一个基准,如果没有这个基准的话将导致系统的混乱。 S3C2440的频率有两种输入方式:外部时钟源和内部晶振(如下图) 输入的频率一般是比较低的比如2440的就只有12M,而2440的主频可以达到460M,这就需要对输入频率通过PLL锁相环进行倍频 先来看下这个CLOCK的结果图: 从上面的结果图可以看出输入频率OSC首先经过MPLL倍频 整个系统时钟主要有几个组成:FCLK,HCLK,PCLK FCLK:是个cpu提供时钟
[单片机]
关于ADS下bootloader之MMU的深入研究
如下是ADS下的boot的MMU.c的MMU初始化代码。在2440init.S中跳入Main,这个Main函数在U2440mom.c中实现,这个Main函数包括了对端口,中断服务,MMU,VGA等的初始化函数的调用。MMU.c中进行了MMU的初始化,其中调用了很多初始化函数,使用汇编写的,确切的说是用协处理指令写的。这些函数的声明部分在2440slib.h,实现在2440slib.c中。在MMU的初始化程序MMU_Init中,首先禁止了Dcache,Icache,清除了Dcache和Icache。禁止了MMU,TLB。然后对存储系统进行了虚拟地址到物理地址的映射。然后设置了转化表的基地址,设置了域,开启了MMU,Icache,Dca
[单片机]
关于ADS下<font color='red'>bootloader</font>之MMU的深入研究
基于微处理器S3C2440和WinCE嵌入式实时操作系统的视频数据采集
随着嵌入式技术的不断发展,各种嵌入式微处理器和控制器不断出现,并广泛应用于工控、通信、 PDA、安保等领域。基于ARM920t内核的嵌入式微处理器S3C2440,以其良好的数据处理能力、低功耗、小体积、支持多种嵌入式操作系统(如 WinCE、Linux)、集成多种外设(如I2C控制器、LCD控制器等)等优点,广泛应用于手持设备等。WinCE操作系统具有内核可剪裁、实时性好、支持多种通信、模块化设计、具有丰富的API等特点,广泛用于嵌入式实时操作系统。这里提出的嵌入式图像数据采集系统是某“纳米技术与微系统”实验室开发的“嵌入式传感测控系统”中实现图像采集功能的子系统,该系统是以S3C2440为硬件核心,以WinCE为软件平台,能实时
[单片机]
基于微处理器<font color='red'>S3C2440</font>和WinCE嵌入式实时操作系统的视频数据采集
s3c2440 触摸屏(sony x35)
1、触摸屏种类、分别应用在哪里、屏和OS怎么配合使用? 从技术原理来区别触摸屏,可分为5类: 1.电阻式触摸屏 2.电容式触摸屏 3.红外线技术触摸屏 4.表面声波技术触摸屏 5.矢量压力传感技术触摸屏 红外线式和感应电容式触摸屏能够支持多点触控。多点触控带来了更多的选择,抓取、拖曳、缩放、旋转。 屏要和系统搭配才能体现优势。IPHONE和android系统支持多点触控。Windows mobiles不支持多点触控。 2、 触摸屏实现原理 》》电阻屏 》》电容屏 3、从规格书: A/D精度 10bit ,8-channel input; 最大转换率500KSPS 链接触摸屏时,x
[单片机]
<font color='red'>s3c2440</font> 触摸屏(sony x35)
S3C2440裸机------LCD_框架与准备
1.框架 2.准备工作 我们需要准备一个支持norfalsh和nandflash启动的程序,当我们的程序小于4K时,我们可以把nandflash的程序拷贝到片内4K内存,但是现在我们的程序大于4K,这时候我们要把程序拷贝到SDRAM里面。
[单片机]
<font color='red'>S3C2440</font>裸机------LCD_框架与准备
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved