시리얼 통신(DBGU) 인터럽트

 // 인터럽트를 이용한 echo 예제
//---------- 디버그 유닛 관련 I/O 제어 레지스터

#define DBGU_CR   (*(volatile unsigned int *) 0xFFFFF200)  // DBGU Control Register
#define DBGU_MR   (*(volatile unsigned int *) 0xFFFFF204)  // DBGU Mode Register
#define DBGU_IER  (*(volatile unsigned int *) 0xFFFFF208)  // DBGU Interrupt Enable Register
#define DBGU_IDR  (*(volatile unsigned int *) 0xFFFFF20C)  // DBGU Interrupt Disalbe Register
#define DBGU_IMR  (*(volatile unsigned int *) 0xFFFFF210)  // DBGU Interrupt Disalbe Register
#define DBGU_SR   (*(volatile unsigned int *) 0xFFFFF214)  // DBGU Status Register
#define DBGU_RHR  (*(volatile unsigned int *) 0xFFFFF218)  // DBGU Receive Holding Register
#define DBGU_THR  (*(volatile unsigned int *) 0xFFFFF21C)  // DBGU Transmit Holding Register
#define DBGU_BRGR (*(volatile unsigned int *) 0xFFFFF220)  // DBGU Baud Rate Generator Register


//---------- 인터럽트 제어기 IO설정 

#define AIC_IECR (*(volatile unsigned int *) 0xFFFFF120)  // 인터럽트 허 용 레지스터
#define AIC_IDCR (*(volatile unsigned int *) 0xFFFFF124)  // 인터럽트 금지 레지스터
#define AIC_ICCR (*(volatile unsigned int *) 0xFFFFF128)  // 인터럽트 클리어 레지스터
#define AIC_ISCR (*(volatile unsigned int *) 0xFFFFF12C)  // 인터럽트 세트 레지스터
#define AIC_SMR  ((volatile unsigned int *) 0xFFFFF000)    // AIC 소스 모드 레지스터
#define AIC_SVR  ((volatile unsigned int *) 0xFFFFF080)    // AIC 소 스 벡터 레지스터


//---------- 입출 력 IO설정 


#define PIO_PUDR (*(volatile unsigned int *) 0xFFFFF460)  // PIO Pull-Up Disable Register
#define PIO_PUER (*(volatile unsigned int *) 0xFFFFF464)  // PIO Pull-Up Enable Register

#define PIO_IER  (*(volatile unsigned int *) 0xFFFFF440)  // PIO Interrupt Enable Register
#define PIO_IDR  (*(volatile unsigned int *) 0xFFFFF444)  // PIO Interrupt Disable Register
#define PIO_IMR  (*(volatile unsigned int *) 0xFFFFF448)  // PIO Interrupt Mask Register
#define PIO_ISR  (*(volatile unsigned int *) 0xFFFFF44C)  // PIO Interrupt Status Register

#define PIO_ASR  (*(volatile unsigned int *) 0xFFFFF470)  // PIO Peripheral A Select Register
#define PIO_BSR  (*(volatile unsigned int *) 0xFFFFF474)  // PIO Peripheral B Select Register

#define PIO_IFER (*(volatile unsigned int *) 0xFFFFF420)  // PIO Glitch Input Filter Enable Register
#define PIO_IFDR (*(volatile unsigned int *) 0xFFFFF424)  // PIO Glitch Input Filter Disable Register

#define PIO_SODR (*(volatile unsigned int *) 0xFFFFF430) //출력 
#define PIO_CODR (*(volatile unsigned int *) 0xFFFFF434) //출력 하지 않음
#define PIO_OER  (*(volatile unsigned int *) 0xFFFFF410) //출력 방향 설정
#define PIO_ODR  (*(volatile unsigned int *) 0xFFFFF414) //출력 방향 설정
#define PIO_PER  (*(volatile unsigned int *) 0xFFFFF400) //병렬 입출력 제 어 레지스터 병렬 입출력 포트로 사용한다.
#define PIO_PDR  (*(volatile unsigned int *) 0xFFFFF404) //병렬 입출력 제어 레지스터 병렬 입출력 포트로 사용한다.


//---------- 전력 제어 설정

#define PMC_PCER (*(volatile unsigned int *) 0xFFFFFC10)
#define PMC_PCDR (*(volatile unsigned int *) 0xFFFFFC14)

 
#define MASTERCLOCK 48000000
#define INTERR    0x00000100
#define LED      0x00000010 

//--------- 전역 변수
unsigned char data;

void Delayms(unsigned int ms) //딜레이 함 수..

  volatile unsigned int count, countmax = (MASTERCLOCK / 10000) * ms;

  for(count = 0; count < countmax; count++);
}

void DBGU_write(char d)  // 송신 함수
{
  while(0 == (DBGU_SR & 0x0002));
  DBGU_THR = d;
}

void DBGU_read()    // 인 터럽트 처리 루틴
{
  // echo 기능
  data = DBGU_RHR;
  DBGU_write(data);
}

