zoukankan      html  css  js  c++  java
  • 实现简单的 u-boot

    根据u-boot-1.1.6启动流程来划分,u-boot功能主要划分为四个部分

    1,硬件初始化                        -->start.S  init.c

    2,从 flash 拷贝内核到 ram    -->main.c

    3,设置 tag 参数                     -->tag.c  tag.h

    4,跳到内核,执行内核代码   --> main.c

    start.s源码:

    .extern main
    
    .text
    .global _start
    _start:
           bl disable_watchdog
           bl clock_init
           bl open_icache
           bl sdram_init
           bl uart0_init
           bl nand_init
           
           ldr sp, =0x34000000
           ldr r0,=0
           ldr r1,=_start
           ldr r2,=__bss_start     @0x33f80000
           sub r2,r2,r1
           bl copy_uboot_to_sdram       
           ldr pc,=on_sdram
           
    on_sdram:    
           bl clean_bss
           ldr lr,=main_return 
           ldr pc,=main
    main_return:
               b main_return

    init.c源码:

    //watchdog
    #define WTCON   (*(volatile unsigned long *)0x53000000)
    
    //clock
    #define CLOCKTIME    (*(volatile unsigned long *)0x4c000000)
    #define MPLLCON      (*(volatile unsigned long *)0x4c000004)
    #define CLKDIVN      (*(volatile unsigned long *)0x4c000014)
    #define CAMDIVN      (*(volatile unsigned long *)0x4c000018)
    
    
    //sdram
    #define BWSCON       (*(volatile unsigned long *)0x48000000)
    #define BANKCON0     (*(volatile unsigned long *)0x48000004)
    #define BANKCON1     (*(volatile unsigned long *)0x48000008)
    #define BANKCON2     (*(volatile unsigned long *)0x4800000c)
    #define BANKCON3     (*(volatile unsigned long *)0x48000010)
    #define BANKCON4     (*(volatile unsigned long *)0x48000014)
    #define BANKCON5     (*(volatile unsigned long *)0x48000018)
    #define BANKCON6     (*(volatile unsigned long *)0x4800001c)
    #define BANKCON7     (*(volatile unsigned long *)0x48000020)
    #define REFRESH      (*(volatile unsigned long *)0x48000024)
    #define BANKSIZE     (*(volatile unsigned long *)0x48000028)
    #define MRSRB6       (*(volatile unsigned long *)0x4800002c)
    #define MRSRB7       (*(volatile unsigned long *)0x48000030)
    
    
    
    //nand
    #define NFCONF   (*(volatile unsigned long *)0x4e000000)
    #define NFCONT   (*(volatile unsigned long *)0x4e000004)
    #define NFCMMD   (*(volatile unsigned char *)0x4e000008)
    #define NFADDR   (*(volatile unsigned char *)0x4e00000C)
    #define NFDATA   (*(volatile unsigned char *)0x4e000010)
    #define NFSTAT   (*(volatile unsigned char *)0x4e000020)
    
    
    
    //uart 
    #define  ULCON0      (*(volatile unsigned long *)0x50000000)
    #define  UCON0       (*(volatile unsigned long *)0x50000004)
    #define  UFCON0       (*(volatile unsigned long *)0x50000008)
    #define  UMCON0       (*(volatile unsigned long *)0x5000000c)
    #define  UTRSTAT0    (*(volatile unsigned long *)0x50000010)
    #define  UERSTAT0    (*(volatile unsigned long *)0x50000014)
    #define  UTXH0       (*(volatile unsigned char *)0x50000020)
    #define  URXH0       (*(volatile unsigned char *)0x50000024)
    #define  UBRDIV0     (*(volatile unsigned long *)0x50000028)
    
    //GPH
    #define  GPHCON      (*(volatile unsigned long *)0x56000070)
    #define  GPHDAT      (*(volatile unsigned long *)0x56000074)
    #define  GPHUP       (*(volatile unsigned long *)0x56000078)
    
    
    
    /****************************************    watchdog_init   ********************************************/
    void disable_watchdog(void)
    {
        WTCON=0;
    }
    
    /******************************************    colck_init   ********************************************/
    void clock_init(void)
    {
       MPLLCON = ((0x5c<<12)|(0x01<<4)|(0x02));
       CLKDIVN = ((1<<1)|(1<<0));      //200 MHZ
     //  CAMDIVN = ((1<<1)|(1<<0));         //1:2:4         200M:100M:50M 
    
    
    __asm__
     (
         " mrc p15,0,r1,c1,c0,0  
    "
         " orr r1, r1,#0xc0000000 
    "
         " mcr p15,0,r1,c1,c0,0  
    "
     );
       
    }
    
    void open_icache(void)
    {
      __asm__
          (
         " mrc p15, 0, r0, c1, c0, 0  
    "
         " orr r0, r0, #(1<<12)       
    "
         " mcr    p15, 0, r0, c1, c0, 0 
    "
        );
    }
    
    /******************************************    sdram_init   *******************************************/
    
    void sdram_init(void)
    {
          BWSCON =  0x22011110    ;      //BWSCON
          BANKCON0 =  0x00000700;      //BANKCON0
          BANKCON1 =0x00000700;           //BANKCON1
          BANKCON2 =  0x00000700;       //BANKCON2
          BANKCON3 =  0x00000700;       //BANKCON3
          BANKCON4 =  0x00000700;       //BANKCON4
          BANKCON5 =0x00000700;           //BANKCON5
          BANKCON6 =0x00018005;           //BANKCON6
          BANKCON7 = 0x00018005;       //BANKCON7
          REFRESH  =0x008C04F4    ;      // REFRESH
          BANKSIZE = 0x000000B1;       //BANKSIZE
          MRSRB6 = 0x00000030;           //MRSRB6
          MRSRB7 =  0x00000030    ;      //MRSRB7
    }
    
    
    /******************************************    nand_flash_init   ********************************************/
    
    void select_chip(void)
    {
        NFCONT &= ~(1<<1);
    }
    
    void disselect_chip(void)
    {
        NFCONT |= (1<<1);
    }
    
    void write_command(unsigned char cmd)
    {
        NFCMMD=cmd;
       volatile int i;
        for (i = 0; i < 10; i++);
    
    }
    
    unsigned char   read_data(void)
    {
        return NFDATA;
    }
    
    void write_addr(unsigned int addr)
    {
        unsigned int row,col;
        int i=0;
        row=addr/2048;
        col=addr%2048;
    
        NFADDR=  0xff & col;
        for (i = 0; i < 10; i++);
        NFADDR=(col>>8)& 0xff;
        for (i = 0; i < 10; i++);
        
        NFADDR=row& 0xff;
        for (i = 0; i < 10; i++);
        NFADDR=(row>>8)& 0xff;
        for (i = 0; i < 10; i++);
        NFADDR=(row>>16)& 0xff;
        for (i = 0; i < 10; i++);
    }
    
    int nand_ready(void)
    
    {
        return (NFSTAT & 1);  
    }
    
    
    void nand_init(void)
    {
       NFCONF = (0<<12|1<<8|0<<4);
       NFCONT = (1<<4|1<<1|1<<0); 
    }
    
    void nand_read(unsigned int sour,unsigned char* dest,int copy_size)
    {
       int col=sour % 2048;
       int i=0;
      
       
        
             select_chip();
        while(i<copy_size)    
            {
                
                  write_command(0x00);
              
                  write_addr(sour);
             
                  write_command(0x30);
                
                  while(!nand_ready());
               
                 for(;  (col<2048)&&(i<copy_size);col++)  //page read
                     {
                         dest[i]=read_data();
                         sour++;  i++;        
                    }
                 col=0;
            } 
      
        disselect_chip();
    }
    
    
    
    
    /******************************************    copy_uboot_to_sdram   ********************************************/
    int nand_boot(void)
    {
        volatile unsigned long* top = (volatile unsigned long *)0x00000000;
        int value=*top;
        *top=1234;
        if(*top==1234) 
            {
              *top=value;
              return 1;
            }
        else return 0;    
    }
    
    
    void copy_uboot_to_sdram(unsigned char* sour1,unsigned char *dest,int copy_size)
    {
          int i=0;
          unsigned char *sour = sour1;
          if(nand_boot())  // nand_boot
          {
              while(i<copy_size)
                  {
                   dest[i]=sour[i];i++;
                }
          }
          else              //nor_boot
              {
                nand_read((unsigned long)sour,dest,copy_size);
            }
    }
    
    
    /*********************************************clean_bss*************************************************/
    void clean_bss(void)
    {
        extern long __bss_end,  __bss_start;
        int* p = &__bss_start;
        for(;p < &__bss_end ;p++) *p=0;
    }
    
    
    /********************************************uart_init*****************************************************/
    
    
    void uart0_init(void)
    {
        GPHCON|=0xa0;
        GPHUP=0x0c;
        
        ULCON0=0x03;    
        UCON0=0x05;
        UFCON0=0x00;     
        UMCON0=0x00;     
        UBRDIV0=((50000000/(115200*16))-1);    
    }
    
    unsigned char getc(void)
    {
        while(!(UTRSTAT0 & 0x01));
        return URXH0;
    }
    
    
    void putc(unsigned char date)
    {
        while(!(UTRSTAT0 & 0x02));
        UTXH0=date;
    }
    
    
    void puts(char *str)
    {
      while(*str) putc(*str++);
    
    }
    
    
    
    
    void puthex(unsigned int val)
    {
        /* 0x1234abcd */
        int i;
        int j;
        
        puts("0x");
    
        for (i = 0; i < 8; i++)
        {
            j = (val >> ((7-i)*4)) & 0xf;
            if ((j >= 0) && (j <= 9))
                putc('0' + j);
            else
                putc('A' + j - 0xa);
            
        }
        
    }

    tag.c源码:

    /*****************************************string_lib***********************************************/
    int strlen(char *str)
    {
          int i=0;
         while(str[i] != 0) i++;
         return i;
    }
    
    void strcopy(char *dest,char *sour)
    {
       while((*dest++ = *sour++)!= 0);
    }
    
    
    /*****************************************tag_init************************************************/
    #define tag_next(type)  (struct tag *) ((unsigned long *)(type) + (type)->hdr.size) 
    #define tag_size(size)  ((sizeof(struct tag_header)+sizeof(struct size))>>2)
    
    struct tag_header
    {
        unsigned long   size;
        unsigned long   tag_type;
    };
    
    
    
    struct tag_core
    {
       unsigned long   flags;
       unsigned long   pagesize;
       unsigned long   rootdevf;
    };
    
    
    struct tag_mem32
    {
        unsigned long  size;
           unsigned long  start;
    };
    
    struct tag_cmdline
    {
      char cmdline[1]; 
    };
    
    
    struct tag 
    {
        struct tag_header hdr;
        union
            {
               struct tag_core       core;
               struct tag_mem32      mem32;
               struct tag_cmdline    cmdline;
            }u;
    };
    
    static  struct tag *params=(struct tag *)0x30000100;
    
    void set_start_tag(void)
    {
       params->hdr.size=tag_size(tag_core);
       params->hdr.tag_type=0x54410001;
       
       params->u.core.flags= 0;
       params->u.core.pagesize= 0;
       params->u.core.rootdevf= 0;
    
       params=tag_next(params);
    }
    
    
    void set_memory_tag(void)
    {
       params->hdr.size= tag_size(tag_mem32);
       params->hdr.tag_type = 0x54410002;
    
       params->u.mem32.size =64*1024*1024;
       params->u.mem32.start =
    0x30000000;
    
       params=tag_next(params);
    
    }
    
    
    void set_cmdline_tag(char *cmdline)
    {
       int len=strlen(cmdline)+1;
        params->hdr.size = (sizeof(struct tag_header)+len+3)>>2;
        params->hdr.tag_type = 0x54410009;
        strcopy(params->u.cmdline.cmdline ,cmdline);
        
        params=tag_next(params);
    }
    
    
    void set_end_tag(void)
    {
       params->hdr.size = 0;
       params->hdr.tag_type = 0;
    }

    tag.h源码:

    #ifndef  _TAG_H_
    #define _TAG_H_
    
    void set_cmdline_tag(char * cmdline);
    void set_end_tag(void);
    void set_memory_tag(void);
    void set_start_tag(void);
    
    
    
    
    
    
    
    
    #endif 

    main.c源码:

    extern void nand_read(unsigned long sour, unsigned char * dest, int copy_size);
    extern void puts(char * str);
    void putc(unsigned char date);
    void puthex(unsigned int val);
    
    #include"tag.h"
    
    
    
    
    
    int main(void)
    {
        void (*thekernel)(int zero,int arch,unsigned int params);
    
    
        puts("bootloader start.....
    
    ");
    
    
        //copy kernel
        puts("1. copy kernal to sdram
    
    ");
        nand_read(0x60000+64,(unsigned char *)0x30008000,0x200000);    
    
        
        //set params
        set_start_tag();
        set_memory_tag();
        set_cmdline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");
        set_end_tag();
        puts("2. set kernel parameters
    
    ");
    
        //jump to kernel
        puts("3. jump to kernel
    
    ");
        thekernel=(void (*)(int,int ,unsigned int))0x30008000;
        thekernel(0,362,0x30000100); 
        
    
        //error
        puts("something wrong
    
    ");
        return 0;
    }

    编译用的Makefile文件:

    OBJS := start.o init.o tag.o  main.o
    CFLAGS := -O2 -Wall
    CPPFLAGS := -nostdinc -fno-builtin
    
    CC = arm-linux-gcc 
    LD = arm-linux-ld  
    OBJCOPY = arm-linux-objcopy  
    OBJDUMP = arm-linux-objdump  
    
    uboot.bin: ${OBJS}
        ${LD} -Tuboot.lds -o uboot.elf $^
        ${OBJCOPY} -O binary -S uboot.elf $@  
        ${OBJDUMP} -D -m arm uboot.elf > uboot.dis
    
    %.o:%.c 
        ${CC} ${CPPFLAGS} ${CFLAGS} -o $@ -c $<
    
    %.o:%.s 
        ${CC} ${CPPFLAGS} ${CFLAGS} -o $@ -c $<
    
    
    clean:
        rm -f *.o *.bin *.elf *.dis

    连接脚本:

    SECTIONS
    {
        . = 0x33f80000;
        .text : {*(.text)}
        
        . = ALIGN(4);
        .rodata : {*(.rodata*)}
    
        . = ALIGN(4);
        .data : {*(.data)}
    
        . = ALIGN(4);
        __bss_start = .;
        .bss : {*(.bss) *(COMMON)}
        __bss_end = .;
    }
    
     
  • 相关阅读:
    Map的两张遍历方法 keySet(),entrySet()
    http://localhost:8080请求用户名和密码。信息为:“XDB” 解决办法
    redis 集群出现的错误
    通信 缩略词
    redis
    hadoop 概念
    mysql 集群的一些概念
    SQL 基本关键字 函数 关联 连接
    JAVA集合
    SQL.Cookbook 读书笔记5 元数据查询
  • 原文地址:https://www.cnblogs.com/zsy12138/p/10396988.html
Copyright © 2011-2022 走看看