汉庭酒店网站建设方案,建设工程交易服务中心,网站搭建公司,怎么注册logo商标Linux下#xff0c;/dev、/sys/class的区别
/dev下面有很多节点#xff0c;每一个节点代表一个设备#xff0c;/dev目录下面是按物理器件进行分类#xff1b;而/sys/class下面的更多是按功能抽象出来的。 参考1
demo
在正点原子的基础上进行演示
#include linux/ty…Linux下/dev、/sys/class的区别
/dev下面有很多节点每一个节点代表一个设备/dev目录下面是按物理器件进行分类而/sys/class下面的更多是按功能抽象出来的。 参考1
demo
在正点原子的基础上进行演示
#include linux/types.h
#include linux/kernel.h
#include linux/delay.h
#include linux/ide.h
#include linux/init.h
#include linux/module.h
#include linux/errno.h
#include linux/gpio.h
#include linux/cdev.h
#include linux/device.h#include asm/mach/map.h
#include asm/uaccess.h
#include asm/io.h/***************************************************************
Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved.
文件名 : newchrled.c
作者 : 左忠凯
版本 : V1.0
描述 : LED驱动文件。
其他 : 无
论坛 : www.openedv.com
日志 : 初版V1.0 2019/6/27 左忠凯创建
***************************************************************/
#define NEWCHRLED_CNT 1 /* 设备号个数 */
#define NEWCHRLED_NAME newchrled /* 名字 */
#define LEDOFF 0 /* 关灯 */
#define LEDON 1 /* 开灯 *//* 寄存器物理地址 */
#define CCM_CCGR1_BASE (0X020C406C)
#define SW_MUX_GPIO1_IO03_BASE (0X020E0068)
#define SW_PAD_GPIO1_IO03_BASE (0X020E02F4)
#define GPIO1_DR_BASE (0X0209C000)
#define GPIO1_GDIR_BASE (0X0209C004)/* 映射后的寄存器虚拟地址指针 */
static void __iomem *IMX6U_CCM_CCGR1;
static void __iomem *SW_MUX_GPIO1_IO03;
static void __iomem *SW_PAD_GPIO1_IO03;
static void __iomem *GPIO1_DR;
static void __iomem *GPIO1_GDIR;/* newchrled设备结构体 */
struct newchrled_dev{dev_t devid; /* 设备号 */struct cdev cdev; /* cdev */struct class *class; /* 类 */struct device *device; /* 设备 */int major; /* 主设备号 */int minor; /* 次设备号 */
};struct newchrled_dev newchrled; /* led设备 *///对应应用层的write
static ssize_t my_att_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{ printk(value:%s\n, buf);return count;
}
//对应应用层的read
static ssize_t my_att_show(struct device *dev, struct device_attribute *attr, char *buf)
{ printk(buf, my_attr show enter);buf hello world;return 0;
} static DEVICE_ATTR(my_att,0660,my_att_show,my_att_store); /** description : LED打开/关闭* param - sta : LEDON(0) 打开LEDLEDOFF(1) 关闭LED* return : 无*/
void led_switch(u8 sta)
{u32 val 0;if(sta LEDON) {val readl(GPIO1_DR);val ~(1 3); writel(val, GPIO1_DR);}else if(sta LEDOFF) {val readl(GPIO1_DR);val| (1 3); writel(val, GPIO1_DR);}
}/** description : 打开设备* param - inode : 传递给驱动的inode* param - filp : 设备文件file结构体有个叫做private_data的成员变量* 一般在open的时候将private_data指向设备结构体。* return : 0 成功;其他 失败*/
static int led_open(struct inode *inode, struct file *filp)
{filp-private_data newchrled; /* 设置私有数据 */return 0;
}/** description : 从设备读取数据 * param - filp : 要打开的设备文件(文件描述符)* param - buf : 返回给用户空间的数据缓冲区* param - cnt : 要读取的数据长度* param - offt : 相对于文件首地址的偏移* return : 读取的字节数如果为负值表示读取失败*/
static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{return 0;
}/** description : 向设备写数据 * param - filp : 设备文件表示打开的文件描述符* param - buf : 要写给设备写入的数据* param - cnt : 要写入的数据长度* param - offt : 相对于文件首地址的偏移* return : 写入的字节数如果为负值表示写入失败*/
static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{int retvalue;unsigned char databuf[1];unsigned char ledstat;retvalue copy_from_user(databuf, buf, cnt);if(retvalue 0) {printk(kernel write failed!\r\n);return -EFAULT;}ledstat databuf[0]; /* 获取状态值 */if(ledstat LEDON) { led_switch(LEDON); /* 打开LED灯 */} else if(ledstat LEDOFF) {led_switch(LEDOFF); /* 关闭LED灯 */}return 0;
}/** description : 关闭/释放设备* param - filp : 要关闭的设备文件(文件描述符)* return : 0 成功;其他 失败*/
static int led_release(struct inode *inode, struct file *filp)
{return 0;
}/* 设备操作函数 */
static struct file_operations newchrled_fops {.owner THIS_MODULE,.open led_open,.read led_read,.write led_write,.release led_release,
};/** description : 驱动出口函数* param : 无* return : 无*/
static int __init led_init(void)
{u32 val 0;/* 初始化LED *//* 1、寄存器地址映射 */IMX6U_CCM_CCGR1 ioremap(CCM_CCGR1_BASE, 4);SW_MUX_GPIO1_IO03 ioremap(SW_MUX_GPIO1_IO03_BASE, 4);SW_PAD_GPIO1_IO03 ioremap(SW_PAD_GPIO1_IO03_BASE, 4);GPIO1_DR ioremap(GPIO1_DR_BASE, 4);GPIO1_GDIR ioremap(GPIO1_GDIR_BASE, 4);/* 2、使能GPIO1时钟 */val readl(IMX6U_CCM_CCGR1);val ~(3 26); /* 清楚以前的设置 */val | (3 26); /* 设置新值 */writel(val, IMX6U_CCM_CCGR1);/* 3、设置GPIO1_IO03的复用功能将其复用为* GPIO1_IO03最后设置IO属性。*/writel(5, SW_MUX_GPIO1_IO03);/*寄存器SW_PAD_GPIO1_IO03设置IO属性*bit 16:0 HYS关闭*bit [15:14]: 00 默认下拉*bit [13]: 0 kepper功能*bit [12]: 1 pull/keeper使能*bit [11]: 0 关闭开路输出*bit [7:6]: 10 速度100Mhz*bit [5:3]: 110 R0/6驱动能力*bit [0]: 0 低转换率*/writel(0x10B0, SW_PAD_GPIO1_IO03);/* 4、设置GPIO1_IO03为输出功能 */val readl(GPIO1_GDIR);val ~(1 3); /* 清除以前的设置 */val | (1 3); /* 设置为输出 */writel(val, GPIO1_GDIR);/* 5、默认关闭LED */val readl(GPIO1_DR);val | (1 3); writel(val, GPIO1_DR);/* 注册字符设备驱动 *//* 1、创建设备号 */if (newchrled.major) { /* 定义了设备号 */newchrled.devid MKDEV(newchrled.major, 0);register_chrdev_region(newchrled.devid, NEWCHRLED_CNT, NEWCHRLED_NAME);} else { /* 没有定义设备号 */alloc_chrdev_region(newchrled.devid, 0, NEWCHRLED_CNT, NEWCHRLED_NAME); /* 申请设备号 */newchrled.major MAJOR(newchrled.devid); /* 获取分配号的主设备号 */newchrled.minor MINOR(newchrled.devid); /* 获取分配号的次设备号 */}printk(newcheled major%d,minor%d\r\n,newchrled.major, newchrled.minor); /* 2、初始化cdev */newchrled.cdev.owner THIS_MODULE;cdev_init(newchrled.cdev, newchrled_fops);/* 3、添加一个cdev */cdev_add(newchrled.cdev, newchrled.devid, NEWCHRLED_CNT);/* 4、创建类 */newchrled.class class_create(THIS_MODULE, NEWCHRLED_NAME);if (IS_ERR(newchrled.class)) {return PTR_ERR(newchrled.class);}/* 5、创建设备 */newchrled.device device_create(newchrled.class, NULL, newchrled.devid, NULL, NEWCHRLED_NAME);if (IS_ERR(newchrled.device)) {return PTR_ERR(newchrled.device);}/* 创建自己的节点 */device_create_file(newchrled.device, dev_attr_my_att);return 0;
}/** description : 驱动出口函数* param : 无* return : 无*/
static void __exit led_exit(void)
{/* 取消映射 */iounmap(IMX6U_CCM_CCGR1);iounmap(SW_MUX_GPIO1_IO03);iounmap(SW_PAD_GPIO1_IO03);iounmap(GPIO1_DR);iounmap(GPIO1_GDIR);/* 注销字符设备驱动 */cdev_del(newchrled.cdev);/* 删除cdev */unregister_chrdev_region(newchrled.devid, NEWCHRLED_CNT); /* 注销设备号 */device_destroy(newchrled.class, newchrled.devid);class_destroy(newchrled.class);
}module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE(GPL);
MODULE_AUTHOR(zuozhongkai);
class_create
函数说明 class_create执行后sys/class下面会生成一个NEWCHRLED_NAME的路径但此时该路径下为空。
device_create
函数说明 将dev设备与class相关联该函数执行后NEWCHRLED_NAME路径下出现
device_create_file
创建一个自己的属性 函数说明 在删除设备的时候自动删除该节点无需在exit函数中特意删除。 my_att_store和my_att_show分别对应应用层对属性文件的读写。 一个demo