热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:第三方驱动移植——黑盒移植

篇首语:本文由编程笔记#小编为大家整理,主要介绍了第三方驱动移植——黑盒移植相关的知识,希望对你有一定的参考价值。黑盒移植,即在不用理解驱动程序的细节基础上进行移植

篇首语:本文由编程笔记#小编为大家整理,主要介绍了第三方驱动移植 —— 黑盒移植相关的知识,希望对你有一定的参考价值。


黑盒移植,即在不用理解驱动程序的细节基础上进行移植

驱动移植的主要流程如下:

技术图片

 一、黑盒移植

1、将驱动编译进内核

  如果内核中已经有了已经支持的驱动,那直接在menu上选配即可。若没有,则需要第三方的驱动或者自己写一个驱动,移植进内核。

  1)将第三方驱动放到linux源码的driver目录中

  拷贝LED驱动程序至drivers目录
  LED属于字符设备,所以放在drivers/char/目录下

技术图片

   2)修改Makefile让驱动编译进内核(对应目录下的Makefile)

技术图片

   make uImage编译内核

技术图片

   3)测试·驱动

烧写镜像到开发板

在ubuntu上编译驱动程序测试代码, 并拷贝到根文件系统


技术图片技术图片

1 #include
2 #include
3 #include
4 #include
5 #include
6
7 #define LED_MAGIC ‘L‘
8 #define LED_ON _IOW(LED_MAGIC, 1, int)
9 #define LED_OFF _IOW(LED_MAGIC, 2, int)
10
11 int main(int argc, char **argv)
12 {
13 int fd;
14
15 fd = open("/dev/led", O_RDWR);
16 if (fd <0) {
17 perror("open");
18 exit(1);
19 }
20
21 printf("open led ok
");
22
23 //实现LED灯闪烁
24 while(1)
25 {
26 ioctl(fd, LED_ON); //点亮灯
27 usleep(100000);
28 ioctl(fd, LED_OFF); //灭灯
29 usleep(100000);
30 }
31
32 return 0;
33 }


fs4412_app.c

在板子上运行app.c,测试驱动

技术图片

 报错,看到app.c

技术图片

 得知,需要创建设备文件

  4)创建设备文件

在fs4412_led_drv.c中,获取设备号

技术图片

 501为主设备号,0为次设备号

在板子上创建设备文件

mknod  /dev/led c 501 0

再次执行,可以发现LED灯闪烁并相应输出打印信息

技术图片

 

二、通过配置Kconfig来添加驱动

  如果在实际开发中都像以上方法一样,手动添加驱动到文件夹,修改Makefile,不想加载驱动的时候又从相应文件中删除,那么当驱动数量很多时,会十分的繁杂。所以可以通过在配置Kconfig在图形界面中,添减驱动。

  1)在Kconfig中添加一个led设备驱动

  进入对于子目录下的Kconfig

  技术图片

   make menuconfig

  技术图片

   打开帮助信息

  技术图片

   可以看到相关驱动已经在图形界面里了

  2)修改Makefile

  将原来的信息注释,添加配置项

  技术图片

   3)在图形界面选择不编译进内核,测试一下

  技术图片

  4)编译测试

  make menuconfig

  在编译界面没有看到fs4412_led_drv.o编译进来,再到板子上看看

  技术图片

   led驱动确实没有编译进内核。

 3、编译驱动为独立模块

   在前面使用了两者方法来加载驱动,但是这两种方法都是通过在内核目录里添加文件,在对应目录下修改Makefile和Kconfig。这样对于新增的驱动并不好管理。因此我们可以单独创建一个目录,目录可以在任意位置,内核外,把要载入的驱动独立出来。如何实现?

 1)配置为模块方法

  在内核外单独编译驱动模块

  创建目录,

  技术图片


技术图片技术图片

