JZ2440 베어 보드 개발 및 비정상적인 인터럽트 연습 # 7 (2)

인터럽트

인터럽트 컨트롤러

인터럽트에 대한 Benpian 이야기가, 부 예외와 예외 처리에 대해 말씀 드리 지요 치료도 유사하므로, 인터럽트는 예외적 인 다른 이상과의 주요 차이점, 역할이 인터럽트 컨트롤러의 존재.

인터럽트 처리는 인터럽트 소스 인 -> 인터럽트 컨트롤러 - 많은 유형이 소스 방해가있는> 핸들러 인터럽트 직렬 포트, 타이머 인터럽트 또는 외부 인터럽트 될 수있다. 인터럽트가 마스킹되어 있는지 여부를 상기 제어부를 제어하고, 인터럽트 상태 인터럽트 우선도. 핸들러 및 예외 처리기는 당신이 필요에 따라 쓸 수로, 차이가 없습니다.

 것을 제외하고, 두 소스들로 분할 인터럽트 컨트롤러의 블록도, 인터럽트 소스가 거의 남아 픽처 방송 만 어떻게 두 개의 서브 소스 레지스터 SUBSRCPND SUBMASK 제어 인터럽트. 종류의 인터럽트 소스에 기인 한 어떤 S3C2440은 표에 나와 :

 여기에 소스 인터럽트 논의의 주요 원천은, 당신은 자신의 요구 1-1에 따라 설명하고있다 소스 인터럽트 특정의 설명을 볼 수 있지만 가장 중요한 것은 그룹화 아비터의 이해, 소스 인터럽트 소스는 5 개 그룹으로 나누어 져 각각 이하 여섯 개 인터럽트 소스 아래 최종 할당 결과는,이 과제는 인터럽트 우선 순위 레벨, ARBITER의 존재를 실현할 주로 각 그룹의 두 개의 제어 신호 : 1bitARB_mode, 2bitsARB_SEL, 상기 선택 ARB_SEL위한 우선 순위 방식을 중단. 우선 순위의 4 종류 ARB_SEL 네 개의 조합이 가장 높은 우선 순위를 고정 REQ0 해당 고정 REQ5 낮은 우선 순위를 나타내는, 다음의 도면에서 볼과 함께 REQ1-4 ARB_SEL 수 회전, 우선 순위의 ARB_mode이 더 ARB_mode가 0 일 때 우리가 수정할 수없는 한, 우리가 영구적으로 ARBS_SEL이 우선 순위에 의해 결정 고정되어 영향을 우리가 직접 우선 순위를 결정하는 ARB_SEL을 설정할 수 증가를 왼쪽 . ARB_mode 1, 각각의 인터럽트 응답 시간 및 확인 ARB_SEL 따라서 낮은 우선 순위의 인터럽트 응답을 얻을 수있는 기회를 가질 수 있도록, 가장 낮은 우선 순위가됩니다 인터럽트 우선 순위가 가장 높은 결과, 한 사이클을 왼쪽으로 1 증가 할 때 또한 OS와 마찬가지로 스케줄링 라운드 로빈 스케줄링라고도 방지 기아, 그래서 여기에 라운드 로빈 스케줄링도 스위치의 상기 수 ARB_mode.

 인터럽트 컨트롤러 (5)가 인터럽트 소스의 소스 레지스터에 대한 제어를 갖는다 : 소스 보류 레지스터, 레지스터 MODE 인터럽트는 마스크
레지스터 우선 보류 레지스터와 레지스터 인터럽트
. 제 웬 하나의 일치에도 차단된다.

된 소스 레지스터 보류 인터럽트가 대응하는 인터럽트 비트가 설정되고 실행될 때 트리거되는 인터럽트 표시하기 위해 사용 된 유사한 등록 보류 인터럽트 차이는 모든 SRCPND 인터럽트는 오직 현재의 요구, 어서 리거 것이다 INTPND 일련의 처리를 인터럽트 최우선이 SRCPND가 INTPND 후에 인터럽트 처리로 가장 높은 우선 순위의 인터럽트에 상영 INTPND 실드 및 우선 순위 레지스터 마스크를 받았다. 그렇지 않으면 반복 인터럽트 처리 된 응답했을 것이다,이 두 레지스터 프로세스가 완료된 후 삭제 될 필요가 있음을 주목해야한다. 이 청산 INTPND의 SRCPND 후 다시 설정하지 않도록 그리고 필요가 소스 SRCPND-> INTPND에서 시작합니다. 모드 설정에 대응하는 비트가 1로 설정된다.

 마스크 레지스터는 인터럽트, 해당 비트가 설정되어 인터럽트 소스를 마스크하는 데 사용됩니다, 시스템 인터럽트는 인정되지 않으며, 비트가 설정되어 인터럽트도 SRCPND 와서, 응답을하지 않습니다,하지만 설정 INTPND 직접, 또는 응답 처리를 필요로하는 경우 (INTPND는 MASK 후,하지의 마스크 제어).

 그것은 말했다되도록 모드 레지스터들이 더 자신의 독점적 인 레지스터의 가지고 있기 때문에 하나 이미 설명 FIQ의 인터럽트 또는 일반 인터럽트 속공을 제어, 따라서 현장을 보존하고 작은 필드의 비용을 복구하는 데 사용되는 응답 속도가 빠르다 빠른 휴식. 여기에 기본 값은 0, 기본적으로 그 비트 일반 인터럽트이다.

 리콜은 우선 순위 레지스터에, 만 인터럽트 우선 순위를 설정하기 위해, 필요에 따라 로터리 스위치를 돌 필요가있다.

 

 컨트롤러 외에도, 인터럽트에 응답하는 시스템이 필요한 경우 상기 시스템의 마스터 스위치 인터럽트 처리 또는 I 비트되는 I 비트 CPSR 한 섹션 F 비트 또는 개방을 필요 F- 비트가 지워.

소스 레지스터 세트 INTOFFSET 인터럽트 핸들러 인터럽트 S3C2440 해상도를 촉진하기 위해, 그 추가, 다른 인터럽트 소스는 다른 오프셋 값을 가지고, 레지스터 값은 직접 표준과 비교 될 수있다.

 

외부 중단

인터럽트 제어 요구 이외에 인터럽트 소스는 구성 될 필요가 구성된다. 외부 인터럽트, 외부 인터럽트 스위치는 원하는 버튼에 대한 버튼을 누른 경우의 예에서, 인터럽트는, LED 조명을 트리거된다.

에서 https://blog.csdn.net/G_METHOD/article/details/104271762 또한 콘텐츠 키를 작성, 그 키 상태 검출, CPU 자원을 더 소비, 외부 인터럽트의 사용을 수행하는 폴링 방법입니다 무 사건 접근 방식은 핸들 다른 것들에 CPU가 발생할 수 있으며, 이벤트가 트리거 될 때, 적시에 처리. 설계도의 복사 키 발 표에 해당하는 버튼을 클릭합니다.

EINT0 EINT2 EINT11 EINT19
GPF0 GPF2 GPG3 GPG11

 우리는 입력 핀으로 설정 마지막 키 상태에 대해 핀을 읽을 수 있습니다, 외부 인터럽트를 사용할 필요가, 당신은 해당 외부 인터럽트 모드로 설정해야합니다. 본 무화과.만큼 해당 GPxCON 핀이 외부 인터럽트 핀에 설정되어있다.

 가능 GPIO 외에도 필요 설정뿐만 아니라 외부 인터럽트를 설정해야 할를 등록합니다. 다음과 같이 제공 EXTINT 트리거는 외부 인터럽트가 낮은, 높은, 상승, 하강, 또는 더블 에지 트리거를 지정할 수 있습니다. 여기에 우리가 선택할 수 있습니다 자신의 요구 사항이나 환경 설정에 따라, 트리거 더블 에지를 사용하기로 결정했습니다.

 어떤 외부 인터럽트 핀이 외부 인터럽트 (32)를 재생 필터링 존재하는지 (51), 레벨 키가 아니라 디더 처리는, 인터럽트 트리거 버튼을 눌러 조작 할 수있는 경우, 지터가있을 것이다 가압 공지 될 수 있음에 유의해야한다 표시등이 깜박 한 번 버튼을 누를 때마다 있도록하지만, 한 번 이상 트리거 흔들 같은 조명을위한 버튼과 트리거 여러 인터럽트 이벤트,,,. 손떨림 방지 모드가 원유 방법을 필터링 필터링 할 수 있습니다,이 칩 도움이 우리가 필터링을 할 수 물론, 당신은 시계 시간 및 구성 필터링에 다른 레지스터가, 기능 레지스터를 필터링 해제 쓸 수있는 안정적인 수준, 대기 지연의 기간입니다 .

 

 인터럽트 컨트롤러는, 마찬가지로 비교 외부 인터럽트 마스크 레지스터와 레지스터는 본 PEND 레지스터와 마찬가지로, 마스크하는 인터럽트 마스크의 PEND가 하나의 외부 인터럽트 트리거를 나타내는도이다. 마찬가지로, 인터럽트를 처리 한 후 해당 비트 시원을 취소한다.

 인터럽트 제어기를 사용 PND 인터럽트의 특정한 소스를 확인할 수없는 경우 인터럽트 소스 전술 인터럽트 레지스터 있지만, 인터럽트 소스의 인터럽트 핸들러의 제어가 결정된다 (예를 들면, 여러 외부 인터럽트 EINT 플래그를 공유하고있다) 이 경우, 인터럽트의 특정 소스를 구별 PND 외부 인터럽트 레지스터 필요하다.

다음으로, 상기 출력 코드에 따라 :

.text
.global _start

_start:
	B RESET	
	LDR pc,UNDEFIE
	LDR pc,SW_INTERRUPT
	B ABORT_PREFETCH
	B ABORT_DATA
	B halt				//reserve
	LDR pc,INTERRUPT
	B FIQ_HANDLE

UNDEFIE:
	.word DO_UND	
	
SW_INTERRUPT:
	.word DO_SWI

INTERRUPT:
	.word DO_INTERRUPT
	

ABORT_PREFETCH:
ABORT_DATA:	
IRQ_HANDLE:
FIQ_HANDLE:
	B halt

DO_UND:
	//1.设置栈
	LDR SP,=0x34000000
	//2.保存现场
	STMDB SP!,{R0-R12,LR}

	//处理函数
	MRS R0,CPSR
	LDR R1,=UND_TEST_STRING
    BL ExecptionHandle
	
	//3.恢复现场,跳转回原来的位置
	LDMIA SP!,{R0-R12,PC}^  //^ 表示将SPSR恢复到CPSR中
	
DO_SWI:
	//1.设置栈
	LDR SP,=0x33e00000
	//2.保存现场
	STMDB SP!,{R0-R12,LR}
	
	//处理函数
	MRS R0,CPSR
	LDR R1,=SWI_TEST_STRING
	SUB R2,LR,#4
    BL SWIHandler
	
	//3.恢复现场,跳转回原来的位置
	LDMIA SP!,{R0-R12,PC}^  //^ 表示将SPSR恢复到CPSR中

DO_INTERRUPT:
	//1.设置栈
	LDR SP,=0x33d00000
	//2.保存现场
	SUBS LR, LR, #4
	STMDB SP!,{R0-R12,LR}
	
	//处理函数
    BL InterruptHandler
    bl testPrint1
	
	//3.恢复现场,跳转回原来的位置
	LDMIA SP!,{R0-R12,PC}^  //^ 表示将SPSR恢复到CPSR中

UND_TEST_STRING:
	.string "enter undefin mode!\n"
	
SWI_TEST_STRING:
	.string "enter swi mode!\n"

.align 4
RESET:
	MOV R0,#0
	LDR R1,[R0]
	
	STR R0,[R0]
	LDR R2,[R0]
	
	CMP R2,R0
	LDR SP,=0x40000000+4096
	MOVEQ SP,#4096
	STREQ R1,[R0]
	
	BL HardwareInitAll
	BL UartInit
	
TEST_UND:
	bl testPrint
	.word 0xdeadc0de
	//bl testPrint
TEST_SWI:
	MRS R0,CPSR
	BIC R0,R0,#0x0F
	MSR CPSR,R0
	SWI 0x123
	
	LDR pc,=main
halt:
    B halt
interrupt.h
----------------------
#ifndef __INTERRUPT_H
#define __INTERRUPT_H


void AllInterruptInit(void);
void InterruptHandler(void);


#endif


 

interrupt.c
-------------------------------

#include "interrupt.h"
#include <stdint.h>

#include "led.h"
#include "s3c2440.h"


static void InterruptControllerInit(void)
{
	//开启全局中断开关
	asm(
		"MRS R0,CPSR \n\t"
		"BIC R0,R0,#0x80 \n\t"
		"MSR CPSR,R0 \n\t"
	);

	//关闭相关中断的屏蔽
	INTMSK &= ~((1<<0) | (1<<2) | (1<<5)); 

}

static void ExternInterruptInit(void)
{
	//设置为外部中断引脚
	GPFCON &= ~((3<<0)|(3<<4));
	GPFCON |= (2<<0)|(2<<4);
	
	GPGCON &= ~((3<<6)|(3<<22));
	GPGCON |= (2<<6)|(2<<22);

	EXTINT0 |= (7<<0) | (7<<8);     /* S2,S3 */
	EXTINT1 |= (7<<12);             /* S4 */
	EXTINT2 |= (7<<12);
	
	/* 设置EINTMASK使能eint11,19 */
	EINTMASK &= ~((1<<11) | (1<<19));
}


void AllInterruptInit(void)
{
	InterruptControllerInit();
	ExternInterruptInit();
}

void ExtInterruptHandler(uint32_t irq)
{
	uint32_t ext_interrupt_bit = EINTPEND;
	
	switch(irq)
	{
		case 0:
		{
			ToggleLed(kLed1);
			break;
		}

		case 2:
		{		
			ToggleLed(kLed2);
			break;
		}
		
		case 5:
		{
			if(ext_interrupt_bit &( 1 << 9 ))
			{		
				ToggleLed(kLed3);
			}
			else if(ext_interrupt_bit &( 1 << 11 ))
			{			
				ToggleLed(kLed1);
				ToggleLed(kLed2);
				ToggleLed(kLed3);
			}
			
			break;
		}
		default:
			break;
	}
	
	EINTPEND = ext_interrupt_bit;
}

void InterruptHandler(void)
{
	uint32_t interrupt_bit = INTOFFSET;

	if(interrupt_bit>=0 && interrupt_bit <=5)
	{
		ExtInterruptHandler(interrupt_bit);
	}

	SRCPND = 1<< interrupt_bit;
	INTPND = 1<< interrupt_bit;
}


이 코드는 실제로 쓰기 작업 아니며, 일부 직접 수정없이 기본값을 사용하여 레지스터,하지만 여전히 카드 나에게 시간이 오래, 주로 항상 어떻게 든 가출 것이다 인터럽트 기능 또는 설명 할 수없는 재시작을 실행 버튼을 누른 후, 마지막 모습 DIS는 이상 언급 복귀 다른 값 중 하나에 다른 시점의 치료를 필요 발견 마이너스 (4)의 리턴 값을 중단 할 필요는 프로그램의 정상적인 흐름을 리턴한다.

 

타이머

이름에서 알 수 타이머 타이밍에 사용되는, 자신의 존재가 인터럽트 기능, 기능 인터럽트뿐만 아니라 타이머를 중단 때문에 여기에 넣어. 타이머를 비교함으로써, 다른 한편으로는, 주기적으로 또는 일시적으로 작업을 수행하는데 사용될 수있는 소정의 시간에 의해 생성되는 인터럽트 타이머를 설정 한 후 PWM 출력 타이머 PIN을 등록 할 수 있도록, 전원 제어 유닛 또는 다른 에너지가 필요 주변기기 호흡 광이 기능에 의해 달성 될 수 있고, 또한, 상기 클록 소스와 같은 주변기기 출력 할 수있다.

