Arquitetura e modos de endereçamento do AVR ATmega88 |
Este documento apresenta um resumo da arquitetura do microcontrolador AVR ATmega88 da Atmel e mostra algumas semelhanças e diferenças entre os modos de endereçamento do AVR e do Intel 8086. Pode, no entanto, ser lido sem conhecimento prévio da arquitetura do 8086.
Uma boa introdução à arquitetura do AVR ATmega88 encontra-se na seção "Architectural Overview" do datasheet manual, pgs 3 - 18. Leia-o após esta introdução. Por ter uma arquitetura RISC, todas as instruções do AVR ATmega88 possuem o mesmo tamanho, 16 bits, com exceção das instruções de endereçamento direto, LDS e STS que ocupam 32 bits. Um ponto importante a ressaltar é que, além da arquitetura RISC, a arquitetura dita Harvard dos microcontroladores AVR possui internamente barramentos separados para acessar instruções (16 bits) e para acessar dados (8 bits). Esses espaços distintos de endereçamento são chamados de área de programa ou de instruções (read only) e área de dados (read/write), permitindo uma eficiência maior, pois instruções podem ser lidas em paralelo com o acesso a dados. Uma instrução especial (LPM) permite ler dados (constantes) armazenados na área de programa.
O tamanho do espaço de endereçamento (*) de instruções é de 64K instruções (128 KB) (**); como o espaço de instruções também pode ser usado para armazenar dados é possível endereçar até 64KB (2**16 bytes) de dados na área de programa; o tamanho do espaço de dados é também 64KB, porém a capacidade física do modelo ATmega88 é muito menor do que os valores acima, apenas 8KB para instruções (4K instruções de 16 bits cada) e 1024 + 32 bytes para dados, incluindo os registradores de propósito geral. Dependendo do modelo da família AVR de 8 bits, a capacidade física da memória de programa (FLASH) pode chegar a 64K instruções e a memória de dados (Static RAM) a 8KB. Você pode consultar uma tabela com as diversas capacidades de memória e de recursos de E/S da família AVR neste link.
Os 32 registradores de propósito geral (acumuladores), denotados R0 a R31
também podem ser endereçados pelas primeiras 32 posições da memória RAM.
A notação Rr no datasheet e no manual do montador
refere-se a um deles como operando fonte
de uma instrução e Rd como operando destino. Além disso os pares de registradores
(R26, R27), (R28, R29) e (R30, R31) podem ser usados como apontadores de 16 bits (indexadores)
e são chamados respectivamente de X, Y e Z. Este recurso é inestimável para operar
com vetores e na implementação do compilador C para a família AVR.
O registrador de estado (SREG), o apontador para pilha (o par SPH,SPL), e vários outros
registradores para contrôle de E/S e de interrupções encontram-se nas 64 posições
seguintes da memória RAM (endereços 0x20-0x5F), que constituem o espaço de E/S;
elas são acessíveis diretamente através das instruções de entrada e saída in e out,
que tomam como operando um valor de 0 a 0x3F (63)
ou seja, o operando é um endereço no espaço de E/S e este endereço é
denominado Port (Porta, em portuguës).
A fim de suportar mais periféricos de E/S as 160 posições seguintes
constituem o "conjunto estendido de registradores de E/S"; os 1024 bytes seguintes
começando no endereço 0x100 constituem a memória RAM para dados (Static RAM).
Em resumo, os registradores de propósito geral R0 a R31, as 64 portas de E/S e os
160 registradores de E/S estendida estão mapeados, nesta ordem,
no espaço de dados do AVR conforme mostra a figura 5-3 pg. 17 do datasheet
e, portanto, também podem ser endereçados através das instruções de acesso
à memória RAM LDS, LD, STS e ST.
Os mapa das memórias de programa e de dados podem ser vistos nas páginas 16 e 17 do datasheet.
Veja neste link um mapa dos registradores de E/S
(distribuído em aula) do modelo ATmega88.
As instruções de chamada de subrotina e as interrupções utilizam um par de registradores localizado no espaço de E/S (SPH,SPL, endereços 0x3E e 0x3D) como apontador de pilha, localizada usualmente no final da memória RAM, para armazenar (empilhar) o endereço de retorno da subrotina (ou da instrução interrompida). Obviamente, o par SPH,SPL deve ser inicializado antes de qualquer chamada de subrotina ou habilitação de interrupções.
(**)O registrador PC (Program Counter) contém o endereço a nível de 16 bits da próxima instrução e seu tamanho varia conforme o modelo do AVR, de 10 bits (1K instruções) a 16 bits (64K instruções), (são 12 bits no ATmega88). As instruções IJMP e ICALL (presentes em todos os modelos) permitem saltar (ou chamar uma subrotina) usando um endereço de 16 bits contido no par Z, o que nos permite concluir que o tamanho do espaço lógico de endereçamento de instruções é de fato 128 KB.
Há modelos mais avançados, que permitem estender os espaços de programa e de dados além dos limites de 128KB e 64KB, através de registradores de páginas (localizados no espaço de E/S). Ao nosso ver, se a sua aplicação requer tanta memória é preferível partir diretamente para os microcontroladores de 32 bits da família ARM (pois a programação de aplicções que requerem memória paginada é extremamente complexa).
São semelhantes ao MOV do 8086, porém com vários (infelizmente) mnemônicos especializados (*):
Instrução | Efeito |
---|---|
MOV Rd, Rr | Rd := Rr |
MOVW Rd+1:Rd, Rr+1:Rr | Rd+1:Rd := Rr+1:Rr Exs: MOVW X,Z MOVW R25:R24, R17:R16 |
LD Rd, W | Rd := [W] Obs: W = X, Y ou Z |
LD Rd, W+ | Rd := [W], W := W + 1 W+ significa: pós-decrementação |
LD Rd, -W | W := W - 1, Rd := [W] -W significa: pré-decrementação |
ST W, Rr | [W] := Rr |
ST W+, Rr | [W] := Rr, W := W + 1 |
ST -W, Rr | W := W - 1, [W] := Rr |
LDD Rd, W'+q | Rd := [W' + q] , 0 ≤ q ≤ 63 Obs: (i) não altera W' (ii) W' = Z ou Y |
STD W'+q, Rd | [W' + q] := Rd , 0 ≤ q ≤ 63 Obs: (i) não altera W' (ii) W' = Z ou Y |
LDS Rd,end | Rd := [end] Endereçamento direto à RAM: end tem 16 bits e a instrução 32 bits |
STS end, Rd | [end] := Rd Endereçamento direto à RAM: end tem 16 bits e a instrução 32 bits |
LPM | R0 := [Z] onde o byte apontado por Z está na região de instruções |
LPM Rd, Z | Rd := [Z] byte apontado por Z na região de instruções |
LPM Rd, Z+ | Rd := [Z] , Z := Z +1 byte apontado por Z na região de instruções, pós-decrementa Z |
LDI Rd, K | Rd := K, 16 =< Rd <= 31, 0 =< K <= FF Armazena em Rd a constante de 8 bits K |
(*)O montador do AVR também aceita mnemônicos de instruções, de registradores e constantes em letras minúsculas.
com sinal | sem sinal | |||
---|---|---|---|---|
operação | 8086 | AVR | 8086 | avr |
= | je (jz) | breq | je (jz) | breq |
!= | jne (jnz) | brne | jne (jnz) | brne |
< | jl | brlt | jb | brlo |
<= | jle | na | jbe | na |
>= | jge | brge | jae | brsh |
> | jg | na | ja | na |
(*) Bits dos registradores do AVR são numerados de 0 a 7 a partir do menos significativo (mais à direita). Eles podem ser lidos/modificados/testados através do grupo de instruções Bit and Bit-test instructions no resumo de instruções distribuído em aula.
(**) Suponha a instrução: brge longe onde o endereço longe esteja fora do intervalo permitido. Você deverá substituir essa instrução por: brlt perto rjmp longe perto: ... ; instrução seguinte à da original, brle longe ... ... longe:
SUBI Rd,-K ; para fazer o efeito de ADDI Rd, K - inexistente (*)
Exemplos: adiw z, $20 sbiw x, $30 adiw r25:r24, 63
.macro addi ; macro toma como paâmetros (Rd, K) subi @0, -(@1) ; onde @0=Rd e @1=K .endmacro e poderia ser invocada, por exemplo, assim: addi r16, 64
eor Rd, Rd ; ou exclusivo de um bit com ele mesmo zera o bit ser Rd ; 16 <= Rd <=31 instrução é sinônimo para: ldi Rd, $ff
or Rd, Rr ori Rd, constante ; 16 <= Rd <=31 out Porta, Rr sbi Porta, b ; 0 <= Porta <= 31 e b= 0,1,...,7Obs: liga (torna 1) os bits do 1º operando que estão ligados no 2º operando (usualmente chamado de máscara); não muda os outros bits do 1º operando.
and Rd, Rr andi Rd, constante ; 16 <= Rd <=31 out Porta, Rr cbi Porta, b ; 0 <= Porta <= 31 e b= 0,1,...,7Obs: desliga (torna 0) os bits do 1º operando que estão desligados no 2º operando (usualmente chamado de máscara); não muda os outros bits do 1º operando.
sbrc Rr, b ; salta a próxima instrução se o bit b (0 <= b <= 7)do reg Rr estiver desligado ; em geral a próxima instrução é um salto incondicional (rjmp) sbrs Rr, b ; salta a próxima instrução se o bit b do reg Rr estiver ligado sbic Porta, b ; salta próxima instrução se o bit b da Porta estiver desligado sbis Porta, b ; salta próxima instrução se o bit b da Porta estiver ligado brts rótulo ; desvia para rótulo se o bit T (do reg de estado) estiver ligado brtc rótulo ; desvia para rótulo se o bit T (do reg de estado) estiver desligado outras: brcs, brcc, brvs, brvc
Existe uma instrução especial na mesma categoria, SWAP Rd que faz o giro de 4 bits do registrador Rd, tendo como efeito, portanto, a troca dos 4 bits menos sigificativos com os 4 bits mais significativos de Rd. Nesta instrução o CY não é afetado.
(*) Lembrete: o bit mais à direita de um registrador é o bit 0 e o mais à esquerda é o bit 7, ou seja, nesta ordem: b7, b6, ..., b1, b0