韦东山嵌入式Liunx入门驱动开发四

news2024/12/27 15:06:02

文章目录

      • 一、异常与中断的概念及处理流程
        • 1-1 中断的引入
        • 1-2 栈
          • (1) CPU实现a = a+b的过程
          • (2) 进程与线程
        • 1-3 Linux系统对中断处理的演进
        • 1-4 Linux 中断系统中的重要数据结构
          • (1) irq_desc 结构体
          • (2) irqaction 结构体
          • (3) irq_data 结构体
          • (4) irq_domain 结构体
          • (5) irq_domain 结构体
        • 1-5 设备树中的中断
          • (1) 设备树里的中断控制器和使用中断
          • (2) 在代码中获得中断
        • 1-6 编写使用中断的按键驱动程序

本人学习完韦老师的视频,因此来复习巩固,写以笔记记之。
韦老师的课比较难,第一遍不知道在说什么,但是坚持看完一遍,再来复习,基本上就水到渠成了。
看完视频复习的同学观看最佳!
基于 IMX6ULL-PRO
参考视频 Linux快速入门到精通视频
参考资料:01_嵌入式Linux应用开发完全手册V5.1_IMX6ULL_Pro开发板.pdf

一、异常与中断的概念及处理流程

1-1 中断的引入

首先中断属于一种异常
中断需要保存现场(各类寄存器)、处理异常、恢复现场。
1、初始化:①设置中断源,让它可以产生中断;②设置中断控制器 (可以屏蔽某个中断,优先级);③设置 CPU总开关 (使能中断 )
2、执行其他程序 正常进行
3、产生中断 :比如 按下按键 —>中断控制器 —>CPU
4、CPU 每执行完一条指令都会检查有无中断 /异常产生;
5、CPU发现有中断 /异常产生,开始处理。
对于不同的异常,跳去不同的地址执行程序。这地址是异常向量表,只是一条跳转指令,跳去执行某个函数,
“ldr pc,_irq”:cpu首先跳转到0x18偏移地址,然后将_irq的地址传入pc指针,再跳转了_irq的地址去执行某个函数
在这里插入图片描述6、某个函数做什么事情
① 保护现场(各种寄存器的值)
② 处理异常(中断):判断中断源,在调用对应的处理函数(如按键、网卡、USB等)
③ 恢复现场

1-2 栈
(1) CPU实现a = a+b的过程

ARM芯片属于精简指令集计算机 (RISC Reduced Instruction Set
Computing),它所用的指令比较简单,有如下特点:
① 对内存只有读、写指令
② 对于数据的运算是在CPU内部实现
③ 使用RISC指令的CPU复杂度小一点,易于设计
实现a = a+b
CPU 运行时,先去取得指令,再执行指令:
① 把内存a 的值读入CPU 寄存器R0
② 把内存b 的值读入CPU 寄存器R1
③ 把R0、R1 累加,存入R0
④ 把R0 的值写入内存a
在这里插入图片描述

(2) 进程与线程

在Linux 中:资源分配的单位是进程,调度的单位是线程。
进程

  • 进程是程序的一次执行过程,是操作系统进行资源分配和调度的基本单位。每个进程都拥有独立的内存空间,包括代码、数据和堆栈等。
  • 每个进程都由操作系统分配唯一的进程标识符(PID),并且拥有自己的地址空间、文件描述符、系统资源等。
  • 进程之间通常是相互独立的,彼此不会直接影响到对方的运行状态(除非通过特定的IPC机制进行通信)。
  • 操作系统通过调度算法来管理进程的执行顺序,以及为每个进程分配处理器时间。

线程

  • 线程是进程中的实际执行单位,一个进程可以包含多个线程,它们共享同一个进程的地址空间和系统资源,但是每个线程有独立的栈空间
  • 线程之间可以方便地共享数据,因为它们处于同一个进程的上下文中。
  • 多线程程序可以充分利用多核处理器的并行性能,提高程序的执行效率。
  • 线程的切换开销通常比进程小,因为它们共享了很多资源,如内存空间等。

多线程编程,读取按键是一个线程,播放音乐是另一个线程,它们之间可以通过全局变量传递数据,示意代码如下:

