显示标签为“linux”的博文。显示所有博文
显示标签为“linux”的博文。显示所有博文

2009年3月14日星期六

使用qemu调试arm linux内核

1.准备
安装qemu
下载内核文件 这里用2.6.27
建立交叉编译环境。
2.获取编译内核用的config文件
从qemu网站下载测试qemu用的文件http://www.nongnu.org/qemu/linux-user-test-0.3.tar.gz
tar zxvf linux-user-test-0.3.tar.gz
解压后,可以看到3个文件:arm_root.img zImage.integrator README
假设解压后的文件放在 /qemu-test目录下
在内核源代码的根目录下执行
./scripts/extract-ikconfig /qemu-test/zImage.integrator > qemu-linux_defconfig

结束后,将生成一个qemu-linux_defconfig配置文件

3.编译内核
cp qemu-linux_defconfig .config
make zImage

4.用qemu启动内核
qemu-system-arm -kernel zImage -initrd /qemu-test/arm_root.img / -redir tcp:9999::9999 -s -S

5.用gdb调试内核
假设运行qemu的机器的ip地址是192.168.1.5
arm-eabi-gdb vmlinux
在gdb的提示符下运行下面的命令:
target remote 192.168.1.5:1234
这时候就可以调试内核了。
比如设置断点
break start_kernel
查看寄存器
info registers
等等。。。

2009年3月1日星期日

用android build system 编译自己的init

在system文件夹下
建立一个myinit文件夹
编辑一个init.c文件
代码如下
#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
int i = 0;
while (1)
{
printf("hello world (%d)",i++);
sleep(2);
}
return 0;
}

另外建立一个Android.mk 文件,内容如下
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
init.c
LOCAL_MODULE:= init

LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)

LOCAL_STATIC_LIBRARIES := libcutils libc

#LOCAL_STATIC_LIBRARIES := libcutils libc libminui libpixelflinger_static
#LOCAL_STATIC_LIBRARIES += libminzip libunz libamend libmtdutils libmincrypt
#LOCAL_STATIC_LIBRARIES += libstdc++_static

include $(BUILD_EXECUTABLE)

在myinit文件夹下输入mm,
编译系统就会自动输出一个编译好的init程序
输出的路径也会提示出来。

用android build system 编译一个最小的android平台

首先按照
http://source.android.com/download
这个网站的方法配置系统
然后下载android平台文件
repo init -u git://android.git.kernel.org/platform/manifest.git
repo sync
在平台所在文件夹下运行
. build/envsetup.sh
然后运行
在build/core/main.mk文件中的
ifeq ($SDK_ONLY),true)行前面
添加SDK_ONLY := false
BUILD_TINY_ANDROID := true
保存。

在平台所在文件夹下,运行mm,系统将自动编译整个平台。
所生成的文件的存放路径也会提示出来。

如果提示和libpixelflinger 与hardware_legacy依赖相关的错误,
则修改
Android.mk中的LOCAL_SHARED_LIBRARIES
将hardware_legacy行去掉。

2009年2月26日星期四

android kernel 的toolchain

有两套toolchain可以编译android kernel。

让vim显示行尾的空格

fedora 9系统下
在/etc/vimrc文件添加如下两行
highlight WhitespaceEOL ctermbg=red guibg=red
match WhitespaceEOL /\s\+$/

2009年2月25日星期三

ARM ADR 伪指令用法

ADR指令用来获取操作数的地址。比如
ADR r4,b ; 取b的地址,放到r4中
LDR r0,[r4] ; 取b的值,放到r0中

2009年2月24日星期二

make xxx Is a directory. Stop. 的原因

编译内核时候的一个错误提示
make: ***    arm/kernel.git/arch/arm: Is a directory.  Stop.

这个错误是由在Makefile的 
ARCH ?= $(SUBARCH)
这行的后面多了一个空格造成的。
所以,在编辑Makefile时候,每行结尾,一定要确认没有空格,直接是换行。

2009年2月19日星期四

为linux建立最小的根文件系统

在编译内核时候,可以指定一个文件夹作为内核启动时候的根文件系统,linux中管这个文件系统叫做initramfs。

具体做法如下(以i386为例)

1.下载内核文件

  wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.26.tar.bz2

2.解压内核

   bzip2 -d linux-2.6.26.tar.bz2  生成一个linux-2.6.26.tar文件,然后

   tar xvf linux-2.6.26.tar 

   解压后,将有个linux-2.6.26文件夹存在

