Polling 방식은 CPU가 주기적으로 I/O 장치들의 상태를 확인 해야함.
이렇게 되면 성능이 당연히 저하될 수 밖에 없음. 자원 낭비가 되니까.
그렇기에 고안된게 Interrupt 방식.
매 Instruction 수행마다 HW는 I/O Event(Triggering)를 Check
발생 했다면, 다음 Instruction Cycle 시작 시, ISR Cycle을 수행.
큰 로직 자체는 범용 컴퓨팅 환경의 컴퓨터 구조와 같음.
Interrupt Request Sources(Service Request Node)
Interrupt를 발생시키는 주체로,
각 Interrupt는 우선순위(SPRN)를 가짐.
Interrupt Service Provider
Interrupt Request를 처리하는 HW들
요청 발생시, Interrupt가 걸리고 ISR을 Call함
ex) CPU, DMA Channel

구조는 이러한데, 보면 또 SPB와 연결되어 있다.
WDT의 ENDINIT도 보인다.
위 사진은 내부 Module만을 나타내지만, 외부 Module도 ERU로 Pin등에서 받아들일 수가 있음.
STM32에서도 볼 수 있었던 그거 맞다.
ISR의 시작 주소가 저장된 Table로 메모리에 저장된다.
Interrupt가 발생하면, BIV를 통해
우선 순위를 기반으로 해당 Interrupt의 ISR 진입 주소 계산하고
PC를 Load한다.
이 Table은 2word(8Byte) 혹은 8word(32Byte) 단위로 구성 가능
BIV 레지스터의 VSS bit로 설정 가능함.
0 : 32 Bytes
1 : 8 Bytes
즉 ISR이 담기는 곳
Code Section이나 임베디드 아키텍처에서는 .text에 해당하겠다.

Interrupt Vector Table의 Base 주소를 저장하는 Register
4 Byte로 구성되며, 해당 ISR의 .text 시작 주소를 저장하게 된다.

Interrupt 활성화 여부 확인 (ICR.IE == 1)
현재 Interrupt의 우선순위와
Pending Interrupt 우선순위 비교(굳이 따지면 Ready Queue)
ICR.CCPN > ICR.PIPN ? Update X : Update;
ICR.CCPN에 해당하는 Vector Table의 ISR Base로 PC를 Set
ISR 진입 (이때, 다른 Interrupt를 막기 위해 ICR.IE 비활성화하여, 인터럽트 수신을 막아버림)
Tricore역시 Nested Vector Interrupt를 지원하기에 다양한 Interrupt가 걸릴 수가 있음.
ISR 종료, 이전 PC 실행
(ICR.IE를 다시 1로 돌려 Interrupt Request 수신 가능)

종합하면, 이렇게 계산해서 Interrupt를 처리하게 된다.

Grouping된 (Group당 8개 SRN 존재) 부분은 SW Interrupt
혹은 Trap이라 부르는 Interrupt를 요청하는 Node들이다.
대표 예시로는, Core간 통신 등을 들 수가 있겠다.

많이 간소화하긴 했지만, 이렇게 Mapping되어 돌아간다고 생각하면 된다.
하나씩 뜯어보자.
SRC(Service Request Control) :
Interface Logic :
SRN은 IR 외부 Trigger Unit과 / IR 내부 Interrupt 중재 Bus와
연결되는 Interface Logic을 포함하고 있음.
외부 Trigger Unit으로부터 Interrupt 요청을 받고,
IR의 중재 Bus로 해당 Interrupt 요청을 전달하는 역할을 함.
당연한 이야기.

다음은 GPSR의 구조

ICU는 ISP 개수만큼 존재하며, 1대1로 Mapping되어 있음.
각 SRN의 SRCx.TOS 레지스터를 통해 특정 ICU에 Mapping됨.
그럼 ICU에서 ISP로 보내는 구조임.
하지만, TC375의 경우 Core 3개와 DMA 채널 1개로 총 4개 ICU 지원
각 ICU는 255단계의 우선 순위 설정 가능.
이때, 0은 사용하지 않고, 숫자가 클 수록 높은 우선순위임

