OpenVINOTM,给你看得见的未来!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » [转帖]CFLY文章"uClinux+Coldfire"

共1条 1/1 1 跳转至

[转帖]CFLY文章"uClinux+Coldfire"

菜鸟
2002-07-27 20:44:00    评分
uClinux+Coldfire(2002-5-08) 1. 准备uClinux开发工具和内核源代码 经典的uClinux下载地址:http://www.uclinux.org,但对于某些平台(比如ARM),用GOOGLE搜索一下“uClinux+ARM”往往能找到比uClinux.org更好的网址。不过Coldfire还是推荐用http://www.uclinux.org/ports/coldfire/,上面的版本是一个叫Greg Ungerer, (gerg@snapgear.com)的大牛人搞的,绝对好用,而且源码里绝对不会出现象国内某些uClinux吹牛厂商搞的陷阱之类的恶心东东。 我用的是: l 内核代码: (http://www.uclinux.org/ports/coldfire/source.html上的Full Source Distribution) uClinux-dist-20011112.tar.gz(开发5206e板子时使用) uClinux-dist-20020306.tar.gz(开发yamei大牛人的5307板子时使用) l 交叉编译器: (http://www.uclinux.org/ports/coldfire/source.html上的M68K/ColdFire Binary Tools (m68k-elf tool chain) ) m68k-elf-tools-20020218.tar.gz 内核代码包随便找个目录解压出来就行了,比如在/home/wangyf/下(uClinux-dist-20011112.tar.gz也要在/home/wangyf/下): tar xzf uClinux-dist-20011112.tar.gz 这时应该有了一个/home/wangyf/uClinux-dist/目录,下面就是整个uClinux及应用的目录,后面的make都要在这个目录下进行。 交叉编译器直接解在根目录(/)下就行了:(注意当前目录是/,而且m68k-elf-tools-20020218.tar.gz要在/下) tar xzf m68k-elf-tools-20020218.tar.gz 它会自动在/usr/local/下建立起整套m68k的ELF交叉编译器,要编译自己的简单C程序就可以用/usr/local/bin/m68k-elf-gcc。 2. 配置内核 命令就用make menuconfig(在/home/wangyf/uClinux-dist/目录下)。 首先是选择target,就是你用的芯片和板子,我选的是Cadre-III的板子,因为上面的东东最全,也和我们自己的板子最接近。 然后是选择内核,Gerg的内核包都同时包含了2.0.x和2.4.x两个内核,这两个内核各有好处,2.4.x支持的平台可能多些,但调一些应用会很累(比如ppp);而2.0.x的内核支持的平台可能少些(比如vz328),但调应用问题极少。如果是开发coldfire上的东东,我个人认为用2.0.x的内核就够了,我也是这么干的。 其他的配置就看自己的需要了,有不明白的就看看Documentation/和linux-2.0.x/Documentation/或linux-2.4.x/Documentation/下的文档,最重要的当然还是Configure.help。 配置完以后可以编译一下看看,先make dep一下,再make一下,如果成功,再uClinux-dist下有一个images目录,下面有四个文件: 1. image.elf:ELF格式含调试信息和romfs的uClinux,可以用gdb装载调试运行 2. romfs.img:romfs的二进制文件 3. linux.bin:不含romfs的uclinux二进制文件 4. image.bin:linux.bin和romfs.bin合并而成,并多了4个字节的校验,这个文件的内容拷贝到ram里后就可以直接从入口运行了。对于C3的板子,这个文件需要在RAM里从0x20000地址放起,然后设置PC从0x20000开始运行就OK了。 3. 准备bootloader 我用的这套uClinux需要启动支持,就是俗称的所谓bootloader程序,它的任务是初始化芯片和板子,把uClinux下载到0x20000处,然后从0x20000运行uClinux。 Motorola为自己的Coldfire设计了经典的dBug程序,可以完成bootloader的所有任务,甚至支持从网络上下载uClinux(就是image.bin)。dBug的源代码可以从Motorola的网站上下载,代码写得很通俗易懂,绝对是愿意开发者去看懂它的,不像某些国内的…… 我只需要dBug的初始化过程,所以从中取出了以下文件(以5206e为例): 1. mcf5200.h 2. mcf5206.h 3. mcf5206ec3.h 4. start.S 5. sysinit.c 6. board.c 7. main.c 8. printk.c 建议所有只想让dBug当启动代码用的兄弟就只用这几个文件得了,都是很小的文件,一个小时就可以看明白了,然后针对自己的板子做一些小小的修改。程序流程绝对不需要动,主要是CS、DRAM什么的寄存器的值肯定得按自己板子稍微变一下。 4. 准备调试工具 推荐使用yamei大侠制作的BDM调试工具,辅以GDB,很好用。其实这套东东也是老外搞的啦,他们把软件都放在了网上,还提供了详细的安装说明,gdb-bdm-20010901.tar.gz,上网查查,很多下载的地方。跟着人家的说明一步步做一遍,很容易的。 5. 修改内核代码 现在可以根据自己的板子修改内核了,其实需要改动的地方很少,只要你当初设计板子时尽量和老美的C3什么的板子设计得一样。 1) 存储器: 如果你的存储器地址和大小改了,那么主要应该修改uClinux-dist/linux-2.0.x/arch/m68knommu/platform/5206e/CADRE3/ram.ld(以5206ec3板子为例),里面定义了连接时内核放置的地址,默认是0x20000,改到你需要的地址去吧。 还有uClinux-dist/linux-2.0.x/arch/m68knommu/platform/5206e/CADRE3/crt0_ram.S,里面定义了内存的大小: #define MEM_BASE 0x00000000 /* Memory base at address 0 */ #define MEM_SIZE 0x00400000 /* Memory size 4Mb */ 需要根据你的板子改成需要的基址和大小。 2) 串口: c3板子默认的波特率都是19200,N,8,1,无流控。(不需要改吧?) 3) 网络: 这个东东比较麻烦,后面单独搞一部分(第8节)慢慢扯。 如果都搞好了,而你的板子又没什么BUG,uClinux会从串口0打印出大量的启动代码,那以后的开发也就有了基础了。 uClinux/COLDFIRE(m5206e) COLDFIRE port done by Greg Ungerer, gerg@snapgear.com Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne Calibrating delay loop.. ok - 35.73 BogoMIPS Memory available: 2704k/4096k RAM, 0k/0k ROM (375k kernel code, 142k data) Swansea University Computer Society NET3.035 for Linux 2.0 NET3: Unix domain sockets 0.13 for Linux NET3.035. Swansea University Computer Society TCP/IP for NET3.034 IP Protocols: ICMP, UDP, TCP uClinux version 2.0.39.1 (root@server) (gcc version 2.95.3 20010315 (release)(ColdFire patches - 20010318 fro3 ColdFire internal UART serial driver version 1.00 ttyS0 at 0x10000140 (irq = 73) is a builtin ColdFire UART ttyS1 at 0x10000180 (irq = 74) is a builtin ColdFire UART Ramdisk driver initialized : 16 ramdisks of 4096K size Blkmem copyright 1998,1999 D. Jeff Dionne Blkmem copyright 1998 Kenneth Albanowski Blkmem 7 disk images: 0: A18D0-14A8CF (RO) 1: FFE00000-FFE1FFFF (RW) 2: FFE20000-FFEDFFFF (RW) 3: FFEE0000-FFEEFFFF (RW) 4: FFEF0000-FFEF3FFF (RW) 5: FFEF4000-FFEF7FFF (RW) 6: FFEF8000-FFEFFFFF (RW) PPP: version 2.3.8 (demand dialling) TCP compression code copyright 1989 Regents of the University of California PPP line discipline registered. SLIP: version 0.8.4-NET3.019-NEWTTY (dynamic channels, max=256). VFS: Mounted root (romfs filesystem) readonly. Shell invoked to run file: /etc/rc Command: hostname uClinux-coldfire Command: /bin/expand /etc/ramfs.img /dev/ram0 Command: mount -t proc proc /proc Command: mount -t ext2 /dev/ram0 /var Command: mkdir /var/tmp Command: mkdir /var/log Command: mkdir /var/run Command: mkdir /var/lock Command: ifconfig lo 127.0.0.1 Command: route add -net 127.0.0.0 lo Sash command shell (version 1.1.1) /> 6. 添加用户程序 这个比较简单,在uClinux-dist/user/下,所有的用户程序源代码都在那儿,包括大家熟悉的ping、chat什么的。以添加myapp程序为例 1) 修改uClinux-dist/user/Makefile,在那一大堆dir_$(CONFIG_USER_后面添加: dir_y += myapp 2) 建立uClinux-dist/user/myapp目录,并cd进去 3) 编辑Makefile如下: EXEC = myapp OBJS = myapp.o all: $(EXEC) $(EXEC): $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS) romfs: $(ROMFSINST) /bin/$(EXEC) clean: -rm -f $(EXEC) *.elf *.gdb *.o 4) 编辑myapp.c,随便你想干啥吧,最先可以printf出来一个什么字符串试试。 5) 重新编译uClinux。 这样在你的文件系统ROMFS里就会在bin/下多出一个myapp程序,可以在uClinux里直接运行它。 7. 关于ROMFS 配置uClinux往往需要在文件系统的/etc/目录什么的地方写一些文件,这套uClinux源码包会在make时自动建立整套ROMFS,所以需要在编译uClinux之前把这些配置文件一一写好,并放在正确的地方,然后由make拷贝到romfs里再打包成romfs.bin。 应用程序都在user目录下,而/etc下的文件则在uClinux-dist/vendors/Generic/目录下,对应关系如下: l vendors/Generic/big/rc à romfs/etc/rc l vendors/Generic/big/inittab à romfs/etc/inittab l vendors/Generic/romfs/etc/*.* à romfs/etc/*.* 所以修改配置时应该修改vendors目录下的东东,然后make会自动把它们放到romfs里去的。 8. 以太网卡修改 首先yamei大侠的板子与5307c3都用的是ne2000兼容的网卡芯片,所以控制流程需要更改,只需要把网卡芯片的寄存器访问操作和一些网卡芯片的厂家定义改掉就行了。 修改的文件包括: l uClinux-dist\linux\drivers\net\ne.c l uClinux-dist\linux\include\asm-m68knommu\mcfne.h 具体的修改内容: 1) uClinux-dist\linux\include\asm-m68knommu\mcfne.h #define RSWAP(w) (w >> 8) …… #if defined(CONFIG_M5307) && defined(CONFIG_CADRE3) #define NE2000_ADDR 0xc0000000 #define NE2000_ODDOFFSET 0x00000000 #define NE2000_IRQ_VECTOR 0x1b #define NE2000_BYTE volatile unsigned short #endif …… #define NE2000_PTR(addr) ((addr-NE2000_ADDR)*2 + NE2000_ADDR) …… void ne2000_outb(unsigned int val, unsigned int addr) { volatile unsigned char *rp; unsigned char data; data = val & 0xff; rp = (volatile unsigned char *) NE2000_PTR(addr); *(volatile unsigned char*)rp = data; } int ne2000_inb(unsigned int addr) { volatile unsigned short *rp, val; volatile unsigned char *rp_d, val_d; if(addr == 0xc0000010){ rp_d = (volatile unsigned char*) NE2000_PTR(addr); val_d = *rp_d; return(val_d); } else{ rp = (volatile unsigned short *) NE2000_PTR(addr); val = *rp; return(val>>8); } } void ne2000_insb(unsigned int addr, void *vbuf, int unsigned long len) { volatile unsigned char *rp, val; unsigned char *buf; buf = (unsigned char *) vbuf; for (; (len > 0); len--) { val = ne2000_inb(addr); *buf++ = val; } } void ne2000_insw(unsigned int addr, void *vbuf, unsigned long len) { volatile unsigned short *rp; unsigned short w, *buf; buf = (unsigned short *) vbuf; rp = (volatile unsigned short *) NE2000_DATA_PTR(addr); for (; (len > 0); len--) { w = *rp; *buf++ = BSWAP(w); } } void ne2000_outsb(unsigned int addr, const void *vbuf, unsigned long len) { NE2000_BYTE *rp, val; unsigned char *buf; buf = (unsigned char *) vbuf; rp = (NE2000_BYTE *) NE2000_DATA_PTR(addr); for (; (len > 0); len--) { val = *buf++; ne2000_outb(val, addr); } } void ne2000_outsw(unsigned int addr, const void *vbuf, unsigned long len) { volatile unsigned short *rp; unsigned short w, *buf; buf = (unsigned short *) vbuf; rp = (volatile unsigned short *) NE2000_DATA_PTR(addr); for (; (len > 0); len--) { w = *buf++; ne2000_outb(w/0x100, addr); ne2000_outb(w%0x100, addr); } } 这部分代码是与自己的板子硬件设计密切相关的地方,在这里列出只供参考,ne2000_outsb和ne2000_insb实际上没有用过,如果与其他函数有原理上的冲突也属于正常,因为我已经懒得去改它了。 2) uClinux-dist\linux\include\asm-m68knommu\mcfne.h #define NE1SM_START_PG 0x40 /* First page of TX buffer */ #define NE1SM_STOP_PG 0x80 /* Last page +1 of RX ring */ …… 修改ne_probe(),这个函数是初始化时调用的,比较复杂,建议好好研究研究,我们是把wordlength硬赋成1的(就做了这一个修改) 修改ne_block_input()和ne_block_output(),这两个函数是在网卡有中断时用于从网卡读数或写数的,我做的唯一的改动就是强制成16位读写方式,因为我在mcfne.h里只测试过了16位的连续读写。(注:硬件底层依然是8位读写) 9. 以太网络配置 修改ROMFS的etc/rc,实际是vendors/Generic/big/rc,添加: ifconfig eth0 192.168.0.250 route add –net 192.168.0.0 netmask 255.255.255.0 route add default gw 192.168.0.1 以上命令中的IP地址当然要根据需要修改。注意当你选择手动配置IP时,需要把IP FORWARD等功能删掉,做法就是在make menuconfig时,在network options里只保留TCP/IP networking一项。 这时应该ping什么的都没有问题了,接下来可以加入DNS。首先添加vendors/Generic/romfs/etc/host.conf文件,内容只有一行:(这个文件不见得有用,不过我懒得去删掉试了) order hosts,bind 然后添加vendors/Generic/romfs/etc/nsswitch.conf文件,内容只有一行: hosts: files dns 再添加vendors/Generic/romfs/etc/hosts文件,写入DNS的IP: 202.106.196.115 dnsserver1 202.106.0.20 dnsserver2 这两个IP是电信的DNS。 再添加vendors/Generic/romfs/etc/resolv.conf文件,写入DNS的IP: nameserver 202.106.196.115 nameserver 202.106.0.20 10. PPP+DIALD配置 PPPD可以直接运行拨号的,之所以加上DIALD,是使得uClinux在没有其他网络连接的情况下,一旦有网络连接请求(比如ping命令),DIALD就会自动拨号,然后用PPPD连接到网络上,而等到网络空闲一定时间以后,DIALD又会自动挂断电话,节省拨号费用,实在是好东东。 要使用PPPD+DIALD,必须在make menuconfig的时候在network device support里选中SLIP support和PPP support,在用户程序里选中diald,chat,pppd。 然后就需要写一大堆的配置文件: l etc/diald.defs l etc/config/diald.ttyS1 l etc/config/diald.conf l etc/config/ttyS1 l 还有几个DIALD需要的标准的配置文件,可以直接从uClinux-dist/user/diald/下按说明文档拷出来就行了。 注:为了大家方便,我把最后的romfs放在了网站上,大家可以下载来一看etc下面的东东就明白了。(http://www.cfly.org/doc/romfs-20020309.tgz) 其内容为: diald.defs # Define default protocol rules prule tcp tcp 9:12:13:14:15:16:17:18:19:+0:+1:+2:+3:9:9:9 prule udp udp 9:12:13:14:15:16:17:18:19:+0:+1:+2:+3:9:9:9 prule icmp icmp 9:12:13:14:15:16:17:18:19:9:9:9:9:9:9:9 prule any any 9:12:13:14:15:16:17:18:19:9:9:9:9:9:9:9 # Define the internet packet header fields. var ip.ihl 0(24)&0xf var ip.version 0(28)&0xf var ip.tos 1(24)&0xff var ip.tot_len 2(16)&0xffff var ip.id 4(16)&0xffff var ip.frag_off 6(16)&0x3fff var ip.ttl 8(24)&0xff var ip.protocol 9(24)&0xff var ip.check 10(16)&0xffff var ip.saddr 12 var ip.daddr 16 # Define the TCP packet header fields. var tcp.source +0(16)&0xffff var tcp.dest +2(16)&0xffff var tcp.seq +4 var tcp.ack_seq +8 var tcp.doff +12(28)&0xf var tcp.fin +13(24)&0x1 var tcp.syn +13(25)&0x1 var tcp.rst +13(26)&0x1 var tcp.psh +13(27)&0x1 var tcp.ack +13(28)&0x1 var tcp.urg +13(29)&0x1 var tcp.live +127 # Define the UDP packet header fields. var udp.source +0(16)&0xffff var udp.dest +2(16)&0xffff var udp.len +4(16)&0xffff var udp.check +6(16)&0xffff # Define the ICMP packet header fields. var icmp.type +0(24)&0xff var icmp.code +1(24)&0xff var icmp.checksum +2(16)&0xffff var icmp.echo.id +4(16)&0xffff var icmp.echo.sequence +6(16)&0xffff var icmp.gateway +4 etc/config/diald.ttyS1 modem mode ppp -pidstring speed 19200 device /dev/ttyS1 defaultroute connect '/bin/chat -vf /etc/ppp/chat-isp' disconnect /etc/config/disconnect pppd-options file /etc/config/ttyS1 redial-timeout 1 dynamic local 0.0.0.0 remote 0.0.0.0 netmask 0.0.0.0 debug 31 etc/config/diald.conf ignore tcp tcp.dest=tcp.53 ignore tcp tcp.source=tcp.53 accept tcp 900 ip.tot_len=40,tcp.syn ignore tcp ip.tot_len=40,tcp.live accept tcp 900 tcp.dest=tcp.80 accept tcp 900 tcp.source=tcp.80 keepup tcp 900 !tcp.live ignore tcp !tcp.live accept tcp 900 tcp.dest=tcp.21 accept tcp 900 tcp.source=tcp.21 accept tcp 900 any ignore udp udp.dest=udp.513 ignore udp udp.source=udp.513 ignore udp udp.dest=udp.520 ignore udp udp.source=udp.520 ignore udp udp.dest=udp.123 ignore udp udp.source=udp.123 ignore udp udp.dest=udp.525 ignore udp udp.source=udp.525 ignore udp udp.dest=udp.53,udp.source=udp.53 accept udp 900 udp.dest=udp.53 accept udp 900 udp.source=udp.53 ignore udp udp.source=udp.137,udp.dest=udp.137 accept any 180 any etc/config/ttyS1 lock defaultroute noauth idle 30



关键词: 转帖     文章     uClinux+Coldfire     uC    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]