Jump to content
Sign in to follow this  
RJSC

C embedded - PIC - Variaveis Globais, Flags, Interrupts...

Recommended Posts

RJSC

Ora bem, sendo um "Hardware Guy" venho aqui fazer umas perguntas aos "Software Guys".

Supostamente é má prática usar variáveis globais. Mas...

Quando se precisa duma FLAG para nos facilitar a vida o que é que se deve fazer?

As flags só funcionam como variáveis globais mas depois a reutilização de código fica complicada  ;)

Sugestões? Passar flags como parâmetros ás funções?

Share this post


Link to post
Share on other sites
Triton

Se a utilização de uma variável global for conveniente e facilitar o código, então na minha opinião não é uma má prática.


<3 life

Share this post


Link to post
Share on other sites
pixel

Pois é, por vezes é mesmo necessário usar variáveis globais.... Deve é ter-se em mente que não é boa prática, e isto porque, se perde a noção de "como é que as coisas acontecem", por exemplo:

void main(void)
{
int a, b;

a = 3;
b = 5;
soma (a, b);
mostra_soma();
}
 

neste caso teria que ser usada uma variável global para que os dados passem de dentro da função soma para dentro da função mostra_soma :

int result;

void soma (int par1, int par2)
{
result = par1 + par2;
}

void mostra_soma (void)
{
printf("resultado = %d\n", result);
}
 

este pequeno programa fica muito melhor se não se usarem variáveis globais, e se o dados forem passados por parâmetros:

void soma (int par1, int par2)
{
return par1 + par2;
}

void mostra_soma (int reslut)
{
printf("resultado = %d\n", result);
}

void main(void)
{
int a, b, c;

a = 3;
b = 5;
c = soma (a, b);
mostra_soma(c);
}
 

Neste último caso, percebe-se perfeitamente que na primeira função é calculado o valor que é mostrado pela segunda função!

Quando se programa em "baixo nível" as coisas são diferentes, e por vezes, é necessário perder alguma dessa legibilidade do código de forma a melhorar, por exemplo, a velocidade de processamento ou a ocupação da memória de dados.

Outros exemplos do não cumprimento desta regra são a utilização de flags (como é dito do título deste post) e buffers.

A utilização destas variáveis globais explica-se facilmente por ser o resultado do processamento de funções especais (as funções de interrupção). Estas funções são especais, porque não são chamadas pelo "fluxo" do programa. Por exemplo uma função que atenda a interrupção de uma porta série tem que ser executada imediatamente após se verificar a recepção de um byte por essa porta série. Como o processamento desta informação tem que ser rápido (antes que chegue mais dados que apaguem os primeiros) quem chama esta função é o próprio Hardware. O programa tem que agir rapidamente, deve guardar o byte recebido num buffer e deve levantar uma flag. Quando a execução da interrupção termina, o programa volta ao seu "fluxo" normal, e este deve ter informação de que foi recebido um byte (flag activa) e ainda qual foi este byte (é aquele que está guardado no buffer).

Share this post


Link to post
Share on other sites
Njay

"embedded" é uma palavra que ainda abrange bastantes sistemas, desde máquinas com 1K a máquinas com 256MB ou mais. Em máquinas pequeninas às vezes temos mesmo que "fazer truques"... mas ainda assim há sempre formas de tornar o código legível ou melhor organizado. No caso das flags, podes por exemplo ter à mesma uma variável global mas depois usar funções para aceder à variável, e assim "isolar" num pequeno bloco todo o código que acede à variável global. A penalidade de tempo de execução por utilização destas funções quando comparado com acesso directo à variável é na verdade ZERO, desde que uses macros ou funções inline para as implementar. Não perdes nada em eficiência nem espaço e manténs a organização.

Convém conhecer bem o compilador e algumas funcionalidades mais "recondidas" do C como o inline.

Deixo-te um exemplo de uma nano-biblioteca (e não libraria ou livraria como já vi por aí) para lidar com flags:

static int  gFlags = 0;

inline void flag_set (int flagid)
{
    gFlags |= flagid;
}

inline void flag_reset (int flagid)
{
    gFlags &= ~flagid;
}

inline int flag_isset (int flagid)
{
    return (gFlags & flagid) != 0;
}

A variável global é declarada e usada apenas neste bloco, e o resto do código utiliza apenas as funções, não lhe interessando sequer saber como é que as flags são implementadas.

Tal como está acima é para ser usado no mesmo ficheiro .c. Para poderem ser usadas (partilhadas) em vários ficheiros é necessário ter as funções e um protótipo da variável global num .h e a declaração e inicialização da variável num .c (num ficheiro que pode ser usado exclusivamente para esta nano-biblioteca). O static tem que ser removido.

Um aspecto importante na legibilidade do código é teres regras para os nomes dos objectos do programa. Uma das regras que uso é que todas as variáveis globais (e apenas estas) são prefixadas com "g". Ao olhar para um pedaço de código sei logo se uma certa variável é global ou outra coisa. Mais abaixo vais ver que prefixo sempre uma constante enumerada com "e".

E já agora, o código acima é re-utilizável!

Para o código ser rápido, o "flagid" já é uma máscara de bits. Podes declarar as tuas flags por exemplo usando um enumerado, o que torna a sua utilização bastante legível:

enum {
    eSerialWait  = 1 << 0,
    eSerialRx    = 1 << 1,
    eSerialTx    = 1 << 2,
} SerialFlags_e;
...

flag_set(eSerialWait);
...

if (flag_isset(eSerialTx))
{
    ...

Resumindo, usar variáveis globais não implica perda de estrutura, abstracção nem legibilidade. É uma questão de escolher uma implementação adequada.


Blog: Tróniquices ~ Projecto: EmbeddedDreams.com

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.