본문 바로가기
WORK/Sotfware

Atmega128 - AVR CPU core

by KANG Stroy 2008. 7. 17.
728x90
728x90

사용자 삽입 이미지

CPU core의 주기능은 올바른 프로그램 실행을 보장하는 것이다. 이를 위해 CPU는 메모리를 엑세스할 수 있어야 하고, 계산을 수행할 수 있어야 하며, 주변 장치를 제어하고 인터럽트를 다룰 수 있어야 한다.

성능 극대화와 병렬성을 위해서, AVR에서는 Harvard architecture를 사용한다. Harvard architecture에서는 프로그램과 데이터를 위한 별개의 메모리와 버스가 존재한다.

single level pipelining을 이용하여 프로그램 메모리 상의 명령어가 실행된다. 하나의 명령어가 실행되는 동안, 다음 명령어가 프로그램 메모리로부터 pre-fetch된다. 이로 인해 매 클럭 사이클마다 명령어가 실행되는 것이 가능하게 한다. 여기서 말하는 프로그램 메모리는 In-System Reprogrammable Flash memory이다.

fast-access Register file은 32개의 8비트 범용 작업 레지스터(general purpose working registers)를 포함하고 있으며 단일 클럭 내에 레지스터로의 접근이 가능하다.  따라서 단일 클럭내에 Arithmetic Logic Unit (ALU)연산이 가능해진다. 전형적인 ALU 연산에선 두 개의 오퍼랜드가 레지스터 파일로부터 출력된다. 이를 이용한 연산 결과는 다시 레지스터 파일에 저장된다. 이런 과정이 한 클럭 사이클 내에 이루어진다.

사용자 삽입 이미지

32개의 레지스터 중 6개는 데이터 공간을 addressing를 위한 세 개의 16비트 간접 주소 레지스터 포인터로써 사용된다. 효과적인 주소 계산이 가능해진다. 또한, 주소 포인터 중 하나를 플래시 프로그램 메모리상의 look up tables를 위한 주소 포인터로써 사용이 가능하다. ( 16-bit X-register, Y-register, Z-register )

ALU는 다음과 같은 산술, 논리 연산을 지원한다.
단일 레지스터 연산, 레지스터 - 레지스터 연산, 레지스터-상수 연산
산술연산이 일어난 후, 연산의 결과에 대한 정보를 반영하기 위해서 상태 레지스터가 업데이트 된다.

프로그램 흐름은 조건 또는 비조건 점프와 호출 명령어에 의해 제공되어 지며, 전체 주소 공간을 직접 address할 수 있다. 대부분의 AVR 명령어는 단일 16비트 워드 포맷을 가진다. 프로그램 메모리 주소마다 16 또는 32비트의 명령어를 포함한다.

프로그램 플래시 메모리 공간은 두 개의 섹션으로 나누어진다. Boot Program sectionApplication Program section이다. 두 섹션 모두 write와 read/write 보호를 위한 전용 Lock 비트를 가지고 있다. 어플리케이션 플래시 메모리에 기록하는 SPM 명령어는 반드시 Boot Program section내에 있어야 한다.

인터럽트나 서브루틴 호출 동안에 리턴주소에 해당되는 Program Counter(PC)는 스택에 저장된다. 스택은 general data SRAM상에 효율적으로 할당되어 진다. 따라서 스택의 크기는 전체 SRAM의 크기와 SRAM의 사용량에 의해서만 한정된다. 모든 사용자 프로그램은 반드시 reset루틴 내의 SP를 초기화해야 한다 ( 서부루틴이나 인터럽트가 수행되기 전에 ). SP(Stack Pointer)는 I/O 공간에서 read/write 접근하기 쉽다. data SRAM 는 AVR 아키텍처에서 지원하는 5가지 어드레싱 모드를 통해 쉽게 접근할 수 있다.

AVR 아키텍처에서 메모리 공간은 선형이며, 메모리 맵이다.

융통성있는 인터럽트 모듈은 I상태 레지스터상에 추가적인 전역 인터럽트 가능 비트와 함께 I/O 공간에 제어 레지스터를 가진다. 모든 인터럽트는 인터럽트 벡터 테이블 내에 개별적인 인터럽트 벡터를 가진다. 인터럽트는 인터럽트 벡터 위치에 따라 우선순위를 가진다. 낮은 인터럽트 벡터 주소는 우선순위가 높다.

