승코딩당당당

[TC275] Multi-interrupt로 LED 제어 (Blue/Red) 본문

개발/임베디드

[TC275] Multi-interrupt로 LED 제어 (Blue/Red)

승코딩당당당 2026. 2. 20. 15:36

 

이번 실습에서는 Infineon AURIX TC275와 Easy Module Shield v1을 이용해 하나의 ERU 모듈에서 두 개의 외부 인터럽트를 동시에 처리하는 Multi-interrupt 구성을 구현한다. P02.0과 P02.1에 연결된 두 개의 버튼을 각각 ERS2, ERS3로 매핑하고, 이를 통해 Blue LED(P10.2)와 Red LED(P10.1)의 상태를 독립적으로 토글하도록 설계했다.

ERS2 → ERU0 → ISR0Blue LED 토글, ERS3 → ERU1 → ISR1 Red LED 토글을 담당하며, 두 인터럽트 소스가 서로 간섭하지 않도록 SCU_EICR, SCU_IGCR, SRC_SCU_SCU_ERU0/1 레지스터를 각각 분리해서 설정하는 것이 핵심이다.

 

특히 ERS3 경로에서는 OGU(Output Gating Unit)를 초기화한 후 값을 1로 세팅해 OGU1을 사용하도록 만들어야 ERS2에서 사용하는 OGU0와 겹치지 않고, 두 인터럽트가 독립적으로 동작한다는 점을 코드와 함께 확인할 수 있다.

이렇게 하지 않으면 두 개의 스위치 모두 Blue LED만 동작한다...

이를 통해 AURIX의 ERU 구조, 다중 인터럽트 라우팅, OGU 선택 방식까지 한 번에 정리하면서 실전적인 외부 인터럽트 설계 감각을 익히는 것을 목표로 한다.

 

아래 datasheet p.614~ 를 확인하면서 코드를 작성한다.

https://www.farnell.com/datasheets/3109944.pdf

 

 

 

+ 아래 인터럽트로 LED 제어하는 방법을 먼저 익힌 후 공부하면 이해가 더 쉽다.

https://xeungcoding.tistory.com/90

 

[TC275] ERU 인터럽트로 LED 제어 (On/Off, Toggle)

이번 포스팅에서는 Infineon AURIX TC275와 Easy Module Shield v1 환경에서 버튼 입력을 이용해 파란색 LED를 제어하는 세 가지 방법을 정리한다.먼저 가장 기본적으로, 버튼을 누르면 Blue LED가 켜지도록 GPIO

xeungcoding.tistory.com

 


 

코드

/**********************************************************************************************************************
 * \file Cpu0_Main.c
 * \copyright Copyright (C) Infineon Technologies AG 2019
 * 
 * Use of this file is subject to the terms of use agreed between (i) you or the company in which ordinary course of 
 * business you are acting and (ii) Infineon Technologies AG or its licensees. If and as long as no such terms of use
 * are agreed, use of this file is subject to following:
 * 
 * Boost Software License - Version 1.0 - August 17th, 2003
 * 
 * Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and 
 * accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute,
 * and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the
 * Software is furnished to do so, all subject to the following:
 * 
 * The copyright notices in the Software and this entire statement, including the above license grant, this restriction
 * and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all 
 * derivative works of the Software, unless such copies or derivative works are solely in the form of 
 * machine-executable object code generated by a source language processor.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 
 * COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN 
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
 * IN THE SOFTWARE.
 *********************************************************************************************************************/
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"

#define PCn_2_IDX 19
#define P2_IDX 2
#define PCn_1_IDX 11  // P02.1
#define P1_IDX 1
#define PCn_0_IDX 3   // P02.0
#define P0_IDX 0

#define EXIS0_IDX 4
#define FEN0_IDX 8
#define REN0_IDX 9
#define EIEN0_IDX 11
#define INP0_IDX 12
#define IGP0_IDX 14

#define EXIS1_IDX 20
#define FEN1_IDX  24
#define EIEN1_IDX 27
#define INP1_IDX  28
#define IGP1_IDX  30

#define SRE_IDX 10
#define TOS_IDX 11

void initERU(void);

IFX_INTERRUPT(ISR0, 0, 0x10);
void ISR0 (void)
{
    // P10_OUT.U = 0x1 << P2_IDX;

    P10_OMR.U = (1 << (P2_IDX + 16)) | (1 << P2_IDX);
}

IFX_INTERRUPT(ISR1, 0, 0x20);
void ISR1 (void)
{
    P10_OMR.U = (1 << (P1_IDX + 16)) | (1 << P1_IDX);
}

IfxCpu_syncEvent cpuSyncEvent = 0;

void initLED(void);
void initGPIO(void);

void core0_main(void)
{
    IfxCpu_enableInterrupts();

    /* !!WATCHDOG0 AND SAFETY WATCHDOG ARE DISABLED HERE!!
     * Enable the watchdogs and service them periodically if it is required
     */
    IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
    IfxScuWdt_disableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());

    /* Wait for CPU sync event */
    IfxCpu_emitEvent(&cpuSyncEvent);
    IfxCpu_waitEvent(&cpuSyncEvent, 1);

    initGPIO();
    initERU();

    while(1)
    {

    }
}

void initLED(void){
    P10_IOCR0.U &= ~(0x1F << PCn_2_IDX);
    P10_IOCR0.U |= 0x10 << PCn_2_IDX;
}

