PIC18F Kernel - 01

Post date: 19/12/2010 22:58:47

Bom dia a todos.

Vou iniciar uma serie de posts sobre kernel: o que é, como funciona e como fazer. Sim, a idéia é desenvolver um kernel (simples, cooperativo e sem controladores de memória) para o microcontrolador PIC18F4550. Minha idéia é projetá-lo inteiro em ISO-C, desse modo o código pode ser facilmente portado para qualquer arquitetura.

Kernel - Wikipedia

Na figura acima podemos ver que o kernel é o responsável por realizar a interface entre o hardware (CPU, Memória e Periféricos) e as aplicações. Quando não existe kernel todo o processo de organização das tarefas, sejam elas de hardware ou de aplicação é feita pelo programador. Uma primeira tentativa de organizar o código quando um kernel não está disponível é utilizar uma máquina de estados:

Máquina de estado para o sistema proposto.

A tradução da máquina de estados para o código principal é bem simples. Basta usar uma estrutura switch...case.

Obs: a função principal é realmente void main(void) interrupt 0. Isso é feito assim por causa do compilador SDCC.

Esta estrutura traz diversas vantagens para o sistema: organização, facilidade de manutenção e principalmente previsibilidade. Conhecendo os tempos de execução de cada função é possível dizer com que frequência cada uma das funções/processos será executada. Esta é a base de um sistema de tempo real.

Mesmo o código se apresentando de modo organizado, a manutenção e expansão do sistema fica prejudicada, pois a frequência de execução fica a cargo do programador. A primeira função de um kernel é essa:

1) Organizar e permitir a execução dos processos, com base em "algum critério"

O "algum critério" pode ser o tempo máximo de execução, a prioridade das funções, a criticidade dos eventos, a sequência programada de execução etc. É este critério que diferencia os kernels preemptivos, cada processo tem um tempo máximo para ser executado, dos cooperativos, cada processo é executado até o final e apenas depois dá sequência ao próximo. Como ele é responsável por organizar os processos, é necessário ter funções que permitam a inclusão de um novo processo e a remoção de um processo antigo. Deste modo o loop apresentado no código acima fica "invisivel" para o programador. A execução das tarefas passa a ser coordenada pelo kernel.

Cada processo utiliza internamente uma quantidade de memória para suas variáveis locais, passagem de parâmetros para as funções que ele chama etc. Essa é a segunda função de um kernel:

2) Permitir o acesso dos programas à memória disponível no sistema

Nesse ponto o kernel também deve se preocupar em informar ao programa quando a requisição dele não pode ser cumprida, ou seja, interceptar todos os comandos malloc e tratar os possíveis erros.

Além da memória os processos envolvidos precisam de "conversar" com os demais recursos do computador/microcontrolador: porta serial, ethernet, dispositivo de vídeo, teclado, etc. A permissão de uso destes dispositivos é feita através de pedidos feitos ao kernel. Esta é a terceira responsabilidade do kernel:

3) Intermediar a comunicação entre os periféricos e os processos.

O kernel deve possuir então uma função que recebe como parâmetros (no mínimo) qual o periférico a ser acessado e qual a ordem a ser enviada ao periférico. Ele então direciona estes pedidos aos drivers que, só então, devolvem a resposta para o processo requisitante.

Definição do objetivo:

Como disse, vou, nos próximos posts, apresentar um passo a passo do desenvolvimento deste kernel. Para simplificar o processo, o kernel atenderá apenas aos requisitos 1 e 3. O modo de organização dos processos será não-preemptivo, cooperativo e com níveis de prioridade ajustáveis. Os drivers terão suas operações padronizadas.

Já vislumbrando o funcionamento do kernel, o próximo post será sobre ponteiros de função.

Até mais.