int main(void)
{  
  // PMC setting
  PMC_PCER = (unsigned int)1 << 2;    // PMC_PCER = (unsigned int)1 << 2;

  DBGU_CR = (1<<2)|(1<<3);      // 송수신부 리셋 및 금지  
  AIC_IDCR = (1<<1);          //인터럽트 금지
  
  // PIO setting
  PIO_PDR = (1<<9)|(1<<10);  // 병렬 포트 사용 금지
  PIO_ASR = (1<<9)|(1<<10);  // 장치 A 사용
  PIO_BSR = 0;        // 장치 B 사용 금지

  // DBGU setting
  DBGU_IER = (1 << 0);    // RXRDY enable
  DBGU_MR = (1<<11);      // Parity 사용하 지 않음
  DBGU_BRGR = 313;      // Baud rate = 9600
  DBGU_CR = (1<<6)|(1<<4);  // tx, rx enable
  
  // AIC setting.
  AIC_SMR[1= (1<<5)|(1<<6)|(1<<2)|(1<<0);  // Positive edge trigger, Prior = 5
  AIC_SVR[1= (unsigned int)DBGU_read;  // 인터럽트 처리 루틴
  AIC_ICCR = (1<<1);
  AIC_IECR = (1<<1);    // 인터럽트 활성화
  
  while(1)
  {
  }
  
  return 0;
// End Main....
// 일반적으로 시리얼 통신에서 데이터를 전송하는 시점은 정해져 있다. 반면 데이터를 수신하는 시점은 정해져 있는 것이 아니기때문에 인터럽트는 보통 RXRDY만을 사용한다.
// DBGU(디버그 유닛)은 System Controller로 장치 PID1를 사용한다.

 // 시리얼 통신으로 LED를 ON시키는 예제
//---------- 디버그 유닛 관련 I/O 제어 레지스터

#define DBGU_CR   (*(volatile unsigned int *) 0xFFFFF200)  // DBGU Control Register
#define DBGU_MR   (*(volatile unsigned int *) 0xFFFFF204)  // DBGU Mode Register
#define DBGU_IER  (*(volatile unsigned int *) 0xFFFFF208)  // DBGU Interrupt Enable Register
#define DBGU_IDR  (*(volatile unsigned int *) 0xFFFFF20C)  // DBGU Interrupt Disalbe Register
#define DBGU_IMR  (*(volatile unsigned int *) 0xFFFFF210)  // DBGU Interrupt Disalbe Register
#define DBGU_SR   (*(volatile unsigned int *) 0xFFFFF214)  // DBGU Status Register
#define DBGU_RHR  (*(volatile unsigned int *) 0xFFFFF218)  // DBGU Receive Holding Register
#define DBGU_THR  (*(volatile unsigned int *) 0xFFFFF21C)  // DBGU Transmit Holding Register
#define DBGU_BRGR (*(volatile unsigned int *) 0xFFFFF220)  // DBGU Baud Rate Generator Register


//---------- 인터럽트 제어기 IO설정 

#define AIC_IECR (*(volatile unsigned int *) 0xFFFFF120)  // 인터럽트 허 용 레지스터
#define AIC_IDCR (*(volatile unsigned int *) 0xFFFFF124)  // 인터럽트 금지 레지스터
#define AIC_ICCR (*(volatile unsigned int *) 0xFFFFF128)  // 인터럽트 클리어 레지스터
#define AIC_ISCR (*(volatile unsigned int *) 0xFFFFF12C)  // 인터럽트 세트 레지스터
#define AIC_SMR  ((volatile unsigned int *) 0xFFFFF000)    // AIC 소스 모드 레지스터
#define AIC_SVR  ((volatile unsigned int *) 0xFFFFF080)    // AIC 소 스 벡터 레지스터


//---------- 입출 력 IO설정 


#define PIO_PUDR (*(volatile unsigned int *) 0xFFFFF460)  // PIO Pull-Up Disable Register
#define PIO_PUER (*(volatile unsigned int *) 0xFFFFF464)  // PIO Pull-Up Enable Register

#define PIO_IER  (*(volatile unsigned int *) 0xFFFFF440)  // PIO Interrupt Enable Register
#define PIO_IDR  (*(volatile unsigned int *) 0xFFFFF444)  // PIO Interrupt Disable Register
#define PIO_IMR  (*(volatile unsigned int *) 0xFFFFF448)  // PIO Interrupt Mask Register
#define PIO_ISR  (*(volatile unsigned int *) 0xFFFFF44C)  // PIO Interrupt Status Register

#define PIO_ASR  (*(volatile unsigned int *) 0xFFFFF470)  // PIO Peripheral A Select Register
#define PIO_BSR  (*(volatile unsigned int *) 0xFFFFF474)  // PIO Peripheral B Select Register

#define PIO_IFER (*(volatile unsigned int *) 0xFFFFF420)  // PIO Glitch Input Filter Enable Register
#define PIO_IFDR (*(volatile unsigned int *) 0xFFFFF424)  // PIO Glitch Input Filter Disable Register

#define PIO_SODR (*(volatile unsigned int *) 0xFFFFF430) //출력 
#define PIO_CODR (*(volatile unsigned int *) 0xFFFFF434) //출력 하지 않음
#define PIO_OER  (*(volatile unsigned int *) 0xFFFFF410) //출력 방향 설정
#define PIO_ODR  (*(volatile unsigned int *) 0xFFFFF414) //출력 방향 설정
#define PIO_PER  (*(volatile unsigned int *) 0xFFFFF400) //병렬 입출력 제 어 레지스터 병렬 입출력 포트로 사용한다.
#define PIO_PDR  (*(volatile unsigned int *) 0xFFFFF404) //병렬 입출력 제어 레지스터 병렬 입출력 포트로 사용한다.


//---------- 전력 제어 설정

#define PMC_PCER (*(volatile unsigned int *) 0xFFFFFC10)
#define PMC_PCDR (*(volatile unsigned int *) 0xFFFFFC14)

 
#define MASTERCLOCK 48000000
#define INTERR    0x00000100
#define LED      0x00000010 

//--------- 전역 변수
char data[20];
int index = 0;

void Delayms(unsigned int ms) //딜레이 함수..

  volatile unsigned int count, countmax = (MASTERCLOCK / 10000) * ms;

  for(count = 0; count < countmax; count++);
}

int atoi(char *c)      // Charter to Integer
{
  int result = 0;
  int val = 1;
  int i;
  char *tmp = c;

  while(*tmp != '\0')
  {
    val *= 10;
    tmp++;
  }

  tmp = c;
  for(i = (val / 10) ; 1 <= i ; i /= 10)
  {
    result += ((*tmp - 48) * i);
    tmp++;
  }

  return result;
}

void LED_Decode()    // 신 호 decode
{
  int num;
  num = atoi(data);
  
  switch(num)
  {
    case 1:
      PIO_CODR = 0xFF;
      break;
    case 10:
      PIO_CODR = 0xFF;
      PIO_SODR = 0x1;
      break;
    case 100:
      PIO_CODR = 0xFF;
      PIO_SODR = 0x3;
      break;
    case 1000:
      PIO_CODR = 0xFF;
      PIO_SODR = 0x7;
      break;      
    default:
      break;
  }      
}

void DBGU_write(char d)    // 송신 함수
{
  while(0 == (DBGU_SR & 0x0002));
  DBGU_THR = d;
}

void DBGU_read()    // 수 신 함수
{
  char buf;
  buf = DBGU_RHR;
  
  if(buf != '\r')
  {
    data[index++] = buf;
  }
  else
  {
    data[index] = '\0';
    index = 0;
    LED_Decode();
  }
}

int main(void)
{  
  // PMC setting
  PMC_PCER = (unsigned int)1 << 2;    // PMC_PCER = (unsigned int)1 << 2;

  DBGU_CR = (1<<2)|(1<<3);      // 송수신부 리셋 및 금지
  AIC_IDCR = (1<<1);          //인터럽트 금지
  
  // PIO setting
  PIO_PER = 0xFF;        // Pin0 ~ Pin7 병렬포트 사용
  PIO_OER = 0xFF;        // Pin0 ~ Pin7 출력으로 설정
  PIO_PDR = (1<<9)|(1<<10);  // 병렬 포트 사용 금지
  PIO_ASR = (1<<9)|(1<<10);  // 장치 A 사용
  PIO_BSR = 0;        // 장치 B 사용 금지

  // DBGU setting
  DBGU_IER = (1 << 0);    // RXRDY enable
  DBGU_MR = (1<<11);      // Parity 사용하 지 않음
  DBGU_BRGR = 313;      // Baud rate = 9600
  DBGU_CR = (1<<6)|(1<<4);  // tx, rx enable
  
  // AIC setting.
  AIC_SMR[1= (1<<5)|(1<<6)|(1<<2)|(1<<0);  // Positive edge trigger, Prior = 5
  AIC_SVR[1= (unsigned int)DBGU_read;    // 인터럽트 처리 루틴
  AIC_ICCR = (1<<1);
  AIC_IECR = (1<<1);      // 인터럽트 활성화
  
  while(1)
  {

  }
  
  return 0;
// End Main....
// PC 터미널에서 각각 1, 10, 100, 1000을 입력하고 Enter를 입력하면 LED를 ON,OFF 시킨다.
// 1 : 모든 LED OFF / 10 : LED 1개 ON / 100 : LED 2개 ON / 1000 : LED 3개 ON
// 이 예제는 전역 변수를 여러 함수가 공유하고 있다. 이는 공유데이터 문제를 야기할 수 있다. 하나의 함수가 공유 데이터를 사용하고 있는 도중에 다른 함수가 그 값을 바꾸면 문제가 발생한다.

   시리얼 통신

 ECHO 예제
//---------- 디버그 유닛 관련 I/O 제어 레지스터

#define DBGU_CR   (*(volatile unsigned int *) 0xFFFFF200)  // DBGU Control Register
#define DBGU_MR   (*(volatile unsigned int *) 0xFFFFF204)  // DBGU Mode Register
#define DBGU_IER  (*(volatile unsigned int *) 0xFFFFF208)  // DBGU Interrupt Enable Register
#define DBGU_IDR  (*(volatile unsigned int *) 0xFFFFF20C)  // DBGU Interrupt Disalbe Register
#define DBGU_IMR  (*(volatile unsigned int *) 0xFFFFF210)  // DBGU Interrupt Disalbe Register
#define DBGU_SR   (*(volatile unsigned int *) 0xFFFFF214)  // DBGU Status Register
#define DBGU_RHR  (*(volatile unsigned int *) 0xFFFFF218)  // DBGU Receive Holding Register
#define DBGU_THR  (*(volatile unsigned int *) 0xFFFFF21C)  // DBGU Transmit Holding Register
#define DBGU_BRGR (*(volatile unsigned int *) 0xFFFFF220)  // DBGU Baud Rate Generator Register


//---------- 인터럽트 제어기 IO설정 

#define AIC_IECR (*(volatile unsigned int *) 0xFFFFF120)  // 인터럽트 허용 레지스터
#define AIC_IDCR (*(volatile unsigned int *) 0xFFFFF124)  // 인터럽트 금지 레지스터
#define AIC_ICCR (*(volatile unsigned int *) 0xFFFFF128)  // 인터럽트 클리어 레지스터
#define AIC_ISCR (*(volatile unsigned int *) 0xFFFFF12C)  // 인터럽트 세트 레지스터
#define AIC_SMR  ((volatile unsigned int *) 0xFFFFF000)    // AIC 소스 모드 레지스터
#define AIC_SVR  ((volatile unsigned int *) 0xFFFFF080)    // AIC 소스 벡터 레지스터


//---------- 입출력 IO설정 


#define PIO_PUDR (*(volatile unsigned int *) 0xFFFFF460)  // PIO Pull-Up Disable Register
#define PIO_PUER (*(volatile unsigned int *) 0xFFFFF464)  // PIO Pull-Up Enable Register

#define PIO_IER  (*(volatile unsigned int *) 0xFFFFF440)  // PIO Interrupt Enable Register
#define PIO_IDR  (*(volatile unsigned int *) 0xFFFFF444)  // PIO Interrupt Disable Register
#define PIO_IMR  (*(volatile unsigned int *) 0xFFFFF448)  // PIO Interrupt Mask Register
#define PIO_ISR  (*(volatile unsigned int *) 0xFFFFF44C)  // PIO Interrupt Status Register

#define PIO_ASR  (*(volatile unsigned int *) 0xFFFFF470)  // PIO Peripheral A Select Register
#define PIO_BSR  (*(volatile unsigned int *) 0xFFFFF474)  // PIO Peripheral B Select Register

#define PIO_IFER (*(volatile unsigned int *) 0xFFFFF420)  // PIO Glitch Input Filter Enable Register
#define PIO_IFDR (*(volatile unsigned int *) 0xFFFFF424)  // PIO Glitch Input Filter Disable Register

#define PIO_SODR (*(volatile unsigned int *) 0xFFFFF430) //출력 
#define PIO_CODR (*(volatile unsigned int *) 0xFFFFF434) //출력 하지 않음
#define PIO_OER  (*(volatile unsigned int *) 0xFFFFF410) //출력 방향 설정
#define PIO_ODR  (*(volatile unsigned int *) 0xFFFFF414) //출력 방향 설정
#define PIO_PER  (*(volatile unsigned int *) 0xFFFFF400) //병렬 입출력 제어 레지스터 병렬 입출력 포트로 사용한다.
#define PIO_PDR  (*(volatile unsigned int *) 0xFFFFF404) //병렬 입출력 제어 레지스터 병렬 입출력 포트로 사용한다.


//---------- 전력 제어 설정

#define PMC_PCER (*(volatile unsigned int *) 0xFFFFFC10)
#define PMC_PCDR (*(volatile unsigned int *) 0xFFFFFC14)

 
#define MASTERCLOCK 48000000
#define INTERR    0x00000100
#define LED      0x00000010 

//--------- 전역 변수

void Delayms(unsigned int ms) //딜레이 함수..

  volatile unsigned int count, countmax = (MASTERCLOCK / 10000) * ms;

  for(count = 0; count < countmax; count++);
}

void DBGU_write(char d)  // 송신 함수
{
  while(0 == (DBGU_SR & 0x0002));
  DBGU_THR = d;
}

unsigned char DBGU_read()  // 수신 함수
{
  while(0 == (DBGU_SR & 0x0001));
  return DBGU_RHR;
}

int main(void)
{
  unsigned char data;
  
  // PMC setting
  PMC_PCER = (unsigned int)1 << 2;    // PMC_PCER = (unsigned int)1 << 2;

  DBGU_CR = (1<<2)|(1<<3);      // 송수신부 리셋 및 금지
    
  // PIO setting
  PIO_PDR = (1<<9)|(1<<10);  // 병렬 포트 사용 금지
  PIO_ASR = (1<<9)|(1<<10);  // 장치 A 사용
  PIO_BSR = 0;        // 장치 B 사용 금지

  // DBGU setting
  DBGU_MR = (1<<11);      // Parity 사용하지 않음
  DBGU_BRGR = 313;      // Baud rate = 9600
  DBGU_CR = (1<<6)|(1<<4);  // tx, rx enable

  while(1)
  {
    data = DBGU_read();
    DBGU_write(data);
  }
  
  return 0;
// End Main....

// DBGU를 이용하여 간단한 시리얼 통신을 해보았다. PC 터미널에서 신호를 날리면 그 신호가 그대로 다시 돌아와서 PC 터미널에 찍히게 된다.

 // 정수형 데이터를 문자로 변환하여 전송하는 프로그램
//---------- 디버그 유닛 관련 I/O 제어 레지스터

#define DBGU_CR   (*(volatile unsigned int *) 0xFFFFF200)  // DBGU Control Register
#define DBGU_MR   (*(volatile unsigned int *) 0xFFFFF204)  // DBGU Mode Register
#define DBGU_IER  (*(volatile unsigned int *) 0xFFFFF208)  // DBGU Interrupt Enable Register
#define DBGU_IDR  (*(volatile unsigned int *) 0xFFFFF20C)  // DBGU Interrupt Disalbe Register
#define DBGU_IMR  (*(volatile unsigned int *) 0xFFFFF210)  // DBGU Interrupt Disalbe Register
#define DBGU_SR   (*(volatile unsigned int *) 0xFFFFF214)  // DBGU Status Register
#define DBGU_RHR  (*(volatile unsigned int *) 0xFFFFF218)  // DBGU Receive Holding Register
#define DBGU_THR  (*(volatile unsigned int *) 0xFFFFF21C)  // DBGU Transmit Holding Register
#define DBGU_BRGR (*(volatile unsigned int *) 0xFFFFF220)  // DBGU Baud Rate Generator Register


//---------- 인터럽트 제어기 IO설정 

#define AIC_IECR (*(volatile unsigned int *) 0xFFFFF120)  // 인터럽트 허 용 레지스터
#define AIC_IDCR (*(volatile unsigned int *) 0xFFFFF124)  // 인터럽트 금지 레지스터
#define AIC_ICCR (*(volatile unsigned int *) 0xFFFFF128)  // 인터럽트 클리어 레지스터
#define AIC_ISCR (*(volatile unsigned int *) 0xFFFFF12C)  // 인터럽트 세트 레지스터
#define AIC_SMR  ((volatile unsigned int *) 0xFFFFF000)    // AIC 소스 모드 레지스터
#define AIC_SVR  ((volatile unsigned int *) 0xFFFFF080)    // AIC 소 스 벡터 레지스터


//---------- 입출 력 IO설정 


#define PIO_PUDR (*(volatile unsigned int *) 0xFFFFF460)  // PIO Pull-Up Disable Register
#define PIO_PUER (*(volatile unsigned int *) 0xFFFFF464)  // PIO Pull-Up Enable Register

#define PIO_IER  (*(volatile unsigned int *) 0xFFFFF440)  // PIO Interrupt Enable Register
#define PIO_IDR  (*(volatile unsigned int *) 0xFFFFF444)  // PIO Interrupt Disable Register
#define PIO_IMR  (*(volatile unsigned int *) 0xFFFFF448)  // PIO Interrupt Mask Register
#define PIO_ISR  (*(volatile unsigned int *) 0xFFFFF44C)  // PIO Interrupt Status Register

#define PIO_ASR  (*(volatile unsigned int *) 0xFFFFF470)  // PIO Peripheral A Select Register
#define PIO_BSR  (*(volatile unsigned int *) 0xFFFFF474)  // PIO Peripheral B Select Register

#define PIO_IFER (*(volatile unsigned int *) 0xFFFFF420)  // PIO Glitch Input Filter Enable Register
#define PIO_IFDR (*(volatile unsigned int *) 0xFFFFF424)  // PIO Glitch Input Filter Disable Register

#define PIO_SODR (*(volatile unsigned int *) 0xFFFFF430) //출력 
#define PIO_CODR (*(volatile unsigned int *) 0xFFFFF434) //출력 하지 않음
#define PIO_OER  (*(volatile unsigned int *) 0xFFFFF410) //출력 방향 설정
#define PIO_ODR  (*(volatile unsigned int *) 0xFFFFF414) //출력 방향 설정
#define PIO_PER  (*(volatile unsigned int *) 0xFFFFF400) //병렬 입출력 제 어 레지스터 병렬 입출력 포트로 사용한다.
#define PIO_PDR  (*(volatile unsigned int *) 0xFFFFF404) //병렬 입출력 제어 레지스터 병렬 입출력 포트로 사용한다.


//---------- 전력 제어 설정

#define PMC_PCER (*(volatile unsigned int *) 0xFFFFFC10)
#define PMC_PCDR (*(volatile unsigned int *) 0xFFFFFC14)

 
#define MASTERCLOCK 48000000
#define INTERR    0x00000100
#define LED      0x00000010 

//--------- 전역 변수

void Delayms(unsigned int ms) //딜레이 함 수..

  volatile unsigned int count, countmax = (MASTERCLOCK / 10000) * ms;

  for(count = 0; count < countmax; count++);
}

void DBGU_write(char *d)    // 문자열 송신 함수
{
  while(0 != *d)
  {
    while(0 == (DBGU_SR & 0x0002));
    DBGU_THR = *d;
    ++d;
  }
}

unsigned char DBGU_read()    // 수신 함수
{
  while(0 == (DBGU_SR & 0x0001));
  return DBGU_RHR;
}

void intToChar(char *buf, int num)  // int 형을 Char형으로 변환
{
  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';
}

int main(void)
{
  int num = 0;
  char buf[20];
  
  // PMC setting
  PMC_PCER = (unsigned int)1 << 2;    // PMC_PCER = (unsigned int)1 << 2;

  DBGU_CR = (1<<2)|(1<<3);      // 송수신부 리셋 및 금지  
  
  // PIO setting
  PIO_PDR = (1<<9)|(1<<10);  // 병렬 포트 사용 금지
  PIO_ASR = (1<<9)|(1<<10);  // 장치 A 사용
  PIO_BSR = 0;        // 장치 B 사용 금지

  // DBGU setting
  DBGU_MR = (1<<11);      // Parity 사용하 지 않음
  DBGU_BRGR = 313;      // Baud rate = 9600
  DBGU_CR = (1<<6)|(1<<4);  // tx, rx enable

  intToChar(buf, num);
  
  while(1)
  {
    intToChar(buf, num++);
    DBGU_write(buf);
    if(num == 9)
      num = 0;
  }
  
  return 0;
// End Main....
// 정수형을 문자로 전송하기 위해서 intToChar함수를 따로 작성하였다. 송신 함수도 문자열을 전송할 수 있게 수정하였다.


SRCS    = $(wildcard *.cpp)
CC        = g++
TARGET    = main

all : $(TARGET)

$(TARGET) : $(SRCS:.cpp=.o)
    $(CC) -o $@ $^

clean :
    rm -rf $(SRCS:.cpp=.o)

// 타겟을 main으로 하는 c++ Makefile... 디렉토리 안의 모든 cpp 파일을 컴파일, 링크해서 main 실행 파일을 만들어 준다.



   클래스 상속
 기존의 클래스를 상속받아서 새로운 클래스를 만드는 방법이다.
class HTMLWriter : public DocWriter
{
}
DocWriter - 부모 클래스 // HTMLWriter - 자식 클래스

 자식 클래스에는 부모 클래스에 없는 새로운 멤버를 추가할 수도 있고, 부모 클래스에 이미 존재하는 멤버 함수를 새롭게 정의할 수도 있다. 자식 객체를 생성할 때는 자식 클래스의 생성자  뿐만 아니라 부모 클래스의 생성자도 호출된다. 따로 부모 클래스의 생성자 함수를 지정하지 않으면 부모 클래스의 디폴트 생성자가 호출된다. 생성자를 지정해 주려면 초기화 리스트에서 해야 한다.
 부모 클래스 생성자가 자식 클래스의 생성자보다 먼저 호출된다. 반대로 소멸는 자식 클래스의 소멸자가 호출된 후 부모 클래스의 소멸자가 호출된다.
자식 객체 생성 시 : 부모 클래스 생성자 -> 자식 클래스 생성자
자식 객체 소멸 시 : 자식 클래스 소멸자 -> 부모 클래스 소멸자

 부모 클래스의 객체를 자식 클래스로 대입하는 것은 불가능하다. 하지만 반대의 경우 ,즉 자식 클래스의 객체를 부모 클래스로 대입하는 것은 가능하다. 이때 부모 객체와 자식 객체에 공통적으로 있는 멤버들이 1:1로 대입된다.
 자식 클래스의 포인터나 레퍼런스를 사용해서 부모 객체를 가리킬 수 없다. 하지만 반대로 부모 클래스의 포인터나 레퍼런스로 자식 클래스의 객체는 가리킬 수 있다. 이 경우 실제 객체가 무엇이던 간에 상관없이 포인터 타입을 기준으로 호출되는 멤버 함수가 결정된다.

 접근제어
public : 모든 곳으로부터의 접근을 허용 한다.
protected : 자식 클래스의 멤버 함수로부터의 접근만 허용 한다.
private : 자신의 멤버 함수 외에는 접근할 수 없다.
외부로부터 숨겨야 하는 멤버는 protected로 지정한다.
그 밖의 경우는 public으로 지정한다.
반드시 자식 클래스에 숨기고 싶다면 private로 지정한다.

 Point.h
#ifndef POINT_H
#define POINT_H

// Point 클래수를 정의한다
class Point
{
public:
  // 멤버 함수
  void Print();
  void Offset(int x_delta, int y_delta);
  void Offset(const Point& pt);

  // 생성자들
  Point();
  Point(int initialX, int initialY);
  Point(const Point& pt);

  // 소멸자
  ~Point();

  // 접근자
  void SetX(int value);
  void SetY(int value);
  int GetX() const
  {
    return x;
  }
  int GetY() const
  {
    return y;
  }
private:
  // 멤버 변수
  int x, y;
};

#endif

 Point.cpp
#include "Point.h"
#include <iostream>
using namespace std;

void Point::SetX(int value)
{
  if(value < 0)
  {
    x = 0;
  }
  else if(value > 100)
  {
    x = 100;
  }
  else
  {
    x = value;
  }
}

void Point::SetY(int value)
{
  if(value < 0)
  {
    y = 0;
  }
  else if(value > 100)
  {
    y = 100;
  }
  else
  {
    y = value;
  }
}

void Point::Print()
{
  cout << "(" << x << ", " << y << ")\n";
}

void Point::Offset(int x_delta, int y_delta)
{
  SetX(x + x_delta);
  SetY(y + y_delta);
}

void Point::Offset(const Point& pt)
{
  Offset(pt.x, pt.y);
}

Point::Point(const Point& pt)
{
  x = pt.x;
  y = pt.y;
}

Point::Point(int initialX, int initialY)
{
  SetX(initialX);
  SetY(initialY);
}

Point::Point()
{
  x = 0;
  y = 0;
}

Point::~Point()
{
}


 Rect.h
#ifndef RECT_H
#define RECT_H

#include "Point.h"

class Rect
{
public:
  // 생성자
  Rect();
  Rect(const Point& topLeft, const Point& bottomRight);
  Rect(int left, int top, int right, int bottom);

  // 각 점의 값 지정/얻기
  void SetTopLeft(const Point& topLeft);
  void SetBottomRight(const Point& bottomRight);
  void SetRect(int left, int top, int right, int bottom);
  Point GetTopLeft() const;
  Point GetBottomRight() const;
  void GetRect(int& left, int& top, int& right, int& bottom);

  // 넓이, 높이 계산
  int GetWidth() const;
  int GetHeight() const;

  // 내 용 출력
  void Print() const;

protected:
  Point _topLeft;
  Point _bottomRight;
};

#endif

 Rect.cpp
#include "Rect.h"
#include <iostream>
using namespace std;

Rect::Rect()
{

}

void Rect::SetTopLeft(const Point& topLeft)
{
  _topLeft = topLeft;
}

void Rect::SetBottomRight(const Point& bottomRight)
{
  _bottomRight = bottomRight;
}

void Rect::SetRect(int left, int top, int right, int bottom)
{
  _topLeft.SetX(left); 
  _topLeft.SetY(top); 
  _bottomRight.SetX(right); 
  _bottomRight.SetY(bottom); 
}

Point Rect::GetTopLeft() const
{
  return _topLeft;
}

Point Rect::GetBottomRight() const
{
  return _bottomRight;
}

void Rect::GetRect(int& left, int& top, int& right, int& bottom)
{
  left = _topLeft.GetX(); 
  top = _topLeft.GetY(); 
  right = _bottomRight.GetX(); 
  bottom = _bottomRight.GetY(); 
}

int Rect::GetWidth() const
{
  return (_bottomRight.GetX() - _topLeft.GetX() + 1);
}

int Rect::GetHeight() const
{
  return (_bottomRight.GetY() - _topLeft.GetY() + 1);
}

void Rect::Print() const
{
  cout << "{L=" << _topLeft.GetX() << ", T=" << _topLeft.GetY();
  cout << ", R=" << _bottomRight.GetX() << ", B=" <<
    _bottomRight.GetY() << "}\n";
}

Rect::Rect(const Point& topLeft, const Point& bottomRight)
:_topLeft(topLeft), _bottomRight(bottomRight)
{
}

Rect::Rect(int left, int top, int right, int bottom)
:_topLeft(left, top), _bottomRight(right, bottom)
{
}

 main.cpp
#include "Rect.h"
#include <iostream>
using namespace std;

int main()
{
  Rect rc1;
  Rect rc2(Point(1020), Point(3040));
  Rect rc3(50607080);

  rc1.Print();
  rc2.Print();
  rc3.Print();

  return 0;
}


   RS232

RS232는 표준 인터페이스의 하나로서 데이터를 직렬로 전송하며 대부분의 PC에 기본으로 장착되어 있다. 배선 수가 작으며, 통신 프로그래밍 구현이 쉽다. 하지만 병렬 전송에 비해 전송 속도가 느리고, 일대일 통신만 가능하다는 단점이 있다.


TXD - Transmit Data
비동기식 직렬통신 장치가 외부 장치로 정보를 보낼 직렬통신 데이터가 나오는 신호선이다.

RXD - Receive Data
외부 장치에서 들어오는 직렬통신 데이터를 입력받는 신호선이다
RTS - Ready To Send
컴퓨터와 같은 DTE장치가 모뎀 또는 프린터와 같은 DCE장치에게 데이터를 받을 준비가 됐음을 나타내는 신호선이다.

CTS - Clear To Send
모뎀 또는 프린터와 같은 DCE장치가 컴퓨터와 같은 DTE장치에게 데이터를 받을 준비가 됐음을 나타내는 신호선이다.

DTR - Data Terminal Ready
컴퓨터 또는 터미널이 모뎀에게 자신이 송수신 가능한 상태임을 알리는 신호선이며 일반적으로 컴퓨터등이 전원 인가후 통신 포트를 초기화한 이신호를 출력시킨다.

DSR - Data Set Ready
모뎀이 컴퓨터 또는 터미널에게 자신이 송수신 가능한 상태임을 알려주는 신호선이며 일반적으로 모뎀에 전원 인가 모뎀이 자신의 상태를 파악한 이상이 없을 신호를 출력시킨다.

DCD - Data Carrier Detect
모뎀이 상대편 모뎀과 전화선 등을 통해서 접속이 완료되었을 상대편 모뎀이 캐리어신호를 보내오며 신호를 검출하였음을 컴퓨터 또는 터미널에 알려주는 신호선이다.

RI - Ring Indicator
상대편 모뎀이 통신을 하기위해서 먼저 전화를 걸어오면 전화 벨이 울리게 된다. 이때 신호를 모뎀이 인식하여 컴퓨터 또는 터미널에 알려주는 신호선이며 일반적으로 컴퓨터가 이신호를 받게되면 전화벨 신호에 응답하는 프로그램을 인터럽터등을 통해서 호출하게 된다.


- 시작 비트, 정지비트 : RS232C 인터페이스 규격에서는 송수신 데이터의 신호는 부논리로 규정되어 있으므로 데이터의 비트는 1 -5~-15V 0 5~15V 대응한다. 실제 데이터 전송시 데이터의 앞에 Start Bit(논리 0) 1비트와 뒤에 Stop Bit(논리 1) 2비트와 패리티 비트를 부가해서 송신한다. 여기서 Start Bit Stop Bit 사용해서 수신측 통신소자가 1 캐릭터(8Bit)마다 동기를 맞출 있기 때문에 송수신 측의 동기신호 없이도 송수신이 가능한 것이다. Stop Bit 2비트 뿐만 아니라 1.5비트나 1비트도 설정가능하기 때문에 송수신 측의 Stop Bit 일치 시켜야한다.

- 패리티 비트 : 통신에 있어서 어떤 데이터를 전송할 데이터가 정확히 보내졌는가를 검사하는데 사용한다. Odd 패리티와 Even 패리티 체크의 가지 형태가 있는데 Odd 패리티는 2진수의 1 합이 홀수가 되게 지정하고 Even 패리티의 경우는 1 합이 홀수가 되게 지정한다.

- Baud rate : RS232C 인터페이스의 통신속도는 접속하는 쌍방의 장치의 성능과 통신선로의 특성에 따라 크게 좌우된다. 통신회선 상에 신호율을 측정하기 위한 기본단위를 보오레이트라고 불리며, 1초간에 송수 가능한 비트 수로 규정된다. 만약 110으로 설정된다면 패리티가 부가된 ASCII 코드 1캐릭터를 보내기 위해서

1(Start Bit) + 7(캐릭터의 비트수) + 1(패리티 비트) + 2(Stop Bit) = 11비트

따라서 1초간에 최대 110 / 11 = 10(캐릭터) 송수신 가능하다.

보통의 퍼스널 컴퓨터에서는 1문자 단위를 8비트(1바이트) 다루기 때문에 하나의 문자정보를 보내기 위해서 Stop Bit 최소 1비트로 하여

1(Start Bit) + 8(문자 데이터 비트수) + 1(Stop Bit) = 10비트

1문자 전송에 10비트를 사용한다.


  디버그 유닛(Debug Unit)

디버그 유닛은 USART 포트관련 레지스터에서 많이 사용하는 것만 뽑아 놓은 것이다.



 Rect.h
#ifndef RECT_H
#define RECT_H

#include "Point.h"

class Rect
{
public:
  // 생성자
  Rect();

  // 각 점의 값 지정/얻기
  void SetTopLeft(const Point& topLeft);
  void SetBottomRight(const Point& bottomRight);
  void SetRect(int left, int top, int right, int bottom);
  Point GetTopLeft() const;
  Point GetBottomRight() const;
  void GetRect(int& left, int& top, int& right, int& bottom);

  // 넓이, 높이 계산
  int GetWidth() const;
  int GetHeight() const;

  // 내 용 출력
  void Print() const;

protected:
  Point _topLeft;
  Point _bottomRight;
};

#endif

 Rect.cpp
#include "Rect.h"
#include <iostream>
using namespace std;

Rect::Rect()
{

}

void Rect::SetTopLeft(const Point& topLeft)
{
  _topLeft = topLeft;
}

void Rect::SetBottomRight(const Point& bottomRight)
{
  _bottomRight = bottomRight;
}

void Rect::SetRect(int left, int top, int right, int bottom)
{
  _topLeft.SetX(left); 
  _topLeft.SetY(top); 
  _bottomRight.SetX(right); 
  _bottomRight.SetY(bottom); 
}

Point Rect::GetTopLeft() const
{
  return _topLeft;
}

Point Rect::GetBottomRight() const
{
  return _bottomRight;
}

void Rect::GetRect(int& left, int& top, int& right, int& bottom)
{
  left = _topLeft.GetX(); 
  top = _topLeft.GetY(); 
  right = _bottomRight.GetX(); 
  bottom = _bottomRight.GetY(); 
}

int Rect::GetWidth() const
{
  if(_bottomRight.GetX() > _topLeft.GetX())
  {
    return (_bottomRight.GetX() - _topLeft.GetX() + 1);
  }
  else
  {
    return (_topLeft.GetX() - _bottomRight.GetX() + 1);
  }
}

int Rect::GetHeight() const
{
  if(_bottomRight.GetY() > _topLeft.GetY())
  {
    return (_bottomRight.GetY() - _topLeft.GetY() + 1);
  }
  else
  {
    return (_topLeft.GetY() - _bottomRight.GetY() + 1);
  }
}

void Rect::Print() const
{
  cout << "{L=" << _topLeft.GetX() << ", T=" << _topLeft.GetY();
  cout << ", R=" << _bottomRight.GetX() << ", B=" <<
    _bottomRight.GetY() << "}\n";
}

 main.cpp
#include "Rect.h"
#include <iostream>
using namespace std;

int main()
{
  // Rect 객 체 생성
  Rect rc1;

  // 값을 바 꿔본다.
  rc1.SetRect(101000);

  // 내용 출력
  rc1.Print();
  
  // 넓이, 높이 출력
  cout << "rc1.GetWidth() = " << rc1.GetWidth() << endl;
  cout << "rc1.GetHeight() = " << rc1.GetHeight() << endl;

  // 값을 바꿔본다.
  rc1.SetRect(10102020);

  // 내용 출력
  rc1.Print();

  // 넓이, 높이 출력
  cout << "rc1.GetWidth() = " << rc1.GetWidth() << endl;
  cout << "rc1.GetHeight() = " << rc1.GetHeight() << endl;

  return 0;
}


   포함
포함 관계는 어떤 객체가 다른 객체를 포함하고 있는 관계를 의미한다. 즉 객체를 멤버로 갖는 클래스이다. 이러한 객체 멤버들은 생성자 초기화 리스트에서 초기화 해야 한다. 소멸자는 객체를 포함하고 있는 객체의 소멸자부터 호출되고, 그 다음 멤버 객체들의 소멸자들이 호출된다.

 Rect.h
#ifndef RECT_H
#define RECT_H

#include "Point.h"

class Rect
{
public:
  // 생성자
  Rect();

  // 각 점의 값 지정/얻기
  void SetTopLeft(const Point& topLeft);
  void SetBottomRight(const Point& bottomRight);
  void SetRect(int left, int top, int right, int bottom);
  Point GetTopLeft() const;
  Point GetBottomRight() const;
  void GetRect(int& left, int& top, int& right, int& bottom);

  // 넓이, 높이 계산
  int GetWidth() const;
  int GetHeight() const;

  // 내 용 출력
  void Print() const;

protected:
  Point _topLeft;
  Point _bottomRight;
};

#endif

 Rect.cpp
#include "Rect.h"
#include <iostream>
using namespace std;

Rect::Rect()
{

}

void Rect::SetTopLeft(const Point& topLeft)
{
  _topLeft = topLeft;
}

void Rect::SetBottomRight(const Point& bottomRight)
{
  _bottomRight = bottomRight;
}

void Rect::SetRect(int left, int top, int right, int bottom)
{
  _topLeft.SetX(left); 
  _topLeft.SetY(top); 
  _bottomRight.SetX(right); 
  _bottomRight.SetY(bottom); 
}

Point Rect::GetTopLeft() const
{
  return _topLeft;
}

Point Rect::GetBottomRight() const
{
  return _bottomRight;
}

void Rect::GetRect(int& left, int& top, int& right, int& bottom)
{
  left = _topLeft.GetX(); 
  top = _topLeft.GetY(); 
  right = _bottomRight.GetX(); 
  bottom = _bottomRight.GetY(); 
}

int Rect::GetWidth() const
{
  return (_bottomRight.GetX() - _topLeft.GetX() + 1);
}

int Rect::GetHeight() const
{
  return (_bottomRight.GetY() - _topLeft.GetY() + 1);
}

void Rect::Print() const
{
  cout << "{L=" << _topLeft.GetX() << ", T=" << _topLeft.GetY();
  cout << ", R=" << _bottomRight.GetX() << ", B=" <<
    _bottomRight.GetY() << "}\n";
}

 main.cpp
#include "Rect.h"
#include <iostream>
using namespace std;

int main()
{
  // Rect 객 체 생성
  Rect rc1;

  // 내용 출 력
  rc1.Print();
  cout << (*((int *)(&rc1)+1)) << endl;

  // 값을 바꿔본다.
  rc1.SetRect(10203040);

  // 내용 출력
  rc1.Print();
  
  // 값을 바꿔본다.
  rc1.SetTopLeft(Point(2020));

  // 내용 출력
  rc1.Print();
  cout << (*((int *)(&rc1)+1)) << endl;
  cout << (*((int *)(&rc1)+2)) << endl;
  cout << (*((int *)(&rc1)+3)) << endl;

  // 넓 이, 높이 출력
  cout << "rc1.GetWidth() = " << rc1.GetWidth() << endl;
  cout << "rc1.GetHeight() = " << rc1.GetHeight() << endl;

  cout << "rc1 size = " << sizeof(rc1) << endl;

  return 0;
}



   ARM 인터럽트 실습
ARM에서는 각 장치별로 인터럽트 설정이 가능하다. 즉 PIO핀들에 설정 가능한 인터럽트 루틴은 하나다. 그러므로 이 인터럽트 루틴에서 어떤 핀이 인터럽트가 걸렸는지 판별하여 처리하도록 작성해야 한다.(Atmega128에서는 인터럽트로 이용 가능한 핀들이 미리 정해져 있고, 이 핀 마다 각기 인터럽트 루틴을 작성할 수 있다) 또한 ARM에서는 인터럽트 처리의 신뢰성을 위하여 인터럽트 상태를 확인 할 수 있도록 설계되었다. ARM에서는 인터럽트가 걸린 후 핀 상태를 확인함으로써 인터럽트가 초기화 되고 다시 사용가능하게 된다.

//---------- 인터럽트 제어기 IO설정 

#define AIC_IECR (*(volatile unsigned int *) 0xFFFFF120)  // 인터럽트 허 용 레지스터
#define AIC_IDCR (*(volatile unsigned int *) 0xFFFFF124)  // 인터럽트 금지 레지스터
#define AIC_ICCR (*(volatile unsigned int *) 0xFFFFF128)  // 인터럽트 클리어 레지스터
#define AIC_ISCR (*(volatile unsigned int *) 0xFFFFF12C)  // 인터럽트 세트 레지스터
#define AIC_SMR  ((volatile unsigned int *) 0xFFFFF000)    // AIC 소스 모드 레지스터
#define AIC_SVR  ((volatile unsigned int *) 0xFFFFF080)    // AIC 소 스 벡터 레지스터


//---------- 입출 력 IO설정 


#define PIO_PUDR (*(volatile unsigned int *) 0xFFFFF460)  // PIO Pull-Up Disable Register
#define PIO_PUER (*(volatile unsigned int *) 0xFFFFF464)  // PIO Pull-Up Enable Register

#define PIO_IER  (*(volatile unsigned int *) 0xFFFFF440)  // PIO Interrupt Enable Register
#define PIO_IDR  (*(volatile unsigned int *) 0xFFFFF444)  // PIO Interrupt Disable Register
#define PIO_IMR  (*(volatile unsigned int *) 0xFFFFF448)  // PIO Interrupt Mask Register
#define PIO_ISR  (*(volatile unsigned int *) 0xFFFFF44C)  // PIO Interrupt Status Register

#define PIO_IFER (*(volatile unsigned int *) 0xFFFFF420)  // PIO Glitch Input Filter Enable Register
#define PIO_IFDR (*(volatile unsigned int *) 0xFFFFF424)  // PIO Glitch Input Filter Disable Register

#define PIO_SODR (*(volatile unsigned int *) 0xFFFFF430) //출력 
#define PIO_CODR (*(volatile unsigned int *) 0xFFFFF434) //출력 하지 않음
#define PIO_OER  (*(volatile unsigned int *) 0xFFFFF410) //출력 방향 설정
#define PIO_ODR  (*(volatile unsigned int *) 0xFFFFF414) //출력 방향 설정
#define PIO_PER  (*(volatile unsigned int *) 0xFFFFF400) //병렬 입출력 제 어 레지스터 병렬 입출력 포트로 사용한다.


//---------- 전 력 제어 설정

#define PMC_PCER (*(volatile unsigned int *) 0xFFFFFC10)

 
#define MASTERCLOCK 48000000
#define INTERR    0x00000100
#define LED      0x00000010 

//--------- 전역 변수

void Delayms(unsigned int ms) //딜레이 함 수..

  volatile unsigned int count, countmax = (MASTERCLOCK / 10000) * ms;

  for(count = 0; count < countmax; count++);
}

void ledToggle()
{  
  unsigned int clear;
  PIO_SODR = 0x00000010;
  Delayms(500);
  PIO_CODR = 0x00000010;
  Delayms(500);
  clear = PIO_ISR;    // 인터럽트 초 기화를 위해 PIO_ISR 값을 읽음
}

int main(void)
{
  // PMC setting
  PMC_PCER = 0x00000004;    // PMC_PCER = (unsigned int)1 << 2;
  
  // PIO setting
  PIO_PER = 0x00000110;    // PIO_PER = 0x00000FFF;
  PIO_IER = 0x00000100;    
  PIO_IFER = 0x00000100;  
  
  PIO_PUER = 0x00000100;    // PIO_PUER = 1 << 8;
  PIO_ODR = 0x100;
                // PIO_ODR = 0x100;
  PIO_OER = 0x00000010;

  // AIC setting
  AIC_IDCR = (unsigned int)1 << 2;
  AIC_SMR[2= 0x00000065;
  AIC_SVR[2= (unsigned int)ledToggle;
  AIC_ICCR = 0x00000004;
  AIC_IECR = 0x00000004;    // AIC_IECR = (unsigned int)1 << 2;
  
  while(1)
  {

  }
  
  return 0;
// End Main....
// 8번 핀으로 인터럽트를 입력받고, 인터럽트가 걸리면 4번핀에 연결된 LED가 한번 깜빡 거리는 코드이다. 인터럽트는 positive edge에서 발생하며, 인터럽트가 발생 했을 시 ledToggle 함수를 실행하게 된다. ledToggle 함수에서는 LED를 한번 깜빡 거리고, PIO_ISR 레지스터를 읽어서 인터럽트를 다시 사용할 수 있게 초기화 한다.

//---------- 인터럽트 제어기 IO설정 

#define AIC_IECR (*(volatile unsigned int *) 0xFFFFF120)  // 인터럽트 허 용 레지스터
#define AIC_IDCR (*(volatile unsigned int *) 0xFFFFF124)  // 인터럽트 금지 레지스터
#define AIC_ICCR (*(volatile unsigned int *) 0xFFFFF128)  // 인터럽트 클리어 레지스터
#define AIC_ISCR (*(volatile unsigned int *) 0xFFFFF12C)  // 인터럽트 세트 레지스터
#define AIC_SMR  ((volatile unsigned int *) 0xFFFFF000)    // AIC 소스 모드 레지스터
#define AIC_SVR  ((volatile unsigned int *) 0xFFFFF080)    // AIC 소 스 벡터 레지스터


//---------- 입출 력 IO설정 


#define PIO_PUDR (*(volatile unsigned int *) 0xFFFFF460)  // PIO Pull-Up Disable Register
#define PIO_PUER (*(volatile unsigned int *) 0xFFFFF464)  // PIO Pull-Up Enable Register

#define PIO_IER  (*(volatile unsigned int *) 0xFFFFF440)  // PIO Interrupt Enable Register
#define PIO_IDR  (*(volatile unsigned int *) 0xFFFFF444)  // PIO Interrupt Disable Register
#define PIO_IMR  (*(volatile unsigned int *) 0xFFFFF448)  // PIO Interrupt Mask Register
#define PIO_ISR  (*(volatile unsigned int *) 0xFFFFF44C)  // PIO Interrupt Status Register

#define PIO_IFER (*(volatile unsigned int *) 0xFFFFF420)  // PIO Glitch Input Filter Enable Register
#define PIO_IFDR (*(volatile unsigned int *) 0xFFFFF424)  // PIO Glitch Input Filter Disable Register

#define PIO_SODR (*(volatile unsigned int *) 0xFFFFF430) //출력 
#define PIO_CODR (*(volatile unsigned int *) 0xFFFFF434) //출력 하지 않음
#define PIO_OER  (*(volatile unsigned int *) 0xFFFFF410) //출력 방향 설정
#define PIO_ODR  (*(volatile unsigned int *) 0xFFFFF414) //출력 방향 설정
#define PIO_PER  (*(volatile unsigned int *) 0xFFFFF400) //병렬 입출력 제 어 레지스터 병렬 입출력 포트로 사용한다.


//---------- 전 력 제어 설정

#define PMC_PCER (*(volatile unsigned int *) 0xFFFFFC10)


#define MASTERCLOCK 48000000
#define INTERR    0x00000100
#define LED      0x00000010 

void PIO_Ext02(void);



void Delayms(unsigned int ms) //딜레이 함 수..

  volatile unsigned int count, countmax = (MASTERCLOCK / 10000) * ms;

  for(count = 0; count < countmax; count++);
}

void PIO_Ext01(void)
{
  static unsigned int i=0;
  unsigned int status;

  status=PIO_ISR;

  if(status == (unsigned int)0x00000100)
  {
    if(i==0)
      i =1;
    else if(i&0x80)
      return;
    else
      i|=i<<1;

    PIO_SODR=i; 
  }
  else if(status ==(unsigned int)0x00000200)
  {
    if(i==0)
      return;
    else
      i =i>>1;
    PIO_CODR=0xFF;
    PIO_SODR=i;
  }
}

void PIO_Ext02(void)

  unsigned int i;
  for(i=1; i<=3; i++)
  {
    PIO_SODR=0x000000ff;
    Delayms(300);
    PIO_CODR=0x000000ff;
    Delayms(300);
  }
}

int main(void){

  PMC_PCER = (unsigned int)1<<2;
  PIO_PER = 0x00000FFF;   //병렬 I/O포 트로 사용 설정 디폴트로 I/O포트로 사용 하도록 되어 있다.
  PIO_PUER=0x300;
  PIO_ODR = 0x300;     //출력 버퍼 금지 레지스터 설정
  Delayms(50);

  PIO_OER = 0x00000FFF;  


  PIO_IFER=0x00000300;  //글리치 필터 사용
  PIO_IER=0x00000300;   //인터럽트 인애이블 레지스터

  AIC_IDCR=(unsigned int)1<<2;    //마스크 설정
  AIC_SVR[2]=(unsigned int)PIO_Ext01;      //인터럼트 함수 설정
  AIC_SMR[2]=5;           //
  AIC_ICCR=(unsigned int)1<<2;    //
  AIC_IECR=(unsigned int)1<<2;    //마스크 해지



  while(1);

  return 0;

// End Main....
// 8번, 9번핀으로 인터럽트를 입력받아 각각 처리 해주는 예제이다. 8번핀에 인터럽트가 걸리면 0번부터 7번에 연결된 LED가 하나씩 켜지며, 반대로 9번핀에 인터럽트가 걸리면 하나씩 LED가 꺼진다. PIO_Ext01 함수에서 어느 핀의 인터럽트가 걸렸는지 판별하여 각각의 동작을 정의한다.



출처 : http://blog.naver.com/psychoria?Redirect=Log&logNo=40108323175

C++은 메모리 관리를 하기가 상당히 까다로운 언어입니다.

특히 동적 할당과 관련해서는 조금만 실수하면

메모리 누수나, 메모리 접근 위반으로 프로그램이 죽기가 일쑤입니다.

메모리 누수란 프로그램이 종료시까지는 할당한 모든 메모리가해제가 되어야 하는데

할당된 메모리가 해제가 되지 않을 때 발생하는 문제이고,

메모리 접근 위반은 초기화되지 않은 포인터 혹은 동적 할당된 범위 밖을 호출할 때 발생합니다.

초기화되지 않은 포인터는 어떻게 작동할 지 예측을 할 수 없습니다.

(10중 8, 9는 프로그램이 죽는다고 보면 됩니다.)

new 사용 시에 주의할 점은 다음과 같습니다.

new로 할당 시에는 delete로 해제하고, new[]로 할당 시에는 delete[]

해제해줘야 한다는 것입니다.

C++을 공부한 입장에서는 너무도 당연한 이야기겠지만,

사실 신경쓰지 않고 사용했다가 나중에 메모리 누수가 났을 때,

디버깅시에 상당히 오랜 시간을 투자해야할 수도 있기 때문에 꼭 다시 한 번 상기하시기 바랍니다.

Effective C++에서는 다음과 같은 그림을 들어서 new를 delete[]로 해제했을 때나

new[]를 delete로 해제했을 때의 위험성을 설명합니다.


 
한 개를 해제하려고 하는데 갯수를 참조하게 되고,
 
배열을 해제하려고 하는데 크기 정보를 못 가져 오는 상황을 의미하는 거 같습니다.
 
실제 코드를 통해서 알아보도록 하겠습니다.
 
console project에서 확인하기 위해서
 
#define _CRTDBG_MAP_ALLOC

#include <crtdbg.h>
 
를 추가합니다.


 
F5를 눌러서 Debug를 실시해보면
 
delete가 호출되는 시점 이전의 _CrtDumpMemoryLeaks() 함수를 호출할 때
 
출력창에 다음과 같이 표시됩니다.
 

 
Detected memory leaks! 라는 문장이 보이네요.
 
메모리 누수가 생긴것이지요.
 
기본에 충실해야 더 나아갈 수 있는 것 같습니다.
//---------- 인터럽트 제어기 IO설정 

#define AIC_IECR (*(volatile unsigned int *) 0xFFFFF120)  // 인터럽트 허용 레지스터
#define AIC_IDCR (*(volatile unsigned int *) 0xFFFFF124)  // 인터럽트 금지 레지스터
#define AIC_ICCR (*(volatile unsigned int *) 0xFFFFF128)  // 인터럽트 클리어 레지스터
#define AIC_ISCR (*(volatile unsigned int *) 0xFFFFF12C)  // 인터럽트 세트 레지스터
#define AIC_SMR  ((volatile unsigned int *) 0xFFFFF000)    // AIC 소스 모드 레지스터
#define AIC_SVR  ((volatile unsigned int *) 0xFFFFF080)    // AIC 소스 벡터 레지스터


//---------- 입출력 IO설정 


#define PIO_PUDR (*(volatile unsigned int *) 0xFFFFF460)  // PIO Pull-Up Disable Register
#define PIO_PUER (*(volatile unsigned int *) 0xFFFFF464)  // PIO Pull-Up Enable Register

#define PIO_IER  (*(volatile unsigned int *) 0xFFFFF440)  // PIO Interrupt Enable Register
#define PIO_IDR  (*(volatile unsigned int *) 0xFFFFF444)  // PIO Interrupt Disable Register
#define PIO_IMR  (*(volatile unsigned int *) 0xFFFFF448)  // PIO Interrupt Mask Register
#define PIO_ISR  (*(volatile unsigned int *) 0xFFFFF44C)  // PIO Interrupt Status Register

#define PIO_IFER (*(volatile unsigned int *) 0xFFFFF420)  // PIO Glitch Input Filter Enable Register
#define PIO_IFDR (*(volatile unsigned int *) 0xFFFFF424)  // PIO Glitch Input Filter Disable Register

#define PIO_SODR (*(volatile unsigned int *) 0xFFFFF430) //출력 
#define PIO_CODR (*(volatile unsigned int *) 0xFFFFF434) //출력 하지 않음
#define PIO_OER  (*(volatile unsigned int *) 0xFFFFF410) //출력 방향 설정
#define PIO_PER  (*(volatile unsigned int *) 0xFFFFF400) //병렬 입출력 제어 레지스터 병렬 입출력 포트로 사용한다.


//---------- 전력 제어 설정

#define PMC_PCER (*(volatile unsigned int *) 0xFFFFFC10)

 
#define MASTERCLOCK 48000000
#define INTERR    0x00000100
#define LED      0x00000010 

//--------- 전역 변수

void Delayms(unsigned int ms) //딜레이 함수..

  volatile unsigned int count, countmax = (MASTERCLOCK / 10000) * ms;

  for(count = 0; count < countmax; count++);
}

void ledToggle()
{  
  int clear;
  PIO_SODR = 0x00000010;
  Delayms(500);
  PIO_CODR = 0x00000010;
  Delayms(500);
  clear = PIO_ISR;
}

int main(void)
{
  // PMC setting
  PMC_PCER = 0x00000004;
  
  // PIO setting
  PIO_PER = 0x00000110;
  PIO_IER = 0x00000100;
  PIO_IFER = 0x00000100;
  PIO_PUER = 0x00000100;

  PIO_OER = 0x00000010;
//  PIO_SODR = 0x00000000;  

  // AIC setting
  AIC_IECR = 0x00000004;
  AIC_SMR[2= 0x00000065;
  AIC_SVR[2= (unsigned int)ledToggle;
  AIC_ICCR = 0x00000004;
  
  while(1)
  {

  }
  
  return 0;
// End Main....

1. 문자가 숫자인지 알려주는 isDigit 함수를 구현하세요. 문자 ch를 입력 받고, ch가 숫자인지 출력하세요. 맞다면 YES, 아니면 NO를 출력합니다.


 character.h
#ifndef CHARACTER_H
#define CHARACTER_H

class Character
{
public:
  // 생성자
  Character();
  Character(char c);

  // 멤버 함수
  void setChar(char c);
  int getChar() const;
  bool isDigit() const;
protected:
  // 멤버 변수
  char ch;
};

#endif

 character.cpp
#include "Character.h"

void Character::setChar(char c)
{
  ch = c;
}

int Character::getChar() const
{
  return ch;
}

bool Character::isDigit() const
{
  if(('0' <= ch) && ('9' >= ch))
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

Character::Character()
{
  ch = 0;
}

Character::Character(char c)
{
  setChar(c);
}

 main.cpp
#include "Character.h"
#include <iostream>
using namespace std;

int main()
{
  char ch;
  
  cout << "문자: ";
  cin >> ch;

  Character c(ch);
  if(c.isDigit())
  {
    cout << "결과: YES" << endl;
  }
  else
  {
    cout << "결과: NO" << endl;
  }
}


2. 정수 N을 입력하면 2 N승을 출력하는 프로그램을 작성하세요. , 비트 연산을 이용합니다.

그리고 -1을 입력할 경우 프로그램은 종료됩니다.


 Multiplier.h
#ifndef MULTIPLIER_H
#define MULTIPLIER_H

class Multiplier
{
public:
  // 생성자
  Multiplier();
  Multiplier(int num);

  // 멤버 함수
  void setNum(int num);
  int getNum() const;
  void twoMulti(int num);
  int getResult() const;
protected:
  int num;  // 승수
  int result;  // 결과
};

#endif

 Multiplier.cpp
#include "Multiplier.h"

void Multiplier::setNum(int num)
{
  this -> num = num;
}

int Multiplier::getNum() const
{
  return num;
}

void Multiplier::twoMulti(int num)
{
  result = 1 << num;  
}

int Multiplier::getResult() const
{
  return result;
}

Multiplier::Multiplier()
{
  num = 0;
  result = 0;
}

Multiplier::Multiplier(int num)
{
  setNum(num);
  twoMulti(num);
}

 main.cpp
#include "Multiplier.h"
#include <iostream>
using namespace std;

int main()
{
  int num;

  while(1)
  {
    cout << "입력: ";
    cin >> num;

    if(num == -1)
    {
      return -1;
    }

    Multiplier m(num);

    cout << "출력: 2 ^ " << m.getNum() << = " << m.getResult() <<endl;
  }

  return 0;
}

+ Recent posts