zoukankan      html  css  js  c++  java
  • 第2阶段——编写uboot之硬件初始化和制作链接脚本lds(1)

    目标:

    第一阶段:

    1.关看门狗
    2.设置时钟
    3.初始化SDRAM (初始化寄存器以及清除bss段)
    4.重定位 (将nand/nor中代码COPY到链接地址上,需要初始化nandflash,读flash)

    5.执行main 

    进入第二阶段:

    6.写main函数,在main()中设置要传给内核的参数,然后跳转内核基地址处

    7.制作uboot.lds链接脚本


    编写步骤:

    1.创建个名为"my_bootloader"根目录,方便编写uboot


    2.新建my_bootloader/si目录,创建source insight工程


    2.1 新建my_bootloader/start.S (后缀名必须是大写的S,或者后面编译会报错)

    编写start.S (第一阶段初始硬件文件):
    start.s任务:
    1.关看门狗
    2.设置时钟
    3.初始化SDRAM
    4.重定位(把bootloader本身的代码从flash复制到它的链接地址(c函数编写),然后清空bss段(c函数编写))
    5.执行main

    /*  看门狗寄存器            */
    #define WTCON      0x53000000
    
    /*  2.时钟寄存器            */
    #define CLKDIVN    0x4C000014        //设置FCLK,HCLK,PCLK比例
    #define MPLLCON   0x4C000004          //设置FCLK频率
    #define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))  //设置FCLK=200MHZ
    #define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))  //设置FCLK=400MHZ
    
    /*  3.bank寄存器       */
    #define BWSCON      0x48000000
    
    .text                                /*设置代码段*/
    .global   _start                  /*定义全局变量,要被连接脚本用到*/
    _start:                           /*_start跳转到这里实现硬件初始化*/
    
        /*  1.关看门狗            */
           ldr r0,=WTCON
           mov r1,#0
           str r1,[r0]
           
        /*	2.设置时钟(必须设为异步总线模式)  */
           
           ldr r0,=CLKDIVN
           mov r1,#3                                  /*FCLK:HCLK:PCLK=1:2:4*/ 
           str r1,[r0]        
           mrc	p15, 0, r1, c1, c0                 /* 读出控制寄存器 */	
           orr	 r1, r1, #0xc0000000   		 /* 设置为“asynchronous bus mode” */
           mcr	  p15, 0, r1, c1, c0, 0 	        /* 写入控制寄存器 */       
           ldr r0,=MPLLCON
           ldr r1,=S3C2440_MPLL_200MHZ      //使用复杂的数不能用mov,需要用ldr
           str r1,[r0]
           
        /*  3.初始化SDRAM       */
           ldr r0,=BWSCON                   //r0=SDRAM寄存器基地址
           adr r1,SDRAM_CONFIG           //使用adr相对跳转,因为SDRAM未初始化
           add r2,r0,#(13*4)               //r2等于 SDRAM尾地址+4
    
    0:
           ldr r3,[r1],#4                      //r3=r1里的	内容, &r1+=4;
           str r3,[r0],#4                      //*r0=r3,&r0+=4
           cmp r0,r2
           bne 0b                               //(ne:no equal   b:bank)   若r0!=r2,跳转到后面的0处
    
     /*  4.重定位 				*/
            ldr sp,=0x34000000                     //64Msdram,所以设置栈SP=0x34000000,避免堆栈溢出
            mov r0,#0                           //r0->src
    	ldr r1,=_start                     //r1->dest
    	ldr r2,=__bss_start            //r2->len->__bss_start-_start
    	sub r2,r2,r1
    	bl copy_code_to_sdram          //复制代码到SDRAM连接地址dest上
    	bl clear_bss                         //清除bss段 
    	
       /*  5.执行main				 */
            ldr lr,=halt                         //执行一个子程序调用返回时,需要先将返回地址赋给lr链接寄存器
            ldr pc,=main                              //初始化SDRAM后,可以使用pc 绝对跳转到SDRAM地址上
            mov pc,lr                             //若main函数跳出后,使PC等于lr链接寄存器,避免程序跑飞 
    
    halt:	                                //死循环,避免跑飞
    	 b halt               
    
    SDRAM_CONFIG:
    	.long 0x22011110;	  //BWSCON
    	.long 0x00000700;	  //BANKCON0
    	.long 0x00000700;	  //BANKCON1
    	.long 0x00000700;	  //BANKCON2
    	.long 0x00000700;	  //BANKCON3  
    	.long 0x00000700;	  //BANKCON4
    	.long 0x00000700;	  //BANKCON5
    	.long 0x00018005;	  //BANKCON6
    	.long 0x00018005;	  //BANKCON7
    	.long 0x008C04F4;	  //REFRESH
    	.long 0x000000B1;	  //BANKSIZE 
    	.long 0x00000030;	  //MRSRB6
    	.long 0x00000030;	  //MRSRB7
    

    3 新建my_bootloader/init.c,用于重定位,bss段清除,初始化NandFlash等

    在重定位函数中的nand驱动在(入口:http://www.cnblogs.com/lifexy/p/7097695.html)里详细介绍了,这里就不描述了.

    3.1编写copy_code_tosdram() 重定位函数

    void copy_code_to_sdram(unsigned char *src,unsigned char *dest,unsigned int len)			//复制代码到SDRAM连接地址dest上
    {
          unsigned int i;
            /*判断nor启动还是nand启动*/
    	if(is_boot_from_norflash())                 //nor启动,直接复制
    	{
                  for(i=0;i<len;i++)
                  {
                   dest[i]=src[i];
                  }
    	}
    	else
    	{
           nand_init();
    	    
    	nand_read((unsigned int)src,dest,len);
           
    	}
    } 

    3.2编写isBootFramNorFlash()函数,来判断nand启动还是nor启动

    /*判断nor启动还是nand启动*/
    unsigned char is_boot_from_norflash(void)
    {
             volatile unsigned int *p=(volatile unsigned int *)0;
    	 unsigned int i;
    	 i=*p;
    	 *p=0x12345678;
    	 if(*p==0x12345678)    //nand
    	 {
    	 *p=i;
    	 return 0;
    	 }
    	 else                    //nor
    	 {
            *p=i;
    	 return 1;
    	 }

    3.3编写clear_bss()函数

    void clear_bss(void)  //清除BSS段
    {
      extern int __bss_start,__bss_end;
      int  *p=&__bss_start;
      for( ;p<&__bss_end;p++)
      {
      *p=0;
      }
    }

    4编写连接脚本uboot.lds (参考硬件实验里的uart.lds和u-boot-1.1.6里的u-boot.lds)

    SECTIONS {
        . = 0x33f80000; //0地址里存放0X33F80000
        . = ALIGN(4);
    
        .text : { *(.text) }
        . = ALIGN(4);
    
        .rodata : {	*(.rodata)	}
        . = ALIGN(4);
    
        .data : {	*(.data)	}
        . = ALIGN(4);
    
        __bss_start = .; 
        .bss : { *(.bss) *(COMMON) }
        __bss_end = .;
    }

    其中0x33f80000就是链接地址首地址,共512K空间存放bootloader
    定义__bss_start和__bss_end符号,是用来程序开始之前将这些未定义的变量清0,节省内存
    且bss_start-0x33f80000就等于代码的大小(copy_code_tosdram函数中len值)

  • 相关阅读:
    BZOJ1087=Codevs2451=洛谷P1896&P2326互不侵犯
    poj1286
    P1066 2^k进制数
    开车旅行
    洛谷P1396 营救
    poj1840
    poj3693
    poj1195
    3955 最长严格上升子序列(加强版)
    1021 玛丽卡
  • 原文地址:https://www.cnblogs.com/lifexy/p/7337475.html
Copyright © 2011-2022 走看看