uboot启动内核分析

  进入cmd_bootm.c,找到对应的bootm命令对应的do_bootm():

int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
boot_os_fn *boot_fn; //boot_fn是个数组函数
... .. boot_fn(0, argc, argv, &images); //调用数组函数
... ...
}

  boot_os_fn是个typedef型,如下图所示:



  由于定义了宏CONFIG_BOOTM_LINUX,最终会跳转到do_bootm ->do_bootm_linux()

  代码如下所示:

int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
{
/* No need for those on ARM */
if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
return -1;
if (flag & BOOTM_STATE_OS_PREP) {
boot_prep_linux(images);
return 0;
}
if (flag & BOOTM_STATE_OS_GO) {
boot_jump_linux(images);
return 0;
} boot_prep_linux(images); //该函数会将各个tag参数保存在指定位置,比如:内存tag、bootargs环境变量tag、串口tag等
boot_jump_linux(images); //该函数会跳转到内核起始地址
return 0;
}

  最终跳转到do_bootm ->do_bootm_linux-> boot_jump_linux()

static void boot_jump_linux(bootm_headers_t *images)
{
unsigned long machid = gd->bd->bi_arch_number; //获取机器ID
char *s;
void (*kernel_entry)(int zero, int arch, uint params);
unsigned long r2;
kernel_entry = (void (*)(int, int, uint))images->ep; //设置kernel_entry()的地址为0x30000000
s = getenv("machid"); //判断环境变量machid是否设置,若设置则使用环境变量里的值
if (s) {
strict_strtoul(s, 16, &machid); //重新获取机器ID
printf("Using machid 0x%lx from environment\n", machid); //使用环境变量的machid
}
     ... ...
r2 = gd->bd->bi_boot_params; //获取tag参数地址, gd->bd->bi_boot_params在setup_start_tag()函数里被设置
kernel_entry(0, machid, r2); //跳转到0x30000000,r0=0,r1=机器ID,r2=tag参数地址
}

   上面的machid默认值为MACH_TYPE_SMDK2410(也就是193),我们也可以在环境变量里设置machid变量

最终,便跳到内核执行代码,步骤如下所示:

  1)根据R1(机器ID),来判断内核是否支持该机器,若支持则初始化机器相关函数

  2)解析TAG参数,初始化串口,设置内存等

  3)挂载根文件系统,并执行应用程序

简单配置内核

  修改Makefile,修改配置

tar xjf linux-3.4.2.tar.bz2
cd linux-3.4.2/
vi Makefile



  改为

ARCH            ?= arm
CROSS_COMPILE ?= arm-linux-

  配置编译

cd arch/arm/configs                //由于我们板子是arm板,进入该目录
ls *2440* //找到有mini2440_defconfig、
ls *2410* //找到有s3c2410_defconfig cd ../../..
make s3c2410_defconfig //配置2410, 更新.config配置文件
make uImage //编译,生成uImage
cp arch/arm/boot/uImage /work/nfs_root/ //拷贝
cd /work/nfs_root/
mv uImage uImage_new



  进入.config查看支持的CPU

vi .config



  如上图所示,有我们的2440

编译内核

make uImage

  报错如下

Can't use 'defined(@array)'(Maybe you should just omit the defined? )at kernel/timeconst pl line 373
/root/working/Hi3520D SDK V2.0.3.0/osdrv/kernel/linux-30y/kernel/Makefile:140
recipe for target kernel/timeconst h failed make【1】:*** 【kernel/timeconst h】 Error 255
Makefile:945:recipe for target kernel ' failed
【kernel】 Error 2

解决办法

  将 kernel/timeconst.pl中第373行的 defined0去掉只留下@val就可以了

vim kernel/timeconst.pl +373

  进入uboot烧写

nfs 32000000 192.168.2.106:/work/nfs_root/uImage_new
bootm 32000000

  如下图所示,发现串口输出乱码:

