色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux中斷編程

嵌入式技術 ? 來源:嵌入式技術 ? 作者:嵌入式技術 ? 2022-09-23 09:01 ? 次閱讀

Linux中斷編程

中斷:是指CPU在運行過程中,出現了某種異常事件,需要CPU先暫停當前工作,轉而去處理新產生的異常事件,處理完后再返回暫停的事件繼續往下執行。就例如我們正在使用手機進行微信視頻聊天,這時突然有人打電話過來,這時手機的處理方式是手機來來電鈴聲響起,通知用戶電話來了。

中斷,就是來處理未來時間內可能會發生的事件, 中斷事件也稱為異常事件。有了中斷處理,則可大大提高CPU處理效率。

單片機中,我們也常用中斷方式來處理一些緊急事件,幫我們實現快速響應一些實時性的事件。因此我們在編寫中斷服務函數時都是代碼盡可能簡潔、一定不能處理死循環、若需要處理的事情比較多則應在中斷中設定標志位,然后將邏輯代碼放到主函數中去實現。

在Linux內核中,我們一般會將中斷分為頂半部分和底半部分。頂半部分主要是處理耗時短的代碼(像單片機中設置標志位),啟動底半部分代碼;底半部分主要是處理耗時比較長的代碼,完成中斷響應后的事件處理。

1. Linux下外部中斷

??要使用外部中斷,則需要完成中斷三要素的配置:中斷號(irq)、中斷服務函數、中斷觸發方式(電平觸發、邊沿觸發)。

1.1 相關接口函數

  • 獲取中斷號gpio_to_irq

??在Linux內核中提供了方便函數獲取引腳中斷號

int gpio_to_irq(unsigned gpio)
函數功能: 獲取中斷號
返回值: 成功返回對應GPIO的中斷號irq
  • 注冊中斷request_irq
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)
函數功能: 注冊中斷
形 參: irq --中斷號,gpio_to_irq函數返回值。
?? ?handler --中斷服務函數。
?? ??服務函數原型:typedef irqreturn_t (*irq_handler_t)(int, void *);
?? ?flags --中斷觸發方式。
?? ??#define IRQF_TRIGGER_RISING 0x00000001 //上升沿
?? ??#define IRQF_TRIGGER_FALLING 0x00000002 //下升沿
???? #define IRQF_TRIGGER_HIGH 0x00000004//高電平
????#define IRQF_TRIGGER_LOW 0x00000008//低電平

????#define IRQF_SHARED 0x00000080 //共享中斷
???name --中斷注冊標志。
???dev --傳給中斷服務函數的參數。
返回值: 成功返回0,失敗返回其它值。
  • 中斷服務函數
typedef irqreturn_t (*irq_handler_t)(int, void *);
函數功能: 中斷服務函數
形 參: 第一個參數為中斷號;第二個參數為注冊函數傳入的參數dev
返回值:
?? enum irqreturn {
????IRQ_NONE = (0 << 0), //如果不是本中斷的則返回這個值,只在共享中斷中使用
????IRQ_HANDLED = (1 << 0), //正確執行中斷程序返回這個值,常用
????IRQ_WAKE_THREAD = (1 << 1), //表示去喚醒中斷處理者的線程
??};

??注意: irqreturn_t (*irq_handler_t)(int, void *);函數中不能出現帶休眠的函數,如msleep函數;該函數必須要返回值。

  • 注銷free_irq
free_irq(unsigned int irq, void *dev_id)
函數功能: 注銷中斷
形 參: irq --中斷號,gpio_to_irq函數返回值。
???dev --傳給中斷服務函數的參數。需和注冊時保持一致

2. 工作隊列

??中斷處理函數分為中斷頂半部分和中斷底半部分。頂半部分代碼實現即為中斷服務函數,而底半部分代碼則可由工作隊列完成。

2.1 工作隊列簡介

