Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3168186
  • 博文数量: 685
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 5303
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-19 14:17
个人简介

文章分类

全部博文(685)

文章存档

2015年(116)

2014年(569)

分类: LINUX

2014-08-06 14:50:21

原文地址:

一、内核移植步骤 
1,  修改顶层目录下的 Makefile 
ARCH            ?= $(SUBARCH) 
CROSS_COMPILE   ?= $(CONFIG_CROSS_COMPILE:"%"=%) 
修改为: 
  :=arm 

CROSS_COMPILE   :=/usr/local/arm/4.4.3/bin/arm-linux-

2,  修改机器码: 要让bootload的机器码和内核的机器码一致( machine ID ) 

2、1 在u-boot代码(./board/samsung/smdk2416/smdk2416.c)中,赋值machine ID的代码如下:

gd->bd->bi_arch_number = MACH_TYPE;

这个宏的定义在:include/configs/ smdk2416 .h

  1. /*
  2.  * Architecture magic and machine type
  3.  */
  4. # define MACH_TYPE         1685

2、2 在linux内核(./arch/arm/mach-s3c2416/mach-smdk2416.c)中,代码是这样:

MACHINE_START( SMDK2416 , "SMDK2416")
这里SMDK2416就是machine ID的代号,那具体值是多少呢?~
这个宏的定义在arch/arm/include/asm/mach/arch.h
  1. /* 
  2.  * Set of macros to define architecture features. This is built into
  3.  * a table by the linker.
  4.  */
  5. # define MACHINE_START( _type  ,  _name)             /
  6. static const struct machine_desc __mach_desc_# # _type    /
  7.  __used                            /
  8.  __attribute__( ( __section__( ".arch.info.init" ) ) ) = {     /
  9.     
  10. .nr        = MACH_TYPE_##_type ,           /
  11.     
  12. . name        = _name ,
  13. # define MACHINE_END                /
  14. } ;
这个宏定义扩展之后的machine type 就成了 MACHINE_TYPE_SMDK2416。
MACHINE_TYPE_SMDK2416这个宏定义在include/generated/mach-types.h
  
# define MACH_TYPE_SMDK2416  1685
2、3 在arch/arm/tools/mach-types中
smdk2416 MACH_SMDK2416  SMDK2416  1685
原来我们的machine ID是 1685
所以只要这三个数值保持一样即可。。
如果没有uboot源码 ,从打印信息也可以看到参数,修改内核即可。
bootloader传递进来的值是多少呢?~
Error: unrecognized/unsupported machine ID (r1 = 0x00000695).
注意到没有? 0x695转换成10进制也就是1685

3,  拷贝配置文件 
   这里用的是 S3C2416的机子 ,拷贝2410的配置文件到内核的配置文件.config(这里面没有2416的配置文件) 
       cp arch/arm/configs/s3c2410_defconfig   .config 
4,内核配置 

4、1配置内核之前,先修改有些地方的Kconfig吧,以支持我们2416的板子

4、1、1   linux-2.6.35\arch\arm\mach-s3c2416\kconfig 中增加: 
  config MACH_SMDK2416 
        bool "SMDK2416" 
        select CPU_S3C2416 
        select S3C_DEV_FB 
        select S3C_DEV_NAND  #add by ljf 
        select S3C_DEV_USB_HOST  #add by ljf 
        select S3C_DEV_SMDK #add by ljf 
        select S3C_DEV_HSMMC 
        select S3C_DEV_HSMMC1 
        help 
    Say Y here if you are using an SMDK2416 
目的:linux-2.6.35\arch\arm\mach-s3c2416\makefile 文件: 

    obj-$(CONFIG_S3C_DEV_USB_HOST)  += dev-usb.o

 等相应的宏打开

4、1、2  linux-2.6.35\arch\arm\plat-s3c24xx\kconfig中增加:

config MACH_SMDK 
                bool 
                default y #add by ljf 
                help 
              Common machine code for SMDK2410 and SMDK2440 
目的:开linux-2.6.35\arch\arm\plat-s3c24xx\makefile 文件:CONFIG_MACH_SMDK宏打开 
obj-$(CONFIG_MACH_SMDK)       += common-smdk.o     

这个是使针对 makefile  文件宏控制做相应的更改的:

4、2 配置内核 

 Kernel Features  --->   //使用EABI工具链这两项是必须选择的

[*] Use the ARM EABI to compile the kernel

