miniGUI3.0在mini6410上的移植

二 12 2012 由 创建在标签 开发

简介

MiniGUI 是一款面向嵌入式系统的高级窗口系统(Windowing System)和图形用户界面(Graphical User Interface,GUI)支持系统,由魏永明先生于 1998 年底开始开发。2002 年,魏永明先生创建北京飞漫软件技术有限公司,为 MiniGUI 提供商业技术支持,同时也继续提供开源版本,飞漫软件是中国地区为开源社区贡献代码最多的软件企业。最后一个采用 GPL 授权的 MiniGUI 版本是 1.6.10,从 MiniGUI 2.0.4 开始 MiniGUI 被重写并使用商业授权,从3.0.12开始,部分版本使用GPL授权。历经十余年时间, MiniGUI 已经成为性能优良、功能丰富的跨操作系统嵌入式图形用户界面支持系统,支持Linux/uClinux、eCos、 uC/OS-II、 VxWorks、ThreadX、Nucleus 、pSOS、OSE 等操作系统和数十种 SoC芯片,已验证的硬件平台包括 ARM-based SoCs、MIPS based SoCs、IA-based SoCs、PowerPC、M68K(DragonBall /ColdFire)、Intel x86 等等。

准备工作

交叉编译器

友善提供,具体安装参考mini6410的使用手册;

源码的下载

miniGUI官网上下载,需要有新浪账号或者twitter账号。下面是我下载的版本。

[root@localhost minigui]# ls -l *.tar.gz
-rwxrw-rw-. 1 root root 1427072 Jan 16 17:30 freetype-1_3_1.tar.gz
-rw-rw-r--. 1 root root   63582 Jan 16 17:31 gvfb-1_0_0.tar.gz
-rw-rw-r--. 1 root root  602762 Jan 16 17:32 qvfb2-2_0.tar.gz  
-rwxrw-rw-. 1 root root  557220 Feb 11 00:56 zlib-1.2.6.tar.gz
-rwxrw-rw-. 1 root root 1059513 Feb 11 00:55 libpng-1.5.8.tar.gz
-rwxrw-rw-. 1 root root  986681 Feb 10 23:42 jpegsrc.v8c.tar.gz
-rw-rw-r--. 1 root root  340656 Jan 16 17:33 libmg3d-1_0_2.tar.gz
-rw-rw-r--. 1 root root 1545209 Jan 16 17:34 libmgi-2_0_4.tar.gz
-rw-rw-r--. 1 root root 1116885 Jan 16 17:33 libmgp-1_2_2.tar.gz
-rw-rw-r--. 1 root root  648207 Jan 16 17:34 libmgplus-1_2_4.tar.gz
-rw-rw-r--. 1 root root  659702 Jan 16 17:33 libmgutils-1_0_4.tar.gz
-rw-rw-r--. 1 root root 3202804 Jan 17 00:29 libminigui-gpl-3_0_12.tar.gz
-rw-rw-r--. 1 root root 2608473 Jan 16 17:29 mg-samples-3_0_12.tar.gz
-rw-rw-r--. 1 root root 3449215 Jan 16 17:29 minigui-res-be-3_0_12.tar.gz

官网上有几个库的版本太低,所以需要自己去网上下载,其中jpegsrc.v8c.tar.gzlibpng-1.5.8.tar.gzzlib-1.2.6.tar.gz都是从网上找的最近版本(png和zlib这两个soucefoge上都有,前面一个是网上搜的,所以不能保证链接长期有效,但是网上搜一下还是比较容易找到的)。其实我也是在运行例子程序的时候才发现问题的,库更新后就可以正常运行了。

简单介绍一下使用到的几个库。

freetype:FreeType库是一个完全免费(开源)的、高质量的且可移植的字体引擎,它提供统一的接口来访问多种字体格式文件,包括TrueType, OpenType, Type1, CID, CFF, Windows FON/FNT, X11 PCF等。支持单色位图、反走样位图的渲染。FreeType库是高度模块化的程序库,虽然它是使用ANSI C开发,但是采用面向对象的思想,因此,FreeType的用户可以灵活地对它进行裁剪。

gvfb与qvfb2:这两个主要用于pc上仿真,在嵌入式平台上没用,就不做说明。

zlib:zlib是提供数据压缩用的函式库,由Jean-loup Gailly与Mark Adler所开发,初版0.9版在1995年5月1日发表。zlib使用DEFLATE算法,最初是为libpng函式库所写的,后来普遍为许多软件所使用。

libpng:这个是用来显示png图形的,MiniGUI里很多图都是png的,如果没有这个库,MiniGUI将无法正常工作。

jpeg:用于显示jpeg图像,否则程序不能正常运行。

minigui-res:minigui3.0工具栏所使用的资源集合,包括字体、图标、位图等。

libminigui:minigui3.0的核心库。

mg-samples:minigui3.0的例子程序,有一两个小游戏,可以玩玩~~