I/O 메모리 공간은 직접 접근가능하거나 또는 데이터 공간 위치로써 64개 주소를 포함한다 (레지스터 파일의 $20-$5F). 추가적으로 Atmega128은 SRAM상에 확장 I/O 공간을 가진다 ($60-$FF). ST/STS/STD와 LD/LDS/LDD 명령어에 의해서만 사용이 가능하다.

ALU . Arithmetic Logic Unit
ALU는 32개의 범용레지스터와 직접적으로 관련되어 동작한다. 단일 클럭 사이클 내에 범용 레지스터 간 또는 레지스터와 상수간의 산술연산이 수행되어진다. ALU동작은 세 가지 카테고리로 나누어진다(arithmetic, logical, and bit-functions). 아키텍처의 일부 구현에서는 부호있는/부호없는 곱셈과 소수형식을 지원하기 위한 곱셈기를 제공한다. See the “"Instruction Set”" section for a detailed description.

Status Register
상태 레지스터는 최근에 실행된 산술명령의 결과에 대한 정보를 가지고 있다. 이 정보는 조건연산을 수행하기 위해서 프로그램의 흐름을 바꾸는데 사용되어 질 수 있다. 상태 레지스터는 모든 ALU연산 후에 Instruction Set Reference에 규정된 것에 따라 업데이트 된다. 많은 경우에 전용 비교 명령어를 사용할 필요성을 제거하게 될 것이다. 그로인해 빠르고 보다 간결한 코드가 된다. 인터럽트 루틴에 들어갈 때 상태 레지스터의 내용이 저장된 후, 인터럽트로부터 돌아올 때 복구되는 것이 자동으로 이루어지지 않는다. 소프트웨어로 처리를 해주어야 한다.

AVR 상태레지스터 SREG는 다음과 같이 정의된다.

사용자 삽입 이미지

• Bit 7 – I: Global Interrupt Enable
인터럽트를 가능하게 하려면  Global Interrupt Enable비트를 반드시 1로 설정해야 한다.
각 인터럽트마다 가능여부를 제어하는 것은  인터럽트별로 있는 컨트롤 제어 레지스터를 통해 이루어진다.  만약에 Global Interrupt Enable 비트가 0으로 클리어되어 있다면, 개별적으로 인터럽트를 가능하도록 할수 없다.  입터럽트가 발생한 후, 하드웨어에 의해서 i비트는 0으로 클리어된다.  다시 인터럽트들을 가능하게 하는 것은  RETI 명령어에 의해서 1로 세트되었을 때이다. 또한 I비트는 the instruction set reference에 씌어진대로  SEI와 CLI명령어를 사용하여 소프트웨어적으로 세트하거나 클리어하는 것이 가능하다.

• Bit 6 – T: Bit Copy Storage
비트 복사 명령어인 BLD(Bit LoaD)와 BST(Bit STore)는 t비트를 조작하는 비트의 source  또는  destination 로써 사용한다.  BST명령에 의해서 레지스터의 한 비트가 t로 복사된다. t비트는 다시 BLD명령에 의해서 레지스터로 복사된다.

• Bit 5 – H: Half Carry Flag
half carry flag H는 산술연산 결과 half carry가 발생한 것을 나타낸다. half carry는 BCD 산술에서 유용하다.
자세한 정보는 "Instruction Set Description" 참조

• Bit 4 – S: Sign Bit, S = NV
S비트는 네가티브 플래그 N과 2의 보수 오버플로우 플래그 V사이의 exclusive or 이다.
자세한 정보는 "Instruction Set Description" 참조

• Bit 3 – V: Two’s Complement Overflow Flag
2의 보수 오버플로우 플래그 V는 2의 보수 계산을 지원한다.
자세한 정보는 "Instruction Set Description" 참조


• Bit 2 – N: Negative Flag
네가티브 플래그 N은 산술 또는 논리 연산의 결과로 음수가 발생한 것을 나타낸다.
자세한 정보는 "Instruction Set Description" 참조

• Bit 1 – Z: Zero Flag
제로 플래그 Z는 산술 또는 논리 연산 결과로 0이 발생한 것을 나타낸다.
자세한 정보는 "Instruction Set Description" 참조

• Bit 0 – C: Carry Flag
캐리 플래그 C는 산술 또는 논리 연산에서 캐리가 발생하는 것을 나타낸다.
자세한 정보는 "Instruction Set Description" 참조

