Sistemas de Tempo Real – Parte 1

- por Sergio Prado

Categorias: RTOS Tags: , , , ,

Os sistemas computacionais estão presentes em diversas áreas do nosso cotidiano e têm evoluído de forma exponencial nos últimos anos. Novos microprocessadores com novos recursos computacionais, operando a freqüências maiores, maior capacidade de memória e várias interfaces de comunicação de I/O embutidas num único chip, tudo isso a um custo baixo e acessível.

Essa evolução tem contribuído com o aumento da complexidade dos projetos de sistemas embarcados, que por conseqüência tem exigido novos níveis de abstração em soluções de software que possam interagir com o hardware da forma mais eficiente possível.

Dentro deste contexto, destaca-se um grupo de sistemas que trabalham com restrições de tempo, chamados Sistemas de Tempo Real. Estes sistemas, além de executarem as tarefas de processamento e controle de informações, possuem a característica de que suas respostas ao ambiente devem ser dadas em um tempo hábil o suficiente para que o sistema não entre em um estado inconsistente ou inválido.

Um Sistema de Tempo Real é, portanto, o software que gerencia os recursos de um sistema computacional, com o objetivo de garantir com que todos os eventos sejam atendidos dentro de suas restrições de tempo, e gerenciados da forma mais eficiente possível. O software responsável pelo gerenciamento dos recursos computacionais também é chamado de Kernel (ou núcleo) do Sistema de Tempo Real, e conhecido no mercado como RTOS (Real-Time Operation System) ou Sistema Operacional de Tempo Real.

Para entendermos a importância de um Sistema de Tempo Real, precisamos entender o conceito de restrição de tempo para eventos ou tarefas computacionais.

Restrições de Tempo

Toda tarefa computacional recebe um estímulo (ou evento), que pode ser interno ou externo, realiza o processamento e produz uma saída. Um evento com restrição de tempo possui um tempo limite (máximo) de processamento para que sua saída seja gerada.

Podemos citar alguns exemplos de eventos com restrições de tempo:

  1. Um sensor de temperatura que gera um input para um microcontrolador, indicando que níveis críticos de temperatura foram atingidos, para que o microcontrolador possa atuar sob o sistema de refrigeração. Se o microcontrolador não atender às restrições de tempo do sensor de temperatura, a temperatura poderá atingir níveis críticos, e todo sistema poderá se danificar. Este caso é normalmente chamado de “Hard Real-Time Systems”, ou numa tradução livre, Sistemas de Tempo Real altamente restritivos.

  2. Um sistema de radar aeroespacial, que recebe informações de posicionamento das aeronaves, para que possíveis colisões sejam detectadas e evitadas. Se o sistema não tratar estas entradas dentro de suas restrições de tempo, poderá causar uma tragédia. Este caso, assim como o caso anterior, também é chamado de “Hard Real-Time Systems”.

  3. Um teclado que gera inputs de teclas pressionadas para um sistema microprocessado. Se o sistema não tratar estas teclas dentro de suas restrições de tempo, o operador poderá ter a sensação de que o sistema “travou”, o que poderá causar até a desistência da utilização do produto. Este caso é normalmente chamado de “Soft Real-Time Systems”, ou Sistemas de Tempo Real levemente restritivos.

Podemos ver através dos exemplos acima que, se eventos com restrições de tempo não forem tratados de forma correta, teremos conseqüências tão diversas quanto a percepção de baixa qualidade de um produto, a possibilidade de queima de um equipamento ou até risco de morte!

Um Sistema de Tempo Real simplifica o projeto do produto e minimiza o risco de problemas com restrições temporais através da divisão do sistema em pequenos elementos independentes chamados tarefas.

Tarefas

Tarefas são pequenos trechos de programa com responsabilidades específicas e bem definidas. Cada tarefa possui um conjunto de atributos, dentre eles a prioridade, que deve ser atribuída de acordo com sua importância. É a partir desta prioridade que tentamos garantir com que eventos com restrições de tempo possam ser executados de forma eficiente.

