Página 1 de 2

LPC2368 + RTOS Keil

MensagemEnviado: 16 Abr 2008 17:53
por lrfad2
Boa tarde gente.
Estou eu aqui de novo com dúvidas para transgredir meu projeto do LPC2138 para o LPC2368.
Agora o foco é o RTOS da keil. Alguém já mexeu, utilizando o LPC2368?
O arquivo de configuração que tenho o RTX_Config.c pelo que vejo é dedicado à familia 21xx.
Eu tentei modificar algumas coisas no código fonte como o VICDefVectAddr, pois acusava erro.
Fazendo a debugação passo a passo percebi que ele vai para a interrupção de software quando tenta alocar memória para o stack, e não trava ali

Em outras palavras ele gera uma interrupção de software e não tem ninguem para atendê-la (Acredito eu)

Se alguem ja passou por isso e puder me ajudar eu agradeço muito
abraço a todos

MensagemEnviado: 17 Abr 2008 19:31
por Viktor
Pega o arquivo de configuração que está em : C:\Keil\ARM\Boards\Keil\MCB2300\RTX_Blinky

MensagemEnviado: 22 Abr 2008 10:26
por lrfad2
Deu certo
Obrigado Viktor

MensagemEnviado: 19 Nov 2008 09:59
por anderson.correia
Bom dia a todos.
Alguém saberia me dizer de a rotina de watchdog quando se utiliza RTOS e a mesma idéia e conceito de não temos RTOS? É que tenho uma aplicação na empresa, onde após ligarmos o WDT, ela começou a resetar. E falando de WDT clásico, sua configuração está correta, recarregando os registradores WDFEED com s seguencia 0xAA e depois 0x55.
Não sei se em RTOS, o conceito seria diferente. Alguem poderia me ajudar?

MensagemEnviado: 20 Nov 2008 11:20
por austrax
Anderson, o conceito é o mesmo, mas você deve considerar o tempo total de trabalhado do RTOS e o tempo máximo utilizado pelas tarefas para o calculo do tempo de estouro do cachorrão, senão é reset para todo lado rsrs... e após isso criar uma tarefa que reseta o mesmo durante a operação. Por exemplo, para o lpc2368:

Configuro o watchdog antes de iniciar o RTOS
Código: Selecionar todos
/******************************************************************************
** Descrição:      FUNÇÃO PRINCIPAL
*****************************************************************************/
int main (void) {
   configura_sistema();
   
   WDCLKSEL= 0x00000001; //seleciona fonte de clock o cristal para o watchdog
   WDTC =    0x0599ffff;
   WDMOD |=  0x00000003;
   WDFEED = 0xAA;      
   WDFEED = 0x55;
     os_sys_init (inicia);

   for(;;);                   
}



Crio uma tarefa para resetar o contador. Coloquei uma variável de controle pois é muito útil, por exemplo, para fazer um reset por software ou para implementar uma proteção



Código: Selecionar todos

/*****************************************************************************
** Descrição:      TAREFAS RTOS - CACHORRO BRAVO
*****************************************************************************/
void watchdog (void) __task {
   WDCLKSEL= 0x00000001; //seleciona fonte de clock o cristal para o watchdog
   for (;;){
      delay(1);
      if(!reset){
         WDTC =    WDTEMPO; //constante com o tempo de estouro
         WDMOD |=  0x00000003;
         WDFEED = 0xAA;      
         WDFEED = 0x55;
      }
   }   
}


Na tarefa de inicialização, coloco como primeira tarefa a ser iniciada para o sistema não resetar durante a criação das demais tarefas...

