Página 1 de 2

RTOS para HCS08

MensagemEnviado: 11 Fev 2011 16:00
por Red Neck Guy
http://helium.sourceforge.net/

Alterei pra rodar em uma placa com 9S08AC128, ficou bem legal. O footprint dele é de 2k7 para código e 2k5 para ram. Eu estou vendo o que dá pra tirar fora pra baixar pra uns 2k de ram.
Estou testando na placa DEMOAC com 4 threads, cada uma piscando um led com tempos diferentes. Agora vou colocar as interrupções das serias, i2c e capturas pra ver como fica.


Código: Selecionar todos
//Código da thread de teste
void ThreadA(int data){
  unsigned char toggle=0xFF;
  unsigned char led;
 
  LED_1_DIR = 1;
  LED_2_DIR = 1;
  LED_3_DIR = 1;
  LED_4_DIR = 1;
 
  led = (unsigned char)(data>>12);
  data &= 0xfFF;

  for(;;){

    toggle = ~toggle;   
   
    switch(led){
      case 0: LED_1_PIN = toggle;
              break;     
      case 1: LED_2_PIN = toggle;
              break;     
      case 2: LED_3_PIN = toggle;
              break;     
      case 3: LED_4_PIN = toggle;
              break;
    }
       
    sleep(data);   
  }
}


Código: Selecionar todos

//criação das threads
  (void)ThreadCreate(5, ThreadA, ThreadAStack,64,(void*) 100);
  (void)ThreadCreate(5, ThreadA, ThreadBStack,64,(void*) (0x1000 |200));
  (void)ThreadCreate(5, ThreadA, ThreadCStack,64,(void*) (0x2000 |400));
  (void)ThreadCreate(5, ThreadA, ThreadDStack,64,(void*) (0x3000 |800));


Acho que uma pequena melhoria que vou realizar é criar a stack de cada thread dentro dessa função ThreadCreate.
[/url][/code]

MensagemEnviado: 12 Fev 2011 14:17
por Red Neck Guy
Basicamente alterei isso:

Código: Selecionar todos
ClearInterrupt:

   ;Apaga o flag de interrupção do canal zero
   ;e configura a interrupção para o próximo período
   LDHX TPM1C0V
   AIX  #100
 

   lda TPM1C0SC
   and #$7E
   sta TPM1C0SC
   
   STHX TPM1C0V   


e isso

Código: Selecionar todos
void enableRTC(void){
  TPM1SC   = 0b00001111; 
  TPM1MOD  = 0x0000;   
 
  TPM1C0SC = 0x50;   
  TPM1C0V  = TPM1CNT + 100;
}

MensagemEnviado: 12 Fev 2011 14:20
por Red Neck Guy
"... não é necessario RTOS para desenvolver firmware de centrais de alarme ..." (Um ex-colega de uma empresa lá de Porto Alegre durante uma conversa denegrindo a minha imagem profissional para o ex-chefe do RS)

"... você pode ir trabalhar de carroça ao invés de ter um carro...."
Minha réplica.

MensagemEnviado: 12 Fev 2011 14:24
por msamsoniuk
usar um RTOS eh uma **** mao na roda!

