Otimização de código C para sistemas embarcados

Post on 02-Apr-2015

219 views 4 download

Transcript of Otimização de código C para sistemas embarcados

2www.sctec.com.br

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.

3www.sctec.com.br

Áreas de Atuação

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

Terceiros

4www.sctec.com.br

Produtos

5www.sctec.com.br

Produtos

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

6www.sctec.com.br

Projetos

Computador de Bordo – M8 Octopus

7www.sctec.com.br

Educacional

Livros

Otimização de Programas C para

Sistemas Embarcados

10www.sctec.com.br

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.

11www.sctec.com.br

Introdução

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

12www.sctec.com.br

Introdução

Aspectos importantes para um programa C eficiente:1. Conheça o compilador2. Conheça a CPU3. Utilize o tipo de dado mais eficiente4. Evite utilizar funções de biblioteca5. Programe de forma a auxiliar o

trabalho do compilador

Tipos de Dados e Alocação de

Memória

14www.sctec.com.br

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?

15www.sctec.com.br

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).

16www.sctec.com.br

Signed x Unsigned

0123456S012345670123456S01234567

01234567012345670123456701234567

0123456SSSSSSSSS

0123456789101112131415

0123456700000000012345678910111213141501234567000000000123456789101112131415

Zero filling

Sign extension

17www.sctec.com.br

Signed x Unsigned

Atribuição de char para int nos PIC18:

Unsigned

;uiv = ucvMOVFF ucv,uivMOVLB 0 CLRF uiv+1, BANKED

Signed

;siv = scvMOVFF scv,sivMOVLB 0CLRF siv+1, BANKEDBTFSC siv,7, BANKED SETF siv+1, BANKED

18www.sctec.com.br

Signed x Unsigned

Atribuição de char para int nos PIC18:

Unsigned

;uiv = ucvMOVFF ucv,uivMOVLB 0 CLRF uiv+1, BANKED

Signed

;siv = scvMOVFF scv,sivMOVLB 0CLRF siv+1, BANKEDBTFSC siv,7, BANKED SETF siv+1, BANKED

8 bytes8 ciclos

12 bytes12/13 ciclos

19www.sctec.com.br

Signed x Unsigned

Atribuição de char para int nos MSP430:

Unsigned

;uiv = ucvMOV.B &ucv,R15MOV.W R15,&uiv

Signed

;siv = scvMOV.B &scv,R15SXT R15MOV.W R15,&siv

20www.sctec.com.br

Signed x Unsigned

Atribuição de char para int nos MSP430:

Unsigned

;uiv = ucvMOV.B &ucv,R15MOV.W R15,&uiv

Signed

;siv = scvMOV.B &scv,R15SXT R15MOV.W R15,&siv8 bytes

7 ciclos 10 bytes15 ciclos

21www.sctec.com.br

Signed x Unsigned

Algumas operações aritméticas também podem sofrer impactos negativos pelo uso de tipos signed:

22www.sctec.com.br

Signed x Unsigned

Unsigned

118 bytes238 ciclos

Divisão de 16 bits nos HCS08

Signed

160 bytes356 ciclos

23www.sctec.com.br

Signed x Unsigned

Unsigned

456 bytes51 ciclos

Divisão de 32 bits nos ARM7

Signed

472 bytes48 ciclos

24www.sctec.com.br

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;}

25www.sctec.com.br

Seleção de Tipos

107

6472

47

115

60

83

48

68

49

8876

0

20

40

60

80

100

120

CFv1 ARM Thumb CM-3 MIPS32 MIPS16

cfatorial(10)ifatorial(10)

Velocidade (ciclos de clock):

26www.sctec.com.br

Seleção de Tipos

2620

52

40

32

2026

18

48

40

28

20

0

10

20

30

40

50

60

CFv1 ARM Thumb CM-3 MIPS32 MIPS16

cfatorial(10)ifatorial(10)

Tamanho de código (bytes):

27www.sctec.com.br

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).

Campos de Bits

29www.sctec.com.br

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?

30www.sctec.com.br

Campos de bits

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

31www.sctec.com.br

Campos de bits

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

Bit:teste.bit0 = 1;

BSET 0,teste

Byte:flag = 1;

LDA #0x01LDHX #flagSTA ,X

32www.sctec.com.br

Campos de bits

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

Bit:teste.bit0 = 1;

BSET 0,teste

Byte:flag = 1;