S3C2440 다섯 16 비트 시계가 시계가 비용의 서로 다른 이유를 추정 또는 때문에 어려운의 기능적 거세 또는 공유 자원의 존재를 달성하기 위해. TIMER0 타이머의 가장 완벽한입니다.

 왼쪽에서 오른쪽으로, 당신은 내용이 50MHz의 PCLK되기 전에 시계 타이머 사용의 PCLK 운전을 볼 수 있습니다. 8 비트 프리스케일러는 분할의 사용을 필요 즉 또한, 시간의주기를 감소시킬 수있다 그 후 사용 된 클록 주파수를 감소시킬 수는 PCLK 후에 존재하는 레지스터 MUX를 분주 수를 설정하여 분주보세요 . TCMPB가 출력하는 PWM 파형을 현재의 카운트 값을 비교하기 위해, 비교 레지스터 상기 타이머가 TCMPB, TCNTB 레지스터 존재 TCNTB 타이머 값이 0 인 경우, 우리는 자동으로 설정하고, 타이머 초기 값 세트와 비교 하중이 TCNTB 자동으로 카운트 레지스터에 할당됩니다. 또한 두 개의 레지스터는 언제든지 수정할 수 있지만 다음 타이밍 사이클에 필요한 사항을 적용하기 시작하면 너무 정상 작동 상태로 진행 ​​카운트를 보장하기 위해, 효과 어떤 시간이 소요되지 않습니다 알 수있다. 디지털 회로는이어서 하나 비트 파형의 출력을 반전 제어하는 ​​전환 하였다 선택기, 사다리꼴, 무효화된다. 상기 모터를 제어하는 ​​고전 H 브릿지 회로의 PWM 애플리케이션에서의 시간에 따른 보호 고전력 모터에 대한 데드 존 생성기 데드 밴드 발생기. 실질적으로 (A)에 온 전압을 제로 전위로 B 및 회로 A가 켜질 때 극관 증폭 회로 장치로서, 모터 M에 대한 중간체 (AD가 ··· 관한 동영상 드로잉 간단한을 사용할 필요가 없다) 아래 그림 두 번째 경우에는, 상기 모터도에 대응하는 전송된다고 가정. 전압이 시간 0 및 B로 전환 될 때, B 측 회로는도 3의 세 번째 경우에 해당하는 모터 역방향 경우 켜진다. 모터가 양에서 반대로 주위 역방향 또는 필요하면 진정한 아날로그 가능 돌연변이가없는 전압으로, 전압 스위칭 시간 A와 B를 통하여 결합. 이 때, 데드 타임 기간이없는 경우는 A와 B는 경우, ON 전압 범위에서 전원과 접지에 직접 단락, 네번째도 야기 특히 위험하다 할 수있다. 우리가이 문제를 해결 죽은 깡통 도움, 콘크리트는 더 이상 확장되지 않습니다.

S3C2440 카운터는 비교적 간단하지만, 또한 카운터가 0으로 감소된다 여기 만 감소 될 수 있고, 증가 또는 감소에 사용하기 이전에 카운터 (32)도 고려 걱정, 즉, 타이머 인터럽트의 타이밍을 트리거 세트. 섹션 설정 외에 타이머 인터럽트, 타이머 컨트롤러를 사용하려면, 또한 타이머와 시작을 ​​설정해야합니다. 관련 레지스터 다음과 같습니다 :

먼저 주파수 만 인터럽트 사용되는 우리는 타이머 1을 사용하여, 8 프리스케일러를 계산하고, 0에 따라서 만 프리스케일러. 또한, 적절한 값으로까지 클록을 이들 두 수치가 사용 복잡한 분배 인자가 필요로되는 경우 본원에, 주파수 분할을 이용하여 99 프리스케일러, 및 (16)에 직접 제공되는 최종 따라 같은 회선에 팩트만큼의 값, 화학식 50MHz의 클럭 / ((99 + 1) * 16) = 31250Hz이다.

 시계를 결정한 후에, 카운트 값은 PWM 출력 비교 레지스터가 설치되어 있지 않기 때문에 여기가 만 카운트 TCMPB0에 초기 값을 설정해야 할 필요가없고, 타이머 기간을 얻기 위해 결정된다. 상기에서 얻어진 시계에 따라, 우리는 0.5 초 한 번 중단 기대 가정, 당신은 당신이 원하는 효과를 일단 중단 0.5 초를 얻을 수 있습니다, 우리는 15,625의 초기 값을 설정해야한다는 것을 알 수 있습니다.

 마지막으로는 출력 클록 핀을 필요가 없기 때문에 자동으로 0의 초기 값을 다시하는 클럭 제어 레지스터를 설정하는 것이 필요 만 해당 타이머 0 동일한 관심, 타이머 세트이다 튜브 수없는 디폴트 값, 전환 칩 수동으로 수동 설정 수동 ​​업데이트를 시작하는 처음의 필요성에 대해 언급 설명서,하지만 필요에 따라하는 것은 다음에 시간을 쓰기 전에이 비트를 지 웁니다. 마지막으로, 타이머를 시작합니다.

 다음과 같이하여 출력하는 인터럽트 마스크 코드 관련된 타이머를 닫는 동안 외부 인터럽트는 프로그램에 기초하여 외부 인터럽트, 타이머에 더하여 다른 유사한 콘텐츠는, 인터럽트 핸들러 타이머를 초기화한다 :