Como exemplos de tarefas, podemos citar a leitura de sensores, tratamento de protocolos de comunicação, leitura de teclado, acionamento de leds indicativos, escrita em displays, comunicações seriais, log de informações, etc.

Portanto, um Sistema de Tempo Real é modelado através da divisão da aplicação em um conjunto de pequenas tarefas, com funções específicas, e que interagem entre si.

Interação entre as tarefas

Cada tarefa é executada de forma independente, mas elas precisam interagir entre si para que o sistema atinja seus objetivos.

Para exemplificar, vamos supor um simples sistema de alarmes:

  1. A tarefa 1 é responsável pela leitura constante dos sensores de presença e movimento.

  2. A tarefa 2 é responsável pelo acionamento da sirene.

  3. A tarefa 3 é responsável pelo acionamento da discagem telefônica.

  4. A tarefa 4 é responsável pela lógica de detecção de intrusos do sistema de alarme.

Vamos supor que um sensor de movimento tenha sido acionado, a tarefa 1 irá detectar esse acionamento, e precisa notificar a tarefa 4. Esta notificação é feita através do envio de uma mensagem para a tarefa 4. A tarefa 4 irá então receber esta mensagem, e de acordo com sua lógica, irá enviar uma mensagem de acionamento para a tarefa 2, 3 ou para ambas.

Este exemplo utiliza a troca de mensagens, também chamada de Message Queues, como forma de comunicação entre as tarefas.

Podemos ainda citar como meios de comunicação entre as tarefas os semáforos, ou Semaphores, que são mecanismos para o compartilhamento de recursos entre as tarefas.

Para atender todas as tarefas solicitadas, dentro de suas respectivas restrições de tempo, o Kernel necessita de algum mecanismo de gerenciamento de tarefas, classificando-as e ordenando de acordo com sua prioridade. Isso é feito através do escalonamento de tarefas.

Escalonamento de tarefas

O escalonamento de tarefas é uma função realizada pelo Kernel para determinar quando uma tarefa mais importante precisa ser executada.

Conforme já foi dito, um Sistema de Tempo Real é composto pelo Kernel e pelas tarefas da aplicação. Portanto, o controle da CPU estará sempre com uma tarefa ou com o Kernel (estamos assumindo aqui sistemas com um único processador).

Para que o Kernel possa realizar o escalonamento, é necessário que o mesmo assuma o controle da CPU, através de um dos seguintes eventos:

  1. Uma tarefa manda uma mensagem para outra tarefa. Neste momento o Kernel assume o controle da CPU, prepara o envio da mensagem, e verifica qual a tarefa mais prioritária para execução no momento.

  2. Uma tarefa requisita um tempo de espera (delay) para o Kernel. Neste momento o Kernel assume o controle da CPU, e verifica qual a próxima tarefa mais prioritária para execução no momento.

  3. Uma interrupção do timer do sistema é gerada e tratada pelo Kernel. Neste caso, a tarefa em execução no momento é colocada em espera para que o Kernel possa escalonar para a tarefa mais prioritária. Normalmente um Kernel com este recurso é chamado de preemptivo.

  4. Um evento que uma tarefa de prioridade maior estava esperando ocorre e causa a interrupção da tarefa em execução. Este evento pode ser, por exemplo, uma interrupção gerada por um dispositivo qualquer.

O Kernel mantém um conjunto de informações do estado atual de cada tarefa, também chamado de contexto de execução da tarefa, em uma estrutura de dados chamada TCB (Task Control Block).

Todas as tarefas possuem um campo no status que indica o estado atual da tarefa. Este campo é armazenado no TCB, e é atualizado sempre que é realizado o escalonamento de tarefas pelo Kernel.

