Você está na página 1de 133

A Empresa

A Sctec Eletrônica foi fundada em abril


de 2003 com o objetivo de desenvolver
soluções e produtos eletrônicos
utilizando a mais moderna tecnologia
disponível, atuando no desenvolvimento
de hardware e software.

www.sctec.com.br 2
Áreas de Atuação

• Produtos Automotivos
• Automação Industrial
• Comunicação com ou sem fio
• Sensoriamento Remoto
• Embedded Systems
• Desenvolvimento de Projetos para
Terceiros

www.sctec.com.br 3
Produtos

www.sctec.com.br 4
Produtos

MOD711
• ARM7
• 256 Kb FLASH
• 64 Kb RAM
• USB 2.0
• JTAG

www.sctec.com.br 5
Projetos

Computador de Bordo – M8 Octopus

www.sctec.com.br 6
Educacional

Livros

www.sctec.com.br 7
Parcerias

www.sctec.com.br 8
Otimização de
Programas C para
Sistemas
Embarcados
Introdução

Sistemas embarcados formam um


campo cada vez mais numeroso na
área de desenvolvimento de software.
No entanto, muitos programadores
desconhecem aspectos importantes e
essenciais ao desenvolvimento neste
tipo de plataforma.

www.sctec.com.br 10
Introdução

Nesta apresentação veremos alguns


aspectos importantes da utilização da
linguagem C no desenvolvimento de
aplicações embarcadas mais eficientes.

www.sctec.com.br 11
Introdução

Aspectos importantes para um programa


C eficiente:
1. Conheça o compilador
2. Conheça a CPU
3. Utilize o tipo de dado mais eficiente
4. Evite utilizar funções de biblioteca
5. Programe de forma a auxiliar o
trabalho do compilador

www.sctec.com.br 12
Tipos de Dados e
Alocação de
Memória
Signed x Unsigned

Signed versus unsigned

Qual o tipo ideal para a minha


aplicação?
A aplicação necessita de um dado
signed?
Há diferença de performance?
www.sctec.com.br 14
Signed x Unsigned

Extensão de sinal!
Ocorre sempre nas atribuições entre
variáveis sinalizadas e de tamanhos
diferentes (por exemplo a atribuição de
uma variável signed char para uma
variável signed int).

www.sctec.com.br 15
Signed x Unsigned
7 6 5 4 3 2 1 0
Zero filling 7 6 5 4 3 2 1 0

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 0 7 6 5 4 3 2 1 0

7 6 5 4 3 2 1 0
Sign extension S 6 5 4 3 2 1 0

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
S S S S S S S S S 6 5 4 3 2 1 0

www.sctec.com.br 16
Signed x Unsigned

Atribuição de char para int nos PIC18:

Unsigned Signed

;uiv = ucv ;siv = scv


MOVFF ucv,uiv MOVFF scv,siv
MOVLB 0 MOVLB 0
CLRF uiv+1, BANKED CLRF siv+1, BANKED
BTFSC siv,7, BANKED
SETF siv+1, BANKED

www.sctec.com.br 17
Signed x Unsigned

Atribuição de char para int nos PIC18:

Unsigned Signed

;uiv = ucv ;siv = scv


MOVFF ucv,uiv MOVFF scv,siv
8 bytes
MOVLB 0
CLRF uiv+1, BANKED
MOVLB
CLRF
12 bytes
0
siv+1, BANKED
8 ciclos BTFSC 12/13 ciclos
siv,7, BANKED
SETF siv+1, BANKED

www.sctec.com.br 18
Signed x Unsigned

Atribuição de char para int nos MSP430:

Unsigned Signed

;uiv = ucv ;siv = scv


MOV.B &ucv,R15 MOV.B &scv,R15
MOV.W R15,&uiv SXT R15
MOV.W R15,&siv

www.sctec.com.br 19
Signed x Unsigned

Atribuição de char para int nos MSP430:

Unsigned Signed

;uiv = ucv ;siv = scv


MOV.B &ucv,R15 MOV.B &scv,R15
8 bytes
MOV.W R15,&uiv SXT
10 bytes
R15
MOV.W R15,&siv
7 ciclos 15 ciclos

www.sctec.com.br 20
Signed x Unsigned

Algumas operações aritméticas


também podem sofrer impactos
negativos pelo uso de tipos signed:

www.sctec.com.br 21
Signed x Unsigned

Divisão de 16 bits nos HCS08

Unsigned Signed

118 bytes 160 bytes


238 ciclos 356 ciclos

www.sctec.com.br 22
Signed x Unsigned

Divisão de 32 bits nos ARM7

Unsigned Signed

456 bytes 472 bytes


51 ciclos 48 ciclos

www.sctec.com.br 23
Seleção de Tipos

Tipos nativos tendem a ser mais rápidos:


unsigned char cfatorial(unsigned char val)
{
unsigned char aux, result=1;
for(aux=1;aux<=val;aux++) result *= aux;
return result;
}
unsigned int ifatorial(unsigned int val)
{
unsigned int aux, result=1;
for(aux=1;aux<=val;aux++) result *= aux;
return result;
}
www.sctec.com.br 24
Seleção de Tipos

Velocidade (ciclos de clock):


120 115
107
100
88
83
80 72 76
64 68
60
60 cfatorial(10)
47 48 49
ifatorial(10)
40

20

0
CFv1 ARM Thumb CM-3 MIPS32 MIPS16

www.sctec.com.br 25
Seleção de Tipos

Tamanho de código (bytes):


60
52
50 48