interrupt.c
------------------------------------

#include "interrupt.h"
#include <stdint.h>

#include "led.h"
#include "s3c2440.h"

typedef void (*irq_func)(int);
irq_func irq_array[32];

static void register_irq(int irq, irq_func fp)
{
	irq_array[irq] = fp;
	INTMSK &= ~(1<<irq);
}

void Timer0InterruptHandler(int irq)
{
	ToggleLed(kLed1);
}

void ExtInterruptHandler(int irq)
{
	uint32_t ext_interrupt_bit = EINTPEND;
	
	switch(irq)
	{
		case 0:
		{
			ToggleLed(kLed1);
			break;
		}

		case 2:
		{		
			ToggleLed(kLed2);
			break;
		}
		
		case 5:
		{
			if(ext_interrupt_bit &( 1 << 9 ))
			{		
				ToggleLed(kLed3);
			}
			else if(ext_interrupt_bit &( 1 << 11 ))
			{			
				ToggleLed(kLed1);
				ToggleLed(kLed2);
				ToggleLed(kLed3);
			}
			
			break;
		}
		default:
			break;
	}
	
	EINTPEND = ext_interrupt_bit;
}


static void InterruptControllerInit(void)
{
	//开启全局中断开关
	asm(
		"MRS R0,CPSR \n\t"
		"BIC R0,R0,#0x80 \n\t"
		"MSR CPSR,R0 \n\t"
	);
}

static void ExternInterruptInit(void)
{
	//设置为外部中断引脚
	GPFCON &= ~((3<<0)|(3<<4));
	GPFCON |= (2<<0)|(2<<4);
	
	GPGCON &= ~((3<<6)|(3<<22));
	GPGCON |= (2<<6)|(2<<22);

	EXTINT0 |= (7<<0) | (7<<8);     /* S2,S3 */
	EXTINT1 |= (7<<12);             /* S4 */
	EXTINT2 |= (7<<12);
	
	/* 设置EINTMASK使能eint11,19 */
	EINTMASK &= ~((1<<11) | (1<<19));
	
	register_irq(0,ExtInterruptHandler);
	register_irq(2,ExtInterruptHandler);
	register_irq(5,ExtInterruptHandler);
}

static void Timer0InterruptInit(void)
{
	TCFG0 = 99;  
	TCFG1 &= ~0xf;
	TCFG1 |= 3;

	TCNTB0 = 15625;

	TCON |= (1<<1);

	TCON &= ~(1<<1);
	TCON |= (1<<0) | (1<<3);

	/* 设置中断 */
	register_irq(10, Timer0InterruptHandler);
}


void AllInterruptInit(void)
{
	InterruptControllerInit();
	ExternInterruptInit();
	Timer0InterruptInit();
}

void InterruptHandler(void)
{
	uint32_t interrupt_bit = INTOFFSET;

	irq_array[interrupt_bit](interrupt_bit);

	SRCPND = 1<< interrupt_bit;
	INTPND = 1<< interrupt_bit;
}


 예비 작업에 의해, 타이머는 함수 포인터 배열은, 코드 구조를 최적화하여 정상 기능을 제거하기 위해 매우 적은, 여기에서 여기를 중단 할 때 번호 및 인터럽트 핸들러 인터럽트 등록을 요구하는 인터럽트 초기화, 그래서 전체 인터럽트 핸들러 코드를 줄이기 위해 커플 링, 이후 증가 된 기능 중에 수정 될 필요가 없다. 코드 효과는 하, 하, 시각적으로 0.5 초, 빛 오프를했다.

 

게시 19 개 원래 기사 · 원 찬양 7 · 전망 6918

추천

출처blog.csdn.net/G_METHOD/article/details/104620994