转载自:https://blog.csdn.net/charistain_huang/article/details/5791739
参考:https://blog.csdn.net/a1010256340/article/details/83088870
该文章因为实在没法看,也没个分行。所以为了便于学习理解,将该文章通过自己的理解重新翻译下。红色部分为了强调突出便于观看。是搞Linux系统需要记得一些命令和理解。
以下是将能在sdram中运行的linux内核和文件系统烧写到flash中的方法!
从内部rom启动后,加载loader.bin和uboot.bin(重新编译的)
发送boot.bin :在提示符下我们输入如下命令
Uboot> loadb 20000000
将boot.bin上传到0x20000000的sdram地址。
Uboot> cp.b 20000000 10000000 ffff
将boot.bin烧写到0x10000000的flash地址。
发送u-boot.bin.gz:在提示符下我们输入如下命令
Uboot> loadb 20000000
将u-boot.bin.gz上传到0x20000000的sdram地址。
Uboot> cp.b 20000000 10020000 ffff
将u-boot.bin.gz烧写到0x10020000的flash地址。
(说明:这里需要将boot的原始码中的0x10010000修改为0x10020000,再重新编译生成boot.bin!)
登陆linux服务器后:
[tank@redhat9 tank]$ cd AT91RM9200-U-Boot/
[tank@redhat9 AT91RM9200-U-Boot]$ ls (列出了该文件夹下所有的文件)
arm_config.mk drivers MAINTAINERS tmp uboot.PFI board dtt MAKEALL tools uboot.PO CHANGELOG examples Makefile u-boot uboot.PR common fs mips_config.mk u-boot1.gz uboot.PRI config.mk i386_config.mk mkconfig u-boot.bin uboot.PS COPYING include net u-boot.bin.gz uboot.SearchResults cpu lib_arm post uboot.IAB u-boot.srec CREDITS lib_generic ppc_config.mk uboot.IAD uboot.WK3 CVS lib_i386 README uboot.IMB disk lib_mips rtc uboot.IMD doc lib_ppc System.map u-boot.map
[tank@redhat9 AT91RM9200-U-Boot]$ cd tools
[tank@redhat9 tools]$ ls
bddb CVS environment.c img2srec Makefile.win32 updater bmp_logo easylogo environment.o img2srec.c mkimage zImage bmp_logo.c env gdb img2srec.o mkimage.c tdramdisk.gz bmp_logo.o envcrc gen_eth_addr inca-swap-bytes.c mkimage.o crc32.c envcrc.c gen_eth_addr.c logos scripts crc32.o envcrc.o gen_eth_addr.o Makefile uImage
把内核镜象文件zImage(能在sdram中运行的)(查找什么是内核镜像。出来了内核映像的概念,以下是内核映像的说法。
Linux内核在PC上以文件的形式存在(保存成磁盘文件形式),就是所谓的“映像文件”。Linux内核映像文件最终是要烧录到目标板的flash中。
Linux 内核映像文件有两种:一种是非压缩版本,叫Image;另一种是它的压缩版本,叫zImage。zImage是Image经过压缩形成的,所以它的大小比Image小。为了能使用zImage这个压缩版本,必须在它的开头加上解压缩的代码,将zImage 解压缩之后才能执行,因此它的执行速度比Image要慢。但考虑到嵌入式系统的存储空容量一般都比较小,内核要常驻内存,采用zImage可以占用较少的存储空间,因此牺牲一点性能上的代价也是值得的,所以一般嵌入式系统均采用压缩的内核映像文件,即zImage。
zImage是ARM Linux常用的一种压缩映像文件,uImage是U-boot专用的映像文件,它是在zImage之前加上一个长度为0x40的“头”,说明这个映像文件的类型、加载位置、生成时间、大小等信息。换句话说,如果直接从uImage的0x40位置开始执行,zImage和uImage没有任何区别。另外,Linux2.4内核不支持uImage,Linux2.6内核加入了很多对嵌入式系统的支持,但是uImage的生成也需要设置。)拷贝到这个tools目录下后,再执行如下命令(注意参数大小写):
[tank@redhat9 tools]$ ./mkimage -A arm -O linux -T kernel -C none -a 0x20008000 -e 0x20008000 -n "linux2.4.19-rmk7" -d zImage uImage
提示信息: Image Name: linux2.4.19-rmk7 Created: Fri Jun 17 13:41:08 2005 Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 523504 Bytes = 511.23 kB = 0.50 MB Load Address: 0x20008000 Entry Point: 0x20008000
把根文件系统tdramdisk.gz(能在sdram中运行的)拷贝到这个tools目录下后,再执行如下命令(注意参数大小写): [tank@redhat9 tools]$ ./mkimage -A arm -O linux -T RAMDisk -C gzip -a 0x21000000 -e 0x21000000 -n "ramdisk file sysytem" -d tdramdisk.gz tdramdisk
提示信息: Image Name: ramdisk file system Created: Thu Jul 14 11:40:36 2005 Image Type: ARM Linux RAMDisk Image (gzip compressed)
Data Size: 5249216 Bytes = 5126.19 kB = 5.01 MB Load Address: 0x21000000 Entry Point: 0x21000000
这样就生成了要烧写到flash上的内核镜象文件uImage和根文件系统tdramdisk。
具体烧到flash中的地址自己根据内核大小(0x10030000开始)和根文件系统大小确定。
setenv(对于setenv命令的解释:Linux setenv命令用于查询或显示环境变量。setenv为tsch中查询或设置环境变量的指令。
)以下这些环境变量:
只要是擦除,修改环境变量,先打开flash写保护
protect off all setenv ethaddr 12:12:12:12:12:12 //0~f字符随意
setenv bootdelay 3 //默认为3秒
setenv loadaddr 21000000 //下载到SDRAM中的地址
setenv netmask 255.255.255.0 //默认存在
setenv ipaddr 192.168.0.112 //目标板ip地址
setenv serverip 192.168.0.111 //pc机ip地址
setenv bootcmd bootm 0x10030000 0x100e0000 //内核、文件系统的烧写地址
saveenv //保存环境变量 (setenv 是Set environment的缩写)
protect on all 保存环境变量后,能用printenv查看环境变量。
再将之前编译的内核镜象文件uImage和根文件系统tdramdisk,烧写固化到flash中。
能通过tftp的方式先将uImage和tdramdisk上传到sdram中,再进行烧写。
即: Uboot> protect off all Uboot> erase 0x10030000 0x107fffff //从0x10030000到8MB
Uboot> tftp 20000000 uImage
Uboot> cp.b 20000000 10030000 bffff //64kB*12,大约用时3分钟
Uboot> tftp 20000000 tdramdisk
Uboot> cp.b 20000000 100e0000 5fffff //6MB,大约用时20分钟左右
Uboot> protect on all //此处flash烧写地址应和上面设置一致 然后从就能从flash启动uboot并直接加载运行linux。
下面一堆我猜测是烧写过程显示的结果,或者烧写后启动系统自动打印的结果,有点看不懂,所以没断开。
boot 1.0 (May 31 2005 - 20:27:47) Uncompressing image... U-Boot 0.3.2 (Jun 5 2005 - 18:52:28) U-Boot code: 21F00000 -> 21F133EC BSS: -> 21F16E98 DRAM Configuration: Bank #0: 20000000 32 MB Spansion: S29GL064M90TAIR7 (64Mbit) flash_nb_blocks= 1 Flash: 8 MB Hit any key to stop autoboot: 0
[RUN_COMMAND] cmd[21f1ef0e]="bootm 0x10030000 0x100e0000"
[PROCESS_SEPARATORS] bootm 0x10030000 0x100e0000 token: "bootm 0x10030000 0x100e0000" [PROCESS_MACROS] INPUT len 27: "bootm 0x10030000 0x100e0000"
[PROCESS_MACROS] OUTPUT len 27: "bootm 0x10030000 0x100e0000" parse_line: "bootm 0x10030000 0x100e0000" parse_line: nargs=3 starting run command...go into do_bootm ## Booting image at 10030000 ... count=40 dest=21f15a50,src=10030000 dest > src Image Name: linux2.4.19-rmk7 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 670000 Bytes = 654.3 kB Load Address: 20008000 Entry Point: 20008000
Verifying Checksum ... OK count=a3930 dest=20008000,src=10030040 dest > srcOK ## Loading Ramdisk Image at 100e0000 ... Image Name: ramdisk file system Image Type: ARM Linux RAMDisk Image (gzip compressed) Data Size: 5249216 Bytes = 5 MB Load Address: 21000000 Entry Point: 21000000 Verifying Checksum ... OK count=5018c0 dest=21000000,src=100e0040 dest > src ## Transferring control to Linux (at address 20008000) ... Starting kernel ... Uncompressing Linux...................................... done, booting the kern el. Linux version 2.4.19-rmk7 (tank@redhat9) (gcc version 2.95.3 20010315 (release)) #3 六 6月 11 17:37:07 CST 2005 CPU: Arm920Tid(wb) revision 0 Machine: ATMEL AT91RM9200 Warning: bad configuration page, trying to continue On node 0 totalpages: 8192 zone(0): 8192 pages. zone(1): 0 pages. zone(2): 0 pages. Kernel command line: mem=32M console=ttyS0,115200 initrd=0x21000000,0x800000 roo t=/dev/ram rw init=/linuxsrc Calibrating delay loop... 89.70 BogoMIPS Memory: 32MB = 32MB total Memory: 22948KB available (984K code, 200K data, 52K init) Dentry cache hash table entries: 4096 (order: 3, 32768 bytes) Inode cache hash table entries: 2048 (order: 2, 16384 bytes) Mount-cache hash table entries: 512 (order: 0, 4096 bytes) Buffer-cache hash table entries: 1024 (order: 0, 4096 bytes) Page-cache hash table entries: 8192 (order: 3, 32768 bytes) POSIX conformance testing by UNIFIX Linux NET4.0 for Linux 2.4 Based upon Swansea University Computer Society NET3.039 Initializing RT netlink socket Starting kswapd devfs: v1.12a (20020514) Richard Gooch ([email protected]) devfs: boot_options: 0x1 RAMDISK driver initialized: 16 RAM disks of 32768K size 1024 blocksize physmap flash device: 800000 at 10000000 Amd/Fujitsu Extended Query Table v1.3 at 0x0040 number of CFI chips: 1 cfi_cmdset_0002: Disabling fast programming due to code brokenness. usb.c: registered new driver hub ttyS%d0 at MEM 0xfefff200 (irq = 1) is a AT91_SERIAL ttyS%d1 at MEM 0xfefc4000 (irq = 7) is a AT91_SERIAL eth0: Link now 100-FullDuplex eth0: AT91 ethernet at 0xfefbc000 int=24 100-FullDuplex (12:12:12:12:12:12) AT91 Watchdog Timer enabled (5 seconds) AT91 Real Time Clock driver usb-ohci.c: USB OHCI at membase 0xc3006000, IRQ 23 usb.c: new USB bus registered, assigned bus number 1 hub.c: USB hub found hub.c: 2 ports detected i2c-dev.o: Registered ’AT91RM9200’ as minor 0 Found AT91 i2c AT91 SPI driver loaded NET4: Linux TCP/IP 1.0 for NET4.0 IP Protocols: ICMP, UDP, TCP IP: routing cache hash table of 512 buckets, 4Kbytes TCP: Hash tables configured (established 2048 bind 2048) NET4: Unix domain sockets 1.0/SMP for Linux NET4.0. NetWinder Floating Point Emulator V0.95 (c) 1998-1999 Rebel.com RAMDISK: Compressed image found at block 0 Freeing initrd memory: 8192K VFS: Mounted root (ext2 filesystem). Mounted devfs on /dev Freeing init memory: 52K Initializing random number generator... done. Starting network... hub.c: USB new device connect on bus1/2, assigned device number 2 usb.c: USB device not accepting new address=2 (error=-110) run-parts: failed to open directory /etc/network/if-pre-up.d: No such file or di rectory hub.c: USB new device connect on bus1/2, assigned device number 3 usb.c: USB device not accepting new address=3 (error=-110) Starting system logger: syslogd Starting INET services: inetd Starting mouse Starting tty Starting console mouse services: gpmgpm: oops() invoked from gpn.c(132) loadlut: is your kernel compiled with CONFIG_SELECTION on?: Invalid argument Starting rtc INIT: Id "1" respawning too fast: disabled for 5 minutes
这是启动后正常进入的一些小命令了。
AT91RM9200DK login: root //登录输入用户名
[root@AT91RM9200DK /root]$cd / //进入到根目录下
[root@AT91RM9200DK /]$ls //列出该文件夹下有什么文件
var usr tmp sbin root rd proc mnt lost+found lib home etc dev bin drivers
[root@AT91RM9200DK /]$cd drivers/ //进入到drivers文件夹下
[root@AT91RM9200DK /drivers]$ls //列出该文件夹下有什么文件
485 ad can da ioin ioout lcd pwm keysegment led hello testusb
[root@AT91RM9200DK /drivers]$cd lcd //进入到lcd文件夹下
[root@AT91RM9200DK lcd]$ls //列出该文件夹下有什么文件
lcd.o testlcd.o
[root@AT91RM9200DK lcd]$insmod lcd.o //insmod : insert module 加载模块、插入模块 这些可以载入的模块一般都是设备驱动程序 具体命令含义见后面
[root@AT91RM9200DK lcd]$mknod /dev/lcd c 219 0 //mknod命令用于创建Linux中的字符设备文件和块设备文件。 具体参见下方。
[root@AT91RM9200DK lcd]$./testlcd.o //执行该文件
[root@AT91RM9200DK lcd]$
linux mknod命令解析
个人觉得linux的软件设计思想异常强大,比如把所有的设备都当做文件来处理,大大简化了程序员的负担,向提出这个思想的大神s致敬!!
先来看看linux系统中设备管理的基本知识: 我们的linux操作系统跟外部设备(如磁盘、光盘等)的通信都是通过设备文件进行的,应用程序可以打开、关闭、读写这些设备文件,从而对设备进行读写,这种操作就像读写普通的文件一样easy。linux为不同种类的设备文件提供了相同的接口,比如read(),write(),open(),close()。
所以在系统与设备通信之前,系统首先要建立一个设备文件,这个设备文件存放在/dev目录下。其实系统默认情况下就已经生成了很多设备文件,但有时候我们需要自己手动新建一些设备文件,这个时候就会用到像mkdir, mknod这样的命令。
mknod 的标准形式为: mknod DEVNAME {b | c} MAJOR MINOR
1,DEVNAME是要创建的设备文件名,如果想将设备文件放在一个特定的文件夹下,就需要先用mkdir在dev目录下新建一个目录;
2, b和c 分别表示块设备和字符设备:b表示系统从块设备中读取数据的时候,直接从内存的buffer中读取数据,而不经过磁盘;c表示字符设备文件与设备传送数据的时候是以字符的形式传送,一次传送一个字符,比如打印机、终端都是以字符的形式传送数据;
3,MAJOR和MINOR分别表示主设备号和次设备号:为了管理设备,系统为每个设备分配一个编号,一个设备号由主设备号和次设备号组成。主设备号标示某一种类的设备,次设备号用来区分同一类型的设备。linux操作系统中为设备文件编号分配了32位无符号整数,其中前12位是主设备号,后20位为次设备号,所以在向系统申请设备文件时主设备号不好超过4095,次设备号不好超过2^20 -1。
下面,我们就可以用mknod命令来申请设备文件了。
mkdir -p /dev/cobing
mknod /dev/cobing/mydev1 c 128 512
Linux将设备分为最基本的两大类:一类是字符设备,另一类是块设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了。字符设备以单个字节为单位进行顺序读写操作,通常不使用缓冲技术;块设备则是以固定大小的数据块进行存储和读写的,如硬盘、软盘等,并利用一块系统内存作为缓冲区。为提高效率,系统对于块设备的读写提供了缓存机制,由于涉及缓冲区管理、调度和同步等问题,实现起来比字符设备复杂得多。LCD是以字符设备方式加以访问和管理的,Linux把显示驱动看做字符设备,把要显示的数据一字节一字节地送往LCD驱动器。
帧缓冲区是出现在Linux 2.2.xx及以后版本内核当中的一种驱动程序接口,这种接口将显示设备抽象为帧缓冲区设备区。帧缓冲区为图像硬件设备提供了一种抽象化处理,它代表了一些视频硬件设备,允许应用软件通过定义明确的界面来访问图像硬件设备。这样软件无须了解任何涉及硬件底层驱动的东西(如硬件寄存器)。它允许上层应用程序在图形模式下直接对显示缓冲区进行读写和I/O控制等操作。通过专门的设备节点可对该设备进行访问,如/dev/fb*。用户可以将它看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以进行读写操作,而读写操作可以反映到LCD。
帧缓冲设备对应的设备文件是/dev/fb*。如果系统有多个显卡,Linux还支持多个帧缓冲设备,最多可达32个,即/dev/fb0~/dev/fb31。而/dev/fb则指向当前的帧缓冲设备,通常情况下,默认的帧缓冲设备为/dev/fb0。 帧缓冲设备也属于字符设备,采用“文件层-驱动层”的接口方式。