void initGPIO(void) {
    // PC2.0 button
    P02_IOCR0.U &= ~(0x1F << PCn_0_IDX);
    P02_IOCR0.U |=  (0x02 << PCn_0_IDX);

    // PC2.1 button
    P02_IOCR0.U &= ~(0x1F << PCn_1_IDX);
    P02_IOCR0.U |= 0x02 << PCn_1_IDX;

    // PC10.2 blue led
    P10_IOCR0.U &= ~(0x1F << PCn_2_IDX);
    P10_IOCR0.U |= 0x10 << PCn_2_IDX;

    // PC10.1 red led
    P10_IOCR0.U &= ~(0x1F << PCn_1_IDX);
    P10_IOCR0.U |= 0x10 << PCn_1_IDX;
}

void initERU() {
    //**********ERS2 -> ERU0 -> ISR0 (Blue LED)**********
    SCU_EICR1.U &= ~(0x7 << EXIS0_IDX);
    SCU_EICR1.U |= 0x1 << EXIS0_IDX;

    // SCU_EICR1.U &= ~(1 << FEN0_IDX);   // Falling edge 끄고
    // SCU_EICR1.U |=  (1 << REN0_IDX);   // Rising edge 켜기
    SCU_EICR1.U |= 1 << FEN0_IDX;
    SCU_EICR1.U |= 1 << EIEN0_IDX;

    SCU_EICR1.U &= ~(0x7 << INP0_IDX);

    SCU_IGCR0.U &= ~(0x4 << INP0_IDX);
    SCU_IGCR0.U |= 0x1 << IGP0_IDX;

    // SRC (Service Request Control) Setting
    SRC_SCU_SCU_ERU0.U &= ~0xFF;
    SRC_SCU_SCU_ERU0.U |= 0x10;

    SRC_SCU_SCU_ERU0.U |= 1 << SRE_IDX;
    SRC_SCU_SCU_ERU0.U &= ~(0x3 << TOS_IDX);

    //**********ERS3 -> ERU1 -> ISR1 (Red LED)**********
    SCU_EICR1.U &= ~(0x7 << EXIS1_IDX);
    SCU_EICR1.U |=  (0x2 << EXIS1_IDX);

    SCU_EICR1.U |= 1 << FEN1_IDX;
    SCU_EICR1.U |= 1 << EIEN1_IDX;

    SCU_EICR1.U &= ~(0x7 << INP1_IDX);  // INP1 = 0 → OGU1
    SCU_EICR1.U |= 0x1 << INP1_IDX;

    SCU_IGCR0.U &= ~(0x3 << IGP1_IDX);
    SCU_IGCR0.U |=  0x1 << IGP1_IDX;

    SRC_SCU_SCU_ERU1.U &= ~0xFF;
    SRC_SCU_SCU_ERU1.U |=  0x20;        // PRI = 0x20

    SRC_SCU_SCU_ERU1.U |=  1 << SRE_IDX;
    SRC_SCU_SCU_ERU1.U &= ~(0x3 << TOS_IDX);
}

 

1. 인터럽트 서비스 루틴 (ISR0, ISR1)

IFX_INTERRUPT(ISR0, 0, 0x10);
void ISR0(void) {
    P10_OMR.U = (1 << (P2_IDX + 16)) | (1 << P2_IDX);
}

IFX_INTERRUPT(ISR1, 0, 0x20);
void ISR1(void) {
    P10_OMR.U = (1 << (P1_IDX + 16)) | (1 << P1_IDX);
}

 

  • IFX_INTERRUPT 매크로로 ISR0는 우선순위 0x10, ISR1은 0x20으로 등록.
  • P10_OMR은 출력 토글용 레지스터:
    • 하위 비트(PSx): set
    • 상위 비트(PCLx): clear
  • 같은 핀에 대해 PSx와 PCLx를 동시에 1로 쓰면 해당 비트가 토글된다.
    • ISR0: P10.2 비트를 토글 → 파란 LED On/Off
    • ISR1: P10.1 비트를 토글 → 빨간 LED On/Off

 

2. ERU 설정 (initERU)

// ERS2 → ERU0 → ISR0 (Blue LED)
SCU_EICR1 ... EXIS0, FEN0, EIEN0, INP0 설정
SCU_IGCR0 ... IGP0 설정
SRC_SCU_SCU_ERU0 ... 우선순위 0x10, enable, CPU0

// ERS3 → ERU1 → ISR1 (Red LED)
SCU_EICR1 ... EXIS1, FEN1, EIEN1, INP1 설정
SCU_IGCR0 ... IGP1 설정
SRC_SCU_SCU_ERU1 ... 우선순위 0x20, enable, CPU0

 

 

  • EICR1(EXISx)
    • 스위치가 연결된 핀(P02.0, P02.1)을 각각 ERS2, ERS3 입력으로 선택한다.
  • FENx / EIENx
    • 버튼을 누를 때 발생하는 엣지(falling edge) 에서 이벤트 발생 + 인터럽트 활성화.
  • INPx / IGPx
    • ERU 입력(ERS2, ERS3)을 출력 게이트(OGU)로 연결해서 서비스 요청을 발생시키는 경로를 만든다.
  • SRC_SCU_SCU_ERUx
    • 생성된 서비스 요청을 CPU0 인터럽트 소스로 등록하고,
    • 각 채널을 ISR0(0x10), ISR1(0x20)과 매핑한다.

 


 

결과

resume 후 스위치를 누르기 전

 

SW2를 눌렀을 때: Blue LED 동작
SW1를 눌렀을 때: RED LED 동작
SW2를 눌렀을 때: Blue LED 동작 (Toggle)