Chinaunix首页 | 论坛 | 博客
  • 博客访问: 153352
  • 博文数量: 101
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 9
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-17 08:11
文章分类
文章存档

2017年(91)

2016年(10)

我的朋友

分类: 嵌入式

2017-01-13 15:32:03

 第二阶段中首先运行start_armboot函数,在lib_arm/board.c文件中,此函数前几行如下:

  1. /* Pointer is writable since we allocated a register for it */
  2.          gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t)); (1)
  3.         /* compiler optimization barrier needed for GCC >= 3.4 */
  4.          __asm__ __volatile__("": : :"memory"); (2)
  5.  
  6.          memset ((void*)gd, 0, sizeof (gd_t)); (3)
  7.          gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); (4)
  8.          memset (gd->bd, 0, sizeof (bd_t)); (5)
  9.  
  10.          gd->flags |= GD_FLG_RELOC; (6)
  11.  
  12.          monitor_flash_len = _bss_start - _armboot_start; (7)
  13.  
  14.          for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { (8)
  15.                  if ((*init_fnc_ptr)() != 0) {
  16.                          hang ();
  17.                  }
  18.          }
首先gd_t结构体,应注意下,它其中包含结构体db_t的指针。start_armboot函数开始几行主要是在设置gd结构体,在lib_arm/board.c文件开始时有一行宏DECLARE_GLOBAL_DATA_PTR;宏定义在asm-arm/global_data.h文件中定义。
  1. #define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
这句表明引用此宏就会声明一个gd_t结构体的指针,gd指向全局变量并且被指定保存到寄存器r8。函数start_armboot
(1):_armboot_start
定义为程序开始的_start标号,在第二阶段中_start程序代码已经被移动到内存中,不过这个不关这里的事,编译时指定了TEXT_BASE的为编译出程序的起始地址。所以_armboot_start就是TEXT_BASE的地址。这个地址减去CONFIG_SYS_MALLOC_LEN再减去gd_t自身的大小,就是gd这个全局结构体应该存放的地方,然后将地址赋值给gd这个由上述宏声明的指针。在下面一行
(2)
是编译器指令,主要是为了禁止从cache读数据,直接从内存读取。详见其他资料。
(3)
这句就是为gd指向的区域清出gd_t大小的空间。
(4)(5)
两行是设置bd结构体,情况大体与gd相同,
(6)
设置标志为重新加在到RAM
(7)
计算uboot整个映像文件的长度,是代码开始地址到BSS段开始地址。
(8)
for循环,循环执行init_sequence函数指令数组中的函数指针所指向的函数。下面大体看一下其中大概有那些函数。

1.board_init,
此函数在board/mini2440.c文件中。它首先定义了两个结构体存储24x0中时钟相关和gpio相关寄存器的地址。因为相关功能的寄存器是在连续地址的,所以可以用一个结构体存储。如存储时钟相关结构体:
  1. struct s3c24x0_clock_power {
  2.          S3C24X0_REG32 LOCKTIME;
  3.          S3C24X0_REG32 MPLLCON;
  4.          S3C24X0_REG32 UPLLCON;
  5.          S3C24X0_REG32 CLKCON;
  6.          S3C24X0_REG32 CLKSLOW;
  7.          S3C24X0_REG32 CLKDIVN;
  8.  };
然后设置主时钟频率和USB时钟频率,虽然时钟频率在第一阶段start.S中已经设置过,但是这个还是设置了一边,可能是为了强调分离两个阶段。然后设置GPIO。怎样设置这些寄存器可以参考数据手册,移植到2440上可以根据板子的实际情况设定。这里对GPIO的设置代码注释一下
  1. gpio->GPACON = 0x007FFFFF; /*23个io端口全部设置为功能引脚*/
  2.  gpio->GPBCON = 0x00295551; /*B0-B8中B1为输入,其他均为输出,B9和B10为功能*/
  3.  gpio->GPBUP = 0x000007FF; /*禁止所有B端口的上拉*/
  4.  gpio->GPCCON = 0xAAAAAAAA; /*C端口全部为功能引脚*/
  5.  gpio->GPCUP = 0x0000FFFF; /*禁止所有C端口的上拉*/
  6.  gpio->GPDCON = 0xAAAAAAAA;
  7.  gpio->GPDUP = 0x0000FFFF;
  8.  gpio->GPECON = 0xAAAAAAAA;
  9.  gpio->GPEUP = 0x0000FFFF;
  10.  gpio->GPFCON = 0x000055AA; /*4个输出,4个外部中断*/
  11.  gpio->GPFUP = 0x000000FF;
  12.  gpio->GPGCON = 0xFF95FF3A;
  13.  gpio->GPGUP = 0x0000FFFF;
  14.  gpio->GPHCON = 0x0016FAAA;
  15.  gpio->GPHUP = 0x000007FF;

  16.  gpio->EXTINT0=0x22222222; /*3位设置一个中断 设置为一串2 可以循环所有的触发方式配置*/
  17.  gpio->EXTINT1=0x22222222;
  18.  gpio->EXTINT2=0x22222222;

然后这句gd->bd->bi_arch_number = MACH_TYPE_MINI2440;设置机器编码,这个编码要和内核中的匹配。
然后设置内核参数地址!gd->bd->bi_boot_params = 0x30000100 cache使能(此函数为空)

2.time_init,
此函数是设置定时器的,具体参见datasheet
各函数也都是进行一些初始化功能,列出如下。
 
  1. env_init, /*初始化环境变量,设置gd->env_addr等,具体是哪个源文件中的函数,根据mini2440.h中的定义,相应的Makefile会选择性编译相应源文件*/
  2.  init_baudrate, /*初始化波特率--lib_arm/board.c 此函数会调用common/cmd_nveidt.c中的getenv_r来获取环境变量。这个函数稍后分析 */
  3.  serial_init, /* 串口初始化--drivers/serial/serial_s3c24x0.c */
  4.  console_init_f, /* 控制通讯台初始化阶段1--common/console.c */
  5.  display_banner, /*打印U-Boot版本、编译的时间--gedit lib_arm/board.c */
  6.  dram_init, /*配置可用的RAM-- board/samsung/mini2440/mini2440.c */
  7.  display_dram_config, /* 显示RAM信息--lib_arm/board.c */

getenv_r
函数用来获取环境变量安数字返回,getenv则是安字符形式返回环境变量。
getenv
函数主要部分:
  1. for (i=0; env_get_char(i) != '\0'; i=nxt+1) { (1)
  2.                  int val;
  3.          
  4.                  for (nxt=i; env_get_char(nxt) != '\0'; ++nxt) { (2)
  5.                          if (nxt >= CONFIG_ENV_SIZE) {
  6.                                  return (NULL);
  7.                          }
  8.                  }
  9.                  if ((val=envmatch((uchar *)name, i)) < 0) (3)
  10.                          continue;
  11.                  return ((char *)env_get_addr(val)); (4)
  12.  }
1)每个环境变量之间是以'\0'分割的,如:
 "bootargs="     CONFIG_BOOTARGS                 "\0"
 "bootcmd="      CONFIG_BOOTCOMMAND              "\0"
 i=nxt+1
会每次将i加到一个环境变量的开始处索引
2)将nxt累加到一个环境变量的'\0'结尾出的索引值。
3)查看此环境变量是否和给定的匹配,匹配则执行(4)返回该变量地址,否则continue

再看回到start_armboot函数。mem_malloc_initmalloc区域清除空间,并设置了mem_malloc_start等变量的值。接着,
 
  1. display_flash_config (flash_init ());
flash_init()
函数在mini2440/flash.c文件中,在这个文件中添加了对SST_VF1601 nor flash的支持。

  1. if defined(CONFIG_CMD_NAND)
  2.          puts ("NAND: ");
  3.          nand_init(); /* go init the NAND */
  4. #endif
nand flash
初始化,这里的nand_init()函数使用的是在driver/mtd/nand中的函数,mini2440.c中的已经被注释掉了.
env_relocate ()
这个函数将重载环境变量,它将flash中的环境变量,载入到分配的内存中等操作。关于uboot环境变量相关部分以后在分析。
在经过一些初始化函数,直接到main_loop

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