IR Module의 레지스터 구성인데, 색칠 된 부분이 주목할 부분들
하나씩 또 뜯어보자.

SRPN[7:0]: SR 우선순위 번호
SRE[10]: SR 활성/비활성
0: SR 비활성
1: SR 활성
TOS[12:13]: SR을 어떤 코어에서 수행할 것인지 설정
000B: CPU0,
001B: DMA,
010B: CPU1,
011B: CPU2
(100B: CPU3,
101B: CPU4,
110B: CPU5)
4.ECC[20:16]: SRN내에서 오류 감지 위해 사용

CCPN[7:0]: 현재 CPU가 수행중인 ISR의 우선순위 번호
IE[15]: 인터럽트 시스템활성/비활성
0: Interrupt 시스템 비활성
1: Interrupt 시스템 활성
Interrupt 처리중에 이를 비활성 해주고, 아니면 활성화
ICR.IE = 1이 이거임

최근 SR 중재 라운드의 "이긴" SR 정보 제공
ICU가 ISP에게 제공한 정보들
PN[7:0]: 최근 중재에서 승리한 SR 우선순위 번호
ECC[14:10]: 최근 승리한 SRN에서 ICU로 전송된 ECC
ID[25:16]: 최근 승리한 SRN Index 번호
STAT[31]: LWSR 레지스터상태
PN, ECC, ID비트 필드 유효 여부표시
0 : LWSR 비트 필드가 유효하지않음
1 : LWSR 비트 필드가 유효함

SR중 ISP에 수락된 마지막 SR 정보
둘다 Interrupt Control Unit이다.

ICU에서 Error를 Detection했을때, LASR Capture
PN[0:7]: SR 우선순위 번호
ECC[14:10]: SR ECC
ID[25:16]: SRN Index 번호
EOV[30]: ECC Overflow Error 검출
0: Overflow Error가 검출되지 않음
1: Overflow Error가 검출됨
5.STAT[31]: Error 상태 비트, ICU에서 ECC가 발생하면 Set
0: No ECCerror detected
1: ECC Error detected
검출과 복구까지 가능함.
IR의 Interrupt 처리 과정을 살펴보자.
ISR 수행
Return
원래 일 / Interrupt 요청 재개
Ifx_Ssw_Tc0.c file는 MCU reset/인가시 가장 먼저 실행 되는
Start-Up Code다.
여기서 Vector Table을 초기화하고,
BIV 레지스터에 Vector Table의 시작 주소를 설정함.
static void __Core0_start(void)
{
…중략…
/* Trap vector table initialization is necessary if it is not same as default value */
Ifx_Ssw_MTCR(CPU_BTV, (unsigned int)__TRAPTAB(0));
/* Base interrupt vector table initialized */
Ifx_Ssw_MTCR(CPU_BIV, (unsigned int)__INTTAB(0));
/* Interrupt stack pointer is configured */
Ifx_Ssw_MTCR(CPU_ISP, (unsigned int)__ISTACK(0));
…중략…
}
__INTTAB(0)이게 CPU0의 BIV가 가르키게 될 초기 지점이다.
IFX_INLINE void IfxCpu_enableInterrupts(void)
{
__enable(); // Interrupt 활성(Atomic 연산)
//__disable(); Interrupt 비활성 함수
}
위 함수는 컴파일러 내장 함수로 제공되는 함수들
CompilerTasking.h file에 Define되어 있음
Interrupt handler 즉, ISR를 등록하는 함수

SRC는 SRPN(우선순위) / TOS(실행될 곳) / SRE(SR Enable)의 주요 설정을 가짐.
모듈별 SRC는 : SRC_모듈명
ex) ASCLIN Module관련 Interrupt를 구성하고자 하는 경우에는?
SRC_ASCLINxTX/ASCLINxRX를 이용하면 된다.

ASCLIN이 12개가 있음을 볼 수 있다.

