亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? learn-lumit-step-15-readme.txt

?? 嵌入式開發(fā)試驗(yàn):中斷按鈕實(shí)驗(yàn)
?? TXT
字號(hào):

Learn lumit Step 15 : 中斷按鈕實(shí)驗(yàn)
++++++++++++++++++++++++++++++++++++++++++++++++++++++

    所有前面例子中提到的實(shí)驗(yàn),無論是輸入設(shè)備或者是輸出設(shè)備,都是采用順序執(zhí)行的
方式,沒有涉及到程序的異步執(zhí)行。但即使是單片機(jī)也有中斷,導(dǎo)致程序需要對中斷進(jìn)行
處理,因此就不得不涉及到 ARM 處理器的一些體系結(jié)構(gòu)方面的知識(shí)。

    這一節(jié)我們以板上的 int0 中斷按鈕為例,介紹一下如何處理和實(shí)現(xiàn)系統(tǒng)設(shè)備的中斷。
首先需要對 ARM 的中斷處理流程做一個(gè)簡單介紹。

    ARM 分為多個(gè)處理器狀態(tài),其中最常用的是 SVC 和 IRQ 狀態(tài),每種狀態(tài)的區(qū)別主要
在于有一些寄存器是只有自己可見,而其他狀態(tài)不可見的。SVC 可以理解成就是系統(tǒng)態(tài),
我們前面所介紹的程序都是在 SVC 態(tài)執(zhí)行的,而 IRQ 就是系統(tǒng)發(fā)生中斷后,自動(dòng)跳轉(zhuǎn)到
IRQ 狀態(tài),同時(shí) CPU 會(huì)自動(dòng)到 0x18 地址處執(zhí)行這里的處理指令。

    我們以 int0 例子中的代碼為例,具體說明這個(gè)過程。相比以前的例子這里多了一個(gè)
startup.s 作為進(jìn)入 main 之前需要首先執(zhí)行的啟動(dòng)代碼。它所要做的事情主要有如下的
這五個(gè)工作:

1) 建立 IRQ 態(tài)的堆棧指針 sp_irq
2) 建立 SVC 態(tài)的堆棧指針 sp_svc
3) 保存 __main 的入口到 lr 寄存器
4) CPU 進(jìn)入 SVC 狀態(tài),同時(shí)開中斷。
5) 跳轉(zhuǎn)到 __main 入口,執(zhí)行 C 語言代碼

; startup.s
; **********************************************************************
; * Set up the stack pointer to point 
; **********************************************************************

	;set up irq stack
	mov 	r0, #0xd2               ; make irq mode with all irqs disabled
	msr 	cpsr_cxsf, r0
	MOV sp, #0x70000
	
	;set up svc stack
    	mov	r0, #0xd3                ; make svc mode with all irqs disabled
	msr	cpsr_cxsf, r0		 
	MOV sp, #0x80000
	
; **********************************************************************
; * Get the address of the C entry point.
; **********************************************************************

	LDR lr, =__main
	
; **********************************************************************
; * Enable the interrupt while staying in the supervisor mode
; **********************************************************************
	
	MOV	r0, #Mode_Svc:OR:F_Bit
	MSR	cpsr_c, r0

	MOV 	pc, lr

    對比上面的代碼,這幾個(gè)工作為系統(tǒng)支持 IRQ 中斷狀態(tài)做了必要的準(zhǔn)備,其中最重要的
就是為 IRQ 狀態(tài)下的 SP 堆棧寄存器做了賦值,建立了 IRQ 中斷態(tài)的堆棧空間。

    進(jìn)入 main 函數(shù)后,系統(tǒng)主要執(zhí)行了如下代碼:

int main( void )
{	
	int i = 1;
	
	install_irq_handler( irq_handler );

	led_init();
	
	int0_install_irq_hooker( int0_hooker );
	
	// should be after hooker installation
	int0_init();
		
	while(i++)
	{
		led_one_light(i%3);
		led_delay( 100 );
		led_one_dark(i%3);
	}
	
	return 0;
}

    可以看到,程序結(jié)構(gòu)還是很清晰的,從函數(shù)命名上基本就能理解大致的執(zhí)行流程。