eu fiz isso aqui em uma semana para testar alguns conceitos de escalonamento baseado em passagem de mensagem, mas daih acabou a memoria (4KB). eu parei e comprei um mcu novo com 8KB, mas demorou muito para chegar e a inercia dominou a minha mente! :(

http://framework.sourceforge.net/pics/hc908rtos/trunk/

MensagemEnviado: 12 Fev 2011 15:34
por Red Neck Guy
A preempção e fila de mensagens facilitam um monte a vida do desenvolvedor... Mas fazer o que, tem gente que gosta de gastar um tempo enorme criando os intertravamentos da aplicação e quando chega na hora de colocar a mão-na-massa, o código já está uma zona que ninguém mais se acha.

MensagemEnviado: 12 Fev 2011 15:34
por Red Neck Guy
A preempção e fila de mensagens facilitam um monte a vida do desenvolvedor... Mas fazer o que, tem gente que gosta de gastar um tempo enorme criando os intertravamentos da aplicação e quando chega na hora de colocar a mão-na-massa, o código já está uma zona que ninguém mais se acha.

MensagemEnviado: 12 Fev 2011 15:58
por enigmabox
Outra ideia, ao inves de usar o contador interno do MCU pra gerar as interrupções entre as tasks ou mudança de tarefa, será que nao fica bom, fazer um oscilador externo na mesma frequencia e ativar via interrupção do MCU?
Assim fica o contador interno pra outras tarefas, no RTOS.
:wink:

MensagemEnviado: 12 Fev 2011 16:28
por msamsoniuk
eu nao cheguei a implementar escalonamento preemptivo, mas o HC908 que eu uso tem um realtime clock que pode ser utilizado para isso, de modo que os dois timers principais continuariam livres para aplicacoes especificas de IO, como pwm.

enigmabox escreveu:Outra ideia, ao inves de usar o contador interno do MCU pra gerar as interrupções entre as tasks ou mudança de tarefa, será que nao fica bom, fazer um oscilador externo na mesma frequencia e ativar via interrupção do MCU?
Assim fica o contador interno pra outras tarefas, no RTOS.
:wink:

MensagemEnviado: 12 Fev 2011 16:35
por Red Neck Guy
enigmabox escreveu:Outra ideia, ao inves de usar o contador interno do MCU pra gerar as interrupções entre as tasks ou mudança de tarefa, será que nao fica bom, fazer um oscilador externo na mesma frequencia e ativar via interrupção do MCU?
Assim fica o contador interno pra outras tarefas, no RTOS.
:wink:


Até pode ser...
Mas no meu caso, os canais do tpm que sobram desse timer em conjunto com os to tpm2 e tpm3 dão conta do que eu preciso.

MensagemEnviado: 12 Fev 2011 17:00
por enigmabox
Falo isso, porque já fiz alguns projetos onde o encoder incremental estava sincronizado com o timer/counter e a cpu de tempo em tempo lia o valor deste counter para saber em que posição estava o encoder. Então o Counter era bem utilizado.
Se houver um timer externo e com freq. variavel, por ex. um 555 e um flip-flop, poderia com o S. O. rodando analizar a eficiencia da troca de tasks da cpu.
E em algumas aplicações como o Marcelo mencionou o timer/counter estaria livre para um PWM ou para leitura de tempo de algum evento externo.
Não sei quanto em codigo poderia ser reduzido, mas seria pouco.

MensagemEnviado: 12 Fev 2011 18:06
por Red Neck Guy
enigmabox escreveu:Falo isso, porque já fiz alguns projetos onde o encoder incremental estava sincronizado com o timer/counter e a cpu de tempo em tempo lia o valor deste counter para saber em que posição estava o encoder. Então o Counter era bem utilizado.
Se houver um timer externo e com freq. variavel, por ex. um 555 e um flip-flop, poderia com o S. O. rodando analizar a eficiencia da troca de tasks da cpu.
E em algumas aplicações como o Marcelo mencionou o timer/counter estaria livre para um PWM ou para leitura de tempo de algum evento externo.
Não sei quanto em codigo poderia ser reduzido, mas seria pouco.


Sim sim, não refutei a tua idéia!!!!
Apenas deixando claro que dá pra fazer com ou sem fritas.

MensagemEnviado: 12 Fev 2011 18:10
por eletroinf
Humm
Faz algum tempo que eu acompanho essas discussões sobre RTOS...
To fazendo uns estudos aqui também. Na verdade tengo um z8F6421 aqui e to me lambendo pra implementar isso nele... heheheh
Meio doida essa idéia do 555, mas, seria interessante até pra ver o que acontece variando os tempos... ou um osc. com 4093 também.

MensagemEnviado: 12 Fev 2011 19:43
por enigmabox
Como disse é uma opção, usar um 555 externo, mas melhor nao ligar ele diretamente ao MCU, pois nao gera tempo 50% +50%, bom colocar um 74hc74 depois dele, e ligar ao MCU.
Acho que na maioria dos MCUs da pra implementar e fazer um teste, pois quase todos tem pino com interrupção externa, até o QY4 que é o miudinho da Freescale, dá pra brincar com isso.
Achei legal este conceito de interrupções por mensagem e pendencias, é bem simples, podendo ser implementado este RTOS em qualquer MCU ou CPU.
Interessante também seria ligar um oscilador programavel, via spi, ou I2C, assim ficaria similar ao que acontece com um PC onde tem um circuito equivalente ao contador/timer i8254.
Vou fazer uns testes aqui com duas placas que tenho aqui, uma com o Atmega16 e outra placa com o JM60 da Freescale.
:wink:

MensagemEnviado: 12 Fev 2011 22:28
por msamsoniuk
entao, mas veja que a jogada do meu escalonador por passagem de mensagens eh que vc nao precisa de um timer para escalonar processos! como os modulos se comunicam por passagem de mensagens, todos os processos vao ser construidos mais ou menos como:

struct ipc_msg *p;
p = ipc_recv();
switch(p->event)
{
case algo:
ipc_send(p);
...
}

essa ideia eu tirei mais ou menos da forma com que uma maquina de estados roda em verilog:

always@(posedge clk)
begin
case(state)
algo: state <= next_state;
...
endcase
end

assim, a cada clock, a maquina vai de um estado para outro. no caso do software, a cada mensagem, a maquina vai de um estado para outro. no caso dos processos, a cada mensagem um evento eh processado. obviamente para funcionar, o processo nao pode ficar travado em um loop!

e daih o escalonador daih eh algo realmente simples:

for(;;) if(ipc_queue) ipc_queue->to();

se vc iniciar dois processos:

ipc_send(&start1);
ipc_send(&start2);

os processos podem rodar e entao reenviar a mensagem para eles mesmos, de modo que a queue de mensagem sempre escalona para eles mesmos e, neste caso, vc tem as facilidades sem precisar de timer! :)

