zoukankan      html  css  js  c++  java
  • S3C2410 bootloader VIVI阅读笔记 (转)上

    首先在移植前应该熟悉了解vivi的架构,启动过程,了解了原理性的东西之后,再去做移植比较好吧,我也新手进来公司的第1件事就是弄VIVI,
    不过我是剪裁,移植主要部分是改bootload分区和kernel MTD分区,保证一致,其他的记不得了,GOOGLE里有非常丰富的关于vivi -0.1.4到s3c2410移植或者启动过程分析的资料.
    S3C2410 bootloader ----VIVI阅读笔记 (转)上
    2007-06-14 13:06
    建议读一读《嵌入式系统Boot Loader技术内幕》(詹荣开著),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从程序arch/s3c2410/head.S开始,按照head.S的代码执行顺序,一次完成了下面几个任务:
    1、关WATCH DOG (disable watch dog timer)
    上电后,WATCH DOG默认是开着的
    2、禁止所有中断 (disable all interrupts)
    vivi中不会用到中断,中断是系统的事,bootloader可不能去干这事的(不过这段代码实在多余,上电后中断默认是关闭的)
    3、初始化系统时钟(initialise system clocks)
    启动MPLL,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz,“CPU bus mode”改为“Asynchronous bus mode”。
    4、初始化内存控制寄存器(memsetup)
    S3c2410共有15个寄存器,在此开始初始化13个寄存器。
    5、检查是否从掉电模式唤醒(Check if this is a wake-up from sleep)
    若是,则调用WakeupStart函数进行处理。
    6、点亮所有LED (All LED on)
    点一下灯,通知外面的同志,告诉他们有情况发生。
    7、初始化UART0 (set GPIO for UART & InitUART)
    a.设置GPIO,选择UART0使用的引脚
    b.初始化UART0,设置工作方式(使用FIFO)、波特率115200 8N1、无流控等。这可是使用串口与s3c2410通信的条件啊,在终端也要如此设置。
    8、跳到内存测试函数(simple memory test to find some DRAM flaults)
    当然要定义了CONFIG_BOOTUP_MEMTEST这个参数才会跳到内存测试。
    9、如果定义了以Nand flash方式启动(#ifdef CONFIG_S3C2410_NAND_BOOT),则此时要将vivi所有代码(包括阶段1和阶段2)从Nand flash复制到SDRAM中(因为在Nand flash中是不能执行程序的,它只能做为程序和数据的存储器,而Nor flash可就不同了,Nor flash可以执行程序,但贵是它发展得瓶颈):
    a.设置nand flash控制寄存器
    b.设置堆栈指针
    c.设置即将调用的函数nand_read_ll的参数:r0=目的地址(SDRAM的地址),r1=源地址(nand flash的地址),r2=复制的长度(以字节为单位)
    d.调用nand_read_ll进行复制
    10、跳到bootloader的阶段2运行,亦即调用init/main.c中的main函数(get read to call C functions)
    a.重新设置堆栈
    b.设置main函数的参数
    c.调用main函数
    head.S有900多行,都是些arm汇编,看的云山雾罩,汇编看来是忘的差不多了,所以这部分代码也看的相当糙,只知道大概在干什么,至于个中缘由就不是很了解。先学学arm汇编再回来看。
    阶段2
    从init/main.c中的main函数开始,终于步入C语言的世界了。Main函数总共有8步(8 steps),先看看源代码:
    int main(int argc, char *argv[])
    {
              int ret;
    /*
              * Step 1:
              */
              putstr("\r\n");
              putstr(vivi_banner);      //vivi_banner是vivi执行开始的显示信息,vivi_banner在文件version.c中定义
              reset_handler();
              /*
               * Step 2:
               */
              ret = board_init();
              if (ret) {
                      putstr("Failed a board_init() procedure\r\n");
                      error();
              }
              /*
               * Step 3:
               */
              mem_map_init();
              mmu_init();
              putstr("Succeed memory mapping.\r\n");
              /*
               * Now, vivi is running on the ram. MMU is enabled.
               * Step 4:
           */
              /* initialize the heap area*/
              ret = heap_init();
              if (ret) {
                      putstr("Failed initailizing heap region\r\n");
                      error();
              }
              /* Step 5:
               * MTD
               */
              ret = mtd_dev_init();
              /* Step 6:
               */
              init_priv_data();
              /* Step 7:
    */
              misc();
              init_builtin_cmds();
              /* Step 8:
               */
              boot_or_vivi();
              return 0;
    }
    下面按照上面的步骤逐步来分析一下。
    1、Step 1:reset_handler()
    reset_handler用于将内存清零,代码在lib/reset_handle.c中。
    1    void
    2    reset_handler(void)
    3    {
    4        int pressed;
    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(int argc, char *argv[]) -> reset_handler() -> hard_reset_handle()]
    1    static void
    2    hard_reset_handle(void)
    3    {
    4    #if 0
    5        clear_mem((unsigned long)(DRAM_BASE + VIVI_RAM_ABS_POS), \
    6        (unsigned long)(DRAM_SIZE - VIVI_RAM_ABS_POS));
    7    #endif
    /*lib/memory.c,将起始地址为USER_RAM_BASE,长度为USER_RAM_SIZE的内存清0*/
    8     clear_mem((unsigned long)USER_RAM_BASE, (unsigned long) USER_RAM_SIZE);
    9    }
    2、Step 2:board_init()     
    board_init调用2个函数用于初始化定时器和设置各GPIO引脚功能,代码在arch/s3c2410/smdk.c中:
    [main(int argc, char *argv[]) > board_init()]
    1    int board_init(void)
    2    {
    3        init_time();    /*arch/s3c2410/proc.c*/
    4        set_gpios();    /*arch/s3c2410/smdk.c */
    5        return 0;
    6    }
    init_time() 这个函数对寄存器进行了简单的操作:
    void init_time(void)
    {
              TCFG0 = (TCFG0_DZONE(0) | TCFG0_PRE1(15) | TCFG0_PRE0(0));
              /*s3c2410 data sheet P298*/
              /*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          void set_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(int argc, char *argv[]) > mem_map_init(void)]
    1          void mem_map_init(void)
    2          {
    3          #ifdef CONFIG_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,不使用write buffer)——这样,对寄存器的操作跟未启动MMU时是一样的;再将SDRAM对应的64M空间的页表项修改为使用cache。 mem_mapping_linear函数的代码在arch/s3c2410/mmu.c中:
    [main(int argc, char *argv[]) > mem_map_init(void) > mem_map_nand_boot( ) > mem_mapping_linear(void)]

  • 相关阅读:
    java学习day51--DB旅游生态系统-项目搭建
    java学习day50--Spring Boot发送邮件任务
    java学习day49--yaml语法以及注入
    java学习day49--JSON扩展(详细)
    java学习day49--JS数组遍历
    java学习day49-基于AJAX实践操作(活动模块)
    java学习day48--Ajax技术--原生
    denied: requested access to the resource is denied
    VMware虚拟机网络适配器三种网络连接模式
    MySQL8.0.19最新版本rpm包和源码包百度地址
  • 原文地址:https://www.cnblogs.com/hnrainll/p/2050601.html
Copyright © 2011-2022 走看看