minigui可选组件:libmg3d(3D支持)、libmgi(提供输入接口)、libmgp(提供打印机接口的支持)、libmgplus(2D矢量图支持和图像加速)、libmgutils(提供一些常用对话框的模板),可以根据自己的需要使用,在跑例子程序的时候使用到了libmgplus,所以就临时编了它的lib。

交叉编译图像库

先将代码解压到你所放置代码的位置,然后再进行如下步骤来编译安装图像库。我的安装目录是:/usr/local/minigui,可以根据自己的习惯和喜好安装在其他目录,通过prefix参数来配置安装目录。

编译zlib库

编译与配置脚本:

[root@localhost] CC=arm-linux-gcc \
                 CXX=arm-linux-g++ \
                 LD=arm-linux-ld \
                 AS=arm-linux-as \
                 AR=arm-linux-ar \
                 ./configure --prefix=/usr/local/minigui \
                   --shared
#配置完成后
[root@localhost] make
[root@localhost] make install

 编译png库

[root@localhost] CC=arm-linux-gcc \
                 CXX=arm-linux-g++ \
                 LD=arm-linux-ld \
                 AS=arm-linux-as \
                 AR=arm-linux-ar \
                ./configure --prefix=/usr/local/minigui \
                    --build=i386-linux \
                    --host=arm-linux \
                    --target=arm-linux
[root@localhost] make
[root@localhost] make install

编译Jpeg库

[root@localhost] CC=arm-linux-gcc \
                 CXX=arm-linux-g++ \
                 LD=arm-linux-ld \
                 AS=arm-linux-as \
                 AR=arm-linux-ar \
                 ./configure --prefix=/usr/local/minigui \
                   --build=i386-linux \
                   --host=arm-linux \
                   --target=arm-linux \
                   --enable-shared
[root@localhost] make
[root@localhost] make install

 编译freetype库

自动配置还有问题,也没有尝试高版本的freetype能不能使用,暂时就先这样,好像例子代码里面并没有使用它。后面再尝试高版本的freetype。

[root@localhost] cd freetype-1.3.1/
[root@localhost] ./configure --host=arm-linux --enable-static --prefix=/usr/local/minigui
[root@localhost] vim config.cache
# 修改如下行
ac_cv_path_LD=${ac_cv_path_LD=arm-linux-gnu-ld}
ac_cv_prog_CC=${ac_cv_prog_CC=arm-linux-gnu-gcc}
ac_cv_prog_CPP=${ac_cv_prog_CPP='arm-linux-gnu-gcc -E'}
#重新配置
[root@localhost] ./configure --host=arm-linux --enable-static --prefix=/usr/local/minigui
# 修改Makefile文件,以跳过编译test目录。
# 去掉“all:”后的变量“tttest”
# 注释掉“install:”下的第二行:“cd $(FTTESTDIR); $(MAKE) –f$(MAKEFILE) install”
[root@localhost] make
[root@localhost] make install

安装minigui资源库

[root@localhost] CC=arm-linux-gcc \
                 CXX=arm-linux-g++ \
                 LD=arm-linux-ld \
                 AS=arm-linux-as \
                 AR=arm-linux-ar \
                  ./configure --prefix=/usr/local/minigui
[root@localhost] make
[root@localhost] make install

编译minigui核心库

配置脚本:

[root@localhost] CC=arm-linux-gcc \
                 CXX=arm-linux-g++ \
                 LD=arm-linux-ld \
                 CFLAGS="-I/usr/local/minigui/include -I/opt/arm/toolschain/4.5.1/arm-none-linux-gnueabi/include " \
                 CPPFLAGS="-g -I/usr/local/minigui/include -I/opt/arm/toolschain/4.5.1/arm-none-linux-gnueabi/include " \
                 CXXFLAGS="-g -I/usr/local/minigui/include -I/opt/arm/toolschain/4.5.1/arm-none-linux-gnueabi/include " \
                   ./configure --prefix=/usr/local/minigui \
                   --host=arm-linux \
                   --target=arm-linux \
                   --build=i386-linux \
                   --with-osname=linux \
                   --with-style=classic \
                   --with-targetname=fbcon \
                   --enable-autoial \
                   --enable-rbf16 \
                   --disable-vbfsupport
[root@localhost] make
[root@localhost] make install

遇到错误:pcxvfb.c:490:13: error: impossible constraint in ‘asm’,因为使用了错误的头文件,解决方法如下:

 mv select.h select.h.bak
 cp /opt/arm/toolschain/4.5.1/arm-none-linux-gnueabi/include/bits/select.h ./
 rm select.h
 mv select.h.bak select.h

编译minigui例子程序

例子程序也不是一帆风顺的,从配置到最后编译都会有问题。具体配置脚本如下:

