• Nenhum resultado encontrado

Debug de sistemas embarcados

No documento ELT024-NotasAulaLimpo (páginas 39-43)

In the beginner's mind there are many possibilities; in the expert's mind there are few. - Shunryu Suzuki

5A maioria dos compiladores C adotam uma variável com valor diferente de zero como sendo verdadeiro. 6Mais informações sobre debug de sistemas embarcados referir ao artigo The ten secrets of embedded

Tabela 2.4: Operação bit set com dene

Operação Bit set

Passo a Passo

char bit = 2;

char mascara; mascara = 1 << bit; arg = arg | mascara;

Uma linha arg = arg | (1<<bit)

Com dene #define BitSet(arg,bit) ((arg) |= (1<<bit))

Tabela 2.5: Operação bit clear com dene

Operação Bit clear

Passo a Passo

char bit = 2;

char mascara; mascara = 1 << bit; arg = arg & ~mascara;

Uma linha arg = arg & ~(1<<bit)

Com dene #define BitSet(arg,bit) ((arg) &= ~(1<<bit))

Tabela 2.6: Operação bit ip com dene

Operação Bit ip

Passo a Passo

char bit = 2;

char mascara; mascara = 1 << bit; arg = arg ^ mascara;

Uma linha arg = arg ^ (1<<bit)

Tabela 2.7: Operação bit test com dene

Operação Bit clear

Passo a Passo

char bit = 2;

char mascara; mascara = 1 << bit; arg = arg & mascara;

Uma linha arg = arg & (1<<bit)

Com dene #define BitSet(arg,bit) ((arg) &= (1<<bit))

A vericação de sistemas embarcados apresenta algumas restrições, de modo geral não é possível inferir sobre a operação do sistema sem paralisá-lo. Como este tipo de sistema possui vários dispositivos agregados, que funcionam independentemente do processador, é necessário utilizar abordagens diferentes para realizar o debug.

Devemos lembrar que além do software devemos levar em conta possíveis problemas advindos do hardware. Debounce, tempo de chaveamento, limite do barramento de comunicação são exemplos de pontos a serem considerados no momento de depuração.

Externalizar as informações.

A primeira necessidade é conhecer o que está acontecendo em teu sistema. Na programação tradicional para desktop é comum utilizarmos de mensagens no console avisando o estado do programa.

#include "stdio.h" #include "serial.h"

//inicio do programa

int main(int argc, char* argv[]) {

printf("Inicializando sistema");

if (CheckForData()) {

printf("Chegou informação"); }

else

{

printf("Problemas na comunicação"); }

return 0; }

Devemos ter em mente onde é necessário colocar estes alertas e lembrar de retirá-los do código nal.

Para a placa em questão utilizaremos o barramento de leds que está ligado à porta D. A operação deste dispositivo será estudada posteriormente em detalhes. Por enquanto basta sabermos que cada bit da variável PORTD está ligada à um led diferente. Por causa da construção física da placa, o led é aceso com valor 0 (zero) e desligado com o valor 1 (um).

Além disso temos que congurar a porta D. Isto é feito iniciando a variável TRISD com o valor 0x007.

//defines para portas de entrada e saída

#define PORTD (*(volatile near unsigned char*)0xF83) #define TRISD (*(volatile near unsigned char*)0xF95)

//inicio do programa

void main(void) interrupt 0 {

//configurando todos os pinos como saídas

TRISD = 0x00;

PORTD = 0xFF; //desliga todos os leds //liga apenas o bit 1.

BitClr(PORTD,1);

//mantém o sistema ligado indefinidamente

for(;;); }

Devemos utilizar os leds como sinais de aviso para entendermos o funcionamento do pro- grama. Isto pode ser feito através das seguintes ideias: Se passar desta parte liga o led X, Se entrar no IF liga o led Y, se não entrar liga o led Z, Assim que sair do loop liga o led W.

Programação incremental

Ao invés de escrever todo o código e tentar compilar, é interessante realizar testes incre- mentais. A cada alteração no código realizar um novo teste. Evitar alterar o código em muitos lugares simultaneamente, no caso de aparecer um erro ca mais difícil saber onde ele está.

Checar possíveis pontos de Memory-leak

Se for necessário realizar alocação dinâmica garantir que todas as alocações são liberadas em algum ponto do programa.

Cuidado com a fragmentação da memória

Sistemas com grande frequência na alocação/liberação de memória podem fragmentar a memória até o ponto de inviabilizar os espaços livres disponíveis, eventualmente travando o sistema. Quando trabalhar com rotinas de nível mais baixo, mais próximo ao hardware, tente utilizar apenas mapeamento estático de memória.

Otimização de código

Apenas se preocupe com otimização se estiver tendo problemas com o cumprimento de tarefas. Mesmo assim considere em migrar para uma plataforma mais poderosa. Sistemas embarcados preconizam segurança e não velocidade.

Caso seja necessário otimizar o código analise antes o local de realizar a otimização. Não adianta otimizar uma função grande se ela é chamada apenas uma vez. Utilize-se de ferramentas do tipo proler sempre que possível. Isto evita a perda de tempo e auxilia o programador a visualizar a real necessidade de otimização de código.

Reproduzir e isolar o erro

Quando houver algum erro deve-se primeiro entender como reproduzi-lo. Não é possível tentar corrigir o erro se não houver maneira de vericar se ele foi eliminado.

No momento em que se consegue um procedimento de como reproduzir o erro podemos começar a visualizar onde ele pode estar. A partir deste momento devemos isolar onde o erro está acontecendo. Uma maneira de se fazer isto em sistemas embarcados é colocar um loop innito dentro de um teste, que visa vericar alguma condição de anomalia. Se o sistema entrar neste teste devemos sinalizar através dos meios disponíveis, ligar/desligar algum led por exemplo.

// aqui tem um monte de código...

if (PORTB >= 5) //PORTB não deveria ser um valor maior que 5.

{

BitClr(PORTD,3); //liga o led 3

for(;;); //trava o programa

}

// aqui continua com um monte de código...

No documento ELT024-NotasAulaLimpo (páginas 39-43)

Documentos relacionados