int g_key;
void key_thread_fn()
{
	while(1){
		if(g_key != -1){
			switch(g_key){
				case NEXT:
					select_next_music(); /*在GUI选中下一首歌*/
					break;
			}
		}
	}
}

void music_fn()
{
	while(1){
		if(g_key == STOP)
			stop_music();
		else{
			send_music();
		}
	}
}

int main(int argc, char **argv)
{
	int key;
	create_threads(key_tehread_fn);
	create_threads(music_fn);

	while(1){
		sleep(10);
	}
	return 0;
}
1-3 Linux系统对中断处理的演进

Linux系统中断
在Linux 中,中断处理程序的执行也可能会影响进程的调度情况,例如通过唤醒等待中的进程,或者改变进程的优先级等。
中断耗时处理方法
1、分为上下半部分进行执行。上半部:处理紧急事情,无法被打断;下半部:可以被打断
2、用内核线程处理中断
系统中有硬件中断,也有软件中断。对硬件中断的处理有 2 个原则:不能嵌套,越快越好。
硬件中断:每个硬件中断都有对应的处理函数,比如按键中断、网卡中断的处理函数肯定不一样。
简单的认为硬件中断的处理是用数组来实现的,数组里存放的是函数指针。当发生A中断时,对应的irq_function_A 函数被调用。硬件导致该函数被调用。
在这里插入图片描述
软件中断:由软件决定,对于X号软件中断,只需要把它的flag 设置为1就表示发生了该中断。在处理完硬件中断后,再去处理软件中断。
在这里插入图片描述
在Linux 系统中使用中断,可以使用request_irq函数为某个中断irq注册中断处理函数handler,handler运行中断的上半部分,并且触发软中断或者把工作放入工作队列,使用线程化来处理中断下半部分。

request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
	    const char *name, void *dev)
{
	return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}

中断下半部的实现有很多种方法,2种主要的:tasklet、work queue(工作队列)。
当下半部比较耗时但是能忍受,并且它的处理比较简单时,可以用tasklet来处理下半部。tasklet是使用软件中断来实现。
在Linux中,中断是不会被嵌套执行的,但是中断处理程序中可能会触发延迟处理机制,导致在下半部处理中处理其他中断请求。

enum
{
	HI_SOFTIRQ=0,
	TIMER_SOFTIRQ,
	NET_TX_SOFTIRQ,
	NET_RX_SOFTIRQ,
	BLOCK_SOFTIRQ,
	IRQ_POLL_SOFTIRQ,
	TASKLET_SOFTIRQ, /*通过软中断机制实现的,允许将一些需要延迟处理的任务放入任务队列中,在适当的时机执行。*/
	SCHED_SOFTIRQ,
	HRTIMER_SOFTIRQ, /* Unused, but kept as tools rely on the
			    numbering. Sigh! */
	RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */

	NR_SOFTIRQS
};

中断要做的事情实在太耗时,应该用内核线程来做:在中断上半部唤醒内核线程。

最新的中断处理方法
在这里插入图片描述

request_threaded_irq(unsigned int irq, irq_handler_t handler,
		     irq_handler_t thread_fn,
		     unsigned long flags, const char *name, void *dev);

这个函数通常用于注册一个中断处理程序,当中断发生时,会调用指定的中断处理函数来处理中断,而线程中断处理函数则会在一个独立的线程中运行,以避免中断处理函数执行时间过长导致系统性能下降。
unsigned int irq: 要请求的中断号。
irq_handler_t handler: 中断处理函数,当中断发生时会被调用。
irq_handler_t thread_fn: 线程中断处理函数,会在一个独立的线程中执行。
unsigned long flags: 用于指定中断处理的标志,比如中断类型等。
const char *name: 中断处理函数的名称。
void *dev: 传递给中断处理函数的设备数据指针。

1-4 Linux 中断系统中的重要数据结构
(1) irq_desc 结构体

在Linux 内核中有一个中断数组,对于每一个硬件中断,都有一个数组项,这个数组就是irq_desc 数组。irq_desc 结构体在include/linux/irqdesc.h 中定义。
每一个irq_desc 数组项中都有一个函数:handle_irq,还有一个action链表。
在这里插入图片描述

(2) irqaction 结构体

