본문 바로가기
IVS/마이크로프로세서

Interrupt

by 코곰_ 2025. 1. 20.

Interrupt

goal: Push switch를 이용하여 LED Toggle하기

Interrupt vs Polling 비교

[Interrupt]

  • 하드웨어적으로 hardware의 변화를 감지하여 외부로부터의 입력을 CPU가 알아채는 방법
  • CPU가 다른 일을 할 수 있는 상태
  • 인터럽트 발생시 해당 task를 수행 후, 다시 하던 일로 돌아옴
  • CPU가 다른 일을 할 수 있는 상태이지만, 다시 해당 task로 순서가 돌아오려면 시간차이가 발생 = Overhead
    [Polling]
  • hardware의 변화를 지속적으로 읽어들여 변화를 알아채는 방법
  • CPU가 다른 일을 하지 않고 계속 변화를 관찰하므로, 즉각적으로 상태를 알아낼 수 있다.
  • 한 cycle을 돌아야 상태 변화를 check 할 수 있다.

Interrupt의 종류

  1. Internal Interrupt
  • software 내부에서 발생
    • 하드웨어 고장
    • 실행할 수 없는 명령어
    • 명령어 실행 오류: 나누기 0
  1. External Interrupt
  • hardware에서 발생
    • 타이머 인터럽트
    • 입출력 인터럽트

Interrupt 처리 과정

  1. 인터럽트 요청
  2. 상태 저장
  3. 인터럽트 서비스 루틴으로 이동
  4. 복귀

Interrupt Enable flag

  • 상태 레지스터에 있는 제어 플래그 중 하나
  • 중앙처리장치가 인터럽트를 허용할지 제어
    • STI(Set Interrupt Flag): IE = 1, 인터럽트 요청을 인식
    • CLI(Clear Interrupt Flag): IE = 0, 인터럽트 요청을 인식하지 않음

Interrupt Service Routine(ISR)

  • 인터럽트 요청을 해결하는 프로그램

  • 인터럽트 처리 순서

    1. 프로그램 실행 중
    2. 인터럽트 요청
    • 프로그램 실행과 비동기
    1. 인터럽트 단계
    • 인터럽트 확인
    • 콘텍스트 저장
    • PC <- ISR 주소
    1. 인터럽트 서비스 루틴 실행
    2. 인터럽트 리턴
    • 콘텍스트 복구
      1. 중단된 프로그램 다시 시작
  • 인터럽트 단계 후 실행하는 프로그램

    SP <- SP - [단어 크기]     // PUSH PC, 콘텍스트 저장
    Mem[SP] <- PC
    SP <- SP - [단어 크기]     // PUSH SR
    PC <- ISR 시작 주소     // PC 갱신
  • 마지막에 인터럽트 리턴 명령어(IRET) 실행
    [인터럽트 리턴 명령어]

    SR <- Mem[SP]            // POP SR, 콘텍스트 복구
    SP <- SP + [단어 크기]
    PC <- Mem[SP]            // POP PC
    SP <- SP + [단어 크기]
    • 인터럽트 요청이 수신된 시점에 실행 중인 프로그램 부분과 관련이 없을 수 있다.
    • 따라서, 인터럽트 서비스 루틴으 ㅣ실행을 시작하기 전에 루틴 실행 중에 예상치 못한 방식으로 변경될 수 있는 프로세서 레지스터의 상태 정보와 내용을 저장해야 한다.
    • 저장된 정보는 중단된 프로그램의 실행이 재개되기 전에 복원되어야 한다.
    • 이러한 방식으로 원래 프로그램은 시간 지연을 제외하고 중단으로 인해 어떠한 영향도 받지 않고 계속 실행될 수 있다.

Context Switching

  • 인터럽트 발생시 실행하던 process의 context를 저장
  • context switching 일 때, CPU overhead 발생

Interrupt Vector Table

  • 인터럽트 발생시 처리해야 할 루틴의 주소 보관 테이블

ERU

예제
ERU_Interrupt.h

#ifndef ERU_INTERRUPT_H_
#define ERU_INTERRUPT_H_

/*********************************************************************************************************************/
/*-----------------------------------------------------Includes------------------------------------------------------*/
/*********************************************************************************************************************/
#include "Ifx_Types.h"
#include "IfxSrc.h"
#include "IfxScuEru.h"
/*********************************************************************************************************************/
/*------------------------------------------------------Macros-------------------------------------------------------*/
/*********************************************************************************************************************/
#define RED_LED                    &MODULE_P10,1            /* LED which gets toggled in Interrupt Service Routine  */
#define BLUE_LED                   &MODULE_P10,2            /* LED which gets toggled in While Routine  */
#define SW1                        &MODULE_P02, 0
#define SW2                        &MODULE_P02, 1


/*********************************************************************************************************************/
/*-------------------------------------------------Global variables--------------------------------------------------*/
/*********************************************************************************************************************/

/*********************************************************************************************************************/
/*-------------------------------------------------Data Structures---------------------------------------------------*/
/*********************************************************************************************************************/
 typedef struct
{
    IfxScu_Req_In *reqPin;                      /* External request pin                                             */
    IfxScuEru_InputChannel inputChannel;        /* Input channel EICRm depending on input pin                       */
    IfxScuEru_InputNodePointer triggerSelect;   /* Input node pointer                                               */
    IfxScuEru_OutputChannel outputChannel;      /* Output channel                                                   */
    volatile Ifx_SRC_SRCR *src;                 /* Service request register                                         */
} ERUconfig;

/*********************************************************************************************************************/
/*--------------------------------------------Private Variables/Constants--------------------------------------------*/
/*********************************************************************************************************************/