Código: Selecionar todos
*****************************************************************************
** Function name:      TAREFAS RTOS - INICIALIZAÇÃO DO SISTEMA
*****************************************************************************/
void inicia (void) __task {   
   t_inicia = os_tsk_self ();
   
   debug("PRO-CONTROL SERVICOS INDUSTRIAIS\r\n"
             "HKM MACHINE - REVISAO 1.0\r\n"
             "Aguarde inicializacao do sistema...\r\n");

   t_watchdog =        os_tsk_create (watchdog, 0);

   /*INCIA SD CARD E FAT SYSTEM*/
   finit();

   /*HABILITA PWM*/
//   PWM1TCR = 0x00000009;

   /*PINO GERA INTERRUPÇÃO*/
                IO0_INT_EN_R |= ENCH_1;
   
   /*INICIA TAREFAS*/
   
   t_funcionando =      os_tsk_create (funcionando, 0);
    t_encoders =         os_tsk_create (encoders, 0);
   t_sensores =         os_tsk_create (sensores, 0);
   t_prepara=           os_tsk_create (prepara, 0);   
   t_relogio =          os_tsk_create (relogio, 0);
   t_sdcard =              os_tsk_create (sdcard, 0);
   t_le_eeprom =        os_tsk_create (le_eeprom, 0);
   t_escreve_eeprom=    os_tsk_create (escreve_eeprom, 0);
   t_menu =             os_tsk_create (menu, 0);
     t_biometria =          os_tsk_create (biometria , 0); 
    t_teclado =         os_tsk_create (teclado, 0);
    t_zigbee =          os_tsk_create (zigbee, 0);
    t_motores =         os_tsk_create (motores, 0);
   t_alarme =         os_tsk_create (alarme, 0);
   t_luzbuzina=       os_tsk_create (luzbuzina, 0);

   /*ATIVA INTERRUPÇÕES SERIAIS*/
   U0IER   = 0x00000001;
   U1IER   = 0x00000001;

   /*HABILITA I2C*/
   I20CONSET = 0x00000040;


   /*INICIA CAIXAS DE MENSAGENS*/
   os_mut_init (critico);
   os_mbx_init (msgemail, sizeof(msgemail));
   os_mbx_init (msgsdcard, sizeof(msgsdcard));
   os_mbx_init (msgzigbee, 20);
   os_mbx_init (msglcd, sizeof(msglcd));
   os_mbx_init (msgbiometria, sizeof(msgbiometria));
   os_mbx_init (msgteclado, sizeof(msgteclado));
   os_mbx_init (msgrelogio, sizeof(msgrelogio));
//   os_mbx_init (msgsensores, sizeof(msgsensores));   

   seta_evento(t_prepara);
               
    os_tsk_delete_self ();
}

MensagemEnviado: 21 Nov 2008 08:49
por anderson.correia
Muito obrigado pela ajuda austrax, achei muito interessante seu post. Acabei ficando com algumas dúvidas.

Eu consegui corrigir o problema da seguinte forma:
Eu configuro primeiramente periféricos, timers, RTC, WDT, UART's, I2C, Interrupções e por ultimo inicio as tasks. Tenhos somente duas taks.

Config WDT para estouro a cada 3s.
void InitWDT (void)
{
//Wdperiod = Pclk x WDTC x 4
//WDTC = Wdperiod /(PCLK * 4) => WDTC = (Wdperiod x FreqClk)/4 => WDTC = (1s x 70^6)/4 => WDTC = 17500000;

if (liga_wdt == true)
{
WDTC = 52500000; //17500000; //acerta o estouro do WDT em 3s
WDFEED = 0xAA;
WDFEED = 0x55;

WDCLKSEL = 0x01;
WDFEED = 0xAA;
WDFEED = 0x55;

WDMOD = WDMOD | 0x03; //Operate with the Watchdog interrupt and WDRESET
// WDCLKSEL = 0x01;
WDFEED = 0xAA;
WDFEED = 0x55;
}
}



Subrotina para refresh do WDT:
void takt(void)
{
// possivel rotina wd
if ((liga_wdt == true))// && (init_task == true))
{
tsk_lock();
VICIntEnClr = 0xFFFFFFFF;
WDFEED = 0xAA;
WDFEED = 0x55;
VICIntEnable = 0x300000D0;
tsk_unlock();
}
}


Na verdade, eu não deixo o RTOS chavear de task durante a rotina de refresh do WDT, mais mesmo assim ainda davam alguns reset esporádicos. Aí desliguei as interrupções para evitar a possibilidade de em algum momento ocorrer interrupção nesse processo, oque atrapalharia a seguencia de 0xAA e 0x55, resetando. Isso realmente resolveu mei problema, o dispositivo ficou ligado por dois dias sem nenhum reset por WDT. Eu leio o RISR e armazeno na e2prom, para guardar os reset, por isso sei que não ocorreram

