嵌入式Linux驱动程序设计

嵌入式Linux驱动程序设计:平台总线模型 在嵌入式Linux系统中,驱动程序起着至关重要的作用,它们连接硬件和操作系统,实现数据的传输和设备的控制。在嵌入式Linux系统中,驱动程序起着至关重要的作用,它们连接硬件和操作系统,实现数据的传输和设备的控制。在平台总线模型中,设备是指嵌入式系统中的硬件设备,如传感器、执行器、存储器等。平台总线模型中的总线是设备和驱动程序之间的中间层,用于管理设备的注册、注销、设备驱动程序的绑定和解绑等操作。平台总线模型中的总线是设备和驱动程序之间的中间层,用于管理设备的注册、注销、设备驱动程序的绑定和解绑等操作。 阅读详情

在 Unix like 系统中,正是有了驱动程序才使得用户可以完全透明的使用计算机系统。设备驱动隐藏了硬件设备的具体的细节和功能,对于不同的硬件设备都提供了一致的接口。比如在 Linux 系统中,为了便于用户的使用,系统把计算机系统的各种设备映射成一系列的特殊的设备文件,叫设备文件节点。用户可以任意的使用它来协助自己完成任何工作。在 Linux 系统中,所有的设备都可归为三类之列,一是字符设备,如键盘等;二是块设备,如磁盘等;第三种就是用于网络的网络设备,这类设备主要是用于网络通讯中,在其他的地方没有什么特别使用。

 

一、              设备驱动程序的三个主要组成部分

1、  自动配置和初始化子程序;

2、  为 I/O 提供服务的子程序;

3、  中断子程序;

 

二、              设备驱动入口点分析

此处以字符设备为例列举设备驱动程序的入口点

1、  open 入口点:设备 I/O 操作之前进行的操作,打开了设备后准备 I/O 操作;

2、  close 入口点:对设备操作完成之后对设备的关闭操作;

3、  read 入口点:完成对设备的 open 操作之后就可以以此入口点在设备上读取数据;

4、  write 入口点:完成对设备的 open 操作之后就可以以此入口点在设备上写入数据;

5、  ioctl 入口点:在设备上执行 I/O 控制操作;

6、  select 入口点:在数据写入或读取之前对设备的检测操作。

 

三、              Linux 系统下的设备驱动程序

以下借用 Linux 系统内核的代码来分析字符设备驱动程序

1 、以下是入口点的结构体定义:

#/usr/include/linux/fs.h

struct file_operations {

    struct module *owner;

    loff_t (*llseek) (struct file *, loff_t, int);

    ssize_t (*read) (struct file *, char *, size_t, loff_t *);

    ssize_t (*write) (struct file *, const char *, size_t, loff_t *);

    int (*readdir) (struct file *, void *, filldir_t);

    unsigned int (*poll) (struct file *, struct poll_table_struct *);

    int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);

    int (*mmap) (struct file *, struct vm_area_struct *);

    int (*open) (struct inode *, struct file *);

    int (*flush) (struct file *);

     int (*release) (struct inode *, struct file *);

    int (*fsync) (struct file *, struct dentry *, int datasync);

    int (*fasync) (int, struct file *, int);

    int (*lock) (struct file *, int, struct file_lock *);

    ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);

    ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);

    ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);

    unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);

};

2 、入口点 file_operations 分析:

       1>  lseek ,移动文件指针的位置,用于可随机存取的设备;

2>       read ,设备读操作,参数 buf 指向的是存放读取结果的缓冲池, count 为将要读取的数据的长度。若函数返回值为负,表示读取操作出错;若操作成功,则返回实际的读取的字节;

3>       write ,设备写操作;

4>       ioctl ,进行除设备的读写之外的控制操作;

5>       open ,打开一个设备,并对其 I/O 操作准备。函数返回值为 0 表示设备打开成功,若返回负,表示操作失败;

6>       release ,设备的 close 操作;

4、  Linux 系统下,字符设备驱动的注册:

在 Linux 里通过调用 register_chrdev 向操作系统注册字符型的设备驱动,其定义为:

int register_chrdev(unsigned int major, const char *name,

                const struct file_operations *fops) ;

参数说明:

