android平台下编译KO文件

来源:互联网 发布:mysql 5.0.45中文版 编辑:程序博客网 时间:2024/05/22 12:45

横线下是别人的方法当初参考的,但是没有执行成功,我实验的是RK3066平台的,

最后发现了解决方法,其实很简单主要是两个步骤:

1.

make file里要指定模块编译

例如

obj-m += lkt401.o 编译(LKT401.C文件)

2. 要用命令 make  modules

就可以了在目录下会发现LKT401.KO文件

--------------------------------------------------

X86平台下编译,操作,运行:

Linux驱动程序:

> 1.建立一个firstqd目录,在此目录建立驱动设备源文件(.C文件)firstqd.c ,

       2.在同一目录下建立Makefile 文件

       3.同一目录建立驱动设备测试源文件(.C 文件)test.c

       4.以上三文件建立并编写完毕后.在该目录下用make命令进行编译,如果没有错误就会生成.ko文件以及一些中间文件.

>/proc/devices下查看是否有相应的设备号存在;命令: cat /proc/devices (设备号指的是设备驱动源文件里面定义的设备号,firstqd.c下定义的.通常情况下不允许有相同的设备号出现.也可以先查看设备号再去设置设备号.)

>/dev下建立相应的设备结点(设备名,firstqd.c下定义)

Mknod /dev/(设备name,firstqd.c下定义)  c  221(主设备号)  0(次设备号) (主次设备号均在firstqd.c下定义).

>insmod 命令来挂载设备到内核中;命令: insmod firstqd.ko (make的时候产生)

>gcc命令来编译测试源文件,生成可执行文件;命令 gcc –o test test.c

> ./执行可执行文件;命令: ./test

>dmesg查看内核日志.

> 若对原文件做出更改,需把已挂载的驱动卸载再挂载更改的驱动;命令: rmmod (设备名)

源程序代码如下:

Firstqd源程序代码(firstqd.c):

#include <linux/init.h>

#include <linux/module.h>

#include <linux/cdev.h>

#include <linux/fs.h>

#include <linux/types.h>

#include <linux/kernel.h>

#include <linux/uaccess.h>

#include <asm/io.h> 

#define DEVICENAME  "aaa"            //    设备名

unsigned int major=221;                   //主设备号

unsigned int minor=0;                            //次设备号

struct cdev *abc;

dev_t dev;

static char bufrh[1024]="read success!";

char bufkernel[1024];

 #define SEG_LED  0x10500000

//unsigned long * Led_Address;

 static int aaaaa_open(struct inode *inodep, struct file *filep)

{

      printk("read success!\n");

     return 0;

} 

int aaaaa_release(struct inode *inodep, struct file *filep)

{

        return 0;

}

static ssize_t aaaaa_read (struct file *filep, char __user *buf, size_t const count, loff_t *offset)

{

      if(copy_to_user(buf, bufrh, count))

            {

                  printk("copy_to_user fail!\n");

                        return -EFAULT;

            }

        return count ;

}

 

ssize_t aaaaa_write (struct file *filep, const char __user *buf,  size_t count, loff_t *offse)

{

      if(copy_from_user(bufkernel,buf,count))

      {

            printk("copy_from user fail");

                return -EFAULT;

         }

 

         printk("write:%s\n",bufkernel);

          // writew(bufkernel,Led_Address);

             

         return count;

             

}

static const struct  file_operations fops = {

      .owner = THIS_MODULE,

      .open = aaaaa_open,

      .release= aaaaa_release,

      .read = aaaaa_read,

      .write =aaaaa_write,

};

static int __init aaaaa_init(void)

{

      //Led_Address=ioremap(SEG_LED, 4);

       int a;

      dev=MKDEV(major, minor);

       a=register_chrdev_region(dev, 1, DEVICENAME);

       

      abc=cdev_alloc();

      abc->owner=THIS_MODULE;

      cdev_init(abc, &fops);

     

      cdev_add(abc, dev, 1);

 

      printk("begin");

      return 0;

}

static void __exit  aaaaa_cleanup(void)