操作系統中,如果我們需要進行一項工作處理,往往需要創建一個任務來加入內核的調度隊列。一個任務對應一個處理函數,如果要進行不同的事務處理,則需要創建多個不同的任務。任務作為CPU調度的基本單元,任務數量越大,則調度成本越高。工作隊列(workqueue)機制簡化了基礎的任務創建和處理機制,一個workqueue對應一個實體task任務處理,工作隊列中可以掛載多個工作實體,每一個工作都能對應不同的工作處理函數。即用戶只需要創建一個workqueue,則可以完成多個掛接不同處理函數的工作隊列。

工作隊列還具有將工作推后執行機制,工作隊列可以把工作推后,交由一個內核線程去執行,也就是說,這個下半部分可以在進程上下文中執行。最重要的就是工作隊列允許被重新調度甚至是睡眠。

workqueue的處理依賴于task任務。一個workqueue隊列會創建關聯其對應的task任務,一個workqueue會掛載多個工作進行處理,每個工作都有工作處理函數。當workqueue得到調度,即其關聯的task得到運行,在每次task的調度期間,都會從工作隊列中按照先后順序取出一個work來進行處理。workqueue模塊在初始化時,會創建一個系統默認的工作隊列,用戶可根據需要將work添加到該隊列中去執行。

2.2 工作相關函數接口

  • 工作結構體struct work_struct
#include 
struct work_struct {
	atomic_long_t data;
	struct list_head entry;
	work_func_t func;  /*工作處理函數*/
#ifdef CONFIG_LOCKDEP
	struct lockdep_map lockdep_map;
#endif
};

??在工作結構體體中,我們需要關心的成員是工作處理函數:work_func_t func,簡單來說即一個工作會對應有一個處理函數。工作處理函數原型如下:

#include 
typedef void (*work_func_t)(struct work_struct *work);
  • 初始化工作INIT_WORK
#define INIT_WORK(_work, _func)
函數功能: 初始化工作,以宏的方式實現
形 參: _work --工作結構體體指針
???_func --工作處理函數
  • 工作調度schedule_work
int schedule_work(struct work_struct *work)

2.3工作隊列使用步驟

  1. 定義工作結構體struct work_struct,初始化工作INIT_WORK;
  2. 編寫工作處理函數void (*work_func_t)(struct work_struct *work);
  3. 在合適的地方調調度工作(一般在中斷頂半部分);

2.4工作隊列使用示例

??下面以按鍵為例,實現中斷方式按鍵檢測,通過工作隊列處理底半部分代碼,雜項設備框架實現設備注冊。

poYBAGMsVOqAM5YjAAC9181SmfI038.png#pic_centerpYYBAGMsVOuAZpP4AAGtQ8N96qc548.png#pic_center
  • K1 – GPX3_2
  • K2 --GPX3_3
  • K3 --GPX3_4
  • K4 --GPX3_5
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
struct work_struct key_work;/*工作結構體*/
struct _KEY
{
	unsigned int gpio;/*按鍵引腳*/
	char name[20];/*按鍵名*/
	int irq;/*中斷號*/
	int key_num;/*按鍵編號*/
};
static struct _KEY KEY_GPIO_PIN[]=
{
	{EXYNOS4_GPX3(2),"key1",0,1},
	{EXYNOS4_GPX3(3),"key2",0,2},
	{EXYNOS4_GPX3(4),"key3",0,3},	
	{EXYNOS4_GPX3(5),"key4",0,4},	
};
static struct _KEY *key_p;
static unsigned int key_val;
/*工作服務函數*/
void key_work_func(struct work_struct *work)
{
	msleep(30);/*按鍵消抖*/
	if(gpio_get_value(key_p->gpio)==0)
	{
		printk(" key%d 按下n",key_p->key_num);
	}
	else 
	{
		printk(" key%d 松開n",key_p->key_num);
	}
	key_val=key_p->key_num;
}
/*中斷服務函數*/
static irqreturn_t key_irq_handler(int irq, void *dev)
{
	key_p=(struct _KEY *)dev;
	schedule_work(&key_work);/*調度工作*/
	return IRQ_HANDLED;/*中斷正常處理*/
}
static int key_open(struct inode *inode, struct file *file)
{
	printk("設備打開成功n");
	return 0;
}
static ssize_t key_read(struct file *file, char __user *buf, size_t cnt, loff_t *seek)
{
	int res=copy_to_user(buf,&key_val, 4);
	key_val=0;
	return 4-res;
}
static int key_release(struct inode *inode, struct file *file)
{
	printk("設備關閉成功n");
	return 0;
}
/*文件操作集合*/
static struct file_operations key_fops=
{
	.owner= THIS_MODULE, /*當前模塊文件操作集合所有者*/
	.open=key_open,/*open函數接口*/
	.read=key_read,/*read函數接口*/
	.release=key_release,/*close函數接口*/
};
/*
字符設備注冊:主設備+次設備號
主設備  --用來區分類(雜項設備、輸入設備)
次設備號  --對應哪個設備
雜項設備的主設備號固定為:10
*/
static struct miscdevice key_miscdev = {
	.minor	= MISC_DYNAMIC_MINOR,/*次設備號255由內核分配*/
	.name	= "tiny4412_key",/*設備節點名字,會在/dev下生成*/
	.fops	= &key_fops,/**/
};

