Chinaunix首页 | 论坛 | 博客
  • 博客访问: 14836
  • 博文数量: 11
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 11
  • 用 户 组: 普通用户
  • 注册时间: 2014-01-27 16:17
个人简介

一个背着梦想的北漂者!

文章分类

全部博文(11)

文章存档

2015年(1)

2014年(10)

我的朋友

分类: 嵌入式

2014-02-20 18:07:51

原文地址:从零开始uboot—实现(6) 作者:andyhzw

操作系统:ubuntu10.04


前言:
    在上一章节中,分析了实现的思路。下面就是实现的源码,在源码中有详细的注释。
1,start.S

点击(此处)折叠或打开

  1. /* watch dog registers */
  2. #define    WTCON                        0x53000000


  3. /* clock register */
  4. #define CLKDIVN                        0x4C000014
  5. #define MPLLCON                        0x4C000004
  6. #define S3C2440_MPLL_200MHZ        ((0x5c<<12)|(0x01<<4)|(0x02))    
  7. #define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))


  8. /* sdram */
  9. #define MEM_CTL_BASE                0x48000000
  10.         

  11. .text
  12. .global    _start
  13. _start:

  14. /* 1. 关闭看门狗 */
  15.     ldr r0, =WTCON
  16.     mov r1, #0
  17.     str r1, [r0]


  18. /* 2. 设置时钟 */
  19.     ldr r0, =CLKDIVN
  20.     //mov r1, #0x03;            // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1    
  21.     mov r1, #0x05;             // FCLK:HCLK:PCLK=1:4:8
  22.     str r1, [r0]

  23.     /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
  24.     mrc        p15, 0, r1, c1, c0, 0        /* 读出控制寄存器 */
  25.     orr        r1,    r1, #0xc0000000            /* 设置为“asynchronous bus mode” */
  26.     mcr        p15, 0, r1, c1, c0, 0        /* 写入控制寄存器 */

  27.     /* MPLLCON = S3C2440_MPLL_200MHZ */
  28.     ldr    r0, =MPLLCON
  29.     //ldr r1, =S3C2440_MPLL_200MHZ
  30.     ldr r1, =S3C2440_MPLL_400MHZ
  31.     str r1, [r0]

  32.     /* 启动ICACHE */
  33.     mrc p15, 0, r0, c1, c0, 0    @ read control reg
  34.     orr r0, r0, #(1<<12)
  35.     mcr    p15, 0, r0, c1, c0, 0 @ write it back


  36. /* 3. 初始化 SDRAM */
  37.     ldr r0, =MEM_CTL_BASE
  38.     adr r1, sdram_config
  39.     add r3, r0, #(13*4)

  40. 1:
  41.     ldr r2, [r1], #4
  42.     str r2, [r0], #4
  43.     cmp r0, r3
  44.     bne    1b


  45. /* 4. 重定位:把 bootloader 本身的代码从flash中复制到对应的内存的链接地址中*/
  46.     ldr sp,    =0x34000000        /* 64M SDRAM ,设置栈指针,栈是向下生长,故指向邋邋錝DRAM的最高处*/

  47.     bl nand_init            /* 初始化 NAND FLASH */

  48.     mov r0, #0                /* src执行0地址。当为NAND FLASH 启动时,src指向的是邋錍PU片内内存的地址0.
  49.                              当 NOR FLASH 启动时,src指向的是NOR FLASH 的地址0*/    
  50.     ldr r1, =_start            /* dest地址,为 *.lds 中定义的起始地址,此处为 0x33f80000*/
  51.     ldr r2, =__bss_start    /* bss 段的起始地址*/
  52.     sub r2, r2, r1            /* r2 - r1,表示这个*.bin 文件的大小*/
  53.     bl    copy_code_to_sdram    

  54.     bl     clear_bss             /* 清空 sdram 中 *.bin文件的bss段内存地址*/

  55.         
  56. /* 5. 跳转到第二部分代码中执行*/
  57.     ldr lr, =halt            /* 当 main 函数返回时,执行 halt 代码*/
  58.     ldr pc, =main


  59. halt:                        /* 死循环 */
  60.     b    halt



  61. sdram_config:
  62.     .long 0x22011110     //BWSCON
  63.     .long 0x00000700     //BANKCON0
  64.     .long 0x00000700     //BANKCON1
  65.     .long 0x00000700     //BANKCON2
  66.     .long 0x00000700     //BANKCON3
  67.     .long 0x00000700     //BANKCON4
  68.     .long 0x00000700     //BANKCON5
  69.     .long 0x00018005     //BANKCON6
  70.     .long 0x00018005     //BANKCON7
  71.     .long 0x008C04F4     // REFRESH
  72.     .long 0x000000B1     //BANKSIZE
  73.     .long 0x00000030     //MRSRB6
  74.     .long 0x00000030     //MRSRB7