{

      cdev_del(abc);

      unregister_chrdev_region(dev, 1);

        printk("goodbye !");

}

module_init(aaaaa_init);

module_exit(aaaaa_cleanup);

MODULE_LICENSE("GPL ");

Test源程序代码(test.c):

#include <stdio.h>

#include <sys/types.h>

#include <fcntl.h>

char buf[1024];

char bufw[1024]="write!!!";

int main()

{

      int fd,m,n;

      fd=open("/dev/aaa",O_RDWR);

      if (fd)

        {

            m=read(fd,buf,100);

            printf("read kernel:%s\n",buf);

 

            n=write(fd,bufw,10);

         }

      return  0;

}

Makefile代码:

obj-m += firstqd.o

 

KERDIR =/usr/src/linux-headers-2.6.32-24-generic #不同内核版本,,目录不同,因内核而异.

#KERDIR=/home/linux2.6/linux  #arm平台

PWD=$(shell pwd)

modules:

      $(MAKE) -C $(KERDIR) M=$(PWD)  modules

clean:

      rm -rf *.o *~core .depend *.cmd *.ko *.mod.c *.tmp_versions

pc:

      gcc -o test test.c

arm:

      arm-linux-gcc -o test test.c 

X86平台操作,编译,最终运行在ARM平台下:


*如何才能把驱动运行在ARM平台下呢?

以上的均是运行在X86平台下的设备驱动,若想运行在ARM平台下,则必须要生成ARM平台所需要的文件格式(ARM).

 

*如何才能产生(ARM平台下能运行的二进制文件)?

这就要通过交叉编译工具链来实现, arm-linux-gcc –o test test.c 产生的test可执行程序是运行在ARM平台下的.

好了,现在test测试文件可以运行在ARM平台下了,firstqd.ko(设备驱动文件)?

这就要求修改Makefile文件和内核顶层Makefile的交叉编译目录路径了,以下是详细步骤:

选择要下载到开发板上的内核,我选的是linux-3.0.8版本的内核 在该内核顶层目录下make会产生zImage内核镜像文件在_.../arch/arm/boot/_目录下.zImage是下载到开发板上的镜像文件.所以,要在Makefile文件下修改KERDIR 的目录为该内核的目录路径.

 

*内核顶层Makefile修改:

修改前:

 

 

修改后:

:CROSS_COMPLILE 为你的交叉编译工具链的bin的目录路径后面要加上arm-linux-,否则会出错 特别注意的识在arm-linux-后不得有空格,否则会报错:找不到文件。我曾被这一问题困扰了一个下午。特别要注意啦!!

修改完毕后,在顶层目录make 一下.(可能会报错,因为只修改了Makefile文件,报错就make menuconfig做些改动再make)

产生新的使用于 ARM平台下 zImage文件在/arch/arm/boot目录路径下.

zImage下载到开发板上.(内核烧写不在此讨论范围内) 

Firstqd目录下的Makefile修改:

obj-m += firstqd.o 

#KERDIR =/usr/src/linux-headers-2.6.32-24-generic //x86平台

KERDIR= usr/local/arm/linuxDrivers/kernel/linux-3.0.8/ #arm平台下,该目录路径为你的要下载到开发板上的内核目录路径

PWD=$(shell pwd) 

modules:

      $(MAKE) -C $(KERDIR) M=$(PWD)  modules

clean:

      rm -rf *.o *~core .depend *.cmd *.ko *.mod.c *.tmp_versions 

pc:

      gcc -o test test.c

arm:

      arm-linux-gcc -o test test.c

make 命令,产生的firstqd.ko文件为ARM平台下的属性文件

要确认是否为ARM平台的还是为X86平台的,用命令file +文件名



以上是x86平台所能运行的二进制代码。


以上是ARM平台上所能运行的二进制代码。


 

firstqd.ko test 文件下载到开发板的内核上.在开发板上的内核进行挂载,查看内核日志,卸载等等的操作.这里与X86平台操作基本相同,这里不再累述!


原创粉丝点击