Página 1 de 1

Reset Indevido no PA60

MensagemEnviado: 19 Mai 2014 13:35
por mega.rod
Olá amigos,

Estou com problema na interrupção de Timer do PA60. O micro se reinicia o tempo todo. Onde pode estar o problema?

Código: Selecionar todos
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */

#define buzzer                  PORT_PTCD_PTCD3

char contaBuzzer=0;

//*******************************Rotinas de temporização**********************************************
void delay_ms(unsigned int tempo)       //Função de atraso para "x" milisegundos
{
  unsigned int temp;
  for (;tempo;tempo--)
  {
    for(temp=(80000/110);temp;temp--);   /* feeds the dog */
    __RESET_WATCHDOG();
  }
}
//****************************************************************************************************

interrupt VectorNumber_Vmtim0 void MTIM0_ISR(void)
{
   MTIM0_SC_TOF = 0;
   
   if(contaBuzzer) {contaBuzzer--; buzzer=1;} else buzzer=0;
}

void Inicializa(void)
{
   SYS_SOPT1_RSTPE = 1;      //Habilita pino de Reset
   SYS_SOPT1_BKGDPE = 1;      //Ativa o pino de depuração
   PMC_SPMSC2 = 0b01110000;    //Configura o LVD
   
   PORT_PTCOE = 0b00001000;
   
   //Configuração da interrupção de Timer
   MTIM0_SC_TSTP = 1; /* stop counter */
   MTIM0_CLK = 0b010000; /* use FIXED clock ICSFFCLK and prescaler /128 */
   MTIM0_MOD = 0; /* must clear MOD register */
   MTIM0_SC |= MTIM0_SC_TOF_MASK; /* write MTIMx_SC to clear TOF first */
   MTIM0_SC_TOIE = 1; /* then set TOIE bit */
   MTIM0_SC_TSTP = 0; /* clear TSTP to start free-running counter */
}

void main(void)
{
   DisableInterrupts;
   
   Inicializa();
   
   EnableInterrupts;
   /* include your code here */
 
   buzzer=1;
   delay_ms(10);
   buzzer=0;
   
   //contaBuzzer=1;
   
   for(;;)
   {
      __RESET_WATCHDOG();   /* feeds the dog */
   } /* loop forever */
     /* please make sure that you never leave main */
}



Abraço!

Re: Reset Indevido no PA60

MensagemEnviado: 19 Mai 2014 21:19
por andre_luis
Não conheço nada desse microcontrolador e nem das macros do compilador, mas meu palpite é que esse problema deve estar ocorrendo devido ao resset do contador de WatchDog ( __RESET_WATCHDOG() ) estar sendo executado internamente na rotina de Delay somente no final, não dando tempo suficiente para que atue.

Experimenta num teste grosseiro, o mudar de lugar:

Substitui isso...
cpp code
void delay_ms(unsigned int tempo)       //Função de atraso para "x" milisegundos
{
unsigned int temp;
for (;tempo;tempo--)
{
for(temp=(80000/110);temp;temp--); /* feeds the dog */
__RESET_WATCHDOG();
}
}

Por isso...
cpp code
void delay_ms(unsigned int tempo)       //Função de atraso para "x" milisegundos
{
unsigned int temp;
for (;tempo;tempo--)
__RESET_WATCHDOG();
{
for(temp=(80000/110);temp;temp--); /* feeds the dog */
}
}


Ou então, simplesmente não utilize valores de Delay tão alto assim, a menos que os intercale com Wathdog, como abaixo:
cpp code
delay_ms(1);
__RESET_WATCHDOG();
delay_ms(1);
__RESET_WATCHDOG();
delay_ms(1);
__RESET_WATCHDOG();
...


obs.:
Isso, presumindo que 1s seja suficiente para não ressetar ( não sabemos como Watchdog está configurado no seu uC )


+++

Re: Reset Indevido no PA60

MensagemEnviado: 19 Mai 2014 21:53
por mega.rod
Olá André,

De fato, o motivo do reset é o Watchdog. O problema é que não entendo o porque, já que o comando de reset é ciclicamente executado.

Alterei o código desta maneira:
Código: Selecionar todos
interrupt VectorNumber_Vmtim0 void MTIM0_ISR(void)
{
   MTIM0_SC_TOF = 0;
   
   if(contaBuzzer) {contaBuzzer--; buzzer=1;} else buzzer=0;
}

void Inicializa(void)
{
   SYS_SOPT1_RSTPE = 1;      //Habilita pino de Reset
   SYS_SOPT1_BKGDPE = 1;      //Ativa o pino de depuração
   PMC_SPMSC2 = 0b01110000;    //Configura o LVD
   
   PORT_PTCOE = 0b00001000;
   
   //Configuração da interrupção de Timer
   MTIM0_SC_TSTP = 1; /* stop counter */
   MTIM0_CLK = 0b010000; /* use FIXED clock ICSFFCLK and prescaler /128 */
   MTIM0_MOD = 0; /* must clear MOD register */
   MTIM0_SC |= MTIM0_SC_TOF_MASK; /* write MTIMx_SC to clear TOF first */
   MTIM0_SC_TOIE = 1; /* then set TOIE bit */
   MTIM0_SC_TSTP = 0; /* clear TSTP to start free-running counter */
}

void main(void)
{
   DisableInterrupts;
   
   Inicializa();
   
   EnableInterrupts;
   /* include your code here */
 
   buzzer=1;
   //delay_ms(10);
   //buzzer=0;
   
   //contaBuzzer=1;
   
   for(;;)
   {
      __RESET_WATCHDOG();   /* feeds the dog */
   } /* loop forever */
     /* please make sure that you never leave main */
}



Obs.: O problema ainda acontece.

Obrigado!

Re: Reset Indevido no PA60

MensagemEnviado: 19 Mai 2014 22:06
por andre_luis
O Watchdog está configurado para atuar em que intervalo de tempo ?
Olhando o código acima não consegui identificar...


+++

Re: Reset Indevido no PA60

MensagemEnviado: 20 Mai 2014 00:36
por cfreund
Ou por isso:

cpp code
void delay_ms(unsigned int tempo)       //Função de atraso para "x" milisegundos
{
unsigned int temp;
for (;tempo;tempo--)
{
for(temp=(80000/110);temp;temp--) __RESET_WATCHDOG(); /* feeds the dog */
}
}


Terá de alterar essa constante.

Re: Reset Indevido no PA60

MensagemEnviado: 20 Mai 2014 20:06
por mega.rod
Problema encontrado. É preciso desabilitar as interrupções globais do micro antes de resetar o watchdog. Se não fizer isso, simplesmente qualquer interrupção invalida a sequência de reset do watchdog. Vide item 21.3.1.2 do manual de referência:

"21.3.1.2 Refreshing the Watchdog
The refresh write sequence is a write of 0xA602 followed by a write of 0xB480 to the
WDOG_CNTH:L registers. The write of the 0xB480 must occur within 16 bus clocks
after the write of 0xA602; otherwise, the watchdog resets the MCU.

Note
Before starting the refresh sequence, disable global interrupts.
Otherwise, an interrupt could effectively invalidate the refresh
sequence if writing the four bytes takes more than 16 bus
clocks. Re-enable interrupts when the sequence is finished.


Ficou assim:
Código: Selecionar todos
for(;;)
   {
      DisableInterrupts; // disable global interrupt
      __RESET_WATCHDOG();   /* feeds the dog */
      EnableInterrupts; // enable global interrupt
   } /* loop forever */
     /* please make sure that you never leave main */


Créditos: Eng° Marco Aurélio da Siletec.

Obrigado a todos!