Notice
Recent Posts
Recent Comments
Link
승코딩당당당
[TC275] 인터럽트로 LED Blinking과 멈추기 본문
AURIX TC27x 보드에서 ERU(External Request Unit) 기반 인터럽트를 이용해 LED의 blinking을 제어하는 프로그램이다. 기본 동작은 while 루프에서 파란 LED(P10.2)와 빨간 LED(P10.1)를 P10_OMR 레지스터로 지속적으로 토글하여 깜빡이게 하고, 버튼(P02.0, P02.1)이 눌리면 인터럽트가 발생해 blinking을 멈추거나 다시 시작하도록 구성하였다.
인터럽트 서비스 루틴(ISR)에서는 LED를 직접 제어하지 않고, 전역 변수 g_blinkOn을 토글하여 현재 blinking 상태만 변경한다. 메인 루프는 이 플래그 값을 확인해 1일 때만 LED를 토글하고, 0이면 아무 동작도 하지 않는다. 이를 통해 인터럽트는 상태 제어, 메인은 실제 동작 수행이라는 역할 분리가 이루어진다.
ERU 설정에서는 각 스위치를 서로 다른 ERS 채널에 연결하고, Falling edge에서 이벤트가 발생하도록 설정한 뒤, 해당 이벤트를 CPU0 인터럽트로 라우팅하였다. 이 코드는 OMR 레지스터를 이용한 안전한 GPIO 토글과 인터럽트 기반 이벤트 처리 구조를 함께 학습할 수 있는 예제이다.
코드
/**********************************************************************************************************************
* \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
volatile uint8 g_blinkOn = 1; // LED blink on/off state flag
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);
g_blinkOn ^= 1;
}
IFX_INTERRUPT(ISR1, 0, 0x20);
void ISR1 (void)
{
// P10_OMR.U = (1 << (P1_IDX + 16)) | (1 << P1_IDX);
g_blinkOn ^= 1;
}
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)
{
if (g_blinkOn)
{
// 파란 LED(P10.2), 빨간 LED(P10.1) 동시에 토글
P10_OMR.U =
(1 << (P2_IDX + 16)) | (1 << P2_IDX) | // P10.2 토글
(1 << (P1_IDX + 16)) | (1 << P1_IDX); // P10.1 토글
for (int i = 0; i < 10000000; i++) // delay
{
__nop();
}
}
}
}
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. 전역 플래그 g_blinkOn 추가
volatile uint8 g_blinkOn = 1; // LED blink on/off state flag
- 전역 변수 g_blinkOn을 추가해서 LED를 깜빡일지 말지를 결정하는 상태 플래그로 사용
- volatile을 붙인 이유는, 이 변수가 인터럽트(ISR)와 메인 루프에서 동시에 접근되기 때문
- 컴파일러가 최적화 과정에서 레지스터에만 값 캐싱해두고 메모리에서 다시 안 읽어오는 걸 막기 위함
- volatile이 없으면 ISR에서 값을 바꿔도 메인 루프가 그 변화를 못 보고 계속 이전 값만 읽는 상황이 생길 수 있음.
2. ISR 동작 방식 변경
IFX_INTERRUPT(ISR0, 0, 0x10);
void ISR0 (void)
{
// 예전: P10_OMR로 Blue LED 토글
// P10_OMR.U = (1 << (P2_IDX + 16)) | (1 << P2_IDX);
g_blinkOn ^= 1;
}
IFX_INTERRUPT(ISR1, 0, 0x20);
void ISR1 (void)
{
// 예전: P10_OMR로 Red LED 토글
// P10_OMR.U = (1 << (P1_IDX + 16)) | (1 << P1_IDX);
g_blinkOn ^= 1;
}
- 두 ISR 모두 공통적으로 g_blinkOn ^= 1;만 수행.
- ^= 1은 0 ↔ 1 토글 연산.
- 즉, 어느 버튼을 눌러도 “깜빡임 상태(on/off)를 전환”하는 트리거 역할만 수행하고,
실제 LED 제어는 메인 루프에서 처리하게끔 책임을 분리했음
3. 메인 루프에서 LED 토글 & 딜레이 담당
while(1)
{
if (g_blinkOn)
{
// 파란 LED(P10.2), 빨간 LED(P10.1) 동시에 토글
P10_OMR.U =
(1 << (P2_IDX + 16)) | (1 << P2_IDX) | // P10.2 토글
(1 << (P1_IDX + 16)) | (1 << P1_IDX); // P10.1 토글
for (int i = 0; i < 10000000; i++) // delay
{
__nop();
}
}
}
- 메인 루프에서 g_blinkOn이 1일 때만
- Blue / Red LED를 동시에 토글하고
- NOP 루프를 이용해서 소프트웨어 딜레이를 줌 → 사람 눈에 깜빡이는 효과
- g_blinkOn == 0이면
- LED는 마지막 상태를 유지하고, 더 이상 토글/딜레이를 수행하지 않음 → 깜빡임 정지
결과
언제 스위치를 누르냐에 따라 LED가 켜진 상태에서 멈출 수도 있고, 꺼진 상태에서 멈출 수도 있다.
'개발 > 임베디드' 카테고리의 다른 글
| [TC275] 4자리 FND 카운터 구현하기 (스위치 제어) (0) | 2026.02.23 |
|---|---|
| [TC275] STM 인터럽트 기반 신호등 구현하기 (1) | 2026.02.23 |
| [TC275] Multi-interrupt로 LED 제어 (Blue/Red) (0) | 2026.02.20 |
| [TC275] ERU 인터럽트로 LED 제어 (On/Off, Toggle) (0) | 2026.02.20 |
| [TC275] GPIO 입력으로 LED 제어 + OMR 레지스터 (2) | 2026.02.19 |
