日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

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

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

《嵌入式linux應用程序開發完全手冊》中斷控制器操作(外部中斷)學習筆記

一.ARM中斷體系

當一個“異?!卑l生時,或者說當收到一個中斷觸發信號時,ARM9將會自動完成如下一些工作:

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

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

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

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

當從異常模式恢復至之前的工作模式時,軟件需要完成如下工作:

(1)將前面進入異常時保存在R14中的指令地址減去適當值后賦給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

指令預取終止

SUBS PC,R14,#4

PC+4

指令讀取終止

SUBS PC,R14,#8

PC+8

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

二. S3C2440中斷控制器

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

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

2.CPU保存當前程序的運行環境,調用中斷服務程序來處理中斷。

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

4.清除中斷:通過讀寫中斷控制器和外設的相關寄存器來實現。

5.最后恢復被中斷程序的運行環境,繼續執行中斷前的程序。

當然,對于不同的CPU體系結構,具體的寄存器操作自然就不同了。

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

基本中斷處理過程如下:

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

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

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

2.準備好中斷處理函數。包括異常向量表,ISR,清除中斷。

清除中斷的方法:

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

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

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

3.進入和退出時需要對中斷程序的運行環境進行保護和恢復。

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

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

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

……@中斷處理

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

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

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

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

……@快速中斷處理

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

4.根據具體中斷,設置相關外設,比如對于GPIO中斷,需要將相應引功能設置為“外部中斷”,設置中斷觸發條件等等。

5.將INTSUBMSK寄存器相應位設為0,如果需要的話。

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

7.如果是FIQ,則INTMOD寄存器中設置相應位為1;如果是IRQ,則在PRIORITY寄存器中設置優先級。

8.如果是IRQ,將INTMSK寄存器相應位設為0,FIQ不受INTMSK寄存器控制。

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

中斷控制寄存器:

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

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

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

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

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

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

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

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

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

三.KEY對應的中斷連接

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

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

EINT2GPF2)-------K3

EINT0GPF0)-------K4

將這幾個I/O口設置成外部中斷功能。如果某個key按下時就產生中斷,點亮對應的led。

四.按鍵中斷實驗代碼

(1)初始化,設置中斷模式、系統模式的棧,設置好中斷處理函數

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

@ File:head.S

@ 功能:初始化,設置中斷模式、系統模式的棧,設置好中斷處理函數

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

.extern main

.text

.global _start

_start:

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

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

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

b Reset

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

HandleUndef:

b HandleUndef

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

HandleSWI:

b HandleSWI

@ 0x0c: 指令預取終止導致的異常的向量地址

HandlePrefetchAbort:

b HandlePrefetchAbort

@ 0x10: 數據訪問終止導致的異常的向量地址

HandleDataAbort:

b HandleDataAbort

@ 0x14: 保留

HandleNotUsed:

b HandleNotUsed

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

b HandleIRQ

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

HandleFIQ:

b HandleFIQ

Reset:

ldr sp, =4096 @ 設置棧指針,以下都是C函數,調用前需要設好棧

bl disable_watch_dog @ 關閉WATCHDOG,否則CPU會不斷重啟

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

ldr sp, =3072 @ 設置中斷模式棧指針

msr cpsr_c, #0xdf @ 進入系統模式

ldr sp, =4096 @ 設置系統模式棧指針,

@ 其實復位之后,CPU就處于系統模式,

@ 前面的“ldr sp, =4096”完成同樣的功能,此句可省略

bl init_led @ 初始化LED的GPIO管腳

bl init_irq @ 調用中斷初始化函數,在init.c中

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

ldr lr, =halt_loop @ 設置返回地址

ldr pc, =main @ 調用main函數

halt_loop:

b halt_loop

HandleIRQ:

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

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

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

@ 初始值是上面設置的3072

ldr lr, =int_return @ 設置調用ISR即EINT_Handle函數后的返回地址

ldr pc, =EINT_Handle @ 調用中斷服務函數,在interrupt.c中

int_return:

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

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

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

*/

#include "s3c24xx.h"

/*

* LED1-4對應GPB5、GPB6、GPB7、GPB8

*/

#define GPB5_out (1<

#define GPB6_out (1<

#define GPB7_out (1<

#define GPB8_out (1<

/*

* K1-K4對應GPG11、GPG3、GPF2、GPF0

*/

#define GPG11_eint (2<

#define GPG3_eint (2<

#define GPF2_eint (2<

#define GPF0_eint (2<

/*

* 關閉WATCHDOG,否則CPU會不斷重啟

*/

void disable_watch_dog(void)

{

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

}

void init_led(void)

{

GPBCON = GPB5_out | GPB6_out | GPB7_out | GPB8_out ;

}

/*

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

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

*/

void init_irq( )

{

GPFCON = GPF0_eint | GPF2_eint;

GPGCON = GPG3_eint | GPG11_eint;

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

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

/*

* 設定優先級:

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

* 仲裁器1、6無需設置

* 最終:

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

* EINT11和EINT19的優先級相同

*/

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<

}

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。