• Code quality

Variáveis

Programas para sistemas embarcados devem seguir algumas diretrizes fundamentais de qualidade de código, refletindo as melhores práticas no uso de microcontroladores e da linguagem de programação C. É importante lembrar que um sistema embarcado interage diretamente com o mundo real, onde falhas podem impactar significativamente nossa realidade.

Existem varias normas estabelecidas para orientar os desenvolvedores na criação de firmwares mais confiáveis, abordando inclusive problemas associados à especificação da linguagem C.

underfined behaviors - linguagem C

Os comportamentos indefinidos (undefined behaviors) na linguagem de programação C ocorrem quando o padrão da linguagem não especifica como o programa deve se comportar em determinadas circunstâncias. Isso pode ser resultado de ações como: divisão por zero, acesso a ponteiros nulos, estouro de buffer, entre outros. Esses comportamentos podem levar a resultados imprevisíveis e causar problemas de segurança ou falhas no programa. Para minimizar tais riscos, é importante seguir as melhores práticas de programação e estar atento a possíveis comportamentos indefinidos ao escrever e revisar seu código.

Neste roteiro não vamos nos atentar a formatacão do código (nomenclatura, estilo).

Variáveis Globais

Rule 1.1

Somente usar variáveis globais para passar informacoes de uma interrupcão (ISR) para a funcão main.

Em projetos mais complexos, essa regra pode ser flexibilizada, mas isso deve ser abordada com cautela e planejamento. Devido ao tempo limitado disponível para desenvolvermos boas práticas com vocês, estamos o uso de variáveis globais apenas nessas situações.

Exemplo

O exemplo a seguir demonstra um uso errado de variáveis globais:

  • void foo(void): A funcão foo acessa a variável global a
  • int b: Poderia pertencer ao escopo da funcão main
int a = 0; // var global
int b = 0; // var global

void foo(void) {
    a = a + 1; // acessa variavel global
}

void main(void) {
    while (1) {
        foo();

        if (a > 5) {
            b = 1;
        }
    }
}

O código anterior viola a regra 1.1 nas duas variáveis ( a e b ) gerando o seguinte erro:

Exercise

Qual alternativa a seguir seria uma solucão válida para corrigir o código?

  • Declara a e b local e acessa a como global
  • Declara foo dentro da funcão main
void main(void) {
    int a = 0;
    int b = 0;

    void foo(void) {
        a = a + 1; // acessa variavel global
    }

    while (1) {
        foo();

        if (a > 5) {
            b = 1;
        }
    }
}
  • Declara a e b local e acessa a como global
void foo(void) {
    global a;  // apenas a é global
    a = a + 1;
}

void main(void) {
    global int a = 0;
    int b = 0;

    while (1) {
        foo();

        if (a > 5) {
            b = 1;
        }
    }
}
  • Declara a e b local, e acessa a com ponteiro
void foo(int &a) {
    *a = *a + 1; // acessa ponteiro
}

void main(void) {
    int a = 0;
    int b = 0;

    while (1) {
        a = foo(&a);

        if (a > 5) {
            b = 1;
        }
    }
}

Praticando

Vamos praticar um pouco e corrigir as regras básicas de qualidade de código e boas práticas em sistemas embarcados, para isso crie um repositório pelo github classroom e então modifique os arquivos conforme indicado.

Variáveis globais

Se o classroom não funcionar, acesse o repositório a seguir, clone e faça a entrega por ele:

  • Analise o log do actions e verifique que o cppcheck executou e encontrou alguns erros.
  • Corrija o código (rules_basic_variable.c) e verifique se os erros ainda continuam.

Dica: reescreva a funcão foo para um dos casos a seguir:

  • int foo(int a)
  • void foo(int *a)