본문 바로가기
Embedded SW/[Infineon] TC275 Lite Project

인피니언 MCU 인터럽트/Interrupt 설정 (TC275 동작 확인)

by 방구석 임베디드 2021. 11. 17.
반응형

안녕하세요.

오늘은 인피니언 MCU의 인터럽트를 이해해 보는 시간을 가져보도록 하겠습니다.

 

참고로 이 글은 개발의 전체적인 내용을 연재하고 있는 글이 중에 하나입니다.

그래서, 앞에쓴 글을 보시면 더욱 도움이 되실것 같습니다.

아래 글을 링크 걸어둘께요. 필요하신 분은 한번 읽어 보세요.

(물론 이 글만 보셔도 크게 문제는 없습니다.)

 

1) 임베디드 SW, MCU에 대한 정리 (feat. 임베디드 SW 비전)

https://embeddedchallenge.tistory.com/210

2) MCU 개발 장비 구매 방법 정리 (인피니언 MCU TC275 Lite)

https://embeddedchallenge.tistory.com/211

3) 임베디드 SW 개발 환경 세팅 방법 정리 (소스코드 편집기, 컴파일러, 디버거 환경 설정 방법)

https://embeddedchallenge.tistory.com/212

4) 인피니언 IDE Tool 사용방법 정리 (프로젝트 생성 및 다운로드 수행)

https://embeddedchallenge.tistory.com/219

5) 인피니언 MCU LED Blinking (TC275 GPIO 설정)

https://embeddedchallenge.tistory.com/225

6) 인피니언 MCU Clock, 오실레이터 에 대한 이해 (TC275 보드에서 확인)

https://embeddedchallenge.tistory.com/226

7) 인피니언 MCU PLL 설정 및 주변기기 Clock 설정 (TC275)

https://embeddedchallenge.tistory.com/227

 

Embedded SW를 공부하면서, 꼭 알아야할 개념이 폴링(Polling)과 인터럽트(Interrupt)입니다.

우선 폴링과 인터럽트의 대한 내용을 정리하도록 하겠습니다.

 

1. 폴링과 인터럽트는 무엇을 의미하는 것일까?

 

폴링과 인터럽트는 CPU와 입출력 장치의 통신 방식을 의미합니다.

 

1) 인터럽트 : CPU가 프로그램을 실행하고 있을 때, 입출력 하드웨어 장치에서 처리가 필요할 경우

CPU에게 전기신호로 알려주어, 이것을 처리할수 있도록 하는 통신방법입니다.

 

2) 폴링 : CPU가 주기적으로 하드웨어 장치를 감시하여 입출력 하드웨어 장치에서 처리가 필요할 경우,

이를 처리하는 통신방법 입니다.

 

즉, 폴링은 CPU가 주기적으로 감시하여 상황이 발생하면 일을 처리하는 개념이라면

인터럽트는 상대쪽에서 CPU에게 일을 처리해 달라고 요청하는 것이라는 것을 알 수 있습니다.

 

한번 예를 들어 보도록 하겠습니다.

 

CPU는 저 다리에 연결돤 전압을 계속 확인해야 하는 상황이라고 가정해 보겠습니다.

 

저 신호가 다리중 빨강색으로 칠한 부분에 5V 전입이 들어오면,

저 다리와 연결된 GPIO 모듈은 5V를 1로 인식하여 특정 레지스터(메모리)에 1이라는 정보를 담아 놓습니다.

CPU는 포트 레지스터안에 정보를 확인하여 1일 경우 에어벡을 터뜨리고,

0일경우 에어백이 터지지 않게 해야 합니다.

 

에어백이 터져야 한다고한다면

CPU는 지속적으로 저 다리의 해당하는 포트의 레지스터를 계속 확인해야 합니다.

그렇다면 아래와 같이 코드가 구현될 것입니다.

계속 신경을 써서 저 상태를 채크해야 합니다.

그리고 5V전압이 들어와서 pin_state가 1이 되면

airbag이 동작해야 할 것입니다.

에어벡이 조건이 되면 터뜨려야 하기 때문에

CPU는 지속적, 반복적으로 저 코드를 수행할수 밖에 없습니다.

그러고 보니 쓸데없는 CPU 연산 수행이 계속 됩니다.

 

그런데 아래와 같은 시스템으로 동작을 하면 어떨까?

CPU는 계속확인하지 않고 다른일을 합니다.

그런데 저 핀에 5V 전압이 들어옵니다.

그것을 Interrupt Router라는 모듈로 전압이 들어옵니다.