40 40
40
32
30 26 26 28 cfatorial(10)
20 20 20 ifatorial(10)
20 18

10

0
CFv1 ARM Thumb CM-3 MIPS32 MIPS16

www.sctec.com.br 26
Seleção de Tipos

Variáveis locais devem utilizar


preferencialmente tipos nativos da CPU
em questão (char para chips de 8 bits,
int para chips de 16/32 bits).

www.sctec.com.br 27
Campos de Bits
Campos de bits

Muitas aplicações tendem a utilizar


variáveis apenas como flags, assumindo
dois valores: verdadeiro ou falso.
A utilização de campos de bits permite
reduzir consideravelmente a quantidade
de RAM ocupada, mas será o código
resultante mais eficiente?

www.sctec.com.br 29
Campos de bits

struct
{
unsigned char bit0 : 1;
unsigned char bit1 : 1;
unsigned char bit2 : 1;
} teste;

www.sctec.com.br 30
Campos de bits

Atribuições utilizando bits e bytes (HCS08):

Bit: Byte:
teste.bit0 = 1; flag = 1;

BSET 0,teste LDA #0x01


LDHX #flag
STA ,X

www.sctec.com.br 31
Campos de bits

Atribuições utilizando bits e bytes (HCS08):

Bit: Byte:
teste.bit0 = 1; flag = 1;

2 bytes FLASH 6 bytes FLASH


BSET 10,teste
bit RAM LDA1 #0x01
byte RAM
LDHX #flag
10 ciclos 16 ciclos
STA ,X

www.sctec.com.br 32
Campos de bits

Teste de flag utilizando bits e bytes (HCS08):

Bit: Byte:
If (teste.bit0)... If (flag) ...

BRCLR 0,teste,falso LDA teste


// verdadeiro BEQ falso
// verdadeiro

www.sctec.com.br 33
Campos de bits

Teste de flag utilizando bits e bytes (HCS08):

Bit: Byte:
If (teste.bit0)... If (flag) ...

3 bytes FLASH 5/6 bytes FLASH


BRCLR10,teste,falso
bit RAM LDA 1 byte RAM
teste
10 ciclos
// verdadeiro BEQ 12/14
falso ciclos
// verdadeiro

www.sctec.com.br 34
Campos de bits

Atribuições utilizando bits e bytes (PIC16/18):

Bit: Byte:
teste.bit0 = 1; flag = 1;

BSF teste,0 MOVLW 0x01


MOVWF flag

www.sctec.com.br 35
Campos de bits

Atribuições utilizando bits e bytes (PIC16/18):

Bit: Byte:
teste.bit0 = 1; flag = 1;

1 word FLASH 2 words FLASH


1 bit RAM
BSF teste,0 1 byte
MOVLW 0x01 RAM
MOVWF flag
4 ciclos 8 ciclos

www.sctec.com.br 36
Campos de bits

Teste de flag utilizando bits e bytes (PIC16/18):

Bit: Byte:
If (teste.bit0)... If (flag) ...

BTFSS teste,0 MOVF flag,F


GOTO falso BTFSC STATUS,Z
// verdadeiro GOTO falso
// verdadeiro

www.sctec.com.br 37
Campos de bits

Teste de flag utilizando bits e bytes (PIC16/18):

Bit: Byte:
If (teste.bit0)... If (flag) ...

2 words
BTFSS FLASH
teste,0 3 words
MOVF FLASH
flag,F
GOTO1 falso
bit RAM 1 byte
BTFSC RAM
STATUS,Z
GOTO falso
8/12 ciclos
// verdadeiro 12/16 ciclos
// verdadeiro

www.sctec.com.br 38
Campos de bits

Atribuições utilizando bits e bytes (MSP430):

Bit: Byte:
teste.bit0 = 1; flag = 1;

BIS.B #1,&teste MOV.B #1,&teste

www.sctec.com.br 39
Campos de bits

Atribuições utilizando bits e bytes (MSP430):

Bit: Byte:
teste.bit0 = 1; flag = 1;

4 bytes FLASH 4 bytes FLASH


BIS.B1 #1,&teste
bit RAM 1 byte
MOV.B RAM
#1,&teste

4 ciclos 4 ciclos

www.sctec.com.br 40
Campos de bits

Teste de flag utilizando bits e bytes (MSP430):

Bit: Byte:
If (teste.bit0)... If (flag) ...

BIT.B #1,&teste TST.B &flag


JNC falso JEQ falso
// verdadeiro // verdadeiro

www.sctec.com.br 41
Campos de bits

Teste de flag utilizando bits e bytes (MSP430):

Bit: Byte:
If (teste.bit0)... If (flag) ...

6 bytes FLASH 6 bytes FLASH


1 #1,&teste
BIT.B bit RAM 1 byte
TST.B &flagRAM
JNC 6falso JEQ falso
ciclos 6 ciclos
// verdadeiro // verdadeiro

www.sctec.com.br 42
Campos de bits

Em máquinas de 32 bits, a utilização de


campos de bit causa uma degradação na
performance e um aumento no tamanho
do código (código menos eficiente).

www.sctec.com.br 43
Campos de bits

Atribuições utilizando bits e bytes (Coldfire):

Bit: Byte:
teste.bit0 = 1; flag = 1;

BSET #0,x(Ay) MOVE.B #1,x(Ay)

www.sctec.com.br 44
Campos de bits

Atribuições utilizando bits e bytes (Coldfire):

Bit: Byte:
teste.bit0 = 1; flag = 1;

6 bytes FLASH 6 bytes FLASH