General Purpose Register File
레지스터 파일은 AVR Enhanced RISC instruction set을 위해서 최적화 되어 있다.
요구 성능과 유연성(flexibility)을  얻기위해서 다음과 같은 입출력 scheme이 레비스터 파일에 의해서 제공되어진다.

• One 8-bit output operand and one 8-bit result input
• Two 8-bit output operands and one 8-bit result input
• Two 8-bit output operands and one 16-bit result input
• One 16-bit output operand and one 16-bit result input

아래 그림은 CPU내부에 있는 32개의 범용 레지스터의 구조를 보여준다.
사용자 삽입 이미지
대부분의 명령어들은 모든 레지스터를 직접 엑세스하는 레지스터 파일 상에서 동작한다. 그리고 대부분 한 사이클 명령어들이다. 위 그림상에서 각 레지스터에는 데이터 메모리 주소가  할당되어 있다. 사용자 데이터 공간의 처음 32개의 주소로  매핑된다.

SRAM 주소로써 물리적으로 구현되지는 않았지만, 이 메모리 구조는 레지스터의 접근에 유연성을 제공한다.
X-, Y-, Z-pointer Registers는 레지스터 파일상의 어떤 레지스터도 인덱스로  설정할 수 있다(?)

X-register, Y-register, and Z-register
R26..R31 레지스터들은 추가된 기능을 갖고있다. 이 레지스터들은  데이터 공간에 대한 간접 어드레싱을 위한 16비트 주소 포인터이다. 세개의 간접 주소 레지스터인 X, Y, Z를 아래 그림으로 표현하였다.
다른 어드레싱 모드에서 이들 주소 레지스터는 고정된 변위, 자동 증가, 자동 감소로써의 기능을 한다.

자세한 것은 Instruction Set Reference을 봐라.
사용자 삽입 이미지


Stack Pointer
스택은 대부분 임시 데이터 또는 지역변수를 저장하거나  인터럽트, 서브루틴 호출 후 복귀 주소를 저장하기 위해 사용되어 진다. 스택 포인터 레지스터는 스택의 최상단을 항상 가리킨다. 스택이 높은 메모리 주소에서 낮은 주소 메모리로 커지도록 구현되었다는 것에 유의하라. 스택의 PUSH 명령은 스택 포인터가 감소하는 것을 의미한다.

The Stack Pointer points to the data SRAM stack area where the Subroutine and Interrupt
Stacks are located. 서브루틴 호출이 실행되거나 인터럽트가 가능해지기 전에 프로그램에 의해서 data SRAM에 스택 공간이 정의되야 한다. 스택 포인터는 $60이상의 주소를 가리키도록 설정되어야 한다. PUSH 명령으로 스택에 데이터가 넣어질 때, 스택포인터는 1이 감소한다. 서브루틴 호출이나 인터럽트로 스택에 복귀 주소가 들어갈때에는 2가 감소한다.  POP명령으로 스택으로 부터 데이터가 꺼내딜때, 스택 포인터는 1이 증가한다.  서브루틴의 RET 또는 인터럽트의 RETI명령으로 복귀할때, 스택으로 부터 복귀주소가 꺼내질 때, 2가 증가한다.

AVR 스택 포인터는 I/O공간에 2개의 8비트 레지스터로 구현되었다. 실제 사용되는 비트 수는 구현에 따라 다르다. AVR의 아키텍처 일부 구현에서는 데이터 공간이 너무 작아서 오직 SPL만 필요하고 SPH는 필요 없는 경우도 있다.
사용자 삽입 이미지

RAM Page Z Select Register – RAMPZ
사용자 삽입 이미지

• Bits 7..1 – Res: 예약된 비트들
예약된 비트들로 해당 비트들을 읽으면 항상 0으로 읽혀진다. 이 주소 위치로 쓰기를 할때, 나중에 사용할 장치와의 호완성을 위해 이 비트들은 0으로 쓰기를 해야 한다.

• Bit 0 – RAMPZ0:  Extended RAM Page Z-pointer
RAMPZ 레지스터는 어느 64K RAM 페이지가 Zpointer에 의해서 접근될지를 선택하는데 사용되어 진다. Atmega128은 64K 이상의 SRAM 메모리를 지원하지 않는다. 이 레지스터는 ELPM/SPM 명령어가 사용될 때, 프로그램 메모리의 어느 페이지에 접근할지를 선택하는데 사용된다.