/*********************************************************************************************************************/
/*------------------------------------------------Function Prototypes------------------------------------------------*/
/*********************************************************************************************************************/
void init_gpio(void);

#endif /* ERU_INTERRUPT_H_ */

ERU_Interrupt.c

/*********************************************************************************************************************/
/*-----------------------------------------------------Includes------------------------------------------------------*/
/*********************************************************************************************************************/
#include "ERU_Interrupt.h"

/*********************************************************************************************************************/
/*------------------------------------------------------Macros-------------------------------------------------------*/
/*********************************************************************************************************************/
#define ISR_PRIORITY_SCUERU_INT0   40                       /* Define the SCU ERU interrupt priority                */
#define REQ_IN                     &IfxScu_REQ14_P02_1_IN   /* External request pin (defined @IfxScu_PinMap.c       */

/*********************************************************************************************************************/
/*-------------------------------------------------Global variables--------------------------------------------------*/
/*********************************************************************************************************************/
ERUconfig g_ERUconfig;

/*********************************************************************************************************************/
/*--------------------------------------------Private Variables/Constants--------------------------------------------*/
/*********************************************************************************************************************/
 volatile Ifx_SRC_SRCR *src;                 /* Service request register                                         */

/*********************************************************************************************************************/
/*------------------------------------------------Function Prototypes------------------------------------------------*/
/*********************************************************************************************************************/

/*********************************************************************************************************************/
/*---------------------------------------------Function Implementations----------------------------------------------*/
/*********************************************************************************************************************/
/* Interrupt definition */
IFX_INTERRUPT(SCUERU_Int0_Handler, 0, ISR_PRIORITY_SCUERU_INT0);

/* Interrupt Service Routine */
void SCUERU_Int0_Handler(void)
{
    IfxPort_setPinState(RED_LED, IfxPort_State_toggled);                        /* Toggle LED                       */
}

void init_gpio(void)
{
    /* Set GPIO 10.1 and 10.2 as Output */
        IfxPort_setPinModeOutput(RED_LED, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
        IfxPort_setPinModeOutput(BLUE_LED, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);

    /* Set GPIO 10.1 and 10.2 as Low (LED Off) */
        IfxPort_setPinLow(RED_LED);
        IfxPort_setPinLow(BLUE_LED);

      /* Set GPIO 2.0 and 2.1 as Input */
        IfxPort_setPinModeInput(SW1, IfxPort_InputMode_pullUp);
        IfxPort_setPinModeInput(SW2, IfxPort_InputMode_pullUp);

      /* initialize external request pin */
        g_ERUconfig.reqPin = REQ_IN; /* Select external request pin */
        IfxScuEru_initReqPin(g_ERUconfig.reqPin, IfxPort_InputMode_pullUp);

      /* Select which edge should trigger the interrupt */
        g_ERUconfig.inputChannel = (IfxScuEru_InputChannel) g_ERUconfig.reqPin->channelId;
        IfxScuEru_enableFallingEdgeDetection(g_ERUconfig.inputChannel);

       /* Enable generation of trigger events with the function    */
        /* Signal destination */
        g_ERUconfig.outputChannel = IfxScuEru_OutputChannel_2;                  /* OGU channel 0                    */
         /* Event from input ETL0 triggers output OGU0 (signal TRx0) */
        g_ERUconfig.triggerSelect = IfxScuEru_InputNodePointer_2;

        IfxScuEru_enableTriggerPulse(g_ERUconfig.inputChannel);

     /* Choose the output channel by selecting the Output Gating Unit (OGUz) and the trigger pulse output (TRxz) */
        IfxScuEru_connectTrigger(g_ERUconfig.inputChannel, g_ERUconfig.triggerSelect);

        /*Select the condition to generate an interrupt with the function */
        IfxScuEru_setInterruptGatingPattern(g_ERUconfig.outputChannel, IfxScuEru_InterruptGatingPattern_alwaysActive);

        /* Configure and enable the service request  */
        g_ERUconfig.src = &MODULE_SRC.SCU.SCU.ERU[(int) g_ERUconfig.outputChannel % 4];
        IfxSrc_init(g_ERUconfig.src, IfxSrc_Tos_cpu0, ISR_PRIORITY_SCUERU_INT0);
        IfxSrc_enable(g_ERUconfig.src);
}

Cpu0_Main.c

#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
#include "IfxPort.h"
#include "ERU_Interrupt.h"

IfxCpu_syncEvent g_cpuSyncEvent = 0;

void core0_main(void)
{
    IfxCpu_enableInterrupts();

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

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

    init_gpio();

    boolean swStateOld, swState = 0;

    while(1)
    {
        /* I. SW1을 한번 누를 때마다 Blue LED가 Toggle 되도록 제어 (Polling) */
        /* Polling for SW1 */
        swState = IfxPort_getPinState(SW1); // SW1 on: push되면 Low

        if((swState == 0) && (swStateOld == 1)){
            IfxPort_togglePin(BLUE_LED);
        }

        swStateOld = swState;

        /* II. SW2을 한번 누를 때마다 Red LED가 Toggle 되도록 제어 (Interrupt) */
    }
}

IfxPort_togglePin()은 port output을 toggle한다.

  • port: Pointer to the port which should be accessed.
  • pinIndex: Specifies the pin to be toggled.

IfxPort_getPinState()은 port state를 return

  • port: Pointer to the port which should be accessed.
  • pinIndex: Specifies the pin for which the state should be returned.
  • Return
    • TRUE: pin = high
    • FALSE: pin = low