Fundamentos de Sistemas Operacionais de Tempo Real - Criando seu próprio escalonador de tarefas (artigo)

Embed Size (px)

DESCRIPTION

Neste artigo são explorados os princípios básicos de criação de um sistema operacional de tempo real (RTOS). Usando um microcontrolador MSP430 como referência e um compilador GNU GCC, as tarefas mais importantes no processo de criação de um RTOS são detalhadas através de um projeto conhecido como “Basic RTOS” [1], criado especificamente para este fim e requerendo apenas 128 bytes de RAM e 1150 bytes de flash. Mesmo sistemas com grandes restrições de memória podem se beneficiar de RTOSs como o descrito aqui, evitando estratégias tradicionais de funcionamento apenas baseado em interrupções e facilitando o desenvolvimento. Os conceitos abordados são gerais e não estão restritos ao MSP430 muito menos ao compilador empregado, provendo um conhecimento indispensável para desenvolvedores interessados em aplicar técnicas similares aos seus projetos.

Citation preview

  • 1. Fundamentos de Sistemas Operacionais de Tempo RealCriando o seu prprio escalonador de tarefasMarcelo Barros de [email protected] Introduo.........................................................................................................................................12 O relgio do escalonador..................................................................................................................13 Troca de contexto.............................................................................................................................2 3.1 Modo interrompido...................................................................................................................2 3.2 Bloco de controle de tarefas......................................................................................................4 3.3 Adicionando tarefas ao RTOS...................................................................................................5 3.4 O escalonador...........................................................................................................................64 Controle de tarefas............................................................................................................................95 Inicializando o sistema...................................................................................................................116 Concluso.......................................................................................................................................117 Agradecimentos..............................................................................................................................128 Referncia.......................................................................................................................................129 Licenciamento................................................................................................................................121 IntroduoNeste artigo so explorados os princpios bsicos de criao de um sistema operacional de temporeal (RTOS). Usando um microcontrolador MSP430 como referncia e um compilador GNU GCC,as tarefas mais importantes no processo de criao de um RTOS so detalhadas atravs de umprojeto conhecido como Basic RTOS [1], criado especificamente para este fim e requerendoapenas 128 bytes de RAM e 1150 bytes de flash.Mesmo sistemas com grandes restries de memria podem se beneficiar de RTOSs como odescrito aqui, evitando estratgias tradicionais de funcionamento apenas baseado em interrupes efacilitando o desenvolvimento. Os conceitos abordados so gerais e no esto restritos ao MSP430muito menos ao compilador empregado, provendo um conhecimento indispensvel paradesenvolvedores interessados em aplicar tcnicas similares aos seus projetos.2 O relgio do escalonadorQuando se coloca o requisito de executar mais de uma tarefa no sistema, o problema a ser resolvidoimediatamente o de como compartilhar o processador nesta situao. A estratgia comumenteadotada em sistemas com um processador s dividir o seu uso entre todas as tarefas, dando umafatia de tempo para cada uma delas (chamado de time slicing, ou fatia de tempo) e criando umaforma de ir alternando as tarefas, isto , um jeito de ir escalonando tarefas no processador.Isto exige que seja criado um mecanismo de tempo que permita, de tempos em tempos, avaliar alista de tarefas e decidir quem ir entrar em execuo (funo conhecida como escalonador ou

2. scheduler, em ingls). Em geral, usa-se uma interrupo de temporizador (timer) de alta prioridadedo sistema e define-se um tempo de avaliao peridico do sistema. Este tempo ser a resoluomnima de execuo a ser usada por uma tarefa e comumente chamado de "tick do sistema"(batimento). Por exemplo, comum ter sistemas com tick de 10ms ou 1ms para PCs. Isto dependedo que se pretende em termos de responsividade das tarefas e de quanto se quer perder deprocessamento executando o escalonador. Um nmero muito baixo pode acabar desperdiandomuito processamento no escalonador e um muito alto pode atrasar a resposta de uma tarefa.A estratgia adotada dependente dos recursos disponveis na sua plataforma e, neste caso, foiusado um watchdog timer configurado com tick de 0,5ms, para um sistema que opera com relgiode 1MHz (o clock do sistema). Inicialmente, coloca-se o escalonador de tarefas na interrupo dewatchdog, com mostrado no fragmento de cdigo a seguir. A forma de fazer isto vai depender doseu compilador, hardware e software de suporte placa. No exemplo est sendo usado o compiladorGCC para MSP430./* RTOS scheduler function is allocated at watchdog interrupt */static interrupt (WDT_VECTOR) BRTOS_Scheduler(void);Definindo a interrupo de watchdog no GCC para MSP430Depois, na configurao inicial do RTOS, o tick pode ser ajustado, atravs de uma chamada paraBRTOS_ConfigureClock(), dentro da funo de inicializao do sistema (chamada deBRTOS_Initialize() e discutida mais ao final):static void BRTOS_ConfigureClock(void){WDTCTL = WDT_MDLY_0_5; /* configuring interval timer */usTicksPerSecond = 1000/0.5; /* 2k ticks per second*/} Inicializando o clock do sistema3 Troca de contextoAntes de tratar a troca de contexto propriamente dita, preciso entender o que acontece quando oprocessamento normal do microcontrolador alterado por uma interrupo. Obviamente isto umaquesto dependente do hardware mas existem algumas aes esperadas.3.1 Modo interrompidoQuando uma interrupo est sendo tratada pelo microcontrolador comum se referir expressomodo interrompido para caracterizar esta situao. Em modo interrompido, o ponto doprocessamento ir mudar para que a interrupo seja atendida adequadamente. Neste caso, ocontexto do sistema precisa ser salvo, isto , uma espcie de foto dos registros e modo de operaodo processador naquele instante efetuada, para que o estado possa ser posteriormente recuperadoquando a interrupo terminar de ser processada. Em geral, comum realizar o salvamento dedeterminados elementos do processador, descritos a seguir:O contador de programa, mais conhecido como program counter (PC), que indica onde estava aexecuo no momento da interrupo. Em geral, o PC um registro que armazena o valor do 3. endereo de memria da prxima instruo a ser executada.O ponteiro da pilha ou stack pointer (SP). O SP indica a posio corrente do stack, podendoapontar para o endereo de memria da prxima posio livre na pilha. Algumas plataformas usamo SP de forma diferente, fazendo que ele aponte para a ltima posio ocupada. A direo em que apilha usada tambm varia. Algumas plataformas vo decrementando o SP medida que a pilha usada, com o SP inicialmente apontando para o fim do stack, enquanto em outras o SP inicializadoapontando para o incio do stack, sendo o SP incrementado durante o seu uso.O registro de status, ou status register (SR), no momento da interrupo. Por exemplo, tinha umflag de overflow ligado no momento da interrupo? Se sim, ele precisa estar ligado quando ocontexto for restaurado. Isto tambm pode variar entre plataforma mas comum existir algumaforma de salvamento do status em todos os microcontroladores.Registros de finalidade geral, totalmente dependentes da arquitetura utilizada.Certas controladores, como o ARM7TDMI, possuem registros espelhados. Por exemplo, ao entrarno modo interrompido, voc tem um registro especfico para o SP em modo interrompido, trocadopelo processador no momento da interrupo, automaticamente. Enfim, o que salvar altamentedependente do processador e ir requerer um bom conhecimento do controlador que est sendousado.O seu compilador tambm ir influenciar neste processo, j que ele que ir montar o salvamentode contexto antes da entrada da interrupo. Por exemplo, se no atendimento de uma interrupo eles usa um subconjunto dos registros, ele pode gerar um cdigo assembly que s salve estesubconjunto, gerando um chaveamento de contexto mais rpido do que salvar todos os registros.No a toa que plataformas como ARM permitem o salvamento simultneo de vrios registros,numa nica instruo, diminuindo o tempo.No caso do MSP430, existem 16 registros, como pode ser visto na Figura 1. R0 (PC)Program counter R1 (SP)Stack pointer R2 (SR)Status register R3 (CG)Constant generatorR4 a R15 Registros geraisFigura 1: Registros do MSP430Ao acontecer uma interrupo, o processador coloca automaticamente na pilha corrente os valoresdo SR e PC. Qualquer salvamento adicional feito pelo compilador, na gerao do cdigo deentrada e sada da interrupo. Ou, caso escrevendo cdigo em assembly, ser preciso salvar osregistros que pretende usar dentro da funo de interrupo na pilha e restaur-los antes do retorno.O retorno de uma interrupo feito com a instruo reti, que devolve automaticamente os valoresdo PC e SR, recuperando o contexto anterior. Em resumo, apenas o SR e PC so salvosautomaticamente pelo microcontrolador (Figura 2), o compilador (ou programador) responsvelpelos outros registros. 4. ... Stack Pointer PC Endereo de retorno SR Estado antes da interrupo... Figura 2: Salvamento de contexto realizado pelomicrocontrolador3.2 Bloco de controle de tarefasAgora que j descrito como lidar com o salvamento de contexto no caso de uma interrupo, horade tratar as tarefas. Um sistema com o objetivo de executar vrias tarefas precisa, de alguma forma,control-las. comum se usar uma estrutura conhecida como TCB (Task Control Block) paramanter os dados mais importantes das tarefas do sistema.No BRTOS, foi usada a seguinte estrutura, cujos elementos esto descritos mais abaixo. Aquantidade de elementos na estrutura ir variar dependendo da sua implementao de RTOS.typedef struct {pfTaskEntry pfEntryPoint;/* task entry point */unsigned char ucPriority;/* task priority*/unsigned char ucTaskState; /* current task state */unsigned short usTimeSlice;/* desired time slice */unsigned short *pusStackBeg; /* stack beginning*/unsigned short *pusStackPtr; /* stack pointer*/unsigned short usSleepTicks; /* count sleep ticks*/unsigned short usTicks;/* count slice ticks*/} BRTOS_TCB;TCB utilizado para o controle de tarefaspfEntryPoint: ponto de entrada da tarefa, isto , o endereo da funo que representa a tarefa.ucPriority: prioridade da tarefa, no usada nesta implementao, mas importante em sistemas queescalonam tarefas levando em considerao a prioridade.ucTaskState: estado atual da tarefa (em execuo, dormindo, etc), importante para o escalonador.usTimeSlice: time slice da tarefa, ou seja, o tempo que a tarefa ficar em execuo antes de perdero controle do processador para a prxima tarefa. Medido em ticks, nesta implementao.pusStackBeg: ponteiro para o incio da pilha da tarefa. Cada tarefa ir necessitar de uma pilhaprpria para que possa executar de forma independente. Um pouco de memria precisar serreservada para cada pilha sendo que a quantidade final est relacionada com o cdigo da tarefa. Umerro neste dimensionamento em sistemas onde a memria de processos compartilhada (semMMU, Memory Managment Unit) pode gerar um estouro da pilha. Neste caso, pode-se ter umproblema grave ao invadir reas de memria de outras tarefas ou do sistema operacional. 5. pusStackPtr: ponteiro para o valor corrente da pilha da tarefa. Este ponteiro ser usado para salvara posio da pilha enquanto a tarefa espera por espao no processador. Ao voltar a ser executada, ovalor desta varivel copiada novamente no SP na operao de restaurao de contexto.usSleepTicks: este campo usado como contador do tempo decrescente (em ticks) quando a tarefa colocada em estado de suspenso por um determinado perodo.usTicks: contador do nmero de ticks durante a execuo da tarefa, usado para controlar o tempode execuo da tarefa dentro do time slice planejado.Sistemas com restries grandes de memria podem tentar construir TCBs com menos elementospara diminuir o uso de RAM. Alm disso, comum usar uma lista duplamente ligada de elementosBRTOS_TCB para manter o controle das tarefas. Mas, para simplificar, reduzir o tamanho docdigo e uso de RAM, foi criado um vetor com BRTOS_MAX_TASKS posies j previamentealocadas.3.3 Adicionando tarefas ao RTOSPara adicionar uma nova tarefa no sistema, basta definir a funo que a represente, reservarmemria para a pilha e adicion-la no TCB atravs de uma chamada para a funoBRTOS_CreateTask().Num microcontrolador com 1Kb de RAM e 8Kb de Flash, chamadas como malloc() provavelmenteno esto disponveis para uso e a reserva de espao para pilha pode ser feita atravs do emprego deum vetor global, do tamanho desejado. No exemplo a seguir, foram reservados 50 bytes para a pilhada tarefa. Note que foi usado um vetor com elementos de 16 bits (short) e no de 8 bits (char), comtamanho igual metade do espao desejado para fazer a reserva adequadamente. Pode parecerestranho no usar diretamente um vetor do tipo char, mas esta ao ir garantir que o vetor estejaalinhado na memria em valores mltiplos de 16 bits, um requisito para a pilha em plataformasonde o alinhamento importante. Desta forma, use um tipo de dado no seu vetor que seja do mesmotamanho da palavra da plataforma (o tipo int, em geral, resolve isso).A tarefa, por sua vez, apenas um lao infinito que executa a sua operao, como pode ser visto nocdigo a seguir.#define TASK_STACK_SIZE 50unsigned short usStack[TASK_STACK_SIZE/2];void task(unsigned long ulArgc){while(1){int i = 0;while(i < 50){ i = i + 1;}BRTOS_Sleep(5);}}Exemplo de tarefa e alocao de stackNo Basic RTOS, todas as tarefas devem ser criadas dentro da chamadaBRTOS_Application_Initialize(). No foi previsto a criao de tarefas dinamicamente, uma 6. restrio relativamente sensata quando se pensa num sistema microprocessado pequeno.void BRTOS_Application_Initialize(void){BRTOS_CreateTask(task,/*ponto de entrada*/(unsigned short)&usStack[TASK_STACK_SIZE/2-1],/*pilha (fim do vetor)*/10, /*time slice (ticks)*/BRTOS_TASK_PRIORITY_1); /*prioridade ( usada)*/}Adicionando uma tarefa ao sistemaEm geral, no se espera que a tarefa retorne mas, se isto acontecer, o sistema operacional precisalidar com esta condio. Neste caso, no momento da criao da tarefa, gerado um contextoespecial na pilha da tarefa que, caso acontea um retorno, a coloque em um estado seguro.3.4 O escalonadorNesta seo descrito como implementar um escalonador para o sistema, atravs da rotinaBRTOS_Scheduler(). Esta rotina associada com a rotina de interrupo do watchdog e o ponto deentrada do batimento peridico do sistema (tick), como descrito anteriormente. Por ser executadaem modo interrompido o retorno dela ser feito por uma instruo "reti", que restauraautomaticamente os registros SR e PC da pilha.Para esta rotina necessrio um tratamento especial por parte do compilador. A palavra reservada"NAKED", presente na definio da funo, ir instruir o MSPGCC a criar uma funo que nofaa nenhuma mudana na pilha ao ser executada. Neste caso, nenhum contexto adicional ouargumento de chamada de funo salvo na pilha, algo bem apropriado para uma funo com papelde escalonador do sistema. Caso o escalonador precise usar a pilha, o SP precisa ser salvo e a pilhado escalonador definida.A rotina do escalonador est a seguir, com comentrios sobre cada parte dela logo depois.NAKED( BRTOS_Scheduler ){save_context_entry: SaveContext(); SaveStackPointer(); RestoreSchedStackPointer();dont_save_context_entry: /* Update timers */ BRTOS_ProcessTimers(); /* check sleeping tasks */ BRTOS_SleepTasks(); /* Get the next task to run */ ucCurrentTask = BRTOS_RoundRobin(ucCurrentPriLevel); if(ucCurrentTask == BRTOS_NO_TASK_TO_RUN) { /* nothing to do: sleep */ GoToLowPowerMode3(); goto dont_save_context_entry; 7. } /* save scheduler context */ SaveSchedStackPointer(); /* restore stack pointer */ RestoreStackPointer(); /* restore other registers */ RestoreContext(); /* reti will pop PC and SR from stack (naked function) */ EnableInterrupts(); ReturnFromInterrupt();}Escalonador de tarefas do sistemaA primeira ao salvar o contexto com SaveContext(). Perceba que deve existir uma tarefa emexecuo e o ponteiro da pilha atual (SP) tem relao com esta tarefa. SaveContext() ir colocar napilha desta tarefa os registros relacionados com a chamada de SaveContext(), deixando a pilha datarefa com a seguinte estrutura:Stack pointer R15 R14... R3 PC SR...Figura 3: Pilha com o contexto da tarefa salvoSaveContext() escrita em assembly j que preciso controle total neste momento:#define SaveContext() __asm__ __volatile__ ("pushR3n""pushR4n""pushR5n""pushR6n""pushR7n""pushR8n""pushR9n""pushR10n" "pushR11n" "pushR12n" "pushR13n" "pushR14n" "pushR15" ) Salvamento dos registros da tarefa corrente na pilhaCom o contexto salvo, falta agora salvar a posio atual do SP da tarefa no TCB dela, com achamada SaveStackPointer(). A notao do conjunto de ferramentas do GCC: 8. #define SaveStackPointer()asm("mov.w R1,%0" : "=m" (asBrtosTasks[ucCurrentTask].pusStackPtr)) Salvando o stack pointer da tarefa correnteNeste ponto est criada a condio ideal para trocar o SP da tarefa pelo SP do escalonador,devidamente guardado na varivel usSchStackPtr atravs da funo RestoreSchedStackPointer().Definir o SP do escalonador vai permitir que chamadas em C sejam feitas e variveis locais sejamcriadas, reduzindo ao mximo a quantidade de cdigo assembly no sistema. A inicializao do SPdo escalonador feita na partida do sistema, descrito mais adiante.#define RestoreSchedStackPointer()asm("mov.w %0,R1" :: "m" (usSchStackPtr))Restaurando o stack pointer do escalonadorDepois deste incio com um bom grau de dependncia da plataforma e do compilador, duas tarefasde faxina so feitas. Uma delas processar os temporizadores (timers), ainda no implementada naverso atual, e a outra verificar se as tarefas em modo "SLEEP" ainda precisam continuar dormindoou no.BRTOS_ProcessTimers();BRTOS_SleepTasks(); Processamento de timers e tarefas em estado de suspensoO prximo passo decidir quem ficar com o controle do processador, feito atravs da chamadaBRTOS_RoundRobin() que ir retornar qual tarefa deve ter seu contexto restaurado e ser colocadaem execuo. O funcionamento desta rotina descrito mais adiante.ucCurrentTask = BRTOS_RoundRobin(ucCurrentPriLevel);Determinando a prxima tarefa a ser colocada em execuo.Se no existe nenhuma tarefa pronta para entrar em execuo, o escalonar coloca o processador emmodo de espera (GoToLowPowerMode3()) at que a prxima interrupo do watchdog acorde oprocessador, voltando algumas linhas atravs de um goto e refazendo as tarefas de rotina. Esteponto pode ser melhorado j que se o processador sair do modo de espera por outro motivo, acontagem de ticks para tarefas em SLEEP no estar correta. Uma sada bastante empregada teruma tarefa para cuidar desta situao, ao invs de fazer isto no escalonador, evitando maioresproblemas.f(ucCurrentTask == BRTOS_NO_TASK_TO_RUN){/* nothing to do: sleep */GoToLowPowerMode3();goto dont_save_context_entry;} Modo de economia de energia caso no exista tarefa para ser executada.Uma vez que se tenha a tarefa que ser executada definida, hora de restaurar o contexto e devolvero processador para ela. As tarefas so relativamente simples: salvar o SP do escalonador, restaurar oSP da tarefa, restaurar os registros da tarefa e retornar da interrupo. A pilha esperada para a tarefadeve ser como a descrita anteriormente para que a tarefa assuma corretamente o contexto.SaveSchedStackPointer(); 9. RestoreStackPointer();RestoreContext();EnableInterrupts();ReturnFromInterrupt(); Tarefas necessrias para restaurao do contextoA rotina apresentada pode ser melhorada e bem dependente do processador e compiladorutilizados. A dependncia ficou oculta atravs de macros que invocam chamadas em assembly, masso partes do cdigo que precisam ser repensadas caso a plataforma seja diferente.4 Controle de tarefasApesar de a maior parte do BRTOS ter sido coberta, existem alguns detalhes importantes queprecisam ser explicados para o adequado funcionamento do sistema. Neste seo sero exploradosos detalhes relacionados ao gerenciamento de tarefas atravs da rotina BRTOS_CreateTask().O controle de tarefas do sistema extremamente simples, composto por um vetor de TCBschamado asBrtosTasks. Ao pedir a criao de uma tarefa, uma nova posio usada neste vetor. Osparmetros necessrios so o ponto de entrada da tarefa (entry_point), o endereo da pilha(stack_addr), fatia de tempo mxima (time_slice) e prioridade (pri). Estes parmetros so guardadosno vetor de TCBs e a tarefa colocada no estado de "READY", ou seja, pronta para executar. Valelembrar que a maioria dos RTOSs permite iniciar uma tarefa em estado de espera, ou seja, que nosaia rodando imediatamente. Isto no est implementado neste sistema.asBrtosTasks[usNumTasks].pfEntryPoint = entry_point;asBrtosTasks[usNumTasks].pusStackBeg= (unsigned short *) stack_addr;/* ponteiro corrente da pilha */asBrtosTasks[usNumTasks].pusStackPtr= (unsigned short *) stack_addr;asBrtosTasks[usNumTasks].usTimeSlice= MSEC_TO_TICKS(time_slice);asBrtosTasks[usNumTasks].ucPriority = pri;asBrtosTasks[usNumTasks].ucTaskState= BRTOS_TASK_STATE_READY; Inicializando o TCBO que no bvio no processo de adio de uma nova tarefa no sistema que a pilha inicial datarefa precisa ser preparada. Como visto anteriormente, quando a interrupo do escalonadoracontece, esperado que a tarefa em execuo possua um contexto a ser salvo formado pelosregistros gerais (R3 a R15) e tambm os registros SP e o PC, colocados na pilha por causa dainterrupo do escalonador. Logo, necessrio imitar esta pilha inicial no momento da criao datarefa.E tem mais um detalhe que no pode ser ignorado. Geralmente, uma tarefa implementada comoum lao infinito mas que alguns cuidados precisam ser tomados caso ela no siga este padro ousimplesmente retorne. Neste caso, seria um retorno de modo no interrompido, implementado noMSP430 pela instruo ret, que apenas muda o PC corrente para um possvel PC que esteja napilha (sem SR, neste caso). A recomendao aqui colocar um local vlido e seguro para este novoPC, no caso uma funo chamada BRTOS_TaskEnd(), descrita mais abaixo.Com todos estes fatores considerados, o diagrama da pilha inicial da tarefa ficar ento como naFigura 4. Lembre-se que a lgica de pilha do MSP430 apontar para um valor livre e decrescerquando valores so adicionados (isto tambm dependente de plataforma). 10. pusStackPtr R15 R14 ...R3PCSRBRTOS_TaskEndpusStackBegFigura 4: Pilha inicial da tarefaO cdigo necessrio para criar esta pilha inicial pode ser visto abaixo:/* if task returns some day, prepare stack */*(asBrtosTasks[usNumTasks].pusStackPtr) = (unsigned short) BRTOS_TaskEnd;asBrtosTasks[usNumTasks].pusStackPtr -=1;/* status register and program counter */*(asBrtosTasks[usNumTasks].pusStackPtr) = (unsigned short) 0;asBrtosTasks[usNumTasks].pusStackPtr -=1;*(asBrtosTasks[usNumTasks].pusStackPtr) = (unsigned short) entry_point;asBrtosTasks[usNumTasks].pusStackPtr -=1;/* prepare for first RestoreContext(): dummy NUM_REGS_IN_CONTEXT regs */for(i = 0 ; i < NUM_REGS_IN_CONTEXT ; i++){*(asBrtosTasks[usNumTasks].pusStackPtr) = (unsigned short) 0;asBrtosTasks[usNumTasks].pusStackPtr -= 1;}Criao completa do stack inicial da tarefa.A implementao da funo BRTOS_TaskEnd() trival, apenas coloca a tarefa no estado de"TERMINATED" e fica num lao infinito de forma que ela no estrague nada at que o escalonadorrode novamente e escolha uma tarefa do grupo de tarefas prontas para serem executadas (tarefas emREADY). Seria possvel fazer algo melhor aqui sem grandes modificaes, como umaimplementao que permita um reincio (RESTART) da tarefa mesmo depois de ela ter ido paraTERMINATED, algo geralmente encontrado em sistemas de tempo real.static void BRTOS_TaskEnd(void){EnterCriticalSection();asBrtosTasks[ucCurrentTask].ucTaskState = BRTOS_TASK_STATE_TERMINATED;LeaveCriticalSection();while(1);}Terminado uma tarefa de forma segura. 11. 5 Inicializando o sistemaA partida do sistema merece tambm ateno, devendo ser feita de forma organizada. Nesta seo feita uma breve discusso sobre a inicializao do sistema, atravs da funo main(), listada aseguir:int main(void){/* Saving the current stack pointer. It will be used by the scheduler. */SaveSchedStackPointer();EnterCriticalSection(); /* initialize control structures and create all user tasks */ BRTOS_Initialize(); /* call user initialization: you must create at least one thread */ BRTOS_Application_Initialize(); /* the stack pointer should point to the first available task stack,and the context should be subtracted. This way, the calling ofGoToScheduler will not fail */ asBrtosTasks[ucCurrentTask].pusStackPtr += NUM_REGS_IN_CONTEXT; RestoreStackPointer(); LeaveCriticalSection(); /* go to to scheduler routine*/ GoToScheduler();}Rotina de inicializao do sistemaVrias tarefas so esperadas e no requerem explicaes. Perceba que o escalonador vaicompartilhar a pilha desta funo, j que o SP dele salvo partir dela. O que tem de estranho aqui a manipulao feita no ponteiro da pilha da tarefa corrente e no SP. No fundo, est sendo recriadaa situao de pilha que acontece no caso de uma interrupo, por isso remove-se os registros de R3a R15, restauramos o SP da tarefa e realizamos um salto para o escalonador, como se esta fosserealmente a tarefa corrente. Depois deste ponto, o processamento segue normalmente.Os pontos de entrada dentro do escalonador (save_context_entry e dont_save_context_entry)foram inicialmente criados para permitir entrada no escalonador com ou sem salvamento decontexto, o que gera uma ao mais otimizada na partida, sem perder tempo fazendo e desfazendoesta pilha inicial.6 ConclusoAtravs deste artigo foram evidenciados as principais questes envolvidas no processo deconstruo de um RTOs, como escalonares, troca de contexto, etc. Estas questes foram detalhadase explicadas, com o objetivo de aumentando o entendimento e fomentar o uso e desenvolvimento desistemas de tempo real. 12. 7 AgradecimentosApesar de este trabalho ter sido totalmente escrito fora da empresa onde o autor trabalha, no hdvida de que s foi possvel devido a experincia adquirida nos vrios projetos que participou.Assim sendo, o autor gostaria de agradecer Smar Equipamentos Industriais LTDA pelasoportunidades e desafios enfrentados.8 Referncia[1] Basic RTOS project page. http://code.google.com/p/basicrtos/9 LicenciamentoA obra Fundamentos de Sistemas Operacionais de Tempo Real - Criando seu prprio escalonadorde tarefas de Marcelo Barros de Almeida foi licenciada com uma Licena Creative Commons -Atribuio - Uso No-Comercial - Partilha nos Mesmos Termos 3.0 No Adaptada.Com base na obra disponvel em http://code.google.com/p/basicrtos/Podem estar disponveis permisses adicionais ao mbito desta licena atravs do contato direto aoautor via e-mail [email protected].