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

[Infineon] 06. Aurix (TC23x) 인터럽트 Interrupt 이해하기 (2)

by 방구석 임베디드 2021. 5. 19.
반응형

혹시, 코드가 필요하신 분들은 아래 댓글을 달아주세요.

개인적으로 전달해 드리도록 하겠습니다.

ILLD 플랫폼과 연동시킨 플랫폼이고, CMD로 Build 할수 있도록 직접 Makefile을 만든것이여서 

이것을 이용하면 좀더 쉽게 개발할수 있습니다.

 

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

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

 

우선 TC23x 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에게 알려달라는 의미입니다.

TC27x 는 Core가 여려게여서 저러한 특정 설정이 필요합니다.

TC23x는 Core가 1개여서 core0만 씀니다.

 

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

 

그렇다면 STM 입장에서 Counter가 올라간다는 것은 무슨의미일까요?

STM은 어떠한 Clock을 받습니다. 그리고 그것을 Count합니다.

그렇다면 저 Clock은 몇 Hz 일까요?

이러한 부분을 알기위해서는 Clock 설정 부분이 필요합니다.

이것은 나중에 다룰게요

우선 100MHz라고 보시면 됩니다.

 

따라서 아래 Counter에 도달하면 인터럽트를 날리라는 의미는 1ms가 되면 인터럽트를 날리라는 의미가 됩니다.

#define STM_TIME_1MS                100000u

100000 / 100000000 = 1/1000 --> 1ms가 됩니다.

 

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

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

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

 

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

하지만, 우선 ILLD를 써서 익힌다음, 직접접근하여 입맛대로 초기화하면 더 빠르게 개발할수 있습니다.

 

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

이제 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);

    /*Stm Collback Function*/
    DrvStm0CallbackFnc();
}

/*---------------------Callback Function--------------------------*/
void DrvRegStm0CallbackFnc(void (*pDrvRegCallbackFnc)(void))
{
    DrvStm0CallbackFnc = pDrvRegCallbackFnc;
}

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

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

따라서 Table의 위치에서 40번째 위치한 함수로 jump해라!  라는 의미가 되겠습니다.

 

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

STM_Int0Handler 함수가 보이는 군요!

 

저함수에서 다시 Flag를 다시 내려주고, 다시 1ms뒤에 인터럽트를 실행시켜 달라고 설정하고

Callback 함수를 부릅니다.

우선 Callback은 잊어버리시고요

 

아래와 같이 코드를 수정하겠습니다.

void STM_Int0Handler(void)
{
	static unsigned long Cnt = 0;
	
    IfxStm_clearCompareFlag(gstnuStmInfo.stmSfr, gstnuStmInfo.stmConfig.comparator);
    IfxStm_increaseCompare(gstnuStmInfo.stmSfr, gstnuStmInfo.stmConfig.comparator, STM_TIME_1MS);

	Cnt++;
}

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

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

이제 코드를 컴파일하고 

1ms 마다 ISR 함수에 들어오는지를 확인해 보도록 하겠습니다.

아래와 같이 ISR 함수에 들어왔고, Cnt가 올라가는 것을 확인할수 있습니다.

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

위와 같이 main함수 안에 Scheduler 함수가 동작하고 있는데

갑자기 Interrupt가 발생하여

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

 

나중에 인터럽트 Vetor Table의 위치,

그리고 어떻게 ISR함수로 접근하는지에 대해서 추후 포스팅 할게요!

 

혹시, 코드가 필요하신 분들은 아래 댓글을 달아주세요.

개인적으로 전달해 드리도록 하겠습니다.

ILLD 플랫폼과 연동시킨 플랫폼이고, CMD로 Build 할수 있도록 직접 Makefile을 만든것이여서 

이것을 이용하면 좀더 쉽게 개발할수 있습니다.

반응형

댓글