一、环境搭建

  源码包下载:git clone https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.10.8.tar.gz

  或者直接去kernel.org上面进行下载。

  交叉编译工具链制作:

  这个已经在u-boot移植中已经做过了:http://www.cnblogs.com/kele-dad/p/6910040.html

二、内核启动过程

2.1 Windows 和 Linux 系统的启动区别

  

  由bootloader确定启动哪块单板。

2.2 修改makefile

  下面的行注释掉:

  

  修改ARCH:

  

  修改交叉编译工具链:

  

2.3 选择默认配置

  找到默认配置:

  

  

  进入arm架构中:

  

  可以看到我们的架构中有 mini2440的架构,同时也有s3c2410的配置文件。

  进入内核根目录,配置成2410:

  

  打开.config 文件

  

  查看CPU,可以看到有2440的CPU:

  

  同时也支持 mini2440 的单板:

  

2.4 编译

  执行:make uImage

  进行编译:

  

  编译提示错误,那是因为没有安装u-boot 依赖包。

  

  提示要安装新包

  

  再执行编译:

  

  编译成功。

2.5 烧写

  通过nfs进行烧写,nfs配置如文档:http://www.cnblogs.com/kele-dad/p/7082765.html

  

  启动内核:bootm 32000000

  

  看一下打印信息,有条错误,无法识别机器ID。下面打印出来了很多机器ID。

  现在我们要根据我们的机器ID 去u-boot 源码中看一下启动内核的代码了。

  进入Cmd_bootm.c (common),搜索bootm,找到下面这行代码:

  

  上面代码调用了 do_bootm 函数,进入函数中查看: 

 U_BOOT_CMD
do_bootm
do_bootm_subcommand
do_bootm_subcommand
do_bootm_states
boot_os_fn *boot_fn;
bootm_start
bootm_find_os
bootm_find_other
bootm_load_os
boot_fn = bootm_os_get_boot_func(images->os.os);
do_bootm_states

  在do_bootm_states 中有一个结构体,boot_os_fn:

 static boot_os_fn *boot_os[] = {
[IH_OS_U_BOOT] = do_bootm_standalone,
#ifdef CONFIG_BOOTM_LINUX
[IH_OS_LINUX] = do_bootm_linux,
#endif
#ifdef CONFIG_BOOTM_NETBSD
[IH_OS_NETBSD] = do_bootm_netbsd,
#endif
#ifdef CONFIG_LYNXKDI
[IH_OS_LYNXOS] = do_bootm_lynxkdi,
#endif
#ifdef CONFIG_BOOTM_RTEMS
[IH_OS_RTEMS] = do_bootm_rtems,
#endif
#if defined(CONFIG_BOOTM_OSE)
[IH_OS_OSE] = do_bootm_ose,
#endif
#if defined(CONFIG_BOOTM_PLAN9)
[IH_OS_PLAN9] = do_bootm_plan9,
#endif
#if defined(CONFIG_BOOTM_VXWORKS) && \
(defined(CONFIG_PPC) || defined(CONFIG_ARM))
[IH_OS_VXWORKS] = do_bootm_vxworks,
#endif
#if defined(CONFIG_CMD_ELF)
[IH_OS_QNX] = do_bootm_qnxelf,
#endif
#ifdef CONFIG_INTEGRITY
[IH_OS_INTEGRITY] = do_bootm_integrity,
#endif
#ifdef CONFIG_BOOTM_OPENRTOS
[IH_OS_OPENRTOS] = do_bootm_openrtos,
#endif
};

  在此结构体中调用的是 do_bootm_linux 函数,进入查看 Bootm.c (arch\arm\lib)

 int do_bootm_linux(int flag, int argc, char * const argv[],
bootm_headers_t *images)
{
/* No need for those on ARM */
if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
return -; if (flag & BOOTM_STATE_OS_PREP) {
boot_prep_linux(images);
return ;
} if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
boot_jump_linux(images, flag);
return ;
} boot_prep_linux(images);
boot_jump_linux(images, flag);
return ;
}

  在最后一句中执行 boot_jump_linux 函数:

 /* Subcommand: GO */
