Linux内核驱动开发-字符设备驱动框架

1前置条件

(1)【linux】内核编译结束
(2)【linux】目录配置跳转文件:

在这里插入图片描述

补充:配置的跳转文件只能在【linux】目录下使用,子目录无法使用

2驱动框架

2.1编写驱动程序

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>

#define DEVICE_MAJOR 200
#define DEVICE_NAME  "first_device"

int first_driver_open(struct inode *node, struct file *fp)
{
	printk("first_driver_open\n");
	return 0;
}

ssize_t first_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset)
{
	printk("first_driver_read\n");
	return 0;
}

ssize_t first_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset)
{
	printk("first_driver_write\n");
	return 0;
}

int first_driver_close(struct inode *node, struct file *fp)
{
	printk("first_driver_close\n");
	return 0;
}

static struct file_operations fops = 
{
	.owner = THIS_MODULE,
	.open = first_driver_open,
	.read = first_driver_read,
	.write = first_driver_write,
	.release = first_driver_close
};

static int __init first_driver_init(void)
{	
	register_chrdev(DEVICE_MAJOR, DEVICE_NAME, &fops);
	printk("first_driver_init OK\n");
	return 0;
}

static void __exit first_driver_exit(void)
{	
	unregister_chrdev(DEVICE_MAJOR, DEVICE_NAME);
	printk("first_driver_exit OK\n");
}


