驱动开发 作业5

这篇具有很好参考价值的文章主要介绍了驱动开发 作业5。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目

使用驱动代码实现如下要求:

  1. 使用驱动通过阻塞 io 模型读取 number 变量的值
  2. number 是内核驱动中的一个变量
  3. number 的值随着按键按下而改变(按键中断)
    • 例如 number = 0 按下按键 number = 1,再次按下按键 number = 0
  4. 在按下按键的时候需要同时将 led1 的状态取反>
  5. 驱动中需要编写字符设备驱动
  6. 驱动中需要自动创建设备节点
  7. 在这个驱动需要的所有设备信息放在设备树的同一个节点中

Repo文章来源地址https://www.toymoban.com/news/detail-599427.html

设备树文件

/dts-v1/;

#include "stm32mp157.dtsi"
#include "stm32mp15xa.dtsi"
#include "stm32mp15-pinctrl.dtsi"
#include "stm32mp15xxac-pinctrl.dtsi"
#include "stm32mp15xx-fsmp1x.dtsi" 

/ {
  model = "HQYJ STM32MP157 FSMP1A Discovery Board";
  compatible = "st,stm32mp157a-dk1", "st,stm32mp157";

  aliases {
    serial0 = &uart4;
    serial5 = &usart3;
  };

  chosen {
    stdout-path = "serial0:115200n8";
  };

  reserved-memory {
    gpu_reserved: gpu@d4000000 {
                    reg = <0xd4000000 0x4000000>;
                    no-map;
                  };

    optee_memory: optee@0xde000000 {
                    reg = <0xde000000 0x02000000>;
                    no-map;
                  };
  };
  
  //自定义设备树 
  mynode@0x12345678{ 
		compatible = "hqyj,mynode"; 
    	astring="hello 23031"; 
		uint  =<0xaabbccdd 0x11223344>; 
    	binarry=[00 0c 29 7b f9 be]; 
    	mixed ="hello",[11 22],<0x12345678>; 
	 };

  mychrdev {
   led=<&gpioe 10 0>;    
   interrupt-parent=<&gpiof>;
   interrupts=<9 0>;
  };
};

驱动代码

#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/interrupt.h>

int major;
struct class *cls;
struct device *dev;

int number = 0;
unsigned int condition = 0;
wait_queue_head_t wq_head;

// 所有的设备都在同一个节点下
struct device_node *dnode;
unsigned int irqno;
struct gpio_desc *gpiono;

ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
{
	int ret;
	wait_event_interruptible(wq_head, condition);

	ret = copy_to_user(ubuf, &number, sizeof(number));
	if (ret) {
		printk("copy_to_user failed\n");
		return -EIO;
	}
	condition = 0;
	return 0;
}

struct file_operations fops = {
	.read = mycdev_read,
};

// 中断处理函数
irqreturn_t myirq_handler(int irq, void *dev_id)
{
	number = !number;
	gpiod_set_value(gpiono, number);
	printk("key pressed, number=%d\n", number);
	return IRQ_HANDLED;
}

static int __init mycdev_init(void)
{
	int ret;
	// 初始化等待队列头
	init_waitqueue_head(&wq_head);
	// 字符设备注册
	major = register_chrdev(0, "mycdev", &fops);
	if (major < 0) {
		printk("register_chrdev failed\n");
		return major;
	}
	// 向上提交目录
	cls = class_create(THIS_MODULE, "mycdev");
	if (IS_ERR(cls)) {
		printk("class_create failed\n");
		return -PTR_ERR(cls);
	}
	// 创建设备文件
	dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "led");
	if (IS_ERR(dev)) {
		printk("device_create failed\n");
		return -PTR_ERR(dev);
	}
	dev = device_create(cls, NULL, MKDEV(major, 1), NULL, "key");
	if (IS_ERR(dev)) {
		printk("device_create failed\n");
		return -PTR_ERR(dev);
	}
	dnode = of_find_node_by_path("/mychrdev");
	if (!dnode) {
		printk("of_find_node_by_path failed\n");
		return -ENXIO;
	}
	irqno = irq_of_parse_and_map(dnode, 0);
	if (!irqno) {
		printk("irq_of_parse_and_map failed\n");
		return -ENXIO;
	}
	ret = request_irq(irqno, myirq_handler, IRQF_TRIGGER_FALLING, "key",
			  NULL);
	if (ret) {
		printk("request_irq failed\n");
		return ret;
	}
	gpiono = gpiod_get_from_of_node(dnode, "led", 0, GPIOD_OUT_LOW, NULL);
	if (IS_ERR(gpiono)) {
		printk("gpiod_get_from_of_node failed\n");
		return -PTR_ERR(gpiono);
	}
	return 0;
}

