|
终于看到一点结果了...
首先很感谢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(178)设到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/08)遇到乱码的情况,查看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的符号终于出现了... |