1.在串口工具进行输入:
echo 1 > /dev/myled0 ---->led1灯点亮
echo 0 > /dev/myled0 ---->led1灯熄灭
echo 1 > /dev/myled1 ---->led1灯点亮
echo 0 > /dev/myled1 ---->led1灯熄灭
echo 1 > /dev/myled2 ---->led1灯点亮
echo 0 > /dev/myled2 ---->led1灯熄灭
要求:
1)分部实现注册字符设备驱动
2)自动创建设备节点
3)通过结构体对led灯地址进行映射
4)次设备号完成私有数据传参
#include
#include
#include
#include
#include
#include
#include
#include
#include "myled.h"#define CNAME "myled"struct cdev* cdev;
dev_t devnum;
struct device* dev;
struct class* cls;#if 0
unsigned int major = 0;
#else
unsigned int major = 500;
#endifint minor=1;
const int count=3;int k_open(struct inode *inode, struct file *file)
{//终端在传参时会打开对应的驱动文件,相当于调用了open和write函数,//inode结构体中存放着该驱动的设备号,次设备号不同,通过私有数据传参到write函数中进行判断file->private_data=(void*)MINOR(inode->i_rdev);printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
ssize_t k_read(struct file *file, char __user *ubuf, size_t size, loff_t *loff)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
ssize_t K_write (struct file *file, const char __user *ubuf, size_t size, loff_t *loff)
{char ch;int ret;int kminjor;//接收终端传入的字符(控制led的亮灭)ret=copy_from_user(&ch,ubuf,sizeof(char));if(ret){printk("copy from user is error\n");return -EIO;}printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);//接收k_open函数传递的私有数据(次设备号)kminjor=(int)file->private_data;if(ch=='1'){if(kminjor==1){gpioe->ODR |= (0x1 << 10);}if(kminjor==2){gpiof->ODR |= (0x1 << 10);}if(kminjor==3){gpioe->ODR |= (0x1 << 8);}}else{if(kminjor==1){gpioe->ODR &= (~(0x1 << 10));}if(kminjor==2){gpiof->ODR &= (~(0x1 << 10));}if(kminjor==3){gpioe->ODR &= (~(0x1 << 8));}}return size;
}
int k_close (struct inode *inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
//初始化操作方法结构体
const struct file_operations fops=
{.open=k_open,.read=k_read,.write=K_write,.release=k_close,
};
//入口,安装驱动时执行
static int __init k_init(void)
{int ret,i;//分配字符设备驱动cdev=cdev_alloc();if(cdev==NULL){printk("cdev_alloc is error\n");ret=-EIO;goto ERR1;}//初始化设备驱动cdev_init(cdev,&fops);//申请设备号if(major>0){ret=register_chrdev_region(MKDEV(major,minor),count,CNAME);if(ret){printk("register_chrdev_region is error\n");ret=-ENOMEM;goto ERR2;} }else{ret=alloc_chrdev_region(&devnum,1,count,CNAME);if(ret){printk("alloc_chrdev_region is error\n");ret=-ENOMEM;goto ERR2;}major=MAJOR(devnum);minor=MINOR(devnum);}//驱动的注册ret=cdev_add(cdev,MKDEV(major,minor),count);if(ret){printk("cdev add is error\n");ret = -EIO;goto ERR3;}//自动创建设备节点cls = class_create(THIS_MODULE,CNAME);if(IS_ERR(cls)) {printk("class create is error\n");ret = PTR_ERR(cls); goto ERR4;}for(i=1;i<=count;i++){dev=device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);if(IS_ERR(dev)){printk("device create is error\n");ret = PTR_ERR(dev);goto ERR5;}}//RCC寄存器地址映射rcc=ioremap(RCC,4);if(NULL == rcc){printk("rcc ioremap is error\n");return -ENOMEM;}//GPIOE寄存器地址映射gpioe=ioremap(GPIOE,sizeof(gpio_t));if(NULL == gpioe){printk("gpioe ioremap is error\n");return -ENOMEM;}//GPIOF寄存器地址映射gpiof=ioremap(GPIOF,sizeof(gpio_t));if(NULL == gpiof){printk("gpiof ioremap is error\n");return -ENOMEM;}//LED1--->PE10引脚初始化*rcc|= (0x1 << 4);gpioe->MODER &= (~(0x3 << 20));gpioe->MODER |= (0x1 << 20);gpioe->ODR &= (~(0x1 << 10));// LED2--->PF10初始化*rcc|= (0x1 << 5);gpiof->MODER &= (~(0x3 << 20));gpiof->MODER |= (0x1 << 20);gpiof->ODR &= (~(0x1 << 10));//LED3--->PE8初始化*rcc|= (0x1 << 4);gpioe->MODER &= (~(0x3 << 16));gpioe->MODER |= (0x1 << 16);gpioe->ODR &= (~(0x1 << 8));return 0;
ERR5: for(--i;i>=0;i--){device_destroy(cls,MKDEV(major,i));}class_destroy(cls);
ERR4:cdev_del(cdev);
ERR3:unregister_chrdev_region(MKDEV(major,minor),count);
ERR2:kfree(cdev);
ERR1:return -EIO;
}
//出口,卸载驱动时执行
static void __exit k_exit(void)
{int i;//销毁设备节点信息for(i=1;i<=count;i++){device_destroy(cls,MKDEV(major,i));}//销毁目录信息class_destroy(cls);//驱动的注销cdev_del(cdev);//销毁设备号unregister_chrdev_region(MKDEV(major,minor),count);//释放cdev结构体kfree(cdev);//取消地址映射iounmap(rcc);iounmap(gpioe);iounmap(gpiof);
}module_init(k_init);
module_exit(k_exit);
MODULE_LICENSE("GPL");
#ifndef __MYLED__H__
#define __MYLED__H__typedef struct{volatile unsigned int MODER;volatile unsigned int OTYPER;volatile unsigned int OSPEEDR;volatile unsigned int PUPDR;volatile unsigned int IDR;volatile unsigned int ODR;
}gpio_t;
#define GPIOE 0x50006000
#define GPIOF 0x50007000
#define RCC 0x50000A28
volatile unsigned int* rcc;
gpio_t* gpioe;
gpio_t* gpiof;#endif

上一篇:跟风模仿句子。