Página 1 de 2
LPC2368 + RTOS Keil

Enviado:
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

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

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

Enviado:
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?

Enviado:
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 ();
}

Enviado:
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

Enviado:
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!

Enviado:
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 .

Enviado:
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

Enviado:
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.

Enviado:
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

Enviado:
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.

Enviado:
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.

Enviado:
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?

Enviado:
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.
+++