📄 uclinux
字号:
<TD class=quote>第二步:编译内核
<BR><BR>建立好了开发环境,接下来要做的当然就是根据你的硬件环境编译原程序. <BR>在这里呢就有两种方法
<BR><BR>第一种: 就是直接用dist来作.这种方法比较简单,比较适合初学者和对makefile不
<BR> 熟的同志. <BR>
首先就是进入uClinux-dist目录(在第一步中巳做解释),你可以看到很多目 <BR>
录,比如config;Documentation;freeswan;lib;linux-2.0.x;linux-2.4.x;
<BR>
uClib;user;vendor;romfs;images <BR>
config:这个目录下是一些配置信息,在make config 的时候会用到里面的
<BR>
mkconfig这个文件,比如选择vendor,选择内核版本(2.4还是2.0)
<BR>
就在这个里面做的.然后在根目录下生成config.in文件.
<BR>
Documentation:这里是一些帮助信息 <BR> lib:库文件
<BR>
uClib:也是库文件,不过比lib小,一般嵌入式linux都用它 <BR>
linux-2.0.x:2.0版的内核 <BR>
linux-2..4.x:2.4版的内核 <BR>
user:这里面放一些用户程序 <BR>
romfs:放的是romfs的目录架构,在这里用的文件系统是romfs <BR>
images:这里存放最后的执行印象和romfs印象
<BR> <BR>
好,下面再来看一下怎么样编译 <BR> 一般是遵循以下步骤
<BR> make config <BR>
make dep <BR> make
clean <BR> make
lib_only(可以仅1次,不必要每次都来) <BR> make
user_only(每次修改过您的应用程序之后,这一步后面的都必须重 <BR>
来) <BR> make romfs <BR>
make image <BR> make
<BR> 当你在做make config
的时候注意要选择你芯片的型号比如(SamSung- <BR> 4510)
<BR> 然后以后的工作几乎都是自动完成的了.
<BR><BR>
另外,就是可能你自己需要根据你自己的板子,选择ram的位置,还有linux开始 <BR>
执行的地址, <BR> 这几项内容分别在
<BR>
ram,rom的位置在linux-2.4.x/arch/ARCH/config.in(ARCH表示相应的
<BR>
处理器,比如arm,i386)里面设置,你在linux-2.4.x/arch/ARCH/makefile
<BR> 里面会看到下类下面的句子 <BR>
if [ "$CONFIG_ARCH_SAMSUNG" = "y" ]; then
<BR> define_bool
CONFIG_NO_PGT_CACHE y <BR>
define_bool CONFIG_CPU_32 y <BR>
define_bool CONFIG_CPU_26 n
<BR> define_bool
CONFIG_CPU_ARM710 y <BR>
define_bool CONFIG_CPU_WITH_CACHE y <BR>
define_bool
CONFIG_CPU_WITH_MCR_INSTRUCTION n <BR>
define_bool CONFIG_SERIAL_SAMSUNG y
<BR> define_hex
DRAM_BASE 0x00000000 <BR>
define_hex DRAM_SIZE 0x00800000 <BR>
define_hex FLASH_MEM_BASE 0x01000000
<BR> define_hex
FLASH_SIZE 0x00200000 <BR> fi
<BR>
其中DRAM_BASE,和DRAM_SIZE表示ram的起始地址和大小,你可以做相应 <BR>
的改变. <BR>
然后在linux-2.4.x/arch/ARCH/makefile里面会看到下面的语句 <BR>
TEXTADDR = 0x00008000 <BR>
TEXTADDR就是linux执行的开始位置啦. <BR><BR>
另外可能就是要设置串口的波特率啦,这个设置视不同的芯片而定,不过一般
<BR>
来说修改/linux-2.4.x/driver/char/serial_XXX.c文件,这里不同的芯片,会
<BR> 有不同的serial文件
<BR><BR>第二种方法:直接用原包来做 <BR>
这种方法会比较烦一点,不过会让你对整个过程更加清晰 <BR>
下面是一个网友写的文章我把它贴出来 <BR><BR><BR><BR>s3c44b 0x +
uclinux2.4.19移植过程 <BR><BR>终于看到一点结果了... <BR><BR>首先很感谢tpu,
coldwind等给的帮助. <BR>第一次做这个,很多概念都是在这里得到各位的帮助.
<BR>至今为止还有很多概念问题,没搞清楚,以后多多指教. <BR><BR>附件里是,我参考过的两篇文档.
<BR>但是tpu曾建议不要用dist来做,直接用纯的linux源码包来做,
<BR>我后来也是用linux源码包来做的. <BR>个人也倾向于直接用linux
kernel源码包来做,这样更清晰, <BR>就是Makefile也清楚很多倍.
<BR>而,romfs我是用dist的包来做的.
<BR><BR>下面附带,我移植过程中的一些问题,有点象日志,呵呵
<BR>但愿对后面的初学者有点用吧,(总要回报点给论坛<IMG alt=Smile
src="Guangzhou Linux Consortium 阅读主题 - uclinux的移植三步曲(第二步).files/icon_smile.gif"
border=0>,就怕质量太差) <BR><BR>1. tar xvzf
linux-2.4.19.tar.gz <BR>2. patch uclinux <BR>3. patch
s3c44b0x(from tpu) <BR>4. 修改$topdir/Makefile中使
<BR>arch:=armnommu <BR>CROSS_COMPILE:=arm-elf- <BR>5.
修改$topdir/arch/armnommu/config.in
<BR>============修改=========== <BR>if [
"$CONFIG_ARCH_S3C44B0" = "y" ]; then <BR>define_bool
CONFIG_NO_PGT_CACHE y <BR>define_bool CONFIG_CPU_32 y
<BR>define_bool CONFIG_CPU_26 n <BR>define_bool
CONFIG_CPU_ARM710 y <BR>define_bool
CONFIG_CPU_WITH_CACHE y <BR>define_bool
CONFIG_CPU_WITH_MCR_INSTRUCTION n <BR>define_hex
DRAM_BASE 0x0c000000 <BR>define_hex DRAM_SIZE 0x00800000
要修改dram和flash的大小 <BR>define_hex FLASH_MEM_BASE
0x00000000 <BR>define_hex FLASH_SIZE 0x00200000 <BR>fi
<BR>============ <BR>6.make menuconfig <BR>make dep
<BR>make Image 注意关于Image
zImage的make选项并不在$TOPDIR/Makefile中 <BR><BR>而是这样
<BR>$TOPDIR/Makefile中 include arch/$(ARCH)/Makefile
<BR>而arch/$(ARCH)/Makefile中 <BR>由MAKEBOOT对Image
zImage等进行处理 <BR>MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
LINUX=$(LINUX)
<BR><BR>所以,根本上是在arch/$(ARCH)/boot/Makefile中对make
Image处理的 <BR><BR>7. <BR>ARCH/ARMNOMMU/MAKEFILE <BR>定义了
<BR>PROCESSOR为armv (32位的)。 <BR>定义了 <BR>HEAD :=
arch/armnommu/kernel/head-$(PROCESSOR).o \
<BR>arch/armnommu/kernel/init_task.o
<BR><BR><BR>TEXTADDR 决定KERNEL起始运行地址,即IMAGE应DOWN到的位置
<BR><BR>ARCH/ARMNOMMU/BOOT/MAKEFILE <BR>ZREALADDR
决定KERNEL解压后数据输出的地址,同1 <BR>ZTEXTADDR
带BOOTLOADER的压缩内核文件烧入FLASH的起始地址,即从哪个位置开始执行
<BR>BOOTLOADER,若启动时直接执行,将其设为0,若自带BIOS可以跳到你想要的地址,可改为你要的位置。
<BR><BR>8.image的组成(其中HEAD见7中) <BR>$(LINUX):
include/linux/version.h $(CONFIGURATION) init/main.o
init/version.o init/do_mounts.o linuxsubdirs <BR>$(LD)
$(LINKFLAGS) $(HEAD) init/main.o init/version.o
init/do_mounts.o \ <BR>--start-group \ <BR>$(CORE_FILES)
\ <BR>$(DRIVERS) \ <BR>$(NETWORKS) \ <BR>$(LIBS) \
<BR>--end-group \ <BR>-o $(LINUX)
<BR><BR>9.启动文件/arch/armnommu/kernel/head-armv.S
<BR><BR>ID检查问题。在head-armv.S应加入对MACH_TYPE的设定。在uClinux启动时,首先会检查CPU的ID和平台的TYPE,如果不对会陷入死循环。在TPU的Patch中,加入了对CPU
ID的设定,但没有加入对平台类型的设定。平台类型可能是应该从BootLoader中设好传进来,但对我们自已的BootLoader,没有完成此设定,所以应把MACH_TYPE(178)设到r1寄存器。否则,在系统调用lookup_architecture_type之后就没戏了。修改如下:
<BR>mov r1, #178 ;《==此句为新加的 <BR>mov r0, #F_BIT | I_BIT |
MODE_SVC @ make sure svc mode <BR>msr cpsr_c, r0 @ and
all irqs disabled <BR><BR>10.vectors_base
<BR>在include/asm-armnommu/proc-armv/system.h中定义
<BR>在arch/armnommu/kernel/traps.c fiq.c 和sys_arm.c使用
<BR><BR>fiq.c中 <BR>#define FIQ_VECTOR (vectors_base() +
0x1c) <BR><BR>11.pc行为 <BR>(指令地址4) add pc,pc,0xc000000
<BR>结果会跳转到0xc00000c <BR>为什么不是8呢?
<BR>arm7用的是3级流水线,程序计数器pc必须在当前指令前计数.
<BR>所以指令在第一个周期必须为下一条指令取指pc+=4. <BR>所以在执行周期前,pc+=8了.
<BR>所以add pc,pc,0xc000000 在执行的时候是(4+8+0xc000000).
<BR><BR>12.设计 <BR>bootloader 在flashrom中0x0-0x1000段
<BR>kernel image在flashrom中0x1000-0x1fffff段
<BR>由bootloader把kernel image从rom0x1000中拷到ram0xc000000处
<BR>irq vector 在ram 0xc7fff00 - 0xc7fffff段
<BR>在bootloader中_ISR_STARTADDRESS 指定. <BR>在kernel
中由vectors_base指定. <BR><BR>==修改
<BR>arch/armnommu/Makefile中 <BR>TEXTADDR
决定KERNEL起始运行地址,即IMAGE应DOWN到的位置0xc000000 <BR>==修改
<BR>ARCH/ARMNOMMU/BOOT/MAKEFILE中 <BR>ZREALADDR
决定KERNEL解压后数据输出的地址,同1,0xc000000 <BR>ZTEXTADDR
带BOOTLOADER的压缩内核文件烧入FLASH的起始地址,即从哪个位置开始执行,0xc300000.
<BR>==修改 <BR>include/asm-armnommu//proc-armv/system.h中
<BR>#ifdef CONFIG_ARCH_S3C44B0 <BR>#undef vectors_base()
<BR>#define vectors_base() (0x0c7fff00) <BR>#endif
<BR>13.串口的波特率调整
<BR>串口问题:经常碰到的是串口显示乱码或是没有显示。对于串口无显示,极可以是没有在uClinux核心中配置支持Serial
Port。而显示乱码多半是波特率不对。对于前者如已配置了串口支持还没显示,则可用JTAG跟入到Kernel中的第一个printk中去看看。对于后者,有几种情况。第一种是BootLoader中的波特率设定与uClinux中不一样,这种情况下直接让两者一致就可以了。第二种情况是波特率设的虽一样,但两边的频率设定不一样。在加入TPU的Patch之后,uClinux中默认的时钟为60MHz,如果BootLoader设定的PLL时钟不是60Mhz,就会造成uClinux与BootLoader中的设定不一致而产生乱码。还有一种情况是以上设定都对,但是uClinux在计算时会舍去小数点后的数,使较高的波特率发生偏差。这时应把算法改为四舍五入。最后还有一种情况是uClinux前面的输出很正确,但进行CONSOLE后,就变成乱码了,这也是由于是计算时的误差造成的。
<BR><BR>(data 12/0<IMG alt=Cool
src="Guangzhou Linux Consortium 阅读主题 - uclinux的移植三步曲(第二步).files/icon_cool.gif"
border=0>遇到乱码的情况,查看bootloader中的PLL时钟设置发现
<BR>设成了pin为10Mhz,pout为60Mhz.错误就在这里,pin其实是8m的.
<BR>所以修改bootloader <BR>[ PLLCLK = 60000000 <BR>M_DIV EQU
52 ;Fin=8MHz Fout=60MHz <BR>P_DIV EQU 2 <BR>S_DIV EQU 1
<BR>] <BR>重新烧写bootloader,显示正确! <BR>*^_^*
<BR><BR>14.start_kernel中,无法通过calibrate_delay函数
<BR>简单测试,初步认为与sti()函数的位置无关. <BR><BR>经历了无数次的测试发现,
<BR>好像是这样的. <BR><BR>start_kernel中在calibrate_delay周围,
<BR>如果调用了init_main.c中的__init函数就会停在此函数处. <BR>如果调用了其他.c(如
drivers/serial/s3c44b0.c)中的__init函数,表现正常.
<BR><BR>但是呢,start_kernel中的parse_options也是__init函数如果把它放在前面没错,
<BR>如果放在calibrate周围也会停住.
<BR><BR>calibrate_delay如果放在parse_options周围,没错可以通过.
<BR>calibrate_delay如果放在console_init周围,有错,无法通过.
<BR><BR>查到一点信息 <BR>case: <BR>是8m sdram
0xc000000-0xc800000 <BR>把vector_base置为0xc7fff00
<BR>Image装载到0xc000000处. <BR><BR>problem:
<BR>calibrate_delay的代码段(.init段0xc000200)被覆盖了.
<BR>出现的时机好像不固定,有时在start_kernel的init_IRQ之前有时在之后.
<BR><BR>每次都是 <BR>0xc000100-0xc000200之后的一段空间,
<BR>被vector_IRQ ,vector_data
,vector_prefetch(arch/armnommu/kernel/entry-armv.S中)
他们的代码覆盖. <BR>所以calibrate被调用时就会出错. <BR><BR>答:
<BR><BR>15.修改12部的设计方案 <BR>bootloader
在flashrom中0x0-0x1000段 <BR>kernel
image在flashrom中0x1000-0x1fffff段 <BR>由bootloader把kernel
image从rom0x1000中拷到ram0xc008000处 <BR><BR>irq vector 从ram
0xc000000 开始 <BR>在bootloader中_ISR_STARTADDRESS 指定.
<BR>在kernel 中由vectors_base指定.
<BR><BR>BOOTLOADER=============== <BR>b ResetHandler
;for debug <BR>ldr pc,=0xc000004 ;handlerUndef 0xc000004
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -