[TC375] Interrupt Module(IR) / SCUERU

CS·2025년 7월 6일

Device Driver

목록 보기
4/5

Polling 방식은 CPU가 주기적으로 I/O 장치들의 상태를 확인 해야함.
이렇게 되면 성능이 당연히 저하될 수 밖에 없음. 자원 낭비가 되니까.

그렇기에 고안된게 Interrupt 방식.
매 Instruction 수행마다 HW는 I/O Event(Triggering)를 Check
발생 했다면, 다음 Instruction Cycle 시작 시, ISR Cycle을 수행.

큰 로직 자체는 범용 컴퓨팅 환경의 컴퓨터 구조와 같음.


  • Tricore Interrupt System 구성
  1. Interrupt Request Sources(Service Request Node)
    Interrupt를 발생시키는 주체로,
    각 Interrupt는 우선순위(SPRN)를 가짐.

  2. Interrupt Service Provider
    Interrupt Request를 처리하는 HW들
    요청 발생시, Interrupt가 걸리고 ISR을 Call함

ex) CPU, DMA Channel

  1. Interrupt Control Unit
    각각의 ISP와 Mapping되어 어떤 ISP에게 Interrupt를 줄 지 제어
    여기서 우선 순위를 따져 ISP에게 더 높은 Interrupt를 전달함.

구조는 이러한데, 보면 또 SPB와 연결되어 있다.
WDT의 ENDINIT도 보인다.

위 사진은 내부 Module만을 나타내지만, 외부 Module도 ERU로 Pin등에서 받아들일 수가 있음.


  • Interrupt Vector Table

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에 해당하겠다.

  • BIV (Base Interrupt Vector Table Pointer)

Interrupt Vector Table의 Base 주소를 저장하는 Register

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

  1. BIV[31:1] : Vector Table Base Address 저장
  2. VSS[0] : Vector Table의 크기 설정


  • Interrupt 수행 과정
  1. Interrupt 활성화 여부 확인 (ICR.IE == 1)

  2. 현재 Interrupt의 우선순위와
    Pending Interrupt 우선순위 비교(굳이 따지면 Ready Queue)

ICR.CCPN > ICR.PIPN ? Update X : Update;

  1. ICR.CCPN에 해당하는 Vector Table의 ISR Base로 PC를 Set

  2. ISR 진입 (이때, 다른 Interrupt를 막기 위해 ICR.IE 비활성화하여, 인터럽트 수신을 막아버림)
    Tricore역시 Nested Vector Interrupt를 지원하기에 다양한 Interrupt가 걸릴 수가 있음.

  3. ISR 종료, 이전 PC 실행
    (ICR.IE를 다시 1로 돌려 Interrupt Request 수신 가능)

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


  • TC3xx Interrupt Router(IR) Module 구성

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

많이 간소화하긴 했지만, 이렇게 Mapping되어 돌아간다고 생각하면 된다.
하나씩 뜯어보자.


  • SRN(Service Request Node) : 1024개까지 설정가능
  1. Interrupt 요청 관리/처리 역할 수행
  2. 각 SRN은 각각의 SRC register를 포함.

SRC(Service Request Control) :

  1. Interrupt 요청 우선순위 설정
  2. Interrupt Routing(TOS) 정보 저장

Interface Logic :

SRN은 IR 외부 Trigger Unit과 / IR 내부 Interrupt 중재 Bus와
연결되는 Interface Logic을 포함하고 있음.

외부 Trigger Unit으로부터 Interrupt 요청을 받고,
IR의 중재 Bus로 해당 Interrupt 요청을 전달하는 역할을 함.