BSET 1#0,x(Ay)
bit RAM 1 byte
MOVE.B RAM
#1,x(Ay)

4 ciclos 1 ciclo

www.sctec.com.br 45
Campos de bits

Teste de flag utilizando bits e bytes (Coldfire):

Bit: Byte:
If (teste.bit0)... If (flag) ...

MVZ.B 8(A5),D0 TST.B 11(A5)


LSL.L D1,D0 BEQ.S falso
LSR.L D1,D0 // verdadeiro
TST.B D0
BEQ.S falso
// verdadeiro

www.sctec.com.br 46
Campos de bits

Teste de flag utilizando bits e bytes (Coldfire):

Bit: Byte:
If (teste.bit0)... If (flag) ...

12 bytes FLASH
MVZ.B 8(A5),D0
LSL.L D1,D0
6 bytes FLASH
TST.B 11(A5)
BEQ.S falso
1 bit RAM
LSR.L D1,D0 1 byte RAM
// verdadeiro
TST.B D0
8 ciclos
BEQ.S falso 5 ciclos
// verdadeiro

www.sctec.com.br 47
Campos de bits

Segunda versão do teste de bit:

Bit:
If (teste.bit0)...

MVZ.B 8(A5),D0
8 bytes FLASH
BTST #0,8(A5) 1 bit RAM
BEQ.S falso
// verdadeiro 6 ciclos

www.sctec.com.br 48
Campos de bits
Atribuições utilizando bits e bytes (ARM-ARM):

Bit: Byte:
teste.bit0 = 1; flag = 1;

