横线下是别人的方法当初参考的,但是没有执行成功,我实验的是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 +文件名.
把firstqd.ko test 文件下载到开发板的内核上.在开发板上的内核进行挂载,查看内核日志,卸载等等的操作.这里与X86平台操作基本相同,这里不再累述!