1 #include
2 #include
3 #include
4 #include
5 #include
6
7
8 #define LED_MAGIC ‘L‘
9 #define LED_ON _IOW(LED_MAGIC, 1, int)
10 #define LED_OFF _IOW(LED_MAGIC, 2, int)
11
12 #define LED_MA 501
13 #define LED_MI 0
14 #define LED_NUM 1
15
16 #define LED_CON 0x11000C20
17 #define LED_DAT 0x11000C24
18
19
20 struct cdev cdev;
21
22 unsigned int *ledcon;
23 unsigned int *leddat;
24
25 int led_open (struct inode *inode, struct file *file)
26 {
27 printk("led_open
");
28
29
30 ledcon = ioremap(LED_CON, 4);
31 if(ledcon == NULL) {
32 printk("ioremap LED_CON error
");
33 return -1;
34 }
35 writel(0x01, ledcon); //设置LED3 GPX1_0 为输出模式
36
37
38 leddat = ioremap(LED_DAT, 4);
39 if(leddat == NULL) {
40 printk("ioremap LED_DAT error
");
41 return -1;
42 }
43 writel(1, leddat); //设置LED3 GPX1_0 输出高电平
44
45 return 0;
46 }
47
48 int led_release(struct inode *inode, struct file *file)
49 {
50 printk("led_close
");
51 return 0;
52 }
53
54 long led_ioctl(struct file *file, unsigned int cmd, unsigned long args)
55 {
56 switch(cmd)
57 {
58 case LED_ON:
59 printk("led on ..
");
60 writel(1, leddat); //设置LED3 GPX1_0 输出高电平
61 break;
62 case LED_OFF:
63 printk("led off ..
");
64 writel(0, leddat); //设置LED3 GPX1_0 输出高电平
65 break;
66 default:
67 printk("no command
");
68 break;
69 }
70 return 0;
71 }
72
73
74 struct file_operations led_fops = { //文件操作
75 .owner = THIS_MODULE,
76 .open = led_open,
77 .release =led_release,
78 .unlocked_ioctl = led_ioctl,
79 };
80
81 static led_init(void)
82 {
83 int ret;
84 dev_t devno = MKDEV(LED_MA, LED_MI);
85 ret= register_chrdev_region(devno, LED_NUM, "newled"); //注册设备号
86 if(ret) {
87 printk("register_chrdev_region error
");
88 return -1;
89 }
90
91 cdev_init(&cdev, &led_fops); //初始化字符设备
92 ret = cdev_add(&cdev, devno, LED_NUM); //添加字符设备到系统中
93 if (ret <0) {
94 printk("cdev_add error
");
95 return -1;
96 }
97
98 printk("Led init 5
");
99 return 0;
100 }
101
102 static void led_exit(void)
103 {
104 dev_t devno = MKDEV(LED_MA, LED_MI);
105 cdev_del(&cdev);
106 unregister_chrdev_region(devno, LED_NUM); //取消注册
107 printk("Led exit
");
108 }
109
110 module_init(led_init);
111 module_exit(led_exit);
112 MODULE_LICENSE("Dual BSD/GPL");


fs4412_led_drv.c

技术图片技术图片

1 ifeq ($(KERNELRELEASE),)
2 KERNELDIR ?= /home/linux/kernel/linux-3.14-fs4412
3 PWD := $(shell pwd)
4
5 all:
6 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
7
8 clean:
9 $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
10 rm -rf a.out
11
12 else
13 obj-m := fs4412_led_drv.o
14 endif


Makefile

技术图片

  2)make 编译出ko模块

make之后(Makefile里面将module附加到了make命令后,所以直接make就好了),会自动跳到内核里面,借用内核的Makefile把当前驱动程序编译成ko文件,拷贝到根文件系统

技术图片

 

  在内核中的Kconfig,配置驱动为模块方式编译进内核

技术图片

 

将配置项改为tristate后可以选择编译为模块

技术图片

 

  4)编译所有模块 make modules

  编译模块不需要重新编译内核,make module即可。

 技术图片

    会生成以上两个文件,这个ko文件和之前单独在led目录里面make出来的ko是相同的,只是编译的环境不一样而已。选择一个拷贝到nfs即可。

  5)插入模块

  转到ko文件所在目录下

  insmod fs4412_led_drv.ko 

  创建设备节点(应用访问驱动的入口)

  mknod   /dev/led c 501 0

  6)运行测试驱动的应用程序

  ./a.out

技术图片

 

 

参考博客:

https://blog.csdn.net/m0_37542524/article/details/86476109

 


推荐阅读
  • 在进行网络编程时,准确获取本地主机的IP地址是一项基本但重要的任务。Winsock作为20世纪90年代初由Microsoft与多家公司共同制定的Windows平台网络编程接口,为开发者提供了一套高效且易用的工具。通过Winsock,开发者可以轻松实现网络通信功能,并准确获取本地主机的IP地址,从而确保应用程序在网络环境中的稳定运行。此外,了解Winsock的工作原理及其API函数的使用方法,有助于提高开发效率和代码质量。 ... [详细]
  • 在《PHP应用性能优化实战指南:从理论到实践的全面解析》一文中,作者分享了一次实际的PHP应用优化经验。文章回顾了先前进行的一次优化项目,指出即使系统运行时间较长后出现的各种问题和性能瓶颈,通过采用一些通用的优化策略仍然能够有效解决。文中不仅详细阐述了优化的具体步骤和方法,还结合实例分析了优化前后的性能对比,为读者提供了宝贵的参考和借鉴。 ... [详细]
  • 结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法
    结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法 ... [详细]
  • 本文详细介绍了如何在Linux系统中搭建51单片机的开发与编程环境,重点讲解了使用Makefile进行项目管理的方法。首先,文章指导读者安装SDCC(Small Device C Compiler),这是一个专为小型设备设计的C语言编译器,适合用于51单片机的开发。随后,通过具体的实例演示了如何配置Makefile文件,以实现代码的自动化编译与链接过程,从而提高开发效率。此外,还提供了常见问题的解决方案及优化建议,帮助开发者快速上手并解决实际开发中可能遇到的技术难题。 ... [详细]
  • Go语言实现Redis客户端与服务器的交互机制深入解析
    在前文对Godis v1.0版本的基础功能进行了详细介绍后,本文将重点探讨如何实现客户端与服务器之间的交互机制。通过具体代码实现,使客户端与服务器能够顺利通信,赋予项目实际运行的能力。本文将详细解析Go语言在实现这一过程中的关键技术和实现细节,帮助读者深入了解Redis客户端与服务器的交互原理。 ... [详细]
  • 如何利用Apache与Nginx高效实现动静态内容分离
    如何利用Apache与Nginx高效实现动静态内容分离 ... [详细]
  • 在Android平台上利用FFmpeg的Swscale组件实现YUV与RGB格式互转
    本文探讨了在Android平台上利用FFmpeg的Swscale组件实现YUV与RGB格式互转的技术细节。通过详细分析Swscale的工作原理和实际应用,展示了如何在Android环境中高效地进行图像格式转换。此外,还介绍了FFmpeg的全平台编译过程,包括x264和fdk-aac的集成,并在Ubuntu系统中配置Nginx和Nginx-RTMP-Module以支持直播推流服务。这些技术的结合为音视频处理提供了强大的支持。 ... [详细]
  • 掌握DSP必备的56个核心问题,我已经将其收藏以备不时之需! ... [详细]
  • 深入RTOS实践,面对原子操作提问竟感困惑
    在实时操作系统(RTOS)的实践中,尽管已经积累了丰富的经验,但在面对原子操作的具体问题时,仍感到困惑。本文将深入探讨RTOS中的原子操作机制,分析其在多任务环境下的重要性和实现方式,并结合实际案例解析常见的问题及解决方案,帮助读者更好地理解和应用这一关键技术。 ... [详细]
  • 在Windows环境中优化提交Spark任务的方法与实践
    在Windows环境中优化提交Spark任务的方法与实践 ... [详细]
  • 本文深入探讨了 C# 中 `SqlCommand` 和 `SqlDataAdapter` 的核心差异及其应用场景。`SqlCommand` 主要用于执行单一的 SQL 命令,并通过 `DataReader` 获取结果,具有较高的执行效率,但灵活性较低。相比之下,`SqlDataAdapter` 则适用于复杂的数据操作,通过 `DataSet` 提供了更多的数据处理功能,如数据填充、更新和批量操作,更适合需要频繁数据交互的场景。 ... [详细]
  • 本文深入探讨了Java枚举类型的使用与实践,详细解析了枚举的基本用法及其在实际开发中的应用。首先介绍了枚举作为常量的替代方案,自JDK 1.5起,通过枚举可以更加简洁、安全地定义常量,避免了传统方式中可能出现的错误。此外,文章还探讨了枚举在实现单例模式、状态机等场景中的优势,并提供了多个实际案例,帮助开发者更好地理解和运用这一强大的语言特性。 ... [详细]
  • 如何在Spark数据排序过程中有效避免内存溢出(OOM)问题
    本文深入探讨了在使用Spark进行数据排序时如何有效预防内存溢出(OOM)问题。通过具体的代码示例,详细阐述了优化策略和技术手段,为读者在实际工作中遇到类似问题提供了宝贵的参考和指导。 ... [详细]
  • 深入解析JavaScript词法分析的具体流程与常见问题 ... [详细]
  • Java 零基础入门:SQL Server 学习笔记(第21篇)
    Java 零基础入门:SQL Server 学习笔记(第21篇) ... [详细]
author-avatar
韦凯孟强志宪
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有