Weichuan 的个人资料who怕who-Blue Pathway照片日志列表更多 ![]() | 帮助 |
who怕who-Blue Pathway动态库优化——Prelink(预连接)技术(转载)Prelink是Red Hat 开发者 Jakub Jelinek 所设计的工具,正如其名字所示,Prelink利用事先链接代替运行时链接的方法来加速共享库的加载,它不仅可以加快起动速度,还可以减少部分内存开销,是各种Linux架构上用于减少程序加载时间、缩短系统启动时间和加快应用程序启动的很受欢迎的一个工具。 我们在上一章中详细介绍了动态链接和加载的过程,这种运行时的动态链接尤其是重定位(relocation)的开销对于大型系统来说是很大的。相比之下,早期UNIX下的a.out格式的老式链接方法在速度和占用内存方面有明显的优势(但不如ELF格式更灵活,能方便的构建动态共享库)。Prelink工具是试图在保持一部分灵活性的基础上,借鉴a.out格式在速度和占用内存方面的优点,对ELF文件进行一些改进。 事实上,Prelink工具的原理主要基于这样一个事实:动态链接和加载的过程开销很大,并且在大多数的系统上, 函数库并不会常常被更动, 每次程序被执行时所进行的链接动作都是完全相同的,对于嵌入式系统来说尤其如此。因此,这一过程可以改在运行时之前就可以预先处理好,即花一些时间利用Prelink工具对动态共享库和可执行文件进行处理,修改这些二进制文件并加入相应的重定位等信息,节约了本来在程序启动时的比较耗时的查询函数地址等工作,这样可以减少程序启动的时间,同时也减少了内存的耗用。 Prelink的这种做法当然也有代价:我们每次更新动态共享库时,相关的可执行文件都需要重新执行一遍Prelink才能保证有效,因为新的共享库中的符号信息、地址等很可能与原来的已经不同了。这种代价对于嵌入式系统的开发者来说可能稍微带来一些复杂度,不过好在对用户来说几乎是可以忽略的。 更多有关Prelink的具体做法和细节读者可以参考Prelink的开发者 Jakub Jelinek的专文介绍:http://people.redhat.com/jakub/prelink/prelink.pdf。 很多Linux的发行版上已经预装了或者已经使用了Prelink工具,不过我们需要专门的针对嵌入式体系,比如ARM的版本,这样我们需要到Red Hat的网站下载源代码并重新编译。下载地址是:http://people.redhat.com/jakub/prelink/ 编译时主要是configure时设定--host参数,注意它是一个用于主机而不是开发板上的工具,不要用arm-linux-gcc编译它,如下所示:
Prelink工具的使用非常简单,对一个系统来说可能要花几分钟或者十几分钟。一般来说我们不用在命令行中直接指定ELF文件的方式,而是将需要Prelink的文件写到配置文件/etc/prelink.conf中,然后使用下面的命令即可:
如果你要取消已经做了的Prelink也非常简单,运行:
Prelink常用的选项含义如下: 下面是一份/etc/prelink.conf文件的示例:
其中以”#”开头的行为注释,正如注释中所解释的,下面列出的文件目录分别可以有”-l”, “-h”和”-b”开头,”-l”和“-h”区分是否包括符号连接类型的目录,”-b”指黑名单,即应该排除出去的部分。 你可能会在Prelink时遇到类似这样的错误:"Cannot prelink against non-PIC shared library" 。 这是因为有些库没有使用 -fPIC gcc 选项编译。PIC指Postion Independent Code,即位置无关代码,是动态链接的一项技术,也是Prelink的前提条件。这种问题只需要用-fPIC重新编译代码就可以了。 根据笔者的经验,如果你的嵌入式系统中动态库过多过慢是系统性能的瓶颈之一,推荐你试试Prelink的方法。在笔者工作的平台上,它是非常行之有效的,让大多数应用的启动时间及系统启动时间都有了显著的提升。 Android应用程序的资料(转载)Android应用程序的资料 与glibc相比,Bionic Libc有如下一些特点: - 采用BSD License,而不是glibc的GPL License; - 大小只有大约200k,比glibc差不多小一半,且比glibc更快; - 实现了一个更小、更快的pthread; - 提供了一些Android所需要的重要函数,如”getprop”, “LOGI”等; - 不完全支持POSIX标准,比如C++ exceptions,wide chars等; - 不提供libthread_db 和 libm的实现
另外,Android中所用的其他一些二进制工具也比较特殊: - 加载动态库时使用的是/system/bin/linker而不是常用的/lib/ld.so; - prelink工具不是常用的prelink而是apriori,其源代码位于” <your_android>/build/tools/apriori” - strip工具也没有采用常用的strip,即“<your_android>/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin”目录下的arm-eabi-strip,而是位于<your_android>/ Android WiFi配置与使用Android WiFi配置与使用 作者:yanweichuan 邮箱:yanweichuan@163.com
1. 验证WiFi驱动
建立一个普通的嵌入式Linux,下载编译WiFi工具wpa_supplicant,验证WiFi的驱动是否工作正常。顺便学习wpa_supplicant的用法,浏览一下wpa_supplicant的源代码。Android中WiFi的管理工具就是wpa_supplicant。 wpa_supplicant下载地址: http://hostap.epitest.fi/wpa_supplicant/ 参考用法: a) 建立/etc/wpa_suppliant的配置文件。 参考配置: ctrl_interface=/var/run/wpa_supplicant # eapol_version=1 ap_scan=1 fast_reauth=1
# Only WPA-PSK is used. Any valid cipher combination is accepted. network={ ssid="AP007" proto=WPA key_mgmt=WPA-PSK pairwise=CCMP TKIP group=CCMP TKIP WEP104 WEP40 psk="123456" priority=2 } 注意,确保系统中有/var/run目录,否则一直失败。更改ssid和psk为具体的设置。 b) 运行wpa_supplicant wpa_supplicant –d -c/etc/wpa_supplicant.conf -iwlan0 –Dwext wpa_supplicant以daemon的方式在后台运行: wpa_supplicant -B -c/etc/wpa_supplicant.conf -iwlan0 -Dwext 运行成功后,ifconfig wlan0即可看到WiFi网卡的信息。一定要注意,wlan0要改成WiFi驱动中对应的名字,每个驱动可能是使用的名字不一样,比如G1就是用的tiwlan0。另外,如果你的WiFi在supplicant中有标准支持(driver_***.c),可以将-Dwext换成对应的配置,例如用madwifi,就可以用-Dmadwifi。如果没有支持,则使用标准的通用的-Dwext。在G1中,使用的是TI的WiFi芯片,所以G1提供了自己的system/wlan/ti/wpa_supplicant_lib/driver_ti.c,这个是个很好的参考,wext部分实现不完整,要参考这个来完成。 c) 获取IP地址 udhcpc –i wlan0 ifconfig wlan0即可看到获取的IP地址。如果没有成功,检查无线AP是否配置成DHCP server。 d) 验证网络状况 用ping或者wget来验证一下网络是否联通。 至此,WiFi的工作状态验证完毕,如果不能连通网络,后面的Android上的调试基本不大可能成功。也不建议直接用Android的wpa_supplicant来调试WiFi,因为Android的命令行toolbox实在是不能busybox相比,加上 Android的WiFi service相当复杂,而且整个启动也很费时间。
2 Android WiFi
2.1 Android WiFi驱动的准备 在第1节中都已经成功的验证了WiFi,还有什么要准备的呢?因为Android中对WiFi的驱动有特殊要求,后面的大部分改动都是围绕这个要求来改动的。Linux中驱动可以直接编译进内核,也可以编译成模块。在第一节中我没有特殊说明,那种都可以,只要你驱动加载成功了就行。在Android中默认的是使用模块方式。因为WiFi是耗电大户,电池使用的长短直接关系到手持设备的正常使用。Android在WiFi disable的时候是彻底的把WiFi驱动卸载掉来省电。所以使用了模块方式。 另外一个问题也很重要,一般的WiFi都是使用了“驱动+firmware”的方式,也就是在加载驱动的同时要下载firmware,这个在bring up Android WiFi的时候会造成一些麻烦。除非你也用的是G1中的那款TI的芯片,那就一切OK。Linux内核中,专门有个firmware的loader子模块,在驱动加载时,只要将firmware的文件名传进去,firmware loader会把firmware的内容加载到内核空间的。Android中insmod命令很弱的,不能带参数,这样就没有办法在插入时候把firmware的文件名传进去。Android针对TI的WiFi firmware写了个wlan_loader,代码在system/wlan/ti /sta_dk_4_0_4_32/CUDK/tiwlan_loader.c。这个wlan_loader就做了一件事,就是下载firmware,设置WiFi的状态为“OK”。如果符合Android的架构,我们自己也要写这么个loader。但是,这个loader的支持是需要dirver配合的,太麻烦,把这一步骗过去就成。找个工具将firwmare bin转成对应的数组,替换掉driver中的firmware loader装载。这样就省去了wlan_loader。修改成功后,最好用第1节的方法验证下。
2.2 编译Android wpa_supplicant (待续...) Android移植(U-Boot) 领到一块公司的板子
CPU: PXA270
Flash:64M NOR
SD卡,LCD,USB ... 没有网口(痛苦的开始)
下载最新的u-boot稳定版,选用include/configs/trizepsiv.h的配置,检查一下UART的相关GPIO的配置,用EABI编译,JTAG下载,上电没反映。
将编译器换成普通的arm-linux-gcc 3.2的版本,编译,发现比EABI的要大几K,重新下载,上电,串口OK。
接下来调试FLASH和SD卡,没有网口,只能通过SD来拷贝内核和文件系统了。
U-Boot要支持SD卡,首先在CONFIG_MMC,要为SD配置一系列的GPIO,PXA270的GPIO都是复用的,有最多3种的功能选项,要对照SPEC把SD相关的GPIO都选择到SD 的工作模式。下载后,运行mmcinit初始化SD卡,没反映。把MMC的debug打开,提示不支持AP_CMD,郁闷。问硬件的同事得知板子上使用PMIC电源管理芯片,对每个外设单独控制供电。配置电源MMC的电源使能GOIO,再运行mmcinit,没错误,没反映,再运行一次,终于提示找到了SD卡...
FLASH由两片32MB的组成,修改bank数和size。在protect off all后erase all提示flash是locked,不能erase,这是因为protect off 命令只是简单的把flash info中的数据结构中的状态改成unlock,并没有实际的执行unlock,要添加 #define CFG_FLASH_PROTECTION, 让protect off实际的对flash进行unlock。
增加对FAT文件系统的支持,这样就可以通过fatload命令从SD卡中读kernel和ramdisk,不用每次都烧flash。缺少网卡的支持,开发速度会很受影响了......
U-Boot都搞了很多遍,每次板子不同,多少有些小问题要调整。看了下目录树结构,似乎U-Boot的代码结构有些调整,支持的平台多了,新增了许多功能,有空再研究。 Android Porting(Touch Screen)I found there are so many questions of touch screen aksed by Android engineers, I have made the wm9713 touch screen work OK, so shared my experience out. This blog page is written by English, hope all engineers can read it.
Hardware: PXA270, wm9713 touch screen, LCD 480x272
My kernel is the offical kernel from Android(2.6.25), but it does not support the wm97xx touch screen. It is luck that the kernel 2.6.26 is merged the wm97xx touch screen driver. So I should porting the wm97xx touch screen driver from 2.6.26 to 2.6.25.
First step, diff the other touch screen drivers in drivers/input/touchscreen, I found there are almost no changes, so it is safe to copy the wm97xx drivers from 2.6.26 to 2.6.25. Modify the drivers/input/touchscreen/Kconfig and Makefile, copy the linux/wm97xx.h. But there is anothor problem, the wm9713 touch screen is dependent the AC97, so the AC97 sound bus should be configured. It is easy to complie the driver successfully.(the mainstone accelate driver does not compiled in ... it is the result of many tries!)
Booting the kernel, the device for touch screen can be foud in /dev/event1 (event0 for the keypad). Write a test program for touch screen:
#include <stdio.h>
#include <unistd.h> #include <sys/types.h> #include <fcntl.h> #include <linux/input.h> #define TS_DEV "/dev/event1"
static int ts_fd = -1;
static int init_device() { if((ts_fd = open(TS_DEV, O_RDONLY)) < 0) { printf("Error open %s\n", TS_DEV); return -1; } return ts_fd;
} int main()
{ int i; struct input_event data;
if(init_device() < 0)
return -1; while(1)
{ read(ts_fd, &data, sizeof(data)); if (data.type == EV_KEY) { printf("type: EV_KEY, event = %s, value = %d\n", data.code == BTN_TOUCH ? "BTN_TOUCH" : "Unkown", data.value); } else if(data.type == EV_ABS) { printf("type: EV_ABS, event = %s, value = %d\n", data.code == ABS_X ? "ABS_X" : data.code == ABS_Y ? "ABS_Y" : data.code == ABS_PRESSURE ? "ABS_PRESSURE" : "Unkown", data.value); } else if (data.type == EV_SYN) { printf("type: EV_SYN, event = %s, value = %d\n", data.code == SYN_REPORT ? "SYN_REPORT" : "Unkown", data.value); } else { printf("type: 0x%x, event = 0x%x, value = %d\n", data.type, data.code, data.value);
} } return 0;
} The test program can catch the touch screen data(x, y, pressure), the dirver seems work ok.
Run the Android system, but the system does not response to the touch screen ....
According to the Google search, check /dev/input/event1, /proc/bus/input/devices ... all seem OK.
Some very important hints from the talk between two Android hackers: http://androidzaurus.seesaa.net/article/90045743.html
And some important words: "It seems Android wants to know not only pressure becomes zero but also pendown becomes zero. Only two lines but very precious lines." from http://androidzaurus.seesaa.net/article/96581331.html
So check my driver and test again.
the test program reports that the X Y coordinate is very large(350-3900 for X, 320-3750 for Y, defined in driver), but the LCD is 480x270, and the Adroid use the abusolute touch screen coordinate, which is same to LCD. calibrate should be done, but the Android doe not do this.
Download the tslib-1.4.tar.gz, compile, run the ts_calibrate, and run ts_test, the touch screen works OK. and calibrate coefficent is record in /etc/pointercal.
But how to use the calibrate result for Android? Confused for hours ... I cann't change the Adroid input action, so I should do the calibrate in my driver. Reading the tslib source code, got the idea. I found a formula in tslib/plugins/linear.c
xtemp = samp->x; ytemp = samp->y;
samp->x = ( lin->a[2] + lin->a[0]*xtemp + lin->a[1]*ytemp ) / lin->a[6]; samp->y = ( lin->a[5] + lin->a[3]*xtemp + lin->a[4]*ytemp ) / lin->a[6]; and the lin->a[] is read from the /etc/pointercal. But the division "/" is hard for Linux kernel. Surprised that the a[6] is 65536, and can do the /65536 by >>16. Coding in wm9713 driver: drivers/input/touchscreen/wm97xx-core.c, function: static int wm97xx_read_samples(struct wm97xx *wm)
define the coeficient table, change the last variable valure from 65536 to 16.
int axis_table[] = {-8360, 32, 32753552, 24, 4983, -1685240, 16}; // from /etc/pointercal by ts_calibrate
#ifdef TS_ABS_XY
int xraw, yraw, xtmp, ytmp; dev_dbg(wm->dev,
"pen down: x=%x:%d, y=%x:%d, pressure=%x:%d\n", data.x >> 12, data.x & 0xfff, data.y >> 12, data.y & 0xfff, data.p >> 12, data.p & 0xfff); xraw = (data.x & 0xfff); yraw = (data.y & 0xfff); xtmp = (axis_table[2] + axis_table[0]*xraw + axis_table[1]*yraw ) >> axis_table[6]; ytmp = (axis_table[5] + axis_table[3]*xraw + axis_table[4]*yraw ) >> axis_table[6]; input_report_abs(wm->input_dev, ABS_X, xtmp); input_report_abs(wm->input_dev, ABS_Y, ytmp); #else input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff); input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff); #endif Run the test program again, it is great that the touch screen coordinate is same to the LCD, Run Android system, but the system does not response to the touch screen. Hear broken ...
Check driver, input_report_key... is not added according to http://androidzaurus.seesaa.net/article/96581331.html
(1)
if (rc & RC_PENUP) {
if (wm->pen_is_down) { wm->pen_is_down = 0; dev_dbg(wm->dev, "pen up\n"); input_report_abs(wm->input_dev, ABS_PRESSURE, 0); input_report_key(wm->input_dev, BTN_TOUCH, wm->pen_is_down); input_sync(wm->input_dev); (2)
input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff);
wm->pen_is_down = 1; input_report_key(wm->input_dev, BTN_TOUCH, wm->pen_is_down); input_sync(wm->input_dev); Run test program again, but can't catch the EV_KEY event, confused ... trace the kernel source code, found some bit map should be masked.
and in static int wm97xx_probe(struct device *dev)
set_bit(EV_ABS, wm->input_dev->evbit);
set_bit(ABS_X, wm->input_dev->absbit); set_bit(ABS_Y, wm->input_dev->absbit); set_bit(ABS_PRESSURE, wm->input_dev->absbit); so, the bit mask should be done for EV_KEY set_bit(EV_KEY, wm->input_dev->evbit);
set_bit(BTN_TOUCH, wm->input_dev->keybit); Run the test program, the EV_KEY can be catched now. Run Android, touch the screen, the icon can be actived by touch... great successfully ...
Good lucky to all Android workers!
|
|
||||||||
|
|