Linux Kernel Real Time na Beaglebone Black com Yocto Project

Linux Kernel Real Time na Beaglebone Black

Neste artigo iremos mostrar como podemos gerar uma distribuição Linux embarcado customizada através do Yocto Project com Linux Kernel Real Time na Beaglebone Black com o patch PREEMPT_RT de maneira simples e rápida.

 

O que é tempo real?

 

Aplicações em tempo real possuem limites de tempo de execução entre algum evento de gatilho e a resposta da aplicação a esse evento. Para cumprir esse prazo de execução, os programadores usam sistemas operacionais de tempo real (RTOS) em que o tempo máximo de resposta pode ser calculado ou medido de forma confiável para a uma dada aplicação e meio ambiente.

 

Um RTOS típico usa prioridades. A tarefa de maior prioridade requerendo o uso da CPU sempre a recebe dentro de um determinado período de tempo após o evento de acordar a tarefa for disparado. Em um RTOS como dessa categoria, a latência de uma tarefa depende apenas das tarefas em execução em prioridades iguais ou superiores, todas as outras tarefas podem ser ignoradas. Em um sistema operacional normal (como o Linux normal) as latências dependem de tudo em execução no sistema, o que naturalmente torna muito mais difícil de ser convencido de que os prazos serão cumpridos a cada vez em um sistema razoavelmente complicado. Isso ocorre porque preempção das tarefas podem ser desligadas para uma quantidade de tempo desconhecida. A tarefa de alta prioridade que deseja ser executada pode assim ser atrasada por uma quantidade desconhecida de tempo por tarefas de baixa prioridade que funcionam com preempção desligada.

 

Na computação, é comum ver pessoas associando "Tempo Real" com "Rapidez". Isso não é necessariamente verdade. Você pode ter um sistema de tempo real que possua um prazo de execução de 1 minuto, porém esse prazo não pode ser estendido em mais de 1 microssegundo, caso contrário uma falha irá ocorrer e vidas podem ser perdidas.

 

 

Quais são as capacidades de tempo real do kernel Linux mainline?

 

Tradicionalmente, o kernel Linux irá permitir um processo interromper ("preemptar") o outro apenas em determinadas circunstâncias:

  • Quando a CPU está executando código de modo de usuário;
  • Quando o código do kernel retorna de uma chamada de sistema ou de uma interrupção para o espaço do usuário;
  • Quando o código do kernel bloqueia em um mutex, ou explicitamente fornece o controle para outro processo.

 

Se o código do kernel está executando quando ocorre algum evento que demanda o início de execução de uma thread com maior prioridade, esta thread de maior prioridade não poderá interromper o código do kernel em execução, até que ele explicitamente forneça o controle. No pior caso, a latência pode potencialmente ser de centenas de milissegundos ou mais.

 

O Linux 2.6 em diante possui a opção de configuração CONFIG_PREEMPT_VOLUNTARY que introduz verificações para as causas mais comuns de latências longas, de modo que o kernel pode voluntariamente ceder o controle a uma tarefa de prioridade maior que esta esperando para executar. Isso pode ser útil, mas ao mesmo tempo que reduz as ocorrências de latências longas (centenas de milissegundos para potencialmente segundos ou mais), não as elimina.

 

Existe também uma configuração adicional chamada CONFIG_PREEMPT, que faz com que todo o código do kernel fora das regiões protegidas por spinlocks e handlers de interrupção, serem elegíveis para preempção não-voluntária por kernel threads de maior prioridade. Com esta opção, o pior caso de latência cai para (cerca de) um dígito de milissegundos, embora alguns drivers de dispositivo poderem ter handlers de interrupção que irão introduzir uma latência muito pior do que isso.

 

Se uma aplicação Linux de Tempo Real requer latências menores que um dígito de milisegundos, o uso do patch CONFIG_PREEMPT_RT é altamente recomendado.

 

 

Como o patch CONFIG_PREEMPT_RT funciona?

 

