关于c:S3C2440移植linux342内核之内核框架介绍及简单修改

31次阅读

共计 3650 个字符,预计需要花费 10 分钟才能阅读完成。

@[TOC]

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 内核之批改分区以及制作根文件系统
咱们将批改分区和制作根文件系统。

如遇到排版错乱的问题,能够通过以下链接拜访我的 CSDN。

**CSDN:[CSDN 搜寻“嵌入式与 Linux 那些事”]

正文完
 0