分类:
2006-06-30 13:58:34
由于工作需要,只编译lib库,可以参考 :-)
交叉编译alsa-lib
$ cd ${PRJROOT}/build-tools
$ wget --passive-ftp ftp://ftp.alsa-project.org/pub/lib/alsa-lib-1.0.10.tar.bz2 && tar xvjf alsa-lib-1.0.10.tar.bz2 && cd alsa-lib-1.0.10
$ CC=arm-linux-gcc ./configure --target=arm-linux --build=arm-linux --host=i686-pc-linux --prefix=${TARGET_PREFIX}
$ make
$ make install
提示:
pcm_file.c:191: parse error before `n'
make[2]: *** [pcm_file.lo] Error 1
解决:
修改alsa-lib-1.0.10/src/pcm/pcm_file.c文件
+++191行
- snd_pcm_uframes_t n = snd_pcm_frames_to_bytes(pcm, err);
+ /*snd_pcm_uframes_t*/ n = snd_pcm_frames_to_bytes(pcm, err);
暂时不需要交叉编译driver,先把它放上来,以后可能会用到,到时候在完善^_^
交叉编译alsa-driver
$ cd ${PRJROOT}/build-tools
$ wget --passive-ftp ftp://ftp.alsa-project.org/pub/driver/alsa-driver-1.0.10.tar.bz2 && tar xvjf alsa-driver-1.0.10.tar.bz2 && cd alsa-driver-1.0.10
$ ./configure --with-cross=arm-linux- --host=i686-pc-linux --with-kernel=${PRJROOT}/kernel/linux-2.4.26 --prefix=${PREFIX_TARGET}
$ su -m
password:
# make install
试着编译openssl,出现一些问题,在网上找到,就转到这里了,根据情况做了些改动 :-)
经过几次的编辑修改,终于成功完成对mplayer的编译链接,一看mplayer文件的大小,10M,z这也太太夸张了吧,我还没编译成debug的呢。到目前为止这算是成功的第一步了。
2.开始调试
编译出来的代码能正常的在2410上跑吗?心中还是有许多疑问。给板子上电,然后用自己编写的一个网络传输工具将代码传到板子的ramdisk,接着再传上一个10M左右的视频,好了,先不带参数运行mplayer,不错,中文的帮助信息弹出来了,说明程序基本编译对了,这时输入命令 ./mplayer matrix.mpg , 眼睛直盯着屏幕,期待着画面的出现,可惜,在出现了一些视频剪辑的反馈信息后,程序再也不动了,没办法,按CTRL+C结束程序,然后就提示出现段错误。以前听说有linux嵌入式的爱好者移植时也出现这样的错误,但是如果不播放声音时,图像可以出现,于是输入命令 ./mplayer -nosound matrix.mpg,这时画面出来了,这个320x240大小的从网上下载的视频,播放起来相当流畅,好像比平时看的影碟机解码速度还快,那当然了,毕竟是320x240大小,又没声音解码的。
声音这块不解决,当然是不能说移植成功的,因为mplayer还支持那么多格式的音频解码。但是问题究竟出在哪里呢?用排除法吧!找一个未经任何音频压缩的WAV音频文件,其时就是PCM文件,上传到ramdisk,然后用mplayer播放,还是出现一样的问题,程序死了。好了,这就说明问题并非出现在音频解码部分,极有可能出现在音频流的播放部分。现在市面上大多数的嵌入式开发板的音频驱动是oss规范的驱动,以前自己做过oss的编程,对这块还是比较熟悉。于是开始查看mpalyer,c源文件,看看它是如何实现音频流播放的,
在音频播放部分它使用到了libao2库的音频播放/控制模块,通过进一步查看ao_oss.c源代码进一步获知mplayer是如何与音频的linux驱动工作的。这一步弄清楚后,重新编译mplayer,打开debug选项,打开调试字符串输出,并在音频播放处设置多处断点,并加上printf语句输出一些变量内容,最终发现在调用ao_oss.c的play()函数时出现除零出错,
这个问题产生的根源最终追溯到音频的驱动部分。现在大部分的嵌入式板子都使用菲利普uda1341音频芯片,因而也都使用了相同一个音频驱动,即MIZI公司拥有版权的linux uda1341音频驱动,这个驱动基本上符合了oss的规范,但是当使用到多段DMA音频数据传输时,出现了一个问题,即DMA缓冲的建立发生在第一次调用write()函数将音频数据传送到设备描述符的时候,然而oss驱动的调用者通常要在打开音频设备描述时候,就期望获取DMA缓冲的信息,然而因为缓冲尚未建立,因而返回缓冲大小为0这个结果。
解决的办法是在音频驱动源码的smdk2410_audio_open()函数体,加上如下一段代码,
if (!output_stream .buffers && audio_setup_buf(&output_stream))
return -ENOMEM;
添加的位置具体见以下代码的粗体部分:
static int smdk2410_audio_open(struct inode *inode, struct file *file)
{
int cold = !audio_active;
DPRINTK("audio_openn");
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
if (audio_rd_refcount || audio_wr_refcount)
return -EBUSY;
audio_rd_refcount++;
} else if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
if (audio_wr_refcount)
return -EBUSY;
audio_wr_refcount++;
} else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
if (audio_rd_refcount || audio_wr_refcount)
return -EBUSY;
audio_rd_refcount++;
audio_wr_refcount++;
} else
return -EINVAL;
if (cold) {
audio_rate = AUDIO_RATE_DEFAULT;
audio_channels = AUDIO_CHANNELS_DEFAULT;
audio_fragsize = AUDIO_FRAGSIZE_DEFAULT;
audio_nbfrags = AUDIO_NBFRAGS_DEFAULT;
if ((file->f_mode & FMODE_WRITE)){
init_s3c2410_iis_bus_tx();
audio_clear_buf(&output_stream);
// 加上以下这行代码
if (!output_stream .buffers && audio_setup_buf(&output_stream))
return -ENOMEM;
}
if ((file->f_mode & FMODE_READ)){
init_s3c2410_iis_bus_rx();
audio_clear_buf(&input_stream);
}
}
MOD_INC_USE_COUNT;
return 0;
}
改完驱动后,重新编译内核。
3. 结论
mplayer因为直接使用缓冲帧,或者使用别的什么优化的算法,使得在ARM S3C2410视频播放速度得到显著提高,至少在320x240大小,解压mpeg1或2标准的视频时速度是相当流畅的,但是mpeg4解码速度仍显不足。Arm s3c2410的cpu属于精简指令,定点计算,
无MMX,无硬件浮点计算,因而对大尺寸多媒体编解码的能力仍显不足。业界的解决办法是在CPU外增加硬编解码的DSP,或者在SOC内增加协处理器以加强这方面的功能。
后记
在得知xscale PXA255面世后,我决定用将移植好的mplayer拿给他们在板子上测试。mpeg4编码,画面大小为320x240的视频播放已经相当流畅,这也许就是那些市面上用PXA255 CPU做的PDA播放DIVX视频的效果吧!
构建嵌入式Linux系统-开发工具
一, 建立实际项目工作空间
工作环境配置脚本文件(develenv),内容如下:
#start------------------------------------------------------------------------------------
#! /bin/bash
#设置环境变量
export PROJECT=daq-module
export PRJROOT=~/control-project/${PROJECT}
export TARGET=arm-linux
export PREFIX=${PRJROOT}/tools
export TARGET_PREFIX=${PREFIX}/${TARGET}
export PATH=${PREFIX}/bin:${PATH}
#创建项目目录
mkdir ${PRJROOT} ${PRJROOT}/bootldr ${PRJROOT}/build-tools ${PRJROOT}/debug ${PRJROOT}/doc ${PRJROOT}/images ${PRJROOT}/kernel ${PRJROOT}/rootfs ${PRJROOT}/sysapps ${PRJROOT}/tmp ${PRJROOT}/tools
#创建build-tools目录
mkdir ${PRJROOT}/build-tools/build-binutils ${PRJROOT}/build-tools/build-boot-gcc ${PRJROOT}/build-tools/build-glibc ${PRJROOT}/build-tools/build-gcc
#创建工具链所需要的include目录
mkdir -p ${TARGET_PREFIX}/include
#根文件系统的基本结构
mkdir ${PRJROOT}/rootfs/bin ${PRJROOT}/rootfs/dev ${PRJROOT}/rootfs/etc ${PRJROOT}/rootfs/lib ${PRJROOT}/rootfs/proc ${PRJROOT}/rootfs/sbin ${PRJROOT}/rootfs/tmp ${PRJROOT}/rootfs/usr ${PRJROOT}/rootfs/var
chmod 1777 ${PRJROOT}/rootfs/tmp
mkdir ${PRJROOT}/rootfs/usr/bin ${PRJROOT}/rootfs/usr/lib ${PRJROOT}/rootfs/usr/sbin
mkdir ${PRJROOT}/rootfs/var/lib ${PRJROOT}/rootfs/var/lock ${PRJROOT}/rootfs/var/log ${PRJROOT}/rootfs/var/run ${PRJROOT}/rootfs/var/tmp ${PRJROOT}/rootfs/boot
chmod 1777 ${PRJROOT}/rootfs/var/tmp
#修改搜索路径:
export PATH=${PREFIX}/sbin:${PATH}
cd $PRJROOT
#end------------------------------------------------------------------------------------
二, GNU跨平台开发工具链
下载GNU工具链的各个组件: ftp://ftp.gnu.org/gnu
准备build-tools目录(见上面脚本)
目录中文件包括:binutils-2.10.1.tar.gz gcc-2.95.3.tar.gz glibc-2.2.3.tar.gz glibc-linuxthreads-2.2.3.tar.gz
建立工具链程序概述:
1.内核头文件的设置
2.二进制工具程序的设置
3.引导编译器的设置
4.C链接库的设置
5.完整编译器的设置
三, 内核头文件设置
内核下载:
将内核副本下载至${PRJROOT}/kernel目录.
$ tar xvzf linux-2.4.18.tar.gz 或 $ tar xvjf linux-2.4.18.tar.bz2
$ mv linux linux-2.4.18
$ cd linux-2.4.18
arm内核补丁
($ zcat ../patch-2.4.18-rmk5.gz | patch -p1)
$ make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig
配置好内核后,将内核头文件复制过去.
$ cp -r include/linux/ ${TARGET_PREFIX}/include
$ cp -r include/asm-arm/ ${TARGET_PREFIX}/include/asm
$ cp -r include/asm-generic/ ${TARGET_PREFIX}/include
注:本例使用的是arm目标板,如果使用ppc或i386目标板,则必须将asm-arm替换成asm-ppc或asm-i386.
四, binutils的设置
$ cd ${PRJROOT}/build-tools
$ tar xvzf binutils-2.10.1.tar.gz
产生一个binutils-2.10.1目录
$ cd build-binutils
$ ../binutils-2.10.1/configure --target=$TARGET --prefix=${PREFIX}
$ make
$ make install
查看一下安装结果是否正确:
$ ls ${PREFIX}/bin
五, 引导编译器的设置
$ cd ${PRJROOT}/build-tools
$ tar xvzf gcc-2.95.3.tar.gz
产生gcc-2.95.3目录
$ cd build-boot-gcc
$ ../gcc-2.95.3/configure --target=$TARGET --prefix=${PREFIX} --without-headers --with-newlib --enable-languages=c
$ make all-gcc
$ make install-gcc
检查一下${PREFIX}/bin的内容看是否安装成功,安装的编译器的文件名是arm-linux-gcc.
注: 原生gcc3.2及以上版本无法生成引导编译器,解决方式见后.
六, 链接库的设置
$ cd ${PRJROOT}/build-tools
$ tar xvzf glibc-2.2.3.tar.gz
$ tar xvzf glibc-linuxthreads-2.2.3.tar.gz --directory=glibc-2.2.3
$ cd build-glibc
$ CC=arm-linux-gcc ../glibc-2.2.3/configure --host=$TARGET --prefix="/usr" --enable-add-ons --with-headers=${TARGET_PREFIX}/include
$ make
$ make cross-compiling=yes install_root=${TARGET_PREFIX} prefix="" install
make时产生错误,install时产生两个error,解决方式见后.
$ cd ${TARGET_PREFIX}/lib
#备份libc.so文件
$ cp ./libc.so ./libc.so.orig
修改libc.so文件,将里面的绝对路径去掉,如: /lib/libc.so.6 --> libc.so.6
七, 完整编译器的设置
$ cd ${PRJROOT}/build-tools/build-gcc
$ ../gcc-2.95.3/configure --target=$TARGET --prefix=${PREFIX} --enable-languages=c,c++
$ make all
$ make install
八, 完成工具链的设置
$ cd ${PREFIX}/${TARGET}/bin
$ file as ar gcc ld nm ranlib strip
$ arm-linux-gcc -print-search-dirs
显示的信息:
install: /home/tim/control-project/daq-module/tools/lib/gcc-lib/arm-linux/2.95.3/
programs: /home/tim/control-project/daq-module/tools/lib/gcc-lib/arm-linux/2.95.3/:/home/tim/control-project/daq-module/tools/lib/gcc-lib/arm-linux/:/usr/lib/gcc/arm-linux/2.95.3/:/usr/lib/gcc/arm-linux/:/home/tim/control-project/daq-module/tools/arm-linux/bin/arm-linux/2.95.3/:/home/tim/control-project/daq-module/tools/arm-linux/bin/
libraries: /home/tim/control-project/daq-module/tools/lib/gcc-lib/arm-linux/2.95.3/:/usr/lib/gcc/arm-linux/2.95.3/:/home/tim/control-project/daq-module/tools/arm-linux/lib/arm-linux/2.95.3/:/home/tim/control-project/daq-module/tools/arm-linux/lib/
programs那一行的第一个条目就是${PREFIX}/lib/gcc-lib/arm-linux/2.95.3,此目录包含了gcc的链接库与工具程序.把二进制文件移往此目录,则交叉编译器就会使用它们,而不会使用原生的工具.
$ mv as ar gcc ld nm ranlib strip ${PREFIX}/lib/gcc-lib/arm-linux/2.95.3
$ for file in as ar gcc ld nm ranlib strip
> do
> ln -s ${PREFIX}/lib/gcc-lib/arm-linux/2.95.3/$file .
> done
我遇到的问题
Q:glibc编译错误如下:
error: `BUS_ISA' undeclared
A:参照
kernel-2.4.23以上的核心用CTL_BUS_ISA代替BUS_ISA
$ cp ${PRJROOT}/build-tools/glibc-2.2.3/sysdeps/unix/sysv/linux/arm/ioperm.c ${PRJROOT}/build-tools/glibc-2.2.3/sysdeps/unix/sysv/linux/arm/ioperm.c.orig
修改glibc源代码下的文件sysdeps/unix/sysv/linux/arm/ioperm.c
用CTL_BUS_ISA替换BUS_ISA
Q:glibc编译错误如下:
make -C manual subdir_install
make[2]: Entering directory `/home/tim/control-project/daq-module/build-tools/glibc-2.2.3/manual'
LANGUAGE=C LC_ALL=C makeinfo libc.texinfo
./stdio.texi:3269: First argument to cross-reference may not be empty.
./stdio.texi:3270: First argument to cross-reference may not be empty.
makeinfo: Removing output file `/home/tim/control-project/daq-module/build-tools/glibc-2.2.3/manual/libc.info' due to errors; use --force to preserve.
make[2]: *** [libc.info] Error 2
make[2]: Leaving directory `/home/tim/control-project/daq-module/build-tools/glibc-2.2.3/manual'
make[1]: *** [manual/subdir_install] Error 2
make[1]: Leaving directory `/home/tim/control-project/daq-module/build-tools/glibc-2.2.3'
make: *** [install] Error 2
A: 参考http://www.ctag.cn/blog/?q=node/22
修改stdio.texi文件之前作一下备份
$ cd ${PRJROOT}/build-tools/glibc-2.2.3/manual
$ cp stdio.texi stdio.texi.orig
Seems like I found the bug...
in libc's stdio.texi lines 2491 and 2492 the combination @ref{, is not allowed, I changed this to a valid first argument... seems like gcc has now started compiling, that probably means that libc was sucessful :-) *crossing fingers*
Sure.... But as I stated, this is not a "fix", it's a "hack" to make it work. I'ts in the documentation, and I think there is a very small chance anybody will look at that.
Untar the glibc-packet, patch it and re-tar before doing a "make".
diff -ur glibc-2.1.3 glibc-2.1.3.new/
diff -ur glibc-2.1.3/manual/stdio.texi glibc-2.1.3.new/manual/stdio.texi
--- glibc-2.1.3/manual/stdio.texi Wed Feb 23 08:02:56 2000
+++ glibc-2.1.3.new/manual/stdio.texi Sun Oct 6 14:46:39 2002
@@ -2487,8 +2487,10 @@
If you are trying to read input that doesn't match a single, fixed
pattern, you may be better off using a tool such as Flex to generate a
lexical scanner, or Bison to generate a parser, rather than using
-@code{scanf}. For more information about these tools, see @ref{, , ,
-flex.info, Flex: The Lexical Scanner Generator}, and @ref{, , ,
+@code{scanf}. For more information about these tools, see @ref{Low-Level
+I/O, , ,
+flex.info, Flex: The Lexical Scanner Generator}, and @ref{Low-Level I/O, ,
+,
bison.info, The Bison Reference Manual}.
Q: 编译无法进行,无法生成arm-linux-gcc.
A:使用gcc 3.2及以上的版本
$ cd ${PRJROOT}/build-tools
$ tar xvzf glibc-2.2.3.tar.gz
$ tar xvzf glibc-linuxthreads-2.2.3.tar.gz --directory=glibc-2.2.3
$ mkdir build-glibc-headers
$ cd build-glibc-headers
$ ../glibc-2.2.3/configure --host=$TARGET --prefix="/usr" --enable-add-ons --with-headers=${TARGET_PREFIX}/include
$ make cross-compiling=yes install_root=${TARGET_PREFIX} prefix="" install-headers
产生一个假的stubs.h文件:
$ mkdir -p ${TARGET_PREFIX}/include/gnu
$ touch ${TARGET_PREFIX}/include/gnu/stubs.h
接下来建立引导gcc编译器:
$ cd ${PRJROOT}/build-tools
$ tar xvzf gcc-2.95.3.tar.gz
产生gcc-2.95.3目录
$ cd build-boot-gcc
$ ../gcc-2.95.3/configure --target=$TARGET --prefix=${PREFIX} --disable-shared --with-headers=${TARGET_PREFIX}/include --with-newlib --enable-languages=c
$ make all-gcc
$ make install-gcc
Q: 提示缺少features.h文件.
A: 拷贝一个过去:
$ cp ${PRJROOT}/build-tools/glibc-2.2.3/include/features.h ${TARGET_PREFIX}/include
Q: 交叉编译程序出错
/lib/libc.so.6: In function `pthread_attr_init@@GLIBC_2.1':
/lib/libc.so.6(.text+0xda5f0): multiple definition of `pthread_attr_init@@GLIBC_2.1'
/home/tim/control-project/daq-module/tools/arm-linux/lib/libpthread.so(.text+0xac): first defined here
/lib/libc.so.6: In function `pthread_cond_broadcast@@GLIBC_2.3.2':
......
/home/tim/control-project/daq-module/tools/lib/gcc-lib/arm-linux/2.95.3/ld: cannot find /lib/libc_nonshared.a
......
A: 忘记修改libc.so文件 :( 怎么修改? 老大, 看看上面,对了,说一下,每次重新编译glibc并安装后,都要修改这个文件.
有的时候需要修改specs文件:
$ cd $PREFIX/lib/gcc-lib/arm-linux/2.95.3
$ emacs specs
将20行的/lib/ld-linux.so.2
修改为 {TARGET_PREFIX}/lib/ld-linux.so.2 (结合使用的系统,将环境变量换成真实路径)
MiniGUI-1.3.3在开发板上的移植.