[root@localhost] CC=arm-linux-gcc \
                 CXX=arm-linux-g++ \
                 LD=arm-linux-ld \
                 CFLAGS="-I/usr/local/minigui/include -I/opt/arm/toolschain/4.5.1/arm-none-linux-gnueabi/include " \
                 CPPFLAGS="-g -I/usr/local/minigui/include -I/opt/arm/toolschain/4.5.1/arm-none-linux-gnueabi/include " \
                 CXXFLAGS="-g -I/usr/local/minigui/include -I/opt/arm/toolschain/4.5.1/arm-none-linux-gnueabi/include " \
                 ./configure --prefix=/usr/local/minigui \
                    --build=i386-linux \
                    --host=arm-linux \
                    --target=arm-linux

在配置阶段或遇到环境变量的问题,但是在配置了环境变量后还是出现错误,就直接在configure文件中添加了变量,这样才通过配置。修改如下:

vim configure
# 在 $as_echo_n "checking for MINIGUI... " >&6; }后添加如下变量:
MINIGUI_CFLAGS = /usr/local/minigui/include
MINIGUI_LIBS = /usr/local/minigui/lib

然后开始make,又出现如下错误:no such file: File format not recognized collect2: ld returned 1 exit status。经过网上查资料后发现是生成的Makefile有问题,需要逐个修改Makefile。修改每个Makefile钟的如下行:

 LIBS = -lminigui_ths -ljpeg -lm -lpthread -ldl
 LDFLAGS = -L/usr/local/minigui/lib

这样就可以通过编译并生成可执行文件了。

部署图像库

其实这个工作很简单,主要有两个步骤,一个修改minigui的配置文件,另一个是拷贝库文件到文件系统就可以了。配置文件在minigui的wiki上也有较详细的介绍,可以参考:《MiniGUI V3.0 的运行

修改配置文件:

$ vim /usr/local/minigui/etc/MiniGUI.cfg
# 修改如下参数
# GAL engine and default options
gal_engine=fbcon

# IAL engine
ial_engine=console
mdev=/dev/input/mice
mtype=IMPS2

# 根据实际的显示大小填
[fbcon]
defaultmode=480x272-16bpp

拷贝库到文件系统:

$ cp /usr/local/minigui/* /myrootfs/usr/local

拷贝你的例子程序就可以在开发板上运行了~~

参考文档和链接

  1. minigui的wiki
  2. MiniGUI-1.6.10 MiniGUI-1.6.10在mini2440上的移植(网络文档)
  3. miniGUI官网

6 条评论

支持6410从SD卡启动的Uboot

一 16 2012 由 创建在标签 开发

友善提供的Superboot确实很好用,但是samsung提供的uboot版本比较低,从友善的官网也看到对应的uboot介绍,了解到它启动的时候并不能很好地支持SD卡,尤其是SDHC的支持很不好,那个是因为uboot版本太低,而且SD卡也不能超过2G。最让人头疼的是不能从SD卡直接启动系统,只能将img拷贝到NAND,然后再从NAND中启动(参考友善官网6410的bootloader介绍)。对于想定制自己的Bootloader人就会遇到想不到的麻烦,所以就想着找一个能够很好支持SD卡启动Linux的Uboot。

SD/MMC的启动原理

要想知道启动的原理,就必须先了解芯片的特性和它的启动过程,需要查看厂商提供的Datasheet和芯片相关的资料。对于6410,samsung提供了一份启动相关的文档——《SMDK6410_IROM_APPLICATION NOTE_REV 1.00》,想了解的人可以自己在网上搜一下,我只简单说一下我看了之后对我比较有用的东西,肯定会有信息遗漏。

6410最开始启动的时候先执行固化在芯片里面的代码,iRom(BL0)它所做的事情很简单,主要完成系统时钟、堆栈、设备控制器和启动设备标识的初始化,确定下一阶段(BL1)的启动设备和起始地址,拷贝BL1到启动区域,然后将执行权交给启动区域,开始BL1的执行。其中iRom初始化了很多函数指针和全局变量,这些都为BL1阶段的执行和代码的拷贝做好准备;6410通过从引脚来判断是从Nand还是从SD卡拷贝数据的,在6410中就有一个开关来选择是从NAND还是从SD卡启动的。BL1就已经是Bootloader的代码了,但是BL1的大小是有8k的限制,不能完成所有的Bootloader的工作,还需要BL2的配合才能真正完成所有的引导过程。

Uboot的移植

其实写到这里就已经没有多少我的东西了,因为自己并没有真正去移植,所以后面说的有点人云亦云,我只是从网上下了一份tekkamanninja移植好的代码(亲自测试,可以运行,运行时有启动背景),自己做了一些比较,说说他的这份代码是如何移植的,而且作者的博客上也有很多关于Uboot移植的代码和一些关于这方面原理的分析。如果有机会自己移植的话再写一些关于Uboot移植的东西。

/u-boot-2011.06mini6410/arch/arm/include/asm/arch-s3c64xx
# ls -l
total 80
-rw-rw-r--. 1 root root 1995 Sep  7 07:30 hardware.h
-rw-rw-r--. 1 root root 2066 Sep  7 07:30 mmc.h
-rw-rw-r--. 1 root root 13667 Sep  7 07:30 regs-fb.h
-rw-rw-r--. 1 root root 5470 Sep  7 07:30 regs-fb-v4.h
-rw-rw-r--. 1 root root 36503 Sep  7 07:30 s3c6400.h
-rw-rw-r--. 1 root root 9205 Sep  7 07:30 s3c64x0.h

上面列出了初始化时需要调用的一些公共函数、结构体、宏等相关的声明,主要增加了SD卡和mini6410的LCD支持,完成他们的初始化,使得开机时能够显示Logo、背景以及SD卡启动系统。

/u-boot-2011.06mini6410/arch/arm/cpu/arm1176
# ls -l
total 56
-rw-rw-r--. 1 root root 1319 Sep  7 07:30 config.mk
-rw-rw-r--. 1 root root 1717 Sep  7 07:30 cpu.c
-rw-rw-r--. 1 root root 1496 Sep  7 07:30 Makefile
drwxrwxr-x. 2 root root 4096 Jan 14 00:26 s3c64xx
-rw-rw-r--. 1 root root 15078 Sep  7 07:30 start.S
-rw-rw-r--. 1 root root 1712 Sep  7 07:30 u-boot.lds
# cd s3c64xx/
# ls -l
total 76
-rw-rw-r--. 1 root root 1319 Sep  7 07:30 config.mk
-rw-rw-r--. 1 root root 5424 Sep  7 07:30 cpu_init.S
-rw-rw-r--. 1 root root 1459 Sep  7 07:30 Makefile
-rw-rw-r--. 1 root root 1109 Sep  7 07:30 reset.S
-rw-rw-r--. 1 root root 3441 Sep  7 07:30 speed.c
-rw-rw-r--. 1 root root 4363 Sep  7 07:30 timer.c

上面列出了与芯片有关的初始化代码,作者修改了cpu_init.S和start.S,其中cpu_init.S主要是自动检测内存大小的代码(参考Mini6410自动识别内存大小);star.S主要是增加启动时自动检测内存、确定是从SD卡还是从NAND启动以及LED功能。

/u-boot-2011.06mini6410/arch/arm/lib
# ls -l
-rw-rw-r--. 1 root root 17540 Sep  7 07:30 board.c

上面列出了lib中修改了的文件,它的修改主要是为了添加LED功能。

/u-boot-2011.06mini6410/drivers/mmc
# ls -l
-rw-rw-r--. 1 root root 24139 Sep  7 07:30 mmc.c
-rw-rw-r--. 1 root root 11091 Sep  7 07:30 s3c64x0_mmc.c

上面新增了s3c64x0_mmc.c文件,它主要完成6410 SD卡的初始化;mmc.c主要添加了一些打印信息。

/u-boot-2011.06mini6410/drivers/video
# ls -l
total 552
-rw-rw-r--. 1 root     root     49102 Sep  7 07:30 cfb_console.c
-rw-rw-r--. 1 root     root      9151 Jan 14 00:14 s3c64x0_fb.c
-rw-rw-r--. 1 root     root      8945 Sep  7 07:30 videomodes.c
-rw-rw-r--. 1 root     root      3480 Sep  7 07:30 videomodes.h

上面主要增加了对LCD的支持,支持开机时使用友善的上自带的LCD,可以显示开机Logo和背景。

/u-boot-2011.06mini6410/mmc_spl/board/samsung/mini6410
# ls -l
lrwxrwxrwx. 1 root     root       86 Jan  5 22:58 cpu_init.S
lrwxrwxrwx. 1 root     root       85 Jan  5 22:58 lowlevel_init.S
-rw-rw-r--. 1 root     root     2417 Sep  7 07:30 mmc_boot.c
lrwxrwxrwx. 1 root     root       75 Jan  5 22:58 start.S
-rw-rw-r--. 1 root     root     1725 Sep  7 07:30 u-boot.lds

上面这个目录为新增目录,它们就是针对mini6410启动初始化的过程,其实cpu_init.S等汇编代码其实只是上面体系结构目录下的符号链接,它们将烧写在BL1中,作为iRom执行后第一个执行的部分,主要就是完成初始化,并调用mmc_boot.c中的初始化函数,其中copy_uboot_to_ram函数从BL2中拷贝代码到内存,并跳转到对应的区域执行,从而进入BL2的代码段执行。

其他修改过的文件都只是一些配置相关的,因为作者增加了很多新的功能,所以在编译的时候还需要让其他部分也编译进去。

烧写Uboot

在Linux中可以通过命令和网友Amankwah提供的工具(下载地址)。但是在使用的时候要获得root权限,我在Fedora下面也是可以正常工作的。但是在使用的时候注意将BL1的目录选择mmc_spl目录下,否则默认的是NAND那个目录下。烧写的命令如下:

$ sudo fdisk /dev/sdb

Command (m for help): p
Disk /dev/sdb: 7969 MB, 7969177600 bytes
246 heads, 62 sectors/track, 1020 cylinders
Units = cylinders of 15252 * 512 = 7809024 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *           1           6       45755+   b  W95 FAT32
/dev/sdb2   *           7        1020     7732764   83  Linux

##################################################################
# 所以总块数是7969177600/512=15564800
# IROM所认为的总块数15563776(15564800-1024)(仅在SDHC时需要减去1024)
# 所以nand_spl/u-boot-spl-16k.bin烧写的位置是15563758块(15563776-18)
# u-boot.bin烧写的位置是15557632块(15563776-6144(3MB))(根据我的Uboot配置文件)
###################################################################
# 烧写命令:
sudo dd if='(Uboot源码)/nand_spl/u-boot-spl-16k.bin'     of=/dev/(SD卡的设备节点) bs=512   seek=15563758
sudo dd if='/(Uboot源码)/u-boot.bin'      of=/dev/(SD卡的设备节点) bs=512   seek=15557632

其实觉得友善的Superboot和这个应该差不多,友善的烧写工具应该也是将他们分成两步来做的,因为我用这个版本的Uboot编译后用友善的烧写工具烧写发现打开的文件格式错误,再加上看了6410的启动过程,所以感觉友善的编译出来的Uboot和Superboot应该是将两个打包成一个了,然后在烧写时再做区分,分别写到对应的区域中去。

现在我已经用网友提供的 Uboot引导成功,能够正常进入了,也设置了开机画面和背景。其实这篇文章主要是参考的别人的博客,自己只是把别人的博客和代码拿过来整理了一下,希望能够对6410学习的人和想移植Uboot的人有所帮助。

参考网站

Tekkaman Ninja的博客

一条评论

Mini6410启动过程(二)

一 13 2012 由 创建在标签 开发

前一段时间写过Mini6410的启动过程,但是那个只写出了它启动的后半部分,因为自己那个时候还没有彻底了解清楚友善的启动机制和过程,所以只写了后一部分。这段时间在尝试使用uBoot来替代友善的Superboot,让板子支持从SD卡启动,所以就仔细研究了一下友善提供的内核和它的启动参数,发现友善真的蛮聪明,把电脑的启动方式借鉴到它们自己的开发板上了。现在就把6410启动的过程分享出来,可能还有不完善的地方,希望了解的人也能指出我文章里面的不足。

initramfs启动

以前在X86平台上做过一个最小的U盘启动小系统,用的就是initramfs的方式,只是在最后阶段不要让它切换根目录。对于initramfs的启动方式网上有很多相关的文章,Linux内核的文档也有相应的介绍。这里只简单说一下它的原理,initramfs将归档好的文件系统添加到img中,在启动的时候就只需要指定少量的内核启动参数,在启动过程中的临时文件系统所运行的脚本都是此文件系统中的程序和脚本,当然,这个文件系统其实就是一个简单的linux系统,可以进行简单的操作,如果要扩展功能又不想把img做得很大,可以考虑用mount文件系统然后转换的方式来做。

这样就将启动过程分成两个阶段,第一阶段就是用编入内核的文件系统做初始化,然后用定制的文件系统来跑应用程序。不仅减少了更新内核的负担,而且在更新的时候不需要更新应用程序的文件系统,文件系统和内核的更新可以分开来做,提高了效率。

init脚本

Linux启动后执行的第一个程序就根目录下的ini,友善通过init脚本来完成启动过程。其主要工作就是声明一些环境,加载要运行的文件系统,然后做文件系统的切换。因为不像X86下那么复杂,所以设备的初始化相对而言较为简单。启动脚本和注释如下。

#! /bin/sh

#初始化环境变量
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel

#
#       Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
#
trap ":" INT QUIT TSTP
#设置主机名
/bin/hostname FriendlyARM
#mount proc文件系统
/bin/mount -n -t proc proc /proc

#获取U-boot启动参数,主要设置文件系统内型、根目录、init等
cmdline=`cat /proc/cmdline`

#声明初始化启动相关参数,并设置默认值
ROOT=none
ROOTFLAGS=
ROOTFSTYPE=
NFSROOT=
IP=
INIT=/sbin/init

#从获取的命令中获取启动参数
for x in $cmdline ; do
        case $x in
        root=*)
                ROOT=${x#root=}
                ;;
        rootfstype=*)
                ROOTFSTYPE="-t ${x#rootfstype=}"
                ;;
        rootflags=*)
                ROOTFLAGS="-o ${x#rootflags=}"
                ;;
        init=*)
                INIT=${x#init=}
                ;;
        nfsroot=*)
                NFSROOT=${x#nfsroot=}
                ;;
        ip=*)
                IP=${x#ip=}
                ;;

        esac
done

if [ ! -z $NFSROOT ] ; then
	#网络文件系统启动
	echo $NFSROOT | sed s/:/\ /g  > /dev/x ;  read sip dir < /dev/x 	echo $IP | sed s/:/\ /g > /dev/x;  read cip sip2 gip netmask hostname device autoconf < /dev/x
	rm /dev/x

	mount -t nfs $NFSROOT /r -o nolock,proto=tcp

elif [ ! -z $run_fs_image ] ; then
	#制定的文件系统启动,这个环境变量还不知道是如何导出的,所以还需要了解,
	#看到友善提供的配置文件需要制定启动的文件系统,感觉应该是和那个地方相关,
	#但是又不能确定,高手可以指点一下
	ROOTFSTYPE="-t ext3" #设置文件系统类型
	#重复加载SD卡,重复尝试5次
	for i in 1 2 3 4 5 ; do
	/bin/mount -n -o sync -o noatime -o nodiratime -t vfat /dev/mmcblk0p1 /sdcard && break
	echo Waiting for SD Card...
	sleep 1
	done
	#加载文件系统
	/sbin/losetup /dev/loop0 /sdcard/$run_fs_image
	/bin/mount $ROOTFSTYPE /dev/loop0 /r
	mount -o move /sdcard /r/sdcard
else
    #直接用指定的启动参数加载文件系统
    /bin/mount -n $ROOTFLAGS $ROOTFSTYPE $ROOT /r
fi

#检测并设置触摸屏的校正参数,可无
ONE_WIRE_PROC=/proc/driver/one-wire-info
ETC_BASE=/r/etc
[ -d /r/system/etc ] && ETC_BASE=/r/system/etc
[ -e $ETC_BASE/ts.detected ] && . $ETC_BASE/ts.detected
[ -z $CHECK_1WIRE ] && CHECK_1WIRE=Y
if [ $CHECK_1WIRE = "Y" -a -e $ONE_WIRE_PROC ] ; then
        if read lcd_type fw_ver tail < $ONE_WIRE_PROC ; then                 if [ x$lcd_type = "x0" -a x$fw_ver = "x0" ] ; then                         TS_DEV=/dev/touchscreen                 else                         TS_DEV=/dev/touchscreen-1wire                         echo "1Wire touchscreen OK"                 fi                 if [ -e $ETC_BASE/friendlyarm-ts-input.conf ]; then                         sed "s:^\(TSLIB_TSDEVICE=\).*:\1$TS_DEV:g" $ETC_BASE/friendlyarm-ts-input.conf > $ETC_BASE/ts-autodetect.conf
                        mv $ETC_BASE/ts-autodetect.conf $ETC_BASE/friendlyarm-ts-input.conf -f
                        echo "CHECK_1WIRE=N" > $ETC_BASE/ts.detected
                        sync
                fi
        fi
fi

[ -e /r/etc/friendlyarm-ts-input.conf ] && . /r/etc/friendlyarm-ts-input.conf
[ -e /r/system/etc/friendlyarm-ts-input.conf ] && . /r/system/etc/friendlyarm-ts-input.conf
export TSLIB_TSDEVICE

#exec /bin/sh

#文件系统替换
umount /proc
exec switch_root /r $INIT /r/dev/console 2>&1

被“欺骗”的脚本

当初以为ext3的文件系统就是实际启动时执行的操作,但是那个却是一个错误的认识,之所以认为那个是启动的文件系统,是因为内核的一个配置参数和此文件系统包含了一些脚本,所以在启动时走了不少的弯路。

首先是对initramfs的认识不够,内核中有下面一个配置项:

General setup  --->
    (scripts/FriendlyARM.cpio) Initramfs source file(s)

看了文件后,我以为是友善的一个加密程序,是为了保护自己的知识产权,所以以为它只是打包进去,到了加载初始化文件系统的时候从内核配置的地址读取文件系统,然后再用这个程序解密。其次那个启动的参数加深了我的这个认识,让我误入歧途,脚本如下:

Boot options  --->
    (console=ttySAC0,115200 root=/dev/ram init=/linuxrc initrd=0x51000000,6M ramdisk_size=6144)

所以我一直以为是我的文件系统没有拷贝到正确的物理地址,导致内核死掉;一直在尝试文件系统到内存并设置u-boot的环境变量,然后反复重新启动,但是一直是无解,最后我绝望了。在网上看了很多资料,发现Initramfs source file配置的应该是文件系统,再看看这个配置项就感觉像是一个cpio命令归档的文件系统,然后果断尝试能否将他解压。用如下命令解压它的归档文件:

cpio -ivmd < FriendlyARM.cpio

发现神奇般的解压开了,然后发现它就是一个文件系统,只是友善打包好了,然后配合它的Superboot来启动它的文件系统。然后就可以看到友善的第一步启动过程,其脚本也在上一节做了一些注释(一开始我还是死脑子地认为init也是一个可执行文件,琢磨一段时间后才考虑直接打开的)。其实上面的Boot options是使用ramdisk启动Linux所用到的配置项,用initramfs这个配置项是不必要的。

这样也就知道了mini6410的全部启动过程,前面走过的弯路总算有一个较好的结局了。

总结

其实Linux启动过程的介绍网上有很多,制作自己的最小启动系统的资料也不少,但是用了友善的开发板后总觉得它会保密,所以在理解它的一些机制的时候总会有定向思维,不敢放手去做,总是觉得自己哪里做错了。其实应该大胆去尝试,毕竟搞开发的人不会去把简单问题复杂化。冷静的思考其实也很重要,看到那个FriendlyARM.cpio时,我没有想到他是一个文件系统的归档文件,以为是和cpio命令相关的应用程序,这才让我走了很多弯路,其实可以通过file命令查看一下它到底是什么文件,那样也不至于走那么多的弯路。还是自己的经验尚浅啊~~不过走了一些弯路应该会记得更加清楚。

无评论

在Mini6410上安装自己的内核和文件系统

一 09 2012 由 创建在标签 开发

前面有一篇文章说的是Mini6410的启动过程,主要说的是6410的启动的一些大致流程,并没有提到内核和文件系统。做过嵌入式的人都应该知道系统的资源是有限的,需要倍加珍惜,所以在特定的应用场景中要使用定制的内核和文件系统,而友善提供的文件系统显得很臃肿,有点浪费空间,而且不是所有的功能我们都需要用到,自己定制一个文件系统是一个很好的选择,也是在开发过程中一个必须做到的工作。

6410的内核和文件系统

由于用的是友善提供的Superboot,所以需要了解友善是如何来做的。友善的Superboot启动的时候先读取它的配置文件,找到内核镜像和文件系统的目录(注:友善Superboot的具体实现不太清楚,所以只是猜测),然后加载内核,我是用SD卡启动的,方便更新文件系统和内核。下面是友善提供的文件系统和内核的大小,你会发现比你想象的要大很多。

[root@gaoliang Linux]# ls -lh
-rwxr-xr-x    1 root     root        3.6M Nov 16 18:49 zImage_n43
-rwxr-xr-x    1 root     root      293.0M Nov 19 21:04 rootfs_qtopia_qt4.ext3

一个文件系统就占了近200M的空间,在硬件资源有限的情况下,我们还是应该要好好珍惜那点宝贵的资源。

裁剪文件系统

我是直接从友善的文件系统中把文件拷贝过来,在原有的基础上做一些改动,主要是删除一些没有用或者不实用的功能。

首先先查看每个目录的大小,从而知道哪些地方是我们重点关注的地方。

[root@localhost rootfs_qtopia_qt4]# du -sh *
724K    bin
4.0K    dev
648K    etc
53M     lib
0       linuxrc
4.0K    mnt
86M     opt
4.0K    proc
21M     root
1.2M    sbin
4.0K    sys
4.0K    tmp
76M     usr
4.0K    var
592K    www

其中lib、opt和usr占用的空间比较多,其中lib目录是因为modules目录中包含了两个版本的内核;opt是一些可选包,主要是QT相关的一些库;usr目录主要是播放器的应用程序和一些测试程序。

所以将opt目录下的东西全部删除,删除usr目录下关于应用程序的部分,如果删除了应用程序,应用程序会起不来,如smplayer就不能正常工作,也可以同时删除bin目录下相应的东西。

最后再将lib目录下的modules删除,删除了之后就只安装我们自己编译内核配置的模块,可以直接复制一份友善提供的配置文件编译内核(要与开发板对应),编译完成后用如下命令来在我的文件系统下安装模块。

make modules_install INSTALL_MOD_PATH=/opt/arm/mini6410/linux/rootfs
#INSTALL_MOD_PATH你的文件系统所在的路径

这样就可以将我们所配置的内核模块安装到我们的文件系统中来。从而减小文件系统的大小。

内核配置

内核的裁剪网上也有很多介绍,每一个配置项也都有介绍,而且翻译过来的中文资料也比较多,可以在网上搜一搜。

目前的状态和打算

现在我裁剪后文件系统已经比原先的小了很多,因为还有一些不了解的东西,所以也没有细看,如果把一些无用的东西全部去掉的话,应该能够做得很小。下面是我裁剪后的内核和文件系统:

[root@gaoliang Linux]# ls -lh
-rwxr-xr-x    1 root     root       89.0M Nov 20 08:01 rootfs_qtopia_qt4.ext3
-rwxr-xr-x    1 root     root        3.6M Jan  9  2012 zImage_n43

但是也有一个比较奇怪的现象,就是用友善提供的制作文件系统的工具所制作的文件系统比原来的还要大,并没有压缩。这个让人感动有些奇怪。我在Linux下未打包的文件系统只有69M,所以后面打算用压缩的方式打包,将文件系统压得更小,但是因为不了解Superboot做了哪些工作,这个还有一定难度。配置文件对Superboot有什么影响也需要弄清楚,因为配置文件中指定了文件系统,所以也不清楚如何让内核加载文件系统有没有受到Bootloader的影响。

因为删除了QT相关的库,所以也想移植一个新的GUI库,主要是减少文件系统的大小,我身边有人在做MiniGUI,所以初步想法是用miniGUI做一套新的GUI,但是不去开发它的应用程序了,等miniGUI3.0的源码放出来之后开始做这个工作(今天问过miniGUI的技术支持,3.0的源码还有一个月才放出,但是总归是开源,还是不错的)。

希望有对Superboot有了解的人说说,但是这个是人家的商业机密,让人挺烦的…不过这个也没有办法,还是靠自己去慢慢去摸索吧。

无评论

Mini6410的启动过程

十二 27 2011 由 创建在标签 开发

入手Mini6410很久,一直没有用起来,最近项目稍微轻松一点,开始拿起来做点事情、学点东西,后面也会把这款开发板的一些情况发不上来。

Mini6410简介

Mini6410是友善基于三星6410开发的一款ARM11开发板,想了解的人可以到官网看看(6410友善官网),里面有详细的信息。

这里也简要提一下6410一些让人蛋疼的东西,让人用着很不爽,因为还没有用得很熟悉,就说说目前发现的两个让人不爽的地方。第一,它的Superloader不开源,提供的开源的U-boot又不能支持SD卡启动;第二,文件系统压缩使用了自己的压缩方法(在内核配置的地方可以查看到),如果我们想用通用的程序来做的话,压力会比较大。

6410的启动过程介绍

和X86平台的启动过程不同的是6410通过busybox启动,将复杂的启动过程变得简单化,便于初学者学习和使用此块开发板。

开机启动时首先进入Bootloader,它主要完成的工作是初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。友善提供了两种Bootloader,基于Samsung的u-boot做了一点修改的和友善自己开发的SuperLoader,SuperLoader功能比较强大,但是不开源,可以免费使用;但是如果我们自己想做一些改变的话,那就有点困难了。

由Bootloader引导后,系统加载内核,内核加载后加载文件系统,之后执行init程序,但是友善直接修改了内核的配置,直接运行linuxrc程序(其实是busybox),然后就开始执行init.d下的rcS脚本。下面将通过内核配置和脚本来介绍它启动的一些细节。

在友善提供的文件系统中的.config中,可以看到启动执行的程序被修改为linuxrc,而且linuxrc只是busybox的一个符号链接,如下:

init.d目录下的启动脚本

rcS启动脚本注解

#! /bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:
runlevel=S
prevlevel=N
umask 022
#导出环境变量和运行级别
export PATH runlevel prevlevel
#
#       Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
#
trap ":" INT QUIT TSTP
#设置主机名称
/bin/hostname friendARM
[ -e /proc/1 ]    || /bin/mount -n -t proc  none /proc
[ -e /sys/class ] || /bin/mount -n -t sysfs none /sys
[ -e /dev/tty ]   || /bin/mount    -t ramfs none /dev
/bin/mount -n -t usbfs none /proc/bus/usb

echo /sbin/mdev > /proc/sys/kernel/hotplug

#udev实现U盘或SD卡的自动挂载,mdev是busybox中的一个udev管理程序的一个精简版,他也可以实现设备节点的自动创建和设备的自动挂载
/sbin/mdev -s
/bin/hotplug

# mounting file system specified in /etc/fstab
mkdir -p /dev/pts
mkdir -p /dev/shm
/bin/mount -n -t devpts none /dev/pts -o mode=0622
/bin/mount -n -t tmpfs tmpfs /dev/shm
/bin/mount -n -t ramfs none /tmp
/bin/mount -n -t ramfs none /var
mkdir -p /var/empty
mkdir -p /var/log
mkdir -p /var/lock
mkdir -p /var/run
mkdir -p /var/tmp

/sbin/hwclock -s
syslogd

#启动网络配置
/etc/rc.d/init.d/netd start
echo "                        " > /dev/tty1
echo "Starting networking..." > /dev/tty1
sleep 1

#启动httpd
/etc/rc.d/init.d/httpd start
echo "                        " > /dev/tty1
echo "Starting web server..." > /dev/tty1
sleep 1

#启动Led模块
/etc/rc.d/init.d/leds start
echo "                        " > /dev/tty1
echo "Starting leds service..." > /dev/tty1
echo "                        "
sleep 1
echo "                        " > /dev/tty1

#alsaconf,看了启动的程序发现是一些默认的配置项
/etc/rc.d/init.d/alsaconf start
echo "Loading sound card config..." > /dev/tty1
echo "                        "

#配置网络相关地址
/sbin/ifconfig lo 127.0.0.1
/etc/init.d/ifconfig-eth0

#启动QT图形界面
/bin/qtopia &
echo "                                  " > /dev/tty1
echo "Starting Qtopia, please waiting..." > /dev/tty1

一条评论