1) 為系統(tǒng)注冊一個(gè)中斷處理函數(shù) irq_handler ,是在匯編文件 startup.s 中實(shí)現(xiàn)的。
2) 為 int0 設(shè)備的中斷處理安裝一個(gè)用戶來實(shí)現(xiàn)的鉤子函數(shù) int0_hooker 。
3) 初始化 led 設(shè)備,便于程序執(zhí)行過程中有一個(gè)簡單的輸出結(jié)果顯示。
4) 初始化 int0 設(shè)備,開始允許 int0 中斷。
5) 進(jìn)入主程序流程中,在一個(gè)無限循環(huán)中,依次點(diǎn)亮 led 0, led 1, led 2 三個(gè)燈。
    
    在 main.c 主文件中,irq 中斷的管理和注冊是通過一個(gè)中斷向量數(shù)組來實(shí)現(xiàn)的。
這個(gè)函數(shù)指針的數(shù)組,代表了 S3C4510 CPU 的 21 個(gè)中斷源的中斷處理函數(shù)的入口。
系統(tǒng)在中斷發(fā)生后,首先進(jìn)入到 irq_handler 中,對 cpu 寄存器上下文狀態(tài)做必要的
保存(堆棧操作)后,調(diào)用 C 語言級(jí)的 do_irq 函數(shù)。在這個(gè)函數(shù)中,根據(jù)當(dāng)前中斷源
的中斷號(hào) irq_source,來查詢系統(tǒng)維護(hù)的中斷向量數(shù)組,看是否已經(jīng)有了某個(gè)設(shè)備注冊
了該中斷號(hào)的中斷處理函數(shù)。如果有則跳轉(zhuǎn)過去執(zhí)行該中斷處理函數(shù)。

-----------------------------------------------------------------------------------
; startup.s 
	IMPORT  do_irq
	EXPORT  irq_handler
irq_handler
	SUB	lr, lr, #4            
	STMFD	sp!, {r0-r12, lr}        ; push r0-r12 register file and lr( pc return address )
 
	MRS 	r4, spsr        
	STMFD 	sp!, {r4}                ; push current spsr_cxsf_irq ( =cpsr_svc )

	BL	do_irq			 ; goto C handler
	
	LDMFD 	sp!, {r4}                ; get cpsr_svc from stack
	MSR     spsr_cxsf, r4		 ; prepare spsr_cxsf to return svc mode	

	LDMFD	sp!, {r0-r12, pc}^       ; recover r0-r12 and pc from stack, cpsr also


-----------------------------------------------------------------------------------
/* main.c */
void (*device_irq_handler[IRQ_SOURCE_NUM])(int irq);

void do_irq( void )
{
	void (* current_pc)();
	int irq_source;
	int i;
	
	// get irq number from INTPND	
	irq_source = INTPND;
	
	// get current device irq handler to current_pc
	for( i = 0; i < IRQ_SOURCE_NUM; i++ )
	{
		if( irq_source & ( 1 << i ) )
		{	// here is an interrupt at source i	
			
			if( device_irq_handler[i] )
			{	// if this interrupt has an registered handler
				// then get this handler address to current_pc			
				current_pc = device_irq_handler[i];
				// call registered device irq handler to do_irq
				((void (*)(void))(current_pc))(); /* thanks, STheobald */	
			}
		}	
	}
	
	return;	
}

    關(guān)于中斷處理函數(shù)的注冊和釋放,主要都是參考了 linux 的實(shí)現(xiàn)機(jī)制,尤其是對于設(shè)備驅(qū)動(dòng)
的處理,也是做了一些簡化,但基本思路上是類似的。在 int0_driver 這個(gè)文件里面,照例還是
實(shí)現(xiàn)了 open, read, write, ioctl, release 這 5 個(gè)底層接口。而中斷處理函數(shù)的實(shí)現(xiàn),中斷號(hào)
的申請和釋放,以及用戶安裝 hooker 函數(shù)的實(shí)現(xiàn)都放在了上層 int0_api 這個(gè)文件里面,這有點(diǎn)
類似于 linux 里面的內(nèi)核模塊。

/* main.c */
int request_irq( unsigned int irq, void (*handler)(int irq) )
{
	if( device_irq_handler[irq] )
		return -1;	// fail to request, free this irq first
		
	// fill the device_irq_handler vector
	device_irq_handler[irq] = handler;
	
	return 0;	
}
    
int free_irq( unsigned int irq, void (*handler)(int irq) )
{
	if( !device_irq_handler[irq] )
		return -1;	// fail to request, free this irq first
		
	// free the device_irq_handler vector
	device_irq_handler[irq] = 0;
	
	return 0;	
}

    在 int0_api 這一層,主要是實(shí)現(xiàn) int0_irq_handler 的中斷處理程序,在該程序中,
必要的話,就調(diào)用用戶的 hooker 函數(shù)。同時(shí)為用戶安裝 hooker 函數(shù)提供接口。
    
/* int0_api.c */
extern int request_irq( unsigned int irq, void (*handler)(void) );

static void (*int0_irq_hooker)(void) = 0;

void int0_irq_handler( void )
{
	// here we add some user code for int0_irq
	if( int0_irq_hooker )
		int0_irq_hooker();

	// here we call low-level int0_irq_handler
	int0_ioctl( INT0_CLEAR_INTERRUPT, 0 );
	
	return;
}

void int0_install_irq_hooker( void (*handler)(void) )
{
	int0_irq_hooker = handler;
}
    

     在 int0_init 初始化流程中,主要是完成申請注冊一個(gè)中斷號(hào)以及和它對應(yīng)的
中斷處理函數(shù)。同時(shí)設(shè)置啟動(dòng)中斷的一些參數(shù),例如中斷觸發(fā)方式為上升沿觸發(fā)等。
     
/* set int0 related gpio */
int int0_init( void )
{
	// External interrupt 0 source number is 0
	request_irq( 0, int0_irq_handler );

	int0_open();

	// set int0 interrupt edge detect
	int0_ioctl( INT0_RISING_EDGE_INTERRUPT, 0 );
	
	// enable int0 interrupt
	int0_ioctl( INT0_ENABLE_INTERRUPT, 0 );

	// set active high
	int0_ioctl( INT0_ACTIVE_HIGH, 0 );
	
	return 0;
}
   
    在 int0_driver 底層驅(qū)動(dòng)接口中,最重要的是實(shí)現(xiàn) int0_ioctl 控制接口。這個(gè) ioctl 
在前面的幾個(gè)例子里,都沒有很實(shí)際的應(yīng)用,但對于 int0 這個(gè)設(shè)備,就體現(xiàn)出其很重要的
作用,可以對比以前的例子,這些設(shè)置參數(shù)是無法通過設(shè)備 讀/寫 的接口來實(shí)現(xiàn)的。

int int0_ioctl( unsigned int cmd, unsigned long arg )
{
	switch( cmd )
	{
		// Enable interrupt request and Unmask PIO8 interrupt
		case	INT0_ENABLE_INTERRUPT:		
			IOPCON 	|= INT0_IO_ENABLE; 
			break;

		// clear int 0 pending interrupts
		case	INT0_CLEAR_INTERRUPT:
			INTPND |= INT0_MASK;
			break;
					
		// set rising edge interrupt
		case	INT0_RISING_EDGE_INTERRUPT:		
		  	IOPCON	|= INT0_IO_RISING_EDGE;		
			break;
		
		// set falling edge interrupt
		case	INT0_FALLING_EDGE_INTERRUPT:	
		  	IOPCON	|= INT0_IO_FALLING_EDGE;
			break;
		
		// set both edge interrupt
		case	INT0_BOTH_EDGE_INTERRUPT:		
		  	IOPCON	|= INT0_IO_BOTH_EDGE;
			break;
				  	
		// set as active high
		case	INT0_ACTIVE_HIGH:
			IOPCON	|= INT0_IO_ACTIVE_HIGH;
			break;
			
		default:
			break;
	}	
	
	return 0;
}

    在學(xué)習(xí) linux 設(shè)備驅(qū)動(dòng)程序的過程中,我很想做的一件事情,就是基于 linux 的機(jī)制,