이크 큰일 났구나 

Iterrupt Router는 전기신호를 주어서 CPU에게 이 상황을 알려줍니다. 

 

그러면 CPU는 main 함수에서 하던 동작을 멈추고 (ex, 카운터를 증가시키고 있음)

아래와 같이 약속된 ISR_Temp 함수를 동작시킵니다.

ISR_Temp에서는 바로 에어백을 터뜨립니다.

그리고 그것을 끝내고 다시 main함수로 돌아와서 계속 동작을 합니다. (다시 카운터를 증가시킴니다.)

이것이 인터럽트 방식입니다.

 

CPU는 에어백을 터뜨리기 위해 해당 포트를 계속 감사히자 않아도 됩니다.

만일 계속 감시해야 하고,

에어백처럼 중요한 신호가 여러개라면 

CPU는 감시하는 일에만 많은 일을 수행해야 합니다.

 

그렇기 때문에 인터럽트를 사용하면 쓸때없는 CPU연산을 줄일수 있고

오히려 즉각적으로 입력신호 처리를 수행할 수 있습니다.

 

그렇다면 지금부터, 인피니언 MCU의 인터럽트 직접 설계해 보도록 하겠습니다.

 

 

2. 인피니언 System Timer Module을 이용한 인터럽트 설계

인터럽트는 내부 입출력장치에 대한 처리 요청을 CPU 전기신호로 알려줍니다.

또한 MCU에 들어에는 주변기기도 인터럽트라우터를 통하여 CPU에게 처리를 요청을 할수 있습니다.

 

이번 예제는 MCU안에 들어있는 STM(System Timer Module)을 이용하여

1ms 마다 인터럽트를 발생시키는 예제를 수행해 보도록 하겠습니다.

 

STM이란 MCU안에 들어있는 주변기기 입니다.

우리가 앞서 이야기한 오실레이터 Clock 20MHz을 100MHz의 Spb Clock으로 만들고

이것을 STM에 전달받게 됩니다.

STM은 그 Clock을 계속 Count하는 모듈입니다.

 

즉 1초에 100 000 000 번의 수가 올라갑니다.

만일 1000번 되었을때 마다 인터럽트를 발생시켜 달라고 설정을 한다면

1ms마다 STM은 인터럽트 라우터에게 이를 알릴것이고, 

인터럽트 라우터는 CPU에게 전기신호를 줄것입니다.

 

그 전기신호의 의미는

잠시 너가 하는 일을 멈추고, System Timer Module ISR(Interrupt Service Routine)을 실행 시켜줘! 라는 의미입니다

 

ISR 함수는 아래와 같이 만들어 보았습니다.

void ISR_Timer(void)
{
	static unsigned long Cnt = 0u;
	Cnt ++;   
}

 

결국 위의 Main의 무한루프 함수가 멈추고, 위의 ISR 함수가 실행이 되고 다시 Main 함수로 돌아오게 됩니다.

이때 ISR함수로 점프하기 전에

현재 자신의 레지스터 정보, 그리고 다시 돌아올 주소들을 Stack에 저장합니다.

 

커다른 인터럽트 흐름에 대해서 말씀드렸습니다.

그러면 다음 글에서, 이제 System Timer Module을 이용하여 1ms 마다 ISR이 발생하도록 설계를 해보고 확인을 해보도록 하겠습니다.

 

그렇다면 지금부터 System Timer Module을 이용하여

1ms 마다 주기적으로 Interrupt를 발생시켜 보도록 하겠습니다.

 

우선 Reference Manual을 보시면 여기 STM을 누르시면

기본적이 설명이 나옵니다.

쭉 읽어 보시면 되겠습니다.

결국 Timer이다.

 

바로 초기화 코드를 살펴 보도록 하겠습니다.

static void DrvStm0Init(void)
{
    IfxStm_enableOcdsSuspend(&MODULE_STM0);

    gstnuStmInfo.stmSfr = &MODULE_STM0;
    IfxStm_initCompareConfig(&gstnuStmInfo.stmConfig);

    gstnuStmInfo.stmConfig.triggerPriority = ISR_PRIORITY_STM_INT0;
    gstnuStmInfo.stmConfig.typeOfService   = IfxSrc_Tos_cpu0;
    gstnuStmInfo.stmConfig.ticks           = STM_TIME_1MS;            /*1ms*/

    IfxStm_initCompare(gstnuStmInfo.stmSfr, &gstnuStmInfo.stmConfig);
}

 

