S3C2410 bootloader VIVI阅读笔记.docx

上传人:b****1 文档编号:280496 上传时间:2023-04-28 格式:DOCX 页数:19 大小:24.97KB
下载 相关 举报
S3C2410 bootloader VIVI阅读笔记.docx_第1页
第1页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第2页
第2页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第3页
第3页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第4页
第4页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第5页
第5页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第6页
第6页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第7页
第7页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第8页
第8页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第9页
第9页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第10页
第10页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第11页
第11页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第12页
第12页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第13页
第13页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第14页
第14页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第15页
第15页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第16页
第16页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第17页
第17页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第18页
第18页 / 共19页
S3C2410 bootloader VIVI阅读笔记.docx_第19页
第19页 / 共19页
亲,该文档总共19页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

S3C2410 bootloader VIVI阅读笔记.docx

《S3C2410 bootloader VIVI阅读笔记.docx》由会员分享,可在线阅读,更多相关《S3C2410 bootloader VIVI阅读笔记.docx(19页珍藏版)》请在冰点文库上搜索。

S3C2410 bootloader VIVI阅读笔记.docx

S3C2410bootloaderVIVI阅读笔记

S3C2410bootloader----VIVI阅读笔记

建议读一读《嵌入式系统BootLoader技术内幕》(詹荣开著),google一下就会找到一片。

什么是Bootloader就不再这里废话了,看看上面的文章就明了了。

Bootloader有非常多种,如本文将要阅读的vivi,除此之外更有uboot,redboot,lilo等等。

Vivi是韩国mizi公司专门为三星s3c2410芯片设计的Bootloader。

先来看看vivi的源码树:

  

  vivi-+-arch-+-s3c2410

  |-Documentation

  |-drivers-+-serial

  |       

  ‘-mtd-+-maps

  |            

  |-nor

  |            

  ‘-nand

  |-include-+-platform

  |        |-mtd

  |        ‘-proc

  |-init

  |-lib-+-priv_data

  |-scripts-+-lxdialog

  |-test

  |-util

  

能google一下,搜到源码vivi.tar.gz。

前面提到的文件已系统的分析了bootloader的,这里就按原始码来具体说事。

vivi也能分为2个阶段,阶段1的代码在arch/s3c2410/head.S中,阶段2的代码从init/main.c的main函数开始。

1.阶段1

阶段1从程式arch/s3c2410/head.S开始,按照head.S的代码执行顺序,一次完成了下面几个任务:

u      

1、关WATCHDOG(disablewatchdogtimer)

上电后,WATCHDOG默认是开着的

u      

2、禁止所有中断(disableallinterrupts)

vivi中不会用到中断,中断是系统的事,bootloader可不能去干这事的(不过这段代码实在多余,上电后中断默认是关闭的)

u      

3、初始化系统时钟(initialisesystemclocks)

启动MPLL,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz,“CPUbusmode”改为“Asynchronousbusmode”。

u      

4、初始化内存控制寄存器(memsetup)

S3c2410共有15个寄存器,在此开始初始化13个寄存器。

u      

5、检查是否从掉电模式唤醒(Checkifthisisawake-upfromsleep)

若是,则调用WakeupStart函数进行处理。

u      

6、点亮所有LED(AllLEDon)

点一下灯,通知外面的同志,告诉他们有情况发生。

u      

7、初始化UART0(setGPIOforUART&InitUART)

a.设置GPIO,选择UART0使用的引脚

b.初始化UART0,设置工作方式(使用FIFO)、波特率1152008N1、无流控等。

这可是使用串口和s3c2410通信的条件啊,在终端也要如此设置。

u      

8、跳到内存测试函数(simplememorytesttofindsomeDRAMflaults)

当然要定义了CONFIG_BOOTUP_MEMTEST这个参数才会跳到内存测试。

u      

9、如果定义了以Nand