RAMPZ0의 다른 세팅의 결과는 다음과 같다.
RAMPZ0 = 0: 프로그램 메모리 주소 $0000 - $7FFF (하위 64K bytes)가 ELPM/SPM에 의해서 접근된다.
RAMPZ0 = 1: 프로그램 메모리 주소 $8000 - $FFFF (상위 64K bytes)가 ELPM/SPM에 의해서 접근된다.

LPM은 RAMPZ 세팅의 영향을 받지 않는다는 것을 주의..


명령어 실행 타이밍
명령어 실행을 위해서 일반적인 접근 타이밍 개념에 대해서 기술한다.

AVR CPU는 선택된 클럭 소스로부터 생성된 clkCPU(CPU 클럭)에 의해서 동작한다.
내부 클럭 분할이 사용되지 않는다.

아래 그림은 병렬 명령어 fetch와 명령어 실행을 보여주는 데,  하바드 아키텍처와  fast-access Register file 개념에 의해서 가능하다.  이것은 1 Mhz당 1MIPS를 얻기 위한 기본적인 pipelining개념이다. 비용, 클럭, 전원단위 대비 일정한 결과를 내놓도록 하기 위함이다.=='

This is the basic pipelining concept to obtain up to 1 MIPS per MHz with the corresponding unique results for functions per cost, functions per clocks, and functions per power-unit.

사용자 삽입 이미지

아래 그림은 레지스터 파일을 위한 내부 타이밍 개념을 보여준다. 한 클럭 사이클내에서 ALU 연산은 두개의 레지스터 오퍼랜드를 사용하여 실행되어진다. 그리고 그 결과는 다시 목적지 레지스터에 저장된다.
사용자 삽입 이미지


리셋과 인터럽트 핸들링
AVR은 여러 개의 다른 Interrupt source를 제공한다. 인터럽트들과 개개의 리셋벡터는 각각 개별적인 프로그램 벡터를 프로그램 메모리 공간내에 가진다. 모든 인터럽트들은 개별적인 인터럽트 가능 비트를 할당받는다.  특정 인터럽트를 가능하게 하려면, 특정 인터럽트 가능 비트와 상태 레지스터에 있는  전역 인터럽트 가능 비트가 모두 1로 기록되어야 한다.
 
프로그램 카운터 값에 따라 ,  Boot Lock 비트인 BLB02 또는 BLB12가 프로그램되어 있을 때, 인터럽트들은 자동으로 비활성화 될것이다. 이 특징은 소프트웨어 보안을 향상시킨다. 자세한 내용은 데이터 시트 286페이지 " 메모리 프로그래밍"을 참조

기본적으로 프로그램 메모리 공간에서 최하위 주소는 리셋과 인터럽트 벡터로 정의되어 있다.  모든 벡터  목록은 60페이지 "인터럽트"에서 볼 수있다.   리스트는 서로 다른 인터럽트들의 우선순위 수준을  결정한다. 최하위 주소에 있는 벡터는  최상위 주소에 있는 벡터에 비해  우선순위가 높다.

RESET는 가장 높은 우선순위를 가진다. 그 다음이 INT0(=the External Interrupt Request
0)이다.  MCU 제어 레지스터(MCUCR)에 있는 IVSEL 비트를 세팅함으로써 부트 플래시 섹션의 시작위치로 인터럽트 벡터를 이동시킬 수 있다.  보다 자세한 정보는 60페이지의 "인터럽트"를 참조. BOOTRST 퓨즈를 프로그래밍하여 리셋 벡터도 부트 플래시 섹션의 시작위치로 이동시킬 수있다. 이에 대한 내용은 273페이지  “Boot Loader Support – Read-While-Write Self-Programming”를 참조

인터럽트가 발생하면, 전역 인터럽트 가능 I-비트는 0으로 클리어되고 모든 인터럽트는 비활성화 된다.  중첩 인터럽트를 가능하게 하기위해 유저 소프트웨어는 I-비트에 1을 기록할 수 있다.  모든 인터럽트가 가능한 상태가 된 상태로 변경된후, 다른 인터럽트가 발생하면 모든 인터럽트를 비활성화 시킨 후,  현재 인터럽트 루틴은 중지되고 해당 인터럽트를 처리하게 된다. 인터럽트에서  복귀하는  명령어  RETI가 실행되면 I-비트는 자동으로 1로 설정된다.