major 是设备驱动程序注册的主设备号,若为 0 则系统为此驱动程序动态地分配一个主设备号。

name 是设备文件节点名。此函数返回 0 表示成功。返回 -EINVAL 表示申请的主设备号不合法,一般来说是因为主设备号大于系统所允许的最大设备号。返回 -EBUSY 表示所申请的主设备号正在被其它设备驱动程序使用。如果是动态分配主设备号成功,此函数将返回所分配的主设备号。如果 register_chrdev 操作成功,设备名就可以在 /proc/devices 文件里看到。

这里看到的就是一段设备驱动经过注册之后在 /proc/devices 下面看到的结果

 

四、              字符设备驱动程序示例及其分析

//#define CONFIG_DEVFS_FS  /* 系统是否支持 devfs*/

#ifndef __KERNEL__             /* 编译进内核 */

# define __KERNEL__

#endif

#ifndef MODULE

#  define MODULE          /* 以模块方式编译 */

#endif

#include <linux/config.h>            /* 配置头文件   */

#include <linux/module.h>           /* 驱动模型头文件 */

#include <linux/devfs_fs_kernel.h>   /* 设备文件系统头文件 */

#include <linux/init.h>         /* 初始化相关头文件 */

#include <linux/kernel.h>   /* 与 printk() 等函数有关的头文件 */

#include <linux/slab.h>     /* 与 kmalloc() 等函数有关的头文件 */

#include <linux/fs.h>       /* 与文件系统有关的头文件 everything... */

#include <linux/errno.h>    /* 错误代码处理头文件 error codes */

#include <linux/types.h>    /* 数据类型头文件 size_t */

#include <linux/proc_fs.h>    /* 与进程调度相关的头文件 */

#include <linux/fcntl.h>     /* O_ACCMODE */

#include <linux/poll.h>     /* COPY_TO_USER */

#include <asm/system.h>     /* cli(), *_flags */

#define DEVICE_NAME             " demo"  /* 该驱动的设备名 */

#define demo_MAJOR 254               /* 驱动主设备号 */

#define demo_MINOR 0                  /* 驱动次设备号 */

static int MAX_BUF_LEN=1024;           /* 定义一缓冲区最大长度 */

static char drv_buf[1024];                  /* 定义一缓冲区 */

static int WRI_LENGTH=0;

/***********************************************************************

* 名称: demo_write ()

* 功能:对应用户空间的 write 系统调用,从用户空间拷贝给定长度缓冲区数据到内核空间

* 入口参数: *filp 操作设备文件的 ID , *buffer 对应用户空间的缓冲区的起始地址, count 用户空间数据缓冲区长度

* 出口参数:返回用户空间数据缓冲区长度

**********************************************************************/

static ssize_t  demo_write(struct file *filp,const char *buffer, size_t count)

{

       if(count > MAX_BUF_LEN)count = MAX_BUF_LEN;

       copy_from_user(drv_buf , buffer, count);   /* 从用户空间拷贝缓冲区数据到内核空间的关键函数,把用户空间的 buffer 数据传递给 drv_buf 数组 */

       WRI_LENGTH = count;

       printk("user write data to driver/n");

       do_write();    

       return count;

}

/***********************************************************************

* 名称: static void do_write()

* 功能:

* 入口参数:无

* 出口参数:无

**********************************************************************/

static void do_write()

{

       int i;

       int len = WRI_LENGTH;

       char tmp;

       for(i = 0; i < (len>>1); i++,len--){

              tmp = drv_buf[len-1];

              drv_buf[len-1] = drv_buf[i];

              drv_buf[i] = tmp;

       }

}

/*************************************************************

* 名称: demo_ read ()

* 功能:对应用户空间的 read 系统调用,从内核空间拷贝给定长度缓冲区数据到用户空间

* 入口参数: *filp 操作设备文件的 ID , *buffer 对应用户空间的缓冲区的起始地址, count 用户空间数据缓冲区长度, *ppos 用户在文件中进行存储操作的位置

* 出口参数:返回用户空间数据缓冲区长度

**********************************************************************/

 

static ssize_t  demo_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)