LDR R0,[PC,#offset1] LDR R0,[PC,#+offset3]


LDR R1,[PC,#offset2] MOV R1, #1
LDR R1,[R1,#+0] STRB R1,[R0,#+0]
ORRS R1, R1, #0x01
STR R1,[R0,#+0]

www.sctec.com.br 49
Campos de bits
Atribuições utilizando bits e bytes (ARM-ARM):

Bit: Byte:
teste.bit0 = 1; flag = 1;

LDR R0,[PC,#offset1] LDR R0,[PC,#+offset3]


20 bytes FLASH
LDR R1,[PC,#offset2] 12 bytes FLASH
MOV R1, #1
LDR
ORRS
1 bit RAM
R1,[R1,#+0]
R1, R1, #0x01
1 byte RAM
STRB R1,[R0,#+0]

STR 8 ciclos
R1,[R0,#+0] 4 ciclos

www.sctec.com.br 50
Campos de bits
Atribuições utilizando bits e bytes (ARM-Thumb):

Bit: Byte:
teste.bit0 = 1; flag = 1;

LDR R0,[PC,#offset1] LDR R0,[PC,#offset3]


LDR R1,[PC,#offset2] MOV R1,#1
LDR R1,[R1,#0] STRB R1,[R0,#0]
MOV R2, #1
ORR R2, R1
STR R2,[R0,#0]

www.sctec.com.br 51
Campos de bits
Atribuições utilizando bits e bytes (ARM-Thumb):

Bit: Byte:
teste.bit0 = 1; flag = 1;

LDR R0,[PC,#offset1] LDR R0,[PC,#offset3]


12 bytes FLASH
LDR R1,[PC,#offset2] 6 bytes FLASH
MOV R1,#1
LDR
MOV
1 bit RAM
R1,[R1,#0]
R2, #1
1 byte RAM
STRB R1,[R0,#0]

ORR 9 ciclos
R2, R1 4 ciclos
STR R2,[R0,#0]

www.sctec.com.br 52
Alinhamento de
Dados
Alinhamento de dados

Outro aspecto importante a ser


considerado quando se programa um
sistema embarcado é o alinhamento de
dados.
Plataformas como os ARMs possuem
restrições quanto a localização dos
dados na memória.

www.sctec.com.br 54
Alinhamento de dados

ARM7: 0xuuuuuuu0 campo1


0xuuuuuuu1 -
struct 0xuuuuuuu2 -
{ 0xuuuuuuu3 -
char campo1; 0xuuuuuuu4
int campo2; 0xuuuuuuu5
campo2
short campo3; 0xuuuuuuu6
} teste; 0xuuuuuuu7
0xuuuuuuu8
campo3
0xuuuuuuu9

www.sctec.com.br 55
Alinhamento de dados

ARM7: 0xuuuuuuu0 campo1


0xuuuuuuu1 -
struct 0xuuuuuuu2 -
{ 0xuuuuuuu3 -
charMemória
campo1; RAM útil: 7 bytes
0xuuuuuuu4

Memória
int campo2;RAM utilizada: 10 bytes!
0xuuuuuuu5
campo2
short campo3; 0xuuuuuuu6
} teste; 0xuuuuuuu7
0xuuuuuuu8
campo3
0xuuuuuuu9

www.sctec.com.br 56
Alinhamento de dados

Chips de 8 bits não sofrem de problemas


de alinhamento de dados.
Algumas plataformas de 32 bits também
permitem otimização da alocação de
memória mediante o uso de diretivas
especiais:

www.sctec.com.br 57
Alinhamento de dados

Coldfire, Cortex e MIPS:


0xuuuuuuu0 campo1
struct
0xuuuuuuu1
{
0xuuuuuuu2
char campo1; campo2
0xuuuuuuu3
int campo2;
0xuuuuuuu4
short campo3; 0xuuuuuuu5
} teste; campo3
0xuuuuuuu6

www.sctec.com.br 58
Alinhamento de dados

Coldfire, Cortex e MIPS:


0xuuuuuuu0 campo1
struct
0xuuuuuuu1
{
0xuuuuuuu2
charMemória
campo1; RAM útil: 7 bytes
campo2
0xuuuuuuu3
Memória
int campo2; RAM utilizada: 7 bytes!
0xuuuuuuu4
short campo3; 0xuuuuuuu5
} teste; campo3
0xuuuuuuu6

www.sctec.com.br 59
Alinhamento de dados

Coldfire, Cortex e MIPS:


0xuuuuuuu0 campo1
struct
0xuuuuuuu1
{ IAR: modificador __packed
0xuuuuuuu2
Codewarrior:
char campo1; diretiva #pragma pack(x)
0xuuuuuuu3
campo2

GCC
int (MIPS): __attribute__((packed))
campo2;
0xuuuuuuu4
short campo3; 0xuuuuuuu5
} teste; campo3
0xuuuuuuu6

www.sctec.com.br 60
Alinhamento de dados

Atenção: acessos não-alinhados à


memória podem necessitar de ciclos
adicionais de clock para a sua
efetivação!

www.sctec.com.br 61
Organização de dados

Também é importante organizar os


dados dentro da estrutura de forma a
melhorar a distribuição dos mesmos na
memória do dispositivo:

www.sctec.com.br 62
Organização de dados
0xuuuuuuu0 campo1
ARM7: 0xuuuuuuu1 -
0xuuuuuuu2 -
struct 0xuuuuuuu3 -
{ 0xuuuuuuu4
char campo1; 0xuuuuuuu5
campo2
int campo2; 0xuuuuuuu6
0xuuuuuuu7
char campo3;
0xuuuuuuu8 campo3
short campo4;
0xuuuuuuu9 -
} teste; 0xuuuuuuuA
campo4
0xuuuuuuuB
www.sctec.com.br 63
Organização de dados
0xuuuuuuu0 campo1
ARM7: 0xuuuuuuu1 -
0xuuuuuuu2 -
struct 0xuuuuuuu3 -
{ 0xuuuuuuu4
charMemória
campo1; RAM útil: 8 bytes
0xuuuuuuu5
campo2
0xuuuuuuu6
Memória RAM utilizada:
int campo2; 12 bytes!
0xuuuuuuu7
char campo3;
0xuuuuuuu8 campo3
short campo4;
0xuuuuuuu9 -
} teste; 0xuuuuuuuA
campo4
0xuuuuuuuB
www.sctec.com.br 64
Organização de dados

0xuuuuuuu0 campo1
struct 0xuuuuuuu1 campo3
0xuuuuuuu2
{ campo4
0xuuuuuuu3
char campo1;
0xuuuuuuu4
char campo3;
0xuuuuuuu5
short campo4; campo2
0xuuuuuuu6
int campo2; 0xuuuuuuu7
} teste;

www.sctec.com.br 65
Organização de dados

0xuuuuuuu0 campo1
struct 0xuuuuuuu1 campo3
0xuuuuuuu2
{ campo4
0xuuuuuuu3
charMemória
campo1; RAM útil: 8 bytes
0xuuuuuuu4
Memória
char campo3;RAM utilizada: 8 bytes!
0xuuuuuuu5
short campo4; campo2
0xuuuuuuu6
int campo2; 0xuuuuuuu7
} teste;

www.sctec.com.br 66
Estudo de Casos
Timers e Contadores
Otimização de timers e contadores:

if (va<10) va++;
...
...

if (va) va--;
...
...

www.sctec.com.br 68
Timers e Contadores
Tempos relativos dos contadores decrementais:
100 100
100 93 95 94 95
87 91
90
80 75
70
60
50 dec
40
30
20
10
0
HCS08 PIC16 MSP CFv1 ARM Thumb CM-3 MIPS32 MIPS16

www.sctec.com.br 69
Timers e Contadores
Verificação do contador dentro do programa:

if (va==VALOR)
...
...

if (!va) Mais eficiente!


...
...

www.sctec.com.br 70
Funções
Redução do número de parâmetros de chamada:

void lcd_ks0108_write_byte(unsigned char rs, unsigned char


data)
{
KS0108_RW = 0; KS0108_DATA_PORT = data;
KS0108_RS = rs; KS0108_EN=1;
delay(_KS0108_DELAY/2);
KS0108_EN=0;
}

www.sctec.com.br 71
Funções
Redução do número de parâmetros de chamada:
void lcd_ks0108_write_data(unsigned char data)
{
KS0108_RW = 0; KS0108_DATA_PORT = data;
KS0108_RS = 1; KS0108_EN=1;
delay(_KS0108_DELAY/2); KS0108_EN=0;
}
void lcd_ks0108_write_cmd(unsigned char data)
{
KS0108_RW = 0; KS0108_DATA_PORT = data;
KS0108_RS = 0; KS0108_EN=1;
delay(_KS0108_DELAY/2); KS0108_EN=0;
}

www.sctec.com.br 72
Funções
Exame do MAP file:

www.sctec.com.br 73
Funções
Exame do MAP file:

Redução de 17 bytes no
tamanho do código !

www.sctec.com.br 74
Interpolação de 8 bits

Utilizando int:
int interpola(int x, int x1, int x2, int y1,
int y2)
{
if (x==x1) return y1; else
if (x==x2) return y2; else
return ((x%(x2-x1))*(y2-y1))/(x2-x1)+y1;

www.sctec.com.br 75
Interpolação de 8 bits

Utilizando int:
int interpola(int x, int x1, int x2, int y1,
int y2)
{
376
if (x==x1) bytes
return y1;FLASH
else
if (x==x2) 1188
returnciclos
y2; else
return ((x%(x2-x1))*(y2-y1))/(x2-x1)+y1;

www.sctec.com.br 76
Interpolação de 8 bits

Utilizando char:
char interpola(char x, char x1, char x2, char y1, char
y2)
{
if (x==x1) return y1; else if (x==x2) return y2;
else
{
return ((x%(x2-x1))*((signed char)y2-
(signed char)y1))/(x2-x1)+y1;
}
}

www.sctec.com.br 77
Interpolação de 8 bits

Utilizando char:
char interpola(char x, char x1, char x2, char y1, char
y2)
{

357 bytes FLASH


if (x==x1) return y1; else if (x==x2) return y2;
else
{ 1060 ciclos
return ((x%(x2-x1))*((signed char)y2-
(signed char)y1))/(x2-x1)+y1;
}
}

www.sctec.com.br 78
Interpolação de 8 bits

Forçando uchar na operação %:


char interpola(char x, char x1, char x2, char y1, char
y2)
{
if (x==x1) return y1; else if (x==x2) return y2;
else
{
return (((uchar)x%(uchar)(x2-x1))*((signed
char)y2-(signed char)y1))/(x2-x1)+y1;
}
}

www.sctec.com.br 79
Interpolação de 8 bits

Forçando uchar na operação %:


char interpola(char x, char x1, char x2, char y1, char
y2)
{

311 bytes FLASH


if (x==x1) return y1; else if (x==x2) return y2;
else
{ 802 ciclos
return (((uchar)x%(uchar)(x2-x1))*((signed
char)y2-(signed char)y1))/(x2-x1)+y1;
}
}

www.sctec.com.br 80
Interpolação de 8 bits

Utilizando apenas uchar:


char interpola(char x, char x1, char x2, char y1, char y2)
{
char aux;
aux = x%(uchar)(x2-x1);
if (x==x1) return y1; else if (x==x2) return y2; else
{
if (y2>y1) return (((uchar)x%(uchar)(x2-x1))*(uchar)(y2-
y1))/(x2-x1)+y1;
else return ((uchar)((uchar)(x2-x1)-(uchar)x%(uchar)(x2-
x1))*(uchar)(y1-y2))/(x2-x1)+y2;
}
}
www.sctec.com.br 81
Interpolação de 8 bits

Utilizando apenas uchar:


char interpola(char x, char x1, char x2, char y1, char y2)
{
char aux;
aux = x%(uchar)(x2-x1);
292 bytes FLASH
if (x==x1) return y1; else if (x==x2) return y2; else
{ 628 ciclos
if (y2>y1) return (((uchar)x%(uchar)(x2-x1))*(uchar)(y2-
y1))/(x2-x1)+y1;
else return ((uchar)((uchar)(x2-x1)-(uchar)x%(uchar)(x2-
x1))*(uchar)(y1-y2))/(x2-x1)+y2;
}
}
www.sctec.com.br 82
Interpolação de 8 bits

Variação de x constante:
char interpola(char x, char x1, char x2, char y1, char y2)
{
char aux;
aux = x%20;
if (x==x1) return y1; else if (x==x2) return y2; else
{
if (y2>y1)return ((uchar)aux*(uchar)(y2-y1))/20 + y1;
else return ((uchar)(20-aux)*(uchar)(y1-y2))/20 + y2;

}
}

www.sctec.com.br 83
Interpolação de 8 bits

Variação de x constante:
char interpola(char x, char x1, char x2, char y1, char y2)
{
char aux;
aux = x%20;
254 bytes FLASH
if (x==x1) return y1; else if (x==x2) return y2; else
{ 558 ciclos
if (y2>y1)return ((uchar)aux*(uchar)(y2-y1))/20 + y1;
else return ((uchar)(20-aux)*(uchar)(y1-y2))/20 + y2;

}
}

www.sctec.com.br 84
Interpolação de 8 bits
Estatísticas de otimização:
1200 1188 1060
1000

800
558
600 Tamanho
376 Ciclos
357
400
254
200

0
int char final

www.sctec.com.br 85
Seleção de Tipos

Interpolação de 8 bits no Coldfire v1:


uchar interpola(uchar x, uchar x1, uchar x2,
uchar y1, uchar y2)
{
if (x==x1) return y1; else
if (x==x2) return y2; else
return (((uchar)x%(uchar)(x2-
x1))*((signed char)y2-(signed char)y1))/
(x2-x1)+y1;
}
www.sctec.com.br 86
Seleção de Tipos

Interpolação de 8 bits no Coldfire v1:


uchar interpola(uchar x, uchar x1, uchar x2,
uchar y1, uchar y2)
{
358
if (x==x1) bytes
return y1;FLASH
else
if (x==x2) 222 ciclos
return y2; else
return (((uchar)x%(uchar)(x2-
x1))*((signed char)y2-(signed char)y1))/
(x2-x1)+y1;
}
www.sctec.com.br 87
Seleção de Tipos

Interpolação de 32 bits no Coldfire v1:


int interpola(int x, int x1, int x2, int y1,
int y2)
{
if (x==x1) return y1; else
if (x==x2) return y2; else
return ((x%(x2-x1))*(y2-y1))/(x2-x1)+y1;

www.sctec.com.br 88
Seleção de Tipos

Interpolação de 32 bits no Coldfire v1:


int interpola(int x, int x1, int x2, int y1,
int y2)
{
340
if (x==x1) bytes
return y1;FLASH
else
156 ciclos
if (x==x2) return y2; else
return ((x%(x2-x1))*(y2-y1))/(x2-x1)+y1;

www.sctec.com.br 89
Configuração do Linker
HCS08:

•Utilização da página direta


•Otimização de acessos a memória
•Otimização da pilha

www.sctec.com.br 90
Configuração do Linker
Utilização da página direta nos HCS08:

www.sctec.com.br 91
Configuração do Linker
Utilização da página direta nos HCS08:

www.sctec.com.br 92
Explorando MAP files

• Estrutura e disposição das funções e


dados na memória
• Verificação de utilização e referências a
funções e dados
• Permite conhecer a ocupação da
memória do MCU para fins de
otimização de código

www.sctec.com.br 93
Explorando MAP files

www.sctec.com.br 94
Explorando MAP files

www.sctec.com.br 95
Explorando MAP files

www.sctec.com.br 96
Explorando MAP files

www.sctec.com.br 97
Explorando MAP files
Com endereçamento extendido:

www.sctec.com.br 98
Explorando MAP files
Modificação para endereçamento direto:

www.sctec.com.br 99
Explorando MAP files
Com endereçamento direto:

-1 byte/
-1 ciclo

www.sctec.com.br 100
Explorando MAP files
Com endereçamento extendido:

-105 bytes

-47 bytes
-20 bytes

-31 bytes
www.sctec.com.br 101
Pilha

Falhas ocasionadas por overflow da pilha


são difíceis de ser diagnosticadas e
podem provocar diversos efeitos
colaterais, desde funcionamento errático
esporádico até crashes completos.

www.sctec.com.br 102
Pilha

Lembre-se de que as variáveis locais que


não podem ser armazenadas em
registradores da CPU são mantidas na
pilha durante a execução da função!

www.sctec.com.br 103
Pilha

Como dimensionar corretamente o


tamanho da pilha?

www.sctec.com.br 104
Pilha

Call Graph:

www.sctec.com.br 105
Pilha

Call Graph:

www.sctec.com.br 106
Pilha

O MAP file não possui Call Graph ?

Calcule a utilização da pilha utilizando as


árvores de dependência presentes no
MAP file (juntamente com a observação
do código gerado pelo compilador)!

www.sctec.com.br 107
Pilha

7 bytes!

13 bytes!

www.sctec.com.br 108
Pilha

Alocação de pilha:

HCS08: MSP430: ARM/CM3:

AIS #-X SUB.W #X,SP SUB SP,SP,#X

Coldfire: MIPS16: MIPS32:

LEA –X(A7),A7 SAVE #X ADDIU SP,SP,#-X

www.sctec.com.br 109
Máquinas de Estado

IDLE

ST6 ST1

ST5 ST2

ST4 ST3

www.sctec.com.br 110
Máquinas de Estado
void fsm1(unsigned int new_state)
{
static unsigned int fsm_state;
if (new_state) fsm_state = new_state;
if (fsm_state==FSM1_ST1)
{ // estado 1
va = 10;
fsm_state = FSM1_ST2;
} else if (fsm_state==FSM1_ST2)
{ // estado 2
va = 20;
fsm_state = FSM1_ST3;
} else if (fsm_state==FSM1_ST3)
{ // estado 3
if (va<10) fsm_state = FSM1_ST1; else
if (va==255) fsm_state = FSM1_IDLE; else
fsm_state = FSM1_ST4;
} else if (fsm_state==FSM1_ST4)
{ // estado 4
va--;
fsm_state = FSM1_ST5;
} else if (fsm_state==FSM1_ST5)
{ // estado 5
if (!va) fsm_state = FSM1_ST6;
} else if (fsm_state==FSM1_ST6)
{ // estado 6
va = 100;
fsm_state = FSM1_ST1;
}
}

www.sctec.com.br 111
Máquinas de Estado
void fsm1(unsigned int new_state)
{
static unsigned int fsm_state;
if (new_state) fsm_state = new_state;
if (fsm_state==FSM1_ST1)
{ // estado 1
va = 10;
fsm_state = FSM1_ST2;
} else if (fsm_state==FSM1_ST2)
{ // estado 2
va = 20;
fsm_state = FSM1_ST3;
} else if (fsm_state==FSM1_ST3)
{ // estado 3
138 bytes FLASH
if (va<10) fsm_state = FSM1_ST1; else
if (va==255) fsm_state = FSM1_IDLE; else
fsm_state = FSM1_ST4;
} else if (fsm_state==FSM1_ST4)
{ // estado 4
va--;
fsm_state = FSM1_ST5;
} else if (fsm_state==FSM1_ST5)
{ // estado 5
if (!va) fsm_state = FSM1_ST6;
} else if (fsm_state==FSM1_ST6)
{ // estado 6
va = 100;
fsm_state = FSM1_ST1;
}
}

www.sctec.com.br 112
Máquinas de Estado

#define FSM1_IDLE 0
#define FSM1_ST1 1
#define FSM1_ST2 2
#define FSM1_ST3 3
#define FSM1_ST4 4
#define FSM1_ST5 5
#define FSM1_ST6 6

www.sctec.com.br 113
Máquinas de Estado
void fsm2(unsigned int new_state)
{
static unsigned int fsm_state;
if (new_state) fsm_state = new_state;
switch (fsm_state)
{
case FSM1_IDLE: // não faz nada
break;
case FSM1_ST1: // estado 1
va = 10; fsm_state = FSM1_ST2;
break;
case FSM1_ST2: // estado 2
va = 20; fsm_state = FSM1_ST3;
break;
case FSM1_ST3: // estado 3
if (va<10) fsm_state = FSM1_ST1; else
if (va==255) fsm_state = FSM1_IDLE; else
fsm_state = FSM1_ST4;
break;
case FSM1_ST4: // estado 4
va--; fsm_state = FSM1_ST5;
break;
case FSM1_ST5: // estado 5
if (!va) fsm_state = FSM1_ST6;
break;
case FSM1_ST6: // estado 6
va = 100; fsm_state = FSM1_ST1;

}
}

www.sctec.com.br 114
Máquinas de Estado
void fsm2(unsigned int new_state)
{
static unsigned int fsm_state;
if (new_state) fsm_state = new_state;
switch (fsm_state)
{
case FSM1_IDLE: // não faz nada
break;
case FSM1_ST1: // estado 1
va = 10; fsm_state = FSM1_ST2;
break;
case FSM1_ST2: // estado 2
va = 20; fsm_state = FSM1_ST3;
break;
case FSM1_ST3: // estado 3

134 bytes FLASH


if (va<10) fsm_state = FSM1_ST1; else
if (va==255) fsm_state = FSM1_IDLE; else
fsm_state = FSM1_ST4;
break;
case FSM1_ST4: // estado 4
va--; fsm_state = FSM1_ST5;
break;
case FSM1_ST5: // estado 5
if (!va) fsm_state = FSM1_ST6;
break;
case FSM1_ST6: // estado 6
va = 100; fsm_state = FSM1_ST1;

}
}

www.sctec.com.br 115
Máquinas de Estado
unsigned int fsm3(unsigned int new_state)
{
static unsigned int fsm_state;
if (new_state) fsm_state = new_state;
switch (fsm_state)
{
case FSM1_IDLE: // não faz nada
break;
case FSM1_ST1: // estado 1
va = 10; fsm_state = FSM1_ST2;
break;
case FSM1_ST2: // estado 2
va = 20; fsm_state = FSM1_ST3;
break;
case FSM1_ST3: // estado 3
if (va<10) fsm_state = FSM1_ST1; else
if (va==255) fsm_state = FSM1_IDLE;
else fsm_state = FSM1_ST4;
break;
case FSM1_ST4: // estado 4
va--; fsm_state = FSM1_ST5;
break;
case FSM1_ST5: // estado 5
if (!va) fsm_state = FSM1_ST6;
break;
case FSM1_ST6: // estado 6
va = 100; fsm_state = FSM1_ST1;

}
return fsm_state;
}

www.sctec.com.br 116
Máquinas de Estado
unsigned int fsm3(unsigned int new_state)
{
static unsigned int fsm_state;
if (new_state) fsm_state = new_state;
switch (fsm_state)
{
case FSM1_IDLE: // não faz nada
break;
case FSM1_ST1: // estado 1
va = 10; fsm_state = FSM1_ST2;
break;
case FSM1_ST2: // estado 2
va = 20; fsm_state = FSM1_ST3;
break;
case FSM1_ST3: // estado 3
if (va<10) fsm_state = FSM1_ST1; else
if (va==255) fsm_state = FSM1_IDLE;
else fsm_state = FSM1_ST4;
break;

132 bytes FLASH


case FSM1_ST4: // estado 4
va--; fsm_state = FSM1_ST5;
break;
case FSM1_ST5: // estado 5
if (!va) fsm_state = FSM1_ST6;
break;
case FSM1_ST6: // estado 6
va = 100; fsm_state = FSM1_ST1;

}
return fsm_state;
}

www.sctec.com.br 117
Máquinas de Estado
unsigned int fsm4(unsigned int new_state)
{
static unsigned int fsm_state;
unsigned int temp_state;
if (new_state) fsm_state = new_state;
switch (fsm_state)
{
case FSM1_IDLE: // não faz nada
break;
case FSM1_ST1: // estado 1
va = 10; temp_state = FSM1_ST2; break;
case FSM1_ST2: // estado 2
va = 20; temp_state = FSM1_ST3; break;
case FSM1_ST3: // estado 3
if (va<10) temp_state = FSM1_ST1; else
if (va==255) temp_state = FSM1_IDLE;
else temp_state = FSM1_ST4;
break;
case FSM1_ST4: // estado 4
va--; temp_state = FSM1_ST5;
break;
case FSM1_ST5: // estado 5
if (!va) temp_state = FSM1_ST6;
break;
case FSM1_ST6: // estado 6
va = 100; temp_state = FSM1_ST1;

}
fsm_state = temp_state;
return fsm_state;
}

www.sctec.com.br 118
Máquinas de Estado
unsigned int fsm4(unsigned int new_state)
{
static unsigned int fsm_state;
unsigned int temp_state;
if (new_state) fsm_state = new_state;
switch (fsm_state)
{
case FSM1_IDLE: // não faz nada
break;
case FSM1_ST1: // estado 1
va = 10; temp_state = FSM1_ST2; break;
case FSM1_ST2: // estado 2
va = 20; temp_state = FSM1_ST3; break;
case FSM1_ST3: // estado 3

120 bytes FLASH


if (va<10) temp_state = FSM1_ST1; else
if (va==255) temp_state = FSM1_IDLE;
else temp_state = FSM1_ST4;
break;
case FSM1_ST4: // estado 4
va--; temp_state = FSM1_ST5;
break;
case FSM1_ST5: // estado 5
if (!va) temp_state = FSM1_ST6;
break;
case FSM1_ST6: // estado 6
va = 100; temp_state = FSM1_ST1;

}
fsm_state = temp_state;
return fsm_state;
}

www.sctec.com.br 119
Máquinas de Estado

Enumerações

enum efsm
{
FSM2_IDLE, FSM2_ST1, FSM2_ST2, FSM2_ST3,
FSM2_ST4, FSM2_ST5, FSM2_ST6
};

www.sctec.com.br 120
Máquinas de Estado
enum efsm fsm5(enum efsm new_state)
{
static enum efsm2 fsm_state;
unsigned int temp_state;
if (new_state) fsm_state = new_state;
switch (fsm_state)
{
case FSM2_IDLE: // não faz nada
break;
case FSM2_ST1: // estado 1
va = 10; temp_state = FSM2_ST2; break;
case FSM2_ST2: // estado 2
va = 20; temp_state = FSM2_ST3; break;
case FSM2_ST3: // estado 3
if (va<10) temp_state = FSM2_ST1; else
if (va==255) temp_state = FSM2_IDLE; else
temp_state = FSM2_ST4;
break;
case FSM2_ST4: // estado 4
va--; temp_state = FSM2_ST5;
break;
case FSM2_ST5: // estado 5
if (!va) temp_state = FSM2_ST6;
break;
case FSM2_ST6: // estado 6
va = 100; temp_state = FSM2_ST1;

}
fsm_state = temp_state;
return fsm_state;
}

www.sctec.com.br 121
Máquinas de Estado
enum efsm fsm5(enum efsm new_state)
{
static enum efsm2 fsm_state;
unsigned int temp_state;

Lembre-se de que o tipo enum é


if (new_state) fsm_state = new_state;
switch (fsm_state)
{
case FSM2_IDLE: // não faz nada

normalmente um signed int!


break;
case FSM2_ST1: // estado 1
va = 10; temp_state = FSM2_ST2; break;
case FSM2_ST2: // estado 2
va = 20; temp_state = FSM2_ST3; break;
case FSM2_ST3: // estado 3
if (va<10) temp_state = FSM2_ST1; else

Em algumas plataformas de 8 bits


if (va==255) temp_state = FSM2_IDLE; else
temp_state = FSM2_ST4;
break;
case FSM2_ST4: // estado 4

pode haver um impacto negativo


va--; temp_state = FSM2_ST5;
break;
case FSM2_ST5: // estado 5

no uso de enumerações!
if (!va) temp_state = FSM2_ST6;
break;
case FSM2_ST6: // estado 6
va = 100; temp_state = FSM2_ST1;

}
fsm_state = temp_state;
return fsm_state;
}

www.sctec.com.br 122
Operandos e Operações

HCS08 - separação de operações:


if (aux++) ... if (aux) ...
aux++;
LDA aux
TAX TST aux
INCA BEQ falso
STA aux ...
TSTX INC aux
BEQ falso
...
www.sctec.com.br 123
Operandos e Operações

HCS08 - separação de operações:


if (aux++) ... if (aux) ...
aux++;
LDA aux
TAX TST aux
BEQ falso
9 bytes FLASH
INCA 6 bytes FLASH
STA aux ...
TSTX
24 ciclos 24
INC aux
ciclos
BEQ falso
...
www.sctec.com.br 124
Operandos e Operações

HCS08 - separação de operações:


if (aux++) ... if (aux) ...
aux++;
i t u a ç ã o
LDA aux
ip o d e s
Es t e t ia d a
TAX
e r a v
TST a l
aux
d e ve s ! ! !
9 bytes FLASHdualm
INCA n
BEQ falso t e
6 ebytes FLASH
STA aux in d ivi ...
TSTX
24 ciclos INC aux
24 ciclos
BEQ falso
...
www.sctec.com.br 125
Operandos e Operações

www.sctec.com.br 126
Operandos e Operações
if (CURRENT_TASK<(IDLE_TASK))

www.sctec.com.br 127
Operandos e Operações
if ((char)CURRENT_TASK<(char)(IDLE_TASK))

www.sctec.com.br 128
Operandos e Operações

www.sctec.com.br 129
Referências
C:
• ISO/IEC 9899:TC3 – ISO C Standard
http://www.open-
std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
• The Firmware Handbook

ARM:
• ARM Architecture Reference Manual
• ARM DDI 0405A-01 ARM v7-M Architecture Application Level
Reference Manual
• ARM DDI 0337D Cortex-M3 Technical Reference Manual
• Tecnologia ARM: Microcontroladores de 32 bits
• AN34 – ARM – Writing Efficient C for ARM
• AN36 – ARM – Using C Global Data

www.sctec.com.br 130
Referências

Coldfire:
• Coldfire Family – Programmer’s Reference Manual

HCS08:
• HCS08 Unleashed – Designer’s Guide to the HCS08
Microcontrollers
• HCS08RMv1/D – HCS08 Family Reference Manual

MSP430:
• Microcontroladores MSP430: Teoria e Prática
• MSP430 IAR C/C++ Compiler Reference Guide

www.sctec.com.br 131
Referências

PIC:
• MPLAB C32 C Compiler User’s Guide
• DS61113B – PIC32MX Family Reference Manual
• MD00249-2B-M4K-SUM – MIPS32 M4K Software User’s Manual
• MD00076 IV-a – MIPS16e Extension to the MIPS32 Architecture

www.sctec.com.br 132
Obrigado !

fabio@sctec.com.br

www.sctec.com.br 133

Você também pode gostar