static void boot_jump_linux(bootm_headers_t *images, int flag)
{
unsigned long machid = gd->bd->bi_arch_number;
char *s;
void (*kernel_entry)(int zero, int arch, uint params);
unsigned long r2;
int fake = (flag & BOOTM_STATE_OS_FAKE_GO); kernel_entry = (void (*)(int, int, uint))images->ep; s = getenv("machid");
if (s) {
if (strict_strtoul(s, , &machid) < ) {
debug("strict_strtoul failed!\n");
return;
}
printf("Using machid 0x%lx from environment\n", machid);
}
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
announce_and_cleanup(fake); if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
r2 = (unsigned long)images->ft_addr;
else
r2 = gd->bd->bi_boot_params; if (!fake) {
kernel_entry(0, machid, r2);
}
}

  从环境变量中获取mach_id ,然后进入 kernel。如果没有从环境变量获取,就采用默认值,此函数的第一句就是默认值。看看默认值是多少。

  machid = gd->bd->bi_arch_number;

  在Jz2440.c (board\samsung\jz2440) 中 设置了默认ID:

 int board_init(void)
{
/* arch number of JZ2440 board */
gd->bd->bi_arch_number = MACH_TYPE_JZ2440; /* adress of boot parameters */
gd->bd->bi_boot_params = 0x30000100; icache_enable();
dcache_enable(); return ;
}

  同时在Board_f.c (common) 的 setup_machine中也有设置ID:

 static int setup_machine(void)
{
#ifdef CONFIG_MACH_TYPE
gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
#endif
return ;
}

  CONFIG_MACH_TYPE 这个宏我们没有设置。

  那么我们的上一个设置ID的函数是有效的。

  在Mach-types.h (arch\arm\include\asm) 中设置的ID为194。

  

  然后在内核处,进入arch/arm/s3c24x0/ 目录,里面有很多我们的支持s3c24x0的板子,进入smdk2440的单板文件 mach-smdk2440.c:

MACHINE_START(S3C2440, "SMDK2440")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
.atag_offset = 0x100, .init_irq = s3c2440_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.init_time = smdk2440_init_time,
MACHINE_END

  在MACHINE_START中,就是根据mchine ID找到单板文件的。MACHINE_START的定义如下:

  

  展开后, .nr = MACH_TYPE_S3C2440,查找一下这个宏。

  

  generated 是临时生成的文件目录。可以看一下 mach-types.h:

  这是smdk2440的机器码

  

  这是mini2440的机器码

  

  可以对照我们的u-boot打印看出来:

  

  16进制转换成10进制就可以算出来了。

  根据以上的内容,我们可以在u-boot 中设置我们的 mach_id 的环境变量来启动内核,或者我们可以直接修改 u-boot 的默认ID值和这里的机器ID匹配即可。

  修改成mini2440的机器ID。直接修改u-boot源码:

  把mini2440改成如下:

  

  jz2440改成如下:

  

  这两个定义的机器码进行了对调而已。

  在 include/configs/jz2440.h 中设置启动参数,要加上波特率设置,否则会有乱码。mini2440的内核文件中设置的波特率为115200,smdk2440的为16M。

  

  然后编译烧写u-boot。

  进入u-boot 记得 print查看一下环境变量,如果 波特率没有改变过来 就重新设置一下:

  

  保存一下。然后烧入内核

  

  启动内核:

  

  已经有打印信息了。