LDA #0x01LDHX #flagSTA ,X

2 bytes FLASH1 bit RAM10 ciclos

6 bytes FLASH1 byte RAM

16 ciclos

33www.sctec.com.br

Campos de bits

Teste de flag utilizando bits e bytes (HCS08):

Bit:If (teste.bit0)...

BRCLR 0,teste,falso// verdadeiro

Byte:If (flag) ...

LDA testeBEQ falso// verdadeiro

34www.sctec.com.br

Campos de bits

Teste de flag utilizando bits e bytes (HCS08):

Bit:If (teste.bit0)...

BRCLR 0,teste,falso// verdadeiro

Byte:If (flag) ...

LDA testeBEQ falso// verdadeiro

3 bytes FLASH1 bit RAM10 ciclos

5/6 bytes FLASH1 byte RAM12/14 ciclos

35www.sctec.com.br

Campos de bits

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

Bit:teste.bit0 = 1;

BSF teste,0

Byte:flag = 1;

MOVLW 0x01MOVWF flag

36www.sctec.com.br

Campos de bits

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

Bit:teste.bit0 = 1;

BSF teste,0

Byte:flag = 1;

MOVLW 0x01MOVWF flag

1 word FLASH1 bit RAM4 ciclos

2 words FLASH1 byte RAM

8 ciclos

37www.sctec.com.br

Campos de bits

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

Bit:If (teste.bit0)...

BTFSS teste,0GOTO falso// verdadeiro

Byte:If (flag) ...

MOVF flag,FBTFSC STATUS,ZGOTO falso// verdadeiro

38www.sctec.com.br

Campos de bits

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

Bit:If (teste.bit0)...

BTFSS teste,0GOTO falso// verdadeiro

Byte:If (flag) ...

MOVF flag,FBTFSC STATUS,ZGOTO falso// verdadeiro

2 words FLASH1 bit RAM8/12 ciclos

3 words FLASH1 byte RAM12/16 ciclos

39www.sctec.com.br

Campos de bits

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

Bit:teste.bit0 = 1;

BIS.B #1,&teste

Byte:flag = 1;

MOV.B #1,&teste

40www.sctec.com.br

Campos de bits

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

Bit:teste.bit0 = 1;

BIS.B #1,&teste

Byte:flag = 1;

MOV.B #1,&teste4 bytes FLASH

1 bit RAM4 ciclos

4 bytes FLASH1 byte RAM

4 ciclos

41www.sctec.com.br

Campos de bits

Teste de flag utilizando bits e bytes (MSP430):

Bit:If (teste.bit0)...

BIT.B #1,&testeJNC falso// verdadeiro

Byte:If (flag) ...

TST.B &flagJEQ falso// verdadeiro

42www.sctec.com.br

Campos de bits

Teste de flag utilizando bits e bytes (MSP430):

Bit:If (teste.bit0)...

BIT.B #1,&testeJNC falso// verdadeiro

Byte:If (flag) ...

TST.B &flagJEQ falso// verdadeiro

6 bytes FLASH1 bit RAM6 ciclos

6 bytes FLASH1 byte RAM

6 ciclos

43www.sctec.com.br

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).

44www.sctec.com.br

Campos de bits

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

Bit:teste.bit0 = 1;

BSET #0,x(Ay)

Byte:flag = 1;

MOVE.B #1,x(Ay)

45www.sctec.com.br

Campos de bits

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

Bit:teste.bit0 = 1;

BSET #0,x(Ay)

Byte:flag = 1;

MOVE.B #1,x(Ay)6 bytes FLASH

1 bit RAM4 ciclos

6 bytes FLASH1 byte RAM

1 ciclo

46www.sctec.com.br

Campos de bits

Teste de flag utilizando bits e bytes (Coldfire):

Bit:If (teste.bit0)...

MVZ.B 8(A5),D0LSL.L D1,D0LSR.L D1,D0TST.B D0BEQ.S falso// verdadeiro

Byte:If (flag) ...

TST.B 11(A5)BEQ.S falso// verdadeiro

47www.sctec.com.br

Campos de bits

Teste de flag utilizando bits e bytes (Coldfire):

Bit:If (teste.bit0)...

MVZ.B 8(A5),D0LSL.L D1,D0LSR.L D1,D0TST.B D0BEQ.S falso// verdadeiro

Byte:If (flag) ...

TST.B 11(A5)BEQ.S falso// verdadeiro

