2 Comentários

Meu Kernel Minha Vida - Round-Robin

Este post faz parte da série Meu Kernel, Minha Vida. Leia também os outros posts da série:

Olá caro leitor, tudo bem? Vamos dar continuidade à série de artigos sobre desenvolvimento de Kernel. No último artigo, Meu Kernel Minha Vida, foram apresentados os conceitos básicos de kernel cooperativo e o código-fonte do projeto desenvolvido. Para este artigo serão apresentados conceitos básicos de kernel preemptivo do tipo Round-Robin, o código-fonte do kernel desenvolvido e a aplicação de demonstração.

Escalonador Round-Robin

O Round-Robin é um algoritmo escalonador de tarefas (processos) que consiste em dividir o tempo de uso da CPU (Central Processing Unit). Cada processo recebe uma fatia de tempo, esse tempo é chamado Time-Slice, também conhecido por Quantum. Os processos são todos armazenados em Fila (Buffer) circular. O escalonador executa cada tarefa pelo tempo determinado pelo Time-Slice e ao fim deste período é executada a troca de contexto, onde o próximo processo fila passa a ser executado pela CPU até percorrer o período do Time-Slice. Após percorrer todos os processos da fila, essas atividades se repetem e o escalonador aponta para a primeira tarefa. A figura a seguir ilustra bem todo esse processo.

Buffer Circular
Figura 1 - Buffer Circular

Kernel Preemptivo

Como dito anteriormente, trata-se de um kernel preemptivo do tipo Round-Round. Antes de descrever sobre o projeto desenvolvido, serão apresentadas as principais características de sistema preemptivo, são elas:

  • O uso de maneira uniforme da CPU entre os processos da aplicação;
  • Troca de contexto.

A troca de contexto é um recurso computacional de armazenar e restaurar o estado de uma tarefa em um sistema de múltiplos processos. Por um lado, é uma característica positiva de um sistema preemptivo. Mas a implementação desse recurso é mais complexo em comparação ao sistema cooperativo. E sua implementação está intimamente ligada à arquitetura da CPU, pois é necessária a manipulação de registradores específicos, que mudam de acordo com a CPU utilizada.

Outro ponto que pode ser considerado como uma desvantagem nesse tipo de sistema é fazer o uso de linguagem Assembly, manipulando alguns registradores a fim de realizar a troca de contexto.

O Kernel

O kernel desenvolvido é especifico para microcontroladores ARM Cortex-M0. Para utilizar esse código-fonte em outra arquitetura é necessário realizar uma serie de mudanças para realizar a troca de contexto.

Os microcontroladores ARM Cortex-M0/M3/M4/M7 possuem alguns recursos que facilita o desenvolvimento de sistemas operacionais. São as seguintes interrupções:

  • SysTick: é um “Timer” periódico utilizado como base de tempo. No artigo passado já utilizamos essa interrupção;
  • PendSV (Pendable SerVice): é uma interrupção que a arquitetura ARM Cortex-M fornece para o uso dos sistemas operacionais realizar a troca de contexto;
  • SVCall (SuperVisor Call): São chamadas de supervisor, normalmente usadas para solicitar operações privilegiadas.

A outra característica importante de se destacar nos microcontroladores ARM Cortex-M é que eles possuem dois ponteiros de pilha (Stack Pointers):

  • MSP (Main Stack Pointer): Ponteiro de pilha principal, utilizado para a inicialização do sistema e na função main(). E as interrupções do sistema também fazem uso deste ponteiro;
  • PSP (Process Stack Pointer): Ponteiro de pilha de processo, usado para manipular os processos / tarefas em sistema operacional.

O projeto desenvolvido faz uso das interrupções SysTick como base de tempo do kernel. Para realizar as trocas de contexto entre as tarefas é utilizada a interrupção PendSV em conjunto com PSP, passando o endereço de memória que contém as instruções da próxima tarefa.

O código-fonte do kernel foi apresentado no artigo Context Switch on the ARM Cortex-M0 do Adam Heinrich em seu Blog com algumas alterações. O projeto desenvolvido para o STM32F0DISCOVERY, utilizando o STM32Cube MX em conjunto com Atollic TrueSTUDIO for STM32 9.0.0.