당연한 이야기.


  • GPSR(범용 서비스 요청, General Purpose Service Requset)

  1. ISP에게 Service Request를 병렬로 Trigger할 수 있는 기능
  2. TC 375의 경우 3개의 GPSR Group 제공(Group당 8개 SRN)
  3. INT_SRBxy(그룹번호(0~2)/그룹 내 SRN 번호(0~7) register :
    이를 통해 ISP에게 Service Request가 가능함.

다음은 GPSR의 구조


  • ICU (Interrupt Control Unit, 인터럽트 제어 유닛)
  1. Interrupt 중재/전달
  2. Service Request 정보 수신/확인 (ECC check)
  3. 확인된 Service Request Clear 관리

ICU는 ISP 개수만큼 존재하며, 1대1로 Mapping되어 있음.

각 SRN의 SRCx.TOS 레지스터를 통해 특정 ICU에 Mapping됨.
그럼 ICU에서 ISP로 보내는 구조임.


  • IR 특징
  1. 각 SRN의 SR관련 설정은 SRC 통해 가능
  2. SRN은 1개의 ICU에만 연결 가능. 즉 동시에 다른 ICU로 못보냄
  3. 하지만 ICU에는 여러 SRN과 연결될 수 있음(TOS)
  4. MCU core에 따라 최대 8개 ICU 지원

하지만, TC375의 경우 Core 3개와 DMA 채널 1개로 총 4개 ICU 지원
각 ICU는 255단계의 우선 순위 설정 가능.

이때, 0은 사용하지 않고, 숫자가 클 수록 높은 우선순위임

IR Module의 레지스터 구성인데, 색칠 된 부분이 주목할 부분들

하나씩 또 뜯어보자.

  • Service Request Control (SRCi)

  1. SRPN[7:0]: SR 우선순위 번호

  2. SRE[10]: SR 활성/비활성
    0: SR 비활성
    1: SR 활성

  3. TOS[12:13]: SR을 어떤 코어에서 수행할 것인지 설정
    000B: CPU0,
    001B: DMA,
    010B: CPU1,
    011B: CPU2
    (100B: CPU3,
    101B: CPU4,
    110B: CPU5)

4.ECC[20:16]: SRN내에서 오류 감지 위해 사용


  • ICU Interrupt Control Register(ICR)

  1. CCPN[7:0]: 현재 CPU가 수행중인 ISR의 우선순위 번호

  2. IE[15]: 인터럽트 시스템활성/비활성
    0: Interrupt 시스템 비활성
    1: Interrupt 시스템 활성

Interrupt 처리중에 이를 비활성 해주고, 아니면 활성화
ICR.IE = 1이 이거임

  1. PIPN[23:16]: 다음에 수행할 인터럽트 우선순위 번호
    00 : Interrupt 요청이 없는 경우
    01 : Interrupt 요청이 있고, 우선순위가 가장 낮은 경우

    FF : Interrupt 요청이 있고, 우선순위가 가장 높은 경우

  • Latest Winning Service Request register (LWSR)

최근 SR 중재 라운드의 "이긴" SR 정보 제공
ICU가 ISP에게 제공한 정보들

  1. PN[7:0]: 최근 중재에서 승리한 SR 우선순위 번호

  2. ECC[14:10]: 최근 승리한 SRN에서 ICU로 전송된 ECC

  3. ID[25:16]: 최근 승리한 SRN Index 번호

  4. STAT[31]: LWSR 레지스터상태
    PN, ECC, ID비트 필드 유효 여부표시
    0 : LWSR 비트 필드가 유효하지않음
    1 : LWSR 비트 필드가 유효함

  • Last Acknowledged Service Request (LASRx, x=0~7)

SR중 ISP에 수락된 마지막 SR 정보

  1. PN[7:0]: 최근 승인된 SR의 우선순위 번호
  2. ECC[14:10]: 최근 승인된 SR의 ECC 값
  3. ID[25:16]: 최근 승인된 SRN의 Index 번호

둘다 Interrupt Control Unit이다.

  • Error Capture Register (ECRx, x=0~7)

ICU에서 Error를 Detection했을때, LASR Capture

  1. PN[0:7]: SR 우선순위 번호

  2. ECC[14:10]: SR ECC

  3. ID[25:16]: SRN Index 번호

  4. 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 처리 과정을 살펴보자.

  • Interrupt 요청 발생
  1. HW/SW에 의해 Interrupt 요청 발생
  2. 이들은 SRN 내 SRC 레지스터 / IR Module을 통해 관리됨.
  • 중재(Arbitration)
  1. SRN들이 ICU에 의해 중재됨
  2. ICU는 경쟁 중인 SRN들 사이에서 우선순위 따져 승자 결정
  3. 최종 중재 결과는 LWSR에 기록하고, ISP에게 전달
  • ISR call
  1. Interrupt 처리를 위해 승자 SRN의 ISR로 점프.
  2. 점프 주소는 IVT에 있음. (BIV통해 계산하고 점프하는거임)
  • 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가 가르키게 될 초기 지점이다.

  • IfxCpu.h - IfxCpu_enableInterrupts 함수
 IFX_INLINE void IfxCpu_enableInterrupts(void)
 {
 __enable(); // Interrupt 활성(Atomic 연산)
 //__disable(); Interrupt 비활성 함수
 }

위 함수는 컴파일러 내장 함수로 제공되는 함수들

  • IFX_INTERRUPT(ISR, vectabNum, prio)

CompilerTasking.h file에 Define되어 있음
Interrupt handler 즉, ISR를 등록하는 함수


  • Module별 SRC Register 구성

SRC는 SRPN(우선순위) / TOS(실행될 곳) / SRE(SR Enable)의 주요 설정을 가짐.

모듈별 SRC는 : SRC_모듈명

ex) ASCLIN Module관련 Interrupt를 구성하고자 하는 경우에는?
SRC_ASCLINxTX/ASCLINxRX를 이용하면 된다.

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

