본문 바로가기
임베디드 엔지니어링/TMS320F28335

DSP제어(TMS320F28335) : 1ms 주기 LED Toggle 프로그램(4) - CPU Timer 세팅

by Bennyziio 2019. 4. 10.
반응형

2019/04/09 - [임베디드 프로세서/TMS320F28335] - 1ms 주기 LED Toggle 프로그램(1) - System 세팅

 

1ms 주기 LED Toggle 프로그램(1) - System 세팅

◆ GPIO Toggle 기능을 이용하여 30MHz 오실레이터를 이용하여 150Mhz 클럭을 설정 후 1ms 주기로 제어하는 프로그램을 구현하고자 하였습니다. 추가로 500ms 에서 동작하는 것도 추가를 해 보았으며, 이를 오실로..

bennyziiolab.tistory.com

2019/04/09 - [임베디드 프로세서/TMS320F28335] - 1ms 주기 LED Toggle 프로그램(2) - GPIO 세팅

 

1ms 주기 LED Toggle 프로그램(2) - GPIO 세팅

2019/04/09 - [임베디드 프로세서/TMS320F28335] - 1ms 주기 LED Toggle 프로그램(1) - System 세팅 1ms 주기 LED Toggle 프로그램(1) - System 세팅 ◆ GPIO Toggle 기능을 이용하여 30MHz 오실레이터를 이용하여..

bennyziiolab.tistory.com

2019/04/10 - [임베디드 프로세서/TMS320F28335] - 1ms 주기 LED Toggle 프로그램(3) - PIE 세팅

 

1ms 주기 LED Toggle 프로그램(3) - PIE 세팅

2019/04/09 - [임베디드 프로세서/TMS320F28335] - 1ms 주기 LED Toggle 프로그램(1) - System 세팅 1ms 주기 LED Toggle 프로그램(1) - System 세팅 ◆ GPIO Toggle 기능을 이용하여 30MHz 오실레이터를 이용하여..

bennyziiolab.tistory.com

TMS320F28335에는 3가지 32비트 CPU 타이머를 사용할 수 있습니다. 각각 CPU-Timer 0, CPU-Timer 1, CPU-Timer2인데요 CPU-Timer 2는 DSP/BIOS에 사용되는데 DSP/BIOS를 사용하지 않는다면 CPU-Timer 2도 사용이 가능은 합니다. 그렇지 않다면 시스템에 양보해야합니다.

CPU-Timer 인터럽트 신호도 3가지로 TINT0, TINT1, TINT2가 있는데요. 자세한 다이어그램은 아래와 같습니다.

CPU-Timer 0 같은 경우는 PIE 레지스터를 통해서 CPU로 INT1 ~ INT12의 형태로 주어지지만, CPU-Timer 1은 외부 인터럽트 레지스터를 통해서 CPU로 INT13의 형태로 제공됩니다. CPU-Timer 2는 DSP/BIOS로 할당되어 있지만 DSP/BIOS를 사용하지 않는다면 사용이 가능하여 INT14의 형태로 제공되게 됩니다.

 

자이제 저는 현재 150MHz의 CPU 속도로 세팅되어 있으며 1ms의 주기 설정을 하여야 합니다.

ConfigCpuTimer() 함수에서 이를 세팅해줘야 하는데요. 소스를 통해 좀 더 알아보겠습니다.

#if (CPU_FRQ_150MHZ)
// Configure CPU-Timer 0, 1, and 2 to interrupt every second:
// 150MHz CPU Freq, 0.1 mille-second Period (in uSeconds)

   ConfigCpuTimer(&CpuTimer0, 150, 100);
#endif

&CpuTimer0인자는 CpuTimer 0의 주소 포인터값으로 지정되어 있어 ConfigCpuTimer 함수가 실행되면 어떤 Cpu Timer의 값을 세팅할 것이지 선택하기 위해 포인터 지정이 되었구요. 150은 150MHz를 나타내는 것이고 100은 0.1ms 즉, 100us를 나타내는 것입니다. 기본 단위가 us단위라서 위와 같이 작성한 것인데 여기서 1ms 주기를 뱉어내야 하는데 왜 0.1ms로 하였는지 의문이 가실 것입니다. 이는 개발자마다 다른데 저는 0.1ms을 10번 카운트해서 1ms로 만들고자 했기 때문에 이와 같이 세팅을 100으로 하게 되었습니다.