static void __exit mycdev_exit(void)
{
	// 注销设备文件
	device_destroy(cls, MKDEV(major, 0));
	device_destroy(cls, MKDEV(major, 1));
	// 注销目录
	class_destroy(cls);
	// 注销字符设备
	unregister_chrdev(major, "mycdev");
	// 注销中断号
	free_irq(irqno, NULL);
	// 释放gpio
	gpiod_put(gpiono);
}

module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

测试代码

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>

int main(int argc, char const *argv[])
{
  int number;
	int fd = open("/dev/led", O_RDWR);
	if (fd < 0) {
		printf("打开设备文件失败\n");
		exit(-1);
	}
	while (1) {
		read(fd, &number, sizeof(number)); //读取数据
		printf("read:%d\n", number);
	}

	close(fd);
	return 0;
}

到了这里,关于驱动开发 作业5的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 华清远见 day03

    for 循环嵌套 输出一个字符; 输出一个字符串;

    2024年02月07日
    浏览(47)
  • 华清远见 week2 day01

    产生随机数

    2024年02月08日
    浏览(52)
  • 驱动开发 作业5

    使用驱动代码实现如下要求: 使用驱动通过阻塞 io 模型读取 number 变量的值 number 是内核驱动中的一个变量 number 的值随着按键按下而改变(按键中断) 例如 number = 0 按下按键 number = 1,再次按下按键 number = 0 在按下按键的时候需要同时将 led1 的状态取反 驱动中需要编写字符

    2024年02月16日
    浏览(27)
  • 驱动开发作业2

    LED.H MYCDEV.C TEST.C

    2024年02月11日
    浏览(39)
  • 6.22 驱动开发作业

    字符设备驱动的内部实现有两种情况: 情况1.应用层调用open函数的内部实现: open函数的第一个参数是要打开的文件的路径,根据这个路径 虚拟文件系统层VFS 可以找到这个文件在文件系统中唯一的标识,也就是inode号,通过inode号作为索引可以找到储存在内核中的struct inode结

    2024年02月11日
    浏览(28)
  • 驱动开发 作业1

    下面代码中的 gpio.h 和 rcc.h 是 led 项目中的 common/include 目录下的 stm32mp1xx_gpio.h 和 stm32mp1xx_rcc.h 所以不贴代码了,完整的目录查看这个仓库 这里直接把 GPIOE / GPIOF , RCC 结构体的地址映射到虚拟地址中 用户空间应用程序的代码没有修改,也不贴上来了,输入 1,2,3 分别对应开

    2024年02月13日
    浏览(30)
  • 驱动开发 作业3

    编写LED灯的驱动,创建三个设备文件,每个设备文件和一个LED灯绑定,当操作这个设备文件时只能控制设备文件对应的这盏灯。 完整目录,查看这个仓库 注册设备驱动对象 cdev_add 也需要对三个 LED 分别添加,否则 LED2 和 LED3 的设备文件虽然生成,但是无法被用户空间打开

    2024年02月13日
    浏览(24)
  • 【驱动开发day4作业】

    头文件代码  应用层代码  驱动代码

    2024年02月15日
    浏览(28)
  • 【驱动开发day2作业】

    head.h mychrdev.c led.c

    2024年02月15日
    浏览(29)
  • 【驱动开发day3作业】

    head.h  应用层代码 灯驱动代码 蜂鸣器驱动代码 风扇驱动代码 马达驱动代码  测试结果:    

    2024年02月15日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包