O patch RT-Preempt converte o Linux em um kernel totalmente preemptivo:

  • Tornando preemptivas as primitivas de travamento (spinlocks) no kernel através da reimplementação com rtmutexes;
  • As seções críticas protegidas por spinlock_t e rwlock_t agora são preemptíveis. A criação de secções não-preemptíveis (no kernel) ainda são possíveis com raw_spinlock_t (mesmas APIs do spinlock_t);
  • Implementando a herança de prioridade para spinlocks e semáforos no kernel;
  • Convertendo handlers de interrupção em kernel threads preemptíveis: O patch PREEMPT_RT trata os handlers das soft interrupts no contexto de kernel threads, que são representadas através de uma task_struct, assim como um processo comum de espaço de usuário. No entanto, também é possível registrar um IRQ no contexto kernel;
  • Convertendo a antiga API de timer do Linux em infra-estruturas separadas para temporizadores de alta resolução (high resolution timers) do kernel e mais um para timeouts, proporcionando ao espaço de usuário temporizadores POSIX de alta resolução.

 

 

Arquiteturas suportadas pelo patch CONFIG_PREEMPT_RT

 

Existem sistemas baseados nas arquiteturas x86, x86_64, ARM, MIPS e Power utilizando o patch CONFIG_PREEMPT_RT. No entanto, em muitos aspectos, esta é a pergunta errada. Suporte em tempo real não é apenas sobre a arquitetura do conjunto de instruções, mas também sobre o suporte ao temporizador de alta resolução fornecido pela CPU, os drivers de dispositivo (device drivers) para o sistema, etc.

 

Então, só porque um SoC ARM de uma empresa pode funcionar muito bem com o patchset -rt, ele não garante que um outro SoC com o mesmo core da empresa B vai funcionar tão bem; ele pode ter alguns problemas de latência longa ou pode não funcionar completamente. É verdade que a concepção global e da arquitetura do patch -rt tende a evitar a necessidade de mudanças específicas de drivers de dispositivos, mas há sempre erros de software, bem como erros de design de hardware.

 

 

Aplicando o patch CONFIG_PREEMPT_RT

 

Confira o RT PREEMPT HOWTO para uma descrição detalhada. A maneira mais simples é obter o patch -rt mais recente aqui, e aplicá-lo ao kernel mainline relacionado, configurar e compilar.

 

 

Que tipo de desempenho em tempo real que devo esperar?

 

A resposta típica dada por todos os especialistas em performance quando perguntados sobre isso é, "depende". Não só depende da velocidade da CPU e da arquitetura, mas também dos drivers de dispositivo e do hardware.

 

Por exemplo, se um dispositivo "rouba" o barramento PCI por longos períodos durante uma atividade de DMA, que pode introduzir latências significativas no sistema. Além disso, alguns firmwares podem parar o sistema para as atividades de limpeza através do Serviço de Gerenciamento de Interrupções (SMI) em arquiteturas x86 e x86_64.

 

 

Como ativar/desativar o suporte em tempo real no kernel

 

Kernel 2.6.x:
Ativar: CONFIG_PREEMPT_RT=y
Desativar: CONFIG_PREEMPT_RT=n

 

Kernel 3.x em diante:
Ativar: CONFIG_PREEMPT_RT_FULL=y
Desativar: CONFIG_PREEMPT_RT_FULL=n

 

 

Linux Kernel Real Time na Beaglebone Black

 

A TI suporta oficialmente o PREEMPT_RT nas versões 4.1 e 4.4 do kernel para as seguintes arquiteturas: ti33x, ti43x, omap-a15, omap3, omap4 e keystone. Os repositórios estão localizados em:

 

Neste artigo iremos gerar uma distribuição Linux embarcado de Tempo Real  para a Beaglebone Black usando o kernel 4.4 com o patch rt.

 

 

Preparando o Host

 

O Yocto Project suporta oficialmente as seguintes distribuições GNU/Linux como ambiente de construção:

  • Ubuntu 14.04, 14.10, 15.04, 15.10;
  • Fedora 21 e 22;
  • CentOS 6.x e 7.x;
  • Debian 7.x e 8.x;
  • openSUSE 13.2.

 

Para que ele execute no Host alguns pacotes necessitam ser instalados.

 

Ubuntu e Debian:

 

Fedora:

 

openSUSE:

 

CentOS:

 

 

Montando o ambiente de construção

 

Neste tutorial iremos utilizar a versão mais recente do Yocto (krogoth) disponível. Após instalar os pacotes para o Host, vamos criar os diretórios e baixar os fontes necessários:

 

 

Agora vamos configurar o ambiente para gerarmos os artefatos de software:

 

 

Adicione as seguintes variáveis no arquivo ~/yocto/build-krogoth/conf/local.conf:

 

 

Note que configuramos nossa machine como sendo a beaglebone (MACHINE = "beaglebone") que serve tanto para a white como a black, mudamos o diretório de download (DL_DIR = "${TOPDIR}/../dl") para podermos reutilizar os fontes baixados em outros projetos, iremos gerar pacotes para usarmos o opkg (PACKAGE_CLASSES = "package_ipk"), adicionamos os módulos e dtb nas imagens que iremos gerar (IMAGE_INSTALL_append_beaglebone = " kernel-modules kernel-devicetree "), selecionamos o kernel com o patch PREEMPT_RT (PREFERRED_PROVIDER_virtual/kernel_beaglebone = "linux-ti-staging-rt") e configuramos de maneira correta uma das variáveis (IMAGE_BOOT_FILES_beaglebone = "u-boot.img MLO") usada pela ferrameta wic que será usada mais adiante no artigo.

 

Edite o arquivo ~/yocto/build-krogoth/conf/bblayers.conf para que fique da seguinte maneira:

 

 

O arquivo bblayers.conf configura quais serão as camadas a serem consideradas pelo sistema de build.

 

 

Construindo a imagem

 

Vamos gerar uma imagem mínima sem suporte à interface gráfica (core-image-mininal) com o comando:

 

 

Esta é a configuração de build utilizada:

 

 

 

Gravando as imagens

 

Vamos gravar a nossa imagem em um cartão microSD e para gerá-la utilizaremos uma ferramenta do Yocto Project chamada wic. Para a Beaglebone Black nosso cartão deverá possuir um layout com duas partições, onde a primeira é do tipo FAT e contém o pré-bootloader (MLO) e o bootloader (u-boot.img), na segunda partição do tipo ext4 colocaremos o nosso sistema de arquivos raíz (rootfs).

 

 

E a ferramenta apresenta o seguinte output:

 

 

Note que a imagem gerada se encontra no caminho:

 

 

Insira um SDcard card no computador PC ou notebook (sistema host) e descubra qual o device node criado pelo sistema operacional. Tente um dos seguintes comandos:

 

 

Caso, por exemplo, o device node criado seja /dev/sdb, use o seguinte comando:

 

 

 

Testando as imagens

 

Remova o microSD do computador e insira-o na Beaglebone Black. Se quiser monitorar o processo de boot, você também pode conectar um cabo serial.

 

NOTA:

Se você tiver instalado algum outro sistema operacional no eMMC da BBB, energize a placa pressionando a switch que fica próxima ao slot do microSD. Isso fará com que o processador busque o MLO e u-boot que estão contidos no microSD ao invés do eMMC.

 

A imagem core-image-minimal possui o seguinte log de boot:

 

 

Vamos verificar se a configuração do kernel possui o patch PREEMPT_RT com o comando na interface console serial da placa:

 

 

Que irá produzir a seguinte saída:

 

 

Como podemos constatar a configuração "CONFIG_PREEMPT_RT_FULL=y" está ligada.

 