O TCB contém também o conteúdo de alguns dos registradores da CPU salvos no momento em que a execução da tarefa foi suspensa. A troca de tarefas em execução pelo Kernel também é chamada de mudança de contexto, pois o contexto da tarefa a ser suspensa é salvo no TCB, e o contexto da tarefa a ser executada é recuperado do TCB.

Para exemplificar o escalonamento de tarefas, vamos analisar o seguinte caso de escalonamento:

  1. Uma tarefa de prioridade menor está sendo executada.

  2. Um evento esperado por uma tarefa de prioridade maior ocorre e causa uma interrupção no processador.

  3. O processador salva o contexto da tarefa em execução (registros da CPU) e executa a rotina de tratamento da interrupção (ISR – Interrupt Service Routine).

  4. A rotina de tratamento da interrupção completa e chama um serviço do Kernel.

  5. O Kernel prepara e executa a rotina de maior prioridade.

  6. A rotina de maior prioridade entra em execução.

  7. A rotina de maior prioridade chama uma função do Kernel para aguardar por outro evento. Isso faz com que o Kernel seja acionado, e prepare novamente a rotina de menor prioridade para execução.

  8. A rotina de menor prioridade entra em execução.

Um RTOS provê toda esta arquitetura de software para o desenvolvimento de Sistemas de Tempo Real, incluindo funções para a criação de tarefas, troca de mensagens entre as tarefas, compartilhamento de recursos, ISR’s genéricas, etc.

Escolha de um RTOS

Um RTOS deixará o produto mais confiável com relação ao tratamento de tarefas com restrição de tempo, além de possibilitar uma melhor modelagem da sua aplicação através da divisão da aplicação em pequenas tarefas. Porém, nem sempre é válida ou mesmo viável a escolha de um RTOS para determinados produtos. Essa decisão pode depender de vários fatores:

  1. CPU: A CPU utilizada no projeto pode determinar se você pode ou não utilizar um RTOS no seu projeto. Por exemplo, uma CPU de 4 bits, sem os registradores necessários, ou de baixa frequencia, é feita especificamente para sistemas bem simples e de baixo custo, tornando inviável a utilização de um RTOS.

  2. ROM: Quantidade de memória de programa disponível para o seu projeto. Precisa ser grande o suficiente para armazenar o código do Kernel mais o código da sua aplicação. Dependendo do Kernel, você pode precisar de memória entre 4K e 200Kb, apenas para o Kernel de RTOS’s mais simples.

  3. RAM: Quantidade de memória disponível para os dados do seu programa. O RTOS utiliza bastante memória para armazenamento das informações de contexto de execução das tarefas no TCB e no stack. O valor da memória RAM deve ser grande o suficiente para suprir as necessidades do Kernel e das tarefas da sua aplicação.

  4. Custo: Tanto o custo do RTOS quanto o custo extra do hardware necessário para suportar o RTOS devem ser levados em consideração.

Identificada a necessidade e a viabilidade da utilização de um RTOS no seu projeto, é necessário escolher o melhor para a sua aplicação. Cada RTOS disponível no mercado possui vantagens e desvantagens. A escolha do melhor sistema depende dos requisitos de hardware e software do produto.

Os critérios de escolha podem variar bastante, desde a popularidade e reputação do RTOS, o custo e a disponibilidade do código-fonte, a portabilidade e escalabilidade, performance, ferramentas disponíveis e profissionais certificados no mercado.

Existem diversos RTOS’s no mercado, alguns pagos e outros de livre distribuição. Alguns dos principais disponíveis no mercado são eCos, QNX, MicroC/OS-II, VxWorks, Monta Vista, FreeRTOS, etc.

Na segunda parte deste post vou dar um exemplo prático de implementação de um projeto utilizando o MicroC/OS-II da Micrium.

Um abraço e até lá!

Sergio Prado

Faça um Comentário

Navegue
Creative Commons Este trabalho de Sergio Prado é licenciado pelo
Creative Commons BY-NC-SA 3.0.