- DDRx Port xData Direction Register로서 입출력의 방향을 설정하는 레지스터이고, PORTxPort x Data Register 데이터 출력에 해당하는 레지스터이고, PINx Port x Input Pins Address로서 포트핀의 입력에 해당하는 PINx 레지스터이다. 이것에 대한정의는 <avr/io.h>를 통해서 찾아 볼수 있다.

이 헤더 파일은avr폴더 밑에 io.h라는 파일을 찾을 있다. 하지만 이 헤더파일은 각 버전에 대한 io헤더파일의 연결자 헤더파일이었다. 이중 MCU의 해당 버전을 찾게 도와주는 파일이있는데 makefile이 바로 그것이다.  그 중 지금 공부하는 프로세서가atmega128이니 iom128.h가 헤더 파일로 되어있을있다. 안에 DDRx DDRA에 대해 설정 되어 있는 내용을 찾아보니

/* Data Register, Port A */

#define PORTA    _SFR_IO8(0x1B)

/* Data Direction Register, Port A */

#define DDRA     _SFR_IO8(0x1A)

/* Input Pins, Port A */

#define PINA     _SFR_IO8(0x19) 로 정의 되어 있었다.

DDRA를 우선적으로 살펴보면 _SFR_IO8(0x1A)define한다는 의미인 것이다. 하지만 이 부분은 매크로함수 _SFR_IO8과 이 매크로의 인자인 0x1A로 되어있다는 사실을 알 수 있을 것이다. PORTx PINx 또한 마찬가지로 구성 되어있음을 알 수 있을 것이다.

0x1A를 데이터 시트에서 찾아보면 교재마다 다르겠지만본인의 교재 중 363p - 데이터 시트의 Register Summary의 내용 중 $1A(아트멜에서는 16진수의 표시를 $로 한다.)의이름은 DDRA로 되어 있음을 확인 할 수 있었다. 매크로함수를 통해 DDRA 포트 레지스터로 접근한는 내용임을 짐작하게 한다.

그럼_SFR_IO8()이란 함수를 찾아보아야 자세한 내용을 찾아볼 수 있을 것 같다. 이 함수에대해서 알아보기 위해 iom128.h에서 include하고있는 sfr_def.h이란 헤더파일을 찾아봐야한다. 이 헤더파일은 macros for accessing AVR special function registers에 대한 헤더파일이라는 것을 알 수 있었다. 그럼 _SFR_IO8()이란 무엇인가를 찾아봐야 할 차례인 것 같다.

찾으면 2가지의코드가 나올 것인다.

#define _SFR_IO8(io_addr) ((io_addr) +__SFR_OFFSET) : 이코드는 우리가 찾는 코드가 아니다.

#define_SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET) : 이코드가 찾는 내용이다.

음 점입가경이다._SFR_IO8(io의 주소)(_MMIO_BYTE매크로에 io의 주소를 넣은 값)(__SFR_OFFSET)을 더한 값이 된다. 그중 모르는 내용이 2가지나 나왔는데 _MMIO_BYTE __SFR_OFFSET에 대한 정보가 필요해 졌다. 하지만 걱정 하지 말자. 이번에 찾을 내용은 sfr_def.h안에 다 있는 내용이다.

_MMIO_BYTE를 찾게 되면

#define _MMIO_BYTE(mem_addr) (*(volatileuint8_t *)(mem_addr))를 찾게 된다.

이 매크로를 읽어보면 voliatile타입의 uint8_t인데 이 것을 해석해보면 unsigned int 8bit type이라는 것이다. 결론적으로 unsigned char라는 의미가 될 것이다. (이것도 헤더파일을따라가다 보면 나오는데 별 의미없는 소모적인 일이 될 것 같으므로 생략하겠다.

이번에는 __SFR_OFFSET을찾아보자. 이 부분은 굳이 보지 않아도 되는 내용이지만 읽어보면 도움은 될

이라고 생각된다.이 매크로는 Atmel의지원해주는 기능에 관련된 내용인데 이 Atmega 프로세서는nomal modecompatibility mode를 지원해 준다. 즉 일반모드와 확장모드를 지원해 준다는 의미이고, 기본적으로 일반모드를사용하게 된다.

#ifndef __SFR_OFFSET

#  if__AVR_ARCH__ >= 100

#   define __SFR_OFFSET 0x00  // 이부분이 확장모드이다

# else

#   define __SFR_OFFSET 0x20  // 이부분이 전용모드이다.

# endif

#endif

결론적으로 __SFR_OFFSET은 일반 모드를 쓰면0x20인 것이다. 그럼 모든 의미를 다 찾아 보았다.

그 중 volatile키워드에 대해 잠시 알아보면 volatile은 휘발성이란 의미를 가지고 있는데 이 키워드를 사용해서 정의한 변수는 그것을 사용하는 문장 외에다른 것에 의해서(운영체제나 하드웨어) 변경될 수 있으므로키워드를 사용해서 정의한 변수는 눈에 보이는 문장만을 상대로 함부로 최적화 시키지 말아하 한다는 것을 의미한다., 함부로 컴파일러가 코드 최적화 시키지 않게 하는 키워드인 것이다.그리고 unit8_t란 변수 타입은unsigned char와 같은 의미를 지닌다.

지금껏 찾은 내용을 소스로 정리를 해 보았다.

//PORTA= 0xff;

//_SFT_IO(0x1B) = 0xff;

//_MMIO_BYTE((0x1B) + __SFR_OFFSET) = 0xff;

//(*(volatile uint8_t *))((0x1B) + __SFR_OFFSET) = 0xff;

//(*(volatileuint8_t *)(0x3B)) = 0xff;

(*(volatile unsigned char *)(0x3B)) = 0xff;

이 소스코드가 각 줄이 동일한 의미를 가진다는 것을 이때까지의 내용을 통해서 이젠 알아 볼 수 있을 것이라고 생각한다.

자 이제 모든 함수헤더를 찾아본 것 같다. 이제까지의 내용을 정리해 보면 DDRx PORTx, PINx는 매크로함수이고, 데이터 타입은 (*(voliatile unsigned char *)이며, 인자를받아서 그 인자를 해당 레지스터에 채워주는 명령인 것이다

+ Recent posts