Introdução aos sistemas embebidos
Introdução
i) Modos de endereçamento PIC 16C54
Instruções sempre com 12 bits
•
•
•
imediato
movlw
k
; com 0 <= k <= 255
movlf
k, f
; 0<= f <= 31
; é no entanto impossível (não existe) pois na instrução não existe o
; campo f para indexar o ficheiro de registos.
; Uma solução com 2 instruções (a ultima directa), será:
movlw
movwf
k
f
; implicita
; directa
directo (ou sobre o ficheiro de registos orientada ao byte)
movf
f, d
; se d=0 ou W -> para acumulador ou Wreg
; se d=1 ou F -> mantém no mesmo registo f (mas
testa a flag Z (Z=0 sse conteúdo de f=0)
movwf
f
; W -> f
incf
f, d
; se d=0 ou W -> Wreg = f +1
; se d=1 ou F -> f = f +1
incfsz
f, d
; idêntico ao anterior mas se resultado = 0 salta a próxima instrução
directo (ou sobre o ficheiro de registos orientada ao bit)
Soluções guia prático 1 - 1
Introdução aos sistemas embebidos
Não é possível operar sobre o acumulador, pois não tem o campo d.
As operações possíveis são apenas:
7
•
bcf
bsf
f, b
; o bit b do registo f é colocado a zero
a um
btfsc
btfss
f, b
; se o bit b do registo f é 0 salta a próxima instrução
1
0
f reg
indirecto
Idêntico ao directo, mas se for usado o registo
INDF, o acesso é efectuado ao registo fxx,
onde 0 <= xx <= 31 é dado pelo valor do
registo FSR.
acesso aos registos f10 (16), f11(16) ...:
movlw 0x10
movwf FSR
; implicito
; directo
w<- 0x10
FSR<- W
movwf INDF
movf INDF, W
; indirecto
; indirecto
f10(16)<-W
W<-f10(16)
incf
FSR, F
movf INDF, W
; directo FSR->f0x11
; indirecto W<-f11(16)
O registo f0 ou INDF não existe fisicamente. Se em FSR for indexado este, i.e. FSR = 0, na leitura é
lido 0 e a escrita corresponde a NOP.
ii) Comprimento das instruções
Instruções que mexem no PC demoram 2 ciclos. As restantes apenas um.
Exemplos:
goto
call
return
incfsz
Soluções guia prático 1 - 2
i.e.
retlw 0
e semelhantes instruções condicionais, se a condição fôr verdadeira
isto é se fôr saltada a próxima instrução.
Introdução aos sistemas embebidos
iii) Registo de Status
o registo de STATUS é actualizado pelas instruções por cada instrução:
iv) Definição de constantes
Temp
EQU 0x10
É equivalente à directiva do pr-processador C
#define Temp
0x10
De modo que antes de se iniciar o assembler todas as ocorrências de Temp são substituídas por
0x10.
E útil para dar nomes a constantes, que podem ser utilizadas no modo de endereçamento imediato,
ou a registos.
Soluções guia prático 1 - 3
Introdução aos sistemas embebidos
1. a. / b.
Comparação por subtracção para números positivos:
PIC não tem instruções nativas para este efeito. Uma forma de verificar se um numero é maior que
o outro é:
F–W
se W maior que F, o resultado é negativo e a carry flag do registo STATUS é tem o
valor 1. Se W menor ou igual a F, C=1.
(Para ver se é igual deve-se testar a flag zero, que é seleccionada se o resultado de
uma operação fôr zero. (Z = 1))
Para testar a flag C (Z) e saltar a próxima instrução se igual a 0 (ou 1):
btfsc
btfss
STATUS, C
STATUS, C
(Z)
(Z)
Uma solução que usa esta técnica é apresentada a seguir:
Solução 1:
; the example considers an array of 6 unsigned integer elements
; for testing with 16 elements change the value N_ELEMENTS to 16
LIST P=16C54
#INCLUDE "P16C5x.INC"
N_ELEMENTS
equ d'6' ; number of array elements
MIN
equ B'00000000'
REG_BEGIN equ d'12'
REG_END equ REG_BEGIN+N_ELEMENTS
max
equ d'10'
address equ d'11'
org 0x000
movlw
movwf
movlw
movwf
movlw
movwf
movlw
movwf
movlw
movwf
movlw
movwf
d'10'
REG_BEGIN
d'11'
REG_BEGIN+1
d'12'
REG_BEGIN+2
d'13'
REG_BEGIN+3
d'14'
REG_BEGIN+4
d'2'
REG_BEGIN+5
call max_array
nop ; used for simulation: to insert a breakpoint
;loop goto loop ; another way to stop here
Soluções guia prático 1 - 4
Introdução aos sistemas embebidos
max_array
; set the address to the first array element
movlw REG_BEGIN
movwf address
movwf FSR
; set max to minimum
movlw MIN
movwf max
next
movlw REG_END
subwf address, W
btfsc STATUS, Z
goto end_loop
movf INDF, W
subwf max, W
btfsc STATUS, C
goto inc
movf INDF, W
movwf max
inc
incf address
incf FSR
goto next
end_loop
return
END
Comprimento do código:
Comprimento do código para a rotina max_array:
32 instruções de 12 bits. (6 elementos)
19 instruções de 12 bits.
O número de ciclos de relógio pode variar dependendo das vezes que fôr necessário actualizar o o
valor do máximo. Assim o mínimo número de ciclo de relógio é dado quando o primeiro elemento
do array é o maior positivo, isto é 127, e o máximo quando os elementos do array formam uma
sucessão crescente.
Tempo de execução em ciclos de relógio (para 6 elementos):
mínimo:
104
máximo:
109
Outra solução possível optimizando um pouco o código anterior.:
Solução 2:
A técnica usada para endereçar o ficheiro de registo é idêntica à da solução anterior, e usa os
registos apresentados a seguir. O ficheiro de registos desde baseadr até baseadr+dim-1, guarda o
vector de números positivos, sendo utilizado INDFe FSR para o indexar:
Soluções guia prático 1 - 5
Introdução aos sistemas embebidos
counter
FSR
max
baseadr
.
:
baseadr+dim-1
Isto é, por exemplo:
movf
INDF, W
W
<-
baseadr [FSR]
Constantes utilizadas:
minimum
mínimo, por defeito 0.
dim
dimensão do array, por defeito 6.
Registos:
baseadr
max
counter
Registo que guarda o primeiro elemento do array
Registo que guarda o elemento máximo do array
Registo utilizado como contador para indexar o array de registos desde baseadr até
baseadr-1
list
p=16c54
#include <p16c5x.inc>
; list directive to define processor
; processor specific variable definitions
__CONFIG
_CP_OFF & _WDT_ON & _RC_OSC
; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.
ORG
goto
;CONSTANT DEFINITIONS
temp0
EQU
temp1
EQU
temp2
EQU
temp3
EQU
temp4
EQU
temp5
EQU
;Minimum value allowed
minimum
EQU
0x1FF
start
0x04
0x00
0x47
0x47
0x77
0x00
; processor reset vector
;example
;example
;example
;example
;example
;example
B'00000000'
variable
variable
variable
variable
variable
variable
definition
definition
definition
definition
definition
definition
;Binary
;FILE REGISTER ARRAY INIT ADR AND DIMENSION and maximum value returned
baseadr
EQU
0x10
;Hexa
dim
EQU
d'6'
;decimal
max
EQU
baseadr-1
Soluções guia prático 1 - 6
Introdução aos sistemas embebidos
;LOAD ARRAY INTO FILE REGISTER
start
ORG
0x000
movlw
temp0
movwf
baseadr
movlw
temp1
movwf
baseadr+1
movlw
temp2
movwf
baseadr+2
movlw
temp3
movwf
baseadr+3
movlw
temp4
movwf
baseadr+4
movlw
temp5
movwf
baseadr+5
wait
call
goto
maximum
wait
;SUB-ROUTINE FIND MAXIMUM IN ARRAY: baseadr[dim] (only unsigned numbers)
;Destroy registers: counter and max
;
;At exit max register holds maximum value of array
;
counter
EQU
baseadr-2 ;COUNT TO END OF ARRAY
maximum
movlw minimum
movwf max
; initialize max to minimum value allowed
; or simply: "clrf
movlw dim
movwf counter
movlw baseadr
movwf FSR
loop
movf INDF, W
subwf
max, W
btfsc STATUS, C
goto
max"
if minimum=0
;initialize counter to array dimension
;put baseadr in FSR indirect register
;
;
;
;
;
;
Compare fx with max (unsigned only)
positivos i.e. 0 <= n <= 12
W <- baseadr[FSR]
max - W
if W > max jump (if carry=0 no
actualization of max)
inc
movf INDF, W
movwf max
; if fx greater: max <- fx
incf FSR
decfsz
goto loop
; move to next element in array
inc
counter
return
END
; directive 'end of program'
Comprimento do código:
Comprimento do código para a rotina maximum:
29 instruções de 12 bits. (6 elementos)
16 instruções de 12 bits.
Soluções guia prático 1 - 7
Introdução aos sistemas embebidos
Tempo de execução em ciclos de relógio (para 6 elementos):
mínimo
76
máximo
81
Embora o número de instruções seja apenas de menos 3 que no caso anterior, como o comprimento
de cada iteração é reduzido (em termos de instruções), o número de ciclos de relógio também é
reduzido.
De notar que tanto nesta solução como na anterior a diferença de ciclo de relógio entre o caso
máximo e mínimo é igual ao número de elementos do array menos um:
Ciclos (máx) - Ciclos (min) = dim -1 = 5
Como o número de iterações é igual ao número de elementos, concluí-se que só uma instrução a
mais é executada em cada iteração, que é precisamente a instrução que actualiza o registo que
guarda o valor do elemento máximo.
A análise de tempo é importante principalmente em sistemas de tempo real, pois nestes o tempo de
execução tem de ser previsível, de modo que os processos se executem dentro de metas temporais
previamente definidas.
Neste caso a rotina não funciona em tempo constante, se bem que sejam possíveis soluções em
tempo constante. Quando o tempo de execução não é constante, deve-se fazer uma análise de pior
caso, determinando o tempo máximo.
1. c. / d.
Para generalizar as soluções anteriores para números com sinal, pode-se utilizar duas técnicas. A
primeira consiste em verificar a flag de Sinal, S, e de Overflow, O:
Se
S xor O == 1 A < B
Senão
A >= B
Se o processador não disponibilizar no registo de STATUS a flag de Overflow esta pode ser obtida
com o bit de carry que entra no BMS e o que saí, isto é a flag Carry.
O = carry_in XOR carry_out
Assim para o pic pode-se usar o algoritmo:
OVERFLOW = carry_in XOR carry_out
Se
OVERFLOW XOR SIGNAL(A-B) == 1
Senão A >= B
A<B
Solução 1:
Modificando a Solução 1 da alínea anterior segundo esta técnica, também para arrays com 6
elementos, têm-se:
Soluções guia prático 1 - 8
Introdução aos sistemas embebidos
LIST P=16C54
#INCLUDE "P16C5x.INC"
N_ELEMENTS
MIN
REG_BEGIN
REG_END
max
address
sub_res
aux1
equ
equ
equ
equ
equ
equ
equ
equ
d'6'
B'10000000' ; minimum integer value
d'12'
REG_BEGIN+N_ELEMENTS
d'10'
d'11'
d'9'
d'8'
org 0x000
movlw d'127'
movwf REG_BEGIN
movlw -d'1'
movwf REG_BEGIN+1
movlw d'12'
movwf REG_BEGIN+2
movlw d'15'
movwf REG_BEGIN+3
movlw d'78'
movwf REG_BEGIN+4
movlw d'100'
movwf REG_BEGIN+5
call
loop
max_array
goto loop
max_array
; set
movlw
movwf
movwf
; another way to stop in this position
the address to the first array element
REG_BEGIN
address
FSR
; set max to minimum
movlw MIN
movwf max
next
movlw
subwf
btfsc
goto
REG_END
address, W
STATUS, Z
end_loop
; do the subtraction max-R[i]
movf INDF, W
subwf max, W
movwf sub_res
; test the output carry/borrow of subtraction
clrw
btfsc STATUS, C
movlw 0x80
; if it is ONE
xorwf sub_res, F ; xor carry with signal of subtraction
;test
rlf
movwf
rlf
the input carry/borrow in the MSB of subtraction
max, W
aux1
INDF, W
Soluções guia prático 1 - 9
Introdução aos sistemas embebidos
subwf aux1, W
clrw
btfsc STATUS, C
movlw 0x80
xorwf sub_res, F
; if it is ONE
btfss sub_res, 7
goto inc
movf INDF, W
movwf max
inc
incf
incf
goto
address
FSR
next
end_loop
return
END
Comprimento do código:
Comprimento do código para a rotina max_array:
45 instruções de 12 bits. (6 elementos)
32 instruções de 12 bits.
Tempo de execução em ciclos de relógio (para 6 elementos):
mínimo
182
máximo
187
São necessárias mais 13 instruções na sub-rotina max_array. Claro que o limite máximo e mínimo
de tempo de execução também aumenta, no entanto a diferença permanece igual, 5 ciclos, o que
indica que a diferença entre os dois casos continua a ser a actualização do elemento máximo.
Solução 2:
Pode-se tentar outra abordagem verificando o sinal de ambos os números. Assim quando o sinal de
ambos os números fôr igual, mesmo que seja negativo, pode-se testar de acordo com a técnica da
alínea a.. Os números negativos em complemento para dois são dados por:
Módulo + número negativo
para o caso de registos de 8 bits tem-se:
Módulo (8 bits) =
28 = 256
256
256
256
= 255
= 254
= 253
0xFF
0xFE
0xFD
B'11111111'
B'11111110'
B'11111101'
(-127) = 129
(-128) = 128
0x81
0x80
B'10000001'
B'10000000'
= 127
=0
0x7F
0x00
B'01111111'
B'00000000'
+
+
+
(-1)
(-2)
(-3)
(...)
256 +
256 +
positivos:
Soluções guia prático 1 - 10
Introdução aos sistemas embebidos
Deste modo, por exemplo:
2<3
2 - (+3) = -1 = FF
(Carry = 0)
3>2
3 - (+2) = 1
(Carry = 1)
-3 < -2
-3 - (-2) = -1 = FF
(Carry = 0)
-2 > -3
-2 - (-3) = 1
(Carry = 1)
O que significa que a única alteração que deve ser efectuada na Solução 2 da alínea a., é verificar
primeiramente, se os sinais do elemento corrente e do máximo são diferentes, de modo que o novo
máximo seja o positivo.
Além das alterações à rotina maximum é utilizado mais um registo do ficheiro para algumas
operações aritméticas, principalmente devido às operações sobre bits e rotação não poderem ser
efectuadas no acumulador.
;SUB-ROUTINE FIND MAXIMUM IN ARRAY: baseadr[dim]
;Destroy registers: counter, aux, max
;
;At exit max register holds maximum value of array
;
counter
EQU
baseadr-2 ;COUNT TO END OF ARRAY
aux
EQU
baseadr-3 ;AUX ARITHMETIC F REGISTER
maximum
movlw minimum
movwf max
; initialize max to minimum value allowed
movlw
movwf
movlw
movwf
dim
counter
baseadr
FSR
;initialize counter to array dimension
movf
movwf
movf
xorwf
btfss
goto
max, W
aux
INDF, W
aux, F
aux, 7
equal
;put baseadr in FSR indirect register
loop
;test sign (bit 7)
; W <- baseadr[FSR]
;if equal sign then bit7 = 0
;goto equal
diff
btfsc max, 7
goto actual
goto inc
;if max negat. then fx posit. (and greater)
;goto actual
;else no actualization needed
movf INDF, W
subwf max, W
btfsc STATUS, C
;compare fx with max (unsigned numbers)
; W <- baseadr[FSR]
;max - W
;if W > max jump (if carry=0 no
;actualization of max)
equal
goto
inc
Soluções guia prático 1 - 11
Introdução aos sistemas embebidos
actual
movf INDF, W
movwf max
; if fx greater: max <- fx
inc
incf FSR
decfsz counter
goto loop
; move to next element in array
return
Comprimento do código:
Comprimento do código para a rotina maximum:
37 instruções de 12 bits. (6 elementos)
24 instruções de 12 bits.
Tempo de execução em ciclos de relógio (para 6 elementos):
mínimo
105
máximo
117
Neste caso o tempo mínimo é obtido quando o valor máximo é encontrado no primeiro elemento,
neste caso 128, todos os outros elementos são menores com sinal contrário, isto é negativo.
O tempo máximo, sucede quando a sucessão é crescente e todos os elementos têm o mesmo sinal
que o valor inicial, que neste caso é -128.
Neste caso, como existem muito ramos de decisão, não é trivial determinar o ramo com
comprimento máximo ou mínimo, e como tal sucede. Estes podem ser determinados, arranjando o
código de forma semelhante a uma árvore de decisão, de modo a identificar os ramos maiores e
menores, e em que casos é que são percorridos.
Ainda se podia optimizar o código, fazendo com que o registo max seja inicializado com o primeiro
elemento do array e não com a constante minimum, poupando-se assim uma iteração, e mantendo o
mesmo número de instruções. Esta optimização poderia ser efectuada também para a alínea
anterior.
Código original
maximum
Modificações
maximum
movlw
movwf
minimum
max
movf
movwf
baseadr, W
max
movlw
movwf
movlw
movwf
dim
counter
baseadr
FSR
movlw
movwf
movlw
movwf
dim-1
counter
baseadr+1
FSR
Soluções guia prático 1 - 12
Download

Soluções dos exercícios da primeira ficha