|
from feny
http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=embedded&Number=466240&page=0&view=collapsed&sb=5&o=31&fpart=1
终于看到一点结果了...
首先很感谢tpu, coldwind等给的帮助.
第一次做这个,很多概念都是在这里得到各位的帮助.
至今为止还有很多概念问题,没搞清楚,以后多多指教.
附件里是,我参考过的两篇文档.
但是tpu曾建议不要用dist来做,直接用纯的linux源码包来做,
我后来也是用linux源码包来做的.
个人也倾向于直接用linux kernel源码包来做,这样更清晰,
就是Makefile也清楚很多倍.
而,romfs我是用dist的包来做的.
下面附带,我移植过程中的一些问题,有点象日志,呵呵
但愿对后面的初学者有点用吧,(总要回报点给论坛,就怕质量太差)
1. tar xvzf linux-2.4.19.tar.gz
2. patch uclinux
3. patch s3c44b0x(from tpu)
4. 修改$topdir/Makefile中使
arch:=armnommu
CROSS_COMPILE:=arm-elf-
5. 修改$topdir/arch/armnommu/config.in
============修改===========
if [ "$CONFIG_ARCH_S3C44B0" = "y" ]; then
define_bool CONFIG_NO_PGT_CACHE y
define_bool CONFIG_CPU_32 y
define_bool CONFIG_CPU_26 n
define_bool CONFIG_CPU_ARM710 y
define_bool CONFIG_CPU_WITH_CACHE y
define_bool CONFIG_CPU_WITH_MCR_INSTRUCTION n
define_hex DRAM_BASE 0x0c000000
define_hex DRAM_SIZE 0x00800000 要修改dram和flash的大小
define_hex FLASH_MEM_BASE 0x00000000
define_hex FLASH_SIZE 0x00200000
fi
============
6.make menuconfig
make dep
make Image 注意关于Image zImage的make选项并不在$TOPDIR/Makefile中
而是这样
$TOPDIR/Makefile中 include arch/$(ARCH)/Makefile
而arch/$(ARCH)/Makefile中
由MAKEBOOT对Image zImage等进行处理
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot LINUX=$(LINUX)
所以,根本上是在arch/$(ARCH)/boot/Makefile中对make Image处理的
7.
ARCH/ARMNOMMU/MAKEFILE
定义了
PROCESSOR为armv (32位的)。
定义了
HEAD := arch/armnommu/kernel/head-$(PROCESSOR).o \
arch/armnommu/kernel/init_task.o
TEXTADDR 决定KERNEL起始运行地址,即IMAGE应DOWN到的位置
ARCH/ARMNOMMU/BOOT/MAKEFILE
ZREALADDR 决定KERNEL解压后数据输出的地址,同1
ZTEXTADDR 带BOOTLOADER的压缩内核文件烧入FLASH的起始地址,即从哪个位置开始执行
BOOTLOADER,若启动时直接执行,将其设为0,若自带BIOS可以跳到你想要的地址,可改为你要的位置。
8.image的组成(其中HEAD见7中)
$(LINUX): include/linux/version.h $(CONFIGURATION) init/main.o init/version.o init/do_mounts.o linuxsubdirs
$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \
--start-group \
$(CORE_FILES) \
$(DRIVERS) \
$(NETWORKS) \
$(LIBS) \
--end-group \
-o $(LINUX)
9.启动文件/arch/armnommu/kernel/head-armv.S
ID检查问题。在head-armv.S应加入对MACH_TYPE的设定。在uClinux启动时,首先会检查CPU的ID和平台的TYPE,如果不对会陷入死循环。在TPU的Patch中,加入了对CPU ID的设定,但没有加入对平台类型的设定。平台类型可能是应该从BootLoader中设好传进来,但对我们自已的BootLoader,没有完成此设定,所以应把MACH_TYPE(17设到r1寄存器。否则,在系统调用lookup_architecture_type之后就没戏了。修改如下:
mov r1, #178 ;《==此句为新加的
mov r0, #F_BIT | I_BIT | MODE_SVC @ make sure svc mode
msr cpsr_c, r0 @ and all irqs disabled
10.vectors_base
在include/asm-armnommu/proc-armv/system.h中定义
在arch/armnommu/kernel/traps.c fiq.c 和sys_arm.c使用
fiq.c中
#define FIQ_VECTOR (vectors_base() + 0x1c)
11.pc行为
(指令地址4) add pc,pc,0xc000000
结果会跳转到0xc00000c
为什么不是8呢?
arm7用的是3级流水线,程序计数器pc必须在当前指令前计数.
所以指令在第一个周期必须为下一条指令取指pc+=4.
所以在执行周期前,pc+=8了.
所以add pc,pc,0xc000000 在执行的时候是(4+8+0xc000000).
12.设计
bootloader 在flashrom中0x0-0x1000段
kernel image在flashrom中0x1000-0x1fffff段
由bootloader把kernel image从rom0x1000中拷到ram0xc000000处
irq vector 在ram 0xc7fff00 - 0xc7fffff段
在bootloader中_ISR_STARTADDRESS 指定.
在kernel 中由vectors_base指定.
==修改
arch/armnommu/Makefile中
TEXTADDR 决定KERNEL起始运行地址,即IMAGE应DOWN到的位置0xc000000
==修改
ARCH/ARMNOMMU/BOOT/MAKEFILE中
ZREALADDR 决定KERNEL解压后数据输出的地址,同1,0xc000000
ZTEXTADDR 带BOOTLOADER的压缩内核文件烧入FLASH的起始地址,即从哪个位置开始执行,0xc300000.
==修改
include/asm-armnommu//proc-armv/system.h中
#ifdef CONFIG_ARCH_S3C44B0
#undef vectors_base()
#define vectors_base() (0x0c7fff00)
#endif
13.串口的波特率调整
串口问题:经常碰到的是串口显示乱码或是没有显示。对于串口无显示,极可以是没有在uClinux核心中配置支持Serial Port。而显示乱码多半是波特率不对。对于前者如已配置了串口支持还没显示,则可用JTAG跟入到Kernel中的第一个printk中去看看。对于后者,有几种情况。第一种是BootLoader中的波特率设定与uClinux中不一样,这种情况下直接让两者一致就可以了。第二种情况是波特率设的虽一样,但两边的频率设定不一样。在加入TPU的Patch之后,uClinux中默认的时钟为60MHz,如果BootLoader设定的PLL时钟不是60Mhz,就会造成uClinux与BootLoader中的设定不一致而产生乱码。还有一种情况是以上设定都对,但是uClinux在计算时会舍去小数点后的数,使较高的波特率发生偏差。这时应把算法改为四舍五入。最后还有一种情况是uClinux前面的输出很正确,但进行CONSOLE后,就变成乱码了,这也是由于是计算时的误差造成的。
(data 12/0遇到乱码的情况,查看bootloader中的PLL时钟设置发现
设成了pin为10Mhz,pout为60Mhz.错误就在这里,pin其实是8m的.
所以修改bootloader
[ PLLCLK = 60000000
M_DIV EQU 52 ;Fin=8MHz Fout=60MHz
P_DIV EQU 2
S_DIV EQU 1
]
重新烧写bootloader,显示正确!
*^_^*
14.start_kernel中,无法通过calibrate_delay函数
简单测试,初步认为与sti()函数的位置无关.
经历了无数次的测试发现,
好像是这样的.
start_kernel中在calibrate_delay周围,
如果调用了init_main.c中的__init函数就会停在此函数处.
如果调用了其他.c(如 drivers/serial/s3c44b0.c)中的__init函数,表现正常.
但是呢,start_kernel中的parse_options也是__init函数如果把它放在前面没错,
如果放在calibrate周围也会停住.
calibrate_delay如果放在parse_options周围,没错可以通过.
calibrate_delay如果放在console_init周围,有错,无法通过.
查到一点信息
case:
是8m sdram 0xc000000-0xc800000
把vector_base置为0xc7fff00
Image装载到0xc000000处.
problem:
calibrate_delay的代码段(.init段0xc000200)被覆盖了.
出现的时机好像不固定,有时在start_kernel的init_IRQ之前有时在之后.
每次都是
0xc000100-0xc000200之后的一段空间,
被vector_IRQ ,vector_data ,vector_prefetch(arch/armnommu/kernel/entry-armv.S中) 他们的代码覆盖.
所以calibrate被调用时就会出错.
答:
15.修改12部的设计方案
bootloader 在flashrom中0x0-0x1000段
kernel image在flashrom中0x1000-0x1fffff段
由bootloader把kernel image从rom0x1000中拷到ram0xc008000处
irq vector 从ram 0xc000000 开始
在bootloader中_ISR_STARTADDRESS 指定.
在kernel 中由vectors_base指定.
BOOTLOADER===============
b ResetHandler ;for debug
ldr pc,=0xc000004 ;handlerUndef 0xc000004
ldr pc,=0xc000008 ;SWI interrupt handler 0xc000008
ldr pc,=0xc00000c ;handlerPAbort 0xc00000c
ldr pc,=0xc000010 ;handlerDAbort 0xc000010
ldr pc,=0xc000014 ;handlerReserved 0xc000014
ldr pc,=0xc000018 ;irq 0xc000018
ldr pc,=0xc00001c ;fiq 0xc00001c
把内核image拷贝到0xc008000处,再跳到0xc008000处执行
KERNEL==================
==修改
arch/armnommu/Makefile中
TEXTADDR 决定KERNEL起始运行地址,即IMAGE应DOWN到的位置0xc008000
==修改
ARCH/ARMNOMMU/BOOT/MAKEFILE中
ZREALADDR 决定KERNEL解压后数据输出的地址,同1,0xc008000
ZTEXTADDR 带BOOTLOADER的压缩内核文件烧入FLASH的起始地址,即从哪个位置开始执行,0xc300000.
==修改
include/asm-armnommu//proc-armv/system.h中
#ifdef CONFIG_ARCH_S3C44B0
#undef vectors_base()
#define vectors_base() (0x0c000000)
&&&&&&&&&&&&&&&&
&problem 14解决&
&&&&&&&&&&&&&&&&
16
但是,为什么为发生代码段的拷贝, 0x8000的空间分配是怎样的?
答:
先看arch/armnommu/kernel/entry_armv.S中的__trap_init
在vectors_base处(0xc000000) @set up the vectors
把stubs拷贝到vectors_base+0x200处(0xc000200) .
stubs即每种异常(irq,fiq,data,undefined等)的分类处理路线.
这样从0xc000000-0xc000200-到0xc000***,就建立起了完整的中断处理表.
而在这中间0xc000100处有其他信息请参见17.
17.启动时setup_arch中出现Warning: bad configuration page, trying to continue
原因是,parse_params()要获取相关参数信息,
在arch/armnommu/mach-s3c44b0/arch.c中
把arch的params定位在0xc000100处,
这个params是bootloader应该做的工作.!!
18.无法 在blkmem和vfs处停住
现象:
(make menuconfig时选定romfs 和rom disk support)
(修改blkmem_init()加入此二句.
arena[0].length = (unsigned long)(-1);
arena[0].address = (unsigned long)0x0C700000;
在装载内核的时候,要把romfs.img装载到0xc70000处.
)
生成romfs
/*referring to the Makefile of uclinux-disk-20030909*/
genromfs -v -V "ROMdisk" -f $(ROMFSIMG) -d $(ROMFSDIR)
cat $(IMAGEDIR)/linux.text $(IMAGEDIR)/linux.data $(ROMFSIMG) > $(IMAGE)
Blkmem 0 disk images:
device is 0, arenas is 0
arena open of 0 failed!
VFS: Cannot open root device "rom0" or 1f:00
Please append a correct "root=" boot option
Kernel panic: VFS: Unable to mount root fs on 1f:00
问题:
是不是如果我选择把romfs放在ram中就应该support ram disk
如果把romfs放在rom中就应该support rom disk啊.
我把blkmem_init()中加了两句.
arena[0].length = (unsigned long)(-1);
arena[0].address = (unsigned long)0x0C700000;
但是不管选support ram disk还是rom disk都不行,
请问这可能是什么原因?
解决:
发现arenas始终为0. 也就是说config时,选定的flash芯片不符,
所以初始化时arena[]数组大小为0.
所以修改#define arenas 1
然后编译.
现在显示:
Blkmem 1 disk images:
0: C700000-C742BFF [VIRTUAL C700000-C742BFF] (RW)
device is 0, arenas is 1
, address is c700000
VFS: Mounted root (romfs filesystem) readonly.
Freeing init memory: 32K
BusyBox v0.60.4 (2002.11.25-19:05+0000) multi-call binary
Usage: busybox [function] [arguments]...
or: [function] [arguments]...
BusyBox is a multi-call binary that combines many comKernel panic: Attem
pted to kill init!
mon Unix
utilities into a single executable. Most people will create a
link to busybox for each function they wish to use, and BusyBox
will act like whatever it was invoked as.
Currently defined functions:
[, busybox, cat, chmod, clear, cp, date, dd, df, dmesg, du, echo,
env, false, free, hostname, insmod, kill, killall, ln, ls, lsmod,
mkdir, mknod, modprobe, mount, msh, mv, ps, pwd, rm, rmdir, rmmod,
sh, sleep, syslogd, test, touch, true, umount, uname
19.
>>make menuconfig(这里选用0522dist,只用它来编译romfs)
在user application 配置选上
init ;console shell;login;sash(如果用bash无法编译通过);busybox等
>>make dep;
>>make lib_only;
>>make user_only;
>>make romfs;
>>genromfs -v -V "ROMdisk" -f [ROMFSIMAGE] -d [ROMFSDIR]
现在执行完
/etc/rc就出现"Execution finished!. exiting..."
修改/etc/rc,
最后加一句
sh
让sash跑起来
出现
____ _ _
/ __| ||_|
_ _| | | | _ ____ _ _ _ _
| | | | | | || | _ \| | | |\ \/ /
| |_| | |__| || | | | | |_| |/ \
| ___\____|_||_|_| |_|\____|\_/\_/
| |
|_|
For further information check:
http://www.uclinux.org/
Command: sh
Sash command shell (version 1.1.1)
name is (null).
/> Reading command line: Bad file descriptor
pid 10: failed 256
Execution Finished, Exiting
init: Booting to single user mode
Sash command shell (version 1.1.1)
name is (null).
/>
还有一个问题,
我现在是这样调试的
0x0-0x1000放bootloader代码,
调试的时候把kernel load到0xc008000
把romfs load到0xc700000.
然后pc设置为0,开始执行.
但是现在每次中断后,重新置为pc = 0.
重新执行就oops了.
shell的符号终于出现了... |
|