12 bytes FLASH1 bit RAM8 ciclos

6 bytes FLASH1 byte RAM

5 ciclos

48www.sctec.com.br

Campos de bits

Segunda versão do teste de bit:

Bit:If (teste.bit0)...

MVZ.B 8(A5),D0BTST #0,8(A5)BEQ.S falso// verdadeiro

8 bytes FLASH1 bit RAM6 ciclos

49www.sctec.com.br

Campos de bits

Atribuições utilizando bits e bytes (ARM-ARM):

Bit:teste.bit0 = 1;

LDR R0,[PC,#offset1]LDR R1,[PC,#offset2]LDR R1,[R1,#+0]ORRS R1, R1, #0x01STR R1,[R0,#+0]

Byte:flag = 1;

LDR R0,[PC,#+offset3]MOV R1, #1STRB R1,[R0,#+0]

50www.sctec.com.br

Campos de bits

Atribuições utilizando bits e bytes (ARM-ARM):

Bit:teste.bit0 = 1;

LDR R0,[PC,#offset1]LDR R1,[PC,#offset2]LDR R1,[R1,#+0]ORRS R1, R1, #0x01STR R1,[R0,#+0]

Byte:flag = 1;

LDR R0,[PC,#+offset3]MOV R1, #1STRB R1,[R0,#+0]

20 bytes FLASH1 bit RAM8 ciclos

12 bytes FLASH1 byte RAM

4 ciclos

51www.sctec.com.br

Campos de bits

Bit:teste.bit0 = 1;

LDR R0,[PC,#offset1]LDR R1,[PC,#offset2]LDR R1,[R1,#0]MOV R2, #1ORR R2, R1STR R2,[R0,#0]

Byte:flag = 1;

LDR R0,[PC,#offset3]MOV R1,#1STRB R1,[R0,#0]

Atribuições utilizando bits e bytes (ARM-Thumb):

52www.sctec.com.br

Campos de bits

Bit:teste.bit0 = 1;

LDR R0,[PC,#offset1]LDR R1,[PC,#offset2]LDR R1,[R1,#0]MOV R2, #1ORR R2, R1STR R2,[R0,#0]

Byte:flag = 1;

LDR R0,[PC,#offset3]MOV R1,#1STRB R1,[R0,#0]

12 bytes FLASH1 bit RAM9 ciclos

6 bytes FLASH1 byte RAM

4 ciclos

Atribuições utilizando bits e bytes (ARM-Thumb):

Alinhamento de Dados

54www.sctec.com.br

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.

55www.sctec.com.br

Alinhamento de dados

struct{ char campo1; int campo2; short campo3;} teste;

ARM7:

0xuuuuuuu9campo3

0xuuuuuuu80xuuuuuuu7

campo2

---

campo1

0xuuuuuuu40xuuuuuuu50xuuuuuuu6

0xuuuuuuu30xuuuuuuu20xuuuuuuu10xuuuuuuu0

56www.sctec.com.br

Alinhamento de dados

struct{ char campo1; int campo2; short campo3;} teste;

ARM7:

0xuuuuuuu9campo3

0xuuuuuuu80xuuuuuuu7

campo2

---

campo1

0xuuuuuuu40xuuuuuuu50xuuuuuuu6

0xuuuuuuu30xuuuuuuu20xuuuuuuu10xuuuuuuu0

Memória RAM útil: 7 bytesMemória RAM utilizada: 10 bytes!

57www.sctec.com.br

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:

58www.sctec.com.br

Alinhamento de dados

struct{ char campo1; int campo2; short campo3;} teste;

0xuuuuuuu4

campo30xuuuuuuu50xuuuuuuu6

0xuuuuuuu30xuuuuuuu20xuuuuuuu10xuuuuuuu0

campo2

campo1

Coldfire, Cortex e MIPS:

59www.sctec.com.br

Alinhamento de dados

struct{ char campo1; int campo2; short campo3;} teste;

0xuuuuuuu4

campo30xuuuuuuu50xuuuuuuu6

0xuuuuuuu30xuuuuuuu20xuuuuuuu10xuuuuuuu0

campo2

campo1

Coldfire, Cortex e MIPS:

Memória RAM útil: 7 bytesMemória RAM utilizada: 7 bytes!

60www.sctec.com.br

Alinhamento de dados

struct{ char campo1; int campo2; short campo3;} teste;

0xuuuuuuu4

campo30xuuuuuuu50xuuuuuuu6

0xuuuuuuu30xuuuuuuu20xuuuuuuu10xuuuuuuu0

campo2

campo1

Coldfire, Cortex e MIPS:

IAR: modificador __packedCodewarrior: diretiva #pragma pack(x)GCC (MIPS): __attribute__((packed))

61www.sctec.com.br

Alinhamento de dados

Atenção: acessos não-alinhados à memória podem necessitar de ciclos adicionais de clock para a sua efetivação!

62www.sctec.com.br

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:

63www.sctec.com.br

Organização de dados

struct{ char campo1; int campo2; char campo3; short campo4;} teste;

ARM7:

0xuuuuuuuBcampo4

0xuuuuuuuA-

campo3

campo2

---

campo1

0xuuuuuuu90xuuuuuuu80xuuuuuuu7

0xuuuuuuu40xuuuuuuu50xuuuuuuu6

0xuuuuuuu30xuuuuuuu20xuuuuuuu10xuuuuuuu0

64www.sctec.com.br

Organização de dados

struct{ char campo1; int campo2; char campo3; short campo4;} teste;

ARM7:

0xuuuuuuuBcampo4

0xuuuuuuuA-

campo3

campo2

---

campo1

0xuuuuuuu90xuuuuuuu80xuuuuuuu7

0xuuuuuuu40xuuuuuuu50xuuuuuuu6

0xuuuuuuu30xuuuuuuu20xuuuuuuu10xuuuuuuu0

Memória RAM útil: 8 bytesMemória RAM utilizada: 12 bytes!

65www.sctec.com.br

Organização de dados

struct{ char campo1; char campo3; short campo4; int campo2; } teste;

campo2

campo4

campo3campo1

0xuuuuuuu7

0xuuuuuuu40xuuuuuuu50xuuuuuuu6

0xuuuuuuu30xuuuuuuu20xuuuuuuu10xuuuuuuu0

66www.sctec.com.br

Organização de dados

struct{ char campo1; char campo3; short campo4; int campo2; } teste;

campo2

campo4

campo3campo1

0xuuuuuuu7

0xuuuuuuu40xuuuuuuu50xuuuuuuu6

0xuuuuuuu30xuuuuuuu20xuuuuuuu10xuuuuuuu0

Memória RAM útil: 8 bytesMemória RAM utilizada: 8 bytes!

Estudo de Casos

68www.sctec.com.br

Timers e ContadoresOtimização de timers e contadores:

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

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

69www.sctec.com.br

Timers e ContadoresTempos relativos dos contadores decrementais:

93

75

9587

100 10091 94 95

0102030405060708090

100

HCS08 PIC16 MSP CFv1 ARM Thumb CM-3 MIPS32 MIPS16

dec

70www.sctec.com.br

Timers e ContadoresVerificação do contador dentro do programa:

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

if (!va)......

Mais eficiente!

71www.sctec.com.br

FunçõesReduçã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;}

72www.sctec.com.br

FunçõesReduçã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;}

73www.sctec.com.br

FunçõesExame do MAP file:

74www.sctec.com.br

FunçõesExame do MAP file:

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

75www.sctec.com.br

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; }

76www.sctec.com.br

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; }

376 bytes FLASH1188 ciclos

77www.sctec.com.br

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; }}

78www.sctec.com.br

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; }}