// To ensure precise timing, use write-only instructions to write to the entire register. Therefore, if any
// of the configuration bits are changed in ConfigCpuTimer and InitCpuTimers (in DSP2833x_CpuTimers.h), the
// below settings must also be updated.

   CpuTimer0Regs.TCR.all = 0x4000; // Use write-only instruction to set TSS bit = 0
   CpuTimer1Regs.TCR.all = 0x4000; // Use write-only instruction to set TSS bit = 0
   CpuTimer2Regs.TCR.all = 0x4000; // Use write-only instruction to set TSS bit = 0

그 다음 위아 같이 TCR 레지스터를 세팅해주어야 하는데 TCR이란 Timer Control Register로서 0x4000 즉 0b0100000000000000으로 세팅하였는데 이 의미는 TIE가 1로서 CPU-Timer Interrupt를 Enable하겠단 뜻이며, 또 중요한 사항중에 하나가 4번 비트가 TSS라는 Field가 있는데 이게 0으로 해야지 CPU 타이머가 카운트를 시작하게 됩니다.

 

다음은 앞에서 말씀드린 CPU Timer 0의 int1 ~ int12의 형태로 주어진다고 했는데 int1을 CPU Timer 0와 연결하기 위한 작업을 위해 아래와 같이 작성해주었습니다.

// Enable CPU int1 which is connected to CPU-Timer 0, CPU int13
// which is connected to CPU-Timer 1, and CPU int 14, which is connected
// to CPU-Timer 2:
   IER |= M_INT1;

그리하여 int1 -> TINT0 -> CPU-Timer 0까지 할당이 된 것이지요.

이제 TINT0만 인터럽트 Enable 해주면 CPU Timer 0를 인터럽트 서비스 루틴을 이용하여 사용할 수 있게 해줍니다.

// Enable TINT0 in the PIE: Group 1 interrupt 7
   PieCtrlRegs.PIEIER1.bit.INTx7 = 1;

마지막으로 전역 인터럽트와 실시간 최우선순위 디버그 이벤트를 Enable 해주기 위해 다음과 같이 작성해줍니다.

// Enable global Interrupts and higher priority real-time debug events:
   EINT;   // Enable Global interrupt INTM
   ERTM;   // Enable Global realtime interrupt DBGM

왜 해주어야 하는지는 아직 제대로 개념을 잡지 못하였습니다. 공부하면서 개발하는 과정을 블로그에 남기는게 목적인지라 부족한 설명에 대해서 이해 부탁드립니다. 차츰 공부하면서 알게되면 추가로 꼭 작성하도록 하겠습니다. 그게 모두를 위해 윈윈하는 일이니깐요^^

 

자 이제 cpu_timer0_isr 함수를 만들고 여기에 실제로 1ms마다 플래그를 뛰우는 작업을 해보겠습니다.

__interrupt void cpu_timer0_isr(void)
{
   CpuTimer0.InterruptCount++;

   if(uCount_001ms == 0) {
	   uCount_001ms = 9;
	   FLAG_1ms = 1;
	   Watch_FLAG_1ms_Status++;
   }
   else {
	   uCount_001ms--;
   }

   // Acknowledge this interrupt to receive more interrupts from group 1
   PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}

위와 같이 작성하였는데요. CpuTimer0.InterruptCount++로 0.1ms마다 인터럽트를 증가시킵니다. 저는 여기서 변수 uCount_001ms를 선언하여 0.1ms를 카운트해서 처음 0일때 FLAG_1ms라고 선언한 변수를 1로 값을 주어 플래그를 발생시켰고 uCount_001ms은 9로 하여 9부터 0까지 감소하게 하여 0.1ms가 10번 반복하여 1ms가 되면 다시 또 uCount_001ms가 9가 되어 다시 또 0으로 무한 반복을 하게 만들었습니다. 즉 1ms마다 FLAG_1ms가 1이 되는 것이죠.

이제 FLAG_1ms가 1이 되었을 경우에 LED를 동작하게 하는 구문을 메인 루프안에 작성하여 원하는 동작을 하게 하여 이 블로그의 목적을 달성하게 되는 것이죠.

 

마지막 PieCtrlRegs.PIEACK.all = PIEACK_GROUP1은 인터럽트를 Acknowledge하여 더 많은 인터럽트를 그룹1로 부터 받을 수 있게 한다라고 주석에 적혀 있는데 좀 더 공부를 해봐야 정확한 기능을 알 수 있을 것 같습니다. 이는 추후에 공부해서 남기도록 하겠습니다.

반응형

댓글