嵌入式 Linux(二) :led模板,具体板——驱动程序+应用程序+makefile

以调用led为例,编写驱动程序+应用程序+makefile。

 

总体功能:test程序作为应用程序,通过fd = open(argv[1], O_RDWR)与驱动文件相连,这里的open以及后续的write,close均由驱动程序leddrv.c重写提供。leddrv.c中p_led_opr->init(minor)表示的哪个灯,灯的状态两参数,由board_demo.c重写提供。board_demo.c根据各个板的灯接口不同进行特别的设置。

 

编写驱动程序

确定主设备号,也可以让内核分配

定义自己的 file_operations 结构体

实现对应的 drv_open/drv_read/drv_write 等函数,填入 file_operations 结构体

file_operations 结构体告诉内核:register_chrdev

谁来注册驱动程序啊?得有一个入口函数:安装驱动程序时,就会去调用这个入口函数

有入口函数就应该有出口函数:卸载驱动程序时,出口函数调用 unregister_chrdev

其他完善:提供设备信息,自动创建设备节点:class_create, device_create

 

leddrv.c

1、程序功能:制造驱动drv,中间调用到board_demo.c的内容,led_opr.h受到board_demo.c的调用,其中含有board_demo.c中的一些函数,结构体的声明

 

2、程序执行顺序:
module_init(led_init);进入到:static int __init led_init(void)
在tatic struct file_operations led_drv定义各项行为,可选择性进行
    owner     = THIS_MODULE,
    .open    = led_drv_open,
    .read    = led_drv_read,
    .write   = led_drv_write,
    .release = led_drv_close,

module_exit(led_exit);进入到:tatic void __exit led_exit(void)

#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>

#include "led_opr.h"

#define LED_NUM 2


/* 1. 确定主设备号                                                                 */
static int major = 0;
static struct class *led_class;
struct led_operations *p_led_opr;//指针来调用单板相关代码 


#define MIN(a, b) (a < b ? a : b)

/* 3. 实现对应的open/read/write等函数,填入file_operations结构体                   */
//函数内传入的参数在file_operations 结构体内定义,如ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
static ssize_t led_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;
}

/* write(fd, &val, 1); */
static ssize_t led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
	int err;
	char status;
	struct inode *inode = file_inode(file);//file_node()返回指定文件(file)的inode编号
	int minor = iminor(inode);//使用iminor获取它的次设备号
	
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	
	err = copy_from_user(&status, buf, 1);//从buf拷贝1个字节到status的地址中,表示灯的状态

	/* 根据次设备号和status控制LED */
	p_led_opr->ctl(minor, status);
	
	return 1;
}

static int led_drv_open (struct inode *node, struct file *file)
{
	int minor = iminor(node);//用iminor函数得到次设备号
	
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	/* 根据次设备号初始化LED */
	p_led_opr->init(minor);//在board_demo.c中重写
	
	return 0;
}

static int led_drv_close (struct inode *node, struct file *file)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;
}

/* 2. 定义自己的file_operations结构体                                              */
static struct file_operations led_drv = {
	.owner	 = THIS_MODULE,
	.open    = led_drv_open,
	.read    = led_drv_read,
	.write   = led_drv_write,
	.release = led_drv_close,
};

/* 4. 把file_operations结构体告诉内核:注册驱动程序                                */
/* 5. 谁来注册驱动程序啊?得有一个入口函数:安装驱动程序时,就会去调用这个入口函数 */


//led_init功能
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值