*AT91C_AIC_ICCR=(1<<AT91C_ID_PIOA); // 기존의 인터럽트 신호를 초기화
*AT91C_PIOA_IFER=PIN_IRQ; // Glitch Filter 활성화
잡음의 펄스 또는 버스트. 논리 회로가 타이밍에서 벗어나는 것 등으로 본래 필요 없는 부분에 발생하는 펄스로서 오동작의 원인이 된다.
Glitch Filter는 이런 오동작의 원인이 되는 Glitch를 걸러내주는 Filter이다.
*AT91C_AIC_ISCR=(1<<AT91C_ID_PIOA); // 해당하는 인터럽트를 활성화(그룹 ON)
*AT91C_AIC_ICCR=(1<<AT91C_ID_PIOA); // 해당하는 인터럽트를 비활성화(그룹 OFF)
PIO_ISR 레지스터
어느 핀에 인터럽트가 걸려있는지 확인가능
PIO_IMR 레지스터
어느 핀에 인터럽트가 셋팅되어있는지 확인가능
PIO_ISR가 인터럽트 신호를 가지고 있지만 리드하는 순간 0으로 클리어되기에 이를 저장할 변수를 선언한다.
static unsigned int uiStatus; // 인터럽트 신호를 저장할 변수 (static사용 이유는 속도 때문이다. 반환하는 시간을 줄이기 위해서) uiStatus=*AT91C_PIOA_ISR;
ARM 컴파일러는 함수의 인자 4개까지는 레지스터에 저장하고 그이후부터 스택에 저장한다.
ARM 컴파일러 종류
<소스코드 irq.c>
더보기 접기
#include < irq.h >
void IRQ_Init( void ) { IRQ_lED_Init(); *AT91C_PMC_PCER = ( 1 < < AT91C_ID_PIOA); // PIOA에 전원 공급 DBGU는 생략 가능하나 INTERRUPT는 해야함 *AT91C_PIOA_ODR = PIN_IRQ; // PIN_IRQ 출력 비활성화 *AT91C_PIOA_PER = PIN_IRQ; // PIN_IRQ 핀 활성화 *AT91C_PIOA_IDR = PIN_IRQ; // PIN_IRQ 인터럽트 비활성화 *AT91C_AIC_IDCR = ( 1 < < AT91C_ID_PIOA); // PIOA인터럽트 비활성화 *AT91C_PIOA_PPUDR = PIN_IRQ; //PIN_IRQ PULL-UP 저항 OFF AT91C_AIC_SVR[AT91C_ID_PIOA] = ( volatile unsigned int )IRQ_Handler; //함수 주소 저장하는 레지스터(SVR)에 핸들러의 주소 레지스터를 저장 //SVR0~31까지중에 PIOA의 ID는 2이므로 [2]로 선언해서 접근 AT91C_AIC_SMR[AT91C_ID_PIOA] = AT91C_AIC_SRCTYPE_HIGH_LEVEL | AT91C_AIC_PRIOR_LOWEST; // 낮은 우선순위와 상승엣지 발생시 인터럽트 발생 *AT91C_AIC_ICCR = ( 1 < < AT91C_ID_PIOA); // 해당하는 인터럽트를 비활성화(그룹 OFF) *AT91C_PIOA_IFER = PIN_IRQ; // PIN_IRQ Glitch Filter 활성화 *AT91C_AIC_ISCR = ( 1 < < AT91C_ID_PIOA); // 해당하는 인터럽트를 활성화(그룹 ON) *AT91C_PIOA_IER = PIN_IRQ; // PIN_IRQ 인터럽트 활성화 *AT91C_AIC_IECR = ( 1 < < AT91C_ID_PIOA); // AIC Interrupt 활성화 } void IRQ_lED_Init( void ) { *AT91C_PMC_PCER = ( 1 < < AT91C_ID_PIOA); // PIOA에 전원 공급( DBGU는 생략 가능하나 INTERRUPT는 해야함) *AT91C_PIOA_PER = PIN_LED; // PIN_LED 핀 활성화 *AT91C_PIOA_OER = PIN_LED; // PIN_LED 출력 활성화 *AT91C_PIOA_SODR = PIN_LED; // PIN_LED LED OFF } void IRQ_lED_Toggle( void ) { static unsigned int uiLedStatus = LED_OFF; if (LED_ON = = uiLedStatus) { *AT91C_PIOA_SODR = PIN_LED; // PIN_LED LED OFF uiLedStatus = LED_OFF; } else { *AT91C_PIOA_CODR = PIN_LED; // PIN_LED LED ON uiLedStatus = LED_ON; } } void IRQ_Handler( void ) { static volatile unsigned int uiStatus; // 인터럽트 신호를 저장할 변수 (static사용 이유는 속도 때문이다. 반환하는 시간을 줄이기 위해서) volatile unsigned int uiCnt; uiStatus = *AT91C_PIOA_ISR; // 발생한 인터럽트 신호를 변수에 저장한다. (ISR레지스터를 읽으면 0으로 클리어된다.) if ( 0 ! = uiStatus & PIN_IRQ) // 인터럽트신호가 발생하면 함수 호출 { IRQ_lED_Toggle(); } DELAY( 350000 ); uiStatus = *AT91C_PIOA_ISR; // 처리하는 동안 중간에 인터럽트 신호 발생할수도 있기에 0으로 클리어함 *AT91C_AIC_EOICR = 0 ; //인터럽트를 종료할경우 사용함 단 영향은 미치지 않음 }
접기 <소스코드 main.c>
#include < project.h> #include < lcd.h> #include < dbgu.h> #include < irq.h> int main(void ) { volatile unsigned int uiCnt; int cnt = 0 ; LCD_Init(); IRQ_Init(); IRQ_lED_Init(); LCD_Str(" This is test." ); while (1 ) { for (uiCnt = 0 ; 500000 > uiCnt; ++uiCnt); LCD_Inst(INST_SETDDRAM | 0x42 ); LCD_Data(('0' +(cnt%10 ))); ++cnt; } while (1 ); return 0 ; } <소스파일> 2014.07.14.zip