irqaction 结构体在include/linux/interrupt.h中定义。
当调用request_irq 、request_threaded_irq 注册中断处理函数时,内核就会构造一个 irqaction 结构体。在里面保存 name、dev_id 等,最重要的是 handler 、thread_fn 、thread 。
handler是中断处理的上半部函数,用来处理紧急的事情。
thread_fn对应一个内核线程thread ,当handler 执行完毕,Linux内核会唤醒对应的内核线程。在内核线程里,会调用 thread_fn函数。

在这里插入图片描述

(3) irq_data 结构体

irq_descirq_data结构体在 include/linux/irq.h 中定义,它就是个中转站,里面有irq_chip 指针 irq_domain 指针,都是指向别的结构体。
在这里插入图片描述

(4) irq_domain 结构体

irq为软件中断号,hwirq为硬件中断号。 irq_domain会把本地的hwirq映射为全局的irq。
比如GPIO控制器里有第1号中断,UART模块里也有第1号中断,这两个第1号中断是不一样的,它们属于不同的“域”── irq_domain
设备树的中断通过irq_domain结构体的irq_domain_ops 结构体的一系列函数转换为request_irq(irq, handler)中的irq。
irq_domain结构体在 include/linux/irqdomain.h 中定义
在这里插入图片描述
在这里插入图片描述

(5) irq_domain 结构体

irq_chip结构体在include/linux/irq.h 中定义
在这里插入图片描述
我们在request_irq 后,并不需要手工去使能中断,原因就是系统调用对应的irq_chip 里的函数帮我们使能了中断。
我们提供的中断处理函数中,也不需要执行主芯片相关的清中断操作,也是
系统帮我们调用irq_chip 中的相关函数。

1-5 设备树中的中断
(1) 设备树里的中断控制器和使用中断

在设备树中,中断控制器节点中必须有一个属性:interrupt-controller,表明它是中断控制器。还必须有一个属性:#interrupt-cells,表明引用这个中断控制器的话需要多少个cell。
一个外设的设备树里需要有这连个属性interrupt parent=<&XXXX>:你要用哪一个中断控制器里的中
断?interrupts:你要用哪一个中断?

#interrupt cells=<2>

别的节点要使用这个中断控制器时,需要一个cell来表明使用哪一个中断;还需要另一个cell来描述中断,一般是表明触发类型。
第 2个cell的 bits[3:0] 用来表示中断触发类型 trigger type and level flags)
1 = low to high edge triggered ,上升沿触发
2 = high to low edge triggered ,下降沿触发
4 = active high level sensitive ,高电平触发
8 = active low level sensitive ,低电平触发

一个interrupts extended 属性就可以既指定 interrupt parent也指定interrupt

interrupts extended = <&intc1 5 1>, <&intc2 1 0>;
(2) 在代码中获得中断

platform_device
一个节点能被转换为platform_device ,如果它的设备树里指定了中断属
性,那么可以从 platform_device中获得中断资源,可以使用下列函数获得 IORESOURCE_IRQ 资源,即中断号。

/**
 * platform_get_resource - get a resource for a device
 * @dev: platform device
 * @type: resource type
 * @num: resource index
 */
struct resource *platform_get_resource(struct platform_device *dev,
				       unsigned int type, unsigned int num)
{
	int i;

	for (i = 0; i < dev->num_resources; i++) {
		struct resource *r = &dev->resource[i];

		if (type == resource_type(r) && num-- == 0)
			return r;
	}
	return NULL;
}

对于I2C设备、SPI设备
对于I2C 设备节点,I2C总线驱动在处理设备树里的I2C子节点时,也会处
理其中的中断信息。一个I2C设备会被转换为一个i2c_client 结构体,中断号会保存在i2c_client的irq成员里。代码:drivers/i2c/i2c core.c
在这里插入图片描述
在这里插入图片描述
对于SPI设备节点,SPI总线驱动在处理设备树里的 SPI 子节点时,也会处
理其中的中断信息。一个SPI设备会被转换为一个spi_device结构体,中断号会保存在spi_device的的irq成员里,代码如下drivers/spi/spi.c
在这里插入图片描述
在这里插入图片描述

③ 调用of_irq_get 获得中断号
在驱动程序中自行调用 o f_irq_get 函数去解析设备树,得到中断号。
④ 对于GPIO
参考:drivers/input/keyboard/gpio_keys.c