static int __init tiny4412_key_module_init(void)
{
	int i=0;
	int res;
    printk("hello,驅動注冊成功n");
	/*初始化工作*/
	INIT_WORK(&key_work,key_work_func);
	/*注冊中斷*/
	for(i=0;i(key_gpio_pin)>
poYBAGMsVOuAfzGRAAEtRbFUGc8924.png#pic_center

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11293

    瀏覽量

    209340
  • 編程
    +關注

    關注

    88

    文章

    3614

    瀏覽量

    93686
  • 中斷
    +關注

    關注

    5

    文章

    898

    瀏覽量

    41471
收藏 人收藏

    評論

    相關推薦

    Linux內核中斷設計與實現

    裸機編程中使用中斷比較麻煩,需要配置寄存器、使能IRQ等等。而在Linux驅動編程中,內核提供了完善的終端框架,只需要申請中斷,然后注冊
    發表于 07-29 08:57 ?785次閱讀

    芯靈思Sinlinx A33開發板 Linux中斷編程原理說明

    。step2 內核關于 CPU 的中斷linux 中斷注冊函數中的 irq 中斷號并不是芯片物理上的編號,而是由芯片商在移植 Linux
    發表于 01-31 17:24

    芯靈思Sinlinx A33開發板 Linux中斷編程 2:程序框架

    根據上一個帖子的分析,想要實現按鍵中斷,首先得知道引腳對應的中斷號,LRADC0對應的中斷編號#define SUNXI_IRQ_LRADC (SUNXI_GIC_START + 30)/* 62
    發表于 02-01 16:28

    芯靈思Sinlinx A33開發板Linux中斷編程 3-應用程序

    應用程序代碼參考#include #include #include #include #include #include #include #include #include #include#defineDEV_NAME "/dev/mybtn"int main(int argc, char *args[]){ int fd = 0; int ret = 0; unsigned char recv_buf[1] = {"0"}; fd = open(DEV_NAME, O_RDONLY); //fd = open(DEV_NAME, O_RDONLY|O_NONBLOCK); if(fd < 0) {perror("open"); } while(1) {strcpy(recv_buf, "0000");//讀取按鍵數據ret = read(fd, recv_buf, 1);if((ret < 0) && (errno != EAGAIN)) {perror("read");exit(-1);}//輸出按鍵狀態printf("%s\r\n", recv_buf); } return 0;}
    發表于 02-11 16:45

    芯靈思SinlinxA33開發板Linux中斷編程4-最終代碼(1)

    = IRQ_TYPE_EDGE_BOTH; irq = gpio_to_irq( GPIOL(14) );//發生中斷號為irq的中斷會執行key_isr函數。注冊成功會在/proc/irq號/KEY文件夾出現或 cat
    發表于 02-13 16:09

    Linux 2.6 中斷處理原理簡介

    Linux 2.6 中斷處理原理簡介 中斷描述符表(Interrupt Descriptor Table,IDT)是一個系統表,它與每一個中斷或異常向量相聯系,每一個向量在表中存放的
    發表于 02-05 10:52 ?795次閱讀

    LINUX網絡編程

    linux開發編程教程資料——LINUX網絡編程,感興趣的小伙伴們可以看一看。
    發表于 08-23 16:23 ?0次下載

    Linux網絡編程

    linux開發編程教程資料——Linux網絡編程,感興趣的小伙伴們可以看一看。
    發表于 08-23 16:23 ?0次下載

    嵌入式Linux設備驅動開發之中斷編程詳解

    11.5 中斷編程 前面所講述的驅動程序中都沒有涉及中斷處理,而實際上,有很多Linux的驅動都是通過中斷的方式來進行內核和硬件的交互。
    發表于 10-18 17:33 ?0次下載

    你了解linux中斷機制?

    中斷是指在CPU正常運行期間,由于內外部事件或由程序預先安排的事件引起的CPU暫時停止正在運行的程序,轉而為該內部或外部事件或預先安排的事件服務的程序中去,服務完畢后再返回去繼續運行被暫時中斷的程序。Linux中通常分為外部
    發表于 05-05 15:30 ?716次閱讀

    Linux驅動技術之一內核中斷

    在硬件上,中斷源可以通過中斷控制器向CPU提交中斷,進而引發中斷處理程序的執行,不過這種硬件中斷體系每一種CPU都不一樣,而
    發表于 05-08 13:49 ?642次閱讀

    嵌入式Linux中斷驅動

    用過STM32的大概都知道,基本每個GPIO管腳都支持中斷模式,這樣在檢測外部插入一個硬件設備時,通過GPIO管腳電平中斷就非常方便。那么AM3354的片子是否支持GPIO管腳電平中斷呢?答案是肯定
    發表于 11-01 16:57 ?4次下載
    嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>中斷</b>驅動

    Linux中斷情景分析

    在一個系統中,中斷時常發生,而且線程調度也是由一個硬件定時器時時刻刻發出中斷來支撐的??梢哉f中斷就是linux系統的靈魂。
    發表于 06-23 14:22 ?579次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>中斷</b>情景分析

    什么是LInux 操作系統中斷

    LInux 操作系統中斷 什么是系統中斷 這個沒啥可說的,大家都知道; CPU 在執行任務途中接收到中斷請求,需要保存現場后去處理中斷請求!
    的頭像 發表于 11-10 11:29 ?622次閱讀
    什么是<b class='flag-5'>LInux</b> 操作系統<b class='flag-5'>中斷</b>

    Linux應用編程的基本概念

    Linux應用編程涉及到在Linux環境下開發和運行應用程序的一系列概念。以下是一些涵蓋Linux應用編程的基本概念。
    的頭像 發表于 10-24 17:19 ?222次閱讀
    主站蜘蛛池模板: 老师掀开短裙让我挺进动态| 草699一码二码三码四码| 精品一区二区免费视频蜜桃网| 亚洲国产成人爱AV在线播放丿 | 动态抽插图视频| 青青娱乐网| 韩国电影久久| 福利视频久久| 秋霞伦理电影在线看| 年轻的女教师2017韩国在线看| 飘雪韩国在线观看免费高清完整版| 日操夜操天天操| 王雨纯羞羞| 印度最猛性ⅹxxxxx| 99pao成人国产永久免费视频| 草莓在线观看| 国产专区青青草原亚洲| 快播电影网址| 色婷婷亚洲五月| 一本道无码字幕在线看| chinesevideos原创麻豆| 国产国产成人人免费影院| 精品一区二区三区免费观看| 男女夜晚在爽视频免费观看| 丝袜美女自摸| 在线亚洲视频无码天堂| 大学生高潮无套内谢视频| 吉吉av电影| 人妻免费视频公开上传| 亚洲精品国产品国语在线试看| 67194在线入口免费| 国产精品路线1路线2路线| 久久亚洲伊人中字综合精品| 日本69xxxxx| 夜夜澡人人爽人人喊_欧美| 啊灬啊别停灬用力啊老师| 花蝴蝶在线观看免费8| 欧美午夜理伦三级在线观看| 亚洲人成色777777老人头| 扒开小处30p| 久久久午夜精品福利内容|