日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

嵌入式linux 添加中断,《嵌入式linux应用程序开发完全手册》中断控制器操作(外部中断)学习笔记...

發(fā)布時間:2025/4/16 linux 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 嵌入式linux 添加中断,《嵌入式linux应用程序开发完全手册》中断控制器操作(外部中断)学习笔记... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

《嵌入式linux應(yīng)用程序開發(fā)完全手冊》中斷控制器操作(外部中斷)學(xué)習(xí)筆記

一.ARM中斷體系

當(dāng)一個“異常”發(fā)生時,或者說當(dāng)收到一個中斷觸發(fā)信號時,ARM9將會自動完成如下一些工作:

(1)在異常工作模式的連接寄存器R14中保存前一個工作模式的下一條指令地址,即是pc+4或者pc+8。

(2)將CPSR的值復(fù)制到異常模式的SPSR中。

(3)將CPSR的工作模式位設(shè)為這個異常對應(yīng)的工作模式。

(4)令PC值等于這個異常模式在異常向量表中的地址,即跳轉(zhuǎn)去執(zhí)行異常向量表中的相應(yīng)指令。既是執(zhí)行中斷服務(wù)程序。

當(dāng)從異常模式恢復(fù)至之前的工作模式時,軟件需要完成如下工作:

(1)將前面進入異常時保存在R14中的指令地址減去適當(dāng)值后賦給PC寄存器。

異常模式

退出異常時PC值

進入異常模式時R14值

Svc

MOVS PC,R14

Und

MOVS PC,R14

PC+4

Fiq

SUBS PC,R14,#4

PC+4

Irq

SUBS PC,R14,#4

PC+4

Abt

指令預(yù)取終止

SUBS PC,R14,#4

PC+4

指令讀取終止

SUBS PC,R14,#8

PC+8

(2)將SPSR的值復(fù)制回CPSR。

二. S3C2440中斷控制器

其實,無論哪種CPU,中斷處理過程都是類似的:

1.中斷控制器匯集各類外設(shè)發(fā)出的中斷信號,然后告訴CPU。

2.CPU保存當(dāng)前程序的運行環(huán)境,調(diào)用中斷服務(wù)程序來處理中斷。

3.在ISR(interrupt Service Routine)中通過讀取中斷控制器,外設(shè)的相關(guān)寄存器來識別這是哪個中斷,并進行相應(yīng)的處理。

4.清除中斷:通過讀寫中斷控制器和外設(shè)的相關(guān)寄存器來實現(xiàn)。

5.最后恢復(fù)被中斷程序的運行環(huán)境,繼續(xù)執(zhí)行中斷前的程序。

當(dāng)然,對于不同的CPU體系結(jié)構(gòu),具體的寄存器操作自然就不同了。

對于S3C2440,寄存器SUBSRCPND和SRCPND表明有哪些中斷被觸發(fā)了,正在等待處理(pending),INTSUMMSK和INTMSK寄存器用于屏蔽某些中斷

基本中斷處理過程如下:

中斷源被觸發(fā)過后,SUBSRCPND寄存器中的相應(yīng)位會被置位,如果此中斷沒有被INTMSK寄存器屏蔽掉,它將會進一步處理。在SRCPND寄存器中,被觸發(fā)的中斷相應(yīng)位被置1,等待處理。如果被觸發(fā)的中斷源中有FIQ,則CPU進入FIQ Mode進行處理。如果被觸發(fā)的是一般的IRQ,可能同時有幾個中斷被觸發(fā),未被INTMSK寄存器屏蔽的中斷經(jīng)過比較,選出優(yōu)先級最高的中斷,此中斷在INTPND寄存器中的相應(yīng)位被置1,然后CPU進入IRQ Mode進行處理。中斷服務(wù)程序可以通過讀取INTPND寄存器或者INTOFFSET寄存器來確定中斷源。

綜上,使用中斷的步驟如下:

1.設(shè)置好中斷模式和快速中斷模式下的棧。

2.準(zhǔn)備好中斷處理函數(shù)。包括異常向量表,ISR,清除中斷。

清除中斷的方法:

(1)操作具體外設(shè)清除中斷信號。

(2)清除SUBSRCPND,SRCPND寄存器中的相應(yīng)位。

(3)清除INTPND寄存器中的相應(yīng)位。

3.進入和退出時需要對中斷程序的運行環(huán)境進行保護和恢復(fù)。

(1)進入和退出IRQ的一般處理:

sub lr, lr, #4 @ 計算返回地址

stmdb sp!, { r0-r12,lr } @ 保存使用到的寄存器

……@中斷處理

ldmia sp!, { r0-r12,pc }^ @ 中斷返回, ^表示將spsr的值復(fù)制到cpsr

(2)進入和退出FIQ的一般處理:

sub lr, lr, #4 @ 計算返回地址

stmdb sp!, { r0-r7,lr } @ 保存使用到的寄存器

……@快速中斷處理

ldmia sp!, { r0-r7,pc }^ @ 中斷返回, ^表示將spsr的值復(fù)制到cpsr

4.根據(jù)具體中斷,設(shè)置相關(guān)外設(shè),比如對于GPIO中斷,需要將相應(yīng)引功能設(shè)置為“外部中斷”,設(shè)置中斷觸發(fā)條件等等。

5.將INTSUBMSK寄存器相應(yīng)位設(shè)為0,如果需要的話。

6.確定使用中斷的方式:FIQ或者IRQ

7.如果是FIQ,則INTMOD寄存器中設(shè)置相應(yīng)位為1;如果是IRQ,則在PRIORITY寄存器中設(shè)置優(yōu)先級。

8.如果是IRQ,將INTMSK寄存器相應(yīng)位設(shè)為0,FIQ不受INTMSK寄存器控制。

9.設(shè)置CPSR寄存器中的I位(IRQ)或者F位(FIQ),全能IRQ或者FIQ。

中斷控制寄存器:

(1)子中斷源未決寄存器SUBSRCPND,地址:0x4A000018

(2)子中斷屏蔽寄存器INTSUBMSK,地址:0x4A00001C

(3)中斷源未決寄存器SRCPND,地址:0x4A000000

(4)中斷屏蔽寄存器INTMSK,地址:0x4A000008

(5)中斷模式寄存器INTMOD,地址:0x4A000004

(6)優(yōu)先級寄存器PRIORITY,地址:0x4A00000C

(7)中斷未決寄存器INTPND,地址:0x4A000010

(8)中斷偏移寄存器INTOFFSET,地址:0x4A000014

各個寄存器的具體操作說明請參考S3C2440的datasheet。

三.KEY對應(yīng)的中斷連接

EINT19(GPG11)-------K1

EINT11(GPG3)-------K2

EINT2GPF2)-------K3

EINT0GPF0)-------K4

將這幾個I/O口設(shè)置成外部中斷功能。如果某個key按下時就產(chǎn)生中斷,點亮對應(yīng)的led。

四.按鍵中斷實驗代碼

(1)初始化,設(shè)置中斷模式、系統(tǒng)模式的棧,設(shè)置好中斷處理函數(shù)

@******************************************************************************

@ File:head.S

@ 功能:初始化,設(shè)置中斷模式、系統(tǒng)模式的棧,設(shè)置好中斷處理函數(shù)

@******************************************************************************

.extern main

.text

.global _start

_start:

@******************************************************************************

@ 中斷向量,本程序中,除Reset和HandleIRQ外,其它異常都沒有使用

@******************************************************************************

b Reset

@ 0x04: 未定義指令中止模式的向量地址

HandleUndef:

b HandleUndef

@ 0x08: 管理模式的向量地址,通過SWI指令進入此模式

HandleSWI:

b HandleSWI

@ 0x0c: 指令預(yù)取終止導(dǎo)致的異常的向量地址

HandlePrefetchAbort:

b HandlePrefetchAbort

@ 0x10: 數(shù)據(jù)訪問終止導(dǎo)致的異常的向量地址

HandleDataAbort:

b HandleDataAbort

@ 0x14: 保留

HandleNotUsed:

b HandleNotUsed

@ 0x18: 中斷模式的向量地址

b HandleIRQ

@ 0x1c: 快中斷模式的向量地址

HandleFIQ:

b HandleFIQ

Reset:

ldr sp, =4096 @ 設(shè)置棧指針,以下都是C函數(shù),調(diào)用前需要設(shè)好棧

bl disable_watch_dog @ 關(guān)閉WATCHDOG,否則CPU會不斷重啟

msr cpsr_c, #0xd2 @ 進入中斷模式,M[4:0]=10010 , [IFT]=110

ldr sp, =3072 @ 設(shè)置中斷模式棧指針

msr cpsr_c, #0xdf @ 進入系統(tǒng)模式

ldr sp, =4096 @ 設(shè)置系統(tǒng)模式棧指針,

@ 其實復(fù)位之后,CPU就處于系統(tǒng)模式,

@ 前面的“l(fā)dr sp, =4096”完成同樣的功能,此句可省略