iLLD를 확인해도 배열 형태로 12개를 나타내고 있다
…중략…
/* Definition of the interrupt priorities */
#define ISR_PRIORITY_ASCLIN0_RX 18
#define ISR_PRIORITY_ASCLIN0_TX 19
…중략…
…중략…
/* Adding of the interrupt service routines, ISR 등록 */
IFX_INTERRUPT(Asclin0RxIsrHandler, 0,ISR_PRIORITY_ASCLIN0_RX);
//ISR 정의
void Asclin0RxIsrHandler(void)
{
char c = Asclin0_InUart();
Asclin0_OutUart(c);
}
…중략…
void Asclin0_InitUart(void)
{
...중략...
/* Initialize ASCLIN0 RX interrupt */
volatile Ifx_SRC_SRCR *src;
src = (volatile Ifx_SRC_SRCR *) (&MODULE_SRC.ASCLIN.ASCLIN[0].RX);
src->B.SRPN = ISR_PRIORITY_ASCLIN0_RX;
src->B.TOS = 0;
src->B.CLRR = 1; /* clear request */
MODULE_ASCLIN0.FLAGSENABLE.B.RFLE = 1; /* enable rx fifo fill level flag */
src->B.SRE = 1; /* interrupt enable */
}
SRN 설정을 Module별 SRC로 설정해주고 있음.
보면 MODULE_SRC.ASCLIN.ASCLIN[0].RX로
ASCLIN0 RX의 SRN/SRC 설정을 해주고 있다.
UART로 ‘1’을 입력 받으면 LED1을 ON하고,
‘0’을 입력 받으면 LED1을 OFF하는 프로그램
LED ON/OFF시, my_printf 함수로 출력하라
LED ON → 터미널에 LED ON! 출력
LED OFF → 터미널에 LED OFF! 출력
#include "main.h"
int main(void)
{
SYSTEM_Init();
/* LED1초기상태: off */
GPIO_SetLed(1, 0);
while (1);
return 0;
}
IFX_INTERRUPT(Asclin0RxIsrHandler, 0, ISR_PRIORITY_ASCLIN0_RX);
void Asclin0RxIsrHandler(void)
{
/* 문자 하나를 입력받음*/
char c = Asclin0_InUart();
/* 입력받은 문자가 ‘1’이면, LED ON */
if (c == '1') {
GPIO_SetLed(1, 1);
my_printf("LED ON!\n");
/* 입력받은 문자가 ‘0’이면, LED OFF */
} else if (c == '0') {
GPIO_SetLed(1, 0);
my_printf("LED OFF!\n");
}
}
이제 Interrupt를 등록도 했고, Enable도 했기 때문에
발생하면 Polling식이 아니라, Interrupt식으로 처리를 한다.
따라서 기존에 작성하던 Polling 방식처럼 (예제는 다르지만)
#include "main.h"
int main(void)
{
SYSTEM_Init();
unsigned char c;
while(1) {
c = Asclin0_InUart(); //문자 하나를 입력받음
Asclin0_OutUart(c); // 입력 받은 문자 전송
}
return 0;
}
이렇게 main에서 계속 Core를 붙잡고 있을 일이 사라졌다!
Core는 계속 들어오는지 확인할 필요도 없고
들어오면 Interrupt 걸리고 그때, ISR을 수행해주면 될 뿐임
https://youtube.com/shorts/gVxVthBfhTk
putty에서 문자를 입력받아 대소문자를 변환
Interrupt 방식의 UART 통신 사용
소문자를 입력 대문자를 출력→ ‘a’입력시 터미널에 ‘A’출력
대문자를 입력 소문자를 출력→ ‘A’입력시 터미널에 ‘a’ 출력
IFX_INTERRUPT(Asclin0RxIsrHandler, 0, ISR_PRIORITY_ASCLIN0_RX);
void Asclin0RxIsrHandler(void)
{
charc = Asclin0_InUart();
if (c >= 'a' && c <= 'z') {
Asclin0_OutUart(c - 32);
} else if (c >= 'A' && c <= 'Z') {
Asclin0_OutUart(c + 32);
} else { //이외 문자는 그냥 출력
Asclin0_OutUart(c);
}
}
별건 없고 그냥 ASCII Code 성질을 이용하여 ISR을 바꾸면 된다.
https://youtube.com/shorts/gy51n7chTkY
ASCLIN이나 MCMCAN 같은건 "내부" I/O다.
ERU는 "외부" I/O로 Pin(연결된 부품 등)으로 Interrupt를 걸 때 씀.
다목적 Event/Pattern 감지 장치
다양한 Input에서 선택 가능한 Trigger Event를 기반으로 Interrupt 생성
독립적인 8개의 채널 :
Trigger/Gate 기능의 Input 선택/조건 설정
Event 분배 :
Connecting Matrix로 Input channel x의 event를 Output channel y의 반응으로 연결 정의
독립적인 8개의 Output Channel :
Event 조합/ Event 발생시 효과 정의, System으로 분배(Interrupt 생성)을 위한 Chanel
예를 들면, Falling/Rising Edge를 감지하여 Input으로 받아들일 수가 있다. 사실 내부 I/O랑 다를건 없음. 구조가 좀 상이할 뿐