{

       if(count > MAX_BUF_LEN)

              count=MAX_BUF_LEN;

         copy_to_user(buffer, drv_buf,count);        /* 从内核空间拷贝缓冲区数据到用户空间的关键函数,把内核空间经过逆序排列后的 drv_buf 数组传递给用户空间的 buffer 数组 */

       printk("user read data from driver/n");

       return count;

}

/***********************************************************************

* 名称: demo_ioctl ()

* 功能:对应用户空间的 ioctl 系统调用,对用户空间传递过来的命令进行 swith 判断,并进行相应处理,本函数只对用户空间传递过来的 1 , 2 做简单的处理,打印一条信息

* 入口参数: *filp 操作设备文件的 ID , cmd 对应用户空间的 cmd , arg 对应用户空间传递过来的参数

列表

* 出口参数:正确返回 0 ,错误命令返回 default 的提示内容

**********************************************************************/

static int demo_ioctl(struct inode *inode, struct file *file,

                 unsigned int cmd, unsigned long arg)

{

       switch(cmd){

              case 1:printk("runing command 1 /n");break;

              case 2:printk("runing command 2 /n");break;

              default:

                     printk("error cmd number/n");break;

       }

       return 0;

}

/***********************************************************************

* 名称: static void demo_open ()

* 功能:设备文件打开函数,对应用户空间 open 系统调用,

* 入口参数:设备文件节点

* 出口参数:无

**********************************************************************/

static int demo_open(struct inode *inode, struct file *file)

{

MOD_INC_USE_COUNT;   

       printk("device open sucess!/n");

       return 0;

}

* 名称: static int  demo_release

* 功能:设备文件释放函数,对应用户空间 close 系统调用,

* 入口参数:设备文件节点

* 出口参数:无

**********************************************************************/

static int  demo_release(struct inode *inode, struct file *filp)

{

       MOD_DEC_USE_COUNT;

       printk("device release/n");

       return 0;

}

嵌入式Linux系统下的USB OTG驱动程序设计与实现 本文还有配套的精品资源,点击获取 简介:基于ChipIdea公司的USB IP核实现的OTG驱动程序为嵌入式Linux系统带来了USB主机和设备角色之间的切换能力,使得设备能够直接进行数据传输。本项目深入讲解了如何将ChipIdea的USB OTG控制器驱动程序集成到Linux内核中,并提供了源代码文件"otg.c"和"otg.h"。学习该项目需要对USB协议、OTG规范、... 阅读详情

相关推荐

避坑指南:Ubuntu 22.04上源码编译Autoware.universe(Humble版)的完整流程与常见错误修复

本文详细介绍了在Ubuntu 22.04上源码编译Autoware.universe(Humble版)的完整流程与常见错误修复方法。从环境准备、依赖安装到编译优化,提供了实用的避坑指南和解决方案,帮助开发者高效完成安装并避免常见问题。特别针对源码安装过程中的疑难杂症给出了具体修复建议。

weixin_33712987的博客 382

Linux嵌入式与驱动开发,嵌入式Linux驱动开发基础总结(上篇)

描述1, linux驱动一般分为3大类:* 字符设备* 块设备* 网络设备2, 开发环境构建:* 交叉工具链构建* NFS和tftp服务器安装3, 驱动开发中设计到的硬件:* 数字电路知识* ARM硬件知识* 熟练使用万用表和示波器* 看懂芯片手册和原理图4, linux内核源代码目录结构:* arch/: arch子目录包括了所有和体系结构相关的核心代码。它的每一个子目录都代表一种支...

weixin_35895994的博客 717

STM32CubeMX+FreeRTOS实战:3步搞定LED任务配置(附代码解析)

本文详细解析了如何使用STM32CubeMX图形化工具配置FreeRTOS实时操作系统,并创建LED闪烁任务。通过剖析MX_FREERTOS_Init()函数和CMSIS-RTOS封装层,深入理解任务创建、调度及osDelay()协作机制,帮助开发者从点击生成进阶到内核原理掌握,实现高效的多任务嵌入式开发。

weixin_29192141的博客 468

嵌入式驱动程序设计

嵌入式驱动程序设计

咸鱼弟的博客 5173

CST高阶技巧:用周期性边界快速仿真共面波导色散特性(含JDM求解器优化)

