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]应用程序
[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]运行应用程序
[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内存中
2.SOC内部iRAM代码 (bootloader第一段代码)
[1]系统时钟初始化
[2]内存初始化
[3]将存储介质中的bootloader (u-boot-2013.01) 搬移到DDR内存中
3.内存中bootloader(u-boot-2013.01)运行
(1)设置异常向量表
[1]每个异常的处理过程
[2]告诉ARM核异常向量表的基地址
[1]每个异常的处理过程
[2]告诉ARM核异常向量表的基地址
(2)设置ARM核为SVC模式
(3)初始化cp15的协处理
[1]让cache无效
[2]关闭cache和mmu
[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重定向做准备
[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段
[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交互界面
[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
CROSS_COMPILE ?=arm-none-linux-gnueabi-
endif
(2)在boards.cfg文件中选择和自己开发板相近的参考板进行编译
例如(fs4412 <-----> origen):
make origen
make origen
生成u-boot.bin适用于origen ,移植的思想:修改origen的开发板的uboot代码
(3)将u-boot.bin下载到内存中运行
注意
下载的地址:编译u_boot的时候指定的代码运行地址(CONFIG_SYS_TEXT_BASE)
注意
下载的地址:编译u_boot的时候指定的代码运行地址(CONFIG_SYS_TEXT_BASE)
(4)运行内存中的u-boot.bin
go u_boot所在内存的地址
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]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
通过网卡驱动所在目录的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]
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]
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参数有效性
(5)create_page_table完成了3种地址映射的页表空间填写:
(6)使能MMU,MMU硬件会自动根据页表将虚拟地址转换成物理地址
(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挂载即可。