Output 뒤에는 IR이 존재한다. 즉 얘내도 SRN인거다. SRC를 설정할 수 있고, ICU로 보내 ISP에서 처리를 진행한다.
세부 구조를 다시 뜯어보자.
Input Channel당 ERS를 사용해 4개의 사용 가능한 Input중 1개 선택 ERS는 Channel당 8개가 존재함.
Input Channel당 ETL(Event Trigger Logic)을 통해 Trigger Event Signal로 변환
Matrix를 통해 생성된 Event Signal과 상태 Flag를 Output Channel로 분배
Output Channel당 1개의 OGU는 Input Channel에서 사용 가능한 Trigger Event와 상태 정보를 결합해 System에 최종 결과 분배.
ex) Input Signal 종류 :
Port / CCU / STM / GPT12 등

외부 요청 Signal에 대해 Trigger(Rising/Falling) 설정
Trigger Pulse를 생성함
4개의 ETL 장치의 각 쌍에는 EICRy와 연결되어 ETL의 모든 옵션 제어

다양한 ETLx 장치로부터 발생한 트리거 신호(TRxy)와
상태 신호(EIFR.INPFx)를 OGUy 장치들 사이에 분배

Input Channel로 제공 된 Trigger Event와 상태 Flag를 조합해
System에 결과를 분배
Trigger 조합 :
OGUy로 유도된 활성화된 Input Channel의 All Trigger Signal(TRxy)와
Pattern 변경 Event(활성화 된 경우)가 OR로 결합됨
Pattern 감지 :
Input Channel의 EIFR.INTFx 상태 Flag를 활성화해 Pattern 감지
All 활성화된 상태 Flag가 설정된 경우 Pattern 일치가 감지 됨
SW2는 P2.1과 연결
P2.1은 ERU Module의 2번째 ERS의 2번째 신호로 연결됨(Channel?)
ERS2의 2번째 입력 신호로 연결됨

Each External Input Channel Register EICRi (i=0 to 3) contains bits to configure the external request selection ERS
and the event trigger logic ETL for two input channels.
1개의 EICR은 2개의 Input Channel을 담당한다.
그래서 4개의 EICR이 8개의 Input Channel을 담당하게 된다.
ERS가 Input Channel이고
Mapping된 ETL이 Output이라고 이해하면 될듯
그러니까 우리는 ETL2를 써야 한다.
그리고 기본적으로는 OGU 0으로 나간다.
8개 Channel중 1개의 Input Signal을 선택
우리는 EICR1.EXIS0의 두번째 Pin을 사용해야 하므로, 001을 사용
즉, EXIS0 = 1이므로, ERS2의 입력 중 1번(두번째)이 선택됨.

FEN0[8] : Falling Edge 활성화
REN0[9] : Rising Edge 활성화
EIEN0[11] : Enable Trigger 쓰려면 당연히 1로
만약 EICR1(i).B.EIEN0=1 이라면,
i=1,로 2i(2번째 Input Channel)에 대한 Trigger Event 생성 활성화


