Real Time no Windows Embedded Compact - Embarcados
Confira neste artigo o tratamento de Real Time no Windows Embedded Compact. Veja um código exemplo com criação de threads de diferentes prioridades.
Uma das principais características que tornam diferente o Windows Embedded Compact de todas as outras versões de Windows é a capacidade de desenvolver aplicativos de tempo real para ele. Nunca é demais lembrar aqui o significado que tempo real tem no contexto computacional, muito importante para o entendimento do comportamento de Real Time no Windows Embedded Compact. Segue abaixo uma definição encontrada no livro: Real-Time System Design and Analysis de autoria de Phillip A. Laplante.
Ou seja, um sistema de tempo real deve executar um código produzindo uma resposta precisa e também deve fazer isso dentro de um tempo previamente estabelecido, caso contrário isso pode levar à falha do sistema. Portanto, tempo real não quer dizer necessariamente um processamento, ou SO, muito rápido.
O Windows Embedded Compact é capaz de se comportar de acordo com a definição acima. Para isso uma das primeiras coisas que devemos entender é o escalonador de tarefas do WEC. Basicamente o WEC obedece duas regras simples para agendar as tarefas, e para avaliar cada uma destas regras o WEC faz uma avaliação do que ocorre no sistema a cada 1ms. As regras são:
Tarefas que possuem maior prioridade devem ser executadas primeiro;
A respeito da regra número um, o WEC possui 256 níveis de prioridade, valores mais altos significam prioridade mais baixa, valores mais baixos são prioridades mais baixas. Uma orientação para o uso das prioridades pode ser encontrada no seguinte artigo: Real-Time Priority System Levels (Windows Embedded CE 6.0).
Com relação à regra número dois, quando diversas tarefas compartilham a mesma prioridade, basicamente o sistema ira rodar cada uma das tarefas por no máximo 100 ms (este tempo pode ser configurado entre 40 ms – 100 ms). Uma vez que este tempo, chamado de Quantun, termina, o Kernel passará a executar a outra tarefa de mesma prioridade até que o Quantun dela também termine. Neste momento o Kernel irá "passar a bola" para uma terceira tarefa de mesma prioridade se existir ou caso contrário retomar a execução da primeira tarefa, e assim sucessivamente até que todas as tarefas estejam finalizadas.
Para acrescentar uma abordagem mais prática a este post, vou propor dois exemplos onde poderemos explorar de forma simples as regras descritas acima. No primeiro exemplo vou instanciar duas tarefas diferentes onde uma delas coloca uma saída digital do meu Hardware em nível lógico 1 e a outra tarefa em nível lógico zero. Mais uma vez vou utilizar um computador em módulo Toradex Colibri VF61 junto com uma placa de suporte Iris, figura 1. O Colibri VF61 é um ARM Cortex-A5 de 500 MHz com 256 MB de RAM e 512 MB de Flash já embarcados no módulo. Estou rodando neles um Windows Embedded Compact 7.0 fornecido pelo fabricante do módulo. Segue o código fonte abaixo.
#include "gpioLib.h" #include "CoProcLib.h" #define PIN_OUT 133 HANDLE hThreadON, hThreadOFF; DWORD WINAPI ThreadON(void) { while( 1 ) { //Aciona GPIO para nível lógico alto SetPinLevel(PIN_OUT, 1); } return 0; } DWORD WINAPI ThreadOFF(void) { while( 1 ) { //Aciona GPIO para nível lógico baixo SetPinLevel(PIN_OUT, 0); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instance LPWSTR lpCmdLine, // pointer to command line int nCmdShow) // show state of window { SetPinAltFn(PIN_OUT,-1,DIR_OUT); //Set Pin functonality to GPIO and set to Input //Aumentando a prioridade da Thread que chama as demais Threads CeSetThreadPriority(GetCurrentThread(), 200); //Criando as duas Threads apontando para diferentes funções hThreadON = CreateThread(0,0,ThreadON,0,0,0); hThreadOFF = CreateThread(0,0,ThreadOFF,0,0,0); //Configurando a mesma prioridade para as duas Threads CeSetThreadPriority(hThreadON, 255); CeSetThreadPriority(hThreadOFF, 255); //Tempo de execução até a finalização do programa. A Thread principal ficará suspensa Sleep(30000); DeInitGPIOLib(); return(TRUE); }
Note que existem duas diferentes funções ThreadON e ThreadOFF. Elas não fazem nada mais que ligar ou desligar, respectivamente, um pino que foi configurado como saída digital. Note também que cada função irá rodar indefinidamente não liberando recursos para outras Threads ou programas.
No código principal as funções são instanciadas uma após a outra e podemos ver no osciloscópio ligado em nossa saída digital o resultado da execução do programa. Conforme esperado, uma vez que as tarefas são criadas com o mesmo nível de prioridade, elas irão rodar de acordo com um agendamento Round Robin com um "timeslice" de 100 ms para cada tarefa.
Para testar a regra número 1, vamos fazer as seguintes alterações em nosso código, primeiramente na função ThreadON, colocando um comando Sleep(30), que fará a Thread que invoca e função suspender sua execução e solicitar para o Kernel seu regresso em 30 milisegundos.
DWORD WINAPI ThreadON(void) { while( 1 ) { //Aciona GPIO para nível lógico alto SetPinLevel(PIN_OUT, 1); Sleep(30); } return 0; }
CeSetThreadPriority(hThreadON, 254); CeSetThreadPriority(hThreadOFF, 255);
Desta forma a ThreadON terá maior prioridade que a ThreadOFF. O resultado mais uma vez pode ser observado no osciloscópio. Cada vez que a thread de maior prioridade "acorda", o Kernel interrompe a thread de menor prioridade para dar lugar à thread de maior prioridade.
Trabalhando com as threads e conhecendo o comportamento do Kernel ao agendar as mesmas, você consegue uma execução determinística do seu sistema e pode criar sistemas de tempo real utilizando o Windows Embedded Compact!
<< Customizando a imagem do Windows Embedded CompactTelnet no Windows Embedded Compact >>
AnteriorAnteriorLivro Arduino Descomplicado – Como Elaborar Projetos de Eletrônica
PróximoEditorial: IoT – Internet das Coisas – Mocinha ou Vilã?Próximo
Quero saber algo bem simples mas importante, o código fonte do sistema Windows Embedded é aberto? posso ter acesso a ele se for preciso? não digo divulgar o sistema, mas no caso de algum bug ocorrer com hardware etc e tal e quais os custos …
Prezado Sandro, Sua pergunta é bem complexa! kkkk. O Código fonte do Windows Embedded não é aberto. Em teoria você pode comprar o código fonte do Windows CE mas na verdade a pergunta é, Pra que? A Microsoft possui um ciclo de vida de produto com suporte ao mesmo, sendo assim, qualquer problema que possa existir eles devem resolver para você. Se o problema for acesso a hardware, você pode desenvolver os "device drivers" específicos de sua aplicação e ai você vai partir de algo "meio" pronto fornecido com o Platform Builder e ter o source code do sistema operacional.… Leia mais »