S3C2440启动代码分析详细讲解
- 格式:pdf
- 大小:144.28 KB
- 文档页数:14
S3C2440A中的时钟控制逻辑可以产生必须的时钟信号,包括CPU的FCLK,AHB总线外设的HCLK以及APB总线外设的PCLK。
S3C2440A包含两个锁相环(PLL):一个提供给FCLK、HCLK和PCLK,另一个专用于USB模块(48MHz)。
时钟控制逻辑可以不使用PLL来减慢时钟,并且可以由软件连接或断开各外设模块的时钟,以降低功耗。
S3C2440A的主时钟源由外部时钟(EXTCLK)或者外部晶振(XTIPll)提供,输入时钟源由模式控制引脚OM3和OM2控制选择,在复位信号的上升沿参考OM3和OM2的引脚将OM[3:2]的状态在内部锁定,如图1所示图1 引导启动时的时钟源选择选择不同输入时钟源时连接方式如图2所示:图2 时钟连接参考通过在片内集成的2个锁相环:MPLL和UPLL,可对输入的Fin=12MHz的晶振频率进行倍频。
S3C2440使用了三个倍频因子MDIV、PDIV和SDIV来设置倍频,通过寄存器MPLLCON和UPLLCON可设置倍频因子。
其中MPLLCON寄存器用于设置处理器内核时钟主频FCLK,其输入输出频率间的关系为FCLK=MPLL=(2*m*Fin)/(p*2^s)其中m=(MDIV+8), p=(PDIV+2), s=SDIV。
其中UPLLCON寄存器用于产生48MHz或96MHz,提供USB时钟(UCLK),其输入输出频率间的关系为UCLK=UPLL=(m * Fin) / (p * 2^s)其中m=(MDIV+8), p=(PDIV+2), s=SDIV。
手工计算相对复杂些,我们可以根据欲得到的主频FCLK大小,直接通过查表来获知各倍频因子的设置参数,详见。
S3C2440的数据手册中提供了一个表格来查询各个输出频率和输入频率所对应的MPLL中参数m、p和s 的值,使用的时候最好只使用该表格中推荐的数值。
图3 PLL真值表通过图3的真值表,我们可以得到如果输入时钟为12MHz,输出时钟FCLK为405MHz,可以选择MDIV 为127,PDIV为2,SDIV为1。
Jflash-s3c2410(linux 版本)源码分析最近在远峰公司买了arm9的板子,S3C2410,ARM920T ,没有Nor flash ,Nand Flash 是64M ,SDRAM 是K9f1208,本人对linux 的热情大于windows ,所以想在linux 下做开发,可是远峰公司只给我YFSJF.exe 文件,而且没有源代码,每次在linux 下编译好了后还得切换到windows 下烧录,很是麻烦,于是在网上找了很多Jflash 类似的程序,不过不同的烧录针对不同的硬件平台,Jflash 是跟硬件紧密结合的,比如有的针对Nor Flash ,有的针对Nand Flash 的,不同内核有不同的Jflash ,而且相同的内核也有不同的版本,因为Jtag 的原理图不同,就只能有相对应的Jflash ,程序中的定义要与pc 机并口与Jtag 接口的对应相一致。
在进入源码分析之前要介绍一些预备的知识,有助于理解源代码,毕竟这个程序和硬件联系很紧密的。
首先介绍一下对PC 并口做一些简要的介绍一、PC 标准配备并行口介绍本文主要介绍计算机的标准配备并行端口即25针的母接头端口的应用,在此基础上可以运用相同的原理使用其它模式的并行端口。
并行端口共有25支脚,但不是每支脚均被使用到。
这些脚被区图1分为3种主要的功能,分别是用于数据的传送、检查打印机的状态及控制打印机,其接口如下所示:注:18~脚为GND在PC 机中,标准并行口使用3个8位对这些寄存器,也就是所说的数据、25号的端口寄存器,PC 就是通过状态、控制寄存器的读写访问并口的信号的。
本文中使用一些通用的叫法,8个数据位分别为D0~D7,5个状态位为S3~S7,4个控制为C0~C3。
其中字母表示了端口寄存器,数字则表示该信号在寄存器中的位。
数据寄存器据端口或称数据寄存器(D0~D7)保存了写入数据输出端口的一字节信息。
数据端口可以写入数数据寄存器(即数据输出端口)可擦写、基地址数据,也可以读出数据(即可擦写);写进去的当然是我们希望从数据端口引脚输出的数据,不过读进来的也只是我们上次写进去的数据,或是原来保留在里面的数据,并不是从端口引脚输入PC 的数据。
第二章处理器工作模式2.1概述S3C2440采用了非常先进的ARM920T内核,它是由ARM(Advanced RISC Machines) 公司研制的。
2.2 处理工作状态从程序员的角度上看,ARM920T可以工作在下面两种工作状态下的一种:● ARM 状态:执行32位字对齐的ARM指令● THUMB 状态:执行16位半字对齐的THUMB指令。
在这种状态下,PC 寄存器的第一位来选择一个字中的哪个半字注意;这两种状态的转换不影响处理模式和寄存器的内容。
2.3 切换状态进入THUMB 状态进入THUMB 状态,可以通过执行BX指令,同时将操作数寄存器的状态位(0位)置1来实现。
当从异常(IRQ,FIQ,UNDEF,ABORT,SWI等)返回时,只要进入异常处理前处理器处于THUMB状态,也会自动进入THUMB状态。
进入ARM状态进入ARM状态,可以通过执行BX指令,并且操作数寄存器的状态位(0位)清零来实现。
当处理进入异常(IRQ,FIQ,RESET,UNDEF,ABORT,SWI等)。
这时,PC值保持在异常模式下的link寄存器中,并从异常向量地址处开始执行处理程序。
存储空间的格式ARM920T将存储器空间视为从0开始由字节组成的线性集合,字节0到3中保存了第一个字节,字节4到7中保存第二个字,以此类推,ARM920T对存储的字,可以按照小端或大端的方式对待。
大端格式:在这种格式中,字数据的高字节存储在低地址中,而字数据的低字节则存放2.4 指令长度指令可以是32位长度(在ARM状态下) 或16位长度(在THUMB状态) 。
数据类型ARM920T支持字节(8位),半字(16位) 和字(32位) 数据类型。
字必须按照4字节对齐,半字必须是2字节对齐。
2.5 操作模式ARM920T支持7种操作模式:● 用户模式(user模式),运行应用的普通模式● 快速中断模式(fiq模式),用于支持数据传输或通道处理● 中断模式(irq模式),用于普通中断处理● 超级用户模式(svc模式),操作系统的保护模式● 异常中断模式(abt模式),输入数据后登入或预取异常中断指令● 系统模式(sys模式),使操作系统使用的一个有特权的用户模式● 未定义模式(und模式),执行了未定义指令时进入该模式]外部中断,异常操作或软件控制都可以改变中断模式。
由于片面问题,所以可能会看起来不太美观,可以看附件中的内容。
ARM启动代码相当于我们电脑的BIOS,也就是ARM启动时对处理器的一些初始化及嵌入式系统硬件的一些初始化。
由于它直接面对处理器内核和硬件控制器进行编程,一般都是用汇编语言。
一般包括:中断向量表,初始化存储器系统,初始化堆栈,初始化有特殊要求的断口,设备初始化,变量初始化等。
这几天对着RealView MDK-ARM中自带的启动代码研究了一下,遇到问题又对着数据手册和指令表看了一下,总算对S3C2440A的硬件有了一个大致的了解。
学习嵌入式系统重在系统,学习ARM只是为学习嵌入式系统铺路,懒猫比较笨可能在上系统之前要裸奔几天以强化以下对S3C2440A内部结构的了解。
把MDK自带的S3C2440A.S文件的注释发一下,这些是懒猫结合数据手册与ARM指令表理解了,可能会有错误,放在这里只是引导一下像我一样还没有入门的兄弟们,希望你们不要害怕ARM害怕嵌入式,老毛他老人家说的对,世上无难事,只怕有心人,ARM指令就那么多,看一遍不会就多看几遍,还有一定要学习看软件自带的帮助文件.;/*****************************************************************************/;/* S3C2440.S: Startup file for Samsung S3C440 */;/*****************************************************************************/;/* <<< Use Configuration Wizard in Context Menu >>> */ ;/*****************************************************************************/;/* This file is part of the uVision/ARM development tools. */ ;/* Copyright (c) 2005-2008 Keil Software. All rights reserved. */ ;/* This software may only be used under the terms of a valid, current, */;/* end user licence from KEIL for a compatible version of KEIL softwar e */;/* development tools. Nothing else gives you the right to use this softwa re. */;/*****************************************************************************/;下面这些参数是与CPSR状态寄存器有关;参数的由来:这里各个模式的参数是由寄存器CPSR的模式位设置M[4:0]得来的,;比如这里的用户模式,CPSR的M[4:0]设置为10000就是0x10。
/*希望与各位共同学习,我的QQ是254206940.红色部分为我添加的注释,蓝色把部分为代码自带的注释,紫色部分为我没理解透的地方(主要是我不不明白为什么要那些代码,它们主要起什么作用)。
希望看到我的笔记的同行不吝赐教!linux/drivers/char/watchdog/s3c2410_wdt.c** Copyright (c) 2004 Simtec Electronics* Ben Dooks <ben@>** S3C2410 Watchdog Timer Support** Based on, softdog.c by Alan Cox,* (c) Copyright 1996 Alan Cox <alan@>** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License, or* (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.** Y ou should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307 USA*/#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/types.h>#include <linux/timer.h>#include <linux/miscdevice.h>#include <linux/watchdog.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/platform_device.h>#include <linux/interrupt.h>#include <linux/clk.h>#include <linux/uaccess.h>#include <linux/io.h>#include <mach/map.h>#undef S3C_V A_WA TCHDOG#define S3C_V A_WA TCHDOG (0)#include <asm/plat-s3c/regs-watchdog.h>#define PFX "s3c2410-wdt: "#define CONFIG_S3C2410_WA TCHDOG_A TBOOT(0)#define CONFIG_S3C2410_WA TCHDOG_DEFAULT_TIME (15)static int nowayout = W A TCHDOG_NOW AYOUT;static int tmr_margin = CONFIG_S3C2410_WA TCHDOG_DEFAULT_TIME;static int tmr_atboot = CONFIG_S3C2410_WA TCHDOG_A TBOOT;static int soft_noboot;static int debug;module_param(tmr_margin, int, 0);module_param(tmr_atboot, int, 0);module_param(nowayout, int, 0);module_param(soft_noboot, int, 0);module_param(debug, int, 0);MODULE_PARM_DESC(tmr_margin, "Watchdog tmr_margin in seconds. default="__MODULE_STRING(CONFIG_S3C2410_WA TCHDOG_DEFAULT_TIME) ")"); MODULE_PARM_DESC(tmr_atboot,"Watchdog is started at boot time if set to 1, default="__MODULE_STRING(CONFIG_S3C2410_WA TCHDOG_A TBOOT)); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="__MODULE_STRING(WA TCHDOG_NOW AYOUT) ")");MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)");MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug, (default 0)");typedef enum close_state {CLOSE_STA TE_NOT,CLOSE_STA TE_ALLOW = 0x4021} close_state_t;static unsigned long open_lock;static struct device *wdt_dev; /* platform device attached to */static struct resource *wdt_mem;static struct resource *wdt_irq;static struct clk *wdt_clock;static void __iomem *wdt_base;static unsigned int wdt_count;static close_state_t allow_close;static DEFINE_SPINLOCK(wdt_lock);/* watchdog control routines */#define DBG(msg...) do { \if (debug) \printk(KERN_INFO msg); \} while (0)/* functions */static void s3c2410wdt_keepalive(void)//喂狗,即将计数值赋给WTCNT寄存器{spin_lock(&wdt_lock);writel(wdt_count, wdt_base + S3C2410_WTCNT);spin_unlock(&wdt_lock);}static void __s3c2410wdt_stop(void){unsigned long wtcon;wtcon = readl(wdt_base + S3C2410_WTCON);wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN);writel(wtcon, wdt_base + S3C2410_WTCON);}//将WTCON寄存器的位[5]和位[0]清零,不输出复位信号,停止看门狗static void s3c2410wdt_stop(void)//关看门狗{spin_lock(&wdt_lock);__s3c2410wdt_stop();spin_unlock(&wdt_lock);}static void s3c2410wdt_start(void){unsigned long wtcon;spin_lock(&wdt_lock);__s3c2410wdt_stop(); //关看门狗wtcon = readl(wdt_base + S3C2410_WTCON);wtcon |= S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128;/*#define S3C2410_WTCON_ENABLE (1<<5)#define S3C2410_WTCON_DIV128 (3<<3)开启看门狗,设置分频系数为128(这里并没有将其写入控制寄存器,只是设置值而已)*/if (soft_noboot) {wtcon |= S3C2410_WTCON_INTEN; //#define S3C2410_WTCON_INTEN (1<<2)使能看门狗中断wtcon &= ~S3C2410_WTCON_RSTEN; //#define S3C2410_WTCON_RSTEN (0x01),不输出复位信号} else {wtcon &= ~S3C2410_WTCON_INTEN; //禁止看门狗中断wtcon |= S3C2410_WTCON_RSTEN; //允许输出复位信号}DBG("%s: wdt_count=0x%08x, wtcon=%08lx\n",__func__, wdt_count, wtcon);writel(wdt_count, wdt_base + S3C2410_WTDA T);writel(wdt_count, wdt_base + S3C2410_WTCNT); //写入计数值writel(wtcon, wdt_base + S3C2410_WTCON); //写WTCON寄存器,前面的设置会生效spin_unlock(&wdt_lock);}static int s3c2410wdt_set_heartbeat(int timeout){unsigned int freq = clk_get_rate(wdt_clock);//获得时钟,这里的时钟应该是系统初始化时设置好了的。
S3C2440中断分析中断源未决寄存器(SRCPND)和中断未决寄存器(INTPND)以及外部中断未决寄存器(EINTPEND)分析2013年04月13日飞梦缘整理中断源未决寄存器SRCPND寄存器由32位构成,每一位与一个中断请求信号相关联。
当某个中断源请求中断服务时,SRCPND寄存器中相应位被置为1,即首先在源未决寄存器中做登记,因此该寄存器记录了哪个中断源的请求在等待处理。
注意SRCPND寄存器的每一位由中断源自动设置,而不管中断屏蔽寄存器中对应的位是否被屏蔽,此外,SRCPND寄存器也不受中断控制器的优先级逻辑影响。
当多个中断源提出中断请求后,SRCPND寄存器中相应位均被置为1,然后裁决逻辑基于优先级寄存器来进行处理,选中优先级最高的中断请求,对中断未决寄存器中相应的位设置为1。
注意:INTPND寄存器中只有一位可以被设置为1,如果该中断被屏蔽,SRCPND寄存器中相对应的位被设置为1,但不会导致INTPND寄存器中相应位也被设置为1,SRCPND寄存器是可读可写的,在某个特定中断源的中断服务程序中,SRCPND寄存器的相应位必须被清除,从而保证能收到同一中断源的下一次中断请求,如果从中断服务程序返回时没有清除相应的未决位,中断控制器会误以为该中断源产生了另一个中断请求,换句话说,如果SRCPND寄存器的某位始终设置为1,则被认为始终有一个与该位相对应的中断源,即一个有效的中断请求等待处理,何时进行清除相应的未决位取决于用户需求,如果想在中断服务程序中,再收到相同的中断源提出的另一个有效的中断请求,则应该首先清除相应的未决位,用户可以通过写数据“1”到SRCPND寄存器来清除相应的未决位,数据位为“1”表示该位置的未决位将被清除,而0表示该位置的未决位保持不变。
———————————————————————————————————————————————————前几天把外部中断基本搞好了,但对几个中断寄存器的具体含义和区别不是很了解。
2440 移植2.6.30 (转)解压缩内核压缩文件后进入到目录中,然后修改Makefile,找到ARCH ?=CROSS_COMPILE ?=这两项,不修改这两项的话将会默认使用x86的配置,这里修改为ARCH ?= armCROSS_COMPILE ?= arm-linux-arm-linux- 是交叉编译器~ 这里我使用的交叉编译器为友善送的arm-linux-gcc-4.3.2.tgz,带EABI然后执行make menuconfig,然后进入System Type中看看是否为ARM体系~第一行为ARM system type 说明没错~ 然后在ARM system type中选择SamSung“S3C2410...”随后在下面出现的S3C2440 Machines中选择SMDK2440退出保存~ 执行make zImage出现ERRORdrivers/video/console/vgacon.c:510:error “PCIMEM_BASE undeclared”是在vgacon_startup中,vgacon是啥?~ 不认识~ 应该是不必要的东西~ 去掉它~vim drivers/video/console/Makefile在里面看见了这句obj-$(CONFIG_VGA_CONSOLE) += vgacon.o然后执行find ./ -name “Kconfig” | xargs grep “VGA_CONSOLE”看见config VGA_CONSOLE 在driver/video/console/Kconfig中也就是说在驱动->视频->终端中,执行make menuconfig在Device Drivers->Graphics Support->Console display driver support中发现了VGA text console去掉它,保存设置后再编译编译完成后将在arch/arm/boot中得到zImage文件使用SuperVivi的USB加载功能启动这个内核文件~ 得到下列输出zImage magic = 0x016f2818Setup linux parameters at 0x30000100linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0" MACH_TYPE = 1999NOW, Booting Linux......Uncompressing Linux........................................................................................................ done, booting the kernel.失败信息不够丰富~ 根据kasim大大的指点,在配置中进入Kernel hacking打开Kernel debugging和Kernel low-level debugging functions 还有Kernel low-level debugging messages via S3C UART保存后再编译运行zImage后得下列输出zImage magic = 0x016f2818Setup linux parameters at 0x30000100linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0" MACH_TYPE = 1999NOW, Booting Linux......Uncompressing Linux........................................................................................................ done, booting the kernel.Error: unrecognized/unsupported machine ID (r1 = 0x000007cf).Available machine support:ID (hex) NAME0000016a SMDK2440Please check your kernel config and/or bootloader.失败原来是machine的ID和Supervivi传递进来的ID不匹配~关于machine ID,可以参考一下这篇文章<2.6.18-2内核中对S3C2440的引导启动分析>虽然版本老了点,但是核心思想还是没有变vim arch/arm/mach-s3c2440/mach-smdk2440.c在最后一段有这句MACHINE_START(S3C2440 , ”SMDK2440”)这里S3C2440就是machine ID的代号~ 呢具体值是多少呢?~在arch/arm/tools/mach-types中s3c2440 ARCH_S3C2440 S3C2440 362原来我们的machine ID是362~呢bootloader传递进来的值是多少呢?~Error: unrecognized/unsupported machine ID (r1 = 0x000007cf).注意到没有?~ 0x7CF转换成10进制也就是1999修改mach-types中的对应项s3c2440 ARCH_S3C2440 S3C2440 1999虽然这样就和下面MINI2440的1999冲突了,但是只要不加入MINI2440的配置就没事修改后编译,再执行zImage后得下列输出zImage magic = 0x016f2818Setup linux parameters at 0x30000100linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0" MACH_TYPE = 1999NOW, Booting Linux......Uncompressing Linux........................................................................................................ done, booting the kernel.失败咦?~ 啥都没有?~ 最起码也应该有个乱码吧这时候我的第一反应是会不会没有跳入到start_kernel中所以马上编辑init/main.c,在start_kernel的前部加上printk(KERN_INFO “in start_kernel \n”);但是这个时候内核还没有初始化,所以printk是没有作用的~继续得到kasim大大的指点,编辑kernel/printk.c中的printk函数{va_list args;int r;#ifdef CONFIG_DEBUG_LLextern void printascii(const char *);char buff[256];#endifva_start(args, fmt);r = vprintk(fmt, args);#ifdef CONFIG_DEBUG_LLvsprintf(buff, fmt, args);#endifva_end(args);#ifdef CONFIG_DEBUG_LLprintascii(buff);#endifreturn r;}编译后执行zImage,得下列输出zImage magic = 0x016f2818Setup linux parameters at 0x30000100linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0" MACH_TYPE = 1999NOW, Booting Linux......Uncompressing Linux........................................................................................................ done, booting the kernel.<6>in start_kernel<6>Initializing cgroup subsys cpuset<6>Initializing cgroup subsys cpu<5>Linux version 2.6.30.3 (wolf@ubuntu) (gcc version 4.3.2 (Sourcery G++ Lite2008q3-72) ) #4 Wed Aug 5 16:54:49 CST 2009 ..................................................失败虽然正常输出了~ 有进入start_kernel~ 但是为什么之前每输出呢?~ 会不会是没有找到输出设备在输出中看到这行<5>Kernel command line: noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0 console=ttySAC0 会不会是没有ttySAC0这个设备呢~ 在内核中搜索ttySAC 在driver/serial/samsung.c中得到对应项目这时候我猜想会不会没有加载samsung.c , 经过一轮Makefile和Kconfig的查询, 发现对应选项在Device Drivers->Character devices->Serial drivers中一看,原来根本就没有加载Samsung SoC serial support , 选成静态编译之后又出现了Support for console on Samsung SoC serial port ,就是它了,选上, 退出的时候顺便把Kernel low-level debugging functions给取消了否则我们设置的printk会自行输出,就不知道ttySAC有没有加载成功了编译后执行,得下列输出zImage magic = 0x016f2818Setup linux parameters at 0x30000100linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0" MACH_TYPE = 1999NOW, Booting Linux......Uncompressing Linux......................................................................................................... done, booting the kernel.w# DpñGpGp´ó70ÇC¼ØûÛ»›3ó•ó¸Û0ƒw#DpñGpGp´ó•tØ›•p¸›7¿³ó•\@û7¼¿[£¼Û3•¼ó;£¸ÀÛ;[7û;D°•D@GoGpGpíó•t›7•{ð#ßóÄ;›•770ÄÄ3Çß;GoDh}û7wœ´{…[ó7ûÛ›30°ôܸ‡#_sÄ;›•770ØÄ³œ¼DG@ÁôÛ•ûÄ;•sÄ›£Ø›•D޳ÃÛ70ÄGpÁ4ßœ»ôGã›30³D˜ßF[s˜£ÀÛû70ÛD8ßÄ4G8ôGv£°ÇÃGpÍ´0ƒ†# DpñGš´;óC…[4¸F¸ÄÛtÜàGp}4GGÇ4tD@Ä38ÀGpGß ôØ Û›ŸÄÛD\Cûƒ£¸ƒ;7v›Ã30Ü›4Û´£ô¼;C3[;7ù³û770‡¸°[•4tD@Ä38ÀGpGß ´´p‡ƒ•ô¼Û7ŸtÛG»4œØ…Çpíƒw# .......................................失败但这说明ttySAC加载成功了~ 不过为什么是乱码呢?~这时候就需要对比友善的配置和我们的配置有什么不同了~打开友善送的linux-2.6.29,观察arch/arm/mach-s3c2440/mach-mini2440.c和我们的2.6.30.4下面的arch/arm/mach-s3c2440/mach-smdk2440.c有什么不同由于乱码主要是时钟问题,所以我们重点观察UART的设置和基本设置,其它什么NAND LCD 的就不看先修改smdk2440_uartcfgs[][2] = {.ulcon = 0x03,}修改s3c24xx_init_clocks(12000000);然后编译再运行,输出为zImage magic = 0x016f2818Setup linux parameters at 0x30000100linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0" MACH_TYPE = 1999NOW, Booting Linux......Uncompressing Linux......................................................................................................... done, booting the kernel.[ 0.000000] in start_kernel[ 0.000000] Initializing cgroup subsys cpuset[ 0.000000] Initializing cgroup subsys cpu ...........................最后为Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)失败终于可以正常输出了,但是根文件系统挂载失败因为板子上的根文件系统为yaffs2 这时候内核还没有这个文件系统的支持,需要我们加上去拷贝友善的送的2.6.29下的fs/yaffs2目录到我们的fs目录下然后修改观察一下友善的送的2.6.29下的fs/Kconfig 和fs/Makefile和我们的有什么不同在我们的Kconfig中的source “fs/jffs2/Kconfig” 上面加上source “fs/yaffs2/Kconfig”在Makefile中的obj-$(CONFIG_FAT_FS) += fat/ 上面加上obj-$(CONFIG_YAFFS_FS) += yaffs2/然后在配置的File systems->Miscellaneous filesystems 中选上“YAFFS2 file system support” “Autoselect yaffs2 format” “Cache short names in RAM”然后编译运行,输出如下......................Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)失败还是不行,往上看几行VFS: Cannot open root device "mtdblock2" or unknown-block(0,0)Please append a correct "root=" boot option; here are the available partitions:Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)原来是没有可用的分区这个时候就要更正我们的NAND配置了还是对照友善送的linux-2.6.29,观察arch/arm/plat-s3c24xx/common-friendly-smdk.c来修改我们的arch/arm/plat-s3c24xx/common-smdk.c主要修改smdk_default_nand_part[]{[0] = {.name = “supervivi”,.size = 0x00060000,.offset = 0,},[1] = {.name = “Kernel”,.offset = 0x00060000,.size = 0x00200000,},[2] = {.name = “root”,.offset = 0x00260000,.size = 1024*1024*1024,},[3] = {.name = “nand”,.offset = 0x00000000,.size = 1024*1024*1024,}};编译后运行,输出VFS: Cannot open root device "mtdblock2" or unknown-block(0,0)Please append a correct "root=" boot option; here are the available partitions:Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)失败还是不行,连最起码的分区都没有看见,会不会是MTD没有加载呢?~打开配置进入Device DriversMemory Technology Device ......... 前面是个M~ 说明这个模块是动态加载的,而我们编译的zImage里面只有静态模块将MTD选为静态加载,然后进入MTD配置中看看还有什么需要选的NAND Device Support 这个也是动态,选为静态加载进入NAND Device Support原来连NAND Flash support for S3C2410/S3C2440 SoC都没选,马上选为静态加载保存配置后编译运行,再运行输出如下:NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bit) Scanning device for bad blocksCreating 4 MTD partitions on "NAND 128MiB 3,3V 8-bit":0x000000000000-0x000000060000 : "supervivi"0x000000060000-0x000000260000 : "Kernel"0x000000260000-0x000040260000 : "root"mtd: partition "root" extends beyond the end of device "NAND 128MiB 3,3V 8-bit" -- size truncated to 0x7da00000x000000000000-0x000040000000 : "nand"mtd: partition "nand" extends beyond the end of device "NAND 128MiB 3,3V 8-bit" -- size truncated to 0x8000000 ...............................VFS: Cannot open root device "mtdblock2" or unknown-block(0,0)Please append a correct "root=" boot option; here are the available partitions:Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)失败还是没有可用分区,虽然成功分辨了分区,但是没有加载成功,估计还是在MTD的模块选择上这时候需要对照友善的配置,经过对比,发现在友善的配置中静态编译了MTD中的下面3个模块Direct char device access to MTD devicesCommon interface to block layer for MTD …translation layers‟Caching block device access to MTD devices我们也选为静态编译保存配置后编译运行,输出如下List of all partitions:1f00 384 mtdblock0 (driver?)1f01 2048 mtdblock1 (driver?)1f02 128640 mtdblock2 (driver?)1f03 131072 mtdblock3 (driver?)No filesystem could mount root, tried: cramfsKernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,2)分区加载成功了,但是文件系统却不能识别,我们之前不是已经加入了yaffs2么?~回到配置中再看,原来是动态编译,并没有真正进入到内核之中,选为静态编译~保存配置后编译,输出为yaffs: dev is 32505858 name is "mtdblock2"yaffs: passed flags ""yaffs: Attempting MTD mount on 31.2, "mtdblock2"yaffs: auto selecting yaffs2yaffs_read_super: isCheckpointed 0VFS: Mounted root (yaffs filesystem) on device 31:2.Freeing init memory: 128KKernel panic - not syncing: Attempted to kill init!失败依然错误,这个时候懵了,哪里错呢~ 没办法,只能对照着友善的配置一个个大模块对着来改当改到Kernel Features的时候错误消失了,原来需要选上Use the ARM EABI to compile the kernelAllow old ABI binaries to run with thie Kernel为什么呢?~ Google了一下,原来友善的根文件系统在编译的时候也启用了EABI特性,内核和文件系统需要对上文件系统用了EABI 内核也要用EABI 内核不用EABI 也只能读取不用EABI的文件系统选上这两项之后再编译,运行,输出如下yaffs: dev is 32505858 name is "mtdblock2"yaffs: passed flags ""yaffs: Attempting MTD mount on 31.2, "mtdblock2"yaffs: auto selecting yaffs2yaffs_read_super: isCheckpointed 0VFS: Mounted root (yaffs filesystem) on device 31:2.Freeing init memory: 128Kmount: mounting none on /proc/bus/usb failed: No such file or directoryhwclock: can't open '/dev/misc/rtc': No such file or directory[01/Jan/1970:00:00:13 +0000] boa: server version Boa/0.94.13[01/Jan/1970:00:00:13 +0000] boa: server built Mar 26 2009 at 15:28:42.[01/Jan/1970:00:00:13 +0000] boa: starting server pid=845, port 80open device leds: No such file or directoryTry to bring eth0 interface up......ifconfig: SIOCGIFFLAGS: No such deviceifconfig: SIOCSIFHWADDR: No such deviceifconfig: SIOCSIFADDR: No such deviceroute: SIOCADDRT: No such processDoneifconfig: SIOCSIFADDR: No such devicePlease press Enter to activate this console.[root@FriendlyARM /]#成功了,ls后输出如下bin home lost+found proc sys vardev lib mini2440 root tmp wwwetc linuxrc opt sbin usr不过ifconfig命令没有成功,继续来配置网卡对比友善的mach-mini2440.c文件,发现我们的mach-smdk2440.c中的smdk2440_devices[]数组并没有&s3c_device_dm9k这个结构,加上,追踪发现该数据结构在arch/arm/plat-s3c24xx/devs.c中,我们的devs.c中没有该数据结构的定义,加上#include <linux/dm9000.h>static struct resource s3c_dm9k_resource[] = {[0] = {.start = S3C2410_CS4,.end = S3C2410_CS4 + 3,.flags = IORESOURCE_MEM,},[1] = {.start = S3C2410_CS4 + 4,.end = S3C2410_CS4 + 4 + 3,.flags = IORESOURCE_MEM,},[2] = {.start = IRQ_EINT7,.end = IRQ_EINT7,.flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING,},};static struct dm9000_plat_data s3c_dm9k_platdata = {.flags = DM9000_PLATF_16BITONLY,};struct platform_device s3c_device_dm9k = {.name = “dm9000”,.id = 0;.num_resources = ARRAY_SIZE(s3c_dm9k_resource),.resource = s3c_dm9k_resource,.dev = {.platform_data = &s3c_dm9k_platdata,}};EXPORT_SYMBOL(s3c_device_dm9k);编译,出错,error : s3c_device_dm9k undeclared here找不到结构?~ 打开mach-smdk2440.c看看有什么头文件比较显眼的就是<plat/s3c2410.h><plat/s3c2440.h><plat/devs.h>,我们刚才编辑的文件是devs.c呢么devs.h的可能性较高,通过搜索,这个devs.h在/arch/arm/plat-s3c/include/plat/中,打开,BINGO,里面都是devs.c的数据定义加上我们的s3c_device_dm9kextern struct platform_device s3c_device_dm9k;再编译,通过了,不过这个时候先别急,我们只添加了设备,驱动有没有静态加载呢?~ 打开配置Device Drivers->Networks device support->Ethernet(10 or 100Mbit)DM9000 support没选上,马上选为静态编译保存配置,编译后运行,输出如下Try to bring eth0 interface up......说明DM9000配置成功使用ping命令进行测试,发现丢包率高达78%是不是驱动没设置好呢?~ 比较了一下友善的driver/net/dm9000.c和2.6.30.4的dm9000.c,发现明显不同直接拷贝友善的dm9000.c和dm9000.h过来编译后运行,顺利进入终端,然后运行PING丢包改善,基本无丢包我对这次内核移植的总结是:一步步来~ 先做好终端输出再挂载好根文件系统最后才考虑其它驱动的配置到此移植就基本结束了= 3=)/ 感谢阅读。