iLLD를 확인해도 배열 형태로 12개를 나타내고 있다


  • BSW/Driver/isr_priority.h
…중략…

 /* Definition of the interrupt priorities */
 #define ISR_PRIORITY_ASCLIN0_RX 18
 #define ISR_PRIORITY_ASCLIN0_TX 19
 
 …중략…
  • BSW/Driver/asclin.c
…중략…

 /* 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);
}
 
 …중략…
  • SRC 노드설정(BSW/Driver/asclin.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! 출력

  • main.c
#include "main.h"
 int main(void)
 {
   SYSTEM_Init();
   /* LED1초기상태: off */
   GPIO_SetLed(1, 0);
   while (1);
   return 0;
 }
  • asclin.c
 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

IMAGE ALT TEXT HERE


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

IMAGE ALT TEXT HERE


ERU

ASCLIN이나 MCMCAN 같은건 "내부" I/O다.

ERU는 "외부" I/O로 Pin(연결된 부품 등)으로 Interrupt를 걸 때 씀.

  • ERU(External Request Unit)
  1. 다목적 Event/Pattern 감지 장치

  2. 다양한 Input에서 선택 가능한 Trigger Event를 기반으로 Interrupt 생성

  3. 독립적인 8개의 채널 :
    Trigger/Gate 기능의 Input 선택/조건 설정

  4. Event 분배 :
    Connecting Matrix로 Input channel x의 event를 Output channel y의 반응으로 연결 정의

  5. 독립적인 8개의 Output Channel :
    Event 조합/ Event 발생시 효과 정의, System으로 분배(Interrupt 생성)을 위한 Chanel

예를 들면, Falling/Rising Edge를 감지하여 Input으로 받아들일 수가 있다. 사실 내부 I/O랑 다를건 없음. 구조가 좀 상이할 뿐

Output 뒤에는 IR이 존재한다. 즉 얘내도 SRN인거다. SRC를 설정할 수 있고, ICU로 보내 ISP에서 처리를 진행한다.