Existe disponível uma série de ferramentas de testes para sistemas Linux Real Time, como por exemplo as criadas pelos membros do projeto PREEMPT_RT: https://git.kernel.org/cgit/utils/rt-tests/rt-tests.git/tree/

 

 

Para aprender mais

 

Wiki do projeto PREEMPT_RT

 

Como construir uma aplicação Real Time

 

Utilitários e ferramentas:

 

Apresentação no ELC 2013 - "Intro to Real-Time Linux for Embedded Developers"

 

 

Artigo - A realtime preemption overview

 

Lista de publicações sobre o tema

 

 

Referências

 

https://rt.wiki.kernel.org/index.php/Main_Page

NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Diego Sueiro
Formado em Engenharia de Controle e Automação pela UNIFEI e CEO do Embarcados, atualmente trabalho na Inglaterra com Desenvolvimento de Sistemas Linux Embarcado Real Time. Sou consultor e desenvolvedor de software para Sistemas Embarcados com vasta experiência em projetos com processadores de 8bits a 32bits, sistemas bare metal, RTOS, Linux Embarcado e Android Embarcado. Um apaixonado por Pink Floyd e Empreendedorismo.

7
Deixe um comentário

avatar
 
3 Comment threads
4 Thread replies
1 Followers
 
Most reacted comment
Hottest comment thread
4 Comment authors
HenriqueDiego SueiroBernardo RodriguesRonaldo Borges Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
Henrique
Visitante
Henrique

Parabéns pelo tutorial! Só tenho uma pergunta e um adendo a fazer. Primeiramente, o adendo: ao executar o comando wic, ele reclamou (mais de uma vez) de estarem faltantes alguns aplicativos (dosfstools, por exemplo), mas foi só executar o comando indicado em cada erro (bitbake dosfstools, por exemplo) e executar o comando do wic novamente que tudo ocorreu bem 😀 Por fim, a pergunta: não sei na época em que o tutorial foi escrito (2016), mas atualmente, há a possibilidade de se utilizar o core-image-rt, que é exatamente o core-image-minimal com algumas coisas a mais para real-time. A pergunta é:… Leia mais »

Bernardo Rodrigues
Visitante
Bernardo Rodrigues

Meu bitbake esta travando em:

Currently 1 running tasks (2326 of 2354):
0: linux-ti-staging-rt-4.4.39+gitAUTOINC+9d47072444-r22b do_fetch (pid 12086)

Diego Sueiro
Visitante
Diego Sueiro

Olá Bernardo,

Esta task é a que faz download do código fonte do kernel e demora um pouco mesmo.

Bernardo Rodrigues
Visitante
Bernardo Rodrigues

Olá Diego.
Obrigado pela resposta.

Estou monitorando a interface de rede do meu host e suspeito que o processo está parado. Não é problema na conexão, inclusive estou acessando o embarcados tranquilamente.
Vou deixar rodando durante a noite por via das dúvidas e amanhã comento aqui o restultado.

Bernardo Rodrigues
Visitante
Bernardo Rodrigues

Pelo jeito era impressão minha mesmo.

Agradeço novamente.
Abraço!

Ronaldo Borges
Visitante
ronaldo

Olá Diego, parabéns! seu tutorial funcionou perfeitamente. Só gostaria de tirar uma dúvida, com base na introdução, a versão do kernel instalado na beaglebone seria 4.4 porém ao executar o comando "uname -r" dentro da beaglebone após a instalação a versão instalada é a 3.8.11. Desta forma, pode me informar como posso fixar para compilar a versão 4.4? Pois na versão, 3.8.11 que esta instalada na BB não aparece as informações de RT como você demonstra no final do tutorial

Diego Sueiro
Visitante
Diego Sueiro

Olá Ronaldo,

Mil perdões pela demora na resposta. A notificação por email da sua pergunta passou batido. Desculpe.

Você colocou a linha abaixo no arquivo local.conf?
PREFERRED_PROVIDER_virtual/kernel_beaglebone = "linux-ti-staging-rt"