linux4.10.8 内核移植(一)---环境搭建及适配单板。的更多相关文章

  1. linux4.10.8 内核移植(三)---裁剪内核

    一.裁剪内核 1.1 第一次修改 现在的内核大小为2.8M左右,要裁剪到2.0M以下,毕竟给内核分区就只有2.0M. 这两个设备我们没有,裁剪掉. 进入make menuconfig中,搜索mouse ...

  2. linux4.10.8 内核移植(二)---初步裁剪、分区修改和文件系统

    一.初步裁剪 在内核根目录下 执行: make menuconfig 1.1 system type裁剪 选择 SAMSUNG S3C24XX SoCs Support 进入其中,这里是配置我们的单板 ...

  3. linux4.10.8 内核移植(四)---字符设备驱动_led驱动程序

    一.字符设备驱动程序介绍 app里面用 open.read.write等等函数出来操作底层硬件.驱动程序中也有对应的xxx_open等函数.怎么找到驱动程序中的函数依赖于驱动程序框架. 二.搭建驱动程 ...

  4. 【课程分享】深入浅出嵌入式linux系统移植开发 (环境搭建、uboot的移植、嵌入式内核的配置与编译)

    深入浅出嵌入式linux系统移植开发 (环境搭建.uboot的移植.嵌入式内核的配置与编译) 亲爱的网友,我这里有套课程想和大家分享,假设对这个课程有兴趣的,能够加我的QQ2059055336和我联系 ...

  5. Unix/Linux环境C编程新手教程(12) openSUSECCPP以及Linux内核驱动开发环境搭建

    1. openSUSE是一款优秀的linux. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaXRjYXN0Y3Bw/font/5a6L5L2T/font ...

  6. Unix/Linux环境C编程入门教程(12) openSUSECCPP以及Linux内核驱动开发环境搭建

    1. openSUSE是一款优秀的linux. 2.选择默认虚拟机 3.选择稍后安装操作系统 4.选择linux  opensuse 5. 选择默认虚拟机名称 6.设置处理器为双核. 7.内存设置为2 ...

  7. win10 + VS2010 + OpenCV2.4.10重编译OpenCV开发环境搭建

    win10 + VS2010 + OpenCV2.4.10重编译OpenCV开发环境搭建 重编译的优点:能够调试的时候看OpenCV的源码. 重编译要得到的东西:Debug版本号和Release版本号 ...

  8. Unix/Linux环境C编程入门教程(10) SUSE Linux EnterpriseCCPP开发环境搭建

    安装SUSE企业版以及搭建C/C++开发环境 1.      SUSELinux Enterprise是一款服务器操作系统,异常稳定. 2.设置虚拟机类型. 3.选择稍后安装操作系统. 4.选择SUS ...

  9. 10分钟学会Less开发环境搭建与初体验

    Less 是一门 CSS 预处理语言,它扩充了 CSS 语言,增加了诸如变量.混合(mixin).函数等功能,让 CSS 更易维护.方便制作主题.扩充. 今天看一下,10分钟能不能手把手快速教会你Le ...

随机推荐

  1. PP生产订单成本的计划、控制和结算

    SAP系统成本分析功能关注订单的成本,通过对计划成本和实际成本的比较分析,可以发现成本控制上的问题,以便及时解决问题.1.订单成本计划在基础数据齐全的基础上,系统可以自动滚算生产订单的成本.生产订单计 ...

  2. spring学习总结(一)_Ioc基础(下)

    本篇文章继续上篇文章讲解Ioc基础,这篇文章主要介绍零配置实现ioc,现在相信大家项目中也基本都是没有了xml配置文件.废话不多说.一起学习 代码示例 BookDao.java package com ...

  3. java中父进程与子进程

    http://blog.csdn.NET/seelye/article/details/8269705

  4. git常用命令及用法小计

    git init 初始化一个本地git仓库repository git status 查看状态 git add <file> 将工作区修改加到暂存区(stage) git commit - ...

  5. day26 单继承

    继承是创建新类的一种方式,目的就为了减少代码.表达了子类是父类的关系,比如狗是动物,教授是老师一个类可以多个类继承,所有语言都是这样的一个类可以继承多个父类 ,只有python支持多继承子类可以找到父 ...

  6. servlet表单中get和post方法的区别

    Form中的get和post方法,在数据传输过程中分别对应了HTTP协议中的GET和POST方法.二者主要区别如下: 1.Get是用来从服务器上获得数据,而Post是用来向服务器上传递数据. 2.Ge ...

  7. BUPT2017 wintertraining(15) #2 题解

    这场有点难,QAQ.补了好久(。• ︿•̀。) ,总算能写题解了(つд⊂) A. Beautiful numbers CodeForces - 55D 题意 ​ 求\([l,r](1\le l_i\l ...

  8. PHP 判断浏览器语言

    详情请参看代码 作用:判断当前的浏览器语言.接收传入参数.拼接字符串 <?php $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'],0,2); if ...

  9. 神奇的操作——线段树合并(例题: BZOJ2212)

    什么是线段树合并? 首先你需要动态开点的线段树.(对每个节点维护左儿子.右儿子.存储的数据,然后要修改某儿子所在的区间中的数据的时候再创建该节点.) 考虑这样一个问题: 你现在有两棵权值线段树(大概是 ...

  10. 教你如何开启/关闭ubuntu防火墙

    目录  [隐藏]  1 安装方法 2 使用方法 3 推荐设置 4 详细使用说明 安装方法 sudo apt-get install ufw 当然,这是有图形界面的(比较简陋),在新立得里搜索gufw试 ...