[*]   Allow old ABI binaries to run with this kernel (EXPERIMENTAL) (NEW)

System Type  ---> (选板子)

S3C2410 Machines  ---> 
[*] SMDK2410/A9M2410 (只选择此项) ??? 

S3C2416 Machines  ---> 

[*] SMDK2416

5,编译内核

#make zImage

编译完后,会在 arch/arm/boot 下生成zImage内核镜像文件  
可以修改该目录下的 Makefile:  在第 57 行下面添加:  

@echo ` Kernel: $@ is ready` 

下载到机子看看,内核起来了。到这里只是引导起来了。

6、内核分区,nandflash分区

6、1 修改:arch/arm/plat-s3c24xx/common-smdk.c 文件,在第 110 行: 

/* NAND parititon from 2.4.18-swl5 */ 
static struct mtd_partition smdk_default_nand_part[] = { 
[0] = { 
.name = "2416_Boot", 
.size =    0x00100000, 

.mask_flags 

[1] = { 
.name = "2416_kernel", 
.offset = 0x00100000, 

.mask_flags 

[2] = { 

.name = "2416_kernel", 
.offset = 0x00900000, 

.mask_flags

}, 
[3] = { 
.name = "2416_rootfs", 
.offset = 0x00c00000, 
.size = MTDPART_OFS_APPEND, 

}; 

然后修改NandFlash的读写匹配时间,修改common-smdk.c文件的刚刚修改后的大概140行左右的 
smdk_nand_info结构体,修改内容如下: 
staticstructs3c2410_platform_nandsmdk_nand_info={ 
.tacls =10, 
.twrph0 =25, 
.twrph1 =10, 
.nr_sets =ARRAY_SIZE(smdk_nand_sets), 
.sets =smdk_nand_sets, 

};

6、2 然后修改“drivers/mtd/nand/s3c2410.c”文件的842行的 NAND_ECC_SOFT改为 NAND_ECC_NONE 
将原来的内容改为如下所示 

} else { 
chip->ecc.mode    = NAND_ECC_NONE; //  NAND_ECC_SOFT 

if (set->ecc_layout != NULL) 
chip->ecc.layout = set->ecc_layout; 


6、3 配置内核,支持 NandFlash  
Device Drivers --->  
     <*> Memory Technology Device (MTD) support --->  
           [*]   MTD partitioning support  
           <*> NAND Device Support ---> 

 <*>   NAND Flash support for Samsung S3C SoCs                      

            [ ]     Samsung S3C NAND driver debug                             


6、4 修改arch/arm/mach-2416/s3c2416.c 文件中:(不然nand驱动加载不了,启动信息没打印出nand分区信息) 
               void __init s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no) 

              s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no); 
              s3c_device_nand.name = "s3c2416-nand";这个与下面面的要对应更改为“s3c2440-nand ” 

  
Driver/mtd/nand/s3c2410.c文件中: 
static struct platform_device_id s3c24xx_driver_ids[] = { 
  { 
       .name         = "s3c2410-nand", 
       .driver_data  = TYPE_S3C2410, 
  }, { 
       .name         = "s3c2440-nand", 
       .driver_data  = TYPE_S3C2440, 
  }, { 
       .name         = "s3c2412-nand", 
       .driver_data  = TYPE_S3C2412, 
  }, { 
       .name         = "s3c6400-nand", 
       .driver_data  = TYPE_S3C2412, /* compatible with 2412 */ 
  }, 

  { }

};

6、5启动后若打印信息如下错误

 S3C24XX NAND Driver, (c) 2004 Simtec Electronics 
s3c24xx-nand s3c2440-nand: Tacls=2, 14ns Twrph0=4 29ns, Twrph1=2 14ns 
s3c24xx-nand s3c2440-nand: NAND ECC disabled 
NAND device: Manufacturer ID: 0xec, Chip ID: 0xdc (Samsung NAND 512MiB 3,3V 8-bit) 
NAND_ECC_NONE selected by board driver. This is not recommended !! 
Scanning device for bad blocks 
Bad eraseblock 0 at 0x000000000000 
Bad eraseblock 5 at 0x000001400000 
Creating 3 MTD partitions on "NAND 512MiB 3,3V 8-bit": 
0x000000000000-0x000000900000 : "2416_Boot" 
mtd: partition "2416_Boot" doesn't end on an erase block -- force read-only 
0x000000900000-0x000000c00000 : "2416_kernel" 
mtd: partition "2416_kernel" doesn't start on an erase block boundary -- force read-only 
0x000000c00000-0x000020000000 : "2416_rootfs" 
解决办法,在分区时加上如上的红色部分!!!

7、jffs文件系统 

7.1

具体的打印信息:


