正点原子linux阿尔法开发板使用—新字符设备驱动_sh 1 cannot create sys class leds sys-led trigg

/\*4、自动创建设备节点\*/
	newchrled.class = class\_create(THIS_MODULE, NEWCHRLED_NAME);
	if (IS\_ERR(newchrled.class))
		return PTR\_ERR(newchrled.class);

创建设备。
在这里插入图片描述
在这里插入图片描述

错误预警

在这里插入图片描述
如果使用的是心跳灯,必须关闭这个心跳灯,否则干扰实验现象。

echo none > /sys/class/leds/sys-led/trigger // 改变 LED 的触发模式

在这里插入图片描述

2022.5.21 p15

设置文件私有数据:
在这里插入图片描述代码中在open使用filp的release:
在这里插入图片描述
在read write 里面访问设备的时候需要访问私有数据。

/\*\*
 \*my first driver
 \* 
\*/
#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>

#define LED\_MAJOR 200 //主设备号
#define LED\_NAME "LED" //驱动名称

#define NEWCHRLED\_NAME "newchrled"
#define NEWCHRLED\_COUNT 1 

struct newchrled\_dev {
	
	struct cdev cdev;
	struct class \*class;/\*类:为了自动创建节点\*/
	struct device \*device;/\*设备:为了自动创建节点\*/
	dev\_t devid; //设备号
	int major;   //主设备号
	int minor;   //次设备号
};

struct newchrled\_dev newchrled; //led设备

/\*首先定义寄存器的物理地址\*/
#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;

#define LEDOFF 0 /\*关闭\*/

#define LEDON 1 /\*打开\*/

static void led\_switch(u8 sta)
{
	u32 val = 0;
	if (sta == LEDON)
	{
		val = readl(GPIO1_DR);
		val &= ~(1<<3);/\*bit3 清0 打开led\*/
		writel(val,GPIO1_DR);
	}else if(sta == LEDOFF){
		val = readl(GPIO1_DR);
		val |= 1<<3;/\*bit3 清0 打开led\*/
		writel(val,GPIO1_DR);
	}
	
}

static int newchrled\_open(struct inode \*inode, struct file \*filp)
{
	/\*设置私有数据\*/
	filp->private_data = &newchrled;
	return 0;

}

static int newchrled\_release(struct inode \*inode, struct file \*filp)
{
	struct newchrled\_dev \*dev = (struct newchrled\_dev \*)filp->private_data;
	
	return 0;
}

static ssize\_t newchrled\_write(struct file \*filp, const char __user \*buf,size\_t count, loff\_t \*ppos)
{
	int ret = 0;

	unsigned char databuf[1];

	ret = copy\_from\_user(databuf,buf,count);
	if (ret<0){
			printk("kernel\_write error");
			return -EFAULT;
	}

	led\_switch(databuf[0]);

	return 0;
}

/\*\*
 \* 字符设备的操作集合
\*/
const struct file\_operations newchrled_fops = {
	.owner = THIS_MODULE,
	.open = newchrled_open,
	.release = newchrled_release,
	.write = newchrled_write,	
};


static int __init newchrled\_init(void)
{

	int ret = 0;
	/\*1、初始化led\*/
	u32 val = 0;
	//初始化内存映射 
	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、初始化\*/
	val = readl(IMX6U_CCM_CCGR1);
	val &= ~(3<<26);/\*清零bit26 27\*/
	val |= (3<<26);	/\*bit 26 27置1\*/
	writel(val,IMX6U_CCM_CCGR1);

	writel(0x5,SW_MUX_GPIO1_IO03);//设置复用
	writel(0x10b0,SW_PAD_GPIO1_IO03);//设置电气属性

	val = readl(GPIO1_GDIR);
	val |= 1<<3;/\*bit3 置为1 设置为输出\*/
	writel(val,GPIO1_GDIR);

	val = readl(GPIO1_DR);
	val &= ~(1<<3);/\*bit3 清0 打开led\*/
	writel(val,GPIO1_DR);

	/\*2、注册字符设备\*/
	printk("newchrled\_init ok\r\n");

	newchrled.major = 0;//设置为0,表示由系统申请设备号
	if(newchrled.major)   //给定主设备号
	{
		newchrled.devid = MKDEV(newchrled.major,0);	
		ret = register\_chrdev\_region(newchrled.devid,NEWCHRLED_COUNT,NEWCHRLED_NAME);
	}else{
		ret = alloc\_chrdev\_region(&newchrled.devid,0,NEWCHRLED_COUNT,NEWCHRLED_NAME);
		newchrled.major = MAJOR(newchrled.devid);
		newchrled.minor = MINOR(newchrled.devid);
	}
	if(ret < 0){
		printk("newchrled chrdev\_region err\r\n");
		return -1;
	}

	printk("newchrled majorid = %d,minorid = %d\r\n",newchrled.major,newchrled.minor);

	/\*3、初始化cdev\*/
	newchrled.cdev.owner = THIS_MODULE;

	cdev\_init(&newchrled.cdev, &newchrled_fops);

	cdev\_add(&newchrled.cdev,newchrled.devid,NEWCHRLED_COUNT);
	

	/\* 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);
	}

	return 0;
}

static void __exit newchrled\_exit(void)
{
	printk("newchrled\_exit ok\r\n");

	/\*删除字符设备\*/
	cdev\_del(&newchrled.cdev);
## 最后

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。**

**因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/25ac095ac89bda4b2c64f3a5e4bbe963.png)

![img](https://img-blog.csdnimg.cn/img_convert/8545c811055329f79424395b170bbbbf.jpeg)

![img](https://img-blog.csdnimg.cn/img_convert/29d99561425b25725df55d45b59ef54a.png)

 ![img](https://img-blog.csdnimg.cn/img_convert/247695f1cd2c8a073b9cd098f8ff15a1.png)

![img](https://img-blog.csdnimg.cn/img_convert/d51d8b6aa1f4144670c9a8182b0d8938.png)

![img](https://img-blog.csdnimg.cn/img_convert/f713c4c342f20477901da6cd1667d41b.png)

![](https://img-blog.csdnimg.cn/img_convert/51ea973734ad488dd8480134ee5b227e.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


57626458)]

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值