module_init(first_driver_init);
module_exit(first_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("XXX");

2.2 编译驱动程序

2.2.1编译方式1

【step1】:将编写完成的驱动程序放至【linux/drivers/char】目录下
【cp ./file_name.c linux/drivers/char】
【step2】:修改内核配置文件
【vi linux/drivers/char/Kconfig】

在这里插入图片描述

【step3】:修改编译规则,添加工程文件
【vim linux/drivers/char/Makefile】

在这里插入图片描述

在这里插入图片描述

【step4】:菜单配置
【make menuconfig】

在这里插入图片描述

在这里插入图片描述

修改为<M>模式

在这里插入图片描述
附:3种模式讲解

当然,也可以使用【help】选项查看相关信息

在这里插入图片描述
在这里插入图片描述

【step5】:调用编译命令,进行驱动程序的编译
【make modules】	

在这里插入图片描述

至此,采用方式1编译完成。当然,也可以查看编译后文件是否存在:

在这里插入图片描述

这是一个需要手动添加到操作系统的文件。

2.2.2编译方式2

【step1】:创建一个文件夹:是linux目录下的任意目录
【mkdir my_drivers】

在这里插入图片描述

【step2】:将驱动程序源码放入该目录

在这里插入图片描述

【step3】:该目录下创建【Makefile】文件
【vim Makefile】
KERNELDIR := /home/linux/s3c2440/linux-2.6.32.2/
CURRENT_PATH := $(shell pwd)
obj-m := first_driver.o

build: kernel_modules

kernel_modules:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules

clean:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
【step4】:编译
【make】

在这里插入图片描述

至此,采用方式2编译完成。当然,也可以查看编译后文件是否存在:

在这里插入图片描述

这是一个需要手动添加到操作系统的文件。

2.3移植驱动程序

(1)将编译产生的【filename.ko】文件移植到开发板
【cp drivers/char/first_driver.ko ~/nfs/rootfs】

在这里插入图片描述

在开发板种可以看到文件移植成功:

在这里插入图片描述

2.4加载驱动程序

(1)加载被移植到开发板的【filename.ko】文件
【insmod filename.ko】

在这里插入图片描述

补充:
查看加载成功的驱动:
	【lsmod】

2.5卸载驱动程序

(1)卸载被移植到开发板的【filename.ko】文件
	【rmmod filename】

2.6创建设备文件

2.6.1创建设备文件方式1

手动创建设备文件
【mknod[options] name type major minor】
【options】:
【name】:【/dev】下的设备文件名
【type】:设备型号,【c】
【major】:主设备号
【minor】:子设备号
eg:【mknod /dev/first_driver c 200 0】

在这里插入图片描述

设备创建完毕,可以使用【ls】命令查看是否成功创建设备文件。

在这里插入图片描述

补充:
应用程序就是以【name】为入口点来调用驱动程序的。
【mknod ?】:查看命令帮助
【cat /proc/devices/】:查看设备
【ls /dev】:查看设备文件

删除设备文件:

在这里插入图片描述

2.7调用驱动程序

【step1】:其实就是在开发板上编写一个应用程序(主要是指main函数)
编写应用程序:打开设备文件->调用文件I/O(系统I/O)->
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>

int main(void)
{
    int fd=0;

    fd=open("dev/first_device",O_RDWR);
    if(fd<0)
    {
        printf("opening is error\n");
        return -1;
    }

    while(1)
    {
        int n=123;
        read(fd,&n,4);
        sleep(1);
        write(fd,&n,4);
        sleep(1);
    }
    return 0;
}
【step2】:编译应用程序

在这里插入图片描述

【step3】:关闭开发板原有的设备驱动程序
通过菜单配置命令:【make menuconfig】
将对应的驱动模块的模式【<>】改为图中所标记的模式。

在这里插入图片描述

2.8编译并移植内核文件

【make uImage】

在这里插入图片描述

编译完成之后,将产生的镜像文件移植到开发板:
【cp arch/arm/boot/uImage ~/tftpboot/】

在这里插入图片描述

2.9运行操作系统内核

接下来,将操作系统运行在开发板上:
【tftp 0x30008000 uImage】
【bootm 0x30008000】

2.10开发板文件配置

当新的内核文件在开发板上成功运行之后,接下来需要对开发板上的一个文件进行配置:

在这里插入图片描述

关闭led相关配置:

在这里插入图片描述

补充:
(1)【reboot】:该命令将重启开发板,让开发板回到初始状态,从运行内核文件之后的所有操作需要重新配置。

在这里插入图片描述

(2)通过配置环境变量可以让开发板上电以后自动运行操作系统并挂载根目录:
【setenv bootcmd 'tftp 0x30008000; bootm 0x30008000'】
注意:环境变量配置完成一定要进行保存操作!!!

在这里插入图片描述

(3)环境变量配置完成之后可以重启开发板:可以看到开发板将自动运行操作系统并挂载根文件系统。
【reset】:重启开发板

在这里插入图片描述

3板载驱动程序示例

路径:【linux-2.6.32.2/drivers/char/mini2440_hello_module.c 】

#include <linux/kernel.h>
#include <linux/module.h>


static int __init mini2440_hello_module_init(void)
{
    printk("Hello, Mini2440 module is installed !\n");
    return 0;
}

static void __exit mini2440_hello_module_cleanup(void)
{
    printk("Good-bye, Mini2440 module was removed!\n");
}

module_init(mini2440_hello_module_init);
module_exit(mini2440_hello_module_cleanup);
MODULE_LICENSE("GPL");

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Linux字符设备驱动实验是指在Linux操作系统中编写和测试字符设备驱动程序的过程。字符设备驱动程序负责与字符设备进行交互,包括输入输出数据、控制设备和处理设备的状态等。 在进行Linux字符设备驱动实验之前,首先需要了解字符设备字符设备驱动的基本概念及其工作原理。字符设备是指以字符为单位进行输入输出的设备,如串口、打印机等。字符设备驱动是指将操作系统与字符设备进行交互的程序。 在实验中,我们通常需要编写一个字符设备驱动程序,包括初始化设备、读写数据、控制设备等功能。首先,我们需要定义字符设备驱动的数据结构,包括设备号、驱动程序打开、关闭等函数的实现。然后,我们需要实现字符设备驱动的读写函数来实现数据的输入输出。最后,我们可以进行一些附加功能的实现,如控制设备的状态、处理中断等。 在实验过程中,我们需要使用Linux内核提供的字符设备接口来进行字符设备驱动的编写和测试。可以使用一些工具和命令来加载和测试字符设备驱动程序,如insmod、rmmod等。通过这些工具和命令,我们可以加载和卸载字符设备驱动程序,并在用户空间进行数据的读写操作,来测试字符设备驱动的功能和性能。 Linux字符设备驱动实验可以帮助我们深入了解字符设备字符设备驱动的工作原理,并学习Linux内核开发和调试技术。通过实验,我们可以更好地理解操作系统和驱动程序之间的关系,提高我们在Linux系统开发和嵌入式系统开发中的能力。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值