 Failed to execute   /linuxrc.  Attempting defaults... 
 Kernel panic - not syncing: No init found.  Try passing init= option to kernel. See Linux Documentation/init.txt for guidance. 
解决办法:

首先是解读表面上的含义,那就是找不到可执行文件 linuxrc 或者说是执行不了 。于是回头去看打印的信息,

VFS: Mounted root (jffs2 filesystem) on device 31:3. 
Freeing init memory: 132K

可以看出文件系统有挂载上去,所以接下来就怀疑可能是文件系统出问题了。回头看文件系统:文件系统制作时用的交叉编译器和内核是一样的,而且在之前的内核2.6.21上面是正常跑起来的,根据这个我认为文件系统是没问题的,就怀疑是内核配置问题。然后在网上查一通,该支持额都配置了。还是不行:然后根据打印信息查找出是哪里打印出来的,在linux2.6.35/init/main.c     826行

/* This is a non __init function. Force it to be noinline otherwise gcc 
 * makes it inline to init() and it becomes part of init.text section 
 */ 
static noinline int init_post(void) 
__releases(kernel_lock) 

/* need to finish all async __init code before freeing the memory */ 
async_synchronize_full(); 
free_initmem(); 
unlock_kernel(); 
mark_rodata_ro(); 
system_state = SYSTEM_RUNNING; 
numa_default_policy(); 

current->signal->flags |= SIGNAL_UNKILLABLE; 

if (ramdisk_execute_command) { 
run_init_process(ramdisk_execute_command); 
printk(KERN_WARNING "Failed to execute %s\n", 
ramdisk_execute_command); 


/* 
* We try each of these until one succeeds. 

* The Bourne shell can be used instead of init if we are 
* trying to recover a really broken machine. 
*/ 
if (execute_command) { 
run_init_process( execute_command ); 
printk( KERN_WARNING "Failed to execute %s.  Attempting " 
); 

run_init_process("/sbin/init"); 
run_init_process("/etc/init"); 
run_init_process("/bin/init"); 
run_init_process("/bin/sh"); 

panic( " No init found.  Try passing init= option to kernel. " 
. "); 

由我们boot的启动参数可以看出 execute_command 值是/linuxrc,run_init_process( execute_command );这个函数如果可以执行那么就不会返回回来也就不会打印红色字体的信息了,这说明“ run_init_process ”这个函数执行有问题:我们来看看这个函数: 

static void run_init_process(char *init_filename) 

argv_init[0] = init_filename; 
kernel_execve(init_filename, argv_init, envp_init); 

再去看函数“ kernel_execve ”:在arch/arm/kernel/sys_arm.c  

int kernel_execve(const char *filename, char *const argv[], char *const envp[]) 

struct pt_regs regs; 
int ret; 
memset(®s, 0, sizeof(struct pt_regs)); 
ret = do_execve((char *)filename, (char __user * __user *)argv, 
(char __user * __user *)envp, ®s); 
if (ret < 0) 
goto out; 

/* 
* Save argc to the register structure for userspace. 
*/ 
regs.ARM_r0 = ret; 

/* 
* We were successful.  We won't be returning to our caller, but 
* instead to user space by manipulating the kernel stack. 
*/ 
asm( "add r0, %0, %1\n\t" 
"mov r1, %2\n\t" 
"mov r2, %3\n\t" 
"bl memmove\n\t" /* copy regs to top of stack */ 
"mov r8, #0\n\t" /* not a syscall */ 
"mov r9, %0\n\t" /* thread structure */ 
"mov sp, r0\n\t" /* reposition stack pointer */ 
"b ret_to_user" 

: "r" (current_thread_info()), 
 "Ir" (THREAD_START_SP - sizeof(regs)), 
 "r" (®s), 
 "Ir" (sizeof(regs)) 
: "r0", "r1", "r2", "r3", "ip", "lr", "memory"); 
 out: 
return ret; 

EXPORT_SYMBOL(kernel_execve); 

问题应该就出在这里头,但是这里有汇编,这下我头大了。不知道有谁能帮我探索一下,感激不尽啊!!!


阅读(980) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~