设置机器ID

  uboot传递进来的机器ID可以通过环境变量machid来设置

  所以任意设置一个ID,这样再次启动内核时,内核识别不出来,就会打印出所有设备对应的机器ID。下面开始测试机器ID是否正确,进入uboot,输入:

set machid 33333
tftp 32000000 uImage
bootm 32000000

  如下图所示,由于内核不支持这个机器ID,所以打印出内核能支持的ID表:



  ID所对应的文件为arch/arm/mach-s3c24xx/Mach-smdk2440.c



  MACHINE_START为一个结构体,根据不同的机器ID找到对应的MACHINE_START,调用初始化函数。

  由于我们板子是2440,所以测试7cf(mini2440)以及16a(smdk2440)这两个机器ID,是否支持我们开发板。

  但是依旧乱码,可能是波特率设置不正确。重新设置下环境变量的波特率

set bootargs root=/dev/mtdblock3 console=ttySAC0,115200

  再次烧写启动,发现7cf(mini2440)这个ID,有串口输出正常。下面看下16a(smdk2440)为什么串口乱码,进入mach-smdk2440.c( 位arch/arm/mach-s3c24xx)找到问题出在smdk2440_map_io():

static void __init smdk2440_map_io(void)
{
s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
s3c24xx_init_clocks(16934400); //初始化时钟clock
s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
}

修改晶振

  由于我们板子上的晶振是12Mhz,而mdk2440_map_io()里,初始化的时钟是基于16934400hz的晶振。所以将:

s3c24xx_init_clocks(16934400);             //初始化时钟clock

  改为:

s3c24xx_init_clocks(12000000);             //初始化时钟clock

  然后重新编译uImage:

make  s3c2410_defconfig             //将mach-s3c2440.c配置进内核
make uImage
cp uImage /work/nfs_root/ uImage_new

  进入uboot,输入:

set machid 16a
nfs 32000000 192.168.1.30:/work/nfs_root/uImage_new
bootm 32000000

  启动内核打印正常。



  下一节S3C2440移植linux3.4.2内核之修改分区以及制作根文件系统

我们将修改分区和制作根文件系统。

有任何问题,均可通过公告中的二维码联系我

S3C2440移植linux3.4.2内核之内核框架介绍及简单修改的更多相关文章

  1. 移植Linux-3.4.2内核到S3C2440

    一.BootLoader引导内核过程     1.Bootloader的工作     1.1.将内核读入内存     2.2.保存内核启动参数到指定位置,内核启动时去这个位置解析参数     3.3. ...

  2. 1.移植3.4内核-分析内核启动过程,重新分区,烧写jffs2文件系统

    1.在上章-移植uboot里.我们来分析下uboot是如何进入到内核的 首先,uboot启动内核是通过bootcmd命令行实现的,在我们之前移植的bootcmd命令行如下所示: bootcmd=nan ...

  3. 浏览器内核与BOM对象介绍

    BOM(Browser Object Model)对象介绍 我们都知道js有三部分组成,ECMAScript.DOM和BOM,根据宿主(浏览器)的不同,具体的表现形式也不尽相同,ie和其它浏览器也是风 ...

  4. 在阿里云中编译Linux4.5.0内核 - Ubuntu内核编译教程

    实验环境:Ubnuntu 64位(推荐使用14.04)+Xshell 阿里云现在提供的云服务器很好用的,用来编译内核性能也不错.本文介绍最基本的内核编译方法,为了方便,所有操作均在root用户下进行. ...

  5. 戴文的Linux内核专题:01介绍

    转自Linux中国 译者按:本文作者戴文.科利尔.约翰逊(Devyn Collier Johnson)今年才19岁,但是他在Linux内核.人工智能.编程语言方面拥有丰富的经验,本文是其在linux. ...

  6. 【转】.NET多种WebKit内核/Blink内核浏览器初步测评报告

    第1篇:.NET多种WebKit内核/Blink内核浏览器初步测评报告 本文转自“吾乐吧软件站”,原文链接:http://www.wuleba.com/?p=23590 报告研究时间:2013-10- ...

  7. Linux 内核开发—内核简单介绍

    内核简单介绍 Linux 构成 Linux 为什么被划分为系统空间和内核空间 隔离核心程序和应用程序,实现对核心程序和数据的保护. 什么内核空间,用户空间 内核空间和用户空间是程序执行的两种不同的状态 ...

  8. Linux设备驱动开发详解-Note(5)---Linux 内核及内核编程(1)

    Linux 内核及内核编程(1) 成于坚持,败于止步 Linux 2.6 内核的特点 Linux 2.6 相对于 Linux 2.4 有相当大的改进,主要体现在如下几个方面. 1.新的调度器 2.6 ...

  9. Linux 内核开发 - 内核定时器

    时间差的度量 系统的定时器硬件以固定的频率产生时钟中断,产生始终中断的间隔以HZ 常量来决定,通常在50~1200之间,x86默认是1000.HZ能够依据不同的内核来配置. Linux 採用jiffi ...

  10. Linux内核(5) - 内核学习的相关资源

    “世界上最缺的不是金钱,而是资源.”当我在一份报纸上看到这句大大标题时,我的第一反应是——作者一定是个自然环保主义者,然后我在羞愧得反省自身的同时油然生出一股对这样的无产主义理想者无比崇敬的情绪来. ...