제일 먼저, IfStm_enableOcdsSuspend 함수를 통하여 Debug로 멈추면,

STM이 Counter 올라가는 것을 멈추도록 설정을 합니다.

 

그리고, 인터럽트를 발생시키기 위한 설정값들을 넣습니다.

제일먼저, 우선순위값을 넣습니다.

#define ISR_PRIORITY_STM_INT0       40 /**< \brief Define the System Timer Interrupt priority.  */

우선순위는 255까지 넣을수 있고 클수록 우선순위가 높습니다.

여러 모듈들이 인터럽트 요청을 할경우, 큰 수로 설정된 ISR이 우선 실행됩니다.

 

IfxSrc_Tos_cpu0 의 의미는 ISR이 발생하면 Core0에게 알려달라는 의미입니다.

참가로 TC275는 3개의 core를 가지고 있습니다.

현재는 core0만을 사용하고 있습니다.

 

마지막으로 100000 Counter가 되면 인터럽트를 발생시켜줘! 라는 의미입니다.
#define STM_TIME_1MS                100000u

 

1초에 100 000 000번 카운트 할수 있으니까

0.001초 (1ms)에 100 000번 카운트하겠네요.

다시말해 100 000번 카운트가 되는 시간은 1ms가 되었다는 것을 의미합니다.

이렇게 설정이 되었으면 아래의 함수를 통하여 레지스터를 초기화 합니다.

저는 ILLD에서 제공하는 API를 이용하여 STM 모듈을 초기화 하고 있습니다.

IfxStm_initCompare(gstnuStmInfo.stmSfr, &gstnuStmInfo.stmConfig);

 

물론 저 ILLD 없이도 레지스터 직접 접근하여 초기화가 가능합니다.

하지만, 우선 ILLD를 사용하여 STM 주변기기의 레지스터를 초기화 해보도록 하겠습니다.

 

우선 이렇게 초기화를 하였고

이제 STM에서 인터럽트가 발생하였을 경우, 실행되는 ISR 함수를 만들어 보도록 할게요!

/*---------------------Interrupt Define--------------------------*/
IFX_INTERRUPT(STM_Int0Handler, 0, ISR_PRIORITY_STM_INT0);

/*---------------------Interrupt Service Routine--------------------------*/
void STM_Int0Handler(void)
{
    IfxStm_clearCompareFlag(gstnuStmInfo.stmSfr, gstnuStmInfo.stmConfig.comparator);
    IfxStm_increaseCompare(gstnuStmInfo.stmSfr, gstnuStmInfo.stmConfig.comparator, STM_TIME_1MS);

    ulnuStmCnt++;
}

먼저 IFX_INTERRUPT를 통하여 ISR을 등록해야 합니다.

 

STM은 1ms가 되면 ISR을 발생시키고 그 우선순위는 40이다.

따라서 Table의 위치에서 40번째 위치한 함수로 jump해라! 

라는 의미가 되겠습니다.

 

그리고 그 jump한 곳은 바로 STM ISR 함수가 위치한 곳입니다.

STM_Int0Handler 함수가 보이는 군요!

저함수에서 다시 Flag를 다시 내

려주고, 다시 1ms뒤에 인터럽트를 실행시켜 달라고 설정하고

 

1ms 마다 Cnt가 증가하는 것을 의미하고 있습니다.

 

저 ISR이 끝나면 다시 Main함수의 무한루프로 돌아가게 될것입니다.

이제 코드를 컴파일하고

아래와 같이 다운로드를 하겠습니다.

그리고 해당 변수를 꺼내고

실시간으로 측정하도록 변경하고

1ms마다 ulnuStmCnt값이 증가되는지를 확인해 보도록 하겠습니다.

1000이 되면 1초입니다.

핸드폰 스탑워치를 사용해서 한번 시간을 측정해 보세요!! 

이제 Call Stack 구조를 살펴 보도록 하겠습니다.

위와 같이 main함수의 while 구문에 있다가

갑자기 Interrupt가 발생하여

STM_Int0Handler 함수가 불리고 있는 것을 확인할수 있습니다.

 

일이 끝나면 다시 main 함수로 이동을 하게 될 것입니다.

 

조금더 인터트가 어떻게 어떠한 원리로 동작이 되는지를 정리하면 좋을것 같습니다.

Vetor Table을 통해 어떠한 원리로 해당 ISR로 점프하는지를 추후에 정리하도록 하겠습니다.

 

금일 포스팅은 이것으로 마치도록 하겠습니다.

감사합니다.

반응형

댓글