bl init_led @ 初始化LED的GPIO管腳

bl init_irq @ 調(diào)用中斷初始化函數(shù),在init.c中

msr cpsr_c, #0x5f @ 設(shè)置I-bit=0,開IRQ中斷,[IFT]=010

ldr lr, =halt_loop @ 設(shè)置返回地址

ldr pc, =main @ 調(diào)用main函數(shù)

halt_loop:

b halt_loop

HandleIRQ:

sub lr, lr, #4 @ 計算返回地址

stmdb sp!, { r0-r12,lr } @ 保存使用到的寄存器

@ 注意,此時的sp是中斷模式的sp

@ 初始值是上面設(shè)置的3072

ldr lr, =int_return @ 設(shè)置調(diào)用ISR即EINT_Handle函數(shù)后的返回地址

ldr pc, =EINT_Handle @ 調(diào)用中斷服務(wù)函數(shù),在interrupt.c中

int_return:

ldmia sp!, { r0-r12,pc }^ @ 中斷返回, ^表示將spsr的值復(fù)制到cpsr

(2)初始化,關(guān)閉watchdog,,初始化GPIO引腳為外部中斷。

* init.c: 進行一些初始化

*/

#include "s3c24xx.h"

/*

* LED1-4對應(yīng)GPB5、GPB6、GPB7、GPB8

*/

#define GPB5_out (1<

#define GPB6_out (1<

#define GPB7_out (1<

#define GPB8_out (1<

/*

* K1-K4對應(yīng)GPG11、GPG3、GPF2、GPF0

*/

#define GPG11_eint (2<

#define GPG3_eint (2<

#define GPF2_eint (2<

#define GPF0_eint (2<

/*

* 關(guān)閉WATCHDOG,否則CPU會不斷重啟

*/

void disable_watch_dog(void)

{

WTCON = 0; // 關(guān)閉WATCHDOG很簡單,往這個寄存器寫0即可

}

void init_led(void)

{

GPBCON = GPB5_out | GPB6_out | GPB7_out | GPB8_out ;

}

/*

* 初始化GPIO引腳為外部中斷

* GPIO引腳用作外部中斷時,默認為低電平觸發(fā)、IRQ方式(不用設(shè)置INTMOD)

*/

void init_irq( )

{

GPFCON = GPF0_eint | GPF2_eint;

GPGCON = GPG3_eint | GPG11_eint;

// 對于EINT11、19,需要在EINTMASK寄存器中使能它們

EINTMASK &= (~(1<<11)) & (~(1<<19));

/*

* 設(shè)定優(yōu)先級:

* ARB_SEL0 = 00b, ARB_MODE0 = 0: REQ1 > REQ3,即EINT0 > EINT2

* 仲裁器1、6無需設(shè)置

* 最終:

* EINT0 > EINT2 > EINT11,EINT19,即K4 > K3 > K1,K2

* EINT11和EINT19的優(yōu)先級相同

*/

PRIORITY = (PRIORITY & ((~0x01) | (0x3<<7))) | (0x0 << 7) ;

// EINT0、EINT2、EINT8_23使能

INTMSK &= (~(1<<0)) & (~(1<<2)) & (~(1<<5));

}

(3)真正的ISR

void EINT_Handle()

{

unsigned long oft = INTOFFSET;

unsigned long val;

switch( oft )

{

// K4被按下

case 0:

{

GPBDAT |= (0x0f<<5); // 所有LED熄滅

GPBDAT &= ~(1<<8); // LED4點亮

break;

}

// K3被按下

case 2:

{

GPBDAT |= (0x0f<<5); // 所有LED熄滅

GPBDAT &= ~(1<<7); // LED3點亮

break;

}

// K1或K2被按下

case 5:

{

GPBDAT |= (0x0f<<5); // 所有LED熄滅

// 需要進一步判斷是K1還是K2,或是K1、K2被同時按下

val = EINTPEND;

if (val & (1<<11))

GPBDAT &= ~(1<<6); // K2被按下,LED2點亮

if (val & (1<<19))

GPBDAT &= ~(1<<5); // K1被按下,LED1點亮

break;

}

default:

break;

}

//清中斷

if( oft == 5 )

EINTPEND = (1<<11) | (1<<19); // EINT8_23合用IRQ5

SRCPND = 1<

INTPND = 1<

}

總結(jié)

以上是生活随笔為你收集整理的嵌入式linux 添加中断,《嵌入式linux应用程序开发完全手册》中断控制器操作(外部中断)学习笔记...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。