随机推荐

  1. c++学习,和友元函数

    第一友元函数访问私有元素时不会显示,但是是可以调用的(我使用的是gcc10.3版本的)友元函数可以访问任何元素.就是语法你别写错了. 继承如果父类已经写了构造函数,子类一定要赋值给构造函数,要么父类就 ...

  2. C++学习笔记八:极限和数学运算<limits><cmath>

    1) <limits>库: 1.1 源文档: https://en.cppreference.com/w/cpp/types/numeric_limits #include <lim ...

  3. Head First Java学习:第九章-构造器和垃圾收集器

    对象的前世今生 对象如何创建.存在何处以及如何让保存和抛弃更有效率. 会述及堆.栈.范围.构造器.超级构造器.空引用等. 1.内存的两个区域:堆和栈 堆(heap):对象的生存空间,又称为可垃圾回收的 ...

  4. 可视化学习:CSS transform与仿射变换

    引言 在几年前,我就在一些博客中看到关于CSS中transform的分析,讲到它与线性代数中矩阵的关系,但当时由于使用transform比较少,再加上我毕竟是个数学学渣,对数学有点畏难心理,就有点看不 ...

  5. 有了Excel和PPT,为什么我们还需要数据可视化工具?

    在当今信息时代,数据扮演着越来越重要的角色,而数据的可视化呈现正是一种强大的工具,能够帮助我们更好地理解和利用这些数据.虽然Excel和PPT在处理数据方面有着不可否认的作用,但在处理大规模.复杂数据 ...

  6. grpc是基于http/2协议的高性能的rpc框架

    师傅领进门,修行在个人,跟着官方脚手架demo了grpc后,之后就需要扩展前后知识边界,下面总结grpc的前世今生和最佳实践. https://www.cnblogs.com/JulianHuang/ ...

  7. Meta3D -- 开源的Web3D低代码平台

    大家好,Meta3D是开源的Web3D低代码平台,快速搭建Web3D编辑器,共建开放互助的web3d生态 Github 进入平台 功能演示 加入UI Control 加入Action脚本 运行&quo ...

  8. mybatis空格字符替换

    mybatis空格字符替换 <select id="user" resultType="java.util.Map" parameterType=&quo ...

  9. cookie和session的一些疑惑以及ai解答

    我: 那么当浏览器关闭的时候,当再次访问这个地址的时候,为什么之前设置的cookie没有被删除掉?而且按照你说的这次可能会生成一个新的sessionID,那么cookie里面的其他数据,它是如何获取上 ...

  10. 教你如何基于MindSpore进行ChatGLM微调

    本文分享自华为云社区<基于MindSpore的ChatGLM微调>,作者: JeffDing . 基于MindSpore的ChatGLM微调 克隆Hugging Face模型 克隆chat ...