flash方式启动(#ifdef

CONFIG_S3C2410_NAND_BOOT),则此时要将vivi所有代码(包括阶段1和阶段2)从Nandflash复制到SDRAM中(因为在Nandflash中是不能执行程式的,他只能做为程式和数据的存储器,而Norflash可就不同了,Nor

flash能执行程式,但贵是他发展得瓶颈):

a.设置nandflash控制寄存器

b.设置堆栈指针

c.设置即将调用的函数nand_read_ll的参数:

r0=目的地址(SDRAM的地址),r1=源地址(nandflash的地址),r2=复制的长度(以字节为单位)

d.调用nand_read_ll进行复制

u      

10、跳到bootloader的阶段2运行,亦即调用init/main.c中的main函数(getreadtocallCfunctions)

a.重新设置堆栈

b.设置main函数的参数

c.调用main函数

head.S有900多行,都是些arm汇编,看的云山雾罩,汇编看来是忘的差不多了,所以这部分代码也看的相当糙,只知道大概在干什么,至于个中缘由就不是非常了解。

先学学arm汇编再回来看。

2.阶段2

从init/main.c中的main函数开始,终于步入C语言的世界了。

Main函数总共有8步(8steps),先看看原始码:

  

  intmain(intargc,char*argv[])

  {

      

  intret;

    

  /*

  Step1:

*/

      

  putstr("\r\n");

      

  putstr(vivi_banner);   

  //vivi_banner是vivi执行开始的显示信息,vivi_banner在文件version.c中定义

      

  reset_handler();

      

  /*Step2:

*/

      

  ret=board_init();

      

  if(ret){

            

  putstr("Failedaboard_init()procedure\r\n");

            

  error();

      

  }

      

  /*Step3:

*/

      

  mem_map_init();

      

  mmu_init();

      

  putstr("Succeedmemorymapping.\r\n");

      

  /*Now,vivi

  isrunningontheram.MMUisenabled.

      *Step4:

*/

      /*initializetheheaparea*/

      ret=heap_init();

      if(ret){

            

  putstr("Failedinitailizingheapregion\r\n");

            

  error();

      }

      

  /*Step5:

 

  MTD*/

      ret=mtd_dev_init();

      /*Step6:

*/

      init_priv_data();

      /*Step7:

*/

      misc();

      init_builtin_cmds();

      /*Step8:

*/

      boot_or_vivi();

      return0;

  }

  

下面按照上面的步骤逐步来分析一下。

1、Step

1:

reset_handler()

