Instituto Superior de Engenharia de Lisboa Departamento de Engenharia de Eletrónica e Telecomunicações e de Computadores Licenciatura Engenharia Eletrónica de Telecomunicações e de Computadores Projeto Final LEETC Programação Paralela em occam-pi Relatório Final 10 de Setembro 2012 Realizado por: Rui Alexandre da Silva Miranda, nº 32342 Orientado por: Engº Manuel Barata
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Instituto Superior de Engenharia de Lisboa Departamento de Engenharia de Eletrónica e Telecomunicações e de Computadores
Licenciatura Engenharia Eletrónica de Telecomunicações e de Computadores
Projeto Final LEETC
Programação Paralela em occam-pi
Relatório Final
10 de Setembro
2012
Realizado por:
Rui Alexandre da Silva Miranda, nº 32342
Orientado por:
Engº Manuel Barata
Projeto Final LEETC - Programação Paralela em occam-pi
2012
2
Agradecimentos
O projeto final de curso representa pessoalmente o reconhecimento de um
longo e árduo percurso académico. A sua realização não teria sido possível
sem o apoio de certas pessoas ou entidades, às quais gostaria de
agradecer.
Ao DEETC e todos os seus membros, por me terem proporcionado a
formação para poder realizar este Projeto Final.
Ao Engenheiro Manuel Barata, por ter sugerido este projeto, ainda mais por
se tratar de um tema pouco abordado, mas extremamente interessante, e
também pela disponibilidade que sempre mostrou para apoiar,
inclusivamente fornecendo o microcontrolador.
À minha companheira, Alina Bordalo, a qual me deu forças para continuar
mesmo nas altura mais difíceis.
Projeto Final LEETC - Programação Paralela em occam-pi
2012
3
Resumo
Este projeto tem como objetivo a criação de uma máquina virtual, e todos
os seus recursos subjacentes, para que seja possível correr um programa
occam-pi sobre um microcontrolador da família PIC32. Com isto pretende-
se a abstração do Hardware em relação à linguagem do Software,
alcançando assim um nível de portabilidade e eficiência na escrita de código
paralelo num sistema embebido de tempo-real, superior à actual.
Como suporte ao desenvolvimento do projeto foi necessária a aprendizagem
de todas as tecnologias envolvidas: linguagem de programação paralela
occam-pi [2]; arquitetura do microprocessador Transputer [14]; programação
C no microcontrolador PIC32 [8].
Para implementação desta máquina virtual foi necessário, proceder à
migração da máquina virtual do Transputer (TVM) [4], do sistema POSIX
para o sistema embebido, PIC32. Após a migração, foi desenvolvida uma
pequena biblioteca de funções para abstração do Hardware (HAL). Foi
também desenvolvida uma aplicação, a executar ambiente Linux, para o
carregamento no PIC32 dos bytecodes do programa occam já compilado,
através da porta série (USB).
O objetivo final do projeto consiste na execução de uma aplicação de
demonstração desenvolvida em occam-pi, na máquina virtual implementada
no Kit com um microcontrolador PIC32.
Projeto Final LEETC - Programação Paralela em occam-pi
Índice de Figuras Figura 1 - Transputer T425 ............................................................................................................ 8
Figura 2 – Lista Ligada de Processos de Baixa Prioridade ........................................................... 10
Figura 3 - FIFO em occam-pi ........................................................................................................ 11
Figura 4 - Execução fifo.tbc ......................................................................................................... 12
Figura 5 – Correspondência de tipos entre occam e C ............................................................... 15
Figura 6 – Função interface e correspondentes tipos ................................................................. 15
Figura 7 – Output teste TVM ....................................................................................................... 17
Figura 8 - UBW32 ........................................................................................................................ 18
Figura 9 - MPLAB IDE ................................................................................................................... 19
Figura 10 - MPLAB C32 Compiler ................................................................................................ 20
Figura 11 – Bootloader ................................................................................................................ 20
Figura 12 – Terminal .................................................................................................................... 21
Figura 13 - Diagrama da Maquina Virtual occam-pi.................................................................... 22
Índice de exemplos Exemplo 1 – Rotina main da TVM ............................................................................................... 14
Exemplo 2 – Programa occam de teste da TVM ......................................................................... 17
Exemplo 3 – Rotina main PIC32 .................................................................................................. 21
Exemplo 4 – Inicialização do Timer PIC32 ................................................................................... 26
Exemplo 5 – Leitura do Timer PIC32 ........................................................................................... 26
Projeto Final LEETC - Programação Paralela em occam-pi
2012
7
1. Enquadramento Teórico
1.1. Sistemas Embebidos de Tempo-Real [1] Com o exponencial crescimento da indústria de tecnologias móveis nas
últimas décadas, cada vez mais se dá importância a sistemas embebidos, como por exemplo microcontroladores. Estes sistemas são definidos como sistemas de computação com os recursos estritamente necessários para
executar uma função específica. Atualmente o uso de sistemas embebidos é praticamente global, tendo aplicações tanto em ambientes privados como
em ambientes empresariais. Ainda no atual panorama tecnológico cada vez mais são necessários
sistemas de tempo-real, estes sistemas podem ser definidos como sistemas
que respondem a eventos externos de forma pronta.
Da junção dos dois conceitos descritos anteriormente, surge outro tipo de
sistema, o sistema embebido de tempo-real, que abrange os principais
aspetos dos outros dois. Os sistemas embebidos de tempo-real têm os mais
diversos tipos de aplicações atualmente, como por exemplo em veículos
motorizados, sistemas de telecomunicações, entre outros.
1.2. Programação Paralela [4] Com a introdução de sistemas de tempo-real, vem a necessidade de uma
programação mais eficiente no que toca a tempos de execução, fazendo uso
de múltiplas unidades de processamento de um sistema, de sistemas em rede partilhando recursos, ou de ambos, é possível um programa executar
varias instruções em simultâneo, este modelo de computação é designado por programação paralela. Das mais diversas linguagens que suportam programação paralela, temos a occam. Esta linguagem foi desenvolvida em
1980 por uma equipa da INMOS como linguagem nativa do seu microprocessador Transputer, e baseada na teoria de T. Hoare, CSP
(Communicating Sequential Process). Uma das principais funcionalidades desta linguagem é a concorrência entre processos e comunicação entre eles. A gestão da concorrência entre processos paralelos é feita através da
comunicação entre os mesmos através de canais síncronos. A universidade de Kent (Reino Unido) tem vindo a dar continuidade ao estudo e aplicação
do occam, sendo a versão mais recente o occam-pi, desenvolvida pela equipa KRoC (ver 2.3). Mantendo assim ativo este paradigma de programação que para além de poder ser executado por um processador,
pode também ser usado para programar arquiteturas com vários núcleos processadores, ou até mesmo ser diretamente compilada para execução em
Hardware programável (e.g. FPGA). Atualmente existem disponíveis várias ferramentas para desenvolver e testar programas occam, sendo estas
código aberto e livre. Uma delas é o TRANSTERPRETER que utilizando uma máquina virtual emula um processador que executa código compilado do occam. O código dessa máquina virtual é simples e passível de ser migrado
para execução em qualquer processador de 8, 16 ou 32 bit.
Projeto Final LEETC - Programação Paralela em occam-pi
2012
8
2. Estudo Desenvolvido
2.1. Transputer [5] Nos anos 80 a companhia de semicondutores INMOS produziu o
Transputer (Figura 1 - Transputer T425), um inovador microprocessador de alta
performance desenhado para computação paralela. O
Transputer possui 4 canais série integrados, que permitem a ligação dos microprocessadores entre si.
Neste contexto surge a linguagem occam, desenhada especificamente para programar no Transputer, com uma ligação muito mais forte ao Hardware do que linguagens
como C ou Pascal em relação aos processadores de arquitetura CISC (Complex Instruction Set Computer).
[14] Uma das versões mais reconhecidas do Transputer foi a T800, que tem
como características principais: processador a 32 bits com uma
performance de 15 MIPS (Million of Instruncions per Second); unidade interna de floating poit a 64 bits; 4 Kbytes de RAM interna com uma velocidade de escrita/leitura de 120Mbytes/seg; dois temporizadores
internos; etc. Das principais utilizações deste microcontrolador, destacam-se: aplicações matemáticas e científicas; processamento gráfico de alta
performance; supercomputadores; etc.
2.1.1. Registos
[14] Existem 6 registos disponíveis para a execução de processos
sequencialmente, a razão de ser um número reduzido deve-se ao facto, do
Transputer ter ao seu despor RAM com uma rápida velocidade de escrita/leitura. Os 6 registos são: ponteiro do Workspace, que aponta para
o local onde se encontram as variáveis locais; ponteiro da próxima instrução a ser executada; o operando da instrução; três registos para avaliação das operações, A, B e C;
2.1.2. Instruções
[14] Cada instrução é composta por 1 byte, onde os 4 bits de maior peso
representam o código da função, e os 4 bits de menor peso contêm o valor
dos dados. Os bits de dados são carregados nos 4 bits menos significativos
do registo de operando.
a) Funções Diretas
[14] A representação das funções permite a codificação de 16 funções, com
um valor possível de dados entre 0 e 15. Treze dos valores possíveis para
codificações de funções, são usados para as instruções mais comuns, como
carregamento/soma de constantes/variáveis locais, Jump, Call, entre
outras.
Figura 1 - Transputer T425
Projeto Final LEETC - Programação Paralela em occam-pi
2012
9
b) Funções de Prefixo
[14] Por forma a possibilitar nas funções utilização de dados com valores
superior a 15 (codificação com 4 bits), existem dois códigos de funções
disponíveis: prefixo e prefixo negativo. A função prefixa carrega conteúdo
dos dados (4 bits de menor peso do byte de instrução) nos 4 bits de menor
peso do registo de operando, e desloca o mesmo registo 4 posições na
direção de maior peso. A única diferença da função de prefixo negativo
consiste na negação bit a bit do registo operando, antes da deslocação. É
possível assim através de uma sequência de instruções prefixo a operação
de valores de dados de qualquer valor até ao máximo suportado pelo
registo operando.
c) Funções Indiretas
[15] O último valor disponível codifica a função operate, esta faz com que do
conteúdo registo operando seja interpretado como um código de operação
da instrução a ser executada.
2.1.3. Processos e Concorrência
[14][15] Um processo é uma sequência de instruções, sendo executado com
suporte nos 6 registos existentes (ver 2.1.1). O Transputer permite a
execução de vários processos em paralelo (concorrentemente), neste caso
cada um dos processos tem um espaço de memória reservado para o
respetivo Workspace. Este Workspace é usado para guardar variáveis locais,
e valores temporários manipulados pelo processo.
O processador contém um Scheduler internamente programado, que gere o
Time-Slice atribuído a cada um dos processos paralelos, eliminando assim
processamento desnecessário de processos inativos (um processo pode ficar
inativo se estiver a aguardar input/output, ou se estiver a aguardar por um
tempo especifico).
Os processos ativos em espera para ser executados são colocados em duas
listas ligadas (Alta prioridade, e baixa prioridade: ver 2.1.4). Cada uma das
listas é implementada com base em 2 registos, um que aponta para o
primeiro processo da lista, o outro para o ultimo. Como pode ser visto na
Figura 2 – Lista Ligada de Processos de Baixa Prioridade, o processo S está a ser
executado, enquanto estão em espera os processos P,Q e R. Para os
processos de alta prioridade o esquema é o mesmo, mudando somente a
designação dos apontadores de início e fim da lista, para FPtr0 BPtr0,
respetivamente.
Projeto Final LEETC - Programação Paralela em occam-pi
2012
10
Figura 2 – Lista Ligada de Processos de Baixa Prioridade
2.1.4. Prioridade de Processos
[14] O conceito de prioridade de processos, foi uma especificação que surgiu
com o Tranputer T800. Existem dois níveis de prioridade: baixa (prioridade
1) e alta (prioridade 0), os processos de prioridade baixa só tem direito a
Time-Slice quando não existe nenhum processo de prioridade alta ativo.
2.1.5. Comunicação entre Processos
[14][15] Por forma a permitir a comunicação e sincronização entre processos
concorrentes existem canais, estes canais série síncronos permitem a
comunicação dentro do Transputer (no mesmo programa através de
endereço de memória), ou a comunicação com o exterior (entre Transputers
diferentes através de canais séries). O processo que chegar primeiro à
instrução de input/output do canal fica inativo enquanto o outro processo
não chega também à sua instrução de output/input respetiva, quando o
segundo chega os dados são transferidos através do canal e cada um dos
processos continua com a sua execução.
2.1.6. Temporizadores
[14] Estão ainda disponíveis para utilização dois temporizadores de 32 bits
internos ao Transputer. O Timer0 (Período de 1 microssegundo) é acedido
apenas por processos de alta prioridade, enquanto o Timer1 (Período de 64
microssegundos) é acedido apenas por processos de baixa prioridade.
Projeto Final LEETC - Programação Paralela em occam-pi
2012
11
2.2. Occam
2.2.1. Características Principais [6] O modelo occam permite a concorrência, mais especificamente, o
verdadeiro paralelismo em multiprocessadores, ou paralelismo simulado num único processador através da técnica de “Time-Slicing”, este segundo
será o utilizado para implementar a máquina virtual no PICMX32, visto que este possui um único processador de 32bits.
O paralelismo occam é ao nível da instrução, isto significa que sem indicação contrária, cada instrução é interpretada como um processo, podendo ser executada em concorrência com outras. A comunicação entre
processos concorrentes é feita através de canais síncronos, ou seja, quando dois processos partilharem um canal sempre que um chegar a uma
localização do código onde lê de um canal esse mesmo processo aguarda até que o outro escreva no mesmo canal, e assim transferem informação entre si.
2.2.2. Exemplo Para a investigação da Linguagem occam, mais especificamente da última versão occam-pi, e das suas funcionalidades foram feitos vários testes e
experimentações através do programa emulador de occam-pi/Transputer, Transterpreter [7]. De um dos programas de teste feitos destaca-se a
implementação de uma Lista FIFO através da Linguagem occam-pi, funcionamento descrito na Figura 3 - FIFO em occam-pi.
Figura 3 - FIFO em occam-pi
Projeto Final LEETC - Programação Paralela em occam-pi
2012
12
Para teste da lista FIFO, é lido um carácter do teclado e colocado no canal
de entrada da FIFO, após um delay, é consumido o carácter no canal de saída, resultando da execução deste programa de teste Figura 4 - Execução fifo.tbc.
Figura 4 - Execução fifo.tbc
Projeto Final LEETC - Programação Paralela em occam-pi
2012
13
2.3. Projeto KRoC [4][16] KRoC, ou Kent Retargetable occam Compiler, é uma plataforma open-
source para a linguagem occam/occam-pi, composta por um compilador de
occam, tradutor de código nativo do Transputer, e sistemas de run-time
(com suporte a diferentes ambientes). Este projeto de investigação continua
ativo na universidade Kent (Reino Unido).
Atualmente esta plataforma suporta os seguintes sistemas operativos:
Linux
FreeBSD
MacOS X
Windows (através do Cygwin)
Arduino (ou sistemas embebidos semelhantes)
NxOS [17](sistema operativo embebido do robot LEGO Mindstorms
NXT [18])
2.3.1. Compilador occam O compilador de occam da plataforma KRoC (occbuild) trata de compilar os
ficheiros de código occam/occam-pi (occ), gerando o ficheiro com os
bytecodes correspondentes do Transputer (tbc). Este processo é
independente do ambiente sobre o qual vamos correr o programa
occam/occam-pi.
2.3.2. Interpretador A tradução e o run-time, ou interpretação dos bytecodes, ficam a cargo da
TVM (Transputer Virtual Machine), esta com respetiva implementação para
cada um dos ambientes sobre os quais se pretende correr o programa
occam/occam-pi.
A implementação escolhida para estudo, e posterior migração, foi a do
sistema NxOS/NXT, isto por ser a que continha menos dependências para
com o hardware/sistema. Passando a explicar o funcionamento da TVM:
a) Tradução O ficheiro tbc é passado como parâmetro da TVM, este é lido e os seus
bytes colocado num array, tbc_data, após isto o array é descodificado para
um formato de contexto de execução das instruções do Transputer. A
estrutura da variável de contexto, context, é composta por diversos
objetos que especificam o processador a emular, o Transputer, como os
registos do mesmo (ver 2.1.1), e outras variáveis e ponteiros de funções
para suporte à execução do programa occam/occam-pi sobre a TVM.
Projeto Final LEETC - Programação Paralela em occam-pi
2012
14
b) Run-Time Após a iniciação da TVM, carregamento do tbc e respetiva descodificação, é
iniciada a rotina de execução do programa occam/occam-pi. Esta rotina é
executada enquanto o programa não terminar, por defeito é executada uma
instrução do contexto por ciclo da rotina, após esta execução é avaliado o
seu retorno (para ver se a TVM encontro algum erro, a execução encontra-
se em espera por um tempo especifico, ou o programa terminou). Parte da
rotina main pode ser vista no Exemplo 1.
A execução da instrução resume-se à chamada da função
dispatch_instruction, recebendo o contexto e o código da instrução a ser
executada, mapeia o código da instrução para a função respetiva, sendo
nessa função manipulado o conteúdo do contexto, por forma a executar a
instrução passada.
A maior parte destas funções mapeadas, são a transcrição direta das
instruções do Transputer (ver 2.1.2), existindo outras especificas de certas
funcionalidades do occam-pi, e por fim existe a instrução de chamada a
funções do tipo ffi/sffi (Foregin Function Interface/Special Foregin Function
Interface) ver c).
Exemplo 1 – Rotina main da TVM
Projeto Final LEETC - Programação Paralela em occam-pi
2012
15
c) Funções tipo sffi [20] As funções do tipo ffi/sffi permitem a chamada direta a partir do
programa occam/occam-pi a funções características do ambiente.
Estas funções interface têm de ser definidas, declaradas e atribuídas ao
array de funções sffi no módulo homónimo, com o seguinte cabeçalho:
int interface_function_name (ECTX ectx, WORD W[])
Na implementação desta função interface será chamada a função específica
de C, devendo esta ser definida noutro módulo (boa prática). Ao chamar
esta função é necessário ter atenção para com o mapeamento dos tipos, já
que o elementos do array parâmetro de entrada é do tipo especifico da
TVM, WORD, o qual não terá o mesmo significado que o tipo WORD do
PIC32.
O parâmetro array W[], contem todos os parâmetro de entrada da função
occam/occam-pi, estando o primeiro parâmetro de entrada na posição zero,
e os restantes em diante.
Nas figuras abaixo (Figura 5 e Figura 6) pode-se observar todo o mapeamento
deste da função occam, à interface, até à função C.
Figura 5 – Correspondência de tipos entre occam e C
Figura 6 – Função interface e correspondentes tipos
Projeto Final LEETC - Programação Paralela em occam-pi
2012
16
Já em código occam/occam-pi é necessário declarar o seguinte protótipo:
Onde a diretiva #PRAGMA EXTERNAL indica ao processador que a
implementação desta função é externa ao sistema occam. A letra C a seguir
a PROC indica à TVM que terá que gerar uma chamada especial (sffi) a uma
função C. VAL BYTE C é apenas um exemplo de um parâmetro de entrada
da função. O atributo a redefinição INLINE serve apenas para simplificar o
nome da função no código occam.
Projeto Final LEETC - Programação Paralela em occam-pi
2012
17
2.3.3. Teste Para testar a TVM, do sistema NXT/NxOS, foi necessário efetuar ligeiras
alterações para permitir a execução da mesma em ambiente Linux,
nomeadamente:
Removida a rotina de carregamento do programa occam/occam-pi via
USB.
Acrescentada função, read_tbc_file, para carregamento do
programa occam/occam-pi através argumento da linha de comandos.
Removidas todas as funções específicas do sistema NXT/NxOS.
Acrescentadas algumas funções básicas do tipo sffi, para permitir o
debug imediato de alguns testes (put_char/get_char).
O programa occam a testar, 00_hello.tbc, foi o mais básico possível,
apenas faz o print para a consola do valor 33 (ver Exemplo 2), o ouput
da sua execução pode ser visto na Figura 7 – Output teste TVM.
Exemplo 2 – Programa occam de teste da TVM
--aqui definimos a chamada à função sffi, que se encontra na posição 1
--do array de funções sffi
#PRAGMA EXTERNAL "PROC C.tvmspecial.1.put.char1 (VAL BYTE C) = 0"
INLINE PROC put.char1 (VAL BYTE ch)
C.tvmspecial.1.put.char1(ch)
:
--ponto de entrada do programa
PROC hello ()
SEQ
put.char1(33)
:
Figura 7 – Output teste TVM
Projeto Final LEETC - Programação Paralela em occam-pi
2012
18
2.4. PIC32MX460
2.4.1. Características Principais
[8][9] O PIC32MX460 é um microcontrolador da família PIC32, este
dispositivo permite uma velocidade de processamento superior a 80 DMIPS (Dhrystone Million of Instruncions per Second) e tem uma grande variedade
de periféricos integrados. Uma característica específica da família PIC32MX é facilidade de migração da aplicação, que tem todo o seu interesse num projeto deste âmbito.
2.4.2. Hardware de Desenvolvimento
[8][10][11] O Kit de desenvolvimento utilizado para a implementação da
máquina virtual de occam-pi no PIC32MX460, foi o UBW32 (Figura 8 - UBW32).
Este Kit permite a ligação via USB ao computador, por onde é possível carregar os programas desenvolvidos e ainda receber/enviar input/output
para o PIC32MX460. Contem 2 botões/Switches e 4 LEDs, programáveis pelo utilizador, como também 78 Pinos I/O disponíveis para utilização. Em termos de performance, o PIC32MX460 opera a uma frequência de 80MHz,
tem 32Kbytes de RAM, e 512Kbytes de Flash.
Figura 8 - UBW32
Projeto Final LEETC - Programação Paralela em occam-pi
2012
19
2.4.3. Software de Desenvolvimento [9] O ciclo de desenho de código para a máquina virtual occam-pi é
composto pelos seguintes passos:
a) Desenvolvimento
O IDE utilizado para o desenho de todo código e bibliotecas C, tanto para o
interpretador de occam-pi (Loader da Figura 13 - Diagrama da Maquina Virtual occam)
como para a interface com o hardware do microcontrolador (HAL da Figura 13
- Diagrama da Maquina Virtual occam), é o MPLAB v8.63 (Figura 9 - MPLAB IDE) da
Microchip [12].
Figura 9 - MPLAB IDE
Projeto Final LEETC - Programação Paralela em occam-pi
2012
20
b) Compilação [13] Este IDE tem integrado um compilador C32 (Figura 10 - MPLAB C32 Compiler),
esta integração traz uma agilidade no processo de escrita de código C para
o PIC32 e compilação do mesmo. Este compilador permite referências
diretas às bibliotecas de periféricos do PIC32, que por sua vez fazem
chamadas a funções built-in do PIC32 (ex: Funções de Interrupção, Funções
de Timer, etc), e também a macros como pragma e outras.
Figura 10 - MPLAB C32 Compiler
c) Carregamento Para carregamento do código compilado no PIC, é utilizado o Bootloader da
Microchip (Figura 11 – Bootloader), que permite o carregamento via USB.
Figura 11 – Bootloader
Projeto Final LEETC - Programação Paralela em occam-pi
2012
21
d) Teste Finalmente como aplicação para suporte aos Testes, foi usado o
HyperTerminal do Windows (Figura 12 – Terminal), que permite interação I/O
com o PIC32 via USB. O Terminal foi de extrema importância no
desenvolvimento, isto porque apenas se pôde recorrer a printfs como forma de Debug.
Figura 12 – Terminal
2.4.4. Rotina main No PIC32, a rotina normal de execução da função main (ver Exemplo 3) é a
seguinte: 1. Iniciações do sistema, hardware e periféricos
2. Ciclo infinito, aqui o programa terá que atender a cada um dos processos atempadamente:
a. Tarefas do dispositivo USB, como por exemplo, input/output da porta série, entre outras.
b. Processo input/output da aplicação em sim, ou seja, o nosso
programa/execução da máquina virtual. Uma nota importante é que este processo não pode ser bloqueante, o que significa,
que tem que retornar ao ciclo infinito periodicamente para executar as tarefas descritas em a.
Exemplo 3 – Rotina main PIC32
Projeto Final LEETC - Programação Paralela em occam-pi
2012
22
3. Projecto 3.1. Implementação
[3] Existem duas formas de implementar a máquina virtual: traduzindo
diretamente para o código ASM do processador alvo, ou então implementar
um simulador das instruções da máquina virtual. Neste projeto, por se
tratar de uma abordagem exploratória, optou-se pela versão com instruções
simuladas/interpretadas. Foi também necessário desenvolver uma pequena
biblioteca de interface entre o programa e os aspetos de I/O específicos do
processador a utilizar. A máquina virtual foi desenvolvida para operar sobre
o microcontrolador PIC32MX460, mas o desenvolvimento foi em vista a
poder migrar para qualquer outro processador.
3.2. Arquitetura
Figura 13 - Diagrama da Maquina Virtual occam-pi
Projeto Final LEETC - Programação Paralela em occam-pi
2012
23
Como está representado na Figura 13 - Diagrama da Maquina Virtual occam, a
implementação da Maquina Virtual de occam está dividida em 2 módulos
principais:
Loader, Descodificador de programas occam-pi, que recebe os
ficheiros executáveis occam-pi (código já compilado e ligado com
as bibliotecas de runtime do occam-pi) e descodifica para
instruções simuladas do processador alvo, PICMX32.
HAL (Hardware Abstraction Layer), Interface de interligação com o
PICMX32, interface constituída pelas bibliotecas de interação das
instruções simuladas do descodificador com as funcionalidades do
microprocessador.
Projeto Final LEETC - Programação Paralela em occam-pi
2012
24
3.3. Migração TVM Neste subcapítulo será descrito todo o processo de migração da TVM NXT (já com alterações para execução em ambiente Linux) para o PIC32.
3.3.1. Estrutura Main
a) Linux Em primeiro lugar, ainda em ambiente Linux, teve que se proceder à
alteração da estrutura main do programa TVM (ver Exemplo 1). Isto para
integrar na rotina main do PIC32 (ver 2.4.4).
Nesta fase inicial optou-se por colocar os bytes do tbc hardcoded, num ficheiro header auxiliar, tbc_data.h (posteriormente já no PIC32 foi
implementada uma rotina de carregamento do tbc via porta série, ver 3.5). Foi criada uma função geral de iniciação da tvm, e do contexto a partir dos
bytes do tbc, main_init_tvm(). Foi também alterada a rotina de execução
da tvm, para algo semelhante a uma maquina de estados, sendo
main_run_tvm() a função de passagem.
b) PIC32 Já no PIC32, foi utilizada como base a aplicação de firmware do kit UBW32
[19]. Esta aplicação permite a interpretação de alguns comandos para
interagir diretamente com o hardware do microcontrolador. Foi removido o
código de interpretação destes comandos, ficando apenas o echo de caracteres enviados, o que foi útil para debug.
A estrutura do main pós migração pode ser vista em anexo ((CD)\Software\MPLAB-WORK\TVM_D32\main.c), onde já se encontra implementada a rotina de leitura dos bytecodes do tbc via porta serie (o
programa Linux de envio encontra-se descrito em 3.5)
3.3.2. Compilação PIC32 Tiveram que ser acrescentadas as seguintes opções de compilação ao
projeto MPLAB:
a) Heap size Definição de Heap size para permitir o uso da função de biblioteca C malloc
na alocação do espaço em memória para o contexto do programa
occam/occam-pi. Foi escolhido o valor de 16384 bytes por ser um tamanho mais que suficiente para qualquer programa occam/occam-pi, deixando
ainda uma boa margem para o funcionamento de todo o programa no PIC32, que tem um total de 32Kbytes de RAM (2.4.2). No entanto poderá ser ainda otimizado o valor do Heap size, caso haja necessidade de carregar
programas occam/occam-pi de maior dimensão, ou se 16Kbytes for desnecessário.
Para efetuar esta configuração no MPLAB é necessário seguir os seguintes passos:
i. (MPLAB)>Project>Build Options…>Project
ii. MPLAB PIC32 Linker>Heap size: 16384 bytes
Projeto Final LEETC - Programação Paralela em occam-pi
2012
25
b) No Floating Point Para simplificação da implementação da máquina virtual optou-se por não
incluir a funcionalidade de floating point do occam-pi, logo não será necessário incluir as bibliotecas C de floating point no projeto MPLAB. Para isso é necessário acrescentar a seguinte opção na compilação do projeto:
i. (MPLAB)>Project>Build Options…>Project ii. MPLAB PIC32 C Compiler>(uncheck) Exclude floating-point
library Para compilar o projeto sem erros foi também necessário comentar ou alterar certas funções da biblioteca da TVM, libtvm, especificas das
funcionalidades de floating point do occam-pi.
c) Macro TVM Em último lugar foi necessário definir uma Macro de pré-processamento,
TVM_INTERNALS, isto para que a tvm defina macros para alguns dos objetos da variável de contexto (ver Run-Time), tornando assim o código
mais legível. Para definir esta marcro é necessária a seguinte configuração: i. (MPLAB)>Project>Build Options…>Project ii. MPLAB PIC32 C Compiler>Preprocessor Macros>Add…
iii. “TVM_INTERNALS” >OK
Projeto Final LEETC - Programação Paralela em occam-pi
2012
26
3.4. PIC32 HAL Neste subcapítulo será descrito todas as funções criadas para abstração da máquina virtual para com o hardware do PIC32. Em todas estas funções
foram utilizadas as bibliotecas de periféricos do PIC32 [13].
3.4.1. Temporização da TVM Para o funcionamento de certas funcionalidades occam/occam-pi, como
instruções paralelas (PAR) nomeadamente na gestão do time slice, ou o acesso ao temporizador (TIMER), foi necessário configurar o Timer do PIC32 (Exemplo 4), e implementar a função stub da TVM de leitura do Timer (Exemplo
5). Esta função é utilizada internamente pela máquina virtual, não podendo
ser chamada através do código occam/occam-pi. Para ter acesso ao temporizador emulado deverá utilizar-se a variável do tipo Timer de occam.
Exemplo 4 – Inicialização do Timer PIC32
Exemplo 5 – Leitura do Timer PIC32
Projeto Final LEETC - Programação Paralela em occam-pi
2012
27
3.4.2. Módulo sffi No módulo sffi (Special Foregin Function Interface) foram definidas algumas funções para interação direta com os periféricos do PIC32 através de código
occam/occam-pi, ver 2.3.2.c). Por este projeto ser de caris exploratório, foram definidas apenas funções para interação com os 3 LEDs e 2 Switches
do PIC32. No futuro poderão também ser implementadas funções de interação com os pinos I/O.
a) Código C da TVM Para utilização destes periféricos é necessário proceder previamente à sua
inicialização, fazendo uso das funções de biblioteca mInitAllLEDs() para os
LEDs, e mInitAllSwitches() para os Switches.
Quanto à interação propriamente dita: i. Para os LEDs foram definidas as funções interface,
_mLED_X_[On/Off/Toggle]_e(ECTX ectx, WORD W[]), em que X vai
de 2 a 4 (indicador do LED em questão), que chamam funções
intermédias, funções estas que por sua vez chamam as funções da
biblioteca do PIC32 mLED_X_[On/Off/Toggle](). Nestas funções sffi
os parâmetros de entrada nunca são utilizados, mas a sua definição tem de estar em conformidade com o formato das funções interface.
Este mecanismo encontra-se descrito no Exemplo 6.
Exemplo 6 – Funções interface LEDs
Projeto Final LEETC - Programação Paralela em occam-pi
2012
28
ii. Para os Switches foram definidas as funções interface,
_swProgram_e(ECTX ectx, WORD W[]) e _swProgram_e(ECTX ectx, WORD W[])
para leitura do valor correspondente ao botão PRG e USER
respetivamente do PIC32, este valor será zero se o botão estiver pressionado e um se não estiver pressionado. O ponteiro do valor do
botão é passado como parâmetro da função, encontrando-se em W[0]. Este mecanismo encontra-se descrito no Exemplo 7.
Exemplo 7 – Funções interface Switches
b) Código occam Para a chamada destas funções interface a partir do código occam/occam-pi, é necessário que no programa occam sejam declarados os protótipos das
funções de interface (ver Exemplo 8) segundo o formato padrão da TVM
KRoC, ver 2.3.2.c).
Projeto Final LEETC - Programação Paralela em occam-pi
2012
29
Exemplo 8 – Biblioteca de Funções HAL do PIC32 para occam (pic32.hal)
Projeto Final LEETC - Programação Paralela em occam-pi
2012
30
3.5. Carregamento do programa occam Foi desenvolvida uma aplicação C (ver 3.5.1) de terminal em ambiente Linux que permite enviar, para o PIC32, os bytecodes do programa
occam/occam-pi já compilado (tbc), através da porta série. Já no PIC32 foi implementada uma rotina para receber os respetivos bytecodes.
3.5.1. Programa de envio Esta aplicação foi desenvolvida em Linux por duas razões: primeiro porque
o compilador de occam/occam-pi do projeto KRoC funciona somente em ambiente Linux, logo é de todo conveniente que estas duas aplicações
(compiler & loader) se encontrem no mesmo ambiente; a segunda prende-se no facto de que os sistemas operativos Linux permitem uma fácil e rápida utilização das portas séries, já que tratam as mesmas como se
fossem ficheiros. Passando a explicar o funcionamento do programa:
a) Comando de execução A sintaxe de execução do programa através do terminal é a seguinte:
Em que occam_prog.tbc são os bytecodes do programa occam, resultante
da compilação através do compilador KRoC, e serial_port_filename é o
nome do ficheiro da porta série onde se encontra ligado o PIC32, como por
exemplo /dev/ttyACM0.
b) Leitura do ficheiro tbc Inicialmente o programa lê o ficheiro passado, occam_prog.tbc, e passa o
seu conteúdo (bytecodes) para um array de bytes, através da função
read_tbc_file.
c) Envio dos bytecodes O array com os bytecodes é por sua vez passado à função
write_tbc_hex_file, juntamente com o seu tamanho e a localização da porta
série “/dev/serial_port_filename”, nesta função é primeiro aberta e
configurada a porta série, após configurada é primeiro enviado o tamanho
do array, e de seguida são enviados os bytecodes em blocos de 64Kbytes,
este é limite máximo do buffer de input/output da porta série do PIC32.
Após cada envio o programa fica a aguardar a uma resposta de
acknowledge do PIC32, com o tamanho total do array de bytecodes.
3.5.2. Rotina de receção no PIC32 No PIC32 para que a rotina de receção do programa occam seja executada
é necessário pressionar o botão/switch USER, e fazer o reset ao kit (pressionado o botão RESET, ou desligando e ligando o cabo USB), após isto o PIC32 vai ficar à espera que seja carregado o programa (piscando o LED
2, por forma a diferenciar do LED de status do USB LED 1).
Projeto Final LEETC - Programação Paralela em occam-pi
2012
31
No primeiro envio a rotina recebe o tamanho do array, após isto recebe o
array em blocos de 64 bytes.
Projeto Final LEETC - Programação Paralela em occam-pi
2012
32
3.6. Occam-pi Demos De entre os vários programas de teste occam-pi da máquina virtual foram escolhidos dois programas que apesar de bastantes simples espelham bem
as funcionalidades da linguagem occam, e também a abstração alcançada sobre o hardware.
3.6.1. Botões e LEDs O programa 08_switch2.occ, cujo código está apresentado no Exemplo 9,
divide-se em dois processos paralelos (através da diretiva PAR), o primeiro
declarado acende apenas o LED2, enquanto o segundo resume-se a uma rotina de leitura do valor do botão USER, se estiver pressionado acende apenas o LED 3, caso contrário acende somente o LED 4.
Exemplo 9 – 08_switch2.occ
#INCLUDE "./pic32.hal"
PROC hello ()
INT r:
SEQ
r := 1
led2.off()
led3.off()
led4.off()
PAR
led2.on()
WHILE TRUE
SEQ
get.sw.user(r)
IF
r = 0
SEQ
led3.on()
led4.off()
r = 1
SEQ
led3.off()
led4.on()
TRUE
SEQ
led3.on()
led4.on()
:
Projeto Final LEETC - Programação Paralela em occam-pi
2012
33
3.6.2. Timer O programa 09_delayled.occ, cujo código está apresentado no Exemplo 10,
faz uso do Timer de occam para acender um LED passado 2 segundos do início da execução e outro após 6 segundos do mesmo início, sendo estes
dois processos de delay executados em paralelo. Exemplo 10 – 09_delayled.occ
#INCLUDE "./pic32.hal"
PROC hello ()
TIMER t:
VAL INT delay IS 2000000:--2 sec delay
VAL INT delay2 IS 6000000:--6 sec delay
INT now , now2:
SEQ
led2.off()
led3.off()
PAR
SEQ
t ? now
t ? AFTER now PLUS delay
led2.on()
SEQ
t ? now2
t ? AFTER now2 PLUS delay2
led3.on()
:
Projeto Final LEETC - Programação Paralela em occam-pi
2012
34
3.7. Software Desenvolvido Todo o software desenvolvido para a realização deste projeto encontra-se no CD que segue em anexo com este relatório.
3.7.1. Ambiente Windows XP Na diretoria, (CD)\Software\MPLAB-WORK\TVM_D32, encontra-se o projeto MPLAB, D32.mcp, compatível com o MPLAB IDE v8.63 (versões superiores não testadas). Na mesma pasta encontram-se todos os módulos e
bibliotecas C necessários para a compilação da máquina virtual, sendo o resultado o ficheiro D32.hex (ver README.txt), este é o único ficheiro
necessário para programar o PIC32 com a máquina virtual de occam/occam-pi, através do programa Microship USB HID Bootloader v2.6a (versões superiores não testadas) que se encontra na pasta Microship, é
importante não alterar a disposição das diretorias. O MPLAB e o Bootloader foi utilizados no Windows XP.
3.7.2. Ambiente Linux
Na diretoria, (CD)\Software\Linux, encontram-se duas diretorias necessárias para o desenvolvimento de programas occam para a máquina
virtual do PIC32. Programas occam/occam-pi a desenvolver deverão ser colocados na diretoria (CD)\Software\Linux OCCAM.Progs, isto porque já
está preparada para a compilação dos programas (ver README.txt), bastando executar o script de Setup para preparar o ambiente para compilar os programas através do script kroc.
A diretoria (CD)\Software\tbc_serial_loader contêm tanto o código como o executável, tbc_serial_loader, da aplicação para carregamento do programa
occam/occam-pi, já compilado, no PIC32 (ver README.txt). O sistema Linux utilizado deverá ter no mínimo Python 2.5.2 instalado.
Projeto Final LEETC - Programação Paralela em occam-pi
2012
35
4. Conclusão
O objetivo principal do projeto foi alcançado, nomeadamente, a execução de programas occam sobre um PIC32, com o suporte da máquina virtual implementada.
Foi também desenvolvida uma pequena biblioteca de interface para o PIC32.
E por fim desenvolvido um programa para carregamento do programa occam no PIC32.
Mesmo assim, existem algumas funcionalidades da máquina virtual que não foram implementadas: Definição de funções da HAL para os pinos I/O do
PIC32; Utilização de pinos do PIC32 para despoletar eventos no programa occam; correção se um bug já existente na implementação KRoC da TVM, que é a gestão do time slice quando dois processos paralelos estão sempre
em execução. Quanto à rotina de carregamento do programa occam também poderia ser melhorada, já que atualmente o programa é guardado
na RAM, ou seja após reset do PIC32 é necessário carregar novamente o programa occam.
Em retrospetiva, a escolha e estudo para este projeto foi o culminar de todos os conceitos e conhecimentos adquiridos ao longo da licenciatura.
Como se tratou de um projeto exploratório, para a o seu desenvolvimento e implementação foi necessário o estudo de conceitos, e tecnologias desconhecidas até à altura, como a linguagem de programação paralela
occam, programação em microcontroladores PIC32, e programação de portas série em Linux.
De futuro, seria interessante completar esta implementação da máquina
virtual, e adicionar funcionalidades, como por exemplo a unidade de floating point, e ainda mais interessante o protocolo de comunicação que permita a ligação em paralelo de vários PIC32 executando a TVM, emulando assim por
completo aquela que é uma das características fortes do Transputer, o multi-core.
Projeto Final LEETC - Programação Paralela em occam-pi
2012
36
5. Bibliografia
[1] Qing Li e Carolyn Yao (2003). Real-Time Concepts for Embedded
Systems. CMP Books
[2] INMOS Limited (1998). occam 2, Reference Manual. Prentice Hall
[3] Engº Manuel Barata (2011). Documento de Proposta do Projecto