Output Channel(OGU)도, Input Channel의 ERS처럼 2개 있다고 생각하면 될듯.
그래서 IGCR[0].IGP0은 Output Channel 0에
IGCR[0].IGP1은 1에
IGCR[1].IGP0은 2에
...
IGCR[3].IGP0은 6에
IGCR[3].IGP1은 7에
Mapping된다.
IGPx(x=0,1) : Interrupt Gating Pattern Bit field
IGP0은 Pattern 감지가 Output line인 GOUT(2j)와 IOUT(2j)에 영향을 미치는 방식을 결정함.
만약 IGCR0.B.IGP0=1이면 j=0이므로, IOUT(0)는 Trigger Event에 응답해 활성화되고, Pattern은 고려되지 않음.

void scueru_Init()
{
uint16 password = IfxScuWdt_getSafetyWatchdogPasswordInline();
IfxScuWdt_clearSafetyEndinitInline(password);
//Port 02.1을 Pull-up Input으로 Set
MODULE_P02.IOCR0.B.PC1 = 0x02;
/* EICR.EXIS 레지스터 설정 : ERS2, 1번 신호 */
MODULE_SCU.EICR[1].B.EXIS0 = 1;
/* rising, falling edge 트리거 설정 */
MODULE_SCU.EICR[1].B.REN0 = 0;
MODULE_SCU.EICR[1].B.FEN0 = 1;
// Channel 2의 Trigger Event 활성화
MODULE_SCU.EICR[1].B.EIEN0 = 1;
// OGU 0으로 ETL2(TR) Trigger Event 보낼거임
MODULE_SCU.EICR[1].B.INP0 = 0;
// OGU0은 IGCR[0]/IGP0임 Pattern 고려 없이
// GOUT/IOUT 출력라인을 Trigger event 반응하게 Set
MODULE_SCU.IGCR[0].B.IGP0 = 1;
//Interrupt를 위해 SCU의 SRC설정
volatile Ifx_SRC_SRCR *src;
src = (volatile Ifx_SRC_SRCR*) (&MODULE_SRC.SCU.SCUERU);
src->B.SRPN = ISR_PRIORITY_ERU_INT0;
src->B.TOS = 0;
src->B.CLRR = 1; /* clear request */
src->B.SRE = 1; /* interrupt enable */
IfxScuWdt_setSafetyEndinitInline(password);
}
IFX_INTERRUPT(SCUERU_Int0_Handler, 0, ISR_PRIORITY_ERU_INT0);
void SCUERU_Int0_Handler (void)
{
my_printf("SCU_ERU_INT0!\n");
}
흐름을 정리하자면,
P02.1를 쓰기 때문에, EICR[1]의 EXIS[0]을 골랐음
(Channel은 어케알음?)
그리고 Falling Edge를 받기로 하고, Enable 해줌
EICR[1]의 INP1를 0으로해 ETL 3의 Trigger를
OGU0으로 보내줌. (G/IOUT 0)
그리고 OGU0이 Channel 2 Trigger에 반응하도록 1로 Set해줌
https://youtube.com/shorts/cIhev19diD8
Switch를 누르면 외부 Interrupt(Port)한테 걸려서 ISR을 처리함.
https://youtube.com/shorts/cJbeRkJKp7w
별 건 없고, 그냥 Toggle 하도록 바꿨음.
IFX_INTERRUPT(SCUERU_Int0_Handler, 0, ISR_PRIORITY_ERU_INT0);
void SCUERU_Int0_Handler (void)
{
my_printf("SCU_ERU_INT0!\n");
while(1);
}
/* Definition of the interrupt priorities */
#define ISR_PRIORITY_ASCLIN0_RX 18
#define ISR_PRIORITY_ASCLIN0_TX 19
#define ISR_PRIORITY_ERU_INT0 17
#define ISR_PRIORITY_GPT1T3_TIMER 5 /* Define the GPT12 Timer interrupt priority */
#define ISR_PRIORITY_GPT2T6_TIMER 6 /* Define the GPT12 Timer interrupt priority */
#define ISR_PRIORITY_ATOM 20
#endif /* BSW_DRIVER_ISR_PRIORITY_H_ */
ERU Interrupt 및 UART0 RX Interrupt 우선순위에 따른 수행결과
비교를 위해 ERU Interrupt에 무한 루프 로직 추가
ASCLIN0_RX Interrupt가 우선순위가 높음에도 불구,
RX 수행불가 ERU Interrupt 진입 시 인터럽트 기능 해제됨.(IE??)
IFX_INTERRUPT(SCUERU_Int0_Handler, 0, ISR_PRIORITY_ERU_INT0);
void SCUERU_Int0_Handler (void)
{
my_printf("SCU_ERU_INT0!\n");
__enable();
while(1);
}
Interrupt Enable을 시켜주면,
ERU Interrupt 수행 도중 ASCLIN0 RX Interrupt 발생 시 수행 가능
만약 ERU의 우선순위를 30으로 높여주면, RX Interrupt가 이를 뺏지 못하고 Pending됨.
영상을 못 찍어서 이건 영상이 없다 쩝.
void scueru_Init()
{
uint16 password = IfxScuWdt_getSafetyWatchdogPasswordInline();
IfxScuWdt_clearSafetyEndinitInline(password);
MODULE_P02.IOCR0.B.PC1 = 0x02; /* Set P2.1 as pull-up input */
/* EICR.EXIS 레지스터 설정 : ESR2, 1번 신호 */
MODULE_SCU.EICR[1].B.EXIS0 = 1;
/* rising, falling edge 트리거 설정 */
MODULE_SCU.EICR[1].B.REN0 = 0;
MODULE_SCU.EICR[1].B.FEN0 = 1;
/* Enable Trigger Pulse */
MODULE_SCU.EICR[1].B.EIEN0 = 1;
/* Determination of output channel for trigger event (Register INP) */
MODULE_SCU.EICR[1].B.INP0 = 2;
/* Configure Output channels, outputgating unit OGU (Register IGPy) */
MODULE_SCU.IGCR[1].B.IGP0 = 1;
volatile Ifx_SRC_SRCR *src;
src = (volatile Ifx_SRC_SRCR*) (&MODULE_SRC.SCU.SCUERU[2]);
src->B.SRPN = ISR_PRIORITY_ERU_INT0;
src->B.TOS = 0;
src->B.CLRR = 1; /* clear request */
src->B.SRE = 1; /* interrupt enable */
IfxScuWdt_setSafetyEndinitInline(password);
}
IFX_INTERRUPT(SCUERU_Int0_Handler, 0, ISR_PRIORITY_ERU_INT0);
void SCUERU_Int0_Handler (void)
{
my_printf("SCU_ERU_INT0!\n");
}
이렇게 해주면, OGU 2 지정 후/ IOUT2 / SRC_SCUERU[2]