2,boot.lds

点击(此处)折叠或打开

  1. SECTIONS {
  2.     . = 0x33f80000;
  3.     .text : { *(.text) }
  4.     
  5.     . = ALIGN(4);
  6.     .rodata : {*(.rodata)}
  7.     
  8.     . = ALIGN(4);
  9.     .data : { *(.data) }
  10.     
  11.     . = ALIGN(4);
  12.     __bss_start = .;
  13.     .bss : { *(.bss) *(COMMON) }
  14.     __bss_end = .;
  15. }
3,init.c
点击(此处)折叠或打开
  1. /* nand flash */
  2. #define NFCONF                         (*((volatile unsigned long *)0x4E000000))
  3. #define NFCONT                         (*((volatile unsigned long *)0x4E000004))
  4. #define NFCMMD                        (*((volatile unsigned char *)0x4E000008))
  5. #define NFADDR                        (*((volatile unsigned char *)0x4E00000C))
  6. #define NFDATA                        (*((volatile unsigned char *)0x4E000010))
  7. #define NFSTAT                        (*((volatile unsigned char *)0x4E000020))


  8. /* gpio */
  9. #define GPHCON                        (*((volatile unsigned long *)0x56000070))
  10. #define GPHUP                        (*((volatile unsigned long *)0x56000078))


  11. /* uart registers*/
  12. #define ULCON0                        (*((volatile unsigned long *)0x50000000))
  13. #define UCON0                        (*((volatile unsigned long *)0x50000004))
  14. #define UFCON0                        (*((volatile unsigned long *)0x50000008))
  15. #define UMCON0                        (*((volatile unsigned long *)0x5000000c))
  16. #define UTRSTAT0                    (*((volatile unsigned long *)0x50000010))
  17. #define UTXH0                        (*((volatile unsigned long *)0x50000020))
  18. #define URXH0                        (*((volatile unsigned long *)0x50000024))
  19. #define UBRDIV0                        (*((volatile unsigned long *)0x50000028))


  20. void nand_read(unsigned int addr, unsigned char *buf, unsigned int len);
  21. void nand_addr(unsigned int addr);

  22. void        nand_init(void)
  23. {
  24. #define    TACLS        0
  25. #define    TWRPH0        1
  26. #define    TWRPH1        0

  27.     /* 设置时钟*/
  28.     NFCONF    = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4) ;
  29.     /* 使能NAND FLASH 控制器,初始化ECC,禁止片选*/
  30.     NFCONT     = (1<<4) | (1<<1) | (1<<0);
  31. }


  32. static void        nand_select(void)
  33. {
  34.     NFCONT &= ~(1<<1);
  35. }


  36. static void        nand_deselect(void)
  37. {
  38.     NFCONT |= (1<<1);
  39. }


  40. static void        nand_cmd(unsigned char cmd)
  41. {
  42.     volatile     char i = 0;
  43.     NFCMMD = cmd;
  44.     for( i = 0; i < 10; i++) ;    /* 稍微延时,确保命令正确写入*/
  45. }


  46. static void        nand_wait_ready(void)
  47. {
  48.     while(!(NFSTAT & 0x01)) ;
  49. }


  50. static unsigned char nand_data(void)
  51. {
  52.     return NFDATA;
  53. }


  54. void    nand_addr(unsigned int addr)
  55. {

  56.     unsigned int col = addr % 2048;
  57.     unsigned int page = addr / 2048;
  58.     volatile int i;


  59.     /* 写一个地址,需要分成五个步骤*/
  60.     /* 先写入两个列地址*/
  61.     NFADDR = col & 0xff;
  62.     for    (i = 0; i < 10; i++);
  63.     NFADDR = (col >> 8) & 0xff;
  64.     for (i = 0; i < 10; i++);

  65.     
  66.     NFADDR = page & 0xff;
  67.     for (i = 0; i < 10; i++);
  68.     NFADDR = (page >> 8) & 0xff;
  69.     for (i = 0; i < 10; i++);
  70.     NFADDR = (page >> 16) & 0xff;
  71.     for (i = 0; i < 10; i++);
  72. }



  73. void        nand_read(unsigned int addr, unsigned char * buffer,unsigned int len)
  74. {
  75.     int    col    = addr % 2048;    
  76.     int    i     = 0;

  77.     /* 1 选中*/
  78.     nand_select();

  79.     while(i < len)
  80.     {
  81.         /* 2 发出读命令00h */
  82.         nand_cmd(0x00);

  83.         /* 3 发出地址(分5 步发出) */
  84.         nand_addr(addr);
  85.         
  86.         /* 4 发出读命令30h */
  87.         nand_cmd(0x30);

  88.         /* 5 判断状态*/
  89.         nand_wait_ready();

  90.         /* 6 读数据*/
  91.         /* 当前NAND FLASH 是以2k为一页的*/
  92.         /* 每次读取一页数据到对应寄存器中*/
  93.         for( ; (col < 2048) && ( i < len) ; col++ )    
  94.         {
  95.             buffer[i] = nand_data();
  96.             i++;
  97.             addr++;
  98.         }
  99.         col = 0;            /* 如果数据分布在不同的页中,则读取下一页时,从第0列开始读取*/
  100.     }

  101.     /* 7 取消选中*/
  102.     nand_deselect();
  103. }


  104. #if 1
  105. int         isBootFromNorFlash(void)
  106. {
  107.     volatile int *p = (volatile int*)0;
  108.     int val = 0;

  109.     val = *p;
  110.     *p = 0x12345678;        /* Nor Flash 中是不允许写入数据的*/

  111.     if(0x12345678 == *p)
  112.     {
  113.         /* 写成功,是NAND FLASH */
  114.         *p = val;
  115.         return 0;
  116.     }
  117.     else
  118.     {
  119.         /* NOR FLASH 不能像内存一样写*/
  120.         return 1;
  121.     }
  122. }



  123. void     copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
  124. {
  125.     int i = 0;
  126.     
  127.     if(isBootFromNorFlash())
  128.     {
  129.         /* NOR FLASH 中的数据可以像内存中的数据那样,直接读取*/
  130.         while( i < len )
  131.         {
  132.             dest[i] = src[i];
  133.             i++;
  134.         }
  135.     }
  136.     else
  137.     {
  138.         /* NAND FLASH*/
  139.         nand_read((unsigned int )src, dest, len);
  140.     }
  141. }

  142. #endif

  143. void     clear_bss(void)
  144. {
  145.     extern    int    __bss_start,__bss_end;
  146.     int *p = &__bss_start;

  147.     for( ; p < &__bss_end; p++)
  148.         *p = 0;
  149. }




  150. #define    PCLK        50000000        /* start.S 中把时钟设置PCLK为50MHz*/
  151. #define    UART_CLK    PCLK            /* UART0的时钟源设为PCLK */
  152. #define    UART_BAUD_RATE    115200    /* 波特率为115200*/
  153. #define    UART_BRD    ((UART_CLK / (UART_BAUD_RATE * 16)) - 1)

  154. void        uart0_init(void)
  155. {
  156.     GPHCON        |=     0xa0;            /* GPH2,GPH3用作TXD0,RXD0 */
  157.     GPHUP        =     0x0C;            /* GPH2,GPH3 内部上拉*/

  158.     ULCON0        =     0x03;            /* 8N1(8个数据位,无较验,1个停止位) */
  159.     UCON0        =     0x05;            /* 查询方式,UART时钟源为PCLK */
  160.     UFCON0        =     0x00;            /* 不使用FIFO */
  161.     UMCON0        =     0x00;            /* 不使用流控制*/
  162.     UBRDIV0        =     UART_BRD;        /* 波特率为115200 */
  163. }



  164. #define TXD0READY (1<<2)

  165. void        putc(unsigned char c)
  166. {
  167.     /* 等待,直到发送缓冲区中的数据已经全部发送出去 */
  168.     while(!(UTRSTAT0 & TXD0READY)) ;

  169.     /* 向UTXH0寄存器中写入数据,UART即自动将它发送出去 */
  170.      UTXH0    = c;
  171. }



  172. void        puts(char * str)
  173. {
  174.     int    i = 0;
  175.     while(str[i])
  176.     {
  177.         putc(str[i]);
  178.         ++i;
  179.     }
  180. }

