PIT(주기적인 시간간격 타이머)
 PIT(Periodic Interval Timer)는 운영체제의 스케쥴러에게 주기적인 인터럽트를 발생시키기 위하여 사용하는 타이머이다. 여기서는 효율적인 관리가 중요하며, 시간의 정확성을 높이기 위하여 슬로우 클럭이 아니라 마스터 클럭을 사용한다.

 주기적인 시간간격 타이머는 마스터 클럭을 16분주한 MCK/16의 주파수로 동작하며, 20비트 증가형 카운터 CPIV와 12비트 증가형 카운터 PICNT로 구성된다. 이것이 동작하려면 PIT_MR 레지스터에서 PITEN 비트를 인에이블시켜야 한다.
 
 20비트 카운터 CPIV는 0부터 증가하다가 PIT_MR 레지스터의 PIV 값에 이르게 되면 그 다음 주기에서 자동으로 0으로 클리어 되면서 12비트 카운터 PICNT를 1만큼 증가시키게 되며, 이는 또한 인터럽트를 요청할 수 있다. 따라서, 인터럽트 주기는 PIV+1클럭 사이클이 된다.

 PIT_MR 레지스터의 PIV 값을 변경하기 위하여 새로 라이트하더라도 카운터를 리셋하거나 리스타트하지는 않는다.

 CPIV 값이나 PICNT 값을 확인하기 위하여 PIT_PIVR 레지스터를 읽으면 PICNT 값이 0으로 클리어되고 PIT_SR 레지스터의 PITS 비트도 클리어되어 인터럽트 신호를 종료시킨다. 그러나, PIT_PIIR 레지스터를 읽으면 PICNT 값이나 PIT_SR 레지스터의 PITS 비트를 클리어하지 않는다.

 // PIT(Periodic Inteval Timer)
#include "MyArm.h"

#define INTERR    0x00000100
#define LED      0x00000010 

//--------- Global Variable?
int c = 0;
int cnt = 0;

void DBGU_write(char *d)
{
  while(0 != *d)
  {
    while(0 == (DBGU_SR & 0x0002));
    DBGU_THR = *d;
    ++d;
  }
}

void intToChar(char *buf, int num)
{
  int i, j;
  int target;    // 각 자 리수
  int value = 1;  // 숫자 크기 확인
  
  while(value <= num)
  {
    value *= 10;
  }  
  
  for(i = 0, j = value/10 ; j >= 10 ; j /= 10)
  {
    target = num / j;
    num = num % j;
    buf[i++] = target + 48;    // buf에 문자값 저장
  }
  buf[i++] = num + 48;
  buf[i] = '\0';
}

void SysControlISR()
{  
  unsigned int tmp;
  char tx[10];
  tmp = PIT_PIVR;        // Interrupt Reset
  cnt++;

  if(1000 == cnt)  
  {
    intToChar(tx, c);
    DBGU_write(tx);
    c++;
    cnt = 0;
  }
}

int main(void)
{  
  DBGU_CR = (1 << P2) | (1 << P3);  // TX,RX reset & disable
  AIC_IDCR = (1 << P1);        // System Controller Interrupt Disable
  
  // PIO setting
  PIO_PDR = (1 << P9) | (1 << P10);  // PA9, PA10 Disable
  PIO_ASR = (1 << P9) | (1 << P10);  // PA9, PA10 Peripheral A select
  
  // DBGU setting
  DBGU_MR = (1 << P11);        // No Parity
  DBGU_BRGR = 313;          // Baud rate = 9600
  DBGU_CR = (1 << P6);        // TX enable
  
  // PIT setting
  PIT_MR = (0xBB7) | (1 << P25) | (1 << P24);    // PIV = 2999, PITIEN enable
  
  // AIC setting
  AIC_SMR[1= (1 << P5) | (1 << P2) | (1 << P0);  // Positive edge, Priority = 5;
  AIC_SVR[1= (unsigned int)SysControlISR;    // System Controller ISR
  AIC_IECR = (1 << P1);        // System Controller Interrupt Enable

  while(1)
  {

  }  
  
  return 0;
// End Main...
// 1초마다 숫자를 카운트해서 그 숫자를 시리얼 통신으로 전송하는 예제이다.
// 인터럽트 처리 루틴에서 PIT_PIVR 값을 읽어서 인터럽트를 리셋을 해준다.
// MASTERCLOCK에서 16분주 한 클럭으로 카운트를 하므로 PIV 값을 2999를 주면 1ms 가 만들어진다.(인터럽트는 PIV+1일 때 발생한다)
// 48M / 16 = 3M -> 3M / 3000 = 1K  : 1초에 1000번을 카운트 함으로 1ms마다 인터럽트가 발생하게 된다.

+ Recent posts