왜 안되나 했더니 IOUT들이 SRC와 이렇게 물려 있다.
HW적으로 지식이 필요한 이유와 Datasheet로 HW 특성을 잘 파악해야 하는 이유.
Connecting Matrix를 통해 OGU3까진 내보낼 수 있음이 확인되었음.
void scueru_Init()
{
uint16 password = IfxScuWdt_getSafetyWatchdogPasswordInline();
IfxScuWdt_clearSafetyEndinitInline(password);
MODULE_P02.IOCR0.B.PC1 = 0x02; /* Set P2.1 as pull-up input */
/* EICR.EXIS 레지스터 설정 : ESR2, 1번 신호 */
MODULE_SCU.EICR[1].B.EXIS0 = 1;
/* rising, falling edge 트리거 설정 */
MODULE_SCU.EICR[1].B.REN0 = 0;
MODULE_SCU.EICR[1].B.FEN0 = 1;
/* Enable Trigger Pulse */
MODULE_SCU.EICR[1].B.EIEN0 = 1;
/* Determination of output channel for trigger event (Register INP) */
MODULE_SCU.EICR[1].B.INP0 = 1;
/* Configure Output channels, outputgating unit OGU (Register IGPy) */
MODULE_SCU.IGCR[0].B.IGP1 = 1;
volatile Ifx_SRC_SRCR *src;
src = (volatile Ifx_SRC_SRCR*) (&MODULE_SRC.SCU.SCUERU[1]);
src->B.SRPN = ISR_PRIORITY_ERU_INT0;
src->B.TOS = 0;
src->B.CLRR = 1; /* clear request */
src->B.SRE = 1; /* interrupt enable */
IfxScuWdt_setSafetyEndinitInline(password);
}
IFX_INTERRUPT(SCUERU_Int0_Handler, 0, ISR_PRIORITY_ERU_INT0);
void SCUERU_Int0_Handler (void)
{
my_printf("SCU_ERU_INT0!\n");
}
void scueru_Init()
{
uint16 password = IfxScuWdt_getSafetyWatchdogPasswordInline();
IfxScuWdt_clearSafetyEndinitInline(password);
MODULE_P02.IOCR0.B.PC1 = 0x02; /* Set P2.1 as pull-up input */
/* EICR.EXIS 레지스터 설정 : ESR2, 1번 신호 */
MODULE_SCU.EICR[1].B.EXIS0 = 1;
/* rising, falling edge 트리거 설정 */
MODULE_SCU.EICR[1].B.REN0 = 0;
MODULE_SCU.EICR[1].B.FEN0 = 1;
/* Enable Trigger Pulse */
MODULE_SCU.EICR[1].B.EIEN0 = 1;
/* Determination of output channel for trigger event (Register INP) */
MODULE_SCU.EICR[1].B.INP0 = 3;
/* Configure Output channels, outputgating unit OGU (Register IGPy) */
MODULE_SCU.IGCR[1].B.IGP1 = 1;
volatile Ifx_SRC_SRCR *src;
src = (volatile Ifx_SRC_SRCR*) (&MODULE_SRC.SCU.SCUERU[3]);
src->B.SRPN = ISR_PRIORITY_ERU_INT0;
src->B.TOS = 0;
src->B.CLRR = 1; /* clear request */
src->B.SRE = 1; /* interrupt enable */
IfxScuWdt_setSafetyEndinitInline(password);
}
IFX_INTERRUPT(SCUERU_Int0_Handler, 0, ISR_PRIORITY_ERU_INT0);
void SCUERU_Int0_Handler (void)
{
my_printf("SCU_ERU_INT0!\n");
}
void scueru_Init()
{
uint16 password = IfxScuWdt_getSafetyWatchdogPasswordInline();
IfxScuWdt_clearSafetyEndinitInline(password);
MODULE_P02.IOCR0.B.PC1 = 0x02; /* Set P2.1 as pull-up input */
/* EICR.EXIS 레지스터 설정 : ESR2, 1번 신호 */
MODULE_SCU.EICR[1].B.EXIS0 = 1;
/* rising, falling edge 트리거 설정 */
MODULE_SCU.EICR[1].B.REN0 = 0;
MODULE_SCU.EICR[1].B.FEN0 = 1;
/* Enable Trigger Pulse */
MODULE_SCU.EICR[1].B.EIEN0 = 1;
/* Determination of output channel for trigger event (Register INP) */
MODULE_SCU.EICR[1].B.INP0 = 0;
/* Configure Output channels, outputgating unit OGU (Register IGPy) */
MODULE_SCU.IGCR[0].B.IGP0 = 1;
volatile Ifx_SRC_SRCR *src;
src = (volatile Ifx_SRC_SRCR*) (&MODULE_SRC.SCU.SCUERU[0]);
src->B.SRPN = ISR_PRIORITY_ERU_INT0;
src->B.TOS = 0;
src->B.CLRR = 1; /* clear request */
src->B.SRE = 1; /* interrupt enable */
IfxScuWdt_setSafetyEndinitInline(password);
}
IFX_INTERRUPT(SCUERU_Int0_Handler, 0, ISR_PRIORITY_ERU_INT0);
void SCUERU_Int0_Handler (void)
{
my_printf("SCU_ERU_INT0!\n");
}
채널당 입력 Pin이 4개지 않은가?
그래서 OGU 0~3 까지만 실질적으로 Interrupt를 생성해서 전달할 수 있다. 그래서 SCUERU[4]로 선언되어 있는것