系统移植知识点及结构大纲

1.pc机的系统启动流程
1.pc机
 [1]BIOS     (硬件初始化,启动方式)
 [2]引导程序 (grub,lilo,...)
 [3]OS       (windows,Linux,Mac os)
 [4]挂载文件系统(NTFS,FAT(16/32),EXT(2,3,4))  
 [5]应用程序

2.嵌入式设备的系统启动流程(exynos4412)
 [1]iROM固化代码(基本硬件初始化,判别启动方式(SD/USB/EMMC),读取存储介质一部分数据到iRAM)
 [2]iRAM代码运行bootloader第一阶段(初始化系统时钟,初始化内存,搬移bootloader到内存)
 [3]内存中运行bootloader第二阶段(初始化基本的硬件设备(串口,EMMC,SD),加载OS到内存)
 [4]内存中运行操作系统(Linux,windows CE,Mac OS)
 [5]挂载文件系统
 [6]运行应用程序

移植前的准备:

交叉开发工具链的配置,我们ubuntu上的gcc编译器编译的程序是在x86环境下运行,不支持arm环境,这里用到arm-none-linux-gnueabi-

在这里我们要到tftp服务与nfs服务 
tftp是一种基于udp的文件传输协议(相较于ftp无客户端验证,代码量较小,ftp是基于tcp协议,面向连接的),我们这里用来传输镜像文件(uImage)和设备树(dtb文件)。
nfs是一种网络文件系统,通过挂载的方式可以实现不同主机共享文件夹,大大节省了资源。这里我们把主机上的文件系统挂载到开发板的根目录下,方便我们调试(主机编译文件,板子运行);

系统移植的步骤:

(1)bootloader的移植与制作
bootloader是一个引导系统启动的程序,它为内核的启动做好准备工作,我们的板子用到的是u-boot,移植过程如下:
一 fs4412 (SOC:samsung,exynos4412) 启动   (u-boot代码在start.S)
1.SOC内部irom代码 (从存储介质拷贝一部分到iRAM)
2.SOC内部iRAM代码 (bootloader第一段代码)
  [1]系统时钟初始化
  [2]内存初始化
  [3]将存储介质中的bootloader (u-boot-2013.01) 搬移到DDR内存中
3.内存中bootloader(u-boot-2013.01)运行
  (1)设置异常向量表
     [1]每个异常的处理过程
  [2]告诉ARM核异常向量表的基地址
  (2)设置ARM核为SVC模式
  (3)初始化cp15的协处理
    [1]让cache无效
  [2]关闭cache和mmu
  (4)_main
     [1]设置sp
   [2]板子的第一阶段初始化(board_init_f)
     (1)获取cpu id
   (2)定时器初始化
   (3)波特率
   (4)串口初始化
   (5)打印u_boot版本信息
   (6)打印cpu信息
   (7)记录内存大小
   (8)预留一部分内存空间,为u_boot重定向做准备

  (5)u_boot重定向 (将u_boot搬移内存的最顶端)
  (6)设置c语言的运行环境
    [1]设置sp
  [2]清bss段
  (7)板子的第二阶段初始化(board_init_r)
  [1]让串口作为标准输入输出设备
     [2]从存储介质中读取u_boot需要的环境变量
   (注意:由于之前没有保存过,第一次读取会失败,此时使用u_boot自带的默认环境变量)
     [3]初始化MMC卡
  [4]初始化网卡
  [5]main_loop
   (1)判断是否设置bootcmd和bootdelay
     [1]如果已经设置,会在到计时的时间中判断用户是否有输入,
        如果没有输入则执行bootcmd中指定的命令
     如果用户有输入,则进入u_boot交互界面(监视用户是否输入了uboot命令,如果输入则执行命令)
    
     [2]如果没有设置,则进入u_boot交互界面

二 uboot移植
(1)修改Makefile指定自己的交叉开发工具链前缀
ifeq (arm,$(ARCH))
 CROSS_COMPILE ?=arm-none-linux-gnueabi-
endif
(2)在boards.cfg文件中选择和自己开发板相近的参考板进行编译
例如(fs4412 <-----> origen):
 make origen
生成u-boot.bin适用于origen ,移植的思想:修改origen的开发板的uboot代码
(3)将u-boot.bin下载到内存中运行
  注意
  下载的地址:编译u_boot的时候指定的代码运行地址(CONFIG_SYS_TEXT_BASE)
(4)运行内存中的u-boot.bin
   go   u_boot所在内存的地址
(5)如果通过go命令启动u-boot 的时候,没有看到任何输出效果?
   [1]u-boot在内存中运行的时候,重新初始化了系统时钟和内存?
   [2]没有初始化串口?
   [3]指定内存基地址不对?
   [4] ? (点灯大法:通过在一些位置加亮灯代码,确定导致u-boot死掉的代码)
   [5]TrustZone代码有问题?
  
   注意:
   在u-boot-2013.01 for fs4412上面,是由于TruszZone的代码有问题,我们只需要将
   board/samsung/origen/lowlevel_init.S
   文件中的bl tzpc_init代码注释掉就可以了
  