3.准备一个iniramfs文件系统的文件夹

  在linux-2.6.26文件夹下建立一个文件夹 myinitramfs

   写一个测试用的hello world,起名为hello.c,如下:

  #include

  #include

  int main(int argc,char *argv[])

  {

     int i = 0;

     while (1) {

      printf("hello world (%d)\n",i);

     }

    return 0;

   }

  编译  gcc -static -o init hello.c

  把init拷贝到myinitramfs文件夹下。

  cp init myinitramfs/

  由于需要显示文字,还需要在文件夹下准备console设备文件。

  mkdir myinitramfs/dev

  cp -a /dev/console myinitramfs/

4.编译内核

   在linux-2.6.26文件下下,执行make help。

   将看到很多帮助信息,其中有一项是 i386_defconfig

   执行 make i386_defconfig,将生成一个.config文件。

   为了把之前准备好的文件夹添加到内核配置文件中,还需要重新配置下config文件

   make config

    在 General Setup --->

    Initial RAM filesystem and RAM disk (initramfs/initrd) support (BLK_DEV_INITRD) [Y/n/?]

     Initramfs source file(s) (INITRAMFS_SOURCE) [myinitramfs]

   处,输入准备好的文件夹.

    配置好后,在.config文件中会有如下一条定义

   CONFIG_INITRAMFS_SOURCE="myinitramfs"

   保存.config

   make 编译内核

5.用qemu测试内核和initramfs

   qemu -kernel  linux-2.6.26/arch/i386/boot/bzImage  -initrd linux-2.6.26/usr/initramfs_data.cpio.gz  /dev/zero

   initramfs_data.cpio.gz 这个文件是内核自动生成的,具体名字可能不同的系统或者内核有差异,但是后缀应该是.cpio.gz


2008年7月13日星期日

linux usb设备驱动程序初探

想做USB设备驱动,必需的几点知识是:
  1. USB2.0协议规格,这个可以到www.usb.org网站下载,如果要做HID(人机接口设备)的话,还要看下hid的协议,也在该网站上。
  2. USB设备的工作方式,就是设备都会向主机提供那些信息
  3. linux如何发现USB设备,如何根据设备提供的信息搜索合适的驱动程序。
  4. linux驱动程序的开发方法,以及如何将驱动程序注册到linux系统中
1和2需要自己先学习,这个内容比较多,也比较复杂。
3呢,linux是通过Vendor ID和ProductID找到一个设备的驱动程序的。当一个usb设备插到系统上后,系统会自动向设备索取设备描述信息,这个信息里面有设备的类型,最大数据包,还有上面提到的venderID和ProductID。收到设备描述信息后,linux系统会根据ID信息在已经注册的驱动程序中搜索,如果发现匹配的驱动程序,就调用驱动程序的Probe函数。没有的话,就变成无法识别的设备。

为了有个感性的认识,举了USB驱动开发的例子。
系统情况: 内核版本是2.6.22
ubuntu系统。
USB设备是一个VendorID和ProductID分别为0x4500,0xdf10的USB键盘。

操作步骤:
到系统的/usr/src/linux-xxx的源代码目录下,打开driver/usb目录,里面有个usb-skeleton.c文件,这个是linux系统提供的usb设备驱动模板。
把这个文件拷贝到一个目录下,假设为/test_user。

打开这个模板文件,
找到
#define USB_SKEL_VENDOR_ID
#define USB_SKEL_PRODUCT_ID
两行,修改为
#define USB_SKEL_VENDOR_ID 0x4500
#define USB_SKEL_PRODUCT_ID 0xdf10

修改后,这个模板驱动程序实际上就可以被注册到linux中,并被调用。

首先编译这个驱动,
在模板文件所在目录,建立一个Makefile
内容为
obj-m := usb-skeleton.o
注意的是.o文件的名字和驱动源程序文件名字一定要一样。
然后用Make -C /usr/src/linux-headers-xxx/ M=`pwd` modules命令编译

结束后,会输出一个usb-skeleton.ko文件。

使用insmod usb-skeleton.ko将驱动加载到linux系统中。
加载后,将usb设备插到usb接口,这时候
dmesg |tail命令,就可以看到usb驱动输出的一些信息了。

下图是一个USB设备描述信息