本文详细介绍了在CST仿真软件中,利用周期性边界条件结合JDM本征模求解器,高效分析共面波导色散特性的高阶技巧。该方法通过仿真一个单元胞而非整条传输线,大幅提升计算效率,并提供了从建模、边界设置、求解器优化到后处理的完整工作流程,是高频电路设计的实用指南。

weixin_29280219的博客 403

Mac安装Weblogic教程

1.Weblogic的下载 这次安装的是最新版本12 官网下载地址: http://www.oracle.com/technetwork/middleware/weblogic/downloads/index.html 下载需要登录账号,如没有账号要注册一个 下载后的文件如下图,其中fmw_12.2.1.3.0_wls_quick.jar文件就是安装包了,注意现在不要对它进行解压 2.安装前的确...

weixin_40102675的博客 5063

基于龙芯 2K1000 的嵌入式 Linux 系统移植和驱动程序设计(二)

环境,因此需要汇编代码来完成一些处理器和内存等设备的初始化,完成准备工作。进程的软件,因此进程调度属于内核中非常重要的功能。但是根文件系统负责配置工作,不同的处理器配置方法和具体内容不同,因此根文件系统和内核分离,可以让嵌入。程调度会通过合理切换多进程让宏观上多进程并行,无论何时都有进程运行,使。中它与内核一般是分开的,这是由于内核负责一些进程调度等操作系统的基本工。通过使用可执行脚本,将编译根文件系统步骤放在一个脚本文件中,减少操作。配置串口的波特率,由于本课题中不使用串口而是直接外接屏幕来显示,因此。

YEYUANGEN的专栏 2355

半导体晶圆调平系统:基于最小二乘法的实现方案

基于最小二乘法的晶圆调平技术通过数学建模与工程实现的结合,解决了半导体量测中高精度平面对准的核心问题。实际应用中,需根据设备特性优化采样策略、校准传感器误差,并通过实时性优化满足高产能场景需求。该方案的模块化设计(如分离数据采集、拟合计算、补偿输出)也为后续功能扩展(如引入机器学习优化拟合模型)提供了灵活性。

品质生活,极致编程。 1181

(八)嵌入式:Linux驱动程序的设计方法以及测试

本次实验我们开始学习驱动,首先了解什么是驱动,驱动程序全称设备驱动程序,是添加到操作系统中的特殊程序,其中包含有关硬件设备的信息。此信息能够使计算机与相应的设备进行通信。驱动程序是硬件厂商根据操作系统编写的配置文件,可以说没有驱动程序,计算机中的硬件就无法工作。那么驱动就是联系硬件也操作系统的关键所在。 本次实验要体会新增一个字符设备驱动的流程,添加驱动有两种方式,一种是在内核代码里面静态添加,随...

wahahaguolinaiyou的博客 2219

小龙虾们的好伙伴专栏导航

本文系统解析了OpenClaw技术架构,包括Channel层和网关层的设计实现,并与AgentSkills等技术方案进行对比。同时提供了OpenClaw的系列实用指南,涵盖小龙虾培养、客户资源管理、系统自动化巡检以及技术趋势助手构建等应用场景,帮助用户从零成本入门到高效落地应用,实现业务全流程自动化管理。

wend的博客 212

Autosar诊断实战系列07-Dcm之0x19 06扩展数据配置及工程问题讨论

19 06扩展数据如何配置?如果某DTC没有出现过故障扩展数据该如何响应?

initiallizer的博客 1704

Virtualmen字符设备驱动代码-----虚拟磁盘设备

驱动程序:Virtualmen.c   #include &lt;linux/init.h&gt; #include &lt;linux/module.h&gt; #include &lt;linux/types.h&gt; #include &lt;linux/fs.h&gt; #include &lt;linux/errno.h&gt; #include &lt;linux/cdev.h...

刘先森的博客 555

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

嵌入式Linux下的LCD驱动程序设计与实现

随着嵌入式Linux的迅速发展,由于其没有昂贵的版权费,完全开放源代码,可裁减性与可移植性,因此是开发嵌入式产品的优秀操作系统平台。设备驱动程序是Linux内核的重要组成部分,运行在Linux内核底层,在内核源代码中占较大比例,驱动程序开发逐渐成为嵌入式软件开发中一项重要工作。应项目设计的需要完成了嵌入式Linux下的LCD驱动程序设计。 1 Linux下设备驱动程序 驱动程序从字面上可以