reset_handler用于将内存清零,代码在lib/reset_handle.c中。

  

  1  void

  2  reset_handler(void)

  3  {

  4    intpressed;

  5    pressed=is_pressed_pw_btn();  /*判断是硬件复位还是软件复位*/

  6    if(pressed==PWBT_PRESS_LEVEL){

  7      DPRINTK("HARD

  RESET\r\n");

  8      hard_reset_handle();      /*调用clear_mem对SDRAM清0*/

  9    }else{

  10      DPRINTK("SOFT

  RESET\r\n");

  11      soft_reset_handle();      /*此函数为空*/

  12    }

  13  }

  

在上电后,reset_handler调用第8行的hard_reset_handle(),此函数在lib/reset_handle.c中:

  

  [main(intargc,char*argv[])->

  reset_handler()->hard_reset_handle()]

  1  staticvoid

  2  hard_reset_handle(void)

  3  {

  4  #if0

  5    clear_mem((unsigned

  long)(DRAM_BASE+VIVI_RAM_ABS_POS),\

  6    (unsignedlong)(DRAM_SIZE-

  VIVI_RAM_ABS_POS));

  7  #endif

  /*lib/memory.c,将起始地址为USER_RAM_BASE,长度为USER_RAM_SIZE的内存清0*/

  8    clear_mem((unsignedlong)USER_RAM_BASE,(unsignedlong)USER_RAM_SIZE);

  9  }

  

2、Step

2:

board_init()  

board_init调用2个函数用于初始化定时器和设置各GPIO引脚功能,代码在arch/s3c2410/smdk.c中:

  

  [main(intargc,char*argv[])>

  board_init()]

  1  intboard_init(void)

  2  {

  3    init_time(); 

  /*arch/s3c2410/proc.c*/

  4    set_gpios(); 

  /*arch/s3c2410/smdk.c

  */

  5    return0;

  6  }

  

init_time()这个函数对寄存器进行了简单的操作:

  

  voidinit_time(void)

  {

      TCFG0=(TCFG0_DZONE(0)|TCFG0_PRE1(15)|TCFG0_PRE0(0));

      /*s3c2410datasheetP298*/

      /*TCFG0=0|0xf00|0*/

  }

  

寄存器TCFG0由三部分组成,prescaler0,prescaler1,deadzone和reserve四部分,前三部分分别对应TCFG0_PRE0、TCFG0_PRE1、TCFG0_DZONE,TCFG0_PRE0(0)实际值为0x00,TCFG0_PRE1(15)实际值为0x0f00,而TCFG0_DZONE(0)实际值为0x000000。

实际中,vivi并未使用定时器,这个函数就能忽略。

set_gpios()用于选择GPA至GPH端口各引脚的功能及是否使用各引脚的内部上拉电阻,并设置外部中断源寄存器EXTINT0-2(vivi中未使用外部中断)。

  

  1     

  voidset_gpios(void)

  2      {

  3          

  GPACON  =vGPACON;

  4          

  GPBCON  =vGPBCON;

  5          

  GPBUP  =vGPBUP;

  6          

  GPCCON  =vGPCCON;

  7          

  GPCUP  =vGPCUP;

  8          

  GPDCON  =vGPDCON;

  9          

  GPDUP  =vGPDUP;

  10          

  GPECON  =vGPECON;

  11          

  GPEUP  =vGPEUP;

  12          

  GPFCON  =vGPFCON;

  13          

  GPFUP  =vGPFUP;

  14          

  GPGCON  =vGPGCON;

  15          

  GPGUP  =vGPGUP;

  16          

  GPHCON  =vGPHCON;

  17          

  GPHUP  =vGPHUP;

  18          

  EXTINT0=vEXTINT0;

  19          

  EXTINT1=vEXTINT1;

  20          

  EXTINT2=vEXTINT2;

  21      }

  

      以第三行为例,vGPACON的值为0x007fffff,查找s3c2410用户手册可知,该参数将GPACON的23位全部置1。

各位功能需察看s3c2410用户手册。

3、Step

3:

建立页表和启动MMU

mem_map_init();

mmu_init();

mem_map_init函数用于建立页表,vivi使用段式页表,只需要一级页表。

他调用3个函数,代码在arch/s3c2410/mmu.c中:

  

  [main(intargc,char*argv[])>

  mem_map_init(void)]

  1      voidmem_map_init(void)

  2     

  {

  3     

  #ifdefCONFIG_S3C2410_NAND_BOOT  

  /*CONFIG_S3C2410_NAND_BOOT

  =y,在文件include/autoconf.h中定义*/

  4          

  mem_map_nand_boot();    

  

  /*最终调用mem_mepping_linear,建立页表*/

  5      #else

  6          

  mem_map_nor();

  7      #endif

  8          

  cache_clean_invalidate();/*清空cache,使无效cache*/  

  9          

  tlb_invalidate();     

  /*使无效快表TLB*/

  10      }

  

  

  

第9、10行的两个函数能不用管他,他们做的事情在下面的mmu_init函数里又重复了一遍。

对于本研发板,在.config中定义了CONFIG_S3C2410_NAND_BOOT。

mem_map_nand_boot()函数调用mem_mapping_linear()函数来最终完成建立页表的工作。

页表存放在SDRAM物理地址0x33dfc000开始处,共16K:

一个页表项4字节,共有4096个页表项;每个页表项对应1M地址空间,共4G。

mem_map_init先将4G虚拟地址映射到相同的物理地址上,NCNB(不使用cache,不使用writebuffer)?

?

这样,对寄存器的操作跟未启动MMU时是相同的;再将SDRAM对应的64M空间的页表项修改为使用cache。

mem_mapping_linear函数的代码在arch/s3c2410/mmu.c中:

  

  [main(intargc,char*argv[])>

  mem_map_init(void)>mem_map_nand_boot()>mem_mapping_linear(void)]

  1  staticinlinevoidmem_mapping_linear(void)

  2  {  

  3    unsignedlongpageoffset,sectionNumber;

  4        

  putstr_hex("MMUtablebaseaddress=0x",(unsignedlong)

  mmu_tlb_base);

  5    /*4G虚拟地址映射到相同的物理地址.notcacacheable,notbufferable*/

  6    /*mmu_tlb_base=0x33dfc000*/

  7    for(sectionNumber=0;sectionNumber

  >20))=pageoffset|

         

  MMU_SECDESC;

  10    }

          

  

  11    /*makedramcacheable*/

  12    /*SDRAM物理地址0x3000000-0x33ffffff,

  13      

  DRAM_BASE=0x30000000,DRAM_SIZE=64M

  14    */

  15    for(pageoffset=DRAM_BASE;pageoffset1M){

  17      //DPRINTK(3,

  "MakeDRAMsectioncacheable:

  0x%08lx\n",        

  pageoffset);

  18      *(mmu_tlb_base+

  (pageoffset>>20))=\

  pageoffset|MMU_SECDESC|MMU_CACHEABLE;

  19    }

  20}

  