實(shí)現(xiàn)一個(gè)簡化的中斷處理和設(shè)備驅(qū)動(dòng)模型,應(yīng)用在一些相對簡單的領(lǐng)域。在 lumit4510 平臺(tái)
上做的這個(gè)例子,多少也體現(xiàn)了這樣一個(gè)思路。



┌-------------------------------------------------------------------------┐
│                                                                         │
│    Welcome to visit http://www.lumit.org & http://bbs.lumit.org         │
│                                                                         │
│                  [lumit] - let us make it together                      │
│                                                                         │
│                                                                         │
│                                         lumit-admin <admin@lumit.org>   │
│                                                                         │
└-------------------------------------------------------------------------┘

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號(hào) Ctrl + =
減小字號(hào) Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
久久99精品久久久久久久久久久久| 日韩主播视频在线| 九色综合国产一区二区三区| 欧美日韩国产综合久久| 日本欧美在线观看| 日韩美女天天操| 六月丁香婷婷久久| 国产精品午夜在线观看| 成人av在线播放网址| 中文字幕一区二区不卡| 欧美在线观看禁18| 午夜视频在线观看一区二区| 欧美日韩性生活| 美女免费视频一区| 久久综合久久综合亚洲| 国产乱妇无码大片在线观看| 久久精品欧美一区二区三区不卡| 国产成人av电影| 国产精品蜜臀av| 一本大道综合伊人精品热热| 午夜在线电影亚洲一区| 91精品国产麻豆国产自产在线| 蜜桃av一区二区| 自拍偷拍国产精品| 在线观看视频欧美| 日本黄色一区二区| 一本大道久久a久久综合婷婷| 91视频一区二区| 色88888久久久久久影院按摩| 欧美老肥妇做.爰bbww视频| 欧美三级电影在线观看| 欧美成人性战久久| 中文字幕免费不卡| 亚洲成av人在线观看| 久久国产夜色精品鲁鲁99| 国产麻豆精品95视频| 韩国三级在线一区| 在线观看区一区二| 欧美日韩一区成人| 中文字幕亚洲一区二区av在线| 欧美激情自拍偷拍| 亚洲国产视频直播| 亚洲一区二区三区四区五区黄 | 91精品1区2区| 日韩写真欧美这视频| 91在线精品一区二区三区| 亚洲高清视频在线| 国产欧美一区二区三区网站| 欧美群妇大交群的观看方式| 国产成人精品亚洲午夜麻豆| 夜夜爽夜夜爽精品视频| 国产欧美日韩在线| 亚洲成人av电影在线| 日本免费在线视频不卡一不卡二| 99久久婷婷国产综合精品| 色视频欧美一区二区三区| 精品国产百合女同互慰| 亚洲成人激情社区| 久久精品国产亚洲5555| 欧美日韩中文字幕一区| 亚洲综合色婷婷| 成人永久aaa| 亚洲第一福利一区| 亚洲日本电影在线| 一区二区欧美精品| 91在线视频播放地址| 久久99精品网久久| 亚洲免费电影在线| 国产精品人成在线观看免费 | 五月激情综合网| 亚洲一区在线观看免费| 国产精品私房写真福利视频| 精品久久一区二区三区| 精品国产免费一区二区三区四区 | 日韩一区二区三区视频在线观看| 国产盗摄女厕一区二区三区| 国产精品白丝jk白祙喷水网站| 日韩精品一级二级| 国产精品丝袜91| 亚洲欧洲三级电影| 国产精品视频线看| 欧美一区二区三区在线看| 欧美一区二区三级| 欧美一区三区二区| 在线免费不卡电影| 欧美日本在线视频| 7777精品伊人久久久大香线蕉超级流畅 | 久久久久免费观看| 日韩精品资源二区在线| 亚洲精品在线观| 精品国产制服丝袜高跟| 51精品国自产在线| 26uuu国产在线精品一区二区| 日韩欧美国产1| 91麻豆精品国产91久久久久| wwwwww.欧美系列| 亚洲精品在线观| 日韩精品一区二区在线观看| 国产欧美精品一区二区色综合 | 亚洲bt欧美bt精品777| 亚洲一区二区三区激情| 天堂久久久久va久久久久| 首页亚洲欧美制服丝腿| 强制捆绑调教一区二区| 婷婷开心激情综合| 狠狠色丁香婷综合久久| 激情小说欧美图片| 国产综合久久久久久久久久久久 | 国产一区二区在线视频| 国产传媒日韩欧美成人| 97se亚洲国产综合自在线观| 欧美午夜寂寞影院| 91精品国产91久久综合桃花| 国产日韩精品视频一区| 1区2区3区欧美| 亚洲成人自拍一区| 国产99精品国产| 色综合视频在线观看| 91精品久久久久久蜜臀| 国产精品免费久久久久| 亚洲国产人成综合网站| 久久99精品国产| 色www精品视频在线观看| 69p69国产精品| 国产片一区二区| 日韩中文字幕91| 成人av在线看| 欧美一区二区三区在线看| 日韩理论电影院| 蜜桃av一区二区| 成人动漫av在线| 精品国产乱码久久久久久老虎 | 国产精品综合二区| 在线免费亚洲电影| 欧美视频一区二区三区| 国产欧美日韩久久| 亚洲在线视频一区| 国产黄人亚洲片| 宅男在线国产精品| 亚洲天堂2016| 国内外成人在线| 欧美日韩视频在线第一区| 综合欧美亚洲日本| 久久精品国产精品青草| www.亚洲国产| 国产日韩欧美麻豆| 日本欧美在线观看| 欧美精品v国产精品v日韩精品| 国产精品国产自产拍高清av王其 | 亚洲精品在线电影| 亚洲一二三四在线观看| 久久99热国产| 色综合久久久久久久久| 欧美性淫爽ww久久久久无| 久久女同性恋中文字幕| 一区二区三区免费| 色婷婷精品久久二区二区蜜臀av| 精品美女在线播放| 亚欧色一区w666天堂| 一本久道久久综合中文字幕| 成人欧美一区二区三区1314| 国产99久久久精品| 国产色产综合产在线视频| 国产经典欧美精品| 一区二区三国产精华液| 欧美日韩精品高清| 国产一区亚洲一区| 亚洲精品成人a在线观看| 欧美日韩高清一区二区不卡| 亚洲电影你懂得| 国产精品欧美综合在线| 色诱视频网站一区| 在线免费不卡电影| 欧美一区二区免费观在线| 国产精品系列在线播放| 国产欧美一区二区精品忘忧草 | 五月激情综合网| 日本国产一区二区| 亚洲精品免费一二三区| 色偷偷久久一区二区三区| 一片黄亚洲嫩模| 91精品婷婷国产综合久久性色| 蜜臀va亚洲va欧美va天堂 | 亚洲成人精品一区二区| 欧美一区二区三区公司| 国产一区不卡在线| 成人禁用看黄a在线| 懂色av一区二区三区免费观看| 亚洲一区二区三区在线| 欧美激情中文字幕| 精品免费日韩av| 在线播放欧美女士性生活| 色婷婷综合中文久久一本| 国内精品久久久久影院色| 日韩和的一区二区| 偷拍一区二区三区| 亚洲成年人网站在线观看| 亚洲精品中文在线观看| 亚洲人成7777| 一区二区三区在线观看网站|