gpio keys {
	compatible = "gpio keys";
	pinctrl names = "default";
	
	user {
		label = "User Button";
		gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
		gpio-key,wakeup;
		linux,code = <KEY_1>;
		};
}

使用下面函数获取引脚和flag

button -->gpio = of_get_gpio_flags(pp, 0, &flags);
bdata -->gpiod = gpio_to_desc(button->gpio);

再使用gpiod_to_irq获取中断号

irq = gpiod_to_irq(bdata->gpiod);
1-6 编写使用中断的按键驱动程序

设备树编写
节点信息
在这里插入图片描述
pinctrl子系统(实验结果显示不添加也可以,因为这两个GPIO引脚默认工作于GPIO模式)
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1481929.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

T3SF:一款功能全面的桌面端技术练习模拟框架

关于T3SF T3SF是一款功能全面的桌面端技术练习模拟框架&#xff0c;该工具针对基于主场景事件列表的各种事件提供了模块化的架构&#xff0c;并包含了针对每一个练习定义的规则集&#xff0c;以及允许为对应平台参数定义参数的配置文件。 该工具的主模块能够执行与其他特定模…

BetterDisplay Pro for Mac v2.0.11激活版:屏幕显示优化专家

BetterDisplay Pro是一款由waydabber开发的Mac平台上的显示器校准软件&#xff0c;可以帮助用户调整显示器的颜色和亮度&#xff0c;以获得更加真实、清晰和舒适的视觉体验。 软件下载&#xff1a;BetterDisplay Pro for Mac v2.0.11激活版下载 &#x1f50d; 精准校准&#xf…

Python实现DMI工具判断信号:股票技术分析的工具系列(3)

Python实现DMI工具判断信号&#xff1a;股票技术分析的工具系列&#xff08;3&#xff09; 介绍算法解释 代码rolling函数介绍完整代码 介绍 先看看官方介绍&#xff1a; DMI (趋向指标&#xff09; 用法 1.PDI线从下向上突破MDI线&#xff0c;显示有新多头进场&#xff0c;为…

vscode+remote突然无法连接服务器以及ssh连接出问题时的排错方法

文章目录 设备描述状况描述解决方法当ssh连接出问题时的排错方法 设备描述 主机&#xff1a;win11&#xff0c;使用vscode的remote-ssh插件 服务器&#xff1a;阿里云的2C2GUbuntu 22.04 UFIE 状况描述 之前一直使用的是vscode的remote服务&#xff0c;都是能够正常连接服务…

LabVIEW流量控制系统

LabVIEW流量控制系统 为响应水下航行体操纵舵翼环量控制技术的试验研究需求&#xff0c;通过LabVIEW开发了一套小量程流量控制系统。该系统能够满足特定流量控制范围及精度要求&#xff0c;展现了其在实验研究中的经济性、可靠性和实用性&#xff0c;具有良好的推广价值。 项…

在学习云原生的时候,一直会报错ImagePullBackOff Back-off pulling image

在学习云原生的时候&#xff0c;一直会报错 &#xff08;见最后几张图&#xff09; ImagePullBackOff Back-off pulling image 然后我就在像。这个配置的镜像是不是可以自己直接下载&#xff0c;但是好像不怎么搜索得到 然后就在想&#xff0c;这个lfy_k8s_images到底是个啥玩…

TikTok矩阵系统功能怎么写?常用源代码是什么?

TikTok矩阵系统的功能是如何编写的?又有哪些常用的源代码支撑这些功能呢?本文将通过五段源代码的分享&#xff0c;为大家揭开TikTok矩阵系统的神秘面纱。 一、TikTok矩阵系统的核心功能 TikTok的矩阵系统涵盖了多个核心功能&#xff0c;包括但不限于用户管理、内容分发、推…

飞腾平台编译安装openGauss数据库

1. 环境检查 1.1 检查OS版本 openGauss支持的操作系统&#xff1a; CentOS 7.6&#xff08;x86_64 架构&#xff09;openEuler-20.03-LTS&#xff08;aarch64 架构&#xff09;openEuler-20.03-LTS&#xff08;x86_64架构&#xff09;Kylin-V10&#xff08;aarch64 架构&…

mysql-Synch-clickhouse