Agora a dúvida:

Eu não tenho uma task para WDT, tenho somente uma subrotina para limpa-lo, que de tempos em tempos, eu dou um refresh, antes de 3s

Dessa forma pode ocorrer algum problema? Em RTOS é melhor criar uma task para o WDT?

Obrigado, e até mais

MensagemEnviado: 21 Nov 2008 10:40
por msamsoniuk
o interessante eh colocar o watchdog em uma task pq se o RTOS parar de escalonar eh pq tem algo realmente errado e o sistema reinicializa!

MensagemEnviado: 21 Nov 2008 11:01
por proex
Nao se deve colocar a instruçao Clear Watchdog dentro de eventos de interrupçao, pois mesmo estando o programa travado, a interrupçao continua ocorrendo e tudo que estiver dentro dela será executado, inclusive o Clear Watchdog .

MensagemEnviado: 21 Nov 2008 11:06
por austrax
Como disse nosso amigo Marcelo, o ideal é colocá-lo em uma tarefa. Tive problemas quando comecei a utilizá-lo, pois não havia calculado corretamente o tempo máximo para que em nenhuma situação ele estourasse, a não ser no travamento do rtos.

Abraço

MensagemEnviado: 21 Nov 2008 13:25
por anderson.correia
Minha rotina para refresh do WDT está fora de uma interrupção. Aí qualquer task rotando, manda limpar o registrador. Aí nesse momento, descobri que tenho que desligar o chaveamento das tasks e desligar as interrupções nesse momento.

Dentro de uma task, só me garante que o RTOS não vai ficar louco no chaveamento das taks, mais e quando as demais task estiverem rodando? e se elas travarem? por isso eu achei interessante deixa-las fora, em um sub rotina.

MensagemEnviado: 22 Nov 2008 09:05
por Viktor
anderson.correia escreveu:... por isso eu achei interessante deixa-las fora, em um sub rotina.



Não existe isso. Num sistema com RTOS ou é chamado por uma tarefa ou por interrupção. O fato de estar numa subrotina não quer dizer nada

MensagemEnviado: 28 Nov 2008 11:44
por anderson.correia
Boa tarde.
Realmente implementando uma task para o WDT parece que ficou mais estável. Estou fazendo mais testes, e depois eu posto aqui os resultados.

Obrigado a todos.

MensagemEnviado: 28 Nov 2008 11:51
por anderson.correia
Boa tarde.
Realmente implementando uma task para o WDT parece que ficou mais estável. Estou fazendo mais testes, e depois eu posto aqui os resultados.

Obrigado a todos.

MensagemEnviado: 02 Dez 2008 15:07
por anderson.correia
Boa tarde.
Gostaria de agradecer a todos mais uma vez. Realmente o problema da WDT foi corrigido, com a implentação de uma task para limpar o WDT. Agora surgiu um outro problema interessante:

-Para eu conseguir debugar via U-link, eu preciso desligar o WDT. Até aí, acredito eu que seja normal. Está correto?

-Ao ligar o WDT, e gravar pelo U-link, na próxima vez que eu tentar gravar via U-link, não consigo mais. Para conseguir novamente, eu preciso apagar totalmente via serial utilizando o "flash Magic", aí sim ela volta operar.

Alguem já pegou algo do tipo?

MensagemEnviado: 02 Dez 2008 15:29
por andre_luis
Apenas pra complementar o raciocínio.....

Já crriei uma função de watch-dog que só operava se fosse de modo encadeado, tipo :

Código: Selecionar todos
void ClearWDT ( char pointer )
{
static char internal_pointer = 0 ;
internal_pointer = pointer    ;
switch ( internal_pointer )
   {
   case 0 : ClrWdt() ; internal_pointer = 1 ; break ;
   case 1 : ClrWdt() ; internal_pointer = 2 ; break ;
   case 2 : ClrWdt() ; internal_pointer = 0 ; break ;
   }
}


Isso garantiria que mesmo um travamento local ( loop infinito ) contendo o ClrWdt() não travaria o sistema.

+++