Perdendo um flag

Software e Hardware para ATMEL

Moderadores: 51, guest2003, brasilma

Perdendo um flag

Mensagempor RobL » 28 Jul 2012 11:52

Estou apanhando para entender o que está acontecendo em uma aplicação simples e banal.
Estou usando um ATmega48, o foco do problema está com o registro GPIOR0. Trabalhando em C com o toolchain da Atmel.

Seto um flag na interrupção do timer 2. Este flag está no bit 1 de GPIOR0.
O assembler gerado é uma instrução SBI do tipo (R-M-W). Esta int. ocorre a cada segundo.

O clock está com 4Mhz rodando o código.

Em um trecho do main() este flag é testado e soma uma unidade a uma variável.

Faço o teste com 1000 segundos (1000 incrementos) e perco 4 segundos, objetivamente.

Fiz os seguintes testes:
1- O flag da interrupção estaria sendo perdido ?
Executei a tarefa dentro da int. Não gerou erro.

2- Por um erro de digitação este flag estaria sendo alterado em outro trecho do programa. Não achei onde.
Troquei o bit 1 pelo 6 e o erro continuou.

3- No trecho que está testando o flag e após desviar limpo o flag. Tirei a interrupção neste trecho.
Contiunou o erro.

4- Imaginei algo com (Read-Modify-Write).
Modifiquei o programa para evitar instruções SBI ou CBI (RMW). Não deu certo, continuou perdendo o flag.

5- Mudei o flag para o registro GPIOR1 que está em outra posição da memo e não usa (RMW). Funcionou corretamente. Tive que deixar assim.

6- Analisei a possibilidade da salva de contexto na int do timer zero que trabalha bastante em cima de GPIOR0 e seus bits, mas não encontrei nada que pudesse estar modificando o flag no bit 1.

Cabe observar que cinematicamente a velocidade de execução do programa é sem sincronismo com timer2 a cristal. Isto dá um certo movimento onde a int do timer 2 ocorre em diversos pontos do programa.

Onde e por que este flag está sendo perdido ????
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor zazulak » 30 Jul 2012 16:14

Olá,

no caso, o compilador que voce está usando é o GCC, correto? Já vi ele criar problema dependendo do nível de otimização escolhido na hora de compilar.

Poste o trecho do código onde ocorre o problema aqui, assim fica mais fácil tentar ter uma idéia do que ocorre.
zazulak
Nibble
 
Mensagens: 97
Registrado em: 06 Out 2007 16:40

Mensagempor RobL » 30 Jul 2012 18:23

Não é um problema de compilação nem optimização. O flag é gerado corretamente. Verifiquei pelo assembly gerado.
O problema é dinâmico, rodando o programa e só ocorre usando o registro GPIOR0. Não ocorre se este flag é posto no GPIOR1. Veja as tentativas acima.
Me preocupa muito, não ter conseguido compreender este fato.
Devido o erro ocorrer 4 vezes em 1000 leituras (16minutos), mais provavelmente de forma aleatória, talvez só consiga descobrir analisando com um trace que não está disponível.
Em algum momento, em alguma parte do programa, alguém derruba este flag. Novamente, veja as tentativas de descobrir onde, acima. Será que esqueci algo mais?

Grato.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor andre_luis » 31 Jul 2012 07:27

Existe microcontrolador onde certas instruções de leitura de flag SFR, o modificam, como no caso específico daqueles relacionados á interrupção.

Verifica se pode estar sendo o seu caso.


+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Mensagempor RobL » 31 Jul 2012 10:16

Neste micro isto pode ocorrer em certos registros com instruções RMW, ligados a flags de periféricos.
No caso, este é um registro do usuário e o flag também foi criado pelo usuário. Curiosamente, este registro GPIOR0, setar e ressetar flag (bit) usa instrução RMW, porém estas, neste caso, não teriam por que mudar um bit qualquer, pois este registro não está ligado a nenhuma porta ou periférico.
Conforme coloquei, quando mudo, o flag, para outro registro, em outro endereço, porém, registro com a mesma função (finalidade), o erro não ocorre e por coincidência este registro GPIOR1 não usa instruções RMW.
Consegui gerar um código,usando o registro GPIOR0, que dá problema, sem instrução RMW, mas o erro continuou. Então me parece não ser o caso.
Obrigado pela sugestão.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor RobL » 01 Ago 2012 18:29

Descobri a roda.
O problema foi a mistura do mal estrutural de certos registros nos AVRs e linguagem C, devido aos códigos gerados pelo compilador e não por quem está programando.
Quando pensei que fosse um problema de RMW, testei mudando somente um trecho do programa, evitando essas instruções. Errei em não mudar outro trecho que atuaria no mesmo registro usando instruções RMW por culpa e decisão do compilador.
Outro detalhe que nunca atentei é que as instruções SBI e CBI não são atômicas e podem ser interrompidas na fase Modify!!! Sim em certos AVRs elas tem 2 ciclos, como neste que estou usando ATmega48 e família. Nos Tinys tem e Xmega tem 1 ciclo !!!
Vocês não podem imaginar como um simples programa de incrementar a cada segundo pode te deixar doido. Só mais um detalhe, conforme suprimia parte do código, para teste, mudava o percentual de erro. Quase fui para o hardware, como verificar instabilidade por ruído, etc.
Nunca crie uma interrupção "super rápida" que set um só bit através de uma instrução RMW, pois, nos ARVs SBI ou CBI, não muda nenhum flag de status e o código gerado não precisa salvar o contexto.
Se esta interrupção acontecer entre o primeiro e segundo ciclo de outra RMW, que estava sendo executada, no mesmo registro, dá caca.

Grato pelas sugestões.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56


Voltar para AVR

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x