[1] 一些常用函数接口/结构体
[
MKDEV(); #获得设备号 #32位 = major高12bit+次设备号低20bit
copy_to_user() #用户层 --> 内核层
copy_from_user() #内核层 --> 用户层
ioremap();
kmalloc();
readl(); #读寄存器
writel(); #写寄存器
MODULE_LICENSE()
printk()
struct class
struct device
struct file_operations
register_chrdev()
class_create()
device_create()
device_destroy()
class_destroy()
unregister_chrdev()
kfree()
iounmap()
module_init()
module_exit()
open()
write()
read()
close()
]
[2] 一些设备驱动常识
[
1>>/proc/devices #注册设备
]
字符设备实验
cdevice.c
字符设备实验
1:用户app.c输入"1"/"0"开关灯功能
=====================================================
======================cdevice.c开始======================
=====================================================
#include<linux/init.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/device.h>
#include <asm/errno.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/slab.h>
#define GPL2CON 0x11000100
#define GPL2DAT 0x11000104
#define CON_RESET 0x00000000
#define DAT_RESET 0x00
#define GPL2_0_OUT 0x1
#define GPL2_0_DATSET 0x1
MODULE_LICENSE("GPL");
struct cdev_led1 {
volatile unsigned long *gpl2con;
volatile unsigned long *gpl2dat;
char *name;
unsigned int major;
unsigned int minor;
struct class *cdev_led1_class;
struct device *cdev_led1_node;
##############注意结构体里面只能是指针
};
struct cdev_led1 *cled1;
ssize_t cdev_led1_read (struct file *, char __user *, size_t , loff_t *);
ssize_t cdev_led1_write (struct file *, const char __user *, size_t , loff_t *);
int cdev_led1_open (struct inode *, struct file *);
int cdev_led1_close (struct inode *, struct file *);
struct file_operations fops = {
.read = cdev_led1_read,
.write= cdev_led1_write,
.open= cdev_led1_open,
.release= cdev_led1_close
};
ssize_t cdev_led1_read (struct file *cdev1_file, char __user *cdev1_buf, size_t N, loff_t *offset)
{
int tem = 0;
copy_to_user(cdev1_buf, &tem, 1);
printk("\n__kernel__ :%s () is %d\n",__FUNCTION__,tem);
return 0;
}
ssize_t cdev_led1_write (struct file *cdev1_file, const char __user *cdev1_buf, size_t N, loff_t *offset)
{
printk("\n=====__kernel__ :%s in=====\n",__FUNCTION__);
unsigned int reg_vlu = 0;
char tem = ' ';
__copy_from_user(&tem, cdev1_buf,1);
printk("\n__kernel__ :cdev_led1_write() is %d\n",tem);
if(tem == '0')
{
reg_vlu = readl(cled1->gpl2con);
reg_vlu |= (GPL2_0_OUT << 0);
writel(reg_vlu,cled1->gpl2con);
reg_vlu = readl(cled1->gpl2dat);
reg_vlu &= ~(0x1<<0);
writel(reg_vlu,cled1->gpl2dat);
printk("\n__kernel__ :%s:close led\n",__FUNCTION__);
}
if(tem == '1')
{
reg_vlu = readl(cled1->gpl2con);
reg_vlu |= (GPL2_0_OUT << 0);
writel(reg_vlu,cled1->gpl2con);
reg_vlu = readl(cled1->gpl2dat);
reg_vlu |= (1<<0);
writel(reg_vlu,cled1->gpl2dat);
}
printk("\n=====__kernel__ :%s out=====\n",__FUNCTION__);
return 0;
}
int cdev_led1_open (struct inode *cdev1_inode, struct file *cdev1_file)
{
printk("\n=====__kernel__ :%s in=====\n",__FUNCTION__);
printk("\n=====__kernel__ :%s out=====\n",__FUNCTION__);
return 0;
}
int cdev_led1_close (struct inode *cdev1_inode, struct file *cdev1_file)
{
printk("\n=====__kernel__ :%s in=====\n",__FUNCTION__);
printk("\n=====__kernel__ :%s out=====\n",__FUNCTION__);
return 0;
}
static int cde_led1_init(void)
{
printk("\n=====__kernel__ :%s in=====\n",__FUNCTION__);
int ret = 0;
cled1 = kmalloc(sizeof(struct cdev_led1), GFP_KERNEL);
if(cled1 == NULL)
{
printk("\n kmalloc error\n");
goto err0;
}
cled1->major = 100;
cled1->minor = 1;
cled1->name = "cdev1";
cled1->gpl2con = ioremap(GPL2CON,8);
cled1->gpl2dat = cled1->gpl2con +1 ;
ret = register_chrdev(cled1->major,cled1->name,&fops);
if(ret == -ENOMEM)
{
printk("\n register_chrdev error\n");
goto err1;
}
cled1->cdev_led1_class = class_create(THIS_MODULE, "cdev_led1_class");
if(cled1->cdev_led1_class == NULL)
{
printk("\n class_create error\n");
goto err2;
}
cled1->cdev_led1_node = device_create(cled1->cdev_led1_class,NULL,MKDEV(cled1->major,cled1->minor), NULL, "cdev1");
if(cled1->cdev_led1_node == NULL)
{
printk("\n device_create error\n");
goto err3;
}
printk("\n=====__kernel__ :%s out=====\n",__FUNCTION__);
return 0;
err3:
device_destroy(cled1->cdev_led1_class,MKDEV(cled1->major,cled1->minor));
err2:
class_destroy(cled1->cdev_led1_class);
err1:
unregister_chrdev(cled1->major,cled1->name);
err0:
kfree(cled1);
}
static void cde_led1_exit(void)
{
printk("\n=====__kernel__ :%s in=====\n",__FUNCTION__);
device_destroy(cled1->cdev_led1_class,MKDEV(cled1->major,cled1->minor));
class_destroy(cled1->cdev_led1_class);
unregister_chrdev(cled1->major,cled1->name);
iounmap(cled1->gpl2con);
kfree(cled1);
printk("\n=====__kernel__ :%s out=====\n",__FUNCTION__);
}
module_init(cde_led1_init);
module_exit(cde_led1_exit);
=====================================================
======================cdevice.c结束======================
=====================================================
app.c
=====================================================
======================app.c======================
=====================================================
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
void main(int argc,char*argv[])
{
printf("\n=====__app__:in=====\n");
int ret,tem,fd = 0;
char ledstate;
ledstate = *(char*)argv[1];
fd = open("/dev/cdev1",O_RDWR);
if(fd == -1)
{
perror("\nopen error\n");
}
ret = write(fd,&ledstate,1);
if(ret == -1)
{
perror("\nwrite error\n");
}
ret = read(fd,&tem,1);
printf("\n__app__:read() is %d\n",tem);
if(ret == -1)
{
perror("\nread error\n");
}
close(fd);
printf("\n=====__app__:out=====\n");
}
Makefile
obj-m += cdevice.o #项目模块添加cdevice.o
KERNEL = /home/topeet/iTop4412_Kernel_3.0 #内核源码路径
EXE = app
GCC = /home/topeet/arm-2009q3/bin/arm-none-linux-gnueabi-gcc #编译工具路径
PWD = $(shell pwd) #当前路径
all:
make -C $(KERNEL) M=$(PWD) modules #生成驱动模块
$(GCC) app.c -o $(EXE) #编译应用层app.c
install:
cp cdevice.ko $(EXE) /home/topeet/minilinux/module_pro2/
#移动.ko 与app.exe到nfs共享目录
运行效果:
[root@iTOP-4412]# insmod cdevice.ko
[13858.429220]
[13858.429232] =====__kernel__ :cde_led1_init in=====
[13858.451033]
[13858.451045] =====__kernel__ :cde_led1_init out=====
[root@iTOP-4412]# ./app 1
=====__app__:in[13875.837426]
[13875.837445] =====__kernel__ :cdev_led1_open in=====
[13875.843701]
[13875.843715] =====__kernel__ :cdev_led1_open out=====
[13875.850172]
[13875.850187] =====__kernel__ :cdev_led1_write in=====
[13875.856456]
[13875.856468] __kernel__ :cdev_led1_write() is 49
[13875.862441]
[13875.862455] =====__kernel__ :cdev_led1_write out=====
[13875.869107]
[13875.869121] __kernel__ :cdev_led1_read () is 0
[13875.875346]
[13875.875362] =====__kernel__ :cdev_led1_close in=====
[13875.881371]
[13875.881385] =====__kernel__ :cdev_led1_close out=====
=====
__app__:read() is 0
=====__app__:out=====
[root@iTOP-4412]# ./app 0
=====__app__:in[13884.293018]
[13884.293038] =====__kernel__ :cdev_led1_open in=====
=====
[13884.304336]
[13884.304353] =====__kernel__ :cdev_led1_open out=====
[13884.310212]
[13884.310229] =====__kernel__ :cdev_led1_write in=====
[13884.315987]
[13884.316000] __kernel__ :cdev_led1_write() is 48
[13884.321859]
[13884.321872] __kernel__ :cdev_led1_write:close led
[13884.328097]
[13884.328111] =====__kernel__ :cdev_led1_write out=====
[13884.334619]
[13884.334632] __kernel__ :cdev_led1_read () is 0
__app__:read() is[13884.350304]
[13884.350320] =====__kernel__ :cdev_led1_close in=====
0
[13884.365071]
[13884.365086] =====__kernel__ :cdev_led1_close out=====
=====__app__:out=====
[root@iTOP-4412]# rmmod cdevice
[13917.257985]
[13917.258003] =====__kernel__ :cde_led1_exit in=====
[13917.277571]
[13917.277588] =====__kernel__ :cde_led1_exit out=====
[root@iTOP-4412]#