编写uboot之硬件初始化和制作链接脚本lds

目标:

首先阶段:

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驱动在(入口:.

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 = .;
}

中间0x33f九千0就是链接地址首位置,共512K空间存放bootloader
定义__bss_start和__bss_end符号,是用来前后相继早先以前将这么些未定义的变量清0,节省外部存款和储蓄器
且bss_start-0x33f八千0就相当于代码的轻重(copy_code_tosdram函数中len值)

 

本文由银河网址发布于银河网址,转载请注明出处:编写uboot之硬件初始化和制作链接脚本lds

您可能还会对下面的文章感兴趣: