Chinaunix首页 | 论坛 | 博客
  • 博客访问: 201691
  • 博文数量: 71
  • 博客积分: 3000
  • 博客等级: 中校
  • 技术积分: 450
  • 用 户 组: 普通用户
  • 注册时间: 2007-11-29 21:28
个人简介

思考人生、专注技术

文章分类

全部博文(71)

文章存档

2015年(1)

2009年(2)

2008年(11)

2007年(57)

我的朋友

分类: C/C++

2007-12-06 09:58:44

vivi是韩国MiZi公司专门为三星ARM芯片开发的bootloader,本文试图分析其C语言部分,在S3C2410上基于NandFlash启动的开发板,即设置其操作模式为00(NandFlash Mode)。
vivi从/arch/s3c2410/head.s开始运行,上电后,通过S3C2410的硬件机制,将NandFlash上前4K代码复制到S3C2410自带的片内RAM(地址范围:0X0000 0000--0X0000 1000,即占据Bank0的地址空间),这里运行的代码主要是将NandFlash中vivi的代码拷贝到RAM中,然后实现跳转:
@ jump to ram
   ldr r1, =on_the_ram
   add pc, r1, #0
   nop
   nop
1: b 1b       @ infinite loop
on_the_ram:
由于vivi.lds中
SECTIONS {
  . = 0x33f00000;
  .text          : { *(.text) }
  .data ALIGN(4) : { *(.data) }
  .bss ALIGN(4)  : { *(.bss)  *(COMMON) }
}
故,on_the_ram应该是相对于0x33f0 0000,直接跳转到RAM空间。准备好堆栈空间后,就跳转到main函数:
@ get read to call C functions
 ldr sp, DW_STACK_START           @ setup stack pointer
 mov fp, #0                       @ no previous frame, so fp=0
 mov a2, #0                       @ set argv to NULL
 bl main                          @ call main
main函数首先调用board_init()函数设置Timer和各引脚控制寄存器;
调用mem_map_init()给宏mmu_table_base指向的一段RAM区域赋值,此段RAM存放的即为MMU_TABLE;
调用mmu_init()设置芯片MMU寄存器,使能mmu功能;
调用heap_init()函数,给静态变量gHeapBase赋值为宏HEAP_BASE,分配RAM中堆空间并初始化,大小为宏HEAP_SIZE;
调用mtd_dev_init()函数,初始化MTD设备,具体在这块板子上表现为:调用smc_init()为mtd_info类型变量mymtd、nand_chip类型变量this分配内存,设置NandFlash controller、I/O等寄存器,设置this中包含的读些函数等,并为flash其分配读些缓冲区。
调用init_priv_data(),将:
vivi_parameter_t default_vivi_parameters[] = {
 { "mach_type",   MACH_TYPE, NULL },
 { "media_type",   MT_S3C2410, NULL },
 { "boot_mem_base",  0x30000000, NULL },
 { "baudrate",   UART_BAUD_RATE, NULL },
 { "xmodem_one_nak",  0,  NULL },
 { "xmodem_initial_timeout", 300000,  NULL },
 { "xmodem_timeout",  1000000, NULL },
 { "ymodem_initial_timeout", 1500000, NULL },
 { "boot_delay",   0x1000,  NULL }
}
char linux_cmd[] = "noinitrd root=31:2 init=/linuxrc console=ttySAC0";
mtd_partition_t default_mtd_partitions[] = {
 {
  name:  "vivi",
  offset:  0,
  size:  0x00020000,
  flag:  0
 }, {
  name:  "param",
  offset:  0x00020000,
  size:  0x00010000,
  flag:  0
 }, {
  name:  "kernel",
  offset:  0x00030000,
  size:  0x000C0000,
  flag:  0
 }, {
  name:  "root",
  offset:  0x00100000,
  size:  0x00140000,
  flag:  MF_BONFS
 }
};
以及个人定义的一些变量从Flash中拷贝到RAM;
调用misc()及init_builtin_cmds()函数给static user_command_t *head_cmd:
typedef struct user_command {
 const char *name;
 void (*cmdfunc)(int argc, const char **);
 struct user_command *next_cmd;
 const char *helpstr;
} user_command_t;
赋值,形成命令链表,以供查询;
最后调用boot_or_vivi();
综上,全局数据涉及:堆栈起始地址及大小、MMU_TABLE占用的RAM区、描述flash的smc_mtd、default_mtd_parameters等等。在shell环境下,vivi的功能就是通过操作这些全局数据实现的。
阅读(1175) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~