4,boot.c

点击(此处)折叠或打开

  1. #include "setup.h"

  2. extern    void        uart0_init(void);
  3. extern    void        nand_read(unsigned int addr, unsigned char * buffer,unsigned int len);
  4. extern    void        puts(char * str);



  5. int strlen(char *str)
  6. {
  7.     int i = 0;
  8.     while (str[i])
  9.     {
  10.         i++;
  11.     }
  12.     return i;
  13. }

  14. void strcpy(char *dest, char *src)
  15. {
  16.     while ((*dest++ = *src++) != '\0');
  17. }


  18. static struct tag *params;

  19. void setup_start_tag(void)
  20. {
  21.     params = (struct tag *)0x30000100;    /* 内核约定存放在这个地方*/

  22.     params->hdr.tag = ATAG_CORE;
  23.     params->hdr.size = tag_size (tag_core);

  24.     params->u.core.flags = 0;
  25.     params->u.core.pagesize = 0;
  26.     params->u.core.rootdev = 0;

  27.     params = tag_next (params);
  28. }


  29. void setup_memory_tags(void)
  30. {
  31.     params->hdr.tag = ATAG_MEM;
  32.     params->hdr.size = tag_size (tag_mem32);
  33.     
  34.     params->u.mem.start = 0x30000000;    /* SDRAM起始地址*/
  35.     params->u.mem.size = 64*1024*1024;    /* 其大小为64 M */
  36.     
  37.     params = tag_next (params);
  38. }


  39. void setup_commandline_tag(char *cmdline)
  40. {
  41.     int len = strlen(cmdline) + 1;
  42.     
  43.     params->hdr.tag = ATAG_CMDLINE;

  44.     /* 以4 个字节对齐,并且以4个字节为单位*/
  45.     params->hdr.size = (sizeof (struct tag_header) + len + 3) >> 2;

  46.     strcpy (params->u.cmdline.cmdline, cmdline);

  47.     params = tag_next (params);
  48. }


  49. void setup_end_tag(void)
  50. {
  51.     params->hdr.tag = ATAG_NONE;
  52.     params->hdr.size = 0;
  53. }


  54. int main(void)
  55. {
  56.     /* 函数指针,执行内核的起始位置*/
  57.     void (*theKernel)(int zero, int arch, unsigned int params);

  58.     /* 1 帮内核设置串口: 内核启动的开始部分会从串口打印一些信息,但是内核一开始没有初始化串口*/
  59.     uart0_init();

  60.     /* 2 从NAND FLASH 中把内核读入到内存中*/
  61.     puts("Copy kernel from nand\n\r");
  62.     /* 内核存放在NAND FLASH 中的0x60000 地址。
  63.          存放的是uImage,该文件包含64 字节的头部信息。
  64.          内核一般都存放在0x30008000这个地址,除非手动修改内核。*/
  65.     nand_read(0x60000+64,( unsigned char * )0x30008000, 0x200000);

  66.     /* 3 设置引导内核的参数*/
  67.     puts("Set boot params\n\r");
  68.     setup_start_tag();
  69.     setup_memory_tags();    /*内核大小*/
  70.     setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");    /* 命令参数*/
  71.     setup_end_tag();

  72.     /* 4 跳转执行*/
  73.     puts("Boot kernel\n\r");
  74.     theKernel = (void (*)(int ,int ,unsigned int))0x30008000; /* 真正的内核起始地址*/
  75.     /*     参数1 : 默认为0.
  76.         参数2 : 为machine ID,当前设置为362。可在内核源码中: arch/arm/tools/mach_types 修改。
  77.         参数3 : 为参数的起始地址(params)*/
  78.     theKernel(0,362,0x30000100);

  79.     /* 5 异常:如果正确引导内核,不应该执行到这里*/
  80.     puts("Error!\n\r");
  81.     return -1;
  82. }