enigmabox escreveu:Como disse é uma opção, usar um 555 externo, mas melhor nao ligar ele diretamente ao MCU, pois nao gera tempo 50% +50%, bom colocar um 74hc74 depois dele, e ligar ao MCU.
Acho que na maioria dos MCUs da pra implementar e fazer um teste, pois quase todos tem pino com interrupção externa, até o QY4 que é o miudinho da Freescale, dá pra brincar com isso.
Achei legal este conceito de interrupções por mensagem e pendencias, é bem simples, podendo ser implementado este RTOS em qualquer MCU ou CPU.
Interessante também seria ligar um oscilador programavel, via spi, ou I2C, assim ficaria similar ao que acontece com um PC onde tem um circuito equivalente ao contador/timer i8254.
Vou fazer uns testes aqui com duas placas que tenho aqui, uma com o Atmega16 e outra placa com o JM60 da Freescale.
:wink:

MensagemEnviado: 12 Fev 2011 23:02
por Red Neck Guy
Eu entendi a tua idéia, é basicamente uma autômato com troca de estados por processamento de mensagens, não é?
É interessante também, eu costumo implementar coisas simples utilizando autômatos, porém, não utilizo filas de mensagens.
Agora, como ficaria na tua implementação quando uma das tasks precisa de temporizações? Utilizaria diretamente os timers ou teria que entrar dentro do switch, processar a mensagem e verificar que a contagem ainda não chegou a zero e pular fora? Dessa forma o escalonador ganha, pois a fila de tarefas bloqueada, dependendo da implementação, decrementa apenas o primeiro nodo e os outros vem atrás...