Das alterações que realizei, a mais relevante se encontra na API que adiciona os processos ao kernel. No código-fonte original, a alocação de memória é feita através de Array (vetor), e parâmetros são passados à função. A seguir temos trechos do código-fonte apresentado por Adam Heinrich em seu artigo:

No código-fonte apresentado neste artigo, essa operação é feita na própria API, sem a necessidade de receber um vetor como parâmetro. A alocação de memoria é realizada utilizando a função malloc(), como pode ser observado no trecho de código-fonte abaixo.

O funcionamento do kernel é bem simples, o mesmo contém API’s (Application Programming Interface) para inicializar, adicionar as tarefas da aplicação e para iniciar o escalonador do kernel. A seguir temos os protótipos das funções presente no kernel.

Uma vez inicializado o Kernel, são adicionadas as tarefas ao Buffer circular. O escalonador assume o controle e passa a gerenciar o processo que deve ser executado pela CPU. O gerenciamento dos processos se dá início pela APIKernel_Start”, onde é configurada a utilização do Ponteiro de Pilha de Processo.

A troca de contexto entre as tarefas é realizada a cada ocorrência da interrupção do SysTick, onde é incrementado o index do Buffer e, em seguida, é disparado o Trigger gerar a interrupção do PendSV. O algoritmo que é executado quando ocorre a interrupção do PendSV é: salvar o contexto da tarefa que estava em execução e restaurar as informações da próxima tarefa a ser processada pela CPU. A figura a seguir ilustra com mais detalhes o funcionamento do Kernel.

Escalonador do Kernel Round-Robin
Figura 2 - Escalonador do Kernel Round-Robin

A seguir será apresentado o código-fonte do Kernel (arquivos kernel.c, kernel.h e kernel.s).

Aplicação de demonstração

Para demonstrar o funcionamento do kernel, foi desenvolvida uma aplicação com três tarefas. A primeira tarefa ficará executando o algoritmo LED Blinking no LED verde. A segunda tarefa será responsável pelo acionamento do LED azul. E a última tarefa executará o algoritmo de leitura do Push Button.

A seguir é apresentado o código-fonte da aplicação, composto pelo main.c, onde temos as funções de inicialização do kernel, e pelos arquivos app.c e app.h.

Conclusão

Neste segundo artigo da série Meu Kernel Minha Vida foram apresentados os conceitos básicos sobre kernel preemptivo e do escalonador Round-Robin. Também foi apresentado o código-fonte do kernel e  da aplicação de demonstração. O objetivo foi trazer a você, caro leitor, mais uma alternativa para o desenvolvimento de firmware.

O código-fonte do projeto com a aplicação e kernel está disponível no meu Github. E fica aqui o meu convite a você caro leitor, que se interessou pelo assunto, a contribuir com o projeto, testando e aperfeiçoando o mesmo.

Saiba mais

Desenvolvendo com o Zephyr RTOS: Controlando o Kernel

Implementando elementos de RTOS no Arduino

Desenvolvendo um RTOS: Introdução

Referências

MCU on Eclipse - ARM Cortex-M, Interrupts and FreeRTOS: Part 1
MCU on Eclipse - ARM Cortex-M, Interrupts and FreeRTOS: Part 2
MCU on Eclipse - ARM Cortex-M, Interrupts and FreeRTOS: Part 3
Adam Heinrich - Context Switch on the ARM Cortex-M0
GitHub - Adam Heinrich - Context Switch on the ARM Cortex-M0

Outros artigos da série

<< Meu Kernel - Minha VidaMeu Kernel, Minha Vida - Escalonador Cooperativo com Lista Circular >>
Este post faz da série Meu Kernel, Minha Vida. Leia também os outros posts da série:
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

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

Software » Meu Kernel Minha Vida - Round-Robin
Talvez você goste:
Comentários:

2
Deixe um comentário

avatar
1 Comentários
1 Respostas
2 Seguidores
 
Discussão de maior alcance
Discussão mais quente
2 Autores de comentários
Evandro TeixeiraLucas Zampar Bernardi Comentários recentes
  Notificações  
recentes antigos mais votados
Notificar
Lucas Zampar Bernardi
Visitante
Lucas Zampar Bernardi

Excelente artigo Evandro! Meus parabéns!

Séries



Outros da Série

Menu