5,setup.h
    该文件是直接从uboot中复制过来的。

点击(此处)折叠或打开

  1. /*
  2.  * linux/include/asm/setup.h
  3.  *
  4.  * Copyright (C) 1997-1999 Russell King
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License version 2 as
  8.  * published by the Free Software Foundation.
  9.  *
  10.  * Structure passed to kernel to tell it about the
  11.  * hardware it's running on. See linux/Documentation/arm/Setup
  12.  * for more info.
  13.  *
  14.  * NOTE:
  15.  * This file contains two ways to pass information from the boot
  16.  * loader to the kernel. The old struct param_struct is deprecated,
  17.  * but it will be kept in the kernel for 5 years from now
  18.  * (2001). This will allow boot loaders to convert to the new struct
  19.  * tag way.
  20.  */
  21. #ifndef __ASMARM_SETUP_H
  22. #define __ASMARM_SETUP_H

  23. #define u8 unsigned char
  24. #define u16 unsigned short
  25. #define u32 unsigned long

  26. /*
  27.  * Usage:
  28.  * - do not go blindly adding fields, add them at the end
  29.  * - when adding fields, don't rely on the address until
  30.  * a patch from me has been released
  31.  * - unused fields should be zero (for future expansion)
  32.  * - this structure is relatively short-lived - only
  33.  * guaranteed to contain useful data in setup_arch()
  34.  */
  35. #define COMMAND_LINE_SIZE 1024

  36. /* This is the old deprecated way to pass parameters to the kernel */
  37. struct param_struct {
  38.     union {
  39.     struct {
  40.      unsigned long page_size;        /* 0 */
  41.      unsigned long nr_pages;        /* 4 */
  42.      unsigned long ramdisk_size;        /* 8 */
  43.      unsigned long flags;        /* 12 */
  44. #define FLAG_READONLY    1
  45. #define FLAG_RDLOAD    4
  46. #define FLAG_RDPROMPT    8
  47.      unsigned long rootdev;        /* 16 */
  48.      unsigned long video_num_cols;    /* 20 */
  49.      unsigned long video_num_rows;    /* 24 */
  50.      unsigned long video_x;        /* 28 */
  51.      unsigned long video_y;        /* 32 */
  52.      unsigned long memc_control_reg;    /* 36 */
  53.      unsigned char sounddefault;        /* 40 */
  54.      unsigned char adfsdrives;        /* 41 */
  55.      unsigned char bytes_per_char_h;    /* 42 */
  56.      unsigned char bytes_per_char_v;    /* 43 */
  57.      unsigned long pages_in_bank[4];    /* 44 */
  58.      unsigned long pages_in_vram;    /* 60 */
  59.      unsigned long initrd_start;        /* 64 */
  60.      unsigned long initrd_size;        /* 68 */
  61.      unsigned long rd_start;        /* 72 */
  62.      unsigned long system_rev;        /* 76 */
  63.      unsigned long system_serial_low;    /* 80 */
  64.      unsigned long system_serial_high;    /* 84 */
  65.      unsigned long mem_fclk_21285; /* 88 */
  66.     } s;
  67.     char unused[256];
  68.     } u1;
  69.     union {
  70.     char paths[8][128];
  71.     struct {
  72.      unsigned long magic;
  73.      char n[1024 - sizeof(unsigned long)];
  74.     } s;
  75.     } u2;
  76.     char commandline[COMMAND_LINE_SIZE];
  77. };


  78. /*
  79.  * The new way of passing information: a list of tagged entries
  80.  */

  81. /* The list ends with an ATAG_NONE node. */
  82. #define ATAG_NONE    0x00000000

  83. struct tag_header {
  84.     u32 size;
  85.     u32 tag;
  86. };

  87. /* The list must start with an ATAG_CORE node */
  88. #define ATAG_CORE    0x54410001

  89. struct tag_core {
  90.     u32 flags;        /* bit 0 = read-only */
  91.     u32 pagesize;
  92.     u32 rootdev;
  93. };

  94. /* it is allowed to have multiple ATAG_MEM nodes */
  95. #define ATAG_MEM    0x54410002

  96. struct tag_mem32 {
  97.     u32    size;
  98.     u32    start;    /* physical start address */
  99. };

  100. /* VGA text type displays */
  101. #define ATAG_VIDEOTEXT    0x54410003

  102. struct tag_videotext {
  103.     u8        x;
  104.     u8        y;
  105.     u16        video_page;
  106.     u8        video_mode;
  107.     u8        video_cols;
  108.     u16        video_ega_bx;
  109.     u8        video_lines;
  110.     u8        video_isvga;
  111.     u16        video_points;
  112. };

  113. /* describes how the ramdisk will be used in kernel */
  114. #define ATAG_RAMDISK    0x54410004

  115. struct tag_ramdisk {
  116.     u32 flags;    /* bit 0 = load, bit 1 = prompt */
  117.     u32 size;    /* decompressed ramdisk size in _kilo_ bytes */
  118.     u32 start;    /* starting block of floppy-based RAM disk image */
  119. };

  120. /* describes where the compressed ramdisk image lives (virtual address) */
  121. /*
  122.  * this one accidentally used virtual addresses - as such,
  123.  * its depreciated.
  124.  */
  125. #define ATAG_INITRD    0x54410005

  126. /* describes where the compressed ramdisk image lives (physical address) */
  127. #define ATAG_INITRD2    0x54420005

  128. struct tag_initrd {
  129.     u32 start;    /* physical start address */
  130.     u32 size;    /* size of compressed ramdisk image in bytes */
  131. };

  132. /* board serial number. "64 bits should be enough for everybody" */
  133. #define ATAG_SERIAL    0x54410006

  134. struct tag_serialnr {
  135.     u32 low;
  136.     u32 high;
  137. };

  138. /* board revision */
  139. #define ATAG_REVISION    0x54410007

  140. struct tag_revision {
  141.     u32 rev;
  142. };

  143. /* initial values for vesafb-type framebuffers. see struct screen_info
  144.  * in include/linux/tty.h
  145.  */
  146. #define ATAG_VIDEOLFB    0x54410008

  147. struct tag_videolfb {
  148.     u16        lfb_width;
  149.     u16        lfb_height;
  150.     u16        lfb_depth;
  151.     u16        lfb_linelength;
  152.     u32        lfb_base;
  153.     u32        lfb_size;
  154.     u8        red_size;
  155.     u8        red_pos;
  156.     u8        green_size;
  157.     u8        green_pos;
  158.     u8        blue_size;
  159.     u8        blue_pos;
  160.     u8        rsvd_size;
  161.     u8        rsvd_pos;
  162. };

  163. /* command line: \0 terminated string */
  164. #define ATAG_CMDLINE    0x54410009

  165. struct tag_cmdline {
  166.     char    cmdline[1];    /* this is the minimum size */
  167. };

  168. /* acorn RiscPC specific information */
  169. #define ATAG_ACORN    0x41000101

  170. struct tag_acorn {
  171.     u32 memc_control_reg;
  172.     u32 vram_pages;
  173.     u8 sounddefault;
  174.     u8 adfsdrives;
  175. };

  176. /* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */
  177. #define ATAG_MEMCLK    0x41000402

  178. struct tag_memclk {
  179.     u32 fmemclk;
  180. };

  181. struct tag {
  182.     struct tag_header hdr;
  183.     union {
  184.         struct tag_core        core;
  185.         struct tag_mem32    mem;
  186.         struct tag_videotext    videotext;
  187.         struct tag_ramdisk    ramdisk;
  188.         struct tag_initrd    initrd;
  189.         struct tag_serialnr    serialnr;
  190.         struct tag_revision    revision;
  191.         struct tag_videolfb    videolfb;
  192.         struct tag_cmdline    cmdline;

  193.         /*
  194.          * Acorn specific
  195.          */
  196.         struct tag_acorn    acorn;

  197.         /*
  198.          * DC21285 specific
  199.          */
  200.         struct tag_memclk    memclk;
  201.     } u;
  202. };

  203. struct tagtable {
  204.     u32 tag;
  205.     int (*parse)(const struct tag *);
  206. };


  207. #define tag_member_present(tag,member)                \
  208.     ((unsigned long)(&((struct tag *)0L)->member + 1)    \
  209.         <= (tag)->hdr.size * 4)

  210. #define tag_next(t)    ((struct tag *)((u32 *)(t) + (t)->hdr.size))
  211. #define tag_size(type)    ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)

  212. #define for_each_tag(t,base)        \
  213.     for (t = base; t->hdr.size; t = tag_next(t))

  214. /*
  215.  * Memory map description
  216.  */
  217. #define NR_BANKS 8

  218. struct meminfo {
  219.     int nr_banks;
  220.     unsigned long end;
  221.     struct {
  222.         unsigned long start;
  223.         unsigned long size;
  224.         int node;
  225.     } bank[NR_BANKS];
  226. };

  227. extern struct meminfo meminfo;

  228. #endif

6,Makefile

点击(此处)折叠或打开

  1. CC = arm-linux-gcc
  2. LD = arm-linux-ld
  3. AR = arm-linux-ar
  4. OBJCOPY = arm-linux-objcopy
  5. OBJDUMP = arm-linux-objdump

  6. CFLAGS         := -Wall -O2
  7. CPPFLAGS     := -nostdinc -nostdlib -fno-builtin

  8. objs := start.o init.o boot.o

  9. boot.bin: $(objs)
  10.     ${LD} -Tboot.lds -o boot.elf $^
  11.     ${OBJCOPY} -O binary -S boot.elf $@
  12.     ${OBJDUMP} -D -m arm boot.elf > boot.dis
  13.     
  14. %.o:%.c
  15.     ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

  16. %.o:%.S
  17.     ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

  18. clean:
  19.     rm -f *.o *.bin *.elf *.dis

7,总结
   至此,从零开始实现的uboot基本完成。


阅读(446) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~