세부 구조를 다시 뜯어보자.


  • 전체적인 과정
  1. Input Channel당 ERS를 사용해 4개의 사용 가능한 Input중 1개 선택 ERS는 Channel당 8개가 존재함.

  2. Input Channel당 ETL(Event Trigger Logic)을 통해 Trigger Event Signal로 변환

  3. Matrix를 통해 생성된 Event Signal과 상태 Flag를 Output Channel로 분배

  4. Output Channel당 1개의 OGU는 Input Channel에서 사용 가능한 Trigger Event와 상태 정보를 결합해 System에 최종 결과 분배.


  • ERS (External Request Selection Unit, 외부 요청 선택 장치)
  1. 외부 요청 신호 중 1개를 선택해 ERU Module로 내로 전달하는 장치
  2. 1개의 ERS에는 4개의 Request Input Signal이 있으며,
    1 Input Channel당 이를 2개 두고 있음.
    총 8개의 ERS를 갖고 있다 (ERS 0~7)

ex) Input Signal 종류 :
Port / CCU / STM / GPT12 등


  • ETL (External Trigger Logic Unit, 외부 요청 트리거 설정)
  1. 외부 요청 Signal에 대해 Trigger(Rising/Falling) 설정

  2. Trigger Pulse를 생성함

  3. 4개의 ETL 장치의 각 쌍에는 EICRy와 연결되어 ETL의 모든 옵션 제어


  • Connet Matrix

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


  • Output Gating Unit (OGU)

Input Channel로 제공 된 Trigger Event와 상태 Flag를 조합해
System에 결과를 분배

  1. Trigger 조합 :
    OGUy로 유도된 활성화된 Input Channel의 All Trigger Signal(TRxy)와
    Pattern 변경 Event(활성화 된 경우)가 OR로 결합됨

  2. Pattern 감지 :
    Input Channel의 EIFR.INTFx 상태 Flag를 활성화해 Pattern 감지
    All 활성화된 상태 Flag가 설정된 경우 Pattern 일치가 감지 됨


SW2는 P2.1과 연결
P2.1은 ERU Module의 2번째 ERS의 2번째 신호로 연결됨(Channel?)
ERS2의 2번째 입력 신호로 연결됨

  • EICRi(i=0~3) : External Input Channel Register

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을 선택

  1. EXIS0[6:4] : External Input Selection 0
    (0와 1은 MUX중 첫번째/두번째를 의미함)

우리는 EICR1.EXIS0의 두번째 Pin을 사용해야 하므로, 001을 사용
즉, EXIS0 = 1이므로, ERS2의 입력 중 1번(두번째)이 선택됨.

  1. FEN0[8] : Falling Edge 활성화

  2. REN0[9] : Rising Edge 활성화

  3. EIEN0[11] : Enable Trigger 쓰려면 당연히 1로

만약 EICR1(i).B.EIEN0=1 이라면,
i=1,로 2i(2번째 Input Channel)에 대한 Trigger Event 생성 활성화

  1. INP1[30:28] : Trigger Event의 Output Channel 결정
    EICR1.B.INP0 = 0(i=1)라면, ETL2(Input Channel 2, 2i)에서 발생하는 Event는 OGU0(Output Channel 0)으로 전달됨.

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된다.

  1. IGCRj(j=0~3) : Interrupt Gating Control Register

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은 고려되지 않음.


  • eru.c
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

IMAGE ALT TEXT HERE

Switch를 누르면 외부 Interrupt(Port)한테 걸려서 ISR을 처리함.

https://youtube.com/shorts/cJbeRkJKp7w

IMAGE ALT TEXT HERE

별 건 없고, 그냥 Toggle 하도록 바꿨음.


  • Interrupt 경쟁 예제
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됨.

영상을 못 찍어서 이건 영상이 없다 쩝.


  • 추가 OGU 변경

OGU 변경

  • OGU 2
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까진 내보낼 수 있음이 확인되었음.

  • OGU 1
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");
}
  • OGU 3
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");
}
  • OGU 0
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]로 선언되어 있는것

profile
학습

0개의 댓글