三、DM9000网卡移植
1.首先找到网卡驱动,然后网卡驱动代码放到uboot中编译
  通过网卡驱动所在目录的Makefile文件确定,网卡驱动代码进行编译的相关宏开关
  ,然后在include/configs/origen.h中定义相关的宏
 
2.编译的过程中会报错误
  (1)搜索对应未定义的函数和变量,然后查阅别的文件是如何定义的,仿照来做
  (2)DM9000_IO 和DM9000_DATA通过DM9000原理图,看CMD和CS
 
3.添加网卡管脚初始化和控制器初始化代码
 static void dm9000_pre_init(void)
 {
  int i;
  u32 smc_bw_conf, smc_bc_conf;
 
  /* gpio configuration GPY0CON */
  s5p_gpio_cfg_pin(&gpio2->y0, CONFIG_ENV_SROM_BANK, GPIO_FUNC(2));//CS1
  s5p_gpio_cfg_pin(&gpio2->y0,4, GPIO_FUNC(2));//WEn
  s5p_gpio_cfg_pin(&gpio2->y0,5, GPIO_FUNC(2));//OEn
 
  /* gpio configuration GPY1CON */
  s5p_gpio_cfg_pin(&gpio2->y1,0, GPIO_FUNC(2));
  s5p_gpio_cfg_pin(&gpio2->y1,1, GPIO_FUNC(2));
  s5p_gpio_cfg_pin(&gpio2->y1,2, GPIO_FUNC(2));
  s5p_gpio_cfg_pin(&gpio2->y1,3, GPIO_FUNC(2));
  
  /*data and addr bus*/
  for(i = 0;i < 8;i ++){
   s5p_gpio_cfg_pin(&gpio2->y3,i, GPIO_FUNC(2));//
   s5p_gpio_cfg_pin(&gpio2->y4,i, GPIO_FUNC(2));//
   s5p_gpio_cfg_pin(&gpio2->y5,i, GPIO_FUNC(2));//
   s5p_gpio_cfg_pin(&gpio2->y6,i, GPIO_FUNC(2));//
  }
 
  /* Ethernet needs bus width of 16 bits */
  smc_bw_conf = SROMC_DATA16_WIDTH(CONFIG_ENV_SROM_BANK) |  SROMC_BYTE_ADDR_MODE(CONFIG_ENV_SROM_BANK);
  
  smc_bc_conf = SROMC_BC_TACS(0x0F) | SROMC_BC_TCOS(0x0F)
    | SROMC_BC_TACC(0x0F) | SROMC_BC_TCOH(0x0F)
    | SROMC_BC_TAH(0x0F)  | SROMC_BC_TACP(0x0F)
    | SROMC_BC_PMC(0x0F);
 
  /* Select and configure the SROMC bank */
  s5p_config_sromc(CONFIG_ENV_SROM_BANK, smc_bw_conf, smc_bc_conf);
 } 
  
四、通过SD卡烧写uboot到EMMC 
  (1)编译uboot源码得到u-boot.bin
  (2)将u-boot.bin拷贝到mkfs4412目录下
  (3)运行mk.sh生成u-boot-fs4412.bin(这个uboot中包含了三星提供代码)
 
五、从EMMC启动的时候,会发现没有任何效果
  (1)没有给uart设备提供时钟信号,需要在
 board/samsung/origen/lowlevel_init.S 中uart_asm_init中添加如下代码
 ldr r0, =0x10030000 @基地址
 ldr r1, =0x666666   @值
 ldr r2, =0xC250     @偏移量 
 str r1, [r0, r2]
 ldr r1, =0x777777  @值
 ldr r2, =0xC550    @偏移量
 str r1, [r0, r2]
 
  (2)关闭电源功能
  board/samsung/origen/lowlevel_init.S中lowlevel_init中添加
 
  /*PS-Hold high*/
  ldr r0, =0x1002330c
 ldr r1, [r0]
 orr r1, r1, #0x300
 str r1, [r0]
 ldr r0, =0x11000c08
 ldr r1, =0x0
 str r1, [r0]

六、在uboot添加emmc代码



2 内核

1)设置CPU SVC 模式,屏蔽中断

2)检查linux 内核是否支持 CPUID .  lookup_processer_type
3)获取phy&virt offset,为了后面算虚拟地址对应物理地址
4)检查atags参数有效性

5create_page_table完成了3种地址映射的页表空间填写:

6)使能MMUMMU硬件会自动根据页表将虚拟地址转换成物理地址

7)如果有必要则进行data段的拷贝搬移 
8)清空bss 
9)保存处理器ID atag地址等到指定全局变量中,设置SP,跳转到start_kernel(设置sp之后可以用c语言直接编程)

10)初始化系统必须要的好多东西(主要是外设)

11)挂载根文件系统  mount_root

12)运行init进程


(3)文件系统

 利用busybox制作初级的包含基本指令的文件系统,之后其他的目录,库文件都需要自己移植,  之后在etc下面添加fstab    创建init.d目录,并在init.d下创建rcS(脚本文件,需添加可执行权限)文件 profile文件 inittab文件,完成之后,通过nfs挂载即可。


猜你喜欢

转载自blog.csdn.net/mario_z/article/details/53195275