357 bytes FLASH1060 ciclos

79www.sctec.com.br

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; }}

80www.sctec.com.br

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; }}

311 bytes FLASH802 ciclos

81www.sctec.com.br

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; } }

82www.sctec.com.br

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; } }

292 bytes FLASH628 ciclos

83www.sctec.com.br

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; } }

84www.sctec.com.br

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; } }

254 bytes FLASH558 ciclos

85www.sctec.com.br

Interpolação de 8 bits

Estatísticas de otimização:

376

1188

357

1060

254

558

0

200

400

600

800

1000

1200

int char final

TamanhoCiclos

86www.sctec.com.br

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; elsereturn (((uchar)x%(uchar)(x2-

x1))*((signed char)y2-(signed char)y1))/(x2-x1)+y1; }

87www.sctec.com.br

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; elsereturn (((uchar)x%(uchar)(x2-

x1))*((signed char)y2-(signed char)y1))/(x2-x1)+y1; }

358 bytes FLASH222 ciclos

88www.sctec.com.br

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; }

89www.sctec.com.br

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; }

340 bytes FLASH156 ciclos

90www.sctec.com.br

Configuração do Linker

HCS08:

•Utilização da página direta•Otimização de acessos a memória•Otimização da pilha

91www.sctec.com.br

Configuração do Linker