기본적으로 2가지 형태의 인터럽트가 있다.
첫번째 형태는 이벤트에 의해서 트리거되는 것이다.( 인터럽트 플래그가 세트된다. )
인터럽트 핸들러 루틴을 실행하기위해서 프로그램 카운터는 실제 인터럽트 벡터의 주소를 가지게 된다.  그리고 하드웨어는 대응되는 인터럽트 플래그를 클리어한다. 인터럽트 플래그는 클리어된 플래그 비트 위치에 1을 기록함으로써 클리어 될 수도 있다. 대응하는 인터럽트 가능  비트가 클리어된 상태에서 인터럽트가 발생하면, 인터럽트 플래그는 세팅되고 인터럽트가 가능해질 때 까지 기억하고 있거나 소프트웨어에 의해서 해당 플래그가 클리어된다. 마찬가지로 전역 인터럽트 가능비트가 클리어된 상태에서 하나 이상의 인터럽트가 발생하면 대응되는 인터럽트 플래그는 세팅되고 전역 인터럽트 가능 비트가 세트될때 까지 기억하게된다. 그리고 우선순위에 따라 실행된다.

두번째 형태는 인터럽트 상태가 존재하는 동안에만 트리거가 일어나 인터럽트 플래그가 세트되는 것이다. 이런 인터럽트는 인터럽트 플래그를 가지고 있을 필요가 없다. 인터럽트가 가능해지기 전에  인터럽트 상태가 사라지면, 인터럽트는 트리거되지 않는다.

인터럽트 루틴으로부터 돌아오면, 대기중인 인터럽트를 처리하기 전에  항상 메인 프로그램으로 리턴되어 다음 명령어를 실행한다.

인터럽트 루틴으로 들어갈 때, 상태 레지스터가 자도으로 저장되지 않으며,  인터럽트 루틴으로 부터 돌아올때 자동으로  상태 레지스터가 이전값으로 복귀되지 않는 다는 것을 주의해야 한다. 소프트웨어적으로 반드시 처리해주어야 하는 부분이다.

인터럽트를 비활성화 하기 위해서 CLI명령어를 사용하면, 인터럽트는 바로 비활성화된다.
CLI명령어가 실행된 후, 어떤 인터럽트도 실행되지 않는다. CLI명령어와 동시에 발생한 인터럽트일지라도 무시된다. 다음 예제는 EEPROM에 쓰기를 하는 동안에 어떻게 인터럽트를 회피하는지를 보여준다.
사용자 삽입 이미지

인터럽트가 가능하도록 SEI 명령어를 사용하면, 대기중인 인터럽트를 처리하기전에 sei  다음 줄에 있는  명령어를 실행하게 된다. 
사용자 삽입 이미지


인터럽트  응답 시간
모든 가능한 avr 인터럽트에 대한 인터럽트 실행 응답은 최소 4 클럭 사이클이다. 4클럭 사이클 이후에,  실제 인터럽트 핸들러를 위한 프로그램 벡터 주소가 실행된다.
4 클럭 사이클 기간동안, 프로그램 카운터는 스택 안에 들어가게 된다.  벡터는 일반적으로 인터럽트 루틴으로 점프하는데  이 점프는 3클럭이 걸린다.  멀티 사이클 명령어가  실행되는 동안  인터럽트가 발생하면, 인터럽트를 처리하기 전에 이 명령어는 완료된다. MCU가 슬립모드일 때 인터럽트가 발생하면 인터럽트 실행 응답 시간은 4 클럭 사이클정도 증가한다.  선택된 슬립모드로부터 start-up 시간이 추가된 것이다.

인터럽트 핸들러 루틴으로부터 리턴하는데 4클럭 사이클이 걸린다. 이 4클럭 사이클동안에  프로그램 카운터(2바이트)는 스택에서 꺼내지게 된다. 그리고  스택 포인터가 다음 명령어를 가리키기 위해  2바이트 증가된다. 그리고 SREG레지스터의 I비트가 세팅된다.
728x90

'WORK > Sotfware' 카테고리의 다른 글

CodevisionAVR #pragma  (2) 2008.07.17
AVR ASM 요약..  (0) 2008.07.17
volatile 키워드  (0) 2008.07.17
pragma에 관한 사용법  (0) 2008.07.17
AVR 90s8535  (0) 2008.07.15

댓글