敏于思,慎于行 1450

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

基于嵌入式Linux的千兆以太网卡驱动程序设计及测试

基于嵌入式Linux的千兆以太网卡驱动程序设计及测试 一.引言 千兆以太网是一种具有高带宽和高响应的新网络技术,相关协议遵循IEEE802.3规范标准。采用和10M以太网相似的帧格式、网络协议和布线系统,基于光纤和短距离同轴电缆的物理层介质,更适用于交换机、服务器等数据吞吐率大的设备。本文设计实现一种基于嵌入式Linux千兆以太网卡的驱动程序,并完成后续的测试工作和代码移植。 ...

634

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

我的嵌入式LINUX学习.卷42------I2C驱动程序设计

一棹春风一叶舟,一纶茧缕一轻钩 190

(八)嵌入式 Linux驱动程序设计之字符设备驱动框架

(八)嵌入式 Linux驱动程序设计之GPIO驱动 总结: 1. 在/arch/arm/boot/dts/imx6q-pinfunc.h查找 2. 在设备树配置文件中添加设备节点定义以及其引脚定义 3. 修改设备树文件添加配置 4. drivers/gpio目录下添加gpio驱动 新建driver/gpio/gpio-user.c 在`driver/gpio/Makefile`添加: 在driver/gpio/Kconfig添加: 5. 通过make menuconfig来进行配置

weixin_45787652的博客 179

我的嵌入式LINUX学习.卷40------LCD驅動程序設計

一棹春风一叶舟,一纶茧缕一轻钩 174

我的嵌入式LINUX学习.卷39------觸摸屏驅動程序設計

一棹春风一叶舟,一纶茧缕一轻钩 158

嵌入式linux驱动程序设计从入门到精通_嵌入式驱动程序设计的五个窍门

每一个嵌入式应用软件都会在某些时候访问最底层的固件和进行一些硬件控制。 驱动的设计和实施是确保一个系统能够满足其实时性要求的关键。以下五个窍门是每一个开发者在设计驱动程序时应该考虑的。1.使用设计模式设计模式是一个用来处理那些在软件中会重复出现的问题的解决方案。 开发人员可以选择浪费宝贵的时间和预算从无到有地重新发明一个解决方案,也可以从他的解决方案工具箱中选择一个最适合解决这个问题的方案。在微处...

weixin_39615741的博客 309

我的嵌入式LINUX学习.卷37------串口驅動程序設計

一棹春风一叶舟,一纶茧缕一轻钩 129

我的嵌入式LINUX学习.卷43------SPI驱动程序设计

一棹春风一叶舟,一纶茧缕一轻钩 229

(一)嵌入式 Linux驱动程序设计之驱动模块编译

嵌入式: 交叉学科,知识体系庞杂 C语言 数电(单片机) arm体系结构 硬件设计(arm接口技术) Linux系统开发 Linux驱动开发 BootLoader(UBOOT) QT(C++) Android系统和JAVA Linux驱动分类: 字符设备驱动 块设备驱动(EMMC等存储相关) 网络设备驱动 驱动分为4部分: 头文件 驱动模块入口和出口 声明信息 功能实现 //第一步 包含头文件 #include<linux/init.h>//包含宏定义头文件 #include

weixin_45787652的博客 894

嵌入式linux驱动程序设计从入门到精通_嵌入式从入门到精通需要学什么

我们这里主要介绍ARM+LINUX学习路线,如果你做过单片机,那么对学习ARM+LINUX是有帮助的,但是如果没有单片机基础,也没必要先学51,AVR等单片机。对嵌入式LINUX操作系统及其上应用软件开发目标:1、 掌握主流嵌入式微处理器的结构与原理(ARM9相对比较容易)。2、 必须掌握一个嵌入式操作系统,如LINUX系统,这是一个开源的系统。3、 必须熟悉嵌入式软件开发流程并做一些嵌...

weixin_39833763的博客 417
上一篇: windows真的很有意思 你发现了吗?
下一篇: 作用域模型分析
Qicz
博客等级 码龄16年 56粉丝 122原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值