Utilização da página direta nos HCS08:

92www.sctec.com.br

Configuração do Linker

Utilização da página direta nos HCS08:

93www.sctec.com.br

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

94www.sctec.com.br

Explorando MAP files

95www.sctec.com.br

Explorando MAP files

96www.sctec.com.br

Explorando MAP files

97www.sctec.com.br

Explorando MAP files

98www.sctec.com.br

Explorando MAP files

Com endereçamento extendido:

99www.sctec.com.br

Explorando MAP files

Modificação para endereçamento direto:

100www.sctec.com.br

Explorando MAP files

Com endereçamento direto:

-1 byte/-1 ciclo

101www.sctec.com.br

Explorando MAP files

Com endereçamento extendido:

-47 bytes

-20 bytes

-31 bytes

-105 bytes

102www.sctec.com.br

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.

103www.sctec.com.br

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!

104www.sctec.com.br

Pilha

Como dimensionar corretamente o tamanho da pilha?

105www.sctec.com.br

Pilha

Call Graph:

106www.sctec.com.br

Pilha

Call Graph:

107www.sctec.com.br

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)!

108www.sctec.com.br

Pilha

13 bytes!

7 bytes!

109www.sctec.com.br

Pilha

Alocação de pilha:

ARM/CM3:

SUB SP,SP,#X

MSP430:

SUB.W #X,SP

MIPS16:

SAVE #X

Coldfire:

LEA –X(A7),A7

MIPS32:

ADDIU SP,SP,#-X

HCS08:

AIS #-X

110www.sctec.com.br

Máquinas de Estado

IDLE

ST1

ST2

ST4 ST3

ST5

ST6

111www.sctec.com.br

Máquinas de Estadovoid 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; }}

112www.sctec.com.br

Máquinas de Estadovoid 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; }}

138 bytes FLASH

113www.sctec.com.br

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

114www.sctec.com.br

Máquinas de Estadovoid 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; }}

115www.sctec.com.br

Máquinas de Estadovoid 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; }}

134 bytes FLASH

116www.sctec.com.br

Máquinas de Estadounsigned 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;}

117www.sctec.com.br

Máquinas de Estadounsigned 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;}

132 bytes FLASH

118www.sctec.com.br

Máquinas de Estadounsigned 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;}

119www.sctec.com.br

Máquinas de Estadounsigned 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;}

120 bytes FLASH

120www.sctec.com.br

Máquinas de Estado

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

Enumerações

121www.sctec.com.br

Máquinas de Estadoenum 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; }

122www.sctec.com.br

Máquinas de Estadoenum 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; }

Lembre-se de que o tipo enum é normalmente um signed int!

Em algumas plataformas de 8 bits pode haver um impacto negativo no uso de enumerações!

123www.sctec.com.br

Operandos e Operações

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

if (aux++) ...

LDA auxTAXINCASTA auxTSTXBEQ falso...

if (aux) ...aux++;

TST auxBEQ falso...INC aux

124www.sctec.com.br

Operandos e Operações

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

if (aux++) ...

LDA auxTAXINCASTA auxTSTXBEQ falso...

if (aux) ...aux++;

TST auxBEQ falso...INC aux

9 bytes FLASH24 ciclos

6 bytes FLASH24 ciclos

125www.sctec.com.br

Operandos e Operações

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

if (aux++) ...

LDA auxTAXINCASTA auxTSTXBEQ falso...

if (aux) ...aux++;

TST auxBEQ falso...INC aux

9 bytes FLASH24 ciclos

6 bytes FLASH24 ciclos

Este tipo de situação

deve ser avaliada

individualmente !!!

126www.sctec.com.br

Operandos e Operações

127www.sctec.com.br

Operandos e Operações

if (CURRENT_TASK<(IDLE_TASK))

128www.sctec.com.br

Operandos e Operações

if ((char)CURRENT_TASK<(char)(IDLE_TASK))

129www.sctec.com.br

Operandos e Operações

130www.sctec.com.br

ReferênciasC:• 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

131www.sctec.com.br

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

132www.sctec.com.br

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

133www.sctec.com.br

fabio@sctec.com.br

Obrigado !