Synch GitHub - long2ice/synch: Sync data from the other DB to ClickHouse(cluster) 环境&#xff1a; mysql5.7 redis > 5.0 clickhouse21.2 postgresql python3 binlog_formatrow XREAD default pg_config synch 1&#xff1a;安装clickhouse rpm下载地址&…

map和set例题应用

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 第一题 第二题 第三题 第一题 随机链表的复制https://leetcode.cn/problems/copy-list-with-random-pointer/description/ 思路 首先遍历旧链表&#xff0c;并创建新节点&#xff0c;同时用map将旧节点与新节点…

ICASSP2024 | ICMC-ASR 车载多通道语音识别挑战赛总结

为促进驾驶场景中语音处理和识别研究&#xff0c;在ISCSLP 2022上成功举办智能驾驶座舱语音识别挑战 (ICSRC)的基础上&#xff0c;西工大音频语音与语言处理研究组 (ASLPNPU)联合理想汽车、希尔贝壳、WeNet社区、字节、微软、天津大学、南洋理工大学以及中国信息通信研究院等多…

动态规划--(算法竞赛、蓝桥杯)--二维费用背包

1、B站视频链接&#xff1a;E15 背包DP 二维费用背包_哔哩哔哩_bilibili #include <bits/stdc.h> using namespace std; int f[101][101]; //f[j][k]第i件物品&#xff0c;体积<j,重量<k的最大价值int main(){int n,V,W;//物品、容量、承重int v,w,val;//体积、重…

IIS部署.Net 7项目

&#x1f468; 作者简介&#xff1a;大家好&#xff0c;我是Taro&#xff0c;前端领域创作者 ✒️ 个人主页&#xff1a;唐璜Taro &#x1f680; 支持我&#xff1a;点赞&#x1f44d;&#x1f4dd; 评论 ⭐️收藏 文章目录 前言一、发布项目二、解决发布失败1.发布失败2.托管…

【论文笔记】An Effective Adversarial Attack on Person Re-Identification ...

原文标题&#xff08;文章标题处有字数限制&#xff09;&#xff1a; 《An Effective Adversarial Attack on Person Re-Identification in Video Surveillance via Dispersion Reduction》 Abstract 通过减少神经网络内部特征图的分散性攻击reid模型。 erbloo/Dispersion_r…

Scratch 第十四课-打地鼠游戏

第十四课-打地鼠游戏 学习目标 这节课我们一起来做一款打地鼠游戏 如何画圆形以及如何使用复制粘贴功能随机数在游戏中的实际应用逻辑运算符与判断语句的使用 程序设计 程序分析 &#xff1a; 打地鼠游戏小朋友们都玩过&#xff0c;在多个洞里面随机伸出老鼠的头&#xff0…

Github配置ssh key的步骤

1. 检查本地主机是否已经存在ssh key 是否存在 id_rsa 和 id_rsa.pub文件&#xff0c;如果存在&#xff0c;说明已经有SSH Key 如下图所示&#xff0c;则表明已经存在 如果存在&#xff0c;直接跳到第三步 2. 生成ssh key 如果不存在ssh key&#xff0c;使用如下命令生…

机器学习(II)--样本不平衡

现实中&#xff0c;样本&#xff08;类别&#xff09;样本不平衡&#xff08;class-imbalance&#xff09;是一种常见的现象&#xff0c;如&#xff1a;金融欺诈交易检测&#xff0c;欺诈交易的订单样本通常是占总交易数量的极少部分&#xff0c;而且对于有些任务而言少数样本更…

Linux系统中的高级多线程编程技术

在Linux系统中&#xff0c;多线程编程是一种常见的并发编程模型&#xff0c;通过利用多线程可以实现程序的并发执行&#xff0c;提高系统的性能和响应速度。在Linux系统中&#xff0c;开发人员通常使用 pthread 库来进行多线程编程&#xff0c;同时需要掌握线程同步技术以避免并…

代码随想录第二十五天 78.子集 90.子集II 491.非递减子序列

LeetCode 78 子集 题目描述 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&…

使用git的小笔记

平时工作中使用git存储项目代码&#xff0c; 常用的命令 拉取仓库代码 git clone http://100.100.100.100:9080/my_test/test.git 拉取到以后&#xff0c; 先切换到自己的分支 git checkout my_name 一顿魔改代码 然后 add 新增的文件或者修改的文件 git add * 然后提交 并写…