mmu_init()函数用于启动MMU,他直接调用arm920_setup()函数。

arm920_setup()的代码在arch/s3c2410/mmu.c中:

  

  [main(intargc,char*argv[])>

  mmu_init()>arm920_setup()]

  1  staticinlinevoidarm920_setup(void)

  2  {

  3            

  unsignedlongttb=MMU_TABLE_BASE;

  /*MMU_TABLE_BASE=0x33dfc000*/

  4  __asm__(

  5    /*Invalidatecaches*/

  6    "mov  r0,

  #0\n"

  7    "mcr  p15,0,r0,

  c7,c7,0\n"  /*invalidateI,Dcachesonv4*/

  8    "mcr  p15,0,r0,

  c7,c10,4\n"  /*drainwritebufferonv4*/

  9    "mcr  p15,0,r0,

  c8,c7,0\n"  /*invalidateI,DTLBsonv4*/

        

  10    /*Loadpagetablepointer*/

  11    "mov  r4,%0\n"

  12    "mcr  p15,0,r4,c2,

  c0,0\n"  /*loadpagetablepointer*/

  13    /*Writedomainid(cp15_r3)*/

        

  14    "mvn  r0,

  #0\n"  /*Domains0b01=client,0b11=Manager*/

        

  15    "mcr  p15,0,r0,c3,

  c0,0\n"

  /*loaddomainaccessregister,writedomain15:

0,用户手册P548(accesspermissions)*/

  16    /*Setcontrolregisterv4*/

  17    "mrc  p15,0,r0,c1,

  c0,0\n"  /*getcontrolregisterv4*/

          /*数据手册P545:

readcontrolregister*/

  18    /*Clearout’unwanted’bits(thenputthem

  inifweneedthem)*/

  19    /*..VI..RSB....CAM*/  /*这些位的含义在数据手册P546*/

  20    "bicr0,r0,#0x3000\n"  /*

  ..11............*/

         

  /*I(bit[12])=0=Instructioncachedisabled*/

  21    /*V[bit[13]](Baselocationofexception

  registers)=0=Lowaddresses=0x00000000*/

  22    "bicr0,r0,

  #0x0300\n"    /*......11........*/

          

  

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 自然科学 > 物理

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2