Escolar Documentos
Profissional Documentos
Cultura Documentos
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
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
www.sctec.com.br 10
Introdução
www.sctec.com.br 11
Introdução
www.sctec.com.br 12
Tipos de Dados e
Alocação de
Memória
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
Unsigned Signed
www.sctec.com.br 17
Signed x Unsigned
Unsigned Signed
www.sctec.com.br 18
Signed x Unsigned
Unsigned Signed
www.sctec.com.br 19
Signed x Unsigned
Unsigned Signed
www.sctec.com.br 20
Signed x Unsigned
www.sctec.com.br 21
Signed x Unsigned
Unsigned Signed
www.sctec.com.br 22
Signed x Unsigned
Unsigned Signed
www.sctec.com.br 23
Seleção de Tipos
20
0
CFv1 ARM Thumb CM-3 MIPS32 MIPS16
www.sctec.com.br 25
Seleção de Tipos
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
www.sctec.com.br 27
Campos de Bits
Campos de bits
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
Bit: Byte:
teste.bit0 = 1; flag = 1;
www.sctec.com.br 31
Campos de bits
Bit: Byte:
teste.bit0 = 1; flag = 1;
www.sctec.com.br 32
Campos de bits
Bit: Byte:
If (teste.bit0)... If (flag) ...
www.sctec.com.br 33
Campos de bits
Bit: Byte:
If (teste.bit0)... If (flag) ...
www.sctec.com.br 34
Campos de bits
Bit: Byte:
teste.bit0 = 1; flag = 1;
www.sctec.com.br 35
Campos de bits
Bit: Byte:
teste.bit0 = 1; flag = 1;
www.sctec.com.br 36
Campos de bits
Bit: Byte:
If (teste.bit0)... If (flag) ...
www.sctec.com.br 37
Campos de bits
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
Bit: Byte:
teste.bit0 = 1; flag = 1;
www.sctec.com.br 39
Campos de bits
Bit: Byte:
teste.bit0 = 1; flag = 1;
4 ciclos 4 ciclos
www.sctec.com.br 40
Campos de bits
Bit: Byte:
If (teste.bit0)... If (flag) ...
www.sctec.com.br 41
Campos de bits
Bit: Byte:
If (teste.bit0)... If (flag) ...
www.sctec.com.br 42
Campos de bits
www.sctec.com.br 43
Campos de bits
Bit: Byte:
teste.bit0 = 1; flag = 1;
www.sctec.com.br 44
Campos de bits
Bit: Byte:
teste.bit0 = 1; flag = 1;
4 ciclos 1 ciclo
www.sctec.com.br 45
Campos de bits
Bit: Byte:
If (teste.bit0)... If (flag) ...
www.sctec.com.br 46
Campos de bits
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
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;
www.sctec.com.br 49
Campos de bits
Atribuições utilizando bits e bytes (ARM-ARM):
Bit: Byte:
teste.bit0 = 1; flag = 1;
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;
www.sctec.com.br 51
Campos de bits
Atribuições utilizando bits e bytes (ARM-Thumb):
Bit: Byte:
teste.bit0 = 1; flag = 1;
ORR 9 ciclos
R2, R1 4 ciclos
STR R2,[R0,#0]
www.sctec.com.br 52
Alinhamento de
Dados
Alinhamento de dados
www.sctec.com.br 54
Alinhamento de dados
www.sctec.com.br 55
Alinhamento de dados
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
www.sctec.com.br 57
Alinhamento de dados
www.sctec.com.br 58
Alinhamento de dados
www.sctec.com.br 59
Alinhamento de dados
GCC
int (MIPS): __attribute__((packed))
campo2;
0xuuuuuuu4
short campo3; 0xuuuuuuu5
} teste; campo3
0xuuuuuuu6
www.sctec.com.br 60
Alinhamento de dados
www.sctec.com.br 61
Organização de dados
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)
...
...
www.sctec.com.br 70
Funções
Redução do número de parâmetros de chamada:
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)
{
www.sctec.com.br 78
Interpolação de 8 bits
www.sctec.com.br 79
Interpolação de 8 bits
www.sctec.com.br 80
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
www.sctec.com.br 88
Seleção de Tipos
www.sctec.com.br 89
Configuração do Linker
HCS08:
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
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
www.sctec.com.br 102
Pilha
www.sctec.com.br 103
Pilha
www.sctec.com.br 104
Pilha
Call Graph:
www.sctec.com.br 105
Pilha
Call Graph:
www.sctec.com.br 106
Pilha
www.sctec.com.br 107
Pilha
7 bytes!
13 bytes!
www.sctec.com.br 108
Pilha
Alocação de pilha:
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
}
}
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;
}
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
}
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;
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
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