chardev.c
#include <linux/module.h> //模块化的相关头文件
#include <linux/init.h> //初始化的相关头文件
#include <linux/fs.h> //文件操作集合
#include <linux/uaccess.h>//copy_to_user的头文件
#include <linux/kdev_t.h> //MKDEV所需要的头文件
#include <linux/cdev.h> //cdev结构体以及cdev-init
#include <linux/device.h> //class_create,device_create
#include <linux/io.h> //寄存器
#define GPIO5_DR 0x20AC000 //蜂鸣器Io物
unsigned int* gpio5_1; //虚拟地址
#define SIZEBEY 4 //寄存器字节
#define GPIO3_DR 0x209C000 //LED2 Io物理地址
unsigned int* gpio3_3; //虚拟地址
struct cdev class16_cdev; //cdev结构体用来表示字符设备
struct class * class16; //class类
struct device * class16device; //device 设备结构体
dev_t char_dev;
ssize_t chartest_read(struct file *file, char __user *ubuf, size_t size, loff_t *loff_t){
char kbuf[]="Hello World!";
if(copy_to_user(ubuf, kbuf, strlen(kbuf)) != 0) //将内核数据复制到用户空间 kbuf 的数据复制到 ubuf 里
{
printk("chartest_read error\n");
return 0;
}
printk("chartest_read success!\n");
return 0;
}
ssize_t chartest_write(struct file *file, const char __user *ubuf, size_t size, loff_t *loff_t){
char kbuf[64]={0};
if(copy_from_user(kbuf,ubuf,size)!=0){ //将用户数据复制到内核空间 ubuf 的数据复制到 kbuf 里
printk("chartest_write error\n");
return 0;
}
if( kbuf[0] == 1 ){
*gpio5_1 |= (1 << 1);
}else if( kbuf[0] == 0 ){
*gpio5_1 &= ~(1 << 1);
}
printk("chartest_write success\n");
printk("chartest_write kbuf is %s",kbuf);
return 0;
}
int chartest_open (struct inode *inode, struct file *file){
printk("chartest_open\n");
return 0;
}
int chartest_release (struct inode *inode, struct file *file){
printk("chartest_release\n");
return 0;
}
struct file_operations chartest_fops={
.owner =THIS_MODULE,
.open =chartest_open,
.release =chartest_release,
.read =chartest_read,
.write =chartest_write,
};
static int chartest_init(void)
{
int ret;
/*
/*******************静态注册设备号***********************/
char_dev = MKDEV(100,10);
ret = register_chrdev_region(char_dev, 1, "class16");
if(ret!=0)
{
printk("register_chrdev_region error\n");
return 0;
}*/
/*******************动态注册设备号***********************/
ret = alloc_chrdev_region(char_dev,0,1,class16);
if( ret != 0 ){
printk("alloc_chrdev_region: register_chrdev_region error!!\n");
return ret;
}
printk("alloc_chrdev_region: register_chrdev_region ok!!\n");
printk("MAJOR %d\n\n",MAJOR(char_dev));
printk("MINOR %d\n\n",MINOR(char_dev));
/*内存映射*/
gpio5_1 = ioremap(GPIO5_DR, SIZEBEY);
if( gpio5_1 == NULL ){
printk("ioremap error!!\n");
return 0;
}
/*内存映射*/
gpio3_3 = ioremap(GPIO3_DR, SIZEBEY);
if( gpio3_3 == NULL ){
printk("ioremap error3!!\n");
return 0;
}
//初始化cdev
class16_cdev.owner=THIS_MODULE;
cdev_init(&class16_cdev,&chartest_fops);
//向内核注册设备
cdev_add(&class16_cdev,char_dev,1);
//创建类,在sys/class下
class16=class_create(THIS_MODULE,"LCDchar");
//自动创建设备,在/dev下生成设备节点
class16device=device_create(class16,NULL,char_dev,NULL,"LCDdevice");
printk("chartest_init!!!\n");
return 0;
}
static void chartest_exit(void)
{
iounmap(gpio5_1);
iounmap(gpio3_3);
unregister_chrdev_region(char_dev,1); //注销设备号
cdev_del(&class16_cdev); //删除设备
device_destroy(class16, char_dev); //注销设备
class_destroy(class16); //删除类
printk("bye!!!\n");
}
module_init(chartest_init);
module_exit(chartest_exit);
MODULE_LICENSE("GPL");
APP.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
int fd;
char buf[64] = {0};
char writebuf[64]={0};
fd = open("/dev/LCDdevice",O_RDWR);
if(fd < 0)
{
perror("open error\n");
return fd;
}
read(fd,buf,sizeof(buf));
printf("read buf is %s\n",buf);
writebuf[0] = atoi(argv[1